exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 7c45caa6664b4f0a699f639397f79f12399bb655
parent db32aebefcdc19b5f7e045f712bb481ce29a072c
Author: Christian Grothoff <grothoff@gnunet.org>
Date:   Sun, 12 Apr 2026 19:10:39 +0200

remove pg_ prefix

Diffstat:
Rsrc/auditordb/pg_template.sh -> src/auditordb/template.sh | 0
Asrc/exchangedb/abort_shard.c | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/activate_signing_key.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/add_denomination_key.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/add_policy_fulfillment_proof.c | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/aggregate.c | 201+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/batch_ensure_coin_known.c | 457+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/begin_revolving_shard.c | 258+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/begin_shard.c | 262+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/clear_aml_lock.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/commit.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/complete_shard.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/compute_shard.c | 46++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/count_known_coins.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/create_aggregation_transient.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/create_tables.c | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/delete_aggregation_transient.c | 46++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/delete_shard_locks.c | 37+++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/disable_rules.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_check_deposit_idempotent.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_deposit.c | 171+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_purse_delete.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_purse_deposit.c | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_purse_merge.c | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_recoup.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_recoup_refresh.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_refresh.c | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_refund.c | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_reserve_open.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_reserve_purse.c | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/do_withdraw.c | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/drain_kyc_alert.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/drop_tables.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/enable_rules.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/ensure_coin_known.c | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/event_listen.c | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/event_listen_cancel.c | 34++++++++++++++++++++++++++++++++++
Asrc/exchangedb/event_notify.c | 37+++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/expire_purse.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/find_aggregation_transient.c | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/gc.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_coin_denomination.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_coin_transactions.c | 1184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_denomination_by_serial.c | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_denomination_info.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_denomination_revocation.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_drain_profit.c | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_expired_reserves.c | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_extension_manifest.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_global_fee.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_global_fees.c | 164+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_known_coin.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_kyc_rules.c | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_old_coin_by_h_blind.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_pending_kyc_requirement_process.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_policy_details.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_purse_deposit.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_purse_request.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_ready_deposit.c | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_refresh.c | 205+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_reserve_balance.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_reserve_by_h_planchets.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_reserve_history.c | 994+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_signature_for_known_coin.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_unfinished_close_requests.c | 162+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_wire_accounts.c | 179+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_wire_fee.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_wire_fees.c | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_wire_hash_for_contract.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/get_withdraw.c | 191+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/have_deposit2.c | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/inject_auditor_triggers.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_active_legitimization_measure.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_aml_decision.c | 185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_aml_officer.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_aml_program_failure.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_auditor.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_auditor_denom_sig.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_close_request.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_contract.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_denomination_info.c | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_denomination_revocation.c | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_drain_profit.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_global_fee.c | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_kyc_failure.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_kyc_requirement_process.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_partner.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_purse_request.c | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_records_by_table.c | 2453+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_refund.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_reserve_closed.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_reserve_open_deposit.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_sanction_list_hit.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_signkey_revocation.c | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_successor_measure.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_wire.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/insert_wire_fee.c | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/iterate_active_auditors.c | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/iterate_active_signkeys.c | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/iterate_auditor_denominations.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/iterate_denomination_info.c | 185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/iterate_denominations.c | 175+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/iterate_kyc_reference.c | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/iterate_reserve_close_info.c | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/kyc_provider_account_lookup.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/kycauth_in_insert.c | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_active_legitimization.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_aml_file_number.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_aml_history.c | 200+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_aml_officer.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_auditor_status.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_auditor_timestamp.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_completed_legitimization.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_denomination_key.c | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_global_fee_by_time.c | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_h_payto_by_access_token.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_kyc_history.c | 192+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_kyc_process_by_account.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_kyc_requirement_by_row.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_kyc_status_by_token.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_pending_legitimization.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_records_by_table.c | 3802+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_rules_by_access_token.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_serial_by_table.c | 465+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_signing_key.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_signkey_revocation.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_transfer_by_deposit.c | 220+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_wire_fee_by_time.c | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_wire_timestamp.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/lookup_wire_transfer.c | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/mark_refresh_reveal_success.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Msrc/exchangedb/meson.build | 414++++++++++++++++++++++++++++++++++++++++----------------------------------------
Asrc/exchangedb/persist_kyc_attributes.c | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/persist_policy_details.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/exchangedb/pg_abort_shard.c | 49-------------------------------------------------
Dsrc/exchangedb/pg_activate_signing_key.c | 54------------------------------------------------------
Dsrc/exchangedb/pg_add_denomination_key.c | 83-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_add_policy_fulfillment_proof.c | 158-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_aggregate.c | 201-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_batch_ensure_coin_known.c | 457-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_begin_revolving_shard.c | 258-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_begin_shard.c | 262-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_clear_aml_lock.c | 45---------------------------------------------
Dsrc/exchangedb/pg_commit.c | 52----------------------------------------------------
Dsrc/exchangedb/pg_complete_shard.c | 52----------------------------------------------------
Dsrc/exchangedb/pg_compute_shard.c | 46----------------------------------------------
Dsrc/exchangedb/pg_count_known_coins.c | 59-----------------------------------------------------------
Dsrc/exchangedb/pg_create_aggregation_transient.c | 61-------------------------------------------------------------
Dsrc/exchangedb/pg_create_tables.c | 78------------------------------------------------------------------------------
Dsrc/exchangedb/pg_delete_aggregation_transient.c | 46----------------------------------------------
Dsrc/exchangedb/pg_delete_shard_locks.c | 37-------------------------------------
Dsrc/exchangedb/pg_disable_rules.c | 57---------------------------------------------------------
Dsrc/exchangedb/pg_do_check_deposit_idempotent.c | 109-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_do_deposit.c | 171-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_do_purse_delete.c | 60------------------------------------------------------------
Dsrc/exchangedb/pg_do_purse_deposit.c | 86-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_do_purse_merge.c | 87-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_do_recoup.c | 81-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_do_recoup_refresh.c | 76----------------------------------------------------------------------------
Dsrc/exchangedb/pg_do_refresh.c | 138-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_do_refund.c | 91-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_do_reserve_open.c | 97-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_do_reserve_purse.c | 118-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_do_withdraw.c | 140-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_drain_kyc_alert.c | 55-------------------------------------------------------
Dsrc/exchangedb/pg_drop_tables.c | 54------------------------------------------------------
Dsrc/exchangedb/pg_enable_rules.c | 74--------------------------------------------------------------------------
Dsrc/exchangedb/pg_ensure_coin_known.c | 166-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_event_listen.c | 49-------------------------------------------------
Dsrc/exchangedb/pg_event_listen_cancel.c | 34----------------------------------
Dsrc/exchangedb/pg_event_notify.c | 37-------------------------------------
Dsrc/exchangedb/pg_expire_purse.c | 65-----------------------------------------------------------------
Dsrc/exchangedb/pg_find_aggregation_transient.c | 69---------------------------------------------------------------------
Dsrc/exchangedb/pg_gc.c | 75---------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_coin_denomination.c | 65-----------------------------------------------------------------
Dsrc/exchangedb/pg_get_coin_transactions.c | 1184-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_denomination_by_serial.c | 87-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_denomination_info.c | 96-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_denomination_revocation.c | 59-----------------------------------------------------------
Dsrc/exchangedb/pg_get_drain_profit.c | 72------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_expired_reserves.c | 169-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_extension_manifest.c | 64----------------------------------------------------------------
Dsrc/exchangedb/pg_get_global_fee.c | 85-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_global_fees.c | 164-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_known_coin.c | 64----------------------------------------------------------------
Dsrc/exchangedb/pg_get_kyc_rules.c | 124-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_old_coin_by_h_blind.c | 60------------------------------------------------------------
Dsrc/exchangedb/pg_get_pending_kyc_requirement_process.c | 62--------------------------------------------------------------
Dsrc/exchangedb/pg_get_policy_details.c | 60------------------------------------------------------------
Dsrc/exchangedb/pg_get_purse_deposit.c | 80-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_purse_request.c | 75---------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_ready_deposit.c | 78------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_refresh.c | 205-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_reserve_balance.c | 65-----------------------------------------------------------------
Dsrc/exchangedb/pg_get_reserve_by_h_planchets.c | 58----------------------------------------------------------
Dsrc/exchangedb/pg_get_reserve_history.c | 994-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_signature_for_known_coin.c | 59-----------------------------------------------------------
Dsrc/exchangedb/pg_get_unfinished_close_requests.c | 162-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_wire_accounts.c | 179-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_wire_fee.c | 74--------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_wire_fees.c | 144-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_wire_hash_for_contract.c | 77-----------------------------------------------------------------------------
Dsrc/exchangedb/pg_get_withdraw.c | 191-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_have_deposit2.c | 113-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_inject_auditor_triggers.c | 55-------------------------------------------------------
Dsrc/exchangedb/pg_insert_active_legitimization_measure.c | 58----------------------------------------------------------
Dsrc/exchangedb/pg_insert_aml_decision.c | 185-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_aml_officer.c | 62--------------------------------------------------------------
Dsrc/exchangedb/pg_insert_aml_program_failure.c | 66------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_auditor.c | 55-------------------------------------------------------
Dsrc/exchangedb/pg_insert_auditor_denom_sig.c | 58----------------------------------------------------------
Dsrc/exchangedb/pg_insert_close_request.c | 64----------------------------------------------------------------
Dsrc/exchangedb/pg_insert_contract.c | 89-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_denomination_info.c | 98-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_denomination_revocation.c | 50--------------------------------------------------
Dsrc/exchangedb/pg_insert_drain_profit.c | 60------------------------------------------------------------
Dsrc/exchangedb/pg_insert_global_fee.c | 137-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_kyc_failure.c | 90-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_kyc_requirement_process.c | 85-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_partner.c | 67-------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_purse_request.c | 122-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_records_by_table.c | 2453-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_refund.c | 62--------------------------------------------------------------
Dsrc/exchangedb/pg_insert_reserve_closed.c | 109-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_reserve_open_deposit.c | 63---------------------------------------------------------------
Dsrc/exchangedb/pg_insert_sanction_list_hit.c | 90-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_signkey_revocation.c | 49-------------------------------------------------
Dsrc/exchangedb/pg_insert_successor_measure.c | 84-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_wire.c | 81-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_insert_wire_fee.c | 108-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_iterate_active_auditors.c | 120-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_iterate_active_signkeys.c | 142-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_iterate_auditor_denominations.c | 117-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_iterate_denomination_info.c | 185-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_iterate_denominations.c | 175-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_iterate_kyc_reference.c | 126-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_iterate_reserve_close_info.c | 127-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_kyc_provider_account_lookup.c | 66------------------------------------------------------------------
Dsrc/exchangedb/pg_kycauth_in_insert.c | 78------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_active_legitimization.c | 62--------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_aml_file_number.c | 59-----------------------------------------------------------
Dsrc/exchangedb/pg_lookup_aml_history.c | 200-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_aml_officer.c | 68--------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_auditor_status.c | 57---------------------------------------------------------
Dsrc/exchangedb/pg_lookup_auditor_timestamp.c | 53-----------------------------------------------------
Dsrc/exchangedb/pg_lookup_completed_legitimization.c | 95-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_denomination_key.c | 79-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_global_fee_by_time.c | 180-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_h_payto_by_access_token.c | 59-----------------------------------------------------------
Dsrc/exchangedb/pg_lookup_kyc_history.c | 192-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_kyc_process_by_account.c | 90-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_kyc_requirement_by_row.c | 109-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_kyc_status_by_token.c | 61-------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_pending_legitimization.c | 76----------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_records_by_table.c | 3802-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_rules_by_access_token.c | 66------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_serial_by_table.c | 465-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_signing_key.c | 60------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_signkey_revocation.c | 55-------------------------------------------------------
Dsrc/exchangedb/pg_lookup_transfer_by_deposit.c | 220-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_wire_fee_by_time.c | 152-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_lookup_wire_timestamp.c | 52----------------------------------------------------
Dsrc/exchangedb/pg_lookup_wire_transfer.c | 184-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_mark_refresh_reveal_success.c | 45---------------------------------------------
Dsrc/exchangedb/pg_persist_kyc_attributes.c | 103-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_persist_policy_details.c | 74--------------------------------------------------------------------------
Dsrc/exchangedb/pg_preflight.c | 111-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_profit_drains_get_pending.c | 75---------------------------------------------------------------------------
Dsrc/exchangedb/pg_profit_drains_set_finished.c | 45---------------------------------------------
Dsrc/exchangedb/pg_release_revolving_shard.c | 56--------------------------------------------------------
Dsrc/exchangedb/pg_reserves_get.c | 57---------------------------------------------------------
Dsrc/exchangedb/pg_reserves_get_origin.c | 61-------------------------------------------------------------
Dsrc/exchangedb/pg_reserves_in_insert.c | 374-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_reserves_update.c | 50--------------------------------------------------
Dsrc/exchangedb/pg_rollback.c | 45---------------------------------------------
Dsrc/exchangedb/pg_select_account_merges_above_serial_id.c | 188-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_aggregation_amounts_for_kyc_check.c | 154-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_aggregation_transient.c | 63---------------------------------------------------------------
Dsrc/exchangedb/pg_select_aggregations_above_serial.c | 137-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_all_kyc_attributes.c | 168-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_all_purse_decisions_above_serial_id.c | 142-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_all_purse_deletions_above_serial_id.c | 142-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_aml_attributes.c | 189-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_aml_decisions.c | 248-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_aml_measures.c | 185-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_aml_statistics.c | 142-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_auditor_denom_sig.c | 62--------------------------------------------------------------
Dsrc/exchangedb/pg_select_batch_deposits_missing_wire.c | 140-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_coin_deposits_above_serial_id.c | 200-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_contract.c | 65-----------------------------------------------------------------
Dsrc/exchangedb/pg_select_contract_by_purse.c | 59-----------------------------------------------------------
Dsrc/exchangedb/pg_select_deposit_amounts_for_kyc_check.c | 153-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_exchange_credit_transfers.c | 180-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_exchange_debit_transfers.c | 181-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_exchange_kycauth_transfers.c | 180-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_kyc_accounts.c | 235-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_kyc_attributes.c | 154-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_merge_amounts_for_kyc_check.c | 152-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_purse.c | 90-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_purse_by_merge_pub.c | 75---------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_purse_decisions_above_serial_id.c | 158-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_purse_deposits_above_serial_id.c | 198-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_purse_deposits_by_purse.c | 149-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_purse_merge.c | 76----------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_purse_merges_above_serial_id.c | 186-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_purse_requests_above_serial_id.c | 174-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_recoup_above_serial_id.c | 184-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_recoup_refresh_above_serial_id.c | 204-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_refreshes_above_serial_id.c | 180-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_refunds_above_serial_id.c | 220-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_refunds_by_coin.c | 139-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_reserve_close_info.c | 62--------------------------------------------------------------
Dsrc/exchangedb/pg_select_reserve_close_request_info.c | 73-------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_reserve_closed_above_serial_id.c | 172-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_reserve_open_above_serial_id.c | 163-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_reserves_in_above_serial_id.c | 163-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c | 166-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_wire_out_above_serial_id.c | 154-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_wire_out_above_serial_id_by_account.c | 157-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_withdraw_amounts_for_kyc_check.c | 158-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_select_withdrawals_above_serial_id.c | 212-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_set_aml_lock.c | 70----------------------------------------------------------------------
Dsrc/exchangedb/pg_set_extension_manifest.c | 53-----------------------------------------------------
Dsrc/exchangedb/pg_set_purse_balance.c | 48------------------------------------------------
Dsrc/exchangedb/pg_start.c | 51---------------------------------------------------
Dsrc/exchangedb/pg_start_deferred_wire_out.c | 56--------------------------------------------------------
Dsrc/exchangedb/pg_start_read_committed.c | 53-----------------------------------------------------
Dsrc/exchangedb/pg_start_read_only.c | 53-----------------------------------------------------
Dsrc/exchangedb/pg_store_wire_transfer_out.c | 63---------------------------------------------------------------
Dsrc/exchangedb/pg_template.c | 20--------------------
Dsrc/exchangedb/pg_test_aml_officer.c | 52----------------------------------------------------
Dsrc/exchangedb/pg_trigger_kyc_rule_for_account.c | 98-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_update_aggregation_transient.c | 54------------------------------------------------------
Dsrc/exchangedb/pg_update_auditor.c | 56--------------------------------------------------------
Dsrc/exchangedb/pg_update_kyc_process_by_row.c | 131-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_update_wire.c | 88-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_wad_in_insert.c | 58----------------------------------------------------------
Dsrc/exchangedb/pg_wire_prepare_data_get.c | 138-------------------------------------------------------------------------------
Dsrc/exchangedb/pg_wire_prepare_data_insert.c | 51---------------------------------------------------
Dsrc/exchangedb/pg_wire_prepare_data_mark_failed.c | 44--------------------------------------------
Dsrc/exchangedb/pg_wire_prepare_data_mark_finished.c | 43-------------------------------------------
Asrc/exchangedb/preflight.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/profit_drains_get_pending.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/profit_drains_set_finished.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/release_revolving_shard.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/reserves_get.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/reserves_get_origin.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/reserves_in_insert.c | 374+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/reserves_update.c | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/rollback.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_account_merges_above_serial_id.c | 188+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_aggregation_amounts_for_kyc_check.c | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_aggregation_transient.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_aggregations_above_serial.c | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_all_kyc_attributes.c | 168+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_all_purse_decisions_above_serial_id.c | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_all_purse_deletions_above_serial_id.c | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_aml_attributes.c | 189+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_aml_decisions.c | 248+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_aml_measures.c | 185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_aml_statistics.c | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_auditor_denom_sig.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_batch_deposits_missing_wire.c | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_coin_deposits_above_serial_id.c | 200+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_contract.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_contract_by_purse.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_deposit_amounts_for_kyc_check.c | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_exchange_credit_transfers.c | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_exchange_debit_transfers.c | 181+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_exchange_kycauth_transfers.c | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_kyc_accounts.c | 235+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_kyc_attributes.c | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_merge_amounts_for_kyc_check.c | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_purse.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_purse_by_merge_pub.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_purse_decisions_above_serial_id.c | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_purse_deposits_above_serial_id.c | 198+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_purse_deposits_by_purse.c | 149+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_purse_merge.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_purse_merges_above_serial_id.c | 186+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_purse_requests_above_serial_id.c | 174+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_recoup_above_serial_id.c | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_recoup_refresh_above_serial_id.c | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_refreshes_above_serial_id.c | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_refunds_above_serial_id.c | 220+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_refunds_by_coin.c | 139+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_reserve_close_info.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_reserve_close_request_info.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_reserve_closed_above_serial_id.c | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_reserve_open_above_serial_id.c | 163+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_reserves_in_above_serial_id.c | 163+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_reserves_in_above_serial_id_by_account.c | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_wire_out_above_serial_id.c | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_wire_out_above_serial_id_by_account.c | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_withdraw_amounts_for_kyc_check.c | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/select_withdrawals_above_serial_id.c | 212+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/set_aml_lock.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/set_extension_manifest.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/set_purse_balance.c | 48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/start.c | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/start_deferred_wire_out.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/start_read_committed.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/start_read_only.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/store_wire_transfer_out.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/template.c | 20++++++++++++++++++++
Rsrc/exchangedb/pg_template.sh -> src/exchangedb/template.sh | 0
Asrc/exchangedb/test_aml_officer.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/trigger_kyc_rule_for_account.c | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/update_aggregation_transient.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/update_auditor.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/update_kyc_process_by_row.c | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/update_wire.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/wad_in_insert.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/wire_prepare_data_get.c | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/wire_prepare_data_insert.c | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/wire_prepare_data_mark_failed.c | 44++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/wire_prepare_data_mark_finished.c | 43+++++++++++++++++++++++++++++++++++++++++++
417 files changed, 30703 insertions(+), 30703 deletions(-)

diff --git a/src/auditordb/pg_template.sh b/src/auditordb/template.sh diff --git a/src/exchangedb/abort_shard.c b/src/exchangedb/abort_shard.c @@ -0,0 +1,49 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/abort_shard.c + * @brief Implementation of the abort_shard function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/abort_shard.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_abort_shard (struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *job_name, + uint64_t start_row, + uint64_t end_row) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_uint64 (&start_row), + GNUNET_PQ_query_param_uint64 (&end_row), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "abort_shard", + "UPDATE work_shards" + " SET last_attempt=0" + " WHERE job_name=$1" + " AND start_row=$2" + " AND end_row=$3;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "abort_shard", + params); +} diff --git a/src/exchangedb/activate_signing_key.c b/src/exchangedb/activate_signing_key.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/activate_signing_key.c + * @brief Implementation of the activate_signing_key function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/activate_signing_key.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_activate_signing_key ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_EXCHANGEDB_SignkeyMetaData *meta, + const struct TALER_MasterSignatureP *master_sig) +{ + struct GNUNET_PQ_QueryParam iparams[] = { + GNUNET_PQ_query_param_auto_from_type (exchange_pub), + GNUNET_PQ_query_param_timestamp (&meta->start), + GNUNET_PQ_query_param_timestamp (&meta->expire_sign), + GNUNET_PQ_query_param_timestamp (&meta->expire_legal), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_signkey", + "INSERT INTO exchange_sign_keys " + "(exchange_pub" + ",valid_from" + ",expire_sign" + ",expire_legal" + ",master_sig" + ") VALUES " + "($1, $2, $3, $4, $5);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_signkey", + iparams); +} diff --git a/src/exchangedb/add_denomination_key.c b/src/exchangedb/add_denomination_key.c @@ -0,0 +1,83 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/add_denomination_key.c + * @brief Implementation of the add_denomination_key function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/add_denomination_key.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_add_denomination_key ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta, + const struct TALER_MasterSignatureP *master_sig) +{ + struct GNUNET_PQ_QueryParam iparams[] = { + GNUNET_PQ_query_param_auto_from_type (h_denom_pub), + TALER_PQ_query_param_denom_pub (denom_pub), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_timestamp (&meta->start), + GNUNET_PQ_query_param_timestamp (&meta->expire_withdraw), + GNUNET_PQ_query_param_timestamp (&meta->expire_deposit), + GNUNET_PQ_query_param_timestamp (&meta->expire_legal), + TALER_PQ_query_param_amount (pg->conn, + &meta->value), + TALER_PQ_query_param_amount (pg->conn, + &meta->fees.withdraw), + TALER_PQ_query_param_amount (pg->conn, + &meta->fees.deposit), + TALER_PQ_query_param_amount (pg->conn, + &meta->fees.refresh), + TALER_PQ_query_param_amount (pg->conn, + &meta->fees.refund), + GNUNET_PQ_query_param_uint32 (&meta->age_mask.bits), + GNUNET_PQ_query_param_end + }; + + /* Sanity check: ensure fees match coin currency */ + GNUNET_assert (GNUNET_YES == + TALER_denom_fee_check_currency (meta->value.currency, + &meta->fees)); + PREPARE (pg, + "denomination_insert", + "INSERT INTO denominations " + "(denom_pub_hash" + ",denom_pub" + ",master_sig" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin" /* value of this denom */ + ",fee_withdraw" + ",fee_deposit" + ",fee_refresh" + ",fee_refund" + ",age_mask" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," + " $11, $12, $13);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "denomination_insert", + iparams); +} diff --git a/src/exchangedb/add_policy_fulfillment_proof.c b/src/exchangedb/add_policy_fulfillment_proof.c @@ -0,0 +1,158 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/add_policy_fulfillment_proof.c + * @brief Implementation of the add_policy_fulfillment_proof function for Postgres + * @author Christian Grothoff + */ +#include "taler/platform.h" /* UNNECESSARY? */ +#include "taler/taler_error_codes.h" /* UNNECESSARY? */ +#include "taler/taler_dbevents.h" /* UNNECESSARY? */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/add_policy_fulfillment_proof.h" +#include "helper.h" + + +/** + * Compares two indices into an array of hash codes according to + * GNUNET_CRYPTO_hash_cmp of the content at those index positions. + * + * Used in a call qsort_t in order to generate sorted policy_hash_codes. + */ +static int +hash_code_cmp ( + const void *hc1, + const void *hc2, + void *arg) +{ + size_t i1 = *(size_t *) hc1; + size_t i2 = *(size_t *) hc2; + const struct TALER_PolicyDetails *d = arg; + + return GNUNET_CRYPTO_hash_cmp (&d[i1].hash_code, + &d[i2].hash_code); +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_add_policy_fulfillment_proof ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + struct TALER_PolicyFulfillmentTransactionData *fulfillment) +{ + enum GNUNET_DB_QueryStatus qs; + size_t count = fulfillment->details_count; + /* FIXME[Oec]: this seems to be prone to VLA attacks */ + struct GNUNET_HashCode hcs[GNUNET_NZL (count)]; + + /* Create the sorted policy_hash_codes */ + { + size_t idx[GNUNET_NZL (count)]; + for (size_t i = 0; i < count; i++) + idx[i] = i; + + /* Sort the indices according to the hash codes of the corresponding + * details. */ + qsort_r (idx, + count, + sizeof(size_t), + hash_code_cmp, + fulfillment->details); + + /* Finally, concatenate all hash_codes in sorted order */ + for (size_t i = 0; i < count; i++) + hcs[i] = fulfillment->details[idx[i]].hash_code; + } + + + /* Now, add the proof to the policy_fulfillments table, retrieve the + * record_id */ + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&fulfillment->timestamp), + TALER_PQ_query_param_json (fulfillment->proof), + GNUNET_PQ_query_param_auto_from_type (&fulfillment->h_proof), + TALER_PQ_query_param_array_hash_code (count, hcs, pg->conn), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("fulfillment_id", + &fulfillment->fulfillment_id), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "insert_proof_into_policy_fulfillments", + "INSERT INTO policy_fulfillments" + "(fulfillment_timestamp" + ",fulfillment_proof" + ",h_fulfillment_proof" + ",policy_hash_codes" + ") VALUES ($1, $2::TEXT::JSON, $3, $4)" + " ON CONFLICT DO NOTHING;"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "insert_proof_into_policy_fulfillments", + params, + rs); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) + return qs; + } + + /* Now, set the states of each entry corresponding to the hash_codes in + * policy_details accordingly */ + for (size_t i = 0; i < count; i++) + { + struct TALER_PolicyDetails *pos = &fulfillment->details[i]; + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&pos->hash_code), + GNUNET_PQ_query_param_timestamp (&pos->deadline), + TALER_PQ_query_param_amount (pg->conn, + &pos->commitment), + TALER_PQ_query_param_amount (pg->conn, + &pos->accumulated_total), + TALER_PQ_query_param_amount (pg->conn, + &pos->policy_fee), + TALER_PQ_query_param_amount (pg->conn, + &pos->transferable_amount), + GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "update_policy_details", + "UPDATE policy_details SET" + " deadline=$2" + ",commitment=$3" + ",accumulated_total=$4" + ",fee=$5" + ",transferable=$6" + ",fulfillment_state=$7" + " WHERE policy_hash_code=$1;"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_policy_details", + params); + if (qs < 0) + return qs; + } + } + + /* + * FIXME[oec]-#7999: When all policies of a deposit are fulfilled, + * unblock it and trigger a wire-transfer. + */ + + return qs; +} diff --git a/src/exchangedb/aggregate.c b/src/exchangedb/aggregate.c @@ -0,0 +1,201 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2023 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/> + */ +/** + * @file exchangedb/aggregate.c + * @brief Implementation of the aggregate function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/compute_shard.h" +#include "taler/exchange-database/aggregate.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_aggregate ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_FullPaytoHashP *h_payto, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_WireTransferIdentifierRawP *wtid, + struct TALER_Amount *total) +{ + uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (merchant_pub); + struct GNUNET_TIME_Absolute now = {0}; + uint64_t sum_deposit_value; + uint64_t sum_deposit_frac; + uint64_t sum_refund_value; + uint64_t sum_refund_frac; + uint64_t sum_fee_value; + uint64_t sum_fee_frac; + enum GNUNET_DB_QueryStatus qs; + struct TALER_Amount sum_deposit; + struct TALER_Amount sum_refund; + struct TALER_Amount sum_fee; + struct TALER_Amount delta; + + now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (), + pg->aggregator_shift); + PREPARE (pg, + "aggregate", + "WITH bdep AS (" /* restrict to our merchant and account and mark as done */ + " UPDATE batch_deposits" + " SET done=TRUE" + " WHERE NOT (done OR policy_blocked)" /* only actually executable deposits */ + " AND refund_deadline<$1" + " AND shard=$5" /* only for efficiency, merchant_pub is what we really filter by */ + " AND merchant_pub=$2" /* filter by target merchant */ + " AND wire_target_h_payto=$3" /* merchant could have a 2nd bank account */ + " RETURNING" + " batch_deposit_serial_id)" + " ,cdep AS (" + " SELECT" + " coin_deposit_serial_id" + " ,batch_deposit_serial_id" + " ,coin_pub" + " ,amount_with_fee AS amount" + " FROM coin_deposits" + " WHERE batch_deposit_serial_id IN (SELECT batch_deposit_serial_id FROM bdep))" + " ,ref AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ + " SELECT" + " amount_with_fee AS refund" + " ,coin_pub" + " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ + " FROM refunds" + " WHERE coin_pub IN (SELECT coin_pub FROM cdep)" + " AND batch_deposit_serial_id IN (SELECT batch_deposit_serial_id FROM bdep))" + " ,ref_by_coin AS (" /* total up refunds by coin */ + " SELECT" + " SUM((ref.refund).val) AS sum_refund_val" + " ,SUM((ref.refund).frac) AS sum_refund_frac" + " ,coin_pub" + " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ + " FROM ref" + " GROUP BY coin_pub, batch_deposit_serial_id)" + " ,norm_ref_by_coin AS (" /* normalize */ + " SELECT" + " sum_refund_val + sum_refund_frac / 100000000 AS norm_refund_val" + " ,sum_refund_frac % 100000000 AS norm_refund_frac" + " ,coin_pub" + " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ + " FROM ref_by_coin)" + " ,fully_refunded_coins AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ + " SELECT" + " cdep.coin_pub" + " FROM norm_ref_by_coin norm" + " JOIN cdep" + " ON (norm.coin_pub = cdep.coin_pub" + " AND norm.batch_deposit_serial_id = cdep.batch_deposit_serial_id" + " AND norm.norm_refund_val = (cdep.amount).val" + " AND norm.norm_refund_frac = (cdep.amount).frac))" + " ,fees AS (" /* find deposit fees for not fully refunded deposits */ + " SELECT" + " denom.fee_deposit AS fee" + " ,cs.batch_deposit_serial_id" /* ensures we get the fee for each coin, not once per denomination */ + " FROM cdep cs" + " JOIN known_coins kc" /* NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ + " USING (coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " WHERE coin_pub NOT IN (SELECT coin_pub FROM fully_refunded_coins))" + " ,dummy AS (" /* add deposits to aggregation_tracking */ + " INSERT INTO aggregation_tracking" + " (batch_deposit_serial_id" + " ,wtid_raw)" + " SELECT batch_deposit_serial_id,$4" + " FROM bdep)" + "SELECT" /* calculate totals (deposits, refunds and fees) */ + " CAST(COALESCE(SUM((cdep.amount).val),0) AS INT8) AS sum_deposit_value" + /* cast needed, otherwise we get NUMBER */ + " ,COALESCE(SUM((cdep.amount).frac),0) AS sum_deposit_fraction" /* SUM over INT returns INT8 */ + " ,CAST(COALESCE(SUM((ref.refund).val),0) AS INT8) AS sum_refund_value" + " ,COALESCE(SUM((ref.refund).frac),0) AS sum_refund_fraction" + " ,CAST(COALESCE(SUM((fees.fee).val),0) AS INT8) AS sum_fee_value" + " ,COALESCE(SUM((fees.fee).frac),0) AS sum_fee_fraction" + " FROM cdep " + " FULL OUTER JOIN ref ON (FALSE)" /* We just want all sums */ + " FULL OUTER JOIN fees ON (FALSE);"); + + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_uint64 (&deposit_shard), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("sum_deposit_value", + &sum_deposit_value), + GNUNET_PQ_result_spec_uint64 ("sum_deposit_fraction", + &sum_deposit_frac), + GNUNET_PQ_result_spec_uint64 ("sum_refund_value", + &sum_refund_value), + GNUNET_PQ_result_spec_uint64 ("sum_refund_fraction", + &sum_refund_frac), + GNUNET_PQ_result_spec_uint64 ("sum_fee_value", + &sum_fee_value), + GNUNET_PQ_result_spec_uint64 ("sum_fee_fraction", + &sum_fee_frac), + GNUNET_PQ_result_spec_end + }; + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "aggregate", + params, + rs); + } + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + return qs; + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (pg->currency, + total)); + return qs; + } + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (pg->currency, + &sum_deposit)); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (pg->currency, + &sum_refund)); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (pg->currency, + &sum_fee)); + sum_deposit.value = sum_deposit_frac / TALER_AMOUNT_FRAC_BASE + + sum_deposit_value; + sum_deposit.fraction = sum_deposit_frac % TALER_AMOUNT_FRAC_BASE; + sum_refund.value = sum_refund_frac / TALER_AMOUNT_FRAC_BASE + + sum_refund_value; + sum_refund.fraction = sum_refund_frac % TALER_AMOUNT_FRAC_BASE; + sum_fee.value = sum_fee_frac / TALER_AMOUNT_FRAC_BASE + + sum_fee_value; + sum_fee.fraction = sum_fee_frac % TALER_AMOUNT_FRAC_BASE; \ + GNUNET_assert (0 <= + TALER_amount_subtract (&delta, + &sum_deposit, + &sum_refund)); + GNUNET_assert (0 <= + TALER_amount_subtract (total, + &delta, + &sum_fee)); + return qs; +} diff --git a/src/exchangedb/batch_ensure_coin_known.c b/src/exchangedb/batch_ensure_coin_known.c @@ -0,0 +1,457 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/batch_ensure_coin_known.c + * @brief Implementation of the batch_ensure_coin_known function for Postgres + * @author Christian Grothoff + * + * FIXME-#9373: use the array support for postgres to simplify this code! + * + */ +#include "taler/taler_exchangedb_lib.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/batch_ensure_coin_known.h" +#include "helper.h" + + +static enum GNUNET_DB_QueryStatus +insert1 (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_CoinPublicInfo coin[1], + struct TALER_EXCHANGEDB_CoinInfo result[1]) +{ + enum GNUNET_DB_QueryStatus qs; + bool is_denom_pub_hash_null = false; + bool is_age_hash_null = false; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("existed", + &result[0].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + &result[0].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &result[0].denom_hash), + &is_denom_pub_hash_null), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &result[0].h_age_commitment), + &is_age_hash_null), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "batch1_known_coin", + "SELECT" + " existed1 AS existed" + ",known_coin_id1 AS known_coin_id" + ",denom_pub_hash1 AS denom_hash" + ",age_commitment_hash1 AS h_age_commitment" + " FROM exchange_do_batch1_known_coin" + " ($1, $2, $3, $4);" + ); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "batch1_known_coin", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + return qs; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); /* should be impossible */ + return GNUNET_DB_STATUS_HARD_ERROR; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; /* continued below */ + } + + if ( (! is_denom_pub_hash_null) && + (0 != GNUNET_memcmp (&result[0].denom_hash, + &coin->denom_pub_hash)) ) + { + GNUNET_break_op (0); + result[0].denom_conflict = true; + } + + if ( (! is_denom_pub_hash_null) && + (0 != GNUNET_memcmp (&result[0].denom_hash, + &coin[0].denom_pub_hash)) ) + { + GNUNET_break_op (0); + result[0].denom_conflict = true; + } + + result[0].age_conflict = TALER_AgeCommitmentHashP_NoConflict; + + if (is_age_hash_null != coin[0].no_age_commitment) + { + if (is_age_hash_null) + { + GNUNET_break_op (0); + result[0].age_conflict = TALER_AgeCommitmentHashP_NullExpected; + } + else + { + GNUNET_break_op (0); + result[0].age_conflict = TALER_AgeCommitmentHashP_ValueExpected; + } + } + else if ( (! is_age_hash_null) && + (0 != GNUNET_memcmp (&result[0].h_age_commitment, + &coin[0].h_age_commitment)) ) + { + GNUNET_break_op (0); + result[0].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers; + } + + return qs; +} + + +static enum GNUNET_DB_QueryStatus +insert2 (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_CoinPublicInfo coin[2], + struct TALER_EXCHANGEDB_CoinInfo result[2]) +{ + enum GNUNET_DB_QueryStatus qs; + bool is_denom_pub_hash_null[2] = {false, false}; + bool is_age_hash_null[2] = {false, false}; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + + GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("existed", + &result[0].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + &result[0].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &result[0].denom_hash), + &is_denom_pub_hash_null[0]), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &result[0].h_age_commitment), + &is_age_hash_null[0]), + GNUNET_PQ_result_spec_bool ("existed2", + &result[1].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id2", + &result[1].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2", + &result[1].denom_hash), + &is_denom_pub_hash_null[1]), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2", + &result[1].h_age_commitment), + &is_age_hash_null[1]), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "batch2_known_coin", + "SELECT" + " existed1 AS existed" + ",known_coin_id1 AS known_coin_id" + ",denom_pub_hash1 AS denom_hash" + ",age_commitment_hash1 AS h_age_commitment" + ",existed2 AS existed2" + ",known_coin_id2 AS known_coin_id2" + ",denom_pub_hash2 AS denom_hash2" + ",age_commitment_hash2 AS h_age_commitment2" + " FROM exchange_do_batch2_known_coin" + " ($1, $2, $3, $4, $5, $6, $7, $8);" + ); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "batch2_known_coin", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + return qs; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); /* should be impossible */ + return GNUNET_DB_STATUS_HARD_ERROR; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; /* continued below */ + } + + for (int i = 0; i < 2; i++) + { + if ( (! is_denom_pub_hash_null[i]) && + (0 != GNUNET_memcmp (&result[i].denom_hash, + &coin[i].denom_pub_hash)) ) + { + GNUNET_break_op (0); + result[i].denom_conflict = true; + } + + result[i].age_conflict = TALER_AgeCommitmentHashP_NoConflict; + + if (is_age_hash_null[i] != coin[i].no_age_commitment) + { + if (is_age_hash_null[i]) + { + GNUNET_break_op (0); + result[i].age_conflict = TALER_AgeCommitmentHashP_NullExpected; + } + else + { + GNUNET_break_op (0); + result[i].age_conflict = TALER_AgeCommitmentHashP_ValueExpected; + } + } + else if ( (! is_age_hash_null[i]) && + (0 != GNUNET_memcmp (&result[i].h_age_commitment, + &coin[i].h_age_commitment)) ) + { + GNUNET_break_op (0); + result[i].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers; + } + } + + return qs; +} + + +static enum GNUNET_DB_QueryStatus +insert4 (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_CoinPublicInfo coin[4], + struct TALER_EXCHANGEDB_CoinInfo result[4]) +{ + enum GNUNET_DB_QueryStatus qs; + bool is_denom_pub_hash_null[4] = {false, false, false, false}; + bool is_age_hash_null[4] = {false, false, false, false}; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + + GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), + + GNUNET_PQ_query_param_auto_from_type (&coin[2].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[2].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[2].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[2].denom_sig), + + GNUNET_PQ_query_param_auto_from_type (&coin[3].coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin[3].denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (&coin[3].h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin[3].denom_sig), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("existed", + &result[0].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + &result[0].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &result[0].denom_hash), + &is_denom_pub_hash_null[0]), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &result[0].h_age_commitment), + &is_age_hash_null[0]), + GNUNET_PQ_result_spec_bool ("existed2", + &result[1].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id2", + &result[1].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2", + &result[1].denom_hash), + &is_denom_pub_hash_null[1]), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2", + &result[1].h_age_commitment), + &is_age_hash_null[1]), + GNUNET_PQ_result_spec_bool ("existed3", + &result[2].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id3", + &result[2].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash3", + &result[2].denom_hash), + &is_denom_pub_hash_null[2]), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash3", + &result[2].h_age_commitment), + &is_age_hash_null[2]), + GNUNET_PQ_result_spec_bool ("existed4", + &result[3].existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id4", + &result[3].known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash4", + &result[3].denom_hash), + &is_denom_pub_hash_null[3]), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash4", + &result[3].h_age_commitment), + &is_age_hash_null[3]), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "batch4_known_coin", + "SELECT" + " existed1 AS existed" + ",known_coin_id1 AS known_coin_id" + ",denom_pub_hash1 AS denom_hash" + ",age_commitment_hash1 AS h_age_commitment" + ",existed2 AS existed2" + ",known_coin_id2 AS known_coin_id2" + ",denom_pub_hash2 AS denom_hash2" + ",age_commitment_hash2 AS h_age_commitment2" + ",existed3 AS existed3" + ",known_coin_id3 AS known_coin_id3" + ",denom_pub_hash3 AS denom_hash3" + ",age_commitment_hash3 AS h_age_commitment3" + ",existed4 AS existed4" + ",known_coin_id4 AS known_coin_id4" + ",denom_pub_hash4 AS denom_hash4" + ",age_commitment_hash4 AS h_age_commitment4" + " FROM exchange_do_batch2_known_coin" + " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16);" + ); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "batch4_known_coin", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + return qs; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); /* should be impossible */ + return GNUNET_DB_STATUS_HARD_ERROR; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; /* continued below */ + } + + for (int i = 0; i < 4; i++) + { + if ( (! is_denom_pub_hash_null[i]) && + (0 != GNUNET_memcmp (&result[i].denom_hash, + &coin[i].denom_pub_hash)) ) + { + GNUNET_break_op (0); + result[i].denom_conflict = true; + } + + result[i].age_conflict = TALER_AgeCommitmentHashP_NoConflict; + + if (is_age_hash_null[i] != coin[i].no_age_commitment) + { + if (is_age_hash_null[i]) + { + GNUNET_break_op (0); + result[i].age_conflict = TALER_AgeCommitmentHashP_NullExpected; + } + else + { + GNUNET_break_op (0); + result[i].age_conflict = TALER_AgeCommitmentHashP_ValueExpected; + } + } + else if ( (! is_age_hash_null[i]) && + (0 != GNUNET_memcmp (&result[i].h_age_commitment, + &coin[i].h_age_commitment)) ) + { + GNUNET_break_op (0); + result[i].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers; + } + } + + return qs; +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_batch_ensure_coin_known ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_CoinPublicInfo *coin, + struct TALER_EXCHANGEDB_CoinInfo *result, + unsigned int coin_length, + unsigned int batch_size) +{ + enum GNUNET_DB_QueryStatus qs = 0; + unsigned int i = 0; + + while ( (qs >= 0) && + (i < coin_length) ) + { + unsigned int bs = GNUNET_MIN (batch_size, + coin_length - i); + if (bs >= 4) + { + qs = insert4 (pg, + &coin[i], + &result[i]); + i += 4; + continue; + } + switch (bs) + { + case 3: + case 2: + qs = insert2 (pg, + &coin[i], + &result[i]); + i += 2; + break; + case 1: + qs = insert1 (pg, + &coin[i], + &result[i]); + i += 1; + break; + case 0: + GNUNET_assert (0); + break; + } + } /* end while */ + if (qs < 0) + return qs; + return i; +} diff --git a/src/exchangedb/begin_revolving_shard.c b/src/exchangedb/begin_revolving_shard.c @@ -0,0 +1,258 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/begin_revolving_shard.c + * @brief Implementation of the begin_revolving_shard function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/begin_revolving_shard.h" +#include "taler/exchange-database/commit.h" +#include "helper.h" +#include "taler/exchange-database/start.h" +#include "taler/exchange-database/rollback.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_begin_revolving_shard (struct + TALER_EXCHANGEDB_PostgresContext *pg, + const char *job_name, + uint32_t shard_size, + uint32_t shard_limit, + uint32_t *start_row, + uint32_t *end_row) +{ + + GNUNET_assert (shard_limit <= 1U + (uint32_t) INT_MAX); + GNUNET_assert (shard_limit > 0); + GNUNET_assert (shard_size > 0); + for (unsigned int retries = 0; retries<3; retries++) + { + if (GNUNET_OK != + TALER_EXCHANGEDB_start (pg, + "begin_revolving_shard")) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + + /* First, find last 'end_row' */ + { + enum GNUNET_DB_QueryStatus qs; + uint32_t last_end; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint32 ("end_row", + &last_end), + GNUNET_PQ_result_spec_end + }; + /* Used in #postgres_begin_revolving_shard() */ + PREPARE (pg, + "get_last_revolving_shard", + "SELECT" + " end_row" + " FROM revolving_work_shards" + " WHERE job_name=$1" + " ORDER BY end_row DESC" + " LIMIT 1;"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_last_revolving_shard", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + *start_row = 1U + last_end; + break; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + *start_row = 0; /* base-case: no shards yet */ + break; /* continued below */ + } + } /* get_last_shard */ + + if (*start_row < shard_limit) + { + /* Claim fresh shard */ + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_TIME_Absolute now; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_uint32 (start_row), + GNUNET_PQ_query_param_uint32 (end_row), + GNUNET_PQ_query_param_end + }; + + *end_row = GNUNET_MIN (shard_limit, + *start_row + shard_size - 1); + now = GNUNET_TIME_absolute_get (); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Trying to claim shard %llu-%llu\n", + (unsigned long long) *start_row, + (unsigned long long) *end_row); + + /* Used in #postgres_claim_revolving_shard() */ + PREPARE (pg, + "create_revolving_shard", + "INSERT INTO revolving_work_shards" + "(job_name" + ",last_attempt" + ",start_row" + ",end_row" + ",active" + ") VALUES " + "($1, $2, $3, $4, TRUE);"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "create_revolving_shard", + params); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + /* continued below (with commit) */ + break; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + /* someone else got this shard already, + try again */ + TALER_EXCHANGEDB_rollback (pg); + continue; + } + } /* end create fresh reovlving shard */ + else + { + /* claim oldest existing shard */ + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint32 ("start_row", + start_row), + GNUNET_PQ_result_spec_uint32 ("end_row", + end_row), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_open_revolving_shard", + "SELECT" + " start_row" + ",end_row" + " FROM revolving_work_shards" + " WHERE job_name=$1" + " AND active=FALSE" + " ORDER BY last_attempt ASC" + " LIMIT 1;"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_open_revolving_shard", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + /* no open shards available */ + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + { + enum GNUNET_DB_QueryStatus qsz; + struct GNUNET_TIME_Timestamp now; + struct GNUNET_PQ_QueryParam iparams[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_timestamp (&now), + GNUNET_PQ_query_param_uint32 (start_row), + GNUNET_PQ_query_param_uint32 (end_row), + GNUNET_PQ_query_param_end + }; + + now = GNUNET_TIME_timestamp_get (); + PREPARE (pg, + "reclaim_revolving_shard", + "UPDATE revolving_work_shards" + " SET last_attempt=$2" + " ,active=TRUE" + " WHERE job_name=$1" + " AND start_row=$3" + " AND end_row=$4"); + qsz = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "reclaim_revolving_shard", + iparams); + switch (qsz) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; /* continue with commit */ + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); /* logic error, should be impossible */ + TALER_EXCHANGEDB_rollback (pg); + return GNUNET_DB_STATUS_HARD_ERROR; + } + } + break; /* continue with commit */ + } + } /* end claim oldest existing shard */ + + /* commit */ + { + enum GNUNET_DB_QueryStatus qs; + + qs = TALER_EXCHANGEDB_commit (pg); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + } + } /* retry 'for' loop */ + return GNUNET_DB_STATUS_SOFT_ERROR; +} diff --git a/src/exchangedb/begin_shard.c b/src/exchangedb/begin_shard.c @@ -0,0 +1,262 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/begin_shard.c + * @brief Implementation of the begin_shard function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/begin_shard.h" +#include "helper.h" +#include "taler/exchange-database/start.h" +#include "taler/exchange-database/rollback.h" +#include "taler/exchange-database/commit.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_begin_shard (struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *job_name, + struct GNUNET_TIME_Relative delay, + uint64_t shard_size, + uint64_t *start_row, + uint64_t *end_row) +{ + + for (unsigned int retries = 0; retries<10; retries++) + { + if (GNUNET_OK != + TALER_EXCHANGEDB_start (pg, + "begin_shard")) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + + { + struct GNUNET_TIME_Absolute past; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_absolute_time (&past), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("start_row", + start_row), + GNUNET_PQ_result_spec_uint64 ("end_row", + end_row), + GNUNET_PQ_result_spec_end + }; + + past = GNUNET_TIME_absolute_get (); + PREPARE (pg, + "get_open_shard", + "SELECT" + " start_row" + ",end_row" + " FROM work_shards" + " WHERE job_name=$1" + " AND completed=FALSE" + " AND last_attempt<$2" + " ORDER BY last_attempt ASC" + " LIMIT 1;"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_open_shard", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Serialization error on getting open shard\n"); + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + { + enum GNUNET_DB_QueryStatus qsz; + struct GNUNET_TIME_Absolute now; + struct GNUNET_PQ_QueryParam iparams[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_uint64 (start_row), + GNUNET_PQ_query_param_uint64 (end_row), + GNUNET_PQ_query_param_end + }; + + now = GNUNET_TIME_relative_to_absolute (delay); + PREPARE (pg, + "reclaim_shard", + "UPDATE work_shards" + " SET last_attempt=$2" + " WHERE job_name=$1" + " AND start_row=$3" + " AND end_row=$4"); + qsz = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "reclaim_shard", + iparams); + switch (qsz) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TALER_EXCHANGEDB_rollback (pg); + return qsz; + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Serialization error on claiming open shard\n"); + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + goto commit; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); /* logic error, should be impossible */ + TALER_EXCHANGEDB_rollback (pg); + return GNUNET_DB_STATUS_HARD_ERROR; + } + } + break; /* actually unreachable */ + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + break; /* continued below */ + } + } /* get_open_shard */ + + /* No open shard, find last 'end_row' */ + { + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("end_row", + start_row), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_last_shard", + "SELECT" + " end_row" + " FROM work_shards" + " WHERE job_name=$1" + " ORDER BY end_row DESC" + " LIMIT 1;"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_last_shard", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Serialization error on getting last shard\n"); + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + *start_row = 0; /* base-case: no shards yet */ + break; /* continued below */ + } + *end_row = *start_row + shard_size; + } /* get_last_shard */ + + /* Claim fresh shard */ + { + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_TIME_Absolute now; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_uint64 (start_row), + GNUNET_PQ_query_param_uint64 (end_row), + GNUNET_PQ_query_param_end + }; + + now = GNUNET_TIME_relative_to_absolute (delay); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Trying to claim shard (%llu-%llu]\n", + (unsigned long long) *start_row, + (unsigned long long) *end_row); + + PREPARE (pg, + "claim_next_shard", + "INSERT INTO work_shards" + "(job_name" + ",last_attempt" + ",start_row" + ",end_row" + ") VALUES " + "($1, $2, $3, $4);"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "claim_next_shard", + params); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Serialization error on claiming next shard\n"); + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + /* continued below */ + break; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + /* someone else got this shard already, + try again */ + TALER_EXCHANGEDB_rollback (pg); + continue; + } + } /* claim_next_shard */ + + /* commit */ +commit: + { + enum GNUNET_DB_QueryStatus qs; + + qs = TALER_EXCHANGEDB_commit (pg); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Serialization error on commit for beginning shard\n"); + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Claimed new shard\n"); + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + } + } /* retry 'for' loop */ + return GNUNET_DB_STATUS_SOFT_ERROR; +} diff --git a/src/exchangedb/clear_aml_lock.c b/src/exchangedb/clear_aml_lock.c @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/clear_aml_lock.c + * @brief Implementation of the clear_aml_lock function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/clear_aml_lock.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_clear_aml_lock ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "clear_aml_lock", + "UPDATE kyc_targets" + " SET aml_program_lock_timeout=NULL" + " WHERE h_normalized_payto=$1"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "clear_aml_lock", + params); +} diff --git a/src/exchangedb/commit.c b/src/exchangedb/commit.c @@ -0,0 +1,52 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/commit.c + * @brief Implementation of the commit function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/commit.h" +#include "helper.h" + + +/** + * Commit the current transaction of a database connection. + * + * @param pg the database context + * @return final transaction status + */ +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_commit (struct TALER_EXCHANGEDB_PostgresContext *pg) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + GNUNET_break (NULL != pg->transaction_name); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Committing transaction `%s'\n", + pg->transaction_name); + PREPARE (pg, + "do_commit", + "COMMIT"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "do_commit", + params); + pg->transaction_name = NULL; + return qs; +} diff --git a/src/exchangedb/complete_shard.c b/src/exchangedb/complete_shard.c @@ -0,0 +1,52 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/complete_shard.c + * @brief Implementation of the complete_shard function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/complete_shard.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_complete_shard (struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *job_name, + uint64_t start_row, + uint64_t end_row) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_uint64 (&start_row), + GNUNET_PQ_query_param_uint64 (&end_row), + GNUNET_PQ_query_param_end + }; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Completing shard %llu-%llu\n", + (unsigned long long) start_row, + (unsigned long long) end_row); + PREPARE (pg, + "complete_shard", + "UPDATE work_shards" + " SET completed=TRUE" + " WHERE job_name=$1" + " AND start_row=$2" + " AND end_row=$3"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "complete_shard", + params); +} diff --git a/src/exchangedb/compute_shard.c b/src/exchangedb/compute_shard.c @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/compute_shard.c + * @brief Implementation of the compute_shard function for Postgres + * @author Christian Grothoff + */ +#include "taler/exchange-database/compute_shard.h" +#include "helper.h" + + +uint64_t +TALER_EXCHANGEDB_compute_shard (const struct TALER_MerchantPublicKeyP * + merchant_pub) +{ + uint32_t res; + + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_hkdf_gnunet ( + &res, + sizeof (res), + merchant_pub, + sizeof (*merchant_pub), + "VOID", + 4)); + /* interpret hash result as NBO for platform independence, + convert to HBO and map to [0..2^31-1] range */ + res = ntohl (res); + if (res > INT32_MAX) + res += INT32_MIN; + GNUNET_assert (res <= INT32_MAX); + return (uint64_t) res; +} diff --git a/src/exchangedb/count_known_coins.c b/src/exchangedb/count_known_coins.c @@ -0,0 +1,59 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/count_known_coins.c + * @brief Implementation of the count_known_coins function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/count_known_coins.h" +#include "helper.h" + +long long +TALER_EXCHANGEDB_count_known_coins (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct + TALER_DenominationHashP *denom_pub_hash) +{ + uint64_t count; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("count", + &count), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + + PREPARE (pg, + "count_known_coins", + "SELECT" + " COUNT(*) AS count" + " FROM known_coins" + " WHERE denominations_serial=" + " (SELECT denominations_serial" + " FROM denominations" + " WHERE denom_pub_hash=$1);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "count_known_coins", + params, + rs); + if (0 > qs) + return (long long) qs; + return (long long) count; +} diff --git a/src/exchangedb/create_aggregation_transient.c b/src/exchangedb/create_aggregation_transient.c @@ -0,0 +1,61 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/create_aggregation_transient.c + * @brief Implementation of the create_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/create_aggregation_transient.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_create_aggregation_transient ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_FullPaytoHashP *h_payto, + const char *exchange_account_section, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, + const struct TALER_Amount *total) +{ + struct GNUNET_PQ_QueryParam params[] = { + TALER_PQ_query_param_amount (pg->conn, + total), + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_uint64 (&kyc_requirement_row), + GNUNET_PQ_query_param_string (exchange_account_section), + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "create_aggregation_transient", + "INSERT INTO aggregation_transient" + " (amount" + " ,merchant_pub" + " ,wire_target_h_payto" + " ,legitimization_requirement_serial_id" + " ,exchange_account_section" + " ,wtid_raw)" + " VALUES ($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "create_aggregation_transient", + params); +} diff --git a/src/exchangedb/create_tables.c b/src/exchangedb/create_tables.c @@ -0,0 +1,78 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/create_tables.c + * @brief Implementation of the create_tables function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/create_tables.h" +#include "helper.h" + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGEDB_create_tables (struct TALER_EXCHANGEDB_PostgresContext *pg, + bool support_partitions, + uint32_t num_partitions) +{ + struct GNUNET_PQ_Context *conn; + enum GNUNET_GenericReturnValue ret; + struct GNUNET_PQ_QueryParam params[] = { + support_partitions + ? GNUNET_PQ_query_param_uint32 (&num_partitions) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + conn = GNUNET_PQ_connect_with_cfg (pg->cfg, + "exchangedb-postgres", + "exchange-", + es, + NULL); + if (NULL == conn) + return GNUNET_SYSERR; + ret = GNUNET_PQ_exec_sql (conn, + "procedures"); + GNUNET_break (GNUNET_OK == ret); + if (GNUNET_OK == ret) + { + struct GNUNET_PQ_Context *tconn; + + tconn = pg->conn; + pg->prep_gen++; + pg->conn = conn; + PREPARE (pg, + "create_tables", + "SELECT" + " exchange_do_create_tables" + " ($1::INTEGER);"); + pg->conn = tconn; + if (0 > + GNUNET_PQ_eval_prepared_non_select (conn, + "create_tables", + params)) + { + GNUNET_break (0); + ret = GNUNET_SYSERR; + } + } + GNUNET_PQ_disconnect (conn); + return ret; +} diff --git a/src/exchangedb/delete_aggregation_transient.c b/src/exchangedb/delete_aggregation_transient.c @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/delete_aggregation_transient.c + * @brief Implementation of the delete_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/delete_aggregation_transient.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_delete_aggregation_transient ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_FullPaytoHashP *h_payto, + const struct TALER_WireTransferIdentifierRawP *wtid) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "delete_aggregation_transient", + "DELETE FROM aggregation_transient" + " WHERE wire_target_h_payto=$1" + " AND wtid_raw=$2"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "delete_aggregation_transient", + params); +} diff --git a/src/exchangedb/delete_shard_locks.c b/src/exchangedb/delete_shard_locks.c @@ -0,0 +1,37 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/delete_shard_locks.c + * @brief Implementation of the delete_shard_locks function for Postgres + * @author Christian Grothoff + */ +#include "taler/exchange-database/delete_shard_locks.h" +#include "helper.h" + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGEDB_delete_shard_locks (struct TALER_EXCHANGEDB_PostgresContext *pg + ) +{ + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_execute ("DELETE FROM work_shards;"), + GNUNET_PQ_make_execute ("DELETE FROM revolving_work_shards;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + return GNUNET_PQ_exec_statements (pg->conn, + es); +} diff --git a/src/exchangedb/disable_rules.c b/src/exchangedb/disable_rules.c @@ -0,0 +1,57 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/disable_rules.c + * @brief Implementation of the disable_rules function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/disable_rules.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_disable_rules ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *schema) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (schema), + GNUNET_PQ_query_param_end + }; + bool found; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("out_found", + &found), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "call_exchange_drop_customization", + "SELECT out_found" + " FROM exchange_drop_customization" + " ($1);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_exchange_drop_customization", + params, + rs); + if (qs < 0) + return qs; + if (found) + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; +} diff --git a/src/exchangedb/do_check_deposit_idempotent.c b/src/exchangedb/do_check_deposit_idempotent.c @@ -0,0 +1,109 @@ +/* + This file is part of TALER + Copyright (C) 2022-2023 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/> + */ +/** + * @file exchangedb/do_deposit.c + * @brief Implementation of the do_deposit function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_check_deposit_idempotent.h" +#include "helper.h" +#include "taler/exchange-database/compute_shard.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_do_check_deposit_idempotent ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_BatchDeposit *bd, + struct GNUNET_TIME_Timestamp *exchange_timestamp, + bool *is_idempotent) +{ + uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&bd->merchant_pub); + const struct TALER_CoinSpendPublicKeyP *coin_pubs[GNUNET_NZL (bd->num_cdis)]; + const struct TALER_CoinSpendSignatureP *coin_sigs[GNUNET_NZL (bd->num_cdis)]; + struct TALER_Amount amounts_with_fee[GNUNET_NZL (bd->num_cdis)]; + struct TALER_NormalizedPaytoHashP h_normalized_payto; + struct GNUNET_PQ_QueryParam params[] = { + /* data for batch_deposits */ + GNUNET_PQ_query_param_uint64 (&deposit_shard), + GNUNET_PQ_query_param_auto_from_type (&bd->merchant_pub), + GNUNET_PQ_query_param_timestamp (&bd->wallet_timestamp), + GNUNET_PQ_query_param_timestamp (exchange_timestamp), + GNUNET_PQ_query_param_timestamp (&bd->refund_deadline), + GNUNET_PQ_query_param_timestamp (&bd->wire_deadline), + GNUNET_PQ_query_param_auto_from_type (&bd->h_contract_terms), + (bd->no_wallet_data_hash) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (&bd->wallet_data_hash), + GNUNET_PQ_query_param_auto_from_type (&bd->wire_salt), + GNUNET_PQ_query_param_auto_from_type (&bd->wire_target_h_payto), + (0 == bd->policy_details_serial_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 (&bd->policy_details_serial_id), + GNUNET_PQ_query_param_bool (bd->policy_blocked), + /* arrays for coin_deposits */ + GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis, + coin_pubs, + pg->conn), + GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis, + coin_sigs, + pg->conn), + TALER_PQ_query_param_array_amount (bd->num_cdis, + amounts_with_fee, + pg->conn), + GNUNET_PQ_query_param_end + }; + bool no_time; + 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_bool ("is_idempotent", + is_idempotent), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + TALER_full_payto_normalize_and_hash (bd->receiver_wire_account, + &h_normalized_payto); + for (unsigned int i = 0; i < bd->num_cdis; i++) + { + const struct TALER_EXCHANGEDB_CoinDepositInformation *cdi + = &bd->cdis[i]; + + amounts_with_fee[i] = cdi->amount_with_fee; + coin_pubs[i] = &cdi->coin.coin_pub; + coin_sigs[i] = &cdi->csig; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Do deposit %u = %s\n", + i, + TALER_B2S (&cdi->coin.coin_pub)); + } + PREPARE (pg, + "call_check_deposit_idempotent", + "SELECT " + " out_exchange_timestamp AS exchange_timestamp" + ",out_is_idempotent AS is_idempotent" + " FROM exchange_do_check_deposit_idempotent" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_check_deposit_idempotent", + params, + rs); + GNUNET_PQ_cleanup_query_params_closures (params); + return qs; +} diff --git a/src/exchangedb/do_deposit.c b/src/exchangedb/do_deposit.c @@ -0,0 +1,171 @@ +/* + This file is part of TALER + 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 + 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/> + */ +/** + * @file exchangedb/do_deposit.c + * @brief Implementation of the do_deposit function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_deposit.h" +#include "helper.h" +#include "taler/exchange-database/compute_shard.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_do_deposit ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + 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) +{ + uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&bd->merchant_pub); + const struct TALER_CoinSpendPublicKeyP *coin_pubs[GNUNET_NZL (bd->num_cdis)]; + 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 */ + GNUNET_PQ_query_param_uint64 (&deposit_shard), + GNUNET_PQ_query_param_auto_from_type (&bd->merchant_pub), + GNUNET_PQ_query_param_auto_from_type (&bd->merchant_sig), + GNUNET_PQ_query_param_timestamp (&bd->wallet_timestamp), + GNUNET_PQ_query_param_timestamp (exchange_timestamp), + GNUNET_PQ_query_param_timestamp (&bd->refund_deadline), + GNUNET_PQ_query_param_timestamp (&bd->wire_deadline), + GNUNET_PQ_query_param_auto_from_type (&bd->h_contract_terms), + (bd->no_wallet_data_hash) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (&bd->wallet_data_hash), + GNUNET_PQ_query_param_auto_from_type (&bd->wire_salt), + GNUNET_PQ_query_param_auto_from_type (&bd->wire_target_h_payto), + GNUNET_PQ_query_param_auto_from_type (&h_normalized_payto), + (0 == bd->policy_details_serial_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 (&bd->policy_details_serial_id), + GNUNET_PQ_query_param_bool (bd->policy_blocked), + /* to create entry in wire_targets */ + GNUNET_PQ_query_param_string (bd->receiver_wire_account.full_payto), + /* arrays for coin_deposits */ + GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis, + coin_pubs, + pg->conn), + GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis, + coin_sigs, + pg->conn), + 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 + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (bd->extra_wire_subject_metadata), + 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), + GNUNET_PQ_result_spec_bool ("conflicted", + ctr_conflict), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + GNUNET_assert (0 < bd->num_cdis); + TALER_full_payto_normalize_and_hash (bd->receiver_wire_account, + &h_normalized_payto); + for (unsigned int i = 0; i < bd->num_cdis; i++) + { + const struct TALER_EXCHANGEDB_CoinDepositInformation *cdi + = &bd->cdis[i]; + + if (0 == i) + { + total_amount = cdi->amount_with_fee; + total_without_fee = cdi->amount_with_fee; + } + else + { + GNUNET_assert (0 <= + 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; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Do deposit %u = %s\n", + i, + TALER_B2S (&cdi->coin.coin_pub)); + } + PREPARE (pg, + "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,$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/do_purse_delete.c b/src/exchangedb/do_purse_delete.c @@ -0,0 +1,60 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/do_purse_delete.c + * @brief Implementation of the do_purse_delete function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_purse_delete.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_do_purse_delete ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig, + bool *decided, + bool *found) +{ + struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_auto_from_type (purse_sig), + GNUNET_PQ_query_param_timestamp (&now), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("decided", + decided), + GNUNET_PQ_result_spec_bool ("found", + found), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "call_purse_delete", + "SELECT " + " out_decided AS decided" + ",out_found AS found" + " FROM exchange_do_purse_delete" + " ($1,$2,$3);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_purse_delete", + params, + rs); +} diff --git a/src/exchangedb/do_purse_deposit.c b/src/exchangedb/do_purse_deposit.c @@ -0,0 +1,86 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/do_purse_deposit.c + * @brief Implementation of the do_purse_deposit function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_purse_deposit.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_do_purse_deposit ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *amount, + const struct TALER_CoinSpendSignatureP *coin_sig, + const struct TALER_Amount *amount_minus_fee, + bool *balance_ok, + bool *too_late, + bool *conflict) +{ + struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get (); + struct GNUNET_TIME_Timestamp reserve_expiration; + uint64_t partner_id = 0; /* FIXME #7271: WAD support... */ + struct GNUNET_PQ_QueryParam params[] = { + (0 == partner_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 (&partner_id), + GNUNET_PQ_query_param_auto_from_type (purse_pub), + TALER_PQ_query_param_amount ( + pg->conn, + amount), + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_auto_from_type (coin_sig), + TALER_PQ_query_param_amount ( + pg->conn, + amount_minus_fee), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_timestamp (&now), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("balance_ok", + balance_ok), + GNUNET_PQ_result_spec_bool ("too_late", + too_late), + GNUNET_PQ_result_spec_bool ("conflict", + conflict), + GNUNET_PQ_result_spec_end + }; + + reserve_expiration + = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), + pg->legal_reserve_expiration_time)); + + PREPARE (pg, + "call_purse_deposit", + "SELECT " + " out_balance_ok AS balance_ok" + ",out_conflict AS conflict" + ",out_late AS too_late" + " FROM exchange_do_purse_deposit" + " ($1,$2,$3,$4,$5,$6,$7,$8);"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_purse_deposit", + params, + rs); +} diff --git a/src/exchangedb/do_purse_merge.c b/src/exchangedb/do_purse_merge.c @@ -0,0 +1,87 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/do_purse_merge.c + * @brief Implementation of the do_purse_merge function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_purse_merge.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_do_purse_merge ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergeSignatureP *merge_sig, + const struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_ReserveSignatureP *reserve_sig, + const char *partner_url, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool *no_partner, + bool *no_balance, + bool *in_conflict) +{ + struct TALER_NormalizedPaytoHashP h_payto; + struct GNUNET_TIME_Timestamp expiration + = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_auto_from_type (merge_sig), + GNUNET_PQ_query_param_timestamp (&merge_timestamp), + GNUNET_PQ_query_param_auto_from_type (reserve_sig), + (NULL == partner_url) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (partner_url), + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_timestamp (&expiration), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("no_partner", + no_partner), + GNUNET_PQ_result_spec_bool ("no_balance", + no_balance), + GNUNET_PQ_result_spec_bool ("conflict", + in_conflict), + GNUNET_PQ_result_spec_end + }; + + { + struct TALER_NormalizedPayto payto_uri; + + payto_uri = TALER_reserve_make_payto (pg->exchange_url, + reserve_pub); + TALER_normalized_payto_hash (payto_uri, + &h_payto); + GNUNET_free (payto_uri.normalized_payto); + } + PREPARE (pg, + "call_purse_merge", + "SELECT" + " out_no_partner AS no_partner" + ",out_no_balance AS no_balance" + ",out_conflict AS conflict" + " FROM exchange_do_purse_merge" + " ($1, $2, $3, $4, $5, $6, $7, $8);"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_purse_merge", + params, + rs); +} diff --git a/src/exchangedb/do_recoup.c b/src/exchangedb/do_recoup.c @@ -0,0 +1,81 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/do_recoup.c + * @brief Implementation of the do_recoup function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_recoup.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_do_recoup ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t withdraw_id, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, + const struct TALER_CoinSpendSignatureP *coin_sig, + struct GNUNET_TIME_Timestamp *recoup_timestamp, + bool *recoup_ok, + bool *internal_failure) +{ + struct GNUNET_TIME_Timestamp reserve_gc + = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time); + struct GNUNET_TIME_Timestamp reserve_expiration + = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_uint64 (&withdraw_id), + GNUNET_PQ_query_param_auto_from_type (coin_bks), + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_uint64 (&known_coin_id), + GNUNET_PQ_query_param_auto_from_type (coin_sig), + GNUNET_PQ_query_param_timestamp (&reserve_gc), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_timestamp (recoup_timestamp), + GNUNET_PQ_query_param_end + }; + bool is_null; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + recoup_timestamp), + &is_null), + GNUNET_PQ_result_spec_bool ("recoup_ok", + recoup_ok), + GNUNET_PQ_result_spec_bool ("internal_failure", + internal_failure), + GNUNET_PQ_result_spec_end + }; + + + PREPARE (pg, + "call_recoup", + "SELECT " + " out_recoup_timestamp AS recoup_timestamp" + ",out_recoup_ok AS recoup_ok" + ",out_internal_failure AS internal_failure" + " FROM exchange_do_recoup_to_reserve" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_recoup", + params, + rs); +} diff --git a/src/exchangedb/do_recoup_refresh.c b/src/exchangedb/do_recoup_refresh.c @@ -0,0 +1,76 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2025 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/> + */ +/** + * @file exchangedb/do_recoup_refresh.c + * @brief Implementation of the do_recoup_refresh function for Postgres + * @author Christian Grothoff + * @author Özgür Kesim + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_recoup_refresh.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_do_recoup_refresh ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + uint64_t refresh_id, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, + const struct TALER_CoinSpendSignatureP *coin_sig, + struct GNUNET_TIME_Timestamp *recoup_timestamp, + bool *recoup_ok, + bool *internal_failure) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (old_coin_pub), + GNUNET_PQ_query_param_uint64 (&refresh_id), + GNUNET_PQ_query_param_auto_from_type (coin_bks), + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_uint64 (&known_coin_id), + GNUNET_PQ_query_param_auto_from_type (coin_sig), + GNUNET_PQ_query_param_timestamp (recoup_timestamp), + GNUNET_PQ_query_param_end + }; + bool is_null; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + recoup_timestamp), + &is_null), + GNUNET_PQ_result_spec_bool ("recoup_ok", + recoup_ok), + GNUNET_PQ_result_spec_bool ("internal_failure", + internal_failure), + GNUNET_PQ_result_spec_end + }; + + + PREPARE (pg, + "call_recoup_refresh", + "SELECT " + " out_recoup_timestamp AS recoup_timestamp" + ",out_recoup_ok AS recoup_ok" + ",out_internal_failure AS internal_failure" + " FROM exchange_do_recoup_to_coin" + " ($1,$2,$3,$4,$5,$6,$7);"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_recoup_refresh", + params, + rs); +} diff --git a/src/exchangedb/do_refresh.c b/src/exchangedb/do_refresh.c @@ -0,0 +1,138 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/do_refresh.c + * @brief Implementation of the do_refresh function for Postgres + * @author Özgür Kesim + */ +#include "taler/taler_exchangedb_lib.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_refresh.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_do_refresh ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh, + const struct GNUNET_TIME_Timestamp *timestamp, + bool *found, + uint32_t *noreveal_index, + bool *zombie_required, + bool *nonce_reuse, + bool *balance_ok, + struct TALER_Amount *coin_balance) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&refresh->rc), + GNUNET_PQ_query_param_timestamp (timestamp), + GNUNET_PQ_query_param_auto_from_type (&refresh->refresh_seed), /* 3 */ + (refresh->is_v27_refresh) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_array_auto_from_type (refresh->num_coins, + refresh->transfer_pubs, + pg->conn), + GNUNET_PQ_query_param_auto_from_type (&refresh->planchets_h), + TALER_PQ_query_param_amount (pg->conn, /* 6 */ + &refresh->amount_with_fee), + (refresh->no_blinding_seed) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (&refresh->blinding_seed), + (0 < refresh->num_cs_r_values) + ? TALER_PQ_query_param_array_cs_r_pub (refresh->num_cs_r_values, + refresh->cs_r_values, + pg->conn) + : GNUNET_PQ_query_param_null (), + (0 < refresh->num_cs_r_values) + ? GNUNET_PQ_query_param_uint64 (&refresh->cs_r_choices) /* 9 */ + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_auto_from_type (&refresh->selected_h), + TALER_PQ_query_param_array_blinded_denom_sig (refresh->num_coins, + refresh->denom_sigs, + pg->conn), + GNUNET_PQ_query_param_array_uint64 (refresh->num_coins, /* 12 */ + refresh->denom_serials, + pg->conn), + GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub), + GNUNET_PQ_query_param_auto_from_type (&refresh->coin_sig), + GNUNET_PQ_query_param_uint32 (&refresh->noreveal_index), /* 15 */ + GNUNET_PQ_query_param_bool (*zombie_required), + GNUNET_PQ_query_param_end + }; + bool coin_found; + bool no_noreveal_index; + bool no_coin_balance; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("coin_found", + &coin_found), + GNUNET_PQ_result_spec_bool ("balance_ok", + balance_ok), + GNUNET_PQ_result_spec_bool ("zombie_required", + zombie_required), + GNUNET_PQ_result_spec_bool ("nonce_reuse", + nonce_reuse), + GNUNET_PQ_result_spec_bool ("found", + found), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint32 ("noreveal_index", + noreveal_index), + &no_noreveal_index), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_RESULT_SPEC_AMOUNT ("coin_balance", + coin_balance), + &no_coin_balance), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "call_refresh", + "SELECT " + " out_coin_found AS coin_found" + ",out_balance_ok AS balance_ok" + ",out_zombie_bad AS zombie_required" + ",out_nonce_reuse AS nonce_reuse" + ",out_idempotent AS found" + ",out_noreveal_index AS noreveal_index" + ",out_coin_balance AS coin_balance" + " FROM exchange_do_refresh" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_refresh", + params, + rs); + GNUNET_PQ_cleanup_query_params_closures (params); + if (0 > qs) + { + GNUNET_break (0); + return qs; + } + if (! coin_found) + { + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + if (*found && no_noreveal_index) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (! balance_ok && no_coin_balance) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + return qs; +} diff --git a/src/exchangedb/do_refund.c b/src/exchangedb/do_refund.c @@ -0,0 +1,91 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/do_refund.c + * @brief Implementation of the do_refund function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_refund.h" +#include "helper.h" +#include "taler/exchange-database/compute_shard.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_do_refund ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_Refund *refund, + const struct TALER_Amount *deposit_fee, + uint64_t known_coin_id, + bool *not_found, + bool *refund_ok, + bool *gone, + bool *conflict) +{ + uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&refund->details. + merchant_pub); + struct TALER_Amount amount_without_fee; + struct GNUNET_PQ_QueryParam params[] = { + TALER_PQ_query_param_amount (pg->conn, + &refund->details.refund_amount), + TALER_PQ_query_param_amount (pg->conn, + &amount_without_fee), + TALER_PQ_query_param_amount (pg->conn, + deposit_fee), + GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms), + GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id), + GNUNET_PQ_query_param_uint64 (&deposit_shard), + GNUNET_PQ_query_param_uint64 (&known_coin_id), + GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub), + GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub), + GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("not_found", + not_found), + GNUNET_PQ_result_spec_bool ("refund_ok", + refund_ok), + GNUNET_PQ_result_spec_bool ("gone", + gone), + GNUNET_PQ_result_spec_bool ("conflict", + conflict), + GNUNET_PQ_result_spec_end + }; + + if (0 > + TALER_amount_subtract (&amount_without_fee, + &refund->details.refund_amount, + &refund->details.refund_fee)) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + PREPARE (pg, + "call_refund", + "SELECT " + " out_not_found AS not_found" + ",out_refund_ok AS refund_ok" + ",out_gone AS gone" + ",out_conflict AS conflict" + " FROM exchange_do_refund" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_refund", + params, + rs); +} diff --git a/src/exchangedb/do_reserve_open.c b/src/exchangedb/do_reserve_open.c @@ -0,0 +1,97 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file do_reserve_open.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_reserve_open.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_do_reserve_open ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *total_paid, + const struct TALER_Amount *reserve_payment, + uint32_t min_purse_limit, + const struct TALER_ReserveSignatureP *reserve_sig, + struct GNUNET_TIME_Timestamp desired_expiration, + struct GNUNET_TIME_Timestamp now, + const struct TALER_Amount *open_fee, + bool *no_funds, + struct TALER_Amount *reserve_balance, + struct TALER_Amount *open_cost, + struct GNUNET_TIME_Timestamp *final_expiration) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + TALER_PQ_query_param_amount ( + pg->conn, + total_paid), + TALER_PQ_query_param_amount ( + pg->conn, + reserve_payment), + GNUNET_PQ_query_param_uint32 (&min_purse_limit), + GNUNET_PQ_query_param_uint32 (&pg->def_purse_limit), + GNUNET_PQ_query_param_auto_from_type (reserve_sig), + GNUNET_PQ_query_param_timestamp (&desired_expiration), + GNUNET_PQ_query_param_relative_time (&pg->legal_reserve_expiration_time), + GNUNET_PQ_query_param_timestamp (&now), + TALER_PQ_query_param_amount (pg->conn, + open_fee), + GNUNET_PQ_query_param_end + }; + bool no_reserve = true; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_amount ("out_open_cost", + pg->currency, + open_cost), + TALER_PQ_result_spec_amount ("out_reserve_balance", + pg->currency, + reserve_balance), + GNUNET_PQ_result_spec_timestamp ("out_final_expiration", + final_expiration), + GNUNET_PQ_result_spec_bool ("out_no_reserve", + &no_reserve), + GNUNET_PQ_result_spec_bool ("out_no_funds", + no_funds), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "do_reserve_open", + "SELECT " + " out_open_cost" + ",out_final_expiration" + ",out_no_funds" + ",out_no_reserve" + ",out_reserve_balance" + " FROM exchange_do_reserve_open" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "do_reserve_open", + params, + rs); + if (qs <= 0) + return qs; + if (no_reserve) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + return qs; +} diff --git a/src/exchangedb/do_reserve_purse.c b/src/exchangedb/do_reserve_purse.c @@ -0,0 +1,118 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/do_reserve_purse.c + * @brief Implementation of the do_reserve_purse function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_reserve_purse.h" +#include "helper.h" + + +/** + * Function called insert request to merge a purse into a reserve by the + * respective purse merge key. The purse must not have been merged into a + * different reserve. + * + * @param pg the database context + * @param purse_pub purse to merge + * @param merge_sig signature affirming the merge + * @param merge_timestamp time of the merge + * @param reserve_sig signature of the reserve affirming the merge + * @param purse_fee amount to charge the reserve for the purse creation, NULL to use the quota + * @param reserve_pub public key of the reserve to credit + * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already + * @param[out] no_reserve set to true if @a reserve_pub is not a known reserve + * @param[out] insufficient_funds set to true if @a reserve_pub has insufficient capacity to create another purse + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_do_reserve_purse ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergeSignatureP *merge_sig, + const struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_Amount *purse_fee, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool *in_conflict, + bool *no_reserve, + bool *insufficient_funds) +{ + struct TALER_Amount zero_fee; + struct TALER_NormalizedPaytoHashP h_payto; + struct GNUNET_TIME_Timestamp reserve_expiration + = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), + pg->idle_reserve_expiration_time)); + struct GNUNET_TIME_Timestamp reserve_gc + = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), + pg->legal_reserve_expiration_time)); + + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_auto_from_type (merge_sig), + GNUNET_PQ_query_param_timestamp (&merge_timestamp), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_timestamp (&reserve_gc), + GNUNET_PQ_query_param_auto_from_type (reserve_sig), + GNUNET_PQ_query_param_bool (NULL == purse_fee), + TALER_PQ_query_param_amount (pg->conn, + NULL == purse_fee + ? &zero_fee + : purse_fee), + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_auto_from_type (&h_payto), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("insufficient_funds", + insufficient_funds), + GNUNET_PQ_result_spec_bool ("conflict", + in_conflict), + GNUNET_PQ_result_spec_bool ("no_reserve", + no_reserve), + GNUNET_PQ_result_spec_end + }; + + { + struct TALER_NormalizedPayto payto_uri; + + payto_uri = TALER_reserve_make_payto (pg->exchange_url, + reserve_pub); + TALER_normalized_payto_hash (payto_uri, + &h_payto); + GNUNET_free (payto_uri.normalized_payto); + } + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (pg->currency, + &zero_fee)); + PREPARE (pg, + "call_reserve_purse", + "SELECT" + " out_no_funds AS insufficient_funds" + ",out_no_reserve AS no_reserve" + ",out_conflict AS conflict" + " FROM exchange_do_reserve_purse" + " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_reserve_purse", + params, + rs); +} diff --git a/src/exchangedb/do_withdraw.c b/src/exchangedb/do_withdraw.c @@ -0,0 +1,140 @@ +/* + This file is part of TALER + Copyright (C) 2023-2025 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/> + */ +/** + * @file exchangedb/do_withdraw.c + * @brief Implementation of the do_withdraw function for Postgres + * @author Özgür Kesim + */ +#include "taler/taler_exchangedb_lib.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/do_withdraw.h" +#include "helper.h" +#include <gnunet/gnunet_time_lib.h> + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_do_withdraw ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_Withdraw *withdraw, + const struct GNUNET_TIME_Timestamp *timestamp, + bool *balance_ok, + struct TALER_Amount *reserve_balance, + bool *age_ok, + uint16_t *required_age, + uint32_t *reserve_birthday, + bool *idempotent, + uint16_t *noreveal_index, + bool *nonce_reuse) +{ + struct GNUNET_TIME_Timestamp gc; + struct GNUNET_PQ_QueryParam params[] = { + TALER_PQ_query_param_amount (pg->conn, + &withdraw->amount_with_fee), + GNUNET_PQ_query_param_auto_from_type (&withdraw->reserve_pub), + GNUNET_PQ_query_param_auto_from_type (&withdraw->reserve_sig), + GNUNET_PQ_query_param_timestamp (timestamp), + GNUNET_PQ_query_param_timestamp (&gc), + GNUNET_PQ_query_param_auto_from_type (&withdraw->planchets_h), + (withdraw->age_proof_required) + ? GNUNET_PQ_query_param_uint16 (&withdraw->max_age) + : GNUNET_PQ_query_param_null (), + (withdraw->age_proof_required) + ? GNUNET_PQ_query_param_uint16 (&withdraw->noreveal_index) + : GNUNET_PQ_query_param_null (), + (withdraw->age_proof_required) + ? GNUNET_PQ_query_param_auto_from_type (&withdraw->selected_h) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_array_uint64 (withdraw->num_coins, + withdraw->denom_serials, + pg->conn), + TALER_PQ_query_param_array_blinded_denom_sig (withdraw->num_coins, + withdraw->denom_sigs, + pg->conn), + (withdraw->no_blinding_seed) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (&withdraw->blinding_seed), + (withdraw->no_blinding_seed) + ? GNUNET_PQ_query_param_null () + : TALER_PQ_query_param_array_cs_r_pub (withdraw->num_cs_r_values, + withdraw->cs_r_values, + pg->conn), + (withdraw->no_blinding_seed) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 (&withdraw->cs_r_choices), + GNUNET_PQ_query_param_end + }; + bool reserve_found; + bool no_noreveal_index; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("out_reserve_found", + &reserve_found), + GNUNET_PQ_result_spec_bool ("out_balance_ok", + balance_ok), + TALER_PQ_RESULT_SPEC_AMOUNT ("out_reserve_balance", + reserve_balance), + GNUNET_PQ_result_spec_bool ("out_age_ok", + age_ok), + GNUNET_PQ_result_spec_uint16 ("out_required_age", + required_age), + GNUNET_PQ_result_spec_uint32 ("out_reserve_birthday", + reserve_birthday), + GNUNET_PQ_result_spec_bool ("out_idempotent", + idempotent), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint16 ("out_noreveal_index", + noreveal_index), + &no_noreveal_index), + GNUNET_PQ_result_spec_bool ("out_nonce_reuse", + nonce_reuse), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + GNUNET_assert ((! withdraw->no_blinding_seed) || + (0 == withdraw->num_cs_r_values)); + + gc = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add (timestamp->abs_time, + pg->legal_reserve_expiration_time)); + PREPARE (pg, + "call_withdraw", + "SELECT " + " out_reserve_found" + ",out_balance_ok" + ",out_reserve_balance" + ",out_age_ok" + ",out_required_age" + ",out_reserve_birthday" + ",out_idempotent" + ",out_noreveal_index" + ",out_nonce_reuse" + " FROM exchange_do_withdraw" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_withdraw", + params, + rs); + GNUNET_PQ_cleanup_query_params_closures (params); + + if (0 > qs) + return qs; + if (! reserve_found) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + if ((withdraw->age_proof_required) && + (idempotent && no_noreveal_index)) + GNUNET_break (0); + return qs; +} diff --git a/src/exchangedb/drain_kyc_alert.c b/src/exchangedb/drain_kyc_alert.c @@ -0,0 +1,55 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/drain_kyc_alert.c + * @brief Implementation of the drain_kyc_alert function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/drain_kyc_alert.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_drain_kyc_alert (struct TALER_EXCHANGEDB_PostgresContext *pg, + uint32_t trigger_type, + struct TALER_NormalizedPaytoHashP *h_payto) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint32 (&trigger_type), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("h_payto", + h_payto), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "drain_kyc_alert", + "DELETE FROM kyc_alerts" + " WHERE trigger_type=$1" + " AND h_payto = " + " (SELECT h_payto " + " FROM kyc_alerts" + " WHERE trigger_type=$1" + " LIMIT 1)" + " RETURNING h_payto;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "drain_kyc_alert", + params, + rs); +} diff --git a/src/exchangedb/drop_tables.c b/src/exchangedb/drop_tables.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/drop_tables.c + * @brief Implementation of the drop_tables function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/drop_tables.h" +#include "helper.h" + + +/** + * Drop all Taler tables. This should only be used by testcases. + * + * @param pg the database context + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + */ +enum GNUNET_GenericReturnValue +TALER_EXCHANGEDB_drop_tables (struct TALER_EXCHANGEDB_PostgresContext *pg) +{ + struct GNUNET_PQ_Context *conn; + enum GNUNET_GenericReturnValue ret; + + if (NULL != pg->conn) + { + GNUNET_PQ_disconnect (pg->conn); + pg->conn = NULL; + } + conn = GNUNET_PQ_connect_with_cfg (pg->cfg, + "exchangedb-postgres", + NULL, + NULL, + NULL); + if (NULL == conn) + return GNUNET_SYSERR; + ret = GNUNET_PQ_exec_sql (conn, + "drop"); + GNUNET_PQ_disconnect (conn); + return ret; +} diff --git a/src/exchangedb/enable_rules.c b/src/exchangedb/enable_rules.c @@ -0,0 +1,74 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/enable_rules.c + * @brief Implementation of the enable_rules function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/enable_rules.h" +#include "helper.h" + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGEDB_enable_rules ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *schema) +{ + struct GNUNET_PQ_Context *conn; + enum GNUNET_GenericReturnValue ret; + char *sp; + + GNUNET_asprintf (&sp, + "SET search_path TO %s,exchange;", + schema); + { + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_try_execute (sp), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + char *schemadash; + + GNUNET_asprintf (&schemadash, + "%s-", + schema); + conn = GNUNET_PQ_connect_with_cfg (pg->cfg, + "exchangedb-postgres", + schemadash, + es, + NULL); + GNUNET_free (schemadash); + } + GNUNET_free (sp); + if (NULL == conn) + return GNUNET_SYSERR; + { + char *procfile; + + GNUNET_asprintf (&procfile, + "%s-procedures", + schema); + ret = GNUNET_PQ_exec_sql (conn, + procfile); + /* $SCHEMA-procedures MAY not exist, so only check for hard error */ + GNUNET_break (GNUNET_SYSERR != ret); + if (GNUNET_NO == ret) + ret = GNUNET_OK; + GNUNET_free (procfile); + } + GNUNET_PQ_disconnect (conn); + return ret; +} diff --git a/src/exchangedb/ensure_coin_known.c b/src/exchangedb/ensure_coin_known.c @@ -0,0 +1,166 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/ensure_coin_known.c + * @brief Implementation of the ensure_coin_known function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_exchangedb_lib.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/ensure_coin_known.h" +#include "helper.h" + + +enum TALER_EXCHANGEDB_CoinKnownStatus +TALER_EXCHANGEDB_ensure_coin_known ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_CoinPublicInfo *coin, + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_hash, + struct TALER_AgeCommitmentHashP *h_age_commitment) +{ + enum GNUNET_DB_QueryStatus qs; + bool existed; + bool no_denom_pub_hash; + bool no_age_commitment_hash; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub), + GNUNET_PQ_query_param_auto_from_type (&coin->denom_pub_hash), + coin->no_age_commitment + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (&coin->h_age_commitment), + TALER_PQ_query_param_denom_sig (&coin->denom_sig), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("existed", + &existed), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + known_coin_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + denom_hash), + &no_denom_pub_hash), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + h_age_commitment), + &no_age_commitment_hash), + GNUNET_PQ_result_spec_end + }; + + /* + See also: + https://stackoverflow.com/questions/34708509/how-to-use-returning-with-on-conflict-in-postgresql/37543015#37543015 + */ + PREPARE (pg, + "insert_known_coin", + "WITH dd" + " (denominations_serial" + " ,coin" + " ) AS (" + " SELECT " + " denominations_serial" + " ,coin" + " FROM denominations" + " WHERE denom_pub_hash=$2" + " ), input_rows" + " (coin_pub) AS (" + " VALUES ($1::BYTEA)" + " ), ins AS (" + " INSERT INTO known_coins " + " (coin_pub" + " ,denominations_serial" + " ,age_commitment_hash" + " ,denom_sig" + " ,remaining" + " ) SELECT " + " $1" + " ,denominations_serial" + " ,$3" + " ,$4" + " ,coin" + " FROM dd" + " ON CONFLICT DO NOTHING" /* CONFLICT on (coin_pub) */ + " RETURNING " + " known_coin_id" + " ) " + "SELECT " + " FALSE AS existed" + " ,known_coin_id" + " ,NULL AS denom_pub_hash" + " ,NULL AS age_commitment_hash" + " FROM ins " + "UNION ALL " + "SELECT " + " TRUE AS existed" + " ,known_coin_id" + " ,denom_pub_hash" + " ,kc.age_commitment_hash" + " FROM input_rows" + " JOIN known_coins kc USING (coin_pub)" + " JOIN denominations USING (denominations_serial)" + " LIMIT 1"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "insert_known_coin", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return TALER_EXCHANGEDB_CKS_HARD_FAIL; + case GNUNET_DB_STATUS_SOFT_ERROR: + return TALER_EXCHANGEDB_CKS_SOFT_FAIL; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break (0); /* should be impossible */ + return TALER_EXCHANGEDB_CKS_HARD_FAIL; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + if (! existed) + return TALER_EXCHANGEDB_CKS_ADDED; + break; /* continued below */ + } + + if ( (! no_denom_pub_hash) && + (0 != GNUNET_memcmp (denom_hash, + &coin->denom_pub_hash)) ) + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; + } + + if (no_age_commitment_hash != coin->no_age_commitment) + { + if (no_age_commitment_hash) + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NULL; + } + else + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NON_NULL; + } + } + else if ( (! no_age_commitment_hash) && + (0 != GNUNET_memcmp (h_age_commitment, + &coin->h_age_commitment)) ) + { + GNUNET_break_op (0); + return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_VALUE_DIFFERS; + } + + return TALER_EXCHANGEDB_CKS_PRESENT; +} diff --git a/src/exchangedb/event_listen.c b/src/exchangedb/event_listen.c @@ -0,0 +1,49 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/event_listen.c + * @brief Implementation of the event_listen function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_dbevents.h" +#include "taler/exchange-database/event_listen.h" +#include "helper.h" + +/** + * Register callback to be invoked on events of type @a es. + * + * @param pg the database context + * @param timeout how long until to generate a timeout event + * @param es specification of the event to listen for + * @param cb function to call when the event happens, possibly + * multiple times (until cancel is invoked) + * @param cb_cls closure for @a cb + * @return handle useful to cancel the listener + */ +struct GNUNET_DB_EventHandler * +TALER_EXCHANGEDB_event_listen (struct TALER_EXCHANGEDB_PostgresContext *pg, + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_DB_EventHeaderP *es, + GNUNET_DB_EventCallback cb, + void *cb_cls) +{ + + return GNUNET_PQ_event_listen (pg->conn, + es, + timeout, + cb, + cb_cls); +} diff --git a/src/exchangedb/event_listen_cancel.c b/src/exchangedb/event_listen_cancel.c @@ -0,0 +1,34 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/event_listen_cancel.c + * @brief Implementation of the event_listen_cancel function for Postgres + * @author Christian Grothoff + */ +#include "taler/exchange-database/event_listen_cancel.h" +#include "helper.h" + + +void +TALER_TALER_EXCHANGEDB_event_listen_cancel (struct + TALER_EXCHANGEDB_PostgresContext *pg + , + struct GNUNET_DB_EventHandler *eh) + +{ + (void) pg; + GNUNET_PQ_event_listen_cancel (eh); +} diff --git a/src/exchangedb/event_notify.c b/src/exchangedb/event_notify.c @@ -0,0 +1,37 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/event_notify.c + * @brief Implementation of the event_notify function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_dbevents.h" +#include "taler/exchange-database/event_notify.h" +#include "helper.h" + + +void +TALER_EXCHANGEDB_event_notify (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct GNUNET_DB_EventHeaderP *es, + const void *extra, + size_t extra_size) +{ + + GNUNET_PQ_event_notify (pg->conn, + es, + extra, + extra_size); +} diff --git a/src/exchangedb/expire_purse.c b/src/exchangedb/expire_purse.c @@ -0,0 +1,65 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/expire_purse.c + * @brief Implementation of the expire_purse function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/expire_purse.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_expire_purse ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + struct GNUNET_TIME_Absolute start_time, + struct GNUNET_TIME_Absolute end_time) +{ + struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_absolute_time (&start_time), + GNUNET_PQ_query_param_absolute_time (&end_time), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + bool found = false; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("found", + &found), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + + PREPARE (pg, + "call_expire_purse", + "SELECT " + " out_found AS found" + " FROM exchange_do_expire_purse" + " ($1,$2,$3);"); + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_expire_purse", + params, + rs); + if (qs < 0) + return qs; + GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); + return found + ? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT + : GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; +} diff --git a/src/exchangedb/find_aggregation_transient.c b/src/exchangedb/find_aggregation_transient.c @@ -0,0 +1,69 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024, 2025 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/> + */ +/** + * @file exchangedb/find_aggregation_transient.c + * @brief Implementation of the find_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/find_aggregation_transient.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_find_aggregation_transient ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + struct TALER_FullPayto *payto_uri, + struct TALER_WireTransferIdentifierRawP *wtid, + struct TALER_MerchantPublicKeyP *merchant_pub, + struct TALER_Amount *total) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", + merchant_pub), + GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", + wtid), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri->full_payto), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + total), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "find_transient_aggregations", + "SELECT" + " atr.amount" + " ,atr.wtid_raw" + " ,atr.merchant_pub" + " ,wt.payto_uri" + " FROM wire_targets wt" + " JOIN aggregation_transient atr" + " USING (wire_target_h_payto)" + " WHERE wt.h_normalized_payto=$1" + " LIMIT 1;"); /* Note: there should really be only 1 match */ + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "find_transient_aggregations", + params, + rs); +} diff --git a/src/exchangedb/gc.c b/src/exchangedb/gc.c @@ -0,0 +1,75 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/gc.c + * @brief Implementation of the gc function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/gc.h" +#include "helper.h" + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGEDB_gc (struct TALER_EXCHANGEDB_PostgresContext *pg) +{ + struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); + struct GNUNET_TIME_Absolute long_ago; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_absolute_time (&long_ago), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_Context *conn; + enum GNUNET_GenericReturnValue ret; + + /* Keep wire fees for 10 years, that should always + be enough _and_ they are tiny so it does not + matter to make this tight */ + long_ago = GNUNET_TIME_absolute_subtract ( + now, + GNUNET_TIME_relative_multiply ( + GNUNET_TIME_UNIT_YEARS, + 10)); + { + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + struct GNUNET_PQ_PreparedStatement ps[] = { + GNUNET_PQ_make_prepare ("run_gc", + "CALL" + " exchange_do_gc" + " ($1,$2);"), + GNUNET_PQ_PREPARED_STATEMENT_END + }; + + conn = GNUNET_PQ_connect_with_cfg (pg->cfg, + "exchangedb-postgres", + NULL, + es, + ps); + } + if (NULL == conn) + return GNUNET_SYSERR; + ret = GNUNET_OK; + if (0 > GNUNET_PQ_eval_prepared_non_select (conn, + "run_gc", + params)) + ret = GNUNET_SYSERR; + GNUNET_PQ_disconnect (conn); + return ret; +} diff --git a/src/exchangedb/get_coin_denomination.c b/src/exchangedb/get_coin_denomination.c @@ -0,0 +1,65 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_coin_denomination.c + * @brief Implementation of the get_coin_denomination function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_coin_denomination.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_coin_denomination ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_hash) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + denom_hash), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + known_coin_id), + GNUNET_PQ_result_spec_end + }; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Getting coin denomination of coin %s\n", + TALER_B2S (coin_pub)); + + /* Used in #postgres_get_coin_denomination() to fetch + the denomination public key hash for + a coin known to the exchange. */ + PREPARE (pg, + "get_coin_denomination", + "SELECT" + " denominations.denom_pub_hash" + ",known_coin_id" + " FROM known_coins" + " JOIN denominations USING (denominations_serial)" + " WHERE coin_pub=$1" + " FOR SHARE;"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_coin_denomination", + params, + rs); +} diff --git a/src/exchangedb/get_coin_transactions.c b/src/exchangedb/get_coin_transactions.c @@ -0,0 +1,1184 @@ +/* + This file is part of TALER + Copyright (C) 2022-2023 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/> + */ +/** + * @file get_coin_transactions.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_exchangedb_lib.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_coin_transactions.h" +#include "helper.h" +#include "taler/exchange-database/start_read_committed.h" +#include "taler/exchange-database/commit.h" +#include "taler/exchange-database/rollback.h" + + +/** + * How often do we re-try when encountering DB serialization issues? + * (We are read-only, so can only happen due to concurrent insert, + * which should be very rare.) + */ +#define RETRIES 3 + +/** + * Closure for callbacks called from #TALER_EXCHANGEDB_get_coin_transactions() + */ +struct CoinHistoryContext +{ + /** + * Head of the coin's history list. + */ + struct TALER_EXCHANGEDB_TransactionList *head; + + /** + * Public key of the coin we are building the history for. + */ + const struct TALER_CoinSpendPublicKeyP *coin_pub; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Our current offset in the coin history. + */ + uint64_t chid; + + /** + * Set to 'true' if the transaction failed. + */ + bool failed; + +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct CoinHistoryContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +add_coin_deposit (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CoinHistoryContext *chc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; + + for (unsigned int i = 0; i < num_results; i++) + { + struct TALER_EXCHANGEDB_DepositListEntry *deposit; + struct TALER_EXCHANGEDB_TransactionList *tl; + uint64_t serial_id; + + deposit = GNUNET_new (struct TALER_EXCHANGEDB_DepositListEntry); + { + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &deposit->amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + &deposit->deposit_fee), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &deposit->h_denom_pub), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &deposit->h_age_commitment), + &deposit->no_age_commitment), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("wallet_data_hash", + &deposit->wallet_data_hash), + &deposit->no_wallet_data_hash), + GNUNET_PQ_result_spec_timestamp ("wallet_timestamp", + &deposit->timestamp), + GNUNET_PQ_result_spec_timestamp ("refund_deadline", + &deposit->refund_deadline), + GNUNET_PQ_result_spec_timestamp ("wire_deadline", + &deposit->wire_deadline), + GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", + &deposit->merchant_pub), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + &deposit->h_contract_terms), + GNUNET_PQ_result_spec_auto_from_type ("wire_salt", + &deposit->wire_salt), + GNUNET_PQ_result_spec_string ("payto_uri", + &deposit->receiver_wire_account.full_payto + ), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &deposit->csig), + GNUNET_PQ_result_spec_uint64 ("coin_deposit_serial_id", + &serial_id), + GNUNET_PQ_result_spec_auto_from_type ("done", + &deposit->done), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + GNUNET_free (deposit); + chc->failed = true; + return; + } + } + tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); + tl->next = chc->head; + tl->type = TALER_EXCHANGEDB_TT_DEPOSIT; + tl->details.deposit = deposit; + tl->serial_id = serial_id; + tl->coin_history_id = chc->chid; + chc->head = tl; + } +} + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct CoinHistoryContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +add_coin_purse_deposit (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CoinHistoryContext *chc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; + + for (unsigned int i = 0; i < num_results; i++) + { + struct TALER_EXCHANGEDB_PurseDepositListEntry *deposit; + struct TALER_EXCHANGEDB_TransactionList *tl; + uint64_t serial_id; + + deposit = GNUNET_new (struct TALER_EXCHANGEDB_PurseDepositListEntry); + { + bool not_finished; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &deposit->amount), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + &deposit->deposit_fee), + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + &deposit->purse_pub), + GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id", + &serial_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("partner_base_url", + &deposit->exchange_base_url), + NULL), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &deposit->coin_sig), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &deposit->h_age_commitment), + &deposit->no_age_commitment), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_bool ("refunded", + &deposit->refunded), + &not_finished), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &deposit->h_denom_pub), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + GNUNET_free (deposit); + chc->failed = true; + return; + } + if (not_finished) + deposit->refunded = false; + /* double-check for all-zeros age commitment */ + if (! deposit->no_age_commitment) + deposit->no_age_commitment + = GNUNET_is_zero (&deposit->h_age_commitment); + } + tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); + tl->next = chc->head; + tl->type = TALER_EXCHANGEDB_TT_PURSE_DEPOSIT; + tl->details.purse_deposit = deposit; + tl->serial_id = serial_id; + tl->coin_history_id = chc->chid; + chc->head = tl; + } +} + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct CoinHistoryContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +add_coin_melt (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CoinHistoryContext *chc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_MeltListEntry *melt; + struct TALER_EXCHANGEDB_TransactionList *tl; + uint64_t serial_id; + + melt = GNUNET_new (struct TALER_EXCHANGEDB_MeltListEntry); + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("rc", + &melt->rc), + /* oldcoin_index not needed */ + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &melt->h_denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", + &melt->coin_sig), + GNUNET_PQ_result_spec_auto_from_type ("refresh_seed", + &melt->refresh_seed), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("blinding_seed", + &melt->blinding_seed), + &melt->no_blinding_seed), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &melt->amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", + &melt->melt_fee), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &melt->h_age_commitment), + &melt->no_age_commitment), + GNUNET_PQ_result_spec_uint64 ("refresh_id", + &serial_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + GNUNET_free (melt); + chc->failed = true; + return; + } + } + tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); + tl->next = chc->head; + tl->type = TALER_EXCHANGEDB_TT_MELT; + tl->details.melt = melt; + tl->serial_id = serial_id; + tl->coin_history_id = chc->chid; + chc->head = tl; + } +} + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct CoinHistoryContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +add_coin_refund (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CoinHistoryContext *chc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_RefundListEntry *refund; + struct TALER_EXCHANGEDB_TransactionList *tl; + uint64_t serial_id; + + refund = GNUNET_new (struct TALER_EXCHANGEDB_RefundListEntry); + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", + &refund->merchant_pub), + GNUNET_PQ_result_spec_auto_from_type ("merchant_sig", + &refund->merchant_sig), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + &refund->h_contract_terms), + GNUNET_PQ_result_spec_uint64 ("rtransaction_id", + &refund->rtransaction_id), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &refund->refund_amount), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", + &refund->refund_fee), + GNUNET_PQ_result_spec_uint64 ("refund_serial_id", + &serial_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + GNUNET_free (refund); + chc->failed = true; + return; + } + } + tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); + tl->next = chc->head; + tl->type = TALER_EXCHANGEDB_TT_REFUND; + tl->details.refund = refund; + tl->serial_id = serial_id; + tl->coin_history_id = chc->chid; + chc->head = tl; + } +} + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct CoinHistoryContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +add_coin_purse_decision (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CoinHistoryContext *chc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_PurseRefundListEntry *prefund; + struct TALER_EXCHANGEDB_TransactionList *tl; + uint64_t serial_id; + + prefund = GNUNET_new (struct TALER_EXCHANGEDB_PurseRefundListEntry); + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + &prefund->purse_pub), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &prefund->refund_amount), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", + &prefund->refund_fee), + GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id", + &serial_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + GNUNET_free (prefund); + chc->failed = true; + return; + } + } + tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); + tl->next = chc->head; + tl->type = TALER_EXCHANGEDB_TT_PURSE_REFUND; + tl->details.purse_refund = prefund; + tl->serial_id = serial_id; + tl->coin_history_id = chc->chid; + chc->head = tl; + } +} + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct CoinHistoryContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +add_old_coin_recoup (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CoinHistoryContext *chc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup; + struct TALER_EXCHANGEDB_TransactionList *tl; + uint64_t serial_id; + + recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupRefreshListEntry); + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &recoup->coin.coin_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &recoup->coin_sig), + GNUNET_PQ_result_spec_auto_from_type ("coin_blind", + &recoup->coin_blind), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &recoup->value), + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + &recoup->timestamp), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &recoup->coin.denom_pub_hash), + TALER_PQ_result_spec_denom_sig ("denom_sig", + &recoup->coin.denom_sig), + GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid", + &serial_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + GNUNET_free (recoup); + chc->failed = true; + return; + } + recoup->old_coin_pub = *chc->coin_pub; + } + tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); + tl->next = chc->head; + tl->type = TALER_EXCHANGEDB_TT_RECOUP_REFRESH_RECEIVER; + tl->details.old_coin_recoup = recoup; + tl->serial_id = serial_id; + tl->coin_history_id = chc->chid; + chc->head = tl; + } +} + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct CoinHistoryContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +add_coin_recoup (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CoinHistoryContext *chc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_RecoupListEntry *recoup; + struct TALER_EXCHANGEDB_TransactionList *tl; + uint64_t serial_id; + + recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupListEntry); + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &recoup->reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &recoup->coin_sig), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &recoup->h_denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_blind", + &recoup->coin_blind), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &recoup->value), + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + &recoup->timestamp), + GNUNET_PQ_result_spec_uint64 ("recoup_uuid", + &serial_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + GNUNET_free (recoup); + chc->failed = true; + return; + } + } + tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); + tl->next = chc->head; + tl->type = TALER_EXCHANGEDB_TT_RECOUP_WITHDRAW; + tl->details.recoup = recoup; + tl->serial_id = serial_id; + tl->coin_history_id = chc->chid; + chc->head = tl; + } +} + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct CoinHistoryContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +add_coin_recoup_refresh (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CoinHistoryContext *chc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup; + struct TALER_EXCHANGEDB_TransactionList *tl; + uint64_t serial_id; + + recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupRefreshListEntry); + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", + &recoup->old_coin_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &recoup->coin_sig), + GNUNET_PQ_result_spec_auto_from_type ("coin_blind", + &recoup->coin_blind), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &recoup->value), + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + &recoup->timestamp), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &recoup->coin.denom_pub_hash), + TALER_PQ_result_spec_denom_sig ("denom_sig", + &recoup->coin.denom_sig), + GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid", + &serial_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + GNUNET_free (recoup); + chc->failed = true; + return; + } + recoup->coin.coin_pub = *chc->coin_pub; + } + tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); + tl->next = chc->head; + tl->type = TALER_EXCHANGEDB_TT_RECOUP_REFRESH; + tl->details.recoup_refresh = recoup; + tl->serial_id = serial_id; + tl->coin_history_id = chc->chid; + chc->head = tl; + } +} + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct CoinHistoryContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +add_coin_reserve_open (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CoinHistoryContext *chc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_ReserveOpenListEntry *role; + struct TALER_EXCHANGEDB_TransactionList *tl; + uint64_t serial_id; + + role = GNUNET_new (struct TALER_EXCHANGEDB_ReserveOpenListEntry); + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", + &role->reserve_sig), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &role->coin_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ("contribution", + &role->coin_contribution), + GNUNET_PQ_result_spec_uint64 ("reserve_open_deposit_uuid", + &serial_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + GNUNET_free (role); + chc->failed = true; + return; + } + } + tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); + tl->next = chc->head; + tl->type = TALER_EXCHANGEDB_TT_RESERVE_OPEN; + tl->details.reserve_open = role; + tl->serial_id = serial_id; + tl->coin_history_id = chc->chid; + chc->head = tl; + } +} + + +/** + * Work we need to do. + */ +struct Work +{ + /** + * Name of the table. + */ + const char *table; + + /** + * SQL prepared statement name. + */ + const char *statement; + + /** + * Function to call to handle the result(s). + */ + GNUNET_PQ_PostgresResultHandler cb; +}; + + +/** + * We found a coin history entry. Lookup details + * from the respective table and store in @a cls. + * + * @param[in,out] cls a `struct CoinHistoryContext` + * @param result a coin history entry result set + * @param num_results total number of results in @a results + */ +static void +handle_history_entry (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CoinHistoryContext *chc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; + static const struct Work work[] = { + [TALER_EXCHANGEDB_TT_DEPOSIT] = + { "coin_deposits", + "get_deposit_with_coin_pub", + &add_coin_deposit }, + [TALER_EXCHANGEDB_TT_MELT] = + { "refresh", + "get_refresh_by_coin", + &add_coin_melt }, + [TALER_EXCHANGEDB_TT_PURSE_DEPOSIT] = + { "purse_deposits", + "get_purse_deposit_by_coin_pub", + &add_coin_purse_deposit }, + [TALER_EXCHANGEDB_TT_PURSE_REFUND] = + { "purse_decision", + "get_purse_decision_by_coin_pub", + &add_coin_purse_decision }, + [TALER_EXCHANGEDB_TT_REFUND] = + { "refunds", + "get_refunds_by_coin", + &add_coin_refund }, + [TALER_EXCHANGEDB_TT_RECOUP_WITHDRAW] = + { "recoup", + "recoup_by_coin", + &add_coin_recoup }, + [TALER_EXCHANGEDB_TT_RECOUP_REFRESH] = + { "recoup_refresh::NEW", + "recoup_by_refreshed_coin", + &add_coin_recoup_refresh }, + [TALER_EXCHANGEDB_TT_RECOUP_REFRESH_RECEIVER] = + { "recoup_refresh::OLD", + "recoup_by_old_coin", + &add_old_coin_recoup }, + [TALER_EXCHANGEDB_TT_RESERVE_OPEN] = + { "reserves_open_deposits", + "reserve_open_by_coin", + &add_coin_reserve_open }, + { NULL, NULL, NULL } + }; + char *table_name; + uint64_t serial_id; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("table_name", + &table_name), + GNUNET_PQ_result_spec_uint64 ("serial_id", + &serial_id), + GNUNET_PQ_result_spec_uint64 ("coin_history_serial_id", + &chc->chid), + GNUNET_PQ_result_spec_end + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (chc->coin_pub), + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + + for (unsigned int i = 0; i<num_results; i++) + { + enum GNUNET_DB_QueryStatus qs; + bool found = false; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + chc->failed = true; + return; + } + + for (unsigned int s = 0; + NULL != work[s].statement; + s++) + { + if (0 != strcmp (table_name, + work[s].table)) + continue; + found = true; + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + work[s].statement, + params, + work[s].cb, + chc); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Coin %s had %d transactions at %llu in table %s\n", + TALER_B2S (chc->coin_pub), + (int) qs, + (unsigned long long) serial_id, + table_name); + if (0 > qs) + chc->failed = true; + break; + } + if (! found) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Coin history includes unsupported table `%s`\n", + table_name); + chc->failed = true; + } + GNUNET_PQ_cleanup_result (rs); + if (chc->failed) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_coin_transactions ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + bool begin_transaction, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t start_off, + uint64_t etag_in, + uint64_t *etag_out, + struct TALER_Amount *balance, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_EXCHANGEDB_TransactionList **tlp) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_QueryParam lparams[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_uint64 (&start_off), + GNUNET_PQ_query_param_end + }; + struct CoinHistoryContext chc = { + .head = NULL, + .coin_pub = coin_pub, + .pg = pg + }; + + *tlp = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Getting transactions for coin %s\n", + TALER_B2S (coin_pub)); + PREPARE (pg, + "get_coin_history_etag_balance", + "SELECT" + " ch.coin_history_serial_id" + ",kc.remaining" + ",denom.denom_pub_hash" + " FROM coin_history ch" + " JOIN known_coins kc" + " USING (coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " WHERE coin_pub=$1" + " ORDER BY coin_history_serial_id DESC" + " LIMIT 1;"); + PREPARE (pg, + "get_coin_history", + "SELECT" + " table_name" + ",serial_id" + ",coin_history_serial_id" + " FROM coin_history" + " WHERE coin_pub=$1" + " AND coin_history_serial_id > $2" + " ORDER BY coin_history_serial_id DESC;"); + PREPARE (pg, + "get_deposit_with_coin_pub", + "SELECT" + " cdep.amount_with_fee" + ",denoms.fee_deposit" + ",denoms.denom_pub_hash" + ",kc.age_commitment_hash" + ",bdep.wallet_timestamp" + ",bdep.refund_deadline" + ",bdep.wire_deadline" + ",bdep.merchant_pub" + ",bdep.h_contract_terms" + ",bdep.wallet_data_hash" + ",bdep.wire_salt" + ",wt.payto_uri" + ",cdep.coin_sig" + ",cdep.coin_deposit_serial_id" + ",bdep.done" + " FROM coin_deposits cdep" + " JOIN batch_deposits bdep" + " USING (batch_deposit_serial_id)" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " JOIN known_coins kc" + " ON (kc.coin_pub = cdep.coin_pub)" + " JOIN denominations denoms" + " USING (denominations_serial)" + " WHERE cdep.coin_pub=$1" + " AND cdep.coin_deposit_serial_id=$2;"); + PREPARE (pg, + "get_refresh_by_coin", + "SELECT" + " rc" + ",refresh_seed" + ",blinding_seed" + ",old_coin_sig" + ",amount_with_fee" + ",denoms.denom_pub_hash" + ",denoms.fee_refresh" + ",kc.age_commitment_hash" + ",refresh_id" + " FROM refresh" + " JOIN known_coins kc" + " ON (refresh.old_coin_pub = kc.coin_pub)" + " JOIN denominations denoms" + " USING (denominations_serial)" + " WHERE old_coin_pub=$1" + " AND refresh_id=$2;"); + PREPARE (pg, + "get_purse_deposit_by_coin_pub", + "SELECT" + " partner_base_url" + ",pd.amount_with_fee" + ",denoms.fee_deposit" + ",denoms.denom_pub_hash" + ",pd.purse_pub" + ",kc.age_commitment_hash" + ",pd.coin_sig" + ",pd.purse_deposit_serial_id" + ",pdes.refunded" + " FROM purse_deposits pd" + " LEFT JOIN partners" + " USING (partner_serial_id)" + " JOIN purse_requests pr" + " USING (purse_pub)" + " LEFT JOIN purse_decision pdes" + " USING (purse_pub)" + " JOIN known_coins kc" + " ON (pd.coin_pub = kc.coin_pub)" + " JOIN denominations denoms" + " USING (denominations_serial)" + " WHERE pd.purse_deposit_serial_id=$2" + " AND pd.coin_pub=$1;"); + PREPARE (pg, + "get_purse_decision_by_coin_pub", + "SELECT" + " pdes.purse_pub" + ",pd.amount_with_fee" + ",denom.fee_refund" + ",pdes.purse_decision_serial_id" + " FROM purse_decision pdes" + " JOIN purse_deposits pd" + " USING (purse_pub)" + " JOIN known_coins kc" + " ON (pd.coin_pub = kc.coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " WHERE pd.coin_pub=$1" + " AND pdes.purse_decision_serial_id=$2" + " AND pdes.refunded;"); + PREPARE (pg, + "get_refunds_by_coin", + "SELECT" + " bdep.merchant_pub" + ",ref.merchant_sig" + ",bdep.h_contract_terms" + ",ref.rtransaction_id" + ",ref.amount_with_fee" + ",denom.fee_refund" + ",ref.refund_serial_id" + " FROM refunds ref" + " JOIN coin_deposits cdep" + " ON (ref.coin_pub = cdep.coin_pub AND ref.batch_deposit_serial_id = cdep.batch_deposit_serial_id)" + " JOIN batch_deposits bdep" + " ON (ref.batch_deposit_serial_id = bdep.batch_deposit_serial_id)" + " JOIN known_coins kc" + " ON (ref.coin_pub = kc.coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " WHERE ref.coin_pub=$1" + " AND ref.refund_serial_id=$2;"); + PREPARE (pg, + "recoup_by_old_coin", + "SELECT" + " coins.coin_pub" + ",rr.coin_sig" + ",rr.coin_blind" + ",rr.amount" + ",rr.recoup_timestamp" + ",denoms.denom_pub_hash" + ",coins.denom_sig" + ",rr.recoup_refresh_uuid" + " FROM recoup_refresh rr" + " JOIN known_coins coins" + " USING (coin_pub)" + " JOIN denominations denoms" + " USING (denominations_serial)" + " WHERE recoup_refresh_uuid=$2" + " AND refresh_id IN" + " (SELECT refresh_id" + " FROM refresh" + " WHERE refresh.old_coin_pub=$1);"); + PREPARE (pg, + "recoup_by_coin", + "SELECT" + " res.reserve_pub" + ",denoms.denom_pub_hash" + ",rcp.coin_sig" + ",rcp.coin_blind" + ",rcp.amount" + ",rcp.recoup_timestamp" + ",rcp.recoup_uuid" + " FROM recoup rcp" + " JOIN withdraw ro" + " USING (withdraw_id)" + " JOIN reserves res" + " USING (reserve_pub)" + " JOIN known_coins coins" + " USING (coin_pub)" + " JOIN denominations denoms" + " ON (denoms.denominations_serial = coins.denominations_serial)" + " WHERE rcp.recoup_uuid=$2" + " AND coins.coin_pub=$1;"); + /* Used to obtain recoup transactions + for a refreshed coin */ + PREPARE (pg, + "recoup_by_refreshed_coin", + "SELECT" + " old_coins.coin_pub AS old_coin_pub" + ",rr.coin_sig" + ",rr.coin_blind" + ",rr.amount" + ",rr.recoup_timestamp" + ",denoms.denom_pub_hash" + ",coins.denom_sig" + ",recoup_refresh_uuid" + " FROM recoup_refresh rr" + " JOIN refresh rfc" + " ON (rr.refresh_id = rfc.refresh_id)" + " JOIN known_coins old_coins" + " ON (rfc.old_coin_pub = old_coins.coin_pub)" + " JOIN known_coins coins" + " ON (rr.coin_pub = coins.coin_pub)" + " JOIN denominations denoms" + " ON (denoms.denominations_serial = coins.denominations_serial)" + " WHERE rr.recoup_refresh_uuid=$2" + " AND coins.coin_pub=$1;"); + PREPARE (pg, + "reserve_open_by_coin", + "SELECT" + " reserve_open_deposit_uuid" + ",coin_sig" + ",reserve_sig" + ",contribution" + " FROM reserves_open_deposits" + " WHERE coin_pub=$1" + " AND reserve_open_deposit_uuid=$2;"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + " --- landed here 1\n"); + for (unsigned int i = 0; i<RETRIES; i++) + { + enum GNUNET_DB_QueryStatus qs; + uint64_t end; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("coin_history_serial_id", + &end), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + h_denom_pub), + TALER_PQ_RESULT_SPEC_AMOUNT ("remaining", + balance), + GNUNET_PQ_result_spec_end + }; + + if (begin_transaction) + { + if (GNUNET_OK != + TALER_TALER_EXCHANGEDB_start_read_committed (pg, + "get-coin-transactions")) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + } + /* First only check the last item, to see if + we even need to iterate */ + qs = GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "get_coin_history_etag_balance", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + if (begin_transaction) + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + if (begin_transaction) + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + if (begin_transaction) + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + *etag_out = end; + if (end == etag_in) + return qs; + } + /* We indeed need to iterate over the history */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Current ETag for coin %s is %llu\n", + TALER_B2S (coin_pub), + (unsigned long long) end); + + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "get_coin_history", + lparams, + &handle_history_entry, + &chc); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + if (begin_transaction) + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + if (begin_transaction) + TALER_EXCHANGEDB_rollback (pg); + continue; + default: + break; + } + if (chc.failed) + { + if (begin_transaction) + TALER_EXCHANGEDB_rollback (pg); + TALER_EXCHANGEDB_free_coin_transaction_list (chc.head); + return GNUNET_DB_STATUS_SOFT_ERROR; + } + if (! begin_transaction) + { + *tlp = chc.head; + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + qs = TALER_EXCHANGEDB_commit (pg); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + TALER_EXCHANGEDB_free_coin_transaction_list (chc.head); + chc.head = NULL; + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TALER_EXCHANGEDB_free_coin_transaction_list (chc.head); + chc.head = NULL; + continue; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + *tlp = chc.head; + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + " --- landed here 2\n"); + return GNUNET_DB_STATUS_SOFT_ERROR; +} diff --git a/src/exchangedb/get_denomination_by_serial.c b/src/exchangedb/get_denomination_by_serial.c @@ -0,0 +1,87 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/get_denomination_by_serial.c + * @brief Implementation of the get_denomination_by_serial function for Postgres + * @author Özgür Kesim + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_denomination_by_serial.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_denomination_by_serial ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t denom_serial, + struct TALER_EXCHANGEDB_DenominationKeyInformation *issue) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&denom_serial), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &issue->signature), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &issue->denom_hash), + GNUNET_PQ_result_spec_timestamp ("valid_from", + &issue->start), + GNUNET_PQ_result_spec_timestamp ("expire_withdraw", + &issue->expire_withdraw), + GNUNET_PQ_result_spec_timestamp ("expire_deposit", + &issue->expire_deposit), + GNUNET_PQ_result_spec_timestamp ("expire_legal", + &issue->expire_legal), + TALER_PQ_RESULT_SPEC_AMOUNT ("coin", + &issue->value), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", + &issue->fees.withdraw), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + &issue->fees.deposit), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", + &issue->fees.refresh), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", + &issue->fees.refund), + GNUNET_PQ_result_spec_uint32 ("age_mask", + &issue->age_mask.bits), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "denomination_get_by_serial", + "SELECT" + " master_sig" + ",denom_pub_hash" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin" /* value of this denom */ + ",fee_withdraw" + ",fee_deposit" + ",fee_refresh" + ",fee_refund" + ",age_mask" + " FROM denominations" + " WHERE denominations_serial=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "denomination_get_by_serial", + params, + rs); +} diff --git a/src/exchangedb/get_denomination_info.c b/src/exchangedb/get_denomination_info.c @@ -0,0 +1,96 @@ +/* + This file is part of TALER + Copyright (C) 2022,2025 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/> + */ +/** + * @file exchangedb/get_denomination_info.c + * @brief Implementation of the get_denomination_info function for Postgres + * @author Christian Grothoff + * @author Özgür Kesim + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_denomination_info.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_denomination_info ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_DenominationHashP *denom_pub_hash, + uint64_t *denom_serial, + struct TALER_EXCHANGEDB_DenominationKeyInformation *issue) +{ + enum GNUNET_DB_QueryStatus qs; + uint64_t serial; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("denominations_serial", + &serial), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &issue->signature), + GNUNET_PQ_result_spec_timestamp ("valid_from", + &issue->start), + GNUNET_PQ_result_spec_timestamp ("expire_withdraw", + &issue->expire_withdraw), + GNUNET_PQ_result_spec_timestamp ("expire_deposit", + &issue->expire_deposit), + GNUNET_PQ_result_spec_timestamp ("expire_legal", + &issue->expire_legal), + TALER_PQ_RESULT_SPEC_AMOUNT ("coin", + &issue->value), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", + &issue->fees.withdraw), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + &issue->fees.deposit), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", + &issue->fees.refresh), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", + &issue->fees.refund), + GNUNET_PQ_result_spec_uint32 ("age_mask", + &issue->age_mask.bits), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "denomination_get", + "SELECT" + " denominations_serial" + ",master_sig" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin" /* value of this denom */ + ",fee_withdraw" + ",fee_deposit" + ",fee_refresh" + ",fee_refund" + ",age_mask" + " FROM denominations" + " WHERE denom_pub_hash=$1;"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "denomination_get", + params, + rs); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) + return qs; + issue->denom_hash = *denom_pub_hash; + if (NULL != denom_serial) + *denom_serial = serial; + return qs; +} diff --git a/src/exchangedb/get_denomination_revocation.c b/src/exchangedb/get_denomination_revocation.c @@ -0,0 +1,59 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_denomination_revocation.c + * @brief Implementation of the get_denomination_revocation function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_denomination_revocation.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_denomination_revocation ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_MasterSignatureP *master_sig, + uint64_t *rowid) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), + GNUNET_PQ_result_spec_uint64 ("denom_revocations_serial_id", + rowid), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "denomination_revocation_get", + "SELECT" + " master_sig" + ",denom_revocations_serial_id" + " FROM denomination_revocations" + " WHERE denominations_serial=" + " (SELECT denominations_serial" + " FROM denominations" + " WHERE denom_pub_hash=$1);"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "denomination_revocation_get", + params, + rs); +} diff --git a/src/exchangedb/get_drain_profit.c b/src/exchangedb/get_drain_profit.c @@ -0,0 +1,72 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_drain_profit.c + * @brief Implementation of the get_drain_profit function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_drain_profit.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_drain_profit ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t *serial, + char **account_section, + struct TALER_FullPayto *payto_uri, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *amount, + struct TALER_MasterSignatureP *master_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("profit_drain_serial_id", + serial), + GNUNET_PQ_result_spec_string ("account_section", + account_section), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri->full_payto), + GNUNET_PQ_result_spec_timestamp ("trigger_date", + request_timestamp), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + amount), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_profit_drain", + "SELECT" + " profit_drain_serial_id" + ",account_section" + ",payto_uri" + ",trigger_date" + ",amount" + ",master_sig" + " FROM profit_drains" + " WHERE wtid=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_profit_drain", + params, + rs); +} diff --git a/src/exchangedb/get_expired_reserves.c b/src/exchangedb/get_expired_reserves.c @@ -0,0 +1,169 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file get_expired_reserves.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_expired_reserves.h" +#include "helper.h" + + +/** + * Closure for #reserve_expired_cb(). + */ +struct ExpiredReserveContext +{ + /** + * Function to call for each expired reserve. + */ + TALER_EXCHANGEDB_ReserveExpiredCallback rec; + + /** + * Closure to give to @e rec. + */ + void *rec_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on error. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +reserve_expired_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ExpiredReserveContext *erc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = erc->pg; + enum GNUNET_GenericReturnValue ret = GNUNET_OK; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_TIME_Timestamp exp_date; + struct TALER_FullPayto account_details; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_Amount remaining_balance; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("expiration_date", + &exp_date), + GNUNET_PQ_result_spec_string ("account_details", + &account_details.full_payto), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + TALER_PQ_result_spec_amount ("current_balance", + pg->currency, + &remaining_balance), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ret = GNUNET_SYSERR; + break; + } + ret = erc->rec (erc->rec_cls, + &reserve_pub, + &remaining_balance, + account_details, + exp_date, + 0); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } + erc->status = ret; +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_expired_reserves ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + struct GNUNET_TIME_Timestamp now, + TALER_EXCHANGEDB_ReserveExpiredCallback rec, + void *rec_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&now), + GNUNET_PQ_query_param_end + }; + struct ExpiredReserveContext ectx = { + .rec = rec, + .rec_cls = rec_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "get_expired_reserves", + "WITH ed AS MATERIALIZED ( " + " SELECT expiration_date" + " ,wire_source_h_payto" + " ,current_balance" + " ,r.reserve_pub" + " FROM reserves r" + " JOIN reserves_in" + " USING (reserve_pub)" + " WHERE expiration_date <= $1 " + " AND ((current_balance).val != 0 OR (current_balance).frac != 0) " + " ORDER BY expiration_date ASC " + " LIMIT 1 " + ") " + "SELECT" + " wt.payto_uri AS account_details" + " ,ed.expiration_date" + " ,ed.reserve_pub" + " ,ed.current_balance" + " FROM wire_targets wt" + " JOIN ed" + " ON (ed.wire_source_h_payto=wt.wire_target_h_payto);"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "get_expired_reserves", + params, + &reserve_expired_cb, + &ectx); + switch (ectx.status) + { + case GNUNET_SYSERR: + return GNUNET_DB_STATUS_HARD_ERROR; + case GNUNET_NO: + return GNUNET_DB_STATUS_SOFT_ERROR; + case GNUNET_OK: + break; + } + return qs; +} diff --git a/src/exchangedb/get_extension_manifest.c b/src/exchangedb/get_extension_manifest.c @@ -0,0 +1,64 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_extension_manifest.c + * @brief Implementation of the get_extension_manifest function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_extension_manifest.h" +#include "helper.h" + +/** + * Function called to get the manifest of an extension + * (age-restriction, policy_extension_...) + * + * @param pg the database context + * @param extension_name the name of the extension + * @param[out] manifest JSON object of the manifest as string + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_extension_manifest (struct + TALER_EXCHANGEDB_PostgresContext *pg, + const char *extension_name, + char **manifest) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (extension_name), + GNUNET_PQ_query_param_end + }; + bool is_null; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("manifest", + manifest), + &is_null), + GNUNET_PQ_result_spec_end + }; + + *manifest = NULL; + PREPARE (pg, + "get_extension_manifest", + "SELECT" + " manifest" + " FROM extensions" + " WHERE name=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_extension_manifest", + params, + rs); +} diff --git a/src/exchangedb/get_global_fee.c b/src/exchangedb/get_global_fee.c @@ -0,0 +1,85 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_global_fee.c + * @brief Implementation of the get_global_fee function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_dbevents.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_global_fee.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative *purse_timeout, + struct GNUNET_TIME_Relative *history_expiration + , + uint32_t *purse_account_limit, + struct TALER_MasterSignatureP *master_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&date), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("start_date", + start_date), + GNUNET_PQ_result_spec_timestamp ("end_date", + end_date), + TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee", + &fees->history), + TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee", + &fees->account), + TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", + &fees->purse), + GNUNET_PQ_result_spec_relative_time ("purse_timeout", + purse_timeout), + GNUNET_PQ_result_spec_relative_time ("history_expiration", + history_expiration), + GNUNET_PQ_result_spec_uint32 ("purse_account_limit", + purse_account_limit), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_global_fee", + "SELECT " + " start_date" + ",end_date" + ",history_fee" + ",account_fee" + ",purse_fee" + ",purse_timeout" + ",history_expiration" + ",purse_account_limit" + ",master_sig" + " FROM global_fee" + " WHERE start_date <= $1" + " AND end_date > $1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_global_fee", + params, + rs); +} diff --git a/src/exchangedb/get_global_fees.c b/src/exchangedb/get_global_fees.c @@ -0,0 +1,164 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_global_fees.c + * @brief Implementation of the get_global_fees function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_dbevents.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_global_fees.h" +#include "helper.h" + + +/** + * Closure for #global_fees_cb(). + */ +struct GlobalFeeContext +{ + /** + * Function to call for each global fee block. + */ + TALER_EXCHANGEDB_GlobalFeeCallback cb; + + /** + * Closure to give to @e rec. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on error. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +global_fees_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct GlobalFeeContext *gctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = gctx->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_GlobalFeeSet fees; + struct GNUNET_TIME_Relative purse_timeout; + struct GNUNET_TIME_Relative history_expiration; + uint32_t purse_account_limit; + struct GNUNET_TIME_Timestamp start_date; + struct GNUNET_TIME_Timestamp end_date; + struct TALER_MasterSignatureP master_sig; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("start_date", + &start_date), + GNUNET_PQ_result_spec_timestamp ("end_date", + &end_date), + TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee", + &fees.history), + TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee", + &fees.account), + TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", + &fees.purse), + GNUNET_PQ_result_spec_relative_time ("purse_timeout", + &purse_timeout), + GNUNET_PQ_result_spec_relative_time ("history_expiration", + &history_expiration), + GNUNET_PQ_result_spec_uint32 ("purse_account_limit", + &purse_account_limit), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &master_sig), + GNUNET_PQ_result_spec_end + }; + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + gctx->status = GNUNET_SYSERR; + break; + } + gctx->cb (gctx->cb_cls, + &fees, + purse_timeout, + history_expiration, + purse_account_limit, + start_date, + end_date, + &master_sig); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_get_global_fees (struct + TALER_EXCHANGEDB_PostgresContext *pg, + TALER_EXCHANGEDB_GlobalFeeCallback cb, + void *cb_cls) +{ + struct GNUNET_TIME_Timestamp date + = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_subtract ( + GNUNET_TIME_absolute_get (), + GNUNET_TIME_UNIT_YEARS)); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&date), + GNUNET_PQ_query_param_end + }; + struct GlobalFeeContext gctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + + PREPARE (pg, + "get_global_fees", + "SELECT " + " start_date" + ",end_date" + ",history_fee" + ",account_fee" + ",purse_fee" + ",purse_timeout" + ",history_expiration" + ",purse_account_limit" + ",master_sig" + " FROM global_fee" + " WHERE start_date >= $1"); + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "get_global_fees", + params, + &global_fees_cb, + &gctx); +} diff --git a/src/exchangedb/get_known_coin.c b/src/exchangedb/get_known_coin.c @@ -0,0 +1,64 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_known_coin.c + * @brief Implementation of the get_known_coin function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_known_coin.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_known_coin (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_CoinSpendPublicKeyP * + coin_pub, + struct TALER_CoinPublicInfo *coin_info) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &coin_info->denom_pub_hash), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &coin_info->h_age_commitment), + &coin_info->no_age_commitment), + TALER_PQ_result_spec_denom_sig ("denom_sig", + &coin_info->denom_sig), + GNUNET_PQ_result_spec_end + }; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Getting known coin data for coin %s\n", + TALER_B2S (coin_pub)); + coin_info->coin_pub = *coin_pub; + PREPARE (pg, + "get_known_coin", + "SELECT" + " denominations.denom_pub_hash" + ",age_commitment_hash" + ",denom_sig" + " FROM known_coins" + " JOIN denominations USING (denominations_serial)" + " WHERE coin_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_known_coin", + params, + rs); +} diff --git a/src/exchangedb/get_kyc_rules.c b/src/exchangedb/get_kyc_rules.c @@ -0,0 +1,124 @@ +/* + This file is part of TALER + Copyright (C) 2022-2025 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/> + */ +/** + * @file exchangedb/get_kyc_rules.c + * @brief Implementation of the get_kyc_rules function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_kyc_rules.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_kyc_rules ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + const struct TALER_MerchantPublicKeyP *merchant_pub, + bool *no_account_pub, + union TALER_AccountPublicKeyP *account_pub, + bool *no_reserve_pub, + struct TALER_ReservePublicKeyP *reserve_pub, + json_t **jrules) +{ + struct GNUNET_TIME_Timestamp now + = GNUNET_TIME_timestamp_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_timestamp (&now), + NULL != merchant_pub + ? GNUNET_PQ_query_param_auto_from_type (merchant_pub) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("target_pub", + account_pub), + no_account_pub), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + reserve_pub), + no_reserve_pub), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("jnew_rules", + jrules), + NULL), + GNUNET_PQ_result_spec_end + }; + + *jrules = NULL; + *no_account_pub = true; + *no_reserve_pub = true; + memset (account_pub, + 0, + sizeof (*account_pub)); + memset (reserve_pub, + 0, + sizeof (*reserve_pub)); + PREPARE (pg, + "get_kyc_rules", + "SELECT" + " out_target_pub AS target_pub" + " ,out_jnew_rules::TEXT AS jnew_rules" + " ,out_reserve_pub AS reserve_pub" + " FROM exchange_do_get_kyc_rules ($1,$2,$3);"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "get_kyc_rules", + params, + rs); +} + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_get_kyc_rules2 ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + json_t **jrules) +{ + struct GNUNET_TIME_Timestamp now + = GNUNET_TIME_timestamp_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_timestamp (&now), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("jnew_rules", + jrules), + NULL), + GNUNET_PQ_result_spec_end + }; + + *jrules = NULL; + PREPARE (pg, + "get_kyc_rules2", + "SELECT" + " jnew_rules::TEXT" + " FROM legitimization_outcomes" + " WHERE h_payto=$1" + " AND expiration_time >= $2" + " AND is_active" + " ORDER BY expiration_time DESC" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "get_kyc_rules2", + params, + rs); +} diff --git a/src/exchangedb/get_old_coin_by_h_blind.c b/src/exchangedb/get_old_coin_by_h_blind.c @@ -0,0 +1,60 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2025 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/> + */ +/** + * @file exchangedb/get_old_coin_by_h_blind.c + * @brief Implementation of the get_old_coin_by_h_blind function for Postgres + * @author Christian Grothoff + * @author Özgür Kesim + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_old_coin_by_h_blind.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_old_coin_by_h_blind ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_BlindedCoinHashP *h_blind_ev, + struct TALER_CoinSpendPublicKeyP *old_coin_pub, + uint64_t *refresh_id) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_blind_ev), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", + old_coin_pub), + GNUNET_PQ_result_spec_uint64 ("refresh_id", + refresh_id), + GNUNET_PQ_result_spec_end + }; + + /* Used in #postgres_get_old_coin_by_h_blind() */ + PREPARE (pg, + "old_coin_by_h_blind", + "SELECT" + " okc.coin_pub AS old_coin_pub" + ",refresh_id" + " FROM refresh " + " JOIN known_coins okc ON (refresh.old_coin_pub = okc.coin_pub)" + " WHERE $1=ANY(h_blind_evs)" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "old_coin_by_h_blind", + params, + rs); +} diff --git a/src/exchangedb/get_pending_kyc_requirement_process.c b/src/exchangedb/get_pending_kyc_requirement_process.c @@ -0,0 +1,62 @@ +/* + This file is part of TALER + Copyright (C) 2023 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/> + */ +/** + * @file exchangedb/get_pending_kyc_requirement_process.c + * @brief Implementation of the get_pending_kyc_requirement_process function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_pending_kyc_requirement_process.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_pending_kyc_requirement_process ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + const char *provider_name, + char **redirect_url) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (provider_name), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("redirect_url", + redirect_url), + NULL), + GNUNET_PQ_result_spec_end + }; + + *redirect_url = NULL; + PREPARE (pg, + "get_pending_kyc_requirement_process", + "SELECT" + " redirect_url" + " FROM legitimization_processes" + " WHERE provider_name=$1" + " AND h_payto=$2" + " AND NOT finished" + " ORDER BY start_time DESC" + " LIMIT 1"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "get_pending_kyc_requirement_process", + params, + rs); +} diff --git a/src/exchangedb/get_policy_details.c b/src/exchangedb/get_policy_details.c @@ -0,0 +1,60 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_policy_details.c + * @brief Implementation of the get_policy_details function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_policy_details.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_policy_details ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct GNUNET_HashCode *hc, + struct TALER_PolicyDetails *details) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (hc), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("deadline", + &details->deadline), + TALER_PQ_RESULT_SPEC_AMOUNT ("commitment", + &details->commitment), + TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total", + &details->accumulated_total), + TALER_PQ_RESULT_SPEC_AMOUNT ("policy_fee", + &details->policy_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("transferable_amount", + &details->transferable_amount), + GNUNET_PQ_result_spec_auto_from_type ("state", + &details->fulfillment_state), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ("policy_fulfillment_id", + &details->policy_fulfillment_id), + &details->no_policy_fulfillment_id), + GNUNET_PQ_result_spec_end + }; + + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_policy_details", + params, + rs); +} diff --git a/src/exchangedb/get_purse_deposit.c b/src/exchangedb/get_purse_deposit.c @@ -0,0 +1,80 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_purse_deposit.c + * @brief Implementation of the get_purse_deposit function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_purse_deposit.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_purse_deposit ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_Amount *amount, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_AgeCommitmentHashP *phac, + struct TALER_CoinSpendSignatureP *coin_sig, + char **partner_url) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_end + }; + bool is_null; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + h_denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + phac), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + coin_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + amount), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("partner_base_url", + partner_url), + &is_null), + GNUNET_PQ_result_spec_end + }; + + *partner_url = NULL; + PREPARE (pg, + "select_purse_deposit_by_coin_pub", + "SELECT " + " coin_sig" + ",amount_with_fee" + ",denom_pub_hash" + ",age_commitment_hash" + ",partner_base_url" + " FROM purse_deposits" + " LEFT JOIN partners" + " USING (partner_serial_id)" + " JOIN known_coins kc" + " USING (coin_pub)" + " JOIN denominations" + " USING (denominations_serial)" + " WHERE purse_pub=$1" + " AND coin_pub=$2;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_purse_deposit_by_coin_pub", + params, + rs); +} diff --git a/src/exchangedb/get_purse_request.c b/src/exchangedb/get_purse_request.c @@ -0,0 +1,75 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/template.c + * @brief Implementation of the template function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_purse_request.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_purse_request ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_PurseMergePublicKeyP *merge_pub, + struct GNUNET_TIME_Timestamp *purse_expiration, + struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t *age_limit, + struct TALER_Amount *target_amount, + struct TALER_Amount *balance, + struct TALER_PurseContractSignatureP *purse_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("merge_pub", + merge_pub), + GNUNET_PQ_result_spec_timestamp ("purse_expiration", + purse_expiration), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + h_contract_terms), + GNUNET_PQ_result_spec_uint32 ("age_limit", + age_limit), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + target_amount), + TALER_PQ_RESULT_SPEC_AMOUNT ("balance", + balance), + GNUNET_PQ_result_spec_auto_from_type ("purse_sig", + purse_sig), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_purse_request", + "SELECT " + " merge_pub" + ",purse_expiration" + ",h_contract_terms" + ",age_limit" + ",amount_with_fee" + ",balance" + ",purse_sig" + " FROM purse_requests" + " WHERE purse_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_purse_request", + params, + rs); +} diff --git a/src/exchangedb/get_ready_deposit.c b/src/exchangedb/get_ready_deposit.c @@ -0,0 +1,78 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2023 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/> + */ +/** + * @file exchangedb/get_ready_deposit.c + * @brief Implementation of the get_ready_deposit function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_ready_deposit.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_ready_deposit (struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t start_shard_row, + uint64_t end_shard_row, + struct TALER_MerchantPublicKeyP * + merchant_pub, + struct TALER_FullPayto *payto_uri, + char **extra_wire_subject_metadata) +{ + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_uint64 (&start_shard_row), + GNUNET_PQ_query_param_uint64 (&end_shard_row), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", + merchant_pub), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri->full_payto), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("extra_wire_subject_metadata", + extra_wire_subject_metadata), + NULL), + GNUNET_PQ_result_spec_end + }; + const char *query = "deposits_get_ready"; + + *extra_wire_subject_metadata = NULL; + PREPARE (pg, + query, + "SELECT" + " wts.payto_uri" + ",bdep.merchant_pub" + ",bdep.extra_wire_subject_metadata" + " FROM batch_deposits bdep" + " JOIN wire_targets wts" + " USING (wire_target_h_payto)" + " WHERE NOT (bdep.done OR bdep.policy_blocked)" + " AND bdep.wire_deadline<=$1" + " AND bdep.shard >= $2" + " AND bdep.shard <= $3" + " ORDER BY " + " bdep.wire_deadline ASC" + " ,bdep.shard ASC" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + query, + params, + rs); +} diff --git a/src/exchangedb/get_refresh.c b/src/exchangedb/get_refresh.c @@ -0,0 +1,205 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_refresh.c + * @brief Implementation of the get_refresh function for Postgres + * @author get_refresh + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_refresh.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_RefreshCommitmentP *rc, + struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh + ) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (rc), + GNUNET_PQ_query_param_end + }; + bool no_cs_r_values; + bool no_cs_r_choices; + bool no_transfer_pubs; + size_t num_denom_sigs; + size_t num_transfer_pubs; + struct TALER_BlindedDenominationSignature *denom_sigs = NULL; + struct GNUNET_CRYPTO_CSPublicRPairP *cs_r_values = NULL; + struct TALER_TransferPublicKeyP *transfer_pubs = NULL; + uint64_t *denom_serials = NULL; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &refresh->amount_with_fee), + GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", + &refresh->coin.coin_pub), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &refresh->coin.h_age_commitment), + &refresh->coin.no_age_commitment), + GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", + &refresh->coin_sig), + GNUNET_PQ_result_spec_auto_from_type ("refresh_seed", + &refresh->refresh_seed), + GNUNET_PQ_result_spec_uint32 ("noreveal_index", + &refresh->noreveal_index), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("blinding_seed", + &refresh->blinding_seed), + &refresh->no_blinding_seed), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_array_cs_r_pub (pg->conn, + "cs_r_values", + &refresh->num_cs_r_values, + &cs_r_values), + &no_cs_r_values), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ("cs_r_choices", + &refresh->cs_r_choices), + &no_cs_r_choices), + GNUNET_PQ_result_spec_auto_from_type ("planchets_h", + &refresh->planchets_h), + GNUNET_PQ_result_spec_auto_from_type ("selected_h", + &refresh->selected_h), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_array_fixed_size (pg->conn, + "transfer_pubs", + sizeof(*transfer_pubs), + &num_transfer_pubs, + (void **) &transfer_pubs), + &no_transfer_pubs), + GNUNET_PQ_result_spec_array_uint64 (pg->conn, + "denom_serials", + &refresh->num_coins, + &denom_serials), + TALER_PQ_result_spec_array_blinded_denom_sig (pg->conn, + "denom_sigs", + &num_denom_sigs, + &denom_sigs), + GNUNET_PQ_result_spec_bool ("revealed", + &refresh->revealed), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + memset (&refresh->coin.denom_sig, + 0, + sizeof (refresh->coin.denom_sig)); + PREPARE (pg, + "get_refresh", + "SELECT" + " amount_with_fee" + ",old_coin_pub" + ",kc.age_commitment_hash AS age_commitment_hash" + ",old_coin_sig" + ",refresh_seed" + ",noreveal_index" + ",blinding_seed" + ",cs_r_values" + ",cs_r_choices" + ",planchets_h" + ",transfer_pubs" + ",selected_h" + ",denom_serials" + ",denom_sigs" + ",revealed" + " FROM refresh" + " JOIN known_coins kc" + " ON (old_coin_pub = kc.coin_pub)" + " WHERE rc = $1;" + ); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_refresh", + params, + rs); + GNUNET_PQ_cleanup_query_params_closures (params); + if (0 > qs) + { + GNUNET_break (0); + GNUNET_PQ_cleanup_result (rs); + return qs; + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + GNUNET_PQ_cleanup_result (rs); + return qs; + } + if (refresh->num_coins != num_denom_sigs) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "got inconsistent number of entries in refresh from DB: " + "num_coins=%ld, num_denom_sigs=%ld\n", + refresh->num_coins, + num_denom_sigs); + GNUNET_PQ_cleanup_result (rs); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (no_transfer_pubs) + { + refresh->is_v27_refresh = true; + refresh->transfer_pubs = NULL; + } + else + { + if (num_transfer_pubs != refresh->num_coins) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "got inconsistent number of transfer_pubs in refresh from DB: " + "num_coins=%ld, num_transfer_pubs=%ld\n", + refresh->num_coins, + num_transfer_pubs); + GNUNET_PQ_cleanup_result (rs); + return GNUNET_DB_STATUS_HARD_ERROR; + } + refresh->is_v27_refresh = false; + refresh->transfer_pubs = transfer_pubs; + } + if (refresh->no_blinding_seed != no_cs_r_values) + { + GNUNET_break (0); + GNUNET_PQ_cleanup_result (rs); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (no_cs_r_choices != no_cs_r_values) + { + GNUNET_break (0); + GNUNET_PQ_cleanup_result (rs); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (no_cs_r_values) + { + refresh->cs_r_values = NULL; + refresh->num_cs_r_values = 0; + } + if (refresh->coin.no_age_commitment) + memset (&refresh->coin.h_age_commitment, + 0, + sizeof(refresh->coin.h_age_commitment)); + refresh->rc = *rc; + /* move the result arrays */ + refresh->denom_sigs = denom_sigs; + refresh->denom_serials = denom_serials; + refresh->cs_r_values = cs_r_values; + transfer_pubs = NULL; + denom_sigs = NULL; + denom_serials = NULL; + cs_r_values = NULL; + GNUNET_PQ_cleanup_result (rs); + return qs; +} diff --git a/src/exchangedb/get_reserve_balance.c b/src/exchangedb/get_reserve_balance.c @@ -0,0 +1,65 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_reserve_balance.c + * @brief Implementation of the get_reserve_balance function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_reserve_balance.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_reserve_balance ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_Amount *balance, + struct TALER_FullPayto *origin_account) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_amount ("current_balance", + pg->currency, + balance), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("payto_uri", + &origin_account->full_payto), + NULL), + GNUNET_PQ_result_spec_end + }; + + origin_account->full_payto = NULL; + PREPARE (pg, + "get_reserve_balance", + "SELECT" + " r.current_balance" + " ,wt.payto_uri" + " FROM reserves r" + " LEFT JOIN reserves_in ri" + " USING (reserve_pub)" + " LEFT JOIN wire_targets wt" + " ON (wt.wire_target_h_payto = ri.wire_source_h_payto)" + " WHERE r.reserve_pub=$1" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_reserve_balance", + params, + rs); +} diff --git a/src/exchangedb/get_reserve_by_h_planchets.c b/src/exchangedb/get_reserve_by_h_planchets.c @@ -0,0 +1,58 @@ +/* + This file is part of TALER + Copyright (C) 2022,2025 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/> + */ +/** + * @file exchangedb/get_reserve_by_h_planchets.c + * @brief Implementation of the get_reserve_by_h_planchets function for Postgres + * @author Christian Grothoff + * @author Özgür Kesim + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_reserve_by_h_planchets.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_reserve_by_h_planchets ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_HashBlindedPlanchetsP *h_planchets, + struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *withdraw_serial_id) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_planchets), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + reserve_pub), + GNUNET_PQ_result_spec_uint64 ("withdraw_id", + withdraw_serial_id), + GNUNET_PQ_result_spec_end + }; + /* Used in #postgres_get_reserve_by_h_planchets() */ + PREPARE (pg, + "reserve_by_h_planchets", + "SELECT" + " reserve_pub" + ",withdraw_id" + " FROM withdraw" + " WHERE planchets_h=$1" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "reserve_by_h_planchets", + params, + rs); +} diff --git a/src/exchangedb/get_reserve_history.c b/src/exchangedb/get_reserve_history.c @@ -0,0 +1,994 @@ +/* + This file is part of TALER + Copyright (C) 2022-2023 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/> + */ +/** + * @file get_reserve_history.c + * @brief Obtain (parts of) the history of a reserve. + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_reserve_history.h" +#include "taler/exchange-database/start_read_committed.h" +#include "taler/exchange-database/commit.h" +#include "taler/exchange-database/rollback.h" +#include "helper.h" + +/** + * How often do we re-try when encountering DB serialization issues? + * (We are read-only, so can only happen due to concurrent insert, + * which should be very rare.) + */ +#define RETRIES 3 + + +/** + * Closure for callbacks invoked via #TALER_EXCHANGEDB_get_reserve_history(). + */ +struct ReserveHistoryContext +{ + + /** + * Which reserve are we building the history for? + */ + const struct TALER_ReservePublicKeyP *reserve_pub; + + /** + * Where we build the history. + */ + struct TALER_EXCHANGEDB_ReserveHistory *rh; + + /** + * Tail of @e rh list. + */ + struct TALER_EXCHANGEDB_ReserveHistory *rh_tail; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Sum of all credit transactions. + */ + struct TALER_Amount balance_in; + + /** + * Sum of all debit transactions. + */ + struct TALER_Amount balance_out; + + /** + * Current reserve_history_serial_id being processed, + * set before each sub-table callback. + */ + uint64_t current_history_offset; + + /** + * Set to true on serious internal errors during + * the callbacks. + */ + bool failed; +}; + + +/** + * Append and return a fresh element to the reserve + * history kept in @a rhc. + * + * @param rhc where the history is kept + * @return the fresh element that was added + */ +static struct TALER_EXCHANGEDB_ReserveHistory * +append_rh (struct ReserveHistoryContext *rhc) +{ + struct TALER_EXCHANGEDB_ReserveHistory *tail; + + tail = GNUNET_new (struct TALER_EXCHANGEDB_ReserveHistory); + tail->history_offset = rhc->current_history_offset; + if (NULL != rhc->rh_tail) + { + rhc->rh_tail->next = tail; + rhc->rh_tail = tail; + } + else + { + rhc->rh_tail = tail; + rhc->rh = tail; + } + return tail; +} + + +/** + * Add bank transfers to result set for #TALER_EXCHANGEDB_get_reserve_history. + * + * @param cls a `struct ReserveHistoryContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +add_bank_to_exchange (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReserveHistoryContext *rhc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; + + while (0 < num_results) + { + struct TALER_EXCHANGEDB_BankTransfer *bt; + struct TALER_EXCHANGEDB_ReserveHistory *tail; + + bt = GNUNET_new (struct TALER_EXCHANGEDB_BankTransfer); + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("wire_reference", + &bt->wire_reference), + TALER_PQ_RESULT_SPEC_AMOUNT ("credit", + &bt->amount), + GNUNET_PQ_result_spec_timestamp ("execution_date", + &bt->execution_date), + GNUNET_PQ_result_spec_string ("sender_account_details", + &bt->sender_account_details.full_payto), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + --num_results)) + { + GNUNET_break (0); + GNUNET_free (bt); + rhc->failed = true; + return; + } + } + GNUNET_assert (0 <= + TALER_amount_add (&rhc->balance_in, + &rhc->balance_in, + &bt->amount)); + bt->reserve_pub = *rhc->reserve_pub; + tail = append_rh (rhc); + tail->type = TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE; + tail->details.bank = bt; + } /* end of 'while (0 < rows)' */ +} + + +/** + * Add coin withdrawals to result set for #TALER_EXCHANGEDB_get_reserve_history. + * + * @param cls a `struct ReserveHistoryContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +add_withdraw (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReserveHistoryContext *rhc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; + + while (0 < num_results) + { + struct TALER_EXCHANGEDB_Withdraw *wd; + struct TALER_EXCHANGEDB_ReserveHistory *tail; + + wd = GNUNET_new (struct TALER_EXCHANGEDB_Withdraw); + { + bool no_noreveal_index; + bool no_max_age; + bool no_selected_h; + size_t num_denom_hs; + size_t num_denom_serials; + uint64_t *my_denom_serials = NULL; + struct TALER_DenominationHashP *my_denom_pub_hashes = NULL; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("planchets_h", + &wd->planchets_h), + GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", + &wd->reserve_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &wd->amount_with_fee), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint16 ("max_age", + &wd->max_age), + &no_max_age), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint16 ("noreveal_index", + &wd->noreveal_index), + &no_noreveal_index), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("blinding_seed", + &wd->blinding_seed), + &wd->no_blinding_seed), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("selected_h", + &wd->selected_h), + &no_selected_h), + TALER_PQ_result_spec_array_denom_hash (pg->conn, + "denom_pub_hashes", + &num_denom_hs, + &my_denom_pub_hashes), + GNUNET_PQ_result_spec_array_uint64 (pg->conn, + "denom_serials", + &num_denom_serials, + &my_denom_serials), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + --num_results)) + { + GNUNET_break (0); + GNUNET_free (wd); + rhc->failed = true; + GNUNET_PQ_cleanup_result (rs); + return; + } + + if (num_denom_hs != num_denom_serials) + { + GNUNET_break (0); + GNUNET_free (wd); + rhc->failed = true; + GNUNET_PQ_cleanup_result (rs); + return; + } + + if ((no_noreveal_index != no_max_age) || + (no_noreveal_index != no_selected_h)) + { + GNUNET_break (0); + GNUNET_free (wd); + rhc->failed = true; + GNUNET_PQ_cleanup_result (rs); + return; + } + wd->age_proof_required = ! no_max_age; + wd->num_coins = num_denom_serials; + wd->reserve_pub = *rhc->reserve_pub; + wd->denom_serials = my_denom_serials; + wd->denom_pub_hashes = my_denom_pub_hashes; + /* prevent cleanup from destroying our actual result */ + my_denom_serials = NULL; + my_denom_pub_hashes = NULL; + GNUNET_PQ_cleanup_result (rs); + } + + tail = append_rh (rhc); + tail->type = TALER_EXCHANGEDB_RO_WITHDRAW_COINS; + tail->details.withdraw = wd; + } +} + + +/** + * Add recoups to result set for #TALER_EXCHANGEDB_get_reserve_history. + * + * @param cls a `struct ReserveHistoryContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +add_recoup (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReserveHistoryContext *rhc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; + + while (0 < num_results) + { + struct TALER_EXCHANGEDB_Recoup *recoup; + struct TALER_EXCHANGEDB_ReserveHistory *tail; + + recoup = GNUNET_new (struct TALER_EXCHANGEDB_Recoup); + { + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &recoup->value), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &recoup->coin.coin_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_blind", + &recoup->coin_blind), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &recoup->coin_sig), + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + &recoup->timestamp), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &recoup->coin.denom_pub_hash), + TALER_PQ_result_spec_denom_sig ( + "denom_sig", + &recoup->coin.denom_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + --num_results)) + { + GNUNET_break (0); + GNUNET_free (recoup); + rhc->failed = true; + return; + } + } + GNUNET_assert (0 <= + TALER_amount_add (&rhc->balance_in, + &rhc->balance_in, + &recoup->value)); + recoup->reserve_pub = *rhc->reserve_pub; + tail = append_rh (rhc); + tail->type = TALER_EXCHANGEDB_RO_RECOUP_COIN; + tail->details.recoup = recoup; + } /* end of 'while (0 < rows)' */ +} + + +/** + * Add exchange-to-bank transfers to result set for + * #TALER_EXCHANGEDB_get_reserve_history. + * + * @param cls a `struct ReserveHistoryContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +add_exchange_to_bank (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReserveHistoryContext *rhc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; + + while (0 < num_results) + { + struct TALER_EXCHANGEDB_ClosingTransfer *closing; + struct TALER_EXCHANGEDB_ReserveHistory *tail; + + closing = GNUNET_new (struct TALER_EXCHANGEDB_ClosingTransfer); + { + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &closing->amount), + TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", + &closing->closing_fee), + GNUNET_PQ_result_spec_timestamp ("execution_date", + &closing->execution_date), + GNUNET_PQ_result_spec_string ("receiver_account", + &closing->receiver_account_details. + full_payto), + GNUNET_PQ_result_spec_auto_from_type ("wtid", + &closing->wtid), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + --num_results)) + { + GNUNET_break (0); + GNUNET_free (closing); + rhc->failed = true; + return; + } + } + GNUNET_assert (0 <= + TALER_amount_add (&rhc->balance_out, + &rhc->balance_out, + &closing->amount)); + closing->reserve_pub = *rhc->reserve_pub; + tail = append_rh (rhc); + tail->type = TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK; + tail->details.closing = closing; + } /* end of 'while (0 < rows)' */ +} + + +/** + * Add purse merge transfers to result set for + * #TALER_EXCHANGEDB_get_reserve_history. + * + * @param cls a `struct ReserveHistoryContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +add_p2p_merge (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReserveHistoryContext *rhc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; + + while (0 < num_results) + { + struct TALER_EXCHANGEDB_PurseMerge *merge; + struct TALER_EXCHANGEDB_ReserveHistory *tail; + + merge = GNUNET_new (struct TALER_EXCHANGEDB_PurseMerge); + { + uint32_t flags32; + struct TALER_Amount balance; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", + &merge->purse_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("balance", + &balance), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &merge->amount_with_fee), + GNUNET_PQ_result_spec_timestamp ("merge_timestamp", + &merge->merge_timestamp), + GNUNET_PQ_result_spec_timestamp ("purse_expiration", + &merge->purse_expiration), + GNUNET_PQ_result_spec_uint32 ("age_limit", + &merge->min_age), + GNUNET_PQ_result_spec_uint32 ("flags", + &flags32), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + &merge->h_contract_terms), + GNUNET_PQ_result_spec_auto_from_type ("merge_pub", + &merge->merge_pub), + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + &merge->purse_pub), + GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", + &merge->reserve_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + --num_results)) + { + GNUNET_break (0); + GNUNET_free (merge); + rhc->failed = true; + return; + } + merge->flags = (enum TALER_WalletAccountMergeFlags) flags32; + if ( (! GNUNET_TIME_absolute_is_future ( + merge->merge_timestamp.abs_time)) && + (-1 != TALER_amount_cmp (&balance, + &merge->amount_with_fee)) ) + merge->merged = true; + } + if (merge->merged) + GNUNET_assert (0 <= + TALER_amount_add (&rhc->balance_in, + &rhc->balance_in, + &merge->amount_with_fee)); + GNUNET_assert (0 <= + TALER_amount_add (&rhc->balance_out, + &rhc->balance_out, + &merge->purse_fee)); + merge->reserve_pub = *rhc->reserve_pub; + tail = append_rh (rhc); + tail->type = TALER_EXCHANGEDB_RO_PURSE_MERGE; + tail->details.merge = merge; + } +} + + +/** + * Add paid for history requests to result set for + * #TALER_EXCHANGEDB_get_reserve_history. + * + * @param cls a `struct ReserveHistoryContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +add_open_requests (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReserveHistoryContext *rhc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; + + while (0 < num_results) + { + struct TALER_EXCHANGEDB_OpenRequest *orq; + struct TALER_EXCHANGEDB_ReserveHistory *tail; + + orq = GNUNET_new (struct TALER_EXCHANGEDB_OpenRequest); + { + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("open_fee", + &orq->open_fee), + GNUNET_PQ_result_spec_timestamp ("request_timestamp", + &orq->request_timestamp), + GNUNET_PQ_result_spec_timestamp ("expiration_date", + &orq->reserve_expiration), + GNUNET_PQ_result_spec_uint32 ("requested_purse_limit", + &orq->purse_limit), + GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", + &orq->reserve_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + --num_results)) + { + GNUNET_break (0); + GNUNET_free (orq); + rhc->failed = true; + return; + } + } + GNUNET_assert (0 <= + TALER_amount_add (&rhc->balance_out, + &rhc->balance_out, + &orq->open_fee)); + orq->reserve_pub = *rhc->reserve_pub; + tail = append_rh (rhc); + tail->type = TALER_EXCHANGEDB_RO_OPEN_REQUEST; + tail->details.open_request = orq; + } +} + + +/** + * Add paid for history requests to result set for + * #TALER_EXCHANGEDB_get_reserve_history. + * + * @param cls a `struct ReserveHistoryContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +add_close_requests (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReserveHistoryContext *rhc = cls; + + while (0 < num_results) + { + struct TALER_EXCHANGEDB_CloseRequest *crq; + struct TALER_EXCHANGEDB_ReserveHistory *tail; + + crq = GNUNET_new (struct TALER_EXCHANGEDB_CloseRequest); + { + struct TALER_FullPayto payto_uri; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("close_timestamp", + &crq->request_timestamp), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri.full_payto), + GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", + &crq->reserve_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + --num_results)) + { + GNUNET_break (0); + GNUNET_free (crq); + rhc->failed = true; + return; + } + TALER_full_payto_hash (payto_uri, + &crq->target_account_h_payto); + GNUNET_free (payto_uri.full_payto); + } + crq->reserve_pub = *rhc->reserve_pub; + tail = append_rh (rhc); + tail->type = TALER_EXCHANGEDB_RO_CLOSE_REQUEST; + tail->details.close_request = crq; + } +} + + +/** + * Add reserve history entries found. + * + * @param cls a `struct ReserveHistoryContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +handle_history_entry (void *cls, + PGresult *result, + unsigned int num_results) +{ + static const struct + { + /** + * Table with reserve history entry we are responsible for. + */ + const char *table; + /** + * Name of the prepared statement to run. + */ + const char *statement; + /** + * Function to use to process the results. + */ + GNUNET_PQ_PostgresResultHandler cb; + } work[] = { + /** #TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE */ + { "reserves_in", + "reserves_in_get_transactions", + add_bank_to_exchange }, + /** #TALER_EXCHANGEDB_RO_WITHDRAW_COINS */ + { "withdraw", + "get_withdraw_details", + &add_withdraw }, + /** #TALER_EXCHANGEDB_RO_RECOUP_COIN */ + { "recoup", + "recoup_by_reserve", + &add_recoup }, + /** #TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK */ + { "reserves_close", + "close_by_reserve", + &add_exchange_to_bank }, + /** #TALER_EXCHANGEDB_RO_PURSE_MERGE */ + { "purse_decision", + "merge_by_reserve", + &add_p2p_merge }, + /** #TALER_EXCHANGEDB_RO_OPEN_REQUEST */ + { "reserves_open_requests", + "open_request_by_reserve", + &add_open_requests }, + /** #TALER_EXCHANGEDB_RO_CLOSE_REQUEST */ + { "close_requests", + "close_request_by_reserve", + &add_close_requests }, + /* List terminator */ + { NULL, NULL, NULL } + }; + struct ReserveHistoryContext *rhc = cls; + char *table_name; + uint64_t serial_id; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("table_name", + &table_name), + GNUNET_PQ_result_spec_uint64 ("serial_id", + &serial_id), + GNUNET_PQ_result_spec_uint64 ("reserve_history_serial_id", + &rhc->current_history_offset), + GNUNET_PQ_result_spec_end + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (rhc->reserve_pub), + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + + while (0 < num_results--) + { + enum GNUNET_DB_QueryStatus qs; + bool found = false; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + num_results)) + { + GNUNET_break (0); + rhc->failed = true; + return; + } + + for (unsigned int i = 0; + NULL != work[i].cb; + i++) + { + if (0 != strcmp (table_name, + work[i].table)) + continue; + found = true; + qs = GNUNET_PQ_eval_prepared_multi_select (rhc->pg->conn, + work[i].statement, + params, + work[i].cb, + rhc); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Reserve %s had %d transactions at %llu in table %s\n", + TALER_B2S (rhc->reserve_pub), + (int) qs, + (unsigned long long) serial_id, + table_name); + if (0 >= qs) + rhc->failed = true; + break; + } + if (! found) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Reserve history includes unsupported table `%s`\n", + table_name); + rhc->failed = true; + } + GNUNET_PQ_cleanup_result (rs); + if (rhc->failed) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_reserve_history ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t start_off, + uint64_t etag_in, + uint64_t *etag_out, + struct TALER_Amount *balance, + struct TALER_EXCHANGEDB_ReserveHistory **rhp) +{ + struct ReserveHistoryContext rhc = { + .pg = pg, + .reserve_pub = reserve_pub + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_QueryParam lparams[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_uint64 (&start_off), + GNUNET_PQ_query_param_end + }; + + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (pg->currency, + &rhc.balance_in)); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (pg->currency, + &rhc.balance_out)); + + *rhp = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Getting transactions for reserve %s\n", + TALER_B2S (reserve_pub)); + PREPARE (pg, + "get_reserve_history_etag", + "SELECT" + " his.reserve_history_serial_id" + ",r.current_balance" + " FROM reserve_history his" + " JOIN reserves r USING (reserve_pub)" + " WHERE his.reserve_pub=$1" + " ORDER BY reserve_history_serial_id DESC" + " LIMIT 1;"); + PREPARE (pg, + "get_reserve_history", + "SELECT" + " table_name" + ",serial_id" + ",reserve_history_serial_id" + " FROM reserve_history" + " WHERE reserve_pub=$1" + " AND reserve_history_serial_id > $2" + " ORDER BY reserve_history_serial_id DESC;"); + PREPARE (pg, + "reserves_in_get_transactions", + "SELECT" + " ri.wire_reference" + ",ri.credit" + ",ri.execution_date" + ",wt.payto_uri AS sender_account_details" + " FROM reserves_in ri" + " JOIN wire_targets wt" + " ON (wire_source_h_payto = wire_target_h_payto)" + " WHERE ri.reserve_pub=$1" + " AND ri.reserve_in_serial_id=$2;"); + PREPARE (pg, + "get_withdraw_details", + "SELECT" + " planchets_h" + ",amount_with_fee" + ",reserve_sig" + ",max_age" + ",noreveal_index" + ",selected_h" + ",blinding_seed" + ",denom_serials" + ",ARRAY(" + " SELECT denominations.denom_pub_hash FROM (" + " SELECT UNNEST(denom_serials) AS id," + " generate_subscripts(denom_serials, 1) AS nr" /* for order */ + " ) AS denoms" + " LEFT JOIN denominations ON denominations.denominations_serial=denoms.id" + ") AS denom_pub_hashes" + " FROM withdraw " + " WHERE withdraw_id=$2" + " AND reserve_pub=$1;"); + PREPARE (pg, + "recoup_by_reserve", + "SELECT" + " rec.coin_pub" + ",rec.coin_sig" + ",rec.coin_blind" + ",rec.amount" + ",rec.recoup_timestamp" + ",denom.denom_pub_hash" + ",kc.denom_sig" + " FROM recoup rec" + " JOIN withdraw ro" + " USING (withdraw_id)" + " JOIN reserves res" + " USING (reserve_pub)" + " JOIN known_coins kc" + " USING (coin_pub)" + " JOIN denominations denom" + " ON (denom.denominations_serial = kc.denominations_serial)" + " WHERE rec.recoup_uuid=$2" + " AND res.reserve_pub=$1;"); + PREPARE (pg, + "close_by_reserve", + "SELECT" + " rc.amount" + ",rc.closing_fee" + ",rc.execution_date" + ",wt.payto_uri AS receiver_account" + ",rc.wtid" + " FROM reserves_close rc" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " WHERE reserve_pub=$1" + " AND close_uuid=$2;"); + PREPARE (pg, + "merge_by_reserve", + "SELECT" + " pr.amount_with_fee" + ",pr.balance" + ",pr.purse_fee" + ",pr.h_contract_terms" + ",pr.merge_pub" + ",am.reserve_sig" + ",pm.purse_pub" + ",pm.merge_timestamp" + ",pr.purse_expiration" + ",pr.age_limit" + ",pr.flags" + " FROM purse_decision pdes" + " JOIN purse_requests pr" + " ON (pr.purse_pub = pdes.purse_pub)" + " JOIN purse_merges pm" + " ON (pm.purse_pub = pdes.purse_pub)" + " JOIN account_merges am" + " ON (am.purse_pub = pm.purse_pub AND" + " am.reserve_pub = pm.reserve_pub)" + " WHERE pdes.purse_decision_serial_id=$2" + " AND pm.reserve_pub=$1" + " AND COALESCE(pm.partner_serial_id,0)=0" /* must be local! */ + " AND NOT pdes.refunded;"); + PREPARE (pg, + "open_request_by_reserve", + "SELECT" + " reserve_payment" + ",request_timestamp" + ",expiration_date" + ",requested_purse_limit" + ",reserve_sig" + " FROM reserves_open_requests" + " WHERE reserve_pub=$1" + " AND open_request_uuid=$2;"); + PREPARE (pg, + "close_request_by_reserve", + "SELECT" + " close_timestamp" + ",payto_uri" + ",reserve_sig" + " FROM close_requests" + " WHERE reserve_pub=$1" + " AND close_request_serial_id=$2;"); + + for (unsigned int i = 0; i<RETRIES; i++) + { + enum GNUNET_DB_QueryStatus qs; + uint64_t end; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("reserve_history_serial_id", + &end), + TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance", + balance), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + TALER_TALER_EXCHANGEDB_start_read_committed (pg, + "get-reserve-transactions") + ) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + /* First only check the last item, to see if + we even need to iterate */ + qs = GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "get_reserve_history_etag", + params, + rs); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TALER_EXCHANGEDB_rollback (pg); + continue; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + *etag_out = end; + if (end == etag_in) + return qs; + } + /* We indeed need to iterate over the history */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Current ETag for reserve %s is %llu\n", + TALER_B2S (reserve_pub), + (unsigned long long) end); + + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "get_reserve_history", + lparams, + &handle_history_entry, + &rhc); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + TALER_EXCHANGEDB_rollback (pg); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TALER_EXCHANGEDB_rollback (pg); + continue; + default: + break; + } + if (rhc.failed) + { + TALER_EXCHANGEDB_rollback (pg); + TALER_EXCHANGEDB_free_reserve_history (rhc.rh); + return GNUNET_DB_STATUS_SOFT_ERROR; + } + qs = TALER_EXCHANGEDB_commit (pg); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + TALER_EXCHANGEDB_free_reserve_history (rhc.rh); + return qs; + case GNUNET_DB_STATUS_SOFT_ERROR: + TALER_EXCHANGEDB_free_reserve_history (rhc.rh); + rhc.rh = NULL; + continue; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + *rhp = rhc.rh; + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + } + return GNUNET_DB_STATUS_SOFT_ERROR; +} diff --git a/src/exchangedb/get_signature_for_known_coin.c b/src/exchangedb/get_signature_for_known_coin.c @@ -0,0 +1,59 @@ +/* + This file is part of TALER + Copyright (C) 2023 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/> + */ +/** + * @file exchangedb/get_signature_for_known_coin.c + * @brief Implementation of the get_signature_for_known_coin function for Postgres + * @author Özgür Kesim + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_signature_for_known_coin.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_signature_for_known_coin ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_DenominationPublicKey *denom_pub, + struct TALER_DenominationSignature *denom_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_denom_pub ("denom_pub", + denom_pub), + TALER_PQ_result_spec_denom_sig ("denom_sig", + denom_sig), + GNUNET_PQ_result_spec_end + }; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Getting denomination and signature for (potentially) known coin %s\n", + TALER_B2S (coin_pub)); + PREPARE (pg, + "get_signature_for_known_coin", + "SELECT" + " denominations.denom_pub" + ",denom_sig" + " FROM known_coins" + " JOIN denominations USING (denominations_serial)" + " WHERE coin_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_signature_for_known_coin", + params, + rs); +} diff --git a/src/exchangedb/get_unfinished_close_requests.c b/src/exchangedb/get_unfinished_close_requests.c @@ -0,0 +1,162 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file get_unfinished_close_requests.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_unfinished_close_requests.h" +#include "helper.h" + + +/** + * Closure for #reserve_close_cb(). + */ +struct CloseReserveContext +{ + /** + * Function to call for each to be closed reserve. + */ + TALER_EXCHANGEDB_ReserveExpiredCallback rec; + + /** + * Closure to give to @e rec. + */ + void *rec_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on error. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +reserve_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CloseReserveContext *erc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = erc->pg; + enum GNUNET_GenericReturnValue ret = GNUNET_OK; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_TIME_Timestamp exp_date; + struct TALER_FullPayto account_details; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_Amount remaining_balance; + uint64_t close_request_row; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("expiration_date", + &exp_date), + GNUNET_PQ_result_spec_string ("account_details", + &account_details.full_payto), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + TALER_PQ_RESULT_SPEC_AMOUNT ("close", + &remaining_balance), + GNUNET_PQ_result_spec_uint64 ("close_request_serial_id", + &close_request_row), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ret = GNUNET_SYSERR; + break; + } + ret = erc->rec (erc->rec_cls, + &reserve_pub, + &remaining_balance, + account_details, + exp_date, + close_request_row); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } + erc->status = ret; +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_unfinished_close_requests ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + TALER_EXCHANGEDB_ReserveExpiredCallback rec, + void *rec_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + struct CloseReserveContext ectx = { + .rec = rec, + .rec_cls = rec_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "get_unfinished_close_requests", + "UPDATE close_requests AS rc" + " SET done=TRUE" + " WHERE NOT done" + " RETURNING" + " reserve_pub" + " ,close_request_serial_id" + " ,close_timestamp AS expiration_date" + " ,close" + " ,(SELECT payto_uri" + " FROM reserves_in ri" + " JOIN wire_targets wt" + " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)" + " WHERE ri.reserve_pub=rc.reserve_pub)" + " AS account_details;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "get_unfinished_close_requests", + params, + &reserve_cb, + &ectx); + switch (ectx.status) + { + case GNUNET_SYSERR: + return GNUNET_DB_STATUS_HARD_ERROR; + case GNUNET_NO: + return GNUNET_DB_STATUS_SOFT_ERROR; + case GNUNET_OK: + break; + } + return qs; +} diff --git a/src/exchangedb/get_wire_accounts.c b/src/exchangedb/get_wire_accounts.c @@ -0,0 +1,179 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/get_wire_accounts.c + * @brief Implementation of the get_wire_accounts function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_wire_accounts.h" +#include "helper.h" + + +/** + * Closure for #get_wire_accounts_cb(). + */ +struct GetWireAccountsContext +{ + /** + * Function to call per result. + */ + TALER_EXCHANGEDB_WireAccountCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Flag set to #GNUNET_OK as long as everything is fine. + */ + enum GNUNET_GenericReturnValue status; + +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct MissingWireContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_wire_accounts_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct GetWireAccountsContext *ctx = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + struct TALER_FullPayto payto_uri; + char *conversion_url = NULL; + char *open_banking_gateway = NULL; + char *wire_transfer_gateway = NULL; + json_t *debit_restrictions = NULL; + json_t *credit_restrictions = NULL; + struct TALER_MasterSignatureP master_sig; + char *bank_label = NULL; + int64_t priority; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri.full_payto), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("conversion_url", + &conversion_url), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("open_banking_gateway", + &open_banking_gateway), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("wire_transfer_gateway", + &wire_transfer_gateway), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("bank_label", + &bank_label), + NULL), + GNUNET_PQ_result_spec_int64 ("priority", + &priority), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("debit_restrictions", + &debit_restrictions), + NULL), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("credit_restrictions", + &credit_restrictions), + NULL), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &master_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + if (NULL == debit_restrictions) + { + debit_restrictions = json_array (); + GNUNET_assert (NULL != debit_restrictions); + } + if (NULL == credit_restrictions) + { + credit_restrictions = json_array (); + GNUNET_assert (NULL != credit_restrictions); + } + ctx->cb (ctx->cb_cls, + payto_uri, + conversion_url, + open_banking_gateway, + wire_transfer_gateway, + debit_restrictions, + credit_restrictions, + &master_sig, + bank_label, + priority); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_wire_accounts (struct TALER_EXCHANGEDB_PostgresContext *pg, + TALER_EXCHANGEDB_WireAccountCallback cb, + void *cb_cls) +{ + struct GetWireAccountsContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .status = GNUNET_OK + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "get_wire_accounts", + "SELECT" + " payto_uri" + ",conversion_url" + ",open_banking_gateway" + ",wire_transfer_gateway" + ",debit_restrictions::TEXT" + ",credit_restrictions::TEXT" + ",master_sig" + ",bank_label" + ",priority" + " FROM wire_accounts" + " WHERE is_active"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "get_wire_accounts", + params, + &get_wire_accounts_cb, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/get_wire_fee.c b/src/exchangedb/get_wire_fee.c @@ -0,0 +1,74 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_wire_fee.c + * @brief Implementation of the get_wire_fee function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_wire_fee.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_wire_fee ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *type, + struct GNUNET_TIME_Timestamp date, + uint64_t *rowid, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_WireFeeSet *fees, + struct TALER_MasterSignatureP *master_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (type), + GNUNET_PQ_query_param_timestamp (&date), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("wire_fee_serial", + rowid), + GNUNET_PQ_result_spec_timestamp ("start_date", + start_date), + GNUNET_PQ_result_spec_timestamp ("end_date", + end_date), + TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", + &fees->wire), + TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", + &fees->closing), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_wire_fee", + "SELECT" + " wire_fee_serial" + ",start_date" + ",end_date" + ",wire_fee" + ",closing_fee" + ",master_sig" + " FROM wire_fee" + " WHERE wire_method=$1" + " AND start_date <= $2" + " AND end_date > $2;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_wire_fee", + params, + rs); +} diff --git a/src/exchangedb/get_wire_fees.c b/src/exchangedb/get_wire_fees.c @@ -0,0 +1,144 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/get_wire_fees.c + * @brief Implementation of the get_wire_fees function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_wire_fees.h" +#include "helper.h" + +/** + * Closure for #get_wire_fees_cb(). + */ +struct GetWireFeesContext +{ + /** + * Function to call per result. + */ + TALER_EXCHANGEDB_WireFeeCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Flag set to #GNUNET_OK as long as everything is fine. + */ + enum GNUNET_GenericReturnValue status; + +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct GetWireFeesContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_wire_fees_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct GetWireFeesContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + + for (unsigned int i = 0; i < num_results; i++) + { + struct TALER_MasterSignatureP master_sig; + struct TALER_WireFeeSet fees; + struct GNUNET_TIME_Timestamp start_date; + struct GNUNET_TIME_Timestamp end_date; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", + &fees.wire), + TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", + &fees.closing), + GNUNET_PQ_result_spec_timestamp ("start_date", + &start_date), + GNUNET_PQ_result_spec_timestamp ("end_date", + &end_date), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &master_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ctx->cb (ctx->cb_cls, + &fees, + start_date, + end_date, + &master_sig); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_get_wire_fees (struct TALER_EXCHANGEDB_PostgresContext * + pg, + const char *wire_method, + TALER_EXCHANGEDB_WireFeeCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (wire_method), + GNUNET_PQ_query_param_end + }; + struct GetWireFeesContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "get_wire_fees", + "SELECT" + " wire_fee" + ",closing_fee" + ",start_date" + ",end_date" + ",master_sig" + " FROM wire_fee" + " WHERE wire_method=$1"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "get_wire_fees", + params, + &get_wire_fees_cb, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/get_wire_hash_for_contract.c b/src/exchangedb/get_wire_hash_for_contract.c @@ -0,0 +1,77 @@ +/* + This file is part of TALER + Copyright (C) 2023, 2024 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/> + */ +/** + * @file exchangedb/get_wire_hash_for_contract.c + * @brief Implementation of the get_wire_hash_for_contract function for Postgres + * @author Özgür Kesim + */ +#include "taler/taler_exchangedb_lib.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_wire_hash_for_contract.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_wire_hash_for_contract ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct TALER_MerchantWireHashP *h_wire) +{ + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_auto_from_type (h_contract_terms), + GNUNET_PQ_query_param_end + }; + struct TALER_FullPayto payto_uri; + struct TALER_WireSaltP wire_salt; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("wire_salt", + &wire_salt), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri.full_payto), + GNUNET_PQ_result_spec_end + }; + + /* check if the necessary records exist and get them */ + PREPARE (pg, + "get_wire_hash_for_contract", + "SELECT" + " bdep.wire_salt" + " ,wt.payto_uri" + " FROM coin_deposits" + " JOIN batch_deposits bdep" + " USING (batch_deposit_serial_id)" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " WHERE bdep.merchant_pub=$1" + " AND bdep.h_contract_terms=$2"); + /* NOTE: above query might be more efficient if we computed the shard + from the merchant_pub and included that in the query */ + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_wire_hash_for_contract", + params, + rs); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + TALER_merchant_wire_signature_hash (payto_uri, + &wire_salt, + h_wire); + GNUNET_PQ_cleanup_result (rs); + } + return qs; +} diff --git a/src/exchangedb/get_withdraw.c b/src/exchangedb/get_withdraw.c @@ -0,0 +1,191 @@ +/* + This file is part of TALER + Copyright (C) 2023, 2025 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/> + */ +/** + * @file exchangedb/get_withdraw.c + * @brief Implementation of the get_withdraw function for Postgres + * @author Özgür Kesim + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/get_withdraw.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_get_withdraw ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_HashBlindedPlanchetsP *wch, + struct TALER_EXCHANGEDB_Withdraw *wd) +{ + enum GNUNET_DB_QueryStatus ret; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (wch), + GNUNET_PQ_query_param_end + }; + struct TALER_BlindedDenominationSignature *my_denom_sigs = NULL; + uint64_t *my_denom_serials = NULL; + struct GNUNET_CRYPTO_CSPublicRPairP *my_cs_r_values = NULL; + size_t num_sigs = 0; + size_t num_coins = 0; + size_t num_cs_r_values = 0; + bool no_noreveal_index; + bool no_max_age; + bool no_selected_h; + bool no_blinding_seed; + bool no_cs_r_values; + bool no_cs_r_choices; + + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("planchets_h", + &wd->planchets_h), + GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", + &wd->reserve_sig), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &wd->reserve_pub), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint16 ("max_age", + &wd->max_age), + &no_max_age), + TALER_PQ_result_spec_amount ("amount_with_fee", + pg->currency, + &wd->amount_with_fee), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint16 ("noreveal_index", + &wd->noreveal_index), + &no_noreveal_index), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("selected_h", + &wd->selected_h), + &no_selected_h), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("blinding_seed", + &wd->blinding_seed), + &no_blinding_seed), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_array_cs_r_pub ( + pg->conn, + "cs_r_values", + &num_cs_r_values, + &my_cs_r_values), + &no_cs_r_values), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ("cs_r_choices", + &wd->cs_r_choices), + &no_cs_r_choices), + TALER_PQ_result_spec_array_blinded_denom_sig ( + pg->conn, + "denom_sigs", + &num_sigs, + &my_denom_sigs), + GNUNET_PQ_result_spec_array_uint64 ( + pg->conn, + "denom_serials", + &num_coins, + &my_denom_serials), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_withdraw", + "SELECT" + " planchets_h" + ",blinding_seed" + ",reserve_sig" + ",reserve_pub" + ",max_age" + ",amount_with_fee" + ",noreveal_index" + ",selected_h" + ",blinding_seed" + ",cs_r_values" + ",cs_r_choices" + ",denom_sigs" + ",denom_serials" + " FROM withdraw" + " WHERE planchets_h=$1;"); + ret = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_withdraw", + params, + rs); + if (0 > ret) + { + GNUNET_break (0); + GNUNET_PQ_cleanup_result (rs); + return ret; + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == ret) + { + GNUNET_PQ_cleanup_result (rs); + return ret; + } + + if ((no_max_age != no_noreveal_index) || + (no_max_age != no_selected_h)) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "got inconsistent state for max_age, noreveal_index and planchets_h in DB: " + "no_max_age=%s, no_noreveal_index=%s, no_selected_h=%s\n", + no_max_age ? "true" : "false", + no_noreveal_index ? "true" : "false", + no_selected_h ? "true" : "false"); + GNUNET_PQ_cleanup_result (rs); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (no_blinding_seed != no_cs_r_values) + { + GNUNET_break (0); + GNUNET_PQ_cleanup_result (rs); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (no_cs_r_choices != no_cs_r_values) + { + GNUNET_break (0); + GNUNET_PQ_cleanup_result (rs); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (num_coins != num_sigs) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "got inconsistent number of entries in withdraw from DB: " + "num_coins=%ld, num_sigs=%ld\n", + num_coins, + num_sigs); + GNUNET_PQ_cleanup_result (rs); + return GNUNET_DB_STATUS_HARD_ERROR; + } + wd->age_proof_required = ! no_max_age; + if (no_cs_r_values) + { + wd->cs_r_values = NULL; + wd->num_cs_r_values = 0; + wd->cs_r_choices = 0; + } + wd->denom_sigs = my_denom_sigs; + wd->num_coins = num_coins; + wd->denom_serials = my_denom_serials; + wd->cs_r_values = my_cs_r_values; + wd->num_cs_r_values = num_cs_r_values; + /* ensure cleanup_result does not trash data we care about */ + my_denom_sigs = NULL; + my_denom_serials = NULL; + my_cs_r_values = NULL; + num_sigs = 0; + num_coins = 0; + num_cs_r_values = 0; + GNUNET_PQ_cleanup_result (rs); + return ret; +} diff --git a/src/exchangedb/have_deposit2.c b/src/exchangedb/have_deposit2.c @@ -0,0 +1,113 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/have_deposit2.c + * @brief Implementation of the have_deposit2 function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/have_deposit2.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_have_deposit2 ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant, + struct GNUNET_TIME_Timestamp refund_deadline, + struct TALER_Amount *deposit_fee, + struct GNUNET_TIME_Timestamp *exchange_timestamp) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_auto_from_type (h_contract_terms), + GNUNET_PQ_query_param_auto_from_type (merchant), + GNUNET_PQ_query_param_end + }; + struct TALER_EXCHANGEDB_Deposit deposit2; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &deposit2.amount_with_fee), + GNUNET_PQ_result_spec_timestamp ("wallet_timestamp", + &deposit2.timestamp), + GNUNET_PQ_result_spec_timestamp ("exchange_timestamp", + exchange_timestamp), + GNUNET_PQ_result_spec_timestamp ("refund_deadline", + &deposit2.refund_deadline), + GNUNET_PQ_result_spec_timestamp ("wire_deadline", + &deposit2.wire_deadline), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + deposit_fee), + GNUNET_PQ_result_spec_auto_from_type ("wire_salt", + &deposit2.wire_salt), + GNUNET_PQ_result_spec_string ("receiver_wire_account", + &deposit2.receiver_wire_account.full_payto), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + struct TALER_MerchantWireHashP h_wire2; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Getting deposits for coin %s\n", + TALER_B2S (coin_pub)); + PREPARE (pg, + "get_deposit", + "SELECT" + " cdep.amount_with_fee" + ",denominations.fee_deposit" + ",bdep.wallet_timestamp" + ",bdep.exchange_timestamp" + ",bdep.refund_deadline" + ",bdep.wire_deadline" + ",bdep.h_contract_terms" + ",bdep.wire_salt" + ",wt.payto_uri AS receiver_wire_account" + " FROM coin_deposits cdep" + " JOIN batch_deposits bdep USING (batch_deposit_serial_id)" + " JOIN known_coins kc ON (kc.coin_pub = cdep.coin_pub)" + " JOIN denominations USING (denominations_serial)" + " JOIN wire_targets wt USING (wire_target_h_payto)" + " WHERE cdep.coin_pub=$1" + " AND bdep.merchant_pub=$3" + " AND bdep.h_contract_terms=$2;"); + /* Note: query might be made more efficient if we computed the 'shard' + from merchant_pub and included that as a constraint on bdep! */ + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_deposit", + params, + rs); + if (0 >= qs) + return qs; + TALER_merchant_wire_signature_hash (deposit2.receiver_wire_account, + &deposit2.wire_salt, + &h_wire2); + GNUNET_free (deposit2.receiver_wire_account.full_payto); + /* Now we check that the other information in @a deposit + also matches, and if not report inconsistencies. */ + if ( (GNUNET_TIME_timestamp_cmp (refund_deadline, + !=, + deposit2.refund_deadline)) || + (0 != GNUNET_memcmp (h_wire, + &h_wire2) ) ) + { + /* Inconsistencies detected! Does not match! */ + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; +} diff --git a/src/exchangedb/inject_auditor_triggers.c b/src/exchangedb/inject_auditor_triggers.c @@ -0,0 +1,55 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/inject_auditor_triggers.c + * @brief Implementation of the inject_auditor_triggers function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/gc.h" +#include "helper.h" +#include "taler/exchange-database/inject_auditor_triggers.h" + + +/** + * Function called to inject auditor triggers into the + * database, triggering the real-time auditor upon + * relevant INSERTs. + * + * @param pg the database context + * @return #GNUNET_OK on success, + * #GNUNET_SYSERR on DB errors + */ +enum GNUNET_GenericReturnValue +TALER_EXCHANGEDB_inject_auditor_triggers (struct + TALER_EXCHANGEDB_PostgresContext *pg) +{ + struct GNUNET_PQ_Context *conn; + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + conn = GNUNET_PQ_connect_with_cfg (pg->cfg, + "exchangedb-postgres", + "auditor-triggers-", + es, + NULL); + if (NULL == conn) + return GNUNET_SYSERR; + GNUNET_PQ_disconnect (conn); + return GNUNET_OK; +} diff --git a/src/exchangedb/insert_active_legitimization_measure.c b/src/exchangedb/insert_active_legitimization_measure.c @@ -0,0 +1,58 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/insert_active_legitimization_measure.c + * @brief Implementation of the insert_active_legitimization_measure function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_active_legitimization_measure.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_active_legitimization_measure ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_AccountAccessTokenP *access_token, + const json_t *jmeasures, + uint64_t *legitimization_measure_serial_id) +{ + struct GNUNET_TIME_Timestamp now + = GNUNET_TIME_timestamp_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (access_token), + GNUNET_PQ_query_param_timestamp (&now), + TALER_PQ_query_param_json (jmeasures), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("out_legitimization_measure_serial_id", + legitimization_measure_serial_id), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "do_insert_active_legitimization_measure", + "SELECT" + " out_legitimization_measure_serial_id" + " FROM exchange_do_insert_active_legitimization_measure" + "($1, $2, $3::TEXT::JSONB);"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "do_insert_active_legitimization_measure", + params, + rs); +} diff --git a/src/exchangedb/insert_aml_decision.c b/src/exchangedb/insert_aml_decision.c @@ -0,0 +1,185 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2023, 2024 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/> + */ +/** + * @file exchangedb/insert_aml_decision.c + * @brief Implementation of the insert_aml_decision function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_aml_decision.h" +#include "helper.h" +#include <gnunet/gnunet_pq_lib.h> + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_aml_decision ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_FullPayto payto_uri, + const struct TALER_NormalizedPaytoHashP *h_payto, + struct GNUNET_TIME_Timestamp decision_time, + struct GNUNET_TIME_Timestamp expiration_time, + const json_t *properties, + const json_t *new_rules, + bool to_investigate, + const char *new_measure_name, + const json_t *jmeasures, + const char *justification, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + const struct TALER_AmlOfficerSignatureP *decider_sig, + size_t num_events, + const char *events[static num_events], + const char *form_name, + size_t enc_attributes_size, + const void *enc_attributes, + struct GNUNET_HashCode *attributes_hash, + struct GNUNET_TIME_Timestamp attributes_expiration_time, + bool *invalid_officer, + bool *unknown_account, + struct GNUNET_TIME_Timestamp *last_date, + uint64_t *legitimization_measure_serial_id, + bool *is_wallet) +{ + struct TALER_EXCHANGEDB_KycCompletedEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), + .h_payto = *h_payto + }; + struct TALER_FullPaytoHashP h_full_payto; + char *notify_s + = GNUNET_PQ_get_event_notify_channel (&rep.header); + bool account_unknown; + struct GNUNET_PQ_QueryParam params[] = { + /* $1: in_payto_uri */ + NULL == payto_uri.full_payto + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (payto_uri.full_payto), + /* $2: in_h_normalized_payto */ + GNUNET_PQ_query_param_auto_from_type (h_payto), + /* $3: in_h_full_payto */ + NULL == payto_uri.full_payto + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (&h_full_payto), + /* $4: in_decision_time */ + GNUNET_PQ_query_param_timestamp (&decision_time), + /* $5: in_expiration_time*/ + GNUNET_PQ_query_param_timestamp (&expiration_time), + /* $6: in_properties */ + NULL != properties + ? TALER_PQ_query_param_json (properties) + : GNUNET_PQ_query_param_null (), + /* $7: in_kyc_attributes_enc */ + NULL != enc_attributes + ? GNUNET_PQ_query_param_fixed_size (enc_attributes, + enc_attributes_size) + : GNUNET_PQ_query_param_null (), + /* $8: in_kyc_attributes_hash */ + NULL != attributes_hash + ? GNUNET_PQ_query_param_auto_from_type (attributes_hash) + : GNUNET_PQ_query_param_null (), + /* $9: in_kyc_attributes_expiration */ + GNUNET_PQ_query_param_timestamp (&attributes_expiration_time), + /* $10: in_new_rules */ + TALER_PQ_query_param_json (new_rules), + /* $11: in_to_investigate */ + GNUNET_PQ_query_param_bool (to_investigate), + /* $12: in_new_measure_name */ + NULL != new_measure_name + ? GNUNET_PQ_query_param_string (new_measure_name) + : GNUNET_PQ_query_param_null (), + /* $13: in_jmeasures */ + NULL != jmeasures + ? TALER_PQ_query_param_json (jmeasures) + : GNUNET_PQ_query_param_null (), + /* $14: in_justification */ + NULL != justification + ? GNUNET_PQ_query_param_string (justification) + : GNUNET_PQ_query_param_null (), + /* $15: in_decider_pub */ + NULL != decider_pub + ? GNUNET_PQ_query_param_auto_from_type (decider_pub) + : GNUNET_PQ_query_param_null (), + /* $16: in_decider_sig */ + NULL != decider_sig + ? GNUNET_PQ_query_param_auto_from_type (decider_sig) + : GNUNET_PQ_query_param_null (), + /* $17: in_notify_s*/ + GNUNET_PQ_query_param_string (notify_s), + /* $18: ina_events */ + GNUNET_PQ_query_param_array_ptrs_string (num_events, + events, + pg->conn), + (NULL == form_name) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (form_name), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("out_invalid_officer", + invalid_officer), + GNUNET_PQ_result_spec_bool ("out_account_unknown", + unknown_account), + GNUNET_PQ_result_spec_timestamp ("out_last_date", + last_date), + GNUNET_PQ_result_spec_uint64 ("out_legitimization_measure_serial_id", + legitimization_measure_serial_id), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_bool ("out_is_wallet", + is_wallet), + &account_unknown), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + *is_wallet = false; + GNUNET_assert ( ( (NULL == decider_pub) && + (NULL == decider_sig) && + (NULL == justification) ) || + ( (NULL != decider_pub) && + (NULL != decider_sig) && + (NULL != justification) ) ); + + if (NULL != payto_uri.full_payto) + TALER_full_payto_hash (payto_uri, + &h_full_payto); + PREPARE (pg, + "do_insert_aml_decision", + "SELECT" + " out_invalid_officer" + ",out_account_unknown" + ",out_last_date" + ",out_legitimization_measure_serial_id" + ",out_is_wallet" + " FROM exchange_do_insert_aml_decision" + "($1,$2,$3,$4,$5,$6::TEXT::JSONB,$7,$8,$9,$10::TEXT::JSONB" + ",$11,$12,$13::TEXT::JSONB,$14,$15,$16,$17,$18,$19);"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Inserting LEGI OUTCOME from AML decision with notification on %s\n", + notify_s); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "do_insert_aml_decision", + params, + rs); + GNUNET_PQ_cleanup_query_params_closures (params); + GNUNET_free (notify_s); + GNUNET_PQ_event_do_poll (pg->conn); + if (qs <= 0) + return qs; + if (account_unknown) + { + GNUNET_assert ((*invalid_officer) || (*unknown_account)); + } + return qs; +} diff --git a/src/exchangedb/insert_aml_officer.c b/src/exchangedb/insert_aml_officer.c @@ -0,0 +1,62 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2023 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/> + */ +/** + * @file exchangedb/insert_aml_officer.c + * @brief Implementation of the insert_aml_officer function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_aml_officer.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_aml_officer ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + const struct TALER_MasterSignatureP *master_sig, + const char *decider_name, + bool is_active, + bool read_only, + struct GNUNET_TIME_Timestamp last_change, + struct GNUNET_TIME_Timestamp *previous_change) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (decider_pub), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_string (decider_name), + GNUNET_PQ_query_param_bool (is_active), + GNUNET_PQ_query_param_bool (read_only), + GNUNET_PQ_query_param_timestamp (&last_change), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("out_last_change", + previous_change), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "do_insert_aml_staff", + "SELECT" + " out_last_change" + " FROM exchange_do_insert_aml_officer" + "($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "do_insert_aml_staff", + params, + rs); +} diff --git a/src/exchangedb/insert_aml_program_failure.c b/src/exchangedb/insert_aml_program_failure.c @@ -0,0 +1,66 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/insert_aml_program_failure.c + * @brief Implementation of the insert_aml_program_failure function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_aml_program_failure.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_aml_program_failure ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t process_row, + const struct TALER_NormalizedPaytoHashP *h_payto, + const char *error_message, + enum TALER_ErrorCode ec) +{ + uint32_t ec32 = (uint32_t) ec; + struct TALER_EXCHANGEDB_KycCompletedEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), + .h_payto = *h_payto + }; + struct GNUNET_TIME_Timestamp now + = GNUNET_TIME_timestamp_get (); + char *kyc_completed_notify_s + = GNUNET_PQ_get_event_notify_channel (&rep.header); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&process_row), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_timestamp (&now), + GNUNET_PQ_query_param_uint32 (&ec32), + GNUNET_PQ_query_param_string (error_message), + GNUNET_PQ_query_param_string (kyc_completed_notify_s), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "insert_aml_program_failure", + "SELECT out_update" + " FROM exchange_do_insert_aml_program_failure" + " ($1, $2, $3, $4, $5, $6);"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_aml_program_failure", + params); + GNUNET_free (kyc_completed_notify_s); + return qs; +} diff --git a/src/exchangedb/insert_auditor.c b/src/exchangedb/insert_auditor.c @@ -0,0 +1,55 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_auditor.c + * @brief Implementation of the insert_auditor function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_auditor.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_auditor (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_AuditorPublicKeyP * + auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp start_date) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (auditor_pub), + GNUNET_PQ_query_param_string (auditor_name), + GNUNET_PQ_query_param_string (auditor_url), + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_end + }; + + /* used in #postgres_insert_auditor() */ + PREPARE (pg, + "insert_auditor", + "INSERT INTO auditors " + "(auditor_pub" + ",auditor_name" + ",auditor_url" + ",is_active" + ",last_change" + ") VALUES " + "($1, $2, $3, true, $4);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_auditor", + params); +} diff --git a/src/exchangedb/insert_auditor_denom_sig.c b/src/exchangedb/insert_auditor_denom_sig.c @@ -0,0 +1,58 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_auditor_denom_sig.c + * @brief Implementation of the insert_auditor_denom_sig function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_auditor_denom_sig.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_insert_auditor_denom_sig ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const struct TALER_AuditorSignatureP *auditor_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (auditor_pub), + GNUNET_PQ_query_param_auto_from_type (h_denom_pub), + GNUNET_PQ_query_param_auto_from_type (auditor_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_auditor_denom_sig", + "WITH ax AS" + " (SELECT auditor_uuid" + " FROM auditors" + " WHERE auditor_pub=$1)" + "INSERT INTO auditor_denom_sigs " + "(auditor_uuid" + ",denominations_serial" + ",auditor_sig" + ") SELECT ax.auditor_uuid, denominations_serial, $3 " + " FROM denominations" + " CROSS JOIN ax" + " WHERE denom_pub_hash=$2" + " ON CONFLICT DO NOTHING;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_auditor_denom_sig", + params); +} diff --git a/src/exchangedb/insert_close_request.c b/src/exchangedb/insert_close_request.c @@ -0,0 +1,64 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file insert_close_request.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_close_request.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_close_request ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_FullPayto payto_uri, + const struct TALER_ReserveSignatureP *reserve_sig, + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_Amount *balance, + const struct TALER_Amount *closing_fee) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_timestamp (&request_timestamp), + GNUNET_PQ_query_param_auto_from_type (reserve_sig), + TALER_PQ_query_param_amount (pg->conn, + balance), + TALER_PQ_query_param_amount (pg->conn, + closing_fee), + GNUNET_PQ_query_param_string (payto_uri.full_payto), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_account_close", + "INSERT INTO close_requests" + "(reserve_pub" + ",close_timestamp" + ",reserve_sig" + ",close" + ",close_fee" + ",payto_uri" + ")" + "VALUES " + "($1, $2, $3, $4, $5, $6)" + " ON CONFLICT DO NOTHING;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_account_close", + params); +} diff --git a/src/exchangedb/insert_contract.c b/src/exchangedb/insert_contract.c @@ -0,0 +1,89 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_contract.c + * @brief Implementation of the insert_contract function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_contract.h" +#include "taler/exchange-database/select_contract_by_purse.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_contract ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_EncryptedContract *econtract, + bool *in_conflict) +{ + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_auto_from_type (&econtract->contract_pub), + GNUNET_PQ_query_param_fixed_size (econtract->econtract, + econtract->econtract_size), + GNUNET_PQ_query_param_auto_from_type (&econtract->econtract_sig), + GNUNET_PQ_query_param_end + }; + + *in_conflict = false; + /* Used in #postgres_insert_contract() */ + PREPARE (pg, + "insert_contract", + "INSERT INTO contracts" + " (purse_pub" + " ,pub_ckey" + " ,e_contract" + " ,contract_sig" + " ,purse_expiration" + " ) SELECT " + " $1, $2, $3, $4, purse_expiration" + " FROM purse_requests" + " WHERE purse_pub=$1" + " ON CONFLICT DO NOTHING;"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_contract", + params); + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs) + return qs; + { + struct TALER_EncryptedContract econtract2; + + qs = TALER_TALER_EXCHANGEDB_select_contract_by_purse (pg, + purse_pub, + &econtract2); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if ( (0 == GNUNET_memcmp (&econtract->contract_pub, + &econtract2.contract_pub)) && + (econtract2.econtract_size == + econtract->econtract_size) && + (0 == memcmp (econtract2.econtract, + econtract->econtract, + econtract->econtract_size)) ) + { + GNUNET_free (econtract2.econtract); + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + GNUNET_free (econtract2.econtract); + *in_conflict = true; + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } +} diff --git a/src/exchangedb/insert_denomination_info.c b/src/exchangedb/insert_denomination_info.c @@ -0,0 +1,98 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_denomination_info.c + * @brief Implementation of the insert_denomination_info function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_denomination_info.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_denomination_info ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue) +{ + struct TALER_DenominationHashP denom_hash; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&issue->denom_hash), + TALER_PQ_query_param_denom_pub (denom_pub), + GNUNET_PQ_query_param_auto_from_type (&issue->signature), + GNUNET_PQ_query_param_timestamp (&issue->start), + GNUNET_PQ_query_param_timestamp (&issue->expire_withdraw), + GNUNET_PQ_query_param_timestamp (&issue->expire_deposit), + GNUNET_PQ_query_param_timestamp (&issue->expire_legal), + TALER_PQ_query_param_amount (pg->conn, + &issue->value), + TALER_PQ_query_param_amount (pg->conn, + &issue->fees.withdraw), + TALER_PQ_query_param_amount (pg->conn, + &issue->fees.deposit), + TALER_PQ_query_param_amount (pg->conn, + &issue->fees.refresh), + TALER_PQ_query_param_amount (pg->conn, + &issue->fees.refund), + GNUNET_PQ_query_param_uint32 (&denom_pub->age_mask.bits), + GNUNET_PQ_query_param_end + }; + + GNUNET_assert (denom_pub->age_mask.bits == + issue->age_mask.bits); + TALER_denom_pub_hash (denom_pub, + &denom_hash); + GNUNET_assert (0 == + GNUNET_memcmp (&denom_hash, + &issue->denom_hash)); + GNUNET_assert (! GNUNET_TIME_absolute_is_zero ( + issue->start.abs_time)); + GNUNET_assert (! GNUNET_TIME_absolute_is_zero ( + issue->expire_withdraw.abs_time)); + GNUNET_assert (! GNUNET_TIME_absolute_is_zero ( + issue->expire_deposit.abs_time)); + GNUNET_assert (! GNUNET_TIME_absolute_is_zero ( + issue->expire_legal.abs_time)); + /* check fees match denomination currency */ + GNUNET_assert (GNUNET_YES == + TALER_denom_fee_check_currency ( + issue->value.currency, + &issue->fees)); + PREPARE (pg, + "denomination_insert", + "INSERT INTO denominations " + "(denom_pub_hash" + ",denom_pub" + ",master_sig" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin" /* value of this denom */ + ",fee_withdraw" + ",fee_deposit" + ",fee_refresh" + ",fee_refund" + ",age_mask" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," + " $11, $12, $13);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "denomination_insert", + params); +} diff --git a/src/exchangedb/insert_denomination_revocation.c b/src/exchangedb/insert_denomination_revocation.c @@ -0,0 +1,50 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_denomination_revocation.c + * @brief Implementation of the insert_denomination_revocation function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_denomination_revocation.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_denomination_revocation ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_DenominationHashP *denom_pub_hash, + const struct TALER_MasterSignatureP *master_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_end + }; + + /* Used in #postgres_insert_denomination_revocation() */ + PREPARE (pg, + "denomination_revocation_insert", + "INSERT INTO denomination_revocations " + "(denominations_serial" + ",master_sig" + ") SELECT denominations_serial,$2" + " FROM denominations" + " WHERE denom_pub_hash=$1;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "denomination_revocation_insert", + params); +} diff --git a/src/exchangedb/insert_drain_profit.c b/src/exchangedb/insert_drain_profit.c @@ -0,0 +1,60 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_drain_profit.c + * @brief Implementation of the insert_drain_profit function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_drain_profit.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_drain_profit ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_WireTransferIdentifierRawP *wtid, + const char *account_section, + const struct TALER_FullPayto payto_uri, + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_Amount *amount, + const struct TALER_MasterSignatureP *master_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_string (account_section), + GNUNET_PQ_query_param_string (payto_uri.full_payto), + GNUNET_PQ_query_param_timestamp (&request_timestamp), + TALER_PQ_query_param_amount (pg->conn, + amount), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "drain_profit_insert", + "INSERT INTO profit_drains " + "(wtid" + ",account_section" + ",payto_uri" + ",trigger_date" + ",amount" + ",master_sig" + ") VALUES ($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "drain_profit_insert", + params); +} diff --git a/src/exchangedb/insert_global_fee.c b/src/exchangedb/insert_global_fee.c @@ -0,0 +1,137 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_global_fee.c + * @brief Implementation of the insert_global_fee function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_dbevents.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_global_fee.h" +#include "helper.h" +#include "taler/exchange-database/get_global_fee.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative + history_expiration, + uint32_t purse_account_limit, + const struct TALER_MasterSignatureP * + master_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_timestamp (&end_date), + TALER_PQ_query_param_amount (pg->conn, + &fees->history), + TALER_PQ_query_param_amount (pg->conn, + &fees->account), + TALER_PQ_query_param_amount (pg->conn, + &fees->purse), + GNUNET_PQ_query_param_relative_time (&purse_timeout), + GNUNET_PQ_query_param_relative_time (&history_expiration), + GNUNET_PQ_query_param_uint32 (&purse_account_limit), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_end + }; + struct TALER_GlobalFeeSet wx; + struct TALER_MasterSignatureP sig; + struct GNUNET_TIME_Timestamp sd; + struct GNUNET_TIME_Timestamp ed; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_TIME_Relative pt; + struct GNUNET_TIME_Relative he; + uint32_t pal; + + qs = TALER_EXCHANGEDB_get_global_fee (pg, + start_date, + &sd, + &ed, + &wx, + &pt, + &he, + &pal, + &sig); + if (qs < 0) + return qs; + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + if (0 != GNUNET_memcmp (&sig, + master_sig)) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (0 != + TALER_global_fee_set_cmp (fees, + &wx)) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if ( (GNUNET_TIME_timestamp_cmp (sd, + !=, + start_date)) || + (GNUNET_TIME_timestamp_cmp (ed, + !=, + end_date)) ) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if ( (GNUNET_TIME_relative_cmp (purse_timeout, + !=, + pt)) || + (GNUNET_TIME_relative_cmp (history_expiration, + !=, + he)) ) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (purse_account_limit != pal) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + /* equal record already exists */ + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + + /* Used in #postgres_insert_global_fee */ + PREPARE (pg, + "insert_global_fee", + "INSERT INTO global_fee " + "(start_date" + ",end_date" + ",history_fee" + ",account_fee" + ",purse_fee" + ",purse_timeout" + ",history_expiration" + ",purse_account_limit" + ",master_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_global_fee", + params); +} diff --git a/src/exchangedb/insert_kyc_failure.c b/src/exchangedb/insert_kyc_failure.c @@ -0,0 +1,90 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/insert_kyc_failure.c + * @brief Implementation of the insert_kyc_failure function for Postgres + * @author Christian Grothoff + */ +#include "taler/platform.h" /* UNNECESSARY? */ +#include "taler/taler_error_codes.h" +#include "taler/taler_dbevents.h" /* UNNECESSARY? */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_kyc_failure.h" +#include "helper.h" +#include "taler/exchange-database/event_notify.h" /* UNNECESSARY? */ + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_kyc_failure ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t process_row, + const struct TALER_NormalizedPaytoHashP *h_payto, + const char *provider_name, + const char *provider_account_id, + const char *provider_legitimization_id, + const char *error_message, + enum TALER_ErrorCode ec) +{ + uint32_t ec32 = (uint32_t) ec; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&process_row), + GNUNET_PQ_query_param_auto_from_type (h_payto), + NULL != provider_name + ? GNUNET_PQ_query_param_string (provider_name) + : GNUNET_PQ_query_param_null (), + NULL != provider_account_id + ? GNUNET_PQ_query_param_string (provider_account_id) + : GNUNET_PQ_query_param_null (), + NULL != provider_legitimization_id + ? GNUNET_PQ_query_param_string (provider_legitimization_id) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_uint32 (&ec32), + GNUNET_PQ_query_param_string (error_message), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "insert_kyc_failure", + "UPDATE legitimization_processes" + " SET" + " finished=TRUE" + " ,provider_user_id=$4" + " ,provider_legitimization_id=$5" + " ,error_code=$6" + " ,error_message=$7" + " WHERE h_payto=$2" + " AND legitimization_process_serial_id=$1" + " AND provider_name=$3;"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_kyc_failure", + params); + if (qs > 0) + { + /* FIXME-#9419: might want to do this eventually in the same transaction... */ + struct TALER_EXCHANGEDB_KycCompletedEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), + .h_payto = *h_payto + }; + + TALER_EXCHANGEDB_event_notify (pg, + &rep.header, + NULL, + 0); + } + return qs; +} diff --git a/src/exchangedb/insert_kyc_requirement_process.c b/src/exchangedb/insert_kyc_requirement_process.c @@ -0,0 +1,85 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_kyc_requirement_process.c + * @brief Implementation of the insert_kyc_requirement_process function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_kyc_requirement_process.h" +#include "helper.h" +#include <gnunet/gnunet_pq_lib.h> + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_kyc_requirement_process ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + uint32_t measure_index, + uint64_t legitimization_measure_serial_id, + const char *provider_name, + const char *provider_account_id, + const char *provider_legitimization_id, + uint64_t *process_row) +{ + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_string (provider_name), + (NULL != provider_account_id) + ? GNUNET_PQ_query_param_string (provider_account_id) + : GNUNET_PQ_query_param_null (), + (NULL != provider_legitimization_id) + ? GNUNET_PQ_query_param_string (provider_legitimization_id) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id), + GNUNET_PQ_query_param_uint32 (&measure_index), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("legitimization_process_serial_id", + process_row), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "insert_kyc_requirement_process", + "INSERT INTO legitimization_processes" + " (h_payto" + " ,start_time" + " ,provider_name" + " ,provider_user_id" + " ,provider_legitimization_id" + " ,legitimization_measure_serial_id" + " ,measure_index" + " ) VALUES " + " ($1, $2, $3, $4, $5, $6, $7)" + " ON CONFLICT (legitimization_measure_serial_id,measure_index)" + " DO UPDATE" + " SET h_payto=$1" + " ,start_time=$2" + " ,provider_name=$3" + " ,provider_user_id=$4" + " ,provider_legitimization_id=$5" + " RETURNING legitimization_process_serial_id"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "insert_kyc_requirement_process", + params, + rs); +} diff --git a/src/exchangedb/insert_partner.c b/src/exchangedb/insert_partner.c @@ -0,0 +1,67 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_partner.c + * @brief Implementation of the insert_partner function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_partner.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_partner (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_MasterPublicKeyP *master_pub + , + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + struct GNUNET_TIME_Relative wad_frequency, + const struct TALER_Amount *wad_fee, + const char *partner_base_url, + const struct TALER_MasterSignatureP *master_sig + ) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (master_pub), + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_timestamp (&end_date), + GNUNET_PQ_query_param_relative_time (&wad_frequency), + TALER_PQ_query_param_amount (pg->conn, + wad_fee), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_string (partner_base_url), + GNUNET_PQ_query_param_end + }; + + + PREPARE (pg, + "insert_partner", + "INSERT INTO partners" + " (partner_master_pub" + " ,start_date" + " ,end_date" + " ,wad_frequency" + " ,wad_fee" + " ,master_sig" + " ,partner_base_url" + " ) VALUES " + " ($1, $2, $3, $4, $5, $6, $7)" + " ON CONFLICT DO NOTHING;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_partner", + params); +} diff --git a/src/exchangedb/insert_purse_request.c b/src/exchangedb/insert_purse_request.c @@ -0,0 +1,122 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_purse_request.c + * @brief Implementation of the insert_purse_request function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_purse_request.h" +#include "taler/exchange-database/get_purse_request.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_purse_request ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePublicKeyP *merge_pub, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t age_limit, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_Amount *purse_fee, + const struct TALER_Amount *amount, + const struct TALER_PurseContractSignatureP *purse_sig, + bool *in_conflict) +{ + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get (); + uint32_t flags32 = (uint32_t) flags; + bool in_reserve_quota = (TALER_WAMF_MODE_CREATE_FROM_PURSE_QUOTA + == (flags & TALER_WAMF_MERGE_MODE_MASK)); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_auto_from_type (merge_pub), + GNUNET_PQ_query_param_timestamp (&now), + GNUNET_PQ_query_param_timestamp (&purse_expiration), + GNUNET_PQ_query_param_auto_from_type (h_contract_terms), + GNUNET_PQ_query_param_uint32 (&age_limit), + GNUNET_PQ_query_param_uint32 (&flags32), + GNUNET_PQ_query_param_bool (in_reserve_quota), + TALER_PQ_query_param_amount (pg->conn, + amount), + TALER_PQ_query_param_amount (pg->conn, + purse_fee), + GNUNET_PQ_query_param_auto_from_type (purse_sig), + GNUNET_PQ_query_param_end + }; + + *in_conflict = false; + PREPARE (pg, + "insert_purse_request", + "INSERT INTO purse_requests" + " (purse_pub" + " ,merge_pub" + " ,purse_creation" + " ,purse_expiration" + " ,h_contract_terms" + " ,age_limit" + " ,flags" + " ,in_reserve_quota" + " ,amount_with_fee" + " ,purse_fee" + " ,purse_sig" + " ) VALUES " + " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)" + " ON CONFLICT DO NOTHING;"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_purse_request", + params); + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs) + return qs; + { + struct TALER_PurseMergePublicKeyP merge_pub2; + struct GNUNET_TIME_Timestamp purse_expiration2; + struct TALER_PrivateContractHashP h_contract_terms2; + uint32_t age_limit2; + struct TALER_Amount amount2; + struct TALER_Amount balance; + struct TALER_PurseContractSignatureP purse_sig2; + + qs = TALER_EXCHANGEDB_get_purse_request (pg, + purse_pub, + &merge_pub2, + &purse_expiration2, + &h_contract_terms2, + &age_limit2, + &amount2, + &balance, + &purse_sig2); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if ( (age_limit2 == age_limit) && + (0 == TALER_amount_cmp (amount, + &amount2)) && + (0 == GNUNET_memcmp (&h_contract_terms2, + h_contract_terms)) && + (0 == GNUNET_memcmp (&merge_pub2, + merge_pub)) ) + { + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + *in_conflict = true; + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } +} diff --git a/src/exchangedb/insert_records_by_table.c b/src/exchangedb/insert_records_by_table.c @@ -0,0 +1,2453 @@ +/* + This file is part of GNUnet + Copyright (C) 2020-2025 Taler Systems SA + + GNUnet 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 Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/** + * @file exchangedb/insert_records_by_table.c + * @brief replicate_records_by_table implementation + * @author Christian Grothoff + * @author Özgür Kesim + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_dbevents.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_records_by_table.h" +#include "helper.h" +#include <gnunet/gnunet_pq_lib.h> + + +/** + * Signature of helper functions of #TALER_EXCHANGEDB_insert_records_by_table(). + * + * @param pg plugin context + * @param td record to insert + * @return transaction status code + */ +typedef enum GNUNET_DB_QueryStatus +(*InsertRecordCallback)(struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td); + + +/** + * Function called with denominations records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_denominations (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct TALER_DenominationHashP denom_hash; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type (&denom_hash), + GNUNET_PQ_query_param_uint32 ( + &td->details.denominations.denom_type), + GNUNET_PQ_query_param_uint32 ( + &td->details.denominations.age_mask), + TALER_PQ_query_param_denom_pub ( + &td->details.denominations.denom_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.denominations.master_sig), + GNUNET_PQ_query_param_timestamp ( + &td->details.denominations.valid_from), + GNUNET_PQ_query_param_timestamp ( + &td->details.denominations.expire_withdraw), + GNUNET_PQ_query_param_timestamp ( + &td->details.denominations.expire_deposit), + GNUNET_PQ_query_param_timestamp ( + &td->details.denominations.expire_legal), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.denominations.coin), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.denominations.fees.withdraw), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.denominations.fees.deposit), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.denominations.fees.refresh), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.denominations.fees.refund), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_denominations", + "INSERT INTO denominations" + "(denominations_serial" + ",denom_pub_hash" + ",denom_type" + ",age_mask" + ",denom_pub" + ",master_sig" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin" + ",fee_withdraw" + ",fee_deposit" + ",fee_refresh" + ",fee_refund" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," + " $11, $12, $13, $14, $15);"); + + TALER_denom_pub_hash ( + &td->details.denominations.denom_pub, + &denom_hash); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_denominations", + params); +} + + +/** + * Function called with denomination_revocations records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_denomination_revocations ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.denomination_revocations.master_sig), + GNUNET_PQ_query_param_uint64 ( + &td->details.denomination_revocations.denominations_serial), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_denomination_revocations", + "INSERT INTO denomination_revocations" + "(denom_revocations_serial_id" + ",master_sig" + ",denominations_serial" + ") VALUES " + "($1, $2, $3);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_denomination_revocations", + params); +} + + +/** + * Function called with wire target records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_wire_targets (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct TALER_NormalizedPaytoHashP normalized_payto_hash; + struct TALER_FullPaytoHashP full_payto_hash; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type (&full_payto_hash), + GNUNET_PQ_query_param_auto_from_type (&normalized_payto_hash), + GNUNET_PQ_query_param_string ( + td->details.wire_targets.full_payto_uri.full_payto), + GNUNET_PQ_query_param_end + }; + + TALER_full_payto_hash ( + td->details.wire_targets.full_payto_uri, + &full_payto_hash); + TALER_full_payto_normalize_and_hash ( + td->details.wire_targets.full_payto_uri, + &normalized_payto_hash); + PREPARE (pg, + "insert_into_table_wire_targets", + "INSERT INTO wire_targets" + "(wire_target_serial_id" + ",wire_target_h_payto" + ",h_normalized_payto" + ",payto_uri" + ") VALUES " + "($1, $2, $3, $4);"); + return GNUNET_PQ_eval_prepared_non_select ( + pg->conn, + "insert_into_table_wire_targets", + params); +} + + +/** + * Function called with kyc target records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_kyc_targets (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.kyc_targets.h_normalized_payto), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.kyc_targets.access_token), + td->details.kyc_targets.no_account + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type ( + &td->details.kyc_targets.target_pub), + GNUNET_PQ_query_param_bool ( + td->details.kyc_targets.is_wallet), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_kyc_targets", + "INSERT INTO kyc_targets" + "(kyc_target_serial_id" + ",h_normalized_payto" + ",access_token" + ",target_pub" + ",is_wallet" + ") VALUES " + "($1, $2, $3, $4, $5);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_kyc_targets", + params); +} + + +/** + * Function called with records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_legitimization_measures ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.legitimization_measures.target_token), + GNUNET_PQ_query_param_timestamp ( + &td->details.legitimization_measures.start_time), + TALER_PQ_query_param_json ( + td->details.legitimization_measures.measures), + GNUNET_PQ_query_param_uint32 ( + &td->details.legitimization_measures.display_priority), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_legitimization_measures", + "INSERT INTO legitimization_measures" + "(legitimization_measure_serial_id" + ",access_token" + ",start_time" + ",jmeasures" + ",display_priority" + ") VALUES " + "($1, $2, $3, $4::TEXT::JSONB, $5);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_legitimization_measures", + params); +} + + +/** + * Function called with records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_legitimization_outcomes ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.legitimization_outcomes.h_payto), + GNUNET_PQ_query_param_timestamp ( + &td->details.legitimization_outcomes.decision_time), + GNUNET_PQ_query_param_timestamp ( + &td->details.legitimization_outcomes.expiration_time), + TALER_PQ_query_param_json ( + td->details.legitimization_outcomes.properties), + GNUNET_PQ_query_param_bool ( + td->details.legitimization_outcomes.to_investigate), + TALER_PQ_query_param_json ( + td->details.legitimization_outcomes.new_rules), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_legitimization_outcomes", + "INSERT INTO legitimization_outcomes" + "(outcome_serial_id" + ",h_payto" + ",decision_time" + ",expiration_time" + ",jproperties" + ",to_investigate" + ",jnew_rules" + ") VALUES " + "($1, $2, $3, $4, $5::TEXT::JSONB, $6, $7::TEXT::JSONB);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_legitimization_outcomes", + params); +} + + +/** + * Function called with records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_legitimization_processes ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.legitimization_processes.h_payto), + GNUNET_PQ_query_param_timestamp ( + &td->details.legitimization_processes.start_time), + GNUNET_PQ_query_param_timestamp ( + &td->details.legitimization_processes.expiration_time), + GNUNET_PQ_query_param_uint64 ( + &td->details.legitimization_processes.legitimization_measure_serial_id), + GNUNET_PQ_query_param_uint32 ( + &td->details.legitimization_processes.measure_index), + GNUNET_PQ_query_param_string ( + td->details.legitimization_processes.provider_name), + GNUNET_PQ_query_param_string ( + td->details.legitimization_processes.provider_user_id), + GNUNET_PQ_query_param_string ( + td->details.legitimization_processes.provider_legitimization_id), + GNUNET_PQ_query_param_string ( + td->details.legitimization_processes.redirect_url), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_legitimization_processes", + "INSERT INTO legitimization_processes" + "(legitimization_process_serial_id" + ",h_payto" + ",start_time" + ",expiration_time" + ",legitimization_measure_serial_id" + ",measure_index" + ",provider_name" + ",provider_user_id" + ",provider_legitimization_id" + ",redirect_url" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_legitimization_processes", + params); +} + + +/** + * Function called with reserves records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_reserves (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type (&td->details.reserves.reserve_pub), + GNUNET_PQ_query_param_timestamp (&td->details.reserves.expiration_date), + GNUNET_PQ_query_param_timestamp (&td->details.reserves.gc_date), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_reserves", + "INSERT INTO reserves" + "(reserve_uuid" + ",reserve_pub" + ",expiration_date" + ",gc_date" + ") VALUES " + "($1, $2, $3, $4);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_reserves", + params); +} + + +/** + * Function called with reserves_in records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_reserves_in (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_uint64 (&td->details.reserves_in.wire_reference), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.reserves_in.credit), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.reserves_in.sender_account_h_payto), + GNUNET_PQ_query_param_string ( + td->details.reserves_in.exchange_account_section), + GNUNET_PQ_query_param_timestamp ( + &td->details.reserves_in.execution_date), + GNUNET_PQ_query_param_auto_from_type (&td->details.reserves_in.reserve_pub), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_reserves_in", + "INSERT INTO reserves_in" + "(reserve_in_serial_id" + ",wire_reference" + ",credit" + ",wire_source_h_payto" + ",exchange_account_section" + ",execution_date" + ",reserve_pub" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_reserves_in", + params); +} + + +/** + * Function called with kycauth_in records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_kycauths_in (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_uint64 (&td->details.kycauth_in.wire_reference), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.reserves_in.credit), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.reserves_in.sender_account_h_payto), + GNUNET_PQ_query_param_string ( + td->details.reserves_in.exchange_account_section), + GNUNET_PQ_query_param_timestamp ( + &td->details.reserves_in.execution_date), + GNUNET_PQ_query_param_auto_from_type (&td->details.kycauth_in.account_pub), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_kycauth_in", + "INSERT INTO kycauths_in" + "(kycauth_in_serial_id" + ",wire_reference" + ",credit" + ",wire_source_h_payto" + ",exchange_account_section" + ",execution_date" + ",account_pub" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_kycauth_in", + params); +} + + +/** + * Function called with reserves_open_requests records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_reserves_open_requests (struct TALER_EXCHANGEDB_PostgresContext * + pg, + const struct + TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_timestamp ( + &td->details.reserves_open_requests.expiration_date), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.reserves_open_requests.reserve_sig), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.reserves_open_requests.reserve_payment), + GNUNET_PQ_query_param_uint32 ( + &td->details.reserves_open_requests.requested_purse_limit), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_reserves_open_requests", + "INSERT INTO reserves_open_requests" + "(open_request_uuid" + ",reserve_pub" + ",request_timestamp" + ",expiration_date" + ",reserve_sig" + ",reserve_payment" + ",requested_purse_limit" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_reserves_open_requests", + params); +} + + +/** + * Function called with reserves_open_requests records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_reserves_open_deposits ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.reserves_open_deposits.coin_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.reserves_open_deposits.coin_sig), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.reserves_open_deposits.reserve_sig), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.reserves_open_deposits.contribution), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_reserves_open_deposits", + "INSERT INTO reserves_open_deposits" + "(reserve_open_deposit_uuid" + ",reserve_sig" + ",reserve_pub" + ",coin_pub" + ",coin_sig" + ",contribution" + ") VALUES " + "($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_reserves_open_deposits", + params); +} + + +/** + * Function called with reserves_close records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_reserves_close (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_timestamp ( + &td->details.reserves_close.execution_date), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.reserves_close.wtid), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.reserves_close.sender_account_h_payto), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.reserves_close.amount), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.reserves_close.closing_fee), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.reserves_close.reserve_pub), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_reserves_close", + "INSERT INTO reserves_close" + "(close_uuid" + ",execution_date" + ",wtid" + ",wire_target_h_payto" + ",amount" + ",closing_fee" + ",reserve_pub" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_reserves_close", + params); +} + + +/** + * Function called with auditors records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_auditors (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type (&td->details.auditors.auditor_pub), + GNUNET_PQ_query_param_string (td->details.auditors.auditor_name), + GNUNET_PQ_query_param_string (td->details.auditors.auditor_url), + GNUNET_PQ_query_param_bool (td->details.auditors.is_active), + GNUNET_PQ_query_param_timestamp (&td->details.auditors.last_change), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_auditors", + "INSERT INTO auditors" + "(auditor_uuid" + ",auditor_pub" + ",auditor_name" + ",auditor_url" + ",is_active" + ",last_change" + ") VALUES " + "($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_auditors", + params); +} + + +/** + * Function called with auditor_denom_sigs records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_auditor_denom_sigs (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_uint64 (&td->details.auditor_denom_sigs.auditor_uuid), + GNUNET_PQ_query_param_uint64 ( + &td->details.auditor_denom_sigs.denominations_serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.auditor_denom_sigs.auditor_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_auditor_denom_sigs", + "INSERT INTO auditor_denom_sigs" + "(auditor_denom_serial" + ",auditor_uuid" + ",denominations_serial" + ",auditor_sig" + ") VALUES " + "($1, $2, $3, $4);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_auditor_denom_sigs", + params); +} + + +/** + * Function called with exchange_sign_keys records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_exchange_sign_keys (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.exchange_sign_keys.exchange_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.exchange_sign_keys.master_sig), + GNUNET_PQ_query_param_timestamp ( + &td->details.exchange_sign_keys.meta.start), + GNUNET_PQ_query_param_timestamp ( + &td->details.exchange_sign_keys.meta.expire_sign), + GNUNET_PQ_query_param_timestamp ( + &td->details.exchange_sign_keys.meta.expire_legal), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_exchange_sign_keys", + "INSERT INTO exchange_sign_keys" + "(esk_serial" + ",exchange_pub" + ",master_sig" + ",valid_from" + ",expire_sign" + ",expire_legal" + ") VALUES " + "($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_exchange_sign_keys", + params); +} + + +/** + * Function called with signkey_revocations records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_signkey_revocations (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_uint64 (&td->details.signkey_revocations.esk_serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.signkey_revocations.master_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_signkey_revocations", + "INSERT INTO signkey_revocations" + "(signkey_revocations_serial_id" + ",esk_serial" + ",master_sig" + ") VALUES " + "($1, $2, $3);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_signkey_revocations", + params); +} + + +/** + * Function called with known_coins records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_known_coins (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.known_coins.coin_pub), + TALER_PQ_query_param_denom_sig ( + &td->details.known_coins.denom_sig), + GNUNET_PQ_query_param_uint64 ( + &td->details.known_coins.denominations_serial), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_known_coins", + "INSERT INTO known_coins" + "(known_coin_id" + ",coin_pub" + ",denom_sig" + ",denominations_serial" + ") VALUES " + "($1, $2, $3, $4);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_known_coins", + params); +} + + +/** + * Function called with refresh records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type (&td->details.refresh.rc), + GNUNET_PQ_query_param_auto_from_type (&td->details.refresh.execution_date), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.refresh.amount_with_fee), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.refresh.old_coin_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.refresh.old_coin_sig), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.refresh.refresh_seed), + GNUNET_PQ_query_param_uint32 ( + &td->details.refresh.noreveal_index), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.refresh.planchets_h), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.refresh.selected_h), + td->details.refresh.no_blinding_seed + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type ( + &td->details.refresh.blinding_seed), + td->details.refresh.no_blinding_seed + ? GNUNET_PQ_query_param_null () + : TALER_PQ_query_param_array_cs_r_pub ( + td->details.refresh.num_cs_r_values, + td->details.refresh.cs_r_values, + pg->conn), + td->details.refresh.no_blinding_seed + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 ( + &td->details.refresh.cs_r_choices), + GNUNET_PQ_query_param_array_uint64 ( + td->details.refresh.num_coins, + td->details.refresh.denom_serials, + pg->conn), + TALER_PQ_query_param_array_blinded_denom_sig ( + td->details.refresh.num_coins, + td->details.refresh.denom_sigs, + pg->conn), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_refresh", + "INSERT INTO refresh" + "(refresh_id" + ",rc" + ",execution_date" + ",amount_with_fee" + ",old_coin_pub" + ",old_coin_sig" + ",refresh_seed" + ",noreveal_index" + ",planchets_h" + ",selected_h" + ",blinding_seed" + ",cs_r_values" + ",cs_r_choices" + ",denom_serials" + ",denom_sigs" + ") VALUES " + "($1, $2, $3, $4, $5, $6,$7,$8,$9,$10,$11,$12,$13,$14,$15);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_refresh", + params); +} + + +/** + * Function called with batch deposits records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_batch_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_uint64 (&td->details.batch_deposits.shard), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.batch_deposits.merchant_pub), + GNUNET_PQ_query_param_timestamp ( + &td->details.batch_deposits.wallet_timestamp), + GNUNET_PQ_query_param_timestamp ( + &td->details.batch_deposits.exchange_timestamp), + GNUNET_PQ_query_param_timestamp ( + &td->details.batch_deposits.refund_deadline), + GNUNET_PQ_query_param_timestamp (&td->details.batch_deposits.wire_deadline), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.batch_deposits.h_contract_terms), + td->details.batch_deposits.no_wallet_data_hash + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type ( + &td->details.batch_deposits.wallet_data_hash), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.batch_deposits.wire_salt), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.batch_deposits.wire_target_h_payto), + td->details.batch_deposits.no_policy_details + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 ( + &td->details.batch_deposits.policy_details_serial_id), + GNUNET_PQ_query_param_bool (td->details.batch_deposits.policy_blocked), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.batch_deposits.total_amount), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.batch_deposits.total_without_fee), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.batch_deposits.merchant_sig), + GNUNET_PQ_query_param_bool (td->details.batch_deposits.done), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_batch_deposits", + "INSERT INTO batch_deposits" + "(batch_deposit_serial_id" + ",shard" + ",merchant_pub" + ",wallet_timestamp" + ",exchange_timestamp" + ",refund_deadline" + ",wire_deadline" + ",h_contract_terms" + ",wallet_data_hash" + ",wire_salt" + ",wire_target_h_payto" + ",policy_details_serial_id" + ",policy_blocked" + ",total_amount" + ",total_without_fee" + ",merchant_sig" + ",done" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," + " $11, $12, $13, $14, $15, $16, $17);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_batch_deposits", + params); +} + + +/** + * Function called with deposits records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_coin_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_uint64 ( + &td->details.coin_deposits.batch_deposit_serial_id), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.coin_deposits.coin_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.coin_deposits.coin_sig), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.coin_deposits.amount_with_fee), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_coin_deposits", + "INSERT INTO coin_deposits" + "(coin_deposit_serial_id" + ",batch_deposit_serial_id" + ",coin_pub" + ",coin_sig" + ",amount_with_fee" + ") VALUES " + "($1, $2, $3, $4, $5);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_coin_deposits", + params); +} + + +/** + * Function called with refunds records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_refunds (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type (&td->details.refunds.coin_pub), + GNUNET_PQ_query_param_auto_from_type (&td->details.refunds.merchant_sig), + GNUNET_PQ_query_param_uint64 (&td->details.refunds.rtransaction_id), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.refunds.amount_with_fee), + GNUNET_PQ_query_param_uint64 ( + &td->details.refunds.batch_deposit_serial_id), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_refunds", + "INSERT INTO refunds" + "(refund_serial_id" + ",coin_pub" + ",merchant_sig" + ",rtransaction_id" + ",amount_with_fee" + ",batch_deposit_serial_id" + ") VALUES " + "($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_refunds", + params); +} + + +/** + * Function called with wire_out records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_wire_out (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_timestamp (&td->details.wire_out.execution_date), + GNUNET_PQ_query_param_auto_from_type (&td->details.wire_out.wtid_raw), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.wire_out.wire_target_h_payto), + GNUNET_PQ_query_param_string ( + td->details.wire_out.exchange_account_section), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.wire_out.amount), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_wire_out", + "INSERT INTO wire_out" + "(wireout_uuid" + ",execution_date" + ",wtid_raw" + ",wire_target_h_payto" + ",exchange_account_section" + ",amount" + ") VALUES " + "($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_wire_out", + params); +} + + +/** + * Function called with aggregation_tracking records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_aggregation_tracking (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_uint64 ( + &td->details.aggregation_tracking.batch_deposit_serial_id), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.aggregation_tracking.wtid_raw), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_aggregation_tracking", + "INSERT INTO aggregation_tracking" + "(aggregation_serial_id" + ",batch_deposit_serial_id" + ",wtid_raw" + ") VALUES " + "($1, $2, $3);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_aggregation_tracking", + params); +} + + +/** + * Function called with wire_fee records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_wire_fee (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_string (td->details.wire_fee.wire_method), + GNUNET_PQ_query_param_timestamp (&td->details.wire_fee.start_date), + GNUNET_PQ_query_param_timestamp (&td->details.wire_fee.end_date), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.wire_fee.fees.wire), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.wire_fee.fees.closing), + GNUNET_PQ_query_param_auto_from_type (&td->details.wire_fee.master_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_wire_fee", + "INSERT INTO wire_fee" + "(wire_fee_serial" + ",wire_method" + ",start_date" + ",end_date" + ",wire_fee" + ",closing_fee" + ",master_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_wire_fee", + params); +} + + +/** + * Function called with wire_fee records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 ( + &td->serial), + GNUNET_PQ_query_param_timestamp ( + &td->details.global_fee.start_date), + GNUNET_PQ_query_param_timestamp ( + &td->details.global_fee.end_date), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.global_fee.fees.history), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.global_fee.fees.account), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.global_fee.fees.purse), + GNUNET_PQ_query_param_relative_time ( + &td->details.global_fee.purse_timeout), + GNUNET_PQ_query_param_relative_time ( + &td->details.global_fee.history_expiration), + GNUNET_PQ_query_param_uint32 ( + &td->details.global_fee.purse_account_limit), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.global_fee.master_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_global_fee", + "INSERT INTO global_fee" + "(global_fee_serial" + ",start_date" + ",end_date" + ",history_fee" + ",account_fee" + ",purse_fee" + ",purse_timeout" + ",history_expiration" + ",purse_account_limit" + ",master_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_global_fee", + params); +} + + +/** + * Function called with recoup records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_recoup (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type (&td->details.recoup.coin_sig), + GNUNET_PQ_query_param_auto_from_type (&td->details.recoup.coin_blind), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.recoup.amount), + GNUNET_PQ_query_param_timestamp (&td->details.recoup.timestamp), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.recoup.coin_pub), + GNUNET_PQ_query_param_uint64 (&td->details.recoup.withdraw_serial_id), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_recoup", + "INSERT INTO recoup" + "(recoup_uuid" + ",coin_sig" + ",coin_blind" + ",amount" + ",recoup_timestamp" + ",coin_pub" + ",withdraw_serial_id" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_recoup", + params); +} + + +/** + * Function called with recoup_refresh records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_recoup_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type (&td->details.recoup_refresh.coin_sig), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.recoup_refresh.coin_blind), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.recoup_refresh.amount), + GNUNET_PQ_query_param_timestamp (&td->details.recoup_refresh.timestamp), + GNUNET_PQ_query_param_uint64 (&td->details.recoup_refresh.known_coin_id), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.recoup.coin_pub), + GNUNET_PQ_query_param_uint64 (&td->details.recoup_refresh.rrc_serial), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_recoup_refresh", + "INSERT INTO recoup_refresh" + "(recoup_refresh_uuid" + ",coin_sig" + ",coin_blind" + ",amount" + ",recoup_timestamp" + ",known_coin_id" + ",coin_pub" + ",rrc_serial" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_recoup_refresh", + params); +} + + +/** + * Function called with extensions records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_extensions (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_string (td->details.extensions.name), + NULL == td->details.extensions.manifest ? + GNUNET_PQ_query_param_null () : + GNUNET_PQ_query_param_string (td->details.extensions.manifest), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_extensions", + "INSERT INTO extensions" + "(extension_id" + ",name" + ",manifest" + ") VALUES " + "($1, $2, $3);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_extensions", + params); +} + + +/** + * Function called with policy_details records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_policy_details (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.policy_details.hash_code), + (td->details.policy_details.no_policy_json) + ? GNUNET_PQ_query_param_null () + : TALER_PQ_query_param_json (td->details.policy_details.policy_json), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.policy_details.commitment), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.policy_details.accumulated_total), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.policy_details.fee), + TALER_PQ_query_param_amount (pg->conn, + &td->details.policy_details.transferable), + GNUNET_PQ_query_param_timestamp (&td->details.policy_details.deadline), + GNUNET_PQ_query_param_uint16 ( + &td->details.policy_details.fulfillment_state), + (td->details.policy_details.no_fulfillment_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 ( + &td->details.policy_details.fulfillment_id), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_policy_details", + "INSERT INTO policy_details" + "(policy_details_serial_id" + ",policy_hash_code" + ",policy_json" + ",deadline" + ",commitment" + ",accumulated_total" + ",fee" + ",transferable" + ",fulfillment_state" + ",fulfillment_id" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_policy_details", + params); +} + + +/** + * Function called with policy_fulfillment records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_policy_fulfillments (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_timestamp ( + &td->details.policy_fulfillments.fulfillment_timestamp), + (NULL == td->details.policy_fulfillments.fulfillment_proof) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string ( + td->details.policy_fulfillments.fulfillment_proof), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.policy_fulfillments.h_fulfillment_proof), + GNUNET_PQ_query_param_fixed_size ( + td->details.policy_fulfillments.policy_hash_codes, + td->details.policy_fulfillments.policy_hash_codes_count), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_policy_fulfillments", + "INSERT INTO policy_fulfillments " + "(fulfillment_id" + ",fulfillment_timestamp" + ",fulfillment_proof" + ",h_fulfillment_proof" + ",policy_hash_codes" + ") VALUES " + "($1, $2, $3::TEXT::JSONB, $4, $5);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_policy_fulfillments", + params); +} + + +/** + * Function called with purse_requests records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_purse_requests (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.purse_requests.purse_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.purse_requests.merge_pub), + GNUNET_PQ_query_param_timestamp ( + &td->details.purse_requests.purse_creation), + GNUNET_PQ_query_param_timestamp ( + &td->details.purse_requests.purse_expiration), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.purse_requests.h_contract_terms), + GNUNET_PQ_query_param_uint32 (&td->details.purse_requests.age_limit), + GNUNET_PQ_query_param_uint32 (&td->details.purse_requests.flags), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.purse_requests.amount_with_fee), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.purse_requests.purse_fee), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.purse_requests.purse_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_purse_requests", + "INSERT INTO purse_requests" + "(purse_requests_serial_id" + ",purse_pub" + ",merge_pub" + ",purse_creation" + ",purse_expiration" + ",h_contract_terms" + ",age_limit" + ",flags" + ",amount_with_fee" + ",purse_fee" + ",purse_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_purse_requests", + params); +} + + +/** + * Function called with purse_decision records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_purse_decision (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.purse_decision.purse_pub), + GNUNET_PQ_query_param_timestamp ( + &td->details.purse_decision.action_timestamp), + GNUNET_PQ_query_param_bool ( + td->details.purse_decision.refunded), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_purse_refunds", + "INSERT INTO purse_refunds" + "(purse_refunds_serial_id" + ",purse_pub" + ",action_timestamp" + ",refunded" + ") VALUES " + "($1, $2, $3, $4);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_purse_decision", + params); +} + + +/** + * Function called with purse_merges records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_purse_merges (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_uint64 (&td->details.purse_merges.partner_serial_id), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.purse_merges.reserve_pub), + GNUNET_PQ_query_param_auto_from_type (&td->details.purse_merges.purse_pub), + GNUNET_PQ_query_param_auto_from_type (&td->details.purse_merges.merge_sig), + GNUNET_PQ_query_param_timestamp (&td->details.purse_merges.merge_timestamp), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_purse_merges", + "INSERT INTO purse_merges" + "(purse_merge_request_serial_id" + ",partner_serial_id" + ",reserve_pub" + ",purse_pub" + ",merge_sig" + ",merge_timestamp" + ") VALUES " + "($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_purse_merges", + params); +} + + +/** + * Function called with purse_deposits records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_purse_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_uint64 ( + &td->details.purse_deposits.partner_serial_id), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.purse_deposits.purse_pub), + GNUNET_PQ_query_param_auto_from_type (&td->details.purse_deposits.coin_pub), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.purse_deposits.amount_with_fee), + GNUNET_PQ_query_param_auto_from_type (&td->details.purse_deposits.coin_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_purse_deposits", + "INSERT INTO purse_deposits" + "(purse_deposit_serial_id" + ",partner_serial_id" + ",purse_pub" + ",coin_pub" + ",amount_with_fee" + ",coin_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_purse_deposits", + params); +} + + +/** +x * Function called with account_mergers records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_account_mergers (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.account_merges.reserve_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.account_merges.reserve_sig), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.account_merges.purse_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.account_merges.wallet_h_payto), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_account_merges", + "INSERT INTO account_merges" + "(account_merge_request_serial_id" + ",reserve_pub" + ",reserve_sig" + ",purse_pub" + ",wallet_h_payto" + ") VALUES " + "($1, $2, $3, $4, $5);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_account_merges", + params); +} + + +/** + * Function called with history_requests records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_history_requests (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.history_requests.reserve_pub), + GNUNET_PQ_query_param_timestamp ( + &td->details.history_requests.request_timestamp), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.history_requests.reserve_sig), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.history_requests.history_fee), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_history_requests", + "INSERT INTO history_requests" + "(history_request_serial_id" + ",reserve_pub" + ",request_timestamp" + ",reserve_sig" + ",history_fee" + ") VALUES " + "($1, $2, $3, $4, $5);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_history_requests", + params); +} + + +/** + * Function called with close_requests records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_close_requests (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.close_requests.reserve_pub), + GNUNET_PQ_query_param_timestamp ( + &td->details.close_requests.close_timestamp), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.close_requests.reserve_sig), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.close_requests.close), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.close_requests.close_fee), + GNUNET_PQ_query_param_string ( + td->details.close_requests.payto_uri.full_payto), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_close_requests", + "INSERT INTO close_requests" + "(close_request_serial_id" + ",reserve_pub" + ",close_timestamp" + ",reserve_sig" + ",close" + ",close_fee" + ",payto_uri" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_close_requests", + params); +} + + +/** + * Function called with wads_out records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_wads_out (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type (&td->details.wads_out.wad_id), + GNUNET_PQ_query_param_uint64 (&td->details.wads_out.partner_serial_id), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.wads_out.amount), + GNUNET_PQ_query_param_timestamp (&td->details.wads_out.execution_time), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_wads_out", + "INSERT INTO wads_out" + "(wad_out_serial_id" + ",wad_id" + ",partner_serial_id" + ",amount" + ",execution_time" + ") VALUES " + "($1, $2, $3, $4, $5);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_wads_out", + params); +} + + +/** + * Function called with wads_out_entries records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_wads_out_entries (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_uint64 ( + &td->details.wads_out_entries.wad_out_serial_id), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.wads_out_entries.reserve_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.wads_out_entries.purse_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.wads_out_entries.h_contract), + GNUNET_PQ_query_param_timestamp ( + &td->details.wads_out_entries.purse_expiration), + GNUNET_PQ_query_param_timestamp ( + &td->details.wads_out_entries.merge_timestamp), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.wads_out_entries.amount_with_fee), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.wads_out_entries.wad_fee), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.wads_out_entries.deposit_fees), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.wads_out_entries.reserve_sig), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.wads_out_entries.purse_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_wad_out_entries", + "INSERT INTO wad_out_entries" + "(wad_out_entry_serial_id" + ",wad_out_serial_id" + ",reserve_pub" + ",purse_pub" + ",h_contract" + ",purse_expiration" + ",merge_timestamp" + ",amount_with_fee" + ",wad_fee" + ",deposit_fees" + ",reserve_sig" + ",purse_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_wads_out_entries", + params); +} + + +/** + * Function called with wads_in records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_wads_in (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type (&td->details.wads_in.wad_id), + GNUNET_PQ_query_param_string (td->details.wads_in.origin_exchange_url), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.wads_in.amount), + GNUNET_PQ_query_param_timestamp (&td->details.wads_in.arrival_time), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_wads_in", + "INSERT INTO wads_in" + "(wad_in_serial_id" + ",wad_id" + ",origin_exchange_url" + ",amount" + ",arrival_time" + ") VALUES " + "($1, $2, $3, $4, $5);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_wads_in", + params); +} + + +/** + * Function called with wads_in_entries records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_wads_in_entries (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.wads_in_entries.reserve_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.wads_in_entries.purse_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.wads_in_entries.h_contract), + GNUNET_PQ_query_param_timestamp ( + &td->details.wads_in_entries.purse_expiration), + GNUNET_PQ_query_param_timestamp ( + &td->details.wads_in_entries.merge_timestamp), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.wads_in_entries.amount_with_fee), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.wads_in_entries.wad_fee), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.wads_in_entries.deposit_fees), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.wads_in_entries.reserve_sig), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.wads_in_entries.purse_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_wad_in_entries", + "INSERT INTO wad_in_entries" + "(wad_in_entry_serial_id" + ",wad_in_serial_id" + ",reserve_pub" + ",purse_pub" + ",h_contract" + ",purse_expiration" + ",merge_timestamp" + ",amount_with_fee" + ",wad_fee" + ",deposit_fees" + ",reserve_sig" + ",purse_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_wads_in_entries", + params); +} + + +/** + * Function called with profit_drains records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_profit_drains (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.profit_drains.wtid), + GNUNET_PQ_query_param_string ( + td->details.profit_drains.account_section), + GNUNET_PQ_query_param_string ( + td->details.profit_drains.payto_uri.full_payto), + GNUNET_PQ_query_param_timestamp ( + &td->details.profit_drains.trigger_date), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.profit_drains.amount), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.profit_drains.master_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_profit_drains", + "INSERT INTO profit_drains" + "(profit_drain_serial_id" + ",wtid" + ",account_section" + ",payto_uri" + ",trigger_date" + ",amount" + ",master_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_profit_drains", + params); +} + + +/** + * Function called with aml_staff records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_aml_staff (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.aml_staff.decider_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.aml_staff.master_sig), + GNUNET_PQ_query_param_string ( + td->details.aml_staff.decider_name), + GNUNET_PQ_query_param_bool ( + td->details.aml_staff.is_active), + GNUNET_PQ_query_param_bool ( + td->details.aml_staff.read_only), + GNUNET_PQ_query_param_timestamp ( + &td->details.aml_staff.last_change), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_aml_staff", + "INSERT INTO aml_staff" + "(aml_staff_uuid" + ",decider_pub" + ",master_sig" + ",decider_name" + ",is_active" + ",read_only" + ",last_change" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_aml_staff", + params); +} + + +/** + * Function called with kyc_attributes records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_kyc_attributes (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.kyc_attributes.h_payto), + GNUNET_PQ_query_param_uint64 ( + &td->details.kyc_attributes.legitimization_serial), + GNUNET_PQ_query_param_timestamp ( + &td->details.kyc_attributes.collection_time), + GNUNET_PQ_query_param_timestamp ( + &td->details.kyc_attributes.expiration_time), + GNUNET_PQ_query_param_uint64 ( + &td->details.kyc_attributes.trigger_outcome_serial), + GNUNET_PQ_query_param_fixed_size ( + &td->details.kyc_attributes.encrypted_attributes, + td->details.kyc_attributes.encrypted_attributes_size), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_kyc_attributes", + "INSERT INTO kyc_attributes" + "(kyc_attributes_serial_id" + ",h_payto" + ",legitimization_serial" + ",collection_time" + ",expiration_time" + ",trigger_outcome_serial" + ",encrypted_attributes" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_kyc_attributes", + params); +} + + +/** + * Function called with aml_history records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_aml_history (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.aml_history.h_payto), + GNUNET_PQ_query_param_uint64 ( + &td->details.aml_history.outcome_serial_id), + GNUNET_PQ_query_param_string ( + td->details.aml_history.justification), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.aml_history.decider_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.aml_history.decider_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_aml_history", + "INSERT INTO aml_history" + "(aml_history_serial_id" + ",h_payto" + ",outcome_serial_id" + ",justification" + ",decider_pub" + ",decider_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_aml_history", + params); +} + + +/** + * Function called with kyc_event records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_kyc_events (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_timestamp ( + &td->details.kyc_events.event_timestamp), + GNUNET_PQ_query_param_string ( + td->details.kyc_events.event_type), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_kyc_events", + "INSERT INTO kyc_events" + "(kyc_event_serial_id" + ",event_timestamp" + ",event_type" + ") VALUES " + "($1, $2, $3);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_kyc_events", + params); +} + + +/** + * Function called with purse_deletion records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_purse_deletion (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.purse_deletion.purse_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.purse_deletion.purse_sig), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_into_table_purse_deletion", + "INSERT INTO purse_deletion" + "(purse_deletion_serial_id" + ",purse_pub" + ",purse_sig" + ") VALUES " + "($1, $2, $3);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_purse_deletion", + params); +} + + +/** + * Function called with withdraw records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_withdraw ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.withdraw.planchets_h), + GNUNET_PQ_query_param_timestamp ( + &td->details.withdraw.execution_date), + TALER_PQ_query_param_amount ( + pg->conn, + &td->details.withdraw.amount_with_fee), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.withdraw.reserve_pub), + GNUNET_PQ_query_param_auto_from_type ( + &td->details.withdraw.reserve_sig), + td->details.withdraw.age_proof_required + ? GNUNET_PQ_query_param_uint16 ( + &td->details.withdraw.max_age) + : GNUNET_PQ_query_param_null (), + td->details.withdraw.age_proof_required + ? GNUNET_PQ_query_param_uint16 ( + &td->details.withdraw.noreveal_index) + : GNUNET_PQ_query_param_null (), + td->details.withdraw.age_proof_required + ? GNUNET_PQ_query_param_auto_from_type ( + &td->details.withdraw.selected_h) + : GNUNET_PQ_query_param_null (), + td->details.withdraw.no_blinding_seed + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type ( + &td->details.withdraw.blinding_seed), + (0 < td->details.withdraw.num_cs_r_values) + ? TALER_PQ_query_param_array_cs_r_pub ( + td->details.withdraw.num_cs_r_values, + td->details.withdraw.cs_r_values, + pg->conn) + : GNUNET_PQ_query_param_null (), + (0 < td->details.withdraw.num_cs_r_values) + ? GNUNET_PQ_query_param_uint64 ( + &td->details.withdraw.cs_r_choices) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_array_uint64 ( + td->details.withdraw.num_coins, + td->details.withdraw.denom_serials, + pg->conn), + TALER_PQ_query_param_array_blinded_denom_sig ( + td->details.withdraw.num_coins, + td->details.withdraw.denom_sigs, + pg->conn), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "insert_into_table_withdraw", + "INSERT INTO withdraw" + "(withdraw_id" + ",planchets_h" + ",execution_date" + ",amount_with_fee" + ",reserve_pub" + ",reserve_sig" + ",max_age" + ",noreveal_index" + ",selected_h" + ",blinding_seed" + ",cs_r_values" + ",cs_r_choices" + ",denom_serials" + ",denom_sigs" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14);"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_withdraw", + params); + GNUNET_PQ_cleanup_query_params_closures (params); + return qs; +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_records_by_table (struct + TALER_EXCHANGEDB_PostgresContext *pg, + const struct + TALER_EXCHANGEDB_TableData *td) +{ + InsertRecordCallback rh = NULL; + + switch (td->table) + { + case TALER_EXCHANGEDB_RT_DENOMINATIONS: + rh = &irbt_cb_table_denominations; + break; + case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS: + rh = &irbt_cb_table_denomination_revocations; + break; + case TALER_EXCHANGEDB_RT_WIRE_TARGETS: + rh = &irbt_cb_table_wire_targets; + break; + case TALER_EXCHANGEDB_RT_KYC_TARGETS: + rh = &irbt_cb_table_kyc_targets; + break; + case TALER_EXCHANGEDB_RT_RESERVES: + rh = &irbt_cb_table_reserves; + break; + case TALER_EXCHANGEDB_RT_RESERVES_IN: + rh = &irbt_cb_table_reserves_in; + break; + case TALER_EXCHANGEDB_RT_KYCAUTHS_IN: + rh = &irbt_cb_table_kycauths_in; + break; + case TALER_EXCHANGEDB_RT_RESERVES_CLOSE: + rh = &irbt_cb_table_reserves_close; + break; + case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS: + rh = &irbt_cb_table_reserves_open_requests; + break; + case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS: + rh = &irbt_cb_table_reserves_open_deposits; + break; + case TALER_EXCHANGEDB_RT_AUDITORS: + rh = &irbt_cb_table_auditors; + break; + case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS: + rh = &irbt_cb_table_auditor_denom_sigs; + break; + case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS: + rh = &irbt_cb_table_exchange_sign_keys; + break; + case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS: + rh = &irbt_cb_table_signkey_revocations; + break; + case TALER_EXCHANGEDB_RT_KNOWN_COINS: + rh = &irbt_cb_table_known_coins; + break; + case TALER_EXCHANGEDB_RT_REFRESH: + rh = &irbt_cb_table_refresh; + break; + case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS: + rh = &irbt_cb_table_batch_deposits; + break; + case TALER_EXCHANGEDB_RT_COIN_DEPOSITS: + rh = &irbt_cb_table_coin_deposits; + break; + case TALER_EXCHANGEDB_RT_REFUNDS: + rh = &irbt_cb_table_refunds; + break; + case TALER_EXCHANGEDB_RT_WIRE_OUT: + rh = &irbt_cb_table_wire_out; + break; + case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING: + rh = &irbt_cb_table_aggregation_tracking; + break; + case TALER_EXCHANGEDB_RT_WIRE_FEE: + rh = &irbt_cb_table_wire_fee; + break; + case TALER_EXCHANGEDB_RT_GLOBAL_FEE: + rh = &irbt_cb_table_global_fee; + break; + case TALER_EXCHANGEDB_RT_RECOUP: + rh = &irbt_cb_table_recoup; + break; + case TALER_EXCHANGEDB_RT_RECOUP_REFRESH: + rh = &irbt_cb_table_recoup_refresh; + break; + case TALER_EXCHANGEDB_RT_EXTENSIONS: + rh = &irbt_cb_table_extensions; + break; + case TALER_EXCHANGEDB_RT_POLICY_DETAILS: + rh = &irbt_cb_table_policy_details; + break; + case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS: + rh = &irbt_cb_table_policy_fulfillments; + break; + case TALER_EXCHANGEDB_RT_PURSE_REQUESTS: + rh = &irbt_cb_table_purse_requests; + break; + case TALER_EXCHANGEDB_RT_PURSE_DECISION: + rh = &irbt_cb_table_purse_decision; + break; + case TALER_EXCHANGEDB_RT_PURSE_MERGES: + rh = &irbt_cb_table_purse_merges; + break; + case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS: + rh = &irbt_cb_table_purse_deposits; + break; + case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES: + rh = &irbt_cb_table_account_mergers; + break; + case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS: + rh = &irbt_cb_table_history_requests; + break; + case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS: + rh = &irbt_cb_table_close_requests; + break; + case TALER_EXCHANGEDB_RT_WADS_OUT: + rh = &irbt_cb_table_wads_out; + break; + case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES: + rh = &irbt_cb_table_wads_out_entries; + break; + case TALER_EXCHANGEDB_RT_WADS_IN: + rh = &irbt_cb_table_wads_in; + break; + case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES: + rh = &irbt_cb_table_wads_in_entries; + break; + case TALER_EXCHANGEDB_RT_PROFIT_DRAINS: + rh = &irbt_cb_table_profit_drains; + break; + case TALER_EXCHANGEDB_RT_AML_STAFF: + rh = &irbt_cb_table_aml_staff; + break; + case TALER_EXCHANGEDB_RT_PURSE_DELETION: + rh = &irbt_cb_table_purse_deletion; + break; + case TALER_EXCHANGEDB_RT_WITHDRAW: + rh = &irbt_cb_table_withdraw; + break; + case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES: + rh = &irbt_cb_table_legitimization_measures; + break; + case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES: + rh = &irbt_cb_table_legitimization_outcomes; + break; + case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES: + rh = &irbt_cb_table_legitimization_processes; + break; + case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES: + rh = &irbt_cb_table_kyc_attributes; + break; + case TALER_EXCHANGEDB_RT_AML_HISTORY: + rh = &irbt_cb_table_aml_history; + break; + case TALER_EXCHANGEDB_RT_KYC_EVENTS: + rh = &irbt_cb_table_kyc_events; + break; + } + if (NULL == rh) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + return rh (pg, + td); +} + + +/* end of insert_records_by_table.c */ diff --git a/src/exchangedb/insert_refund.c b/src/exchangedb/insert_refund.c @@ -0,0 +1,62 @@ +/* + This file is part of TALER + Copyright (C) 2022-2023 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/> + */ +/** + * @file exchangedb/insert_refund.c + * @brief Implementation of the insert_refund function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_refund.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_refund (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_Refund *refund) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub), + GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub), + GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig), + GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms), + GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id), + TALER_PQ_query_param_amount (pg->conn, + &refund->details.refund_amount), + GNUNET_PQ_query_param_end + }; + + GNUNET_assert (GNUNET_YES == + TALER_amount_cmp_currency (&refund->details.refund_amount, + &refund->details.refund_fee)); + PREPARE (pg, + "insert_refund", + "INSERT INTO refunds " + "(coin_pub" + ",batch_deposit_serial_id" + ",merchant_sig" + ",rtransaction_id" + ",amount_with_fee" + ") SELECT $1, cdep.batch_deposit_serial_id, $3, $5, $6" + " FROM coin_deposits cdep" + " JOIN batch_deposits bdep USING (batch_deposit_serial_id)" + " WHERE coin_pub=$1" + " AND h_contract_terms=$4" + " AND merchant_pub=$2"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_refund", + params); +} diff --git a/src/exchangedb/insert_reserve_closed.c b/src/exchangedb/insert_reserve_closed.c @@ -0,0 +1,109 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/insert_reserve_closed.c + * @brief Implementation of the insert_reserve_closed function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_reserve_closed.h" +#include "helper.h" +#include "taler/exchange-database/reserves_get.h" +#include "taler/exchange-database/reserves_update.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_reserve_closed ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct GNUNET_TIME_Timestamp execution_date, + const struct TALER_FullPayto receiver_account, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_Amount *amount_with_fee, + const struct TALER_Amount *closing_fee, + uint64_t close_request_row) +{ + struct TALER_EXCHANGEDB_Reserve reserve; + enum GNUNET_DB_QueryStatus qs; + struct TALER_FullPaytoHashP h_payto; + + TALER_full_payto_hash (receiver_account, + &h_payto); + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_timestamp (&execution_date), + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_auto_from_type (&h_payto), + TALER_PQ_query_param_amount (pg->conn, + amount_with_fee), + TALER_PQ_query_param_amount (pg->conn, + closing_fee), + GNUNET_PQ_query_param_uint64 (&close_request_row), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "reserves_close_insert", + "INSERT INTO reserves_close " + "(reserve_pub" + ",execution_date" + ",wtid" + ",wire_target_h_payto" + ",amount" + ",closing_fee" + ",close_request_row" + ") VALUES ($1, $2, $3, $4, $5, $6, $7);"); + + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "reserves_close_insert", + params); + } + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) + return qs; + + /* update reserve balance */ + reserve.pub = *reserve_pub; + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + (qs = TALER_EXCHANGEDB_reserves_get (pg, + &reserve))) + { + /* Existence should have been checked before we got here... */ + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + qs = GNUNET_DB_STATUS_HARD_ERROR; + return qs; + } + { + enum TALER_AmountArithmeticResult ret; + + ret = TALER_amount_subtract (&reserve.balance, + &reserve.balance, + amount_with_fee); + if (ret < 0) + { + /* The reserve history was checked to make sure there is enough of a balance + left before we tried this; however, concurrent operations may have changed + the situation by now. We should re-try the transaction. */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Closing of reserve `%s' refused due to balance mismatch. Retrying.\n", + TALER_B2S (reserve_pub)); + return GNUNET_DB_STATUS_HARD_ERROR; + } + GNUNET_break (TALER_AAR_RESULT_ZERO == ret); + } + return TALER_EXCHANGEDB_reserves_update (pg, + &reserve); +} diff --git a/src/exchangedb/insert_reserve_open_deposit.c b/src/exchangedb/insert_reserve_open_deposit.c @@ -0,0 +1,63 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file insert_reserve_open_deposit.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_reserve_open_deposit.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_reserve_open_deposit ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_CoinPublicInfo *cpi, + const struct TALER_CoinSpendSignatureP *coin_sig, + uint64_t known_coin_id, + const struct TALER_Amount *coin_total, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool *insufficient_funds) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&cpi->coin_pub), + GNUNET_PQ_query_param_uint64 (&known_coin_id), + GNUNET_PQ_query_param_auto_from_type (coin_sig), + GNUNET_PQ_query_param_auto_from_type (reserve_sig), + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + TALER_PQ_query_param_amount (pg->conn, + coin_total), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("out_insufficient_funds", + insufficient_funds), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "insert_reserve_open_deposit", + "SELECT " + " out_insufficient_funds" + " FROM exchange_do_reserve_open_deposit" + " ($1,$2,$3,$4,$5,$6);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "insert_reserve_open_deposit", + params, + rs); +} diff --git a/src/exchangedb/insert_sanction_list_hit.c b/src/exchangedb/insert_sanction_list_hit.c @@ -0,0 +1,90 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/insert_sanction_list_hit.c + * @brief Implementation of the insert_sanction_list_hit function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_sanction_list_hit.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_sanction_list_hit ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + bool to_investigate, + const json_t *new_rules, + const json_t *account_properties, + unsigned int num_events, + const char **events) +{ + struct GNUNET_TIME_Timestamp never + = GNUNET_TIME_UNIT_FOREVER_TS; + struct GNUNET_TIME_Timestamp now + = GNUNET_TIME_timestamp_get (); + struct TALER_EXCHANGEDB_KycCompletedEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), + .h_payto = *h_payto + }; + char *notify_s + = GNUNET_PQ_get_event_notify_channel (&rep.header); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_timestamp (&now), + GNUNET_PQ_query_param_timestamp (&never), + NULL != account_properties + ? TALER_PQ_query_param_json (account_properties) + : GNUNET_PQ_query_param_null (), + NULL != new_rules + ? TALER_PQ_query_param_json (new_rules) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_bool (to_investigate), + GNUNET_PQ_query_param_string (notify_s), + GNUNET_PQ_query_param_array_ptrs_string (num_events, + events, + pg->conn), + GNUNET_PQ_query_param_end + }; + uint64_t outcome_serial_id; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("outcome_serial_id", + &outcome_serial_id), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "do_insert_sanction_list_hit", + "SELECT" + " out_outcome_serial_id AS outcome_serial_id" + " FROM exchange_do_insert_sanction_list_hit" + "($1,$2,$3,$4::TEXT::JSONB,$5::TEXT::JSONB,$6,$7,$8);"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Inserting LEGI OUTCOME from sanction list hit\n"); + qs = GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "do_insert_sanction_list_hit", + params, + rs); + (void) outcome_serial_id; + GNUNET_PQ_cleanup_query_params_closures (params); + GNUNET_free (notify_s); + GNUNET_PQ_event_do_poll (pg->conn); + return qs; +} diff --git a/src/exchangedb/insert_signkey_revocation.c b/src/exchangedb/insert_signkey_revocation.c @@ -0,0 +1,49 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_signkey_revocation.c + * @brief Implementation of the insert_signkey_revocation function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_signkey_revocation.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_signkey_revocation ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_MasterSignatureP *master_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (exchange_pub), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_end + }; + + + PREPARE (pg, + "insert_signkey_revocation", + "INSERT INTO signkey_revocations " + "(esk_serial" + ",master_sig" + ") SELECT esk_serial, $2 " + " FROM exchange_sign_keys" + " WHERE exchange_pub=$1;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_signkey_revocation", + params); +} diff --git a/src/exchangedb/insert_successor_measure.c b/src/exchangedb/insert_successor_measure.c @@ -0,0 +1,84 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2023, 2024 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/> + */ +/** + * @file exchangedb/insert_successor_measure.c + * @brief Implementation of the insert_succesor_measure function for Postgres + * @author Florian Dold + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_successor_measure.h" +#include "helper.h" +#include <gnunet/gnunet_pq_lib.h> + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_successor_measure ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + struct GNUNET_TIME_Timestamp decision_time, + const char *new_measure_name, + const json_t *jmeasures, + bool *unknown_account, + struct GNUNET_TIME_Timestamp *last_date) +{ + struct TALER_EXCHANGEDB_KycCompletedEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), + .h_payto = *h_payto + }; + /* We're reverting back to default rules => never expires.*/ + struct GNUNET_TIME_Timestamp expiration_time = { + .abs_time = GNUNET_TIME_UNIT_FOREVER_ABS, + }; + char *notify_s + = GNUNET_PQ_get_event_notify_channel (&rep.header); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_timestamp (&decision_time), + GNUNET_PQ_query_param_timestamp (&expiration_time), + NULL != new_measure_name + ? GNUNET_PQ_query_param_string (new_measure_name) + : GNUNET_PQ_query_param_null (), + NULL != jmeasures + ? TALER_PQ_query_param_json (jmeasures) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("out_account_unknown", + unknown_account), + GNUNET_PQ_result_spec_timestamp ("out_last_date", + last_date), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "do_insert_successor_measure", + "SELECT" + " out_account_unknown" + ",out_last_date" + ",out_legitimization_measure_serial_id" + " FROM exchange_do_insert_successor_measure" + "($1, $2, $3, $4, $5::TEXT::JSONB);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "do_insert_successor_measure", + params, + rs); + GNUNET_free (notify_s); + GNUNET_PQ_event_do_poll (pg->conn); + return qs; +} diff --git a/src/exchangedb/insert_wire.c b/src/exchangedb/insert_wire.c @@ -0,0 +1,81 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2023, 2024 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/> + */ +/** + * @file exchangedb/insert_wire.c + * @brief Implementation of the insert_wire function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_wire.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_insert_wire ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_FullPayto payto_uri, + const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + struct GNUNET_TIME_Timestamp start_date, + const struct TALER_MasterSignatureP *master_sig, + const char *bank_label, + int64_t priority) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (payto_uri.full_payto), + NULL == conversion_url + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (conversion_url), + TALER_PQ_query_param_json (debit_restrictions), + TALER_PQ_query_param_json (credit_restrictions), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_timestamp (&start_date), + NULL == bank_label + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (bank_label), + GNUNET_PQ_query_param_int64 (&priority), + NULL == open_banking_gateway + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (open_banking_gateway), + NULL == wire_transfer_gateway + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (wire_transfer_gateway), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_wire", + "INSERT INTO wire_accounts " + "(payto_uri" + ",conversion_url" + ",debit_restrictions" + ",credit_restrictions" + ",master_sig" + ",is_active" + ",last_change" + ",bank_label" + ",priority" + ",open_banking_gateway" + ",wire_transfer_gateway" + ") VALUES " + "($1,$2,$3::TEXT::JSONB,$4::TEXT::JSONB,$5,true,$6,$7,$8,$9,$10);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_wire", + params); +} diff --git a/src/exchangedb/insert_wire_fee.c b/src/exchangedb/insert_wire_fee.c @@ -0,0 +1,108 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/insert_wire_fee.c + * @brief Implementation of the insert_wire_fee function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/insert_wire_fee.h" +#include "helper.h" +#include "taler/exchange-database/get_wire_fee.h" + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_insert_wire_fee (struct + TALER_EXCHANGEDB_PostgresContext *pg, + const char *type, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_WireFeeSet *fees, + const struct TALER_MasterSignatureP * + master_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (type), + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_timestamp (&end_date), + TALER_PQ_query_param_amount (pg->conn, + &fees->wire), + TALER_PQ_query_param_amount (pg->conn, + &fees->closing), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_end + }; + struct TALER_WireFeeSet wx; + struct TALER_MasterSignatureP sig; + struct GNUNET_TIME_Timestamp sd; + struct GNUNET_TIME_Timestamp ed; + enum GNUNET_DB_QueryStatus qs; + uint64_t rowid; + + qs = TALER_EXCHANGEDB_get_wire_fee (pg, + type, + start_date, + &rowid, + &sd, + &ed, + &wx, + &sig); + if (qs < 0) + return qs; + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + if (0 != GNUNET_memcmp (&sig, + master_sig)) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (0 != + TALER_wire_fee_set_cmp (fees, + &wx)) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if ( (GNUNET_TIME_timestamp_cmp (sd, + !=, + start_date)) || + (GNUNET_TIME_timestamp_cmp (ed, + !=, + end_date)) ) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + /* equal record already exists */ + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + + PREPARE (pg, + "insert_wire_fee", + "INSERT INTO wire_fee " + "(wire_method" + ",start_date" + ",end_date" + ",wire_fee" + ",closing_fee" + ",master_sig" + ") VALUES " + "($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_wire_fee", + params); +} diff --git a/src/exchangedb/iterate_active_auditors.c b/src/exchangedb/iterate_active_auditors.c @@ -0,0 +1,120 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/iterate_active_auditors.c + * @brief Implementation of the iterate_active_auditors function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/iterate_active_auditors.h" +#include "helper.h" + + +/** + * Closure for #auditors_cb_helper() + */ +struct AuditorsIteratorContext +{ + /** + * Function to call with the results. + */ + TALER_EXCHANGEDB_AuditorsCallback cb; + + /** + * Closure to pass to @e cb + */ + void *cb_cls; + +}; + + +/** + * Helper function for #TALER_EXCHANGEDB_iterate_active_auditors(). + * Calls the callback with each auditor. + * + * @param cls a `struct SignkeysIteratorContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +auditors_cb_helper (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct AuditorsIteratorContext *dic = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_AuditorPublicKeyP auditor_pub; + char *auditor_url; + char *auditor_name; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("auditor_pub", + &auditor_pub), + GNUNET_PQ_result_spec_string ("auditor_url", + &auditor_url), + GNUNET_PQ_result_spec_string ("auditor_name", + &auditor_name), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + return; + } + dic->cb (dic->cb_cls, + &auditor_pub, + auditor_url, + auditor_name); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_iterate_active_auditors (struct + TALER_EXCHANGEDB_PostgresContext *pg, + TALER_EXCHANGEDB_AuditorsCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + struct AuditorsIteratorContext dic = { + .cb = cb, + .cb_cls = cb_cls, + }; + + PREPARE (pg, + "select_auditors", + "SELECT" + " auditor_pub" + ",auditor_url" + ",auditor_name" + " FROM auditors" + " WHERE" + " is_active;"); + + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "select_auditors", + params, + &auditors_cb_helper, + &dic); +} diff --git a/src/exchangedb/iterate_active_signkeys.c b/src/exchangedb/iterate_active_signkeys.c @@ -0,0 +1,142 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/iterate_active_signkeys.c + * @brief Implementation of the iterate_active_signkeys function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/iterate_active_signkeys.h" +#include "helper.h" + + +/** + * Closure for #signkeys_cb_helper() + */ +struct SignkeysIteratorContext +{ + /** + * Function to call with the results. + */ + TALER_EXCHANGEDB_ActiveSignkeysCallback cb; + + /** + * Closure to pass to @e cb + */ + void *cb_cls; + +}; + + +/** + * Helper function for #TALER_EXCHANGEDB_iterate_active_signkeys(). + * Calls the callback with each signkey. + * + * @param cls a `struct SignkeysIteratorContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +signkeys_cb_helper (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct SignkeysIteratorContext *dic = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_SignkeyMetaData meta; + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_MasterSignatureP master_sig; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &master_sig), + GNUNET_PQ_result_spec_auto_from_type ("exchange_pub", + &exchange_pub), + GNUNET_PQ_result_spec_timestamp ("valid_from", + &meta.start), + GNUNET_PQ_result_spec_timestamp ("expire_sign", + &meta.expire_sign), + GNUNET_PQ_result_spec_timestamp ("expire_legal", + &meta.expire_legal), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + return; + } + dic->cb (dic->cb_cls, + &exchange_pub, + &meta, + &master_sig); + } +} + + +/** + * Function called to invoke @a cb on every non-revoked exchange signing key + * that has been signed by the master key. Revoked and (for signing!) + * expired keys are skipped. Runs in its own read-only transaction. + * + * @param pg the database context + * @param cb function to call on each signing key + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_iterate_active_signkeys (struct + TALER_EXCHANGEDB_PostgresContext *pg, + TALER_EXCHANGEDB_ActiveSignkeysCallback + cb, + void *cb_cls) +{ + struct GNUNET_TIME_Absolute now = {0}; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + struct SignkeysIteratorContext dic = { + .cb = cb, + .cb_cls = cb_cls, + }; + + PREPARE (pg, + "select_signkeys", + "SELECT" + " master_sig" + ",exchange_pub" + ",valid_from" + ",expire_sign" + ",expire_legal" + " FROM exchange_sign_keys esk" + " WHERE" + " expire_sign > $1" + " AND NOT EXISTS " + " (SELECT esk_serial " + " FROM signkey_revocations skr" + " WHERE esk.esk_serial = skr.esk_serial);"); + now = GNUNET_TIME_absolute_get (); + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "select_signkeys", + params, + &signkeys_cb_helper, + &dic); +} diff --git a/src/exchangedb/iterate_auditor_denominations.c b/src/exchangedb/iterate_auditor_denominations.c @@ -0,0 +1,117 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/iterate_auditor_denominations.c + * @brief Implementation of the iterate_auditor_denominations function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/iterate_auditor_denominations.h" +#include "helper.h" + +/** + * Closure for #auditor_denoms_cb_helper() + */ +struct AuditorDenomsIteratorContext +{ + /** + * Function to call with the results. + */ + TALER_EXCHANGEDB_AuditorDenominationsCallback cb; + + /** + * Closure to pass to @e cb + */ + void *cb_cls; +}; + + +/** + * Helper function for #TALER_EXCHANGEDB_iterate_auditor_denominations(). + * Calls the callback with each auditor and denomination pair. + * + * @param cls a `struct AuditorDenomsIteratorContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +auditor_denoms_cb_helper (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct AuditorDenomsIteratorContext *dic = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_AuditorPublicKeyP auditor_pub; + struct TALER_DenominationHashP h_denom_pub; + struct TALER_AuditorSignatureP auditor_sig; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("auditor_pub", + &auditor_pub), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &h_denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("auditor_sig", + &auditor_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + return; + } + dic->cb (dic->cb_cls, + &auditor_pub, + &h_denom_pub, + &auditor_sig); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_iterate_auditor_denominations ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + TALER_EXCHANGEDB_AuditorDenominationsCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + struct AuditorDenomsIteratorContext dic = { + .cb = cb, + .cb_cls = cb_cls, + }; + /* Used in #postgres_iterate_auditor_denominations() */ + PREPARE (pg, + "select_auditor_denoms", + "SELECT" + " auditors.auditor_pub" + ",denominations.denom_pub_hash" + ",auditor_denom_sigs.auditor_sig" + " FROM auditor_denom_sigs" + " JOIN auditors USING (auditor_uuid)" + " JOIN denominations USING (denominations_serial)" + " WHERE auditors.is_active;"); + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "select_auditor_denoms", + params, + &auditor_denoms_cb_helper, + &dic); +} diff --git a/src/exchangedb/iterate_denomination_info.c b/src/exchangedb/iterate_denomination_info.c @@ -0,0 +1,185 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/iterate_denomination_info.c + * @brief Implementation of the iterate_denomination_info function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/iterate_denomination_info.h" +#include "helper.h" + + +/** + * Closure for #domination_cb_helper() + */ +struct DenomIteratorContext +{ + /** + * Function to call with the results. + */ + TALER_EXCHANGEDB_DenominationCallback cb; + + /** + * Closure to pass to @e cb + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; +}; + + +/** + * Helper function for #TALER_EXCHANGEDB_iterate_denomination_info(). + * Calls the callback with each denomination key. + * + * @param cls a `struct DenomIteratorContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +domination_cb_helper (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct DenomIteratorContext *dic = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = dic->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_DenominationKeyInformation issue; + struct TALER_DenominationPublicKey denom_pub; + struct TALER_DenominationHashP denom_hash; + uint64_t denom_serial; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("denominations_serial", + &denom_serial), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &issue.signature), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &denom_hash), + GNUNET_PQ_result_spec_timestamp ("valid_from", + &issue.start), + GNUNET_PQ_result_spec_timestamp ("expire_withdraw", + &issue.expire_withdraw), + GNUNET_PQ_result_spec_timestamp ("expire_deposit", + &issue.expire_deposit), + GNUNET_PQ_result_spec_timestamp ("expire_legal", + &issue.expire_legal), + TALER_PQ_RESULT_SPEC_AMOUNT ("coin", + &issue.value), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", + &issue.fees.withdraw), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + &issue.fees.deposit), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", + &issue.fees.refresh), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", + &issue.fees.refund), + TALER_PQ_result_spec_denom_pub ("denom_pub", + &denom_pub), + GNUNET_PQ_result_spec_uint32 ("age_mask", + &issue.age_mask.bits), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + return; + } + + /* Unfortunately we have to carry the age mask in both, the + * TALER_DenominationPublicKey and + * TALER_EXCHANGEDB_DenominationKeyInformation at different times. + * Here we use _both_ so let's make sure the values are the same. */ + denom_pub.age_mask = issue.age_mask; + TALER_denom_pub_hash (&denom_pub, + &issue.denom_hash); + if (0 != + GNUNET_memcmp (&issue.denom_hash, + &denom_hash)) + { + GNUNET_break (0); + } + else + { + dic->cb (dic->cb_cls, + denom_serial, + &denom_pub, + &issue); + } + TALER_denom_pub_free (&denom_pub); + } +} + + +/** + * Fetch information about all known denomination keys. + * + * @param pg the database context + * @param cb function to call on each denomination key + * @param cb_cls closure for @a cb + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_iterate_denomination_info (struct + TALER_EXCHANGEDB_PostgresContext *pg + , + TALER_EXCHANGEDB_DenominationCallback + cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + struct DenomIteratorContext dic = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg + }; + + PREPARE (pg, + "denomination_iterate", + "SELECT" + " denominations_serial" + ",master_sig" + ",denom_pub_hash" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin" /* value of this denom */ + ",fee_withdraw" + ",fee_deposit" + ",fee_refresh" + ",fee_refund" + ",denom_pub" + ",age_mask" + " FROM denominations;"); + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "denomination_iterate", + params, + &domination_cb_helper, + &dic); +} diff --git a/src/exchangedb/iterate_denominations.c b/src/exchangedb/iterate_denominations.c @@ -0,0 +1,175 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/iterate_denominations.c + * @brief Implementation of the iterate_denominations function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/iterate_denominations.h" +#include "helper.h" + + +/** + * Closure for #dominations_cb_helper() + */ +struct DenomsIteratorContext +{ + /** + * Function to call with the results. + */ + TALER_EXCHANGEDB_DenominationsCallback cb; + + /** + * Closure to pass to @e cb + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; +}; + + +/** + * Helper function for #TALER_EXCHANGEDB_iterate_denominations(). + * Calls the callback with each denomination key. + * + * @param cls a `struct DenomsIteratorContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +dominations_cb_helper (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct DenomsIteratorContext *dic = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = dic->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0}; + struct TALER_DenominationPublicKey denom_pub = {0}; + struct TALER_MasterSignatureP master_sig = {0}; + struct TALER_DenominationHashP h_denom_pub = {0}; + bool revoked; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("denominations_serial", + &meta.serial), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &master_sig), + GNUNET_PQ_result_spec_bool ("revoked", + &revoked), + GNUNET_PQ_result_spec_timestamp ("valid_from", + &meta.start), + GNUNET_PQ_result_spec_timestamp ("expire_withdraw", + &meta.expire_withdraw), + GNUNET_PQ_result_spec_timestamp ("expire_deposit", + &meta.expire_deposit), + GNUNET_PQ_result_spec_timestamp ("expire_legal", + &meta.expire_legal), + TALER_PQ_RESULT_SPEC_AMOUNT ("coin", + &meta.value), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", + &meta.fees.withdraw), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + &meta.fees.deposit), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", + &meta.fees.refresh), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", + &meta.fees.refund), + TALER_PQ_result_spec_denom_pub ("denom_pub", + &denom_pub), + GNUNET_PQ_result_spec_uint32 ("age_mask", + &meta.age_mask.bits), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + return; + } + + /* make sure the mask information is the same */ + denom_pub.age_mask = meta.age_mask; + + TALER_denom_pub_hash (&denom_pub, + &h_denom_pub); + dic->cb (dic->cb_cls, + &denom_pub, + &h_denom_pub, + &meta, + &master_sig, + revoked); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_iterate_denominations (struct + TALER_EXCHANGEDB_PostgresContext *pg, + TALER_EXCHANGEDB_DenominationsCallback + cb, + void *cb_cls) +{ + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + struct DenomsIteratorContext dic = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg + }; + + PREPARE (pg, + "select_denominations", + "SELECT" + " denominations_serial" + ",denominations.master_sig" + ",denom_revocations_serial_id IS NOT NULL AS revoked" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin" /* value of this denom */ + ",fee_withdraw" + ",fee_deposit" + ",fee_refresh" + ",fee_refund" + ",denom_type" + ",age_mask" + ",denom_pub" + " FROM denominations" + " LEFT JOIN " + " denomination_revocations USING (denominations_serial)" + " WHERE expire_deposit > $1;"); + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "select_denominations", + params, + &dominations_cb_helper, + &dic); +} diff --git a/src/exchangedb/iterate_kyc_reference.c b/src/exchangedb/iterate_kyc_reference.c @@ -0,0 +1,126 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file iterate_kyc_reference.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/iterate_kyc_reference.h" +#include "helper.h" + + +/** + * Closure for #iterate_kyc_reference_cb() + */ +struct IteratorContext +{ + /** + * Function to call with the results. + */ + TALER_EXCHANGEDB_LegitimizationProcessCallback cb; + + /** + * Closure to pass to @e cb + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; +}; + + +/** + * Helper function for #TALER_EXCHANGEDB_iterate_kyc_reference(). + * Calls the callback with each denomination key. + * + * @param cls a `struct IteratorContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +iterate_kyc_reference_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct IteratorContext *ic = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + char *kyc_provider_name_name; + char *provider_user_id; + char *legitimization_id; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("provider_name", + &kyc_provider_name_name), + GNUNET_PQ_result_spec_string ("provider_user_id", + &provider_user_id), + GNUNET_PQ_result_spec_string ("provider_legitimization_id", + &legitimization_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + return; + } + ic->cb (ic->cb_cls, + kyc_provider_name_name, + provider_user_id, + legitimization_id); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_iterate_kyc_reference ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + TALER_EXCHANGEDB_LegitimizationProcessCallback lpc, + void *lpc_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_end + }; + struct IteratorContext ic = { + .cb = lpc, + .cb_cls = lpc_cls, + .pg = pg + }; + + PREPARE (pg, + "iterate_kyc_reference", + "SELECT " + " provider_name" + ",provider_user_id" + ",provider_legitimization_id" + " FROM legitimization_processes" + " WHERE h_payto=$1;"); + return GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "iterate_kyc_reference", + params, + &iterate_kyc_reference_cb, + &ic); +} diff --git a/src/exchangedb/iterate_reserve_close_info.c b/src/exchangedb/iterate_reserve_close_info.c @@ -0,0 +1,127 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file iterate_reserve_close_info.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/iterate_reserve_close_info.h" +#include "helper.h" + +/** + * Closure for #iterate_reserve_close_info_cb() + */ +struct IteratorContext +{ + /** + * Function to call with the results. + */ + TALER_KYCLOGIC_KycAmountCallback cb; + + /** + * Closure to pass to @e cb + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; +}; + + +/** + * Helper function for #TALER_EXCHANGEDB_iterate_reserve_close_info(). + * Calls the callback with each denomination key. + * + * @param cls a `struct IteratorContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +iterate_reserve_close_info_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct IteratorContext *ic = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ic->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_Amount amount; + struct GNUNET_TIME_Absolute ts; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_absolute_time ("execution_date", + &ts), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + return; + } + ic->cb (ic->cb_cls, + &amount, + ts); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_iterate_reserve_close_info ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_KYCLOGIC_KycAmountCallback kac, + void *kac_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_absolute_time (&time_limit), + GNUNET_PQ_query_param_end + }; + struct IteratorContext ic = { + .cb = kac, + .cb_cls = kac_cls, + .pg = pg + }; + + PREPARE (pg, + "iterate_reserve_close_info", + "SELECT amount" + " ,execution_date" + " FROM reserves_close" + " WHERE wire_target_h_payto IN (" + " SELECT wire_target_h_payto" + " FROM wire_targets" + " WHERE h_normalized_payto=$1" + " )" + " AND execution_date >= $2" + " ORDER BY execution_date DESC"); + return GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "iterate_reserve_close_info", + params, + &iterate_reserve_close_info_cb, + &ic); +} diff --git a/src/exchangedb/kyc_provider_account_lookup.c b/src/exchangedb/kyc_provider_account_lookup.c @@ -0,0 +1,66 @@ +/* + This file is part of TALER + Copyright (C) 2022-2025 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/> + */ +/** + * @file exchangedb/kyc_provider_account_lookup.c + * @brief Implementation of the kyc_provider_account_lookup function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/kyc_provider_account_lookup.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_kyc_provider_account_lookup ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *provider_name, + const char *provider_legitimization_id, + struct TALER_NormalizedPaytoHashP *h_payto, + bool *is_wallet, + uint64_t *process_row) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (provider_legitimization_id), + GNUNET_PQ_query_param_string (provider_name), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("h_payto", + h_payto), + GNUNET_PQ_result_spec_bool ("is_wallet", + is_wallet), + GNUNET_PQ_result_spec_uint64 ("legitimization_process_serial_id", + process_row), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_wire_target_by_legitimization_id", + "SELECT " + " lp.h_payto" + ",kt.is_wallet" + ",lp.legitimization_process_serial_id" + " FROM legitimization_processes lp" + " JOIN kyc_targets kt" + " ON (lp.h_payto = kt.h_normalized_payto)" + " WHERE provider_legitimization_id=$1" + " AND provider_name=$2;"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "get_wire_target_by_legitimization_id", + params, + rs); +} diff --git a/src/exchangedb/kycauth_in_insert.c b/src/exchangedb/kycauth_in_insert.c @@ -0,0 +1,78 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/kycauth_in_insert.c + * @brief Implementation of the kycauth_in_insert function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/kycauth_in_insert.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_kycauth_in_insert ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const union TALER_AccountPublicKeyP *account_pub, + const struct TALER_Amount *credit_amount, + struct GNUNET_TIME_Timestamp execution_date, + const struct TALER_FullPayto debit_account_uri, + const char *section_name, + uint64_t serial_id) +{ + struct TALER_NormalizedPaytoHashP h_normalized_payto; + struct TALER_FullPaytoHashP h_full_payto; + + TALER_full_payto_hash (debit_account_uri, + &h_full_payto); + TALER_full_payto_normalize_and_hash (debit_account_uri, + &h_normalized_payto); + { + struct TALER_EXCHANGEDB_KycCompletedEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), + .h_payto = h_normalized_payto + }; + char *notify_s + = GNUNET_PQ_get_event_notify_channel (&rep.header); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (account_pub), + GNUNET_PQ_query_param_uint64 (&serial_id), + TALER_PQ_query_param_amount (pg->conn, + credit_amount), + GNUNET_PQ_query_param_auto_from_type (&h_full_payto), + GNUNET_PQ_query_param_auto_from_type (&h_normalized_payto), + GNUNET_PQ_query_param_string (debit_account_uri.full_payto), + GNUNET_PQ_query_param_string (section_name), + GNUNET_PQ_query_param_timestamp (&execution_date), + GNUNET_PQ_query_param_string (notify_s), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "kycauth_in_insert", + "CALL" + " exchange_do_kycauth_in_insert" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9);"); + qs = GNUNET_PQ_eval_prepared_non_select ( + pg->conn, + "kycauth_in_insert", + params); + GNUNET_free (notify_s); + return qs; + } +} diff --git a/src/exchangedb/lookup_active_legitimization.c b/src/exchangedb/lookup_active_legitimization.c @@ -0,0 +1,62 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/lookup_pending_legitimization.c + * @brief Implementation of the lookup_pending_legitimization function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_active_legitimization.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_active_legitimization ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t legitimization_process_serial_id, + uint32_t *measure_index, + json_t **jmeasures) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&legitimization_process_serial_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_json ( + "jmeasures", + jmeasures), + GNUNET_PQ_result_spec_uint32 ( + "measure_index", + measure_index), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "lookup_active_legitimization", + "SELECT " + " lm.jmeasures::TEXT" + ",lp.measure_index" + " FROM legitimization_processes lp" + " JOIN legitimization_measures lm" + " USING (legitimization_measure_serial_id)" + " WHERE lp.legitimization_process_serial_id=$1" + " AND NOT lm.is_finished;"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "lookup_active_legitimization", + params, + rs); +} diff --git a/src/exchangedb/lookup_aml_file_number.c b/src/exchangedb/lookup_aml_file_number.c @@ -0,0 +1,59 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/lookup_aml_file_number.c + * @brief Implementation of the lookup_aml_file_number function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_aml_file_number.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_aml_file_number ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + uint64_t *kyc_target_row, + bool *is_wallet) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "kyc_target_serial_id", + kyc_target_row), + GNUNET_PQ_result_spec_bool ( + "is_wallet", + is_wallet), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "lookup_aml_file_number", + "SELECT " + " kyc_target_serial_id" + ",is_wallet" + " FROM kyc_targets" + " WHERE h_normalized_payto=$1"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "lookup_aml_file_number", + params, + rs); +} diff --git a/src/exchangedb/lookup_aml_history.c b/src/exchangedb/lookup_aml_history.c @@ -0,0 +1,200 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/lookup_aml_history.c + * @brief Implementation of the lookup_aml_history function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_aml_history.h" +#include "helper.h" + + +/** + * Closure for callbacks called from #TALER_EXCHANGEDB_lookup_aml_history() + */ +struct AmlHistoryContext +{ + + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_AmlHistoryCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to 'true' if the transaction failed. + */ + bool failed; + +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct AmlHistoryContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +handle_aml_entry (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct AmlHistoryContext *ahc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + uint64_t outcome_serial_id; + struct GNUNET_TIME_Timestamp decision_time; + char *justification; + struct TALER_AmlOfficerPublicKeyP decider_pub; + json_t *jproperties; + json_t *jnew_rules = NULL; + bool to_investigate; + bool is_active; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("outcome_serial_id", + &outcome_serial_id), + GNUNET_PQ_result_spec_timestamp ("decision_time", + &decision_time), + GNUNET_PQ_result_spec_string ("justification", + &justification), + GNUNET_PQ_result_spec_auto_from_type ("decider_pub", + &decider_pub), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("jproperties", + &jproperties), + NULL), + TALER_PQ_result_spec_json ("jnew_rules", + &jnew_rules), + GNUNET_PQ_result_spec_bool ("to_investigate", + &to_investigate), + GNUNET_PQ_result_spec_bool ("is_active", + &is_active), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ahc->failed = true; + return; + } + ahc->cb (ahc->cb_cls, + outcome_serial_id, + decision_time, + justification, + &decider_pub, + jproperties, + jnew_rules, + to_investigate, + is_active); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_aml_history ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + uint64_t offset, + int64_t limit, + TALER_EXCHANGEDB_AmlHistoryCallback cb, + void *cb_cls) +{ + struct AmlHistoryContext ahc = { + .pg = pg, + .cb = cb, + .cb_cls = cb_cls + }; + uint64_t ulimit = (limit < 0) ? (-limit) : limit; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&ulimit), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "lookup_aml_history_desc", + "SELECT" + " lo.decision_time" + ",lo.outcome_serial_id" + ",ah.justification" + ",ah.decider_pub" + ",lo.jproperties::TEXT" + ",lo.jnew_rules::TEXT" + ",lo.to_investigate" + ",lo.is_active" + " FROM aml_history ah" + " JOIN legitimization_outcomes lo" + " USING (outcome_serial_id)" + " WHERE ah.h_payto=$1" + " AND lo.outcome_serial_id < $2" + " ORDER BY outcome_serial_id DESC" + " LIMIT $3;"); + PREPARE (pg, + "lookup_aml_history_asc", + "SELECT" + " lo.decision_time" + ",lo.outcome_serial_id" + ",ah.justification" + ",ah.decider_pub" + ",lo.jproperties::TEXT" + ",lo.jnew_rules::TEXT" + ",lo.to_investigate" + ",lo.is_active" + " FROM aml_history ah" + " JOIN legitimization_outcomes lo" + " USING (outcome_serial_id)" + " WHERE ah.h_payto=$1" + " AND lo.outcome_serial_id > $2" + " ORDER BY outcome_serial_id ASC" + " LIMIT $3;"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + (limit < 0) + ? "lookup_aml_history_desc" + : "lookup_aml_history_asc", + params, + &handle_aml_entry, + &ahc); + if (qs <= 0) + return qs; + if (ahc.failed) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + return qs; +} diff --git a/src/exchangedb/lookup_aml_officer.c b/src/exchangedb/lookup_aml_officer.c @@ -0,0 +1,68 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/lookup_aml_officer.c + * @brief Implementation of the lookup_aml_officer function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_aml_officer.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_aml_officer ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + struct TALER_MasterSignatureP *master_sig, + char **decider_name, + bool *is_active, + bool *read_only, + struct GNUNET_TIME_Absolute *last_change) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (decider_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), + GNUNET_PQ_result_spec_string ("decider_name", + decider_name), + GNUNET_PQ_result_spec_bool ("is_active", + is_active), + GNUNET_PQ_result_spec_bool ("read_only", + read_only), + GNUNET_PQ_result_spec_absolute_time ("last_change", + last_change), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "lookup_aml_officer", + "SELECT " + " master_sig" + ",decider_name" + ",is_active" + ",read_only" + ",last_change" + " FROM aml_staff" + " WHERE decider_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "lookup_aml_officer", + params, + rs); +} diff --git a/src/exchangedb/lookup_auditor_status.c b/src/exchangedb/lookup_auditor_status.c @@ -0,0 +1,57 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/lookup_auditor_status.c + * @brief Implementation of the lookup_auditor_status function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_auditor_status.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_auditor_status ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_AuditorPublicKeyP *auditor_pub, + char **auditor_url, + bool *enabled) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (auditor_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("auditor_url", + auditor_url), + GNUNET_PQ_result_spec_bool ("is_active", + enabled), + GNUNET_PQ_result_spec_end + }; + + /* Used in #postgres_lookup_auditor_status() */ + PREPARE (pg, + "lookup_auditor_status", + "SELECT" + " auditor_url" + ",is_active" + " FROM auditors" + " WHERE auditor_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_auditor_status", + params, + rs); +} diff --git a/src/exchangedb/lookup_auditor_timestamp.c b/src/exchangedb/lookup_auditor_timestamp.c @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/lookup_auditor_timestamp.c + * @brief Implementation of the lookup_auditor_timestamp function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_auditor_timestamp.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_auditor_timestamp ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct GNUNET_TIME_Timestamp *last_date) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (auditor_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("last_change", + last_date), + GNUNET_PQ_result_spec_end + }; + + /* Used in #postgres_lookup_auditor_timestamp() */ + PREPARE (pg, + "lookup_auditor_timestamp", + "SELECT" + " last_change" + " FROM auditors" + " WHERE auditor_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_auditor_timestamp", + params, + rs); +} diff --git a/src/exchangedb/lookup_completed_legitimization.c b/src/exchangedb/lookup_completed_legitimization.c @@ -0,0 +1,95 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/lookup_completed_legitimization.c + * @brief Implementation of the lookup_pending_legitimization function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_completed_legitimization.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_completed_legitimization ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t legitimization_measure_serial_id, + uint32_t measure_index, + struct TALER_AccountAccessTokenP *access_token, + struct TALER_NormalizedPaytoHashP *h_payto, + bool *is_wallet, + json_t **jmeasures, + bool *is_finished, + size_t *encrypted_attributes_len, + void **encrypted_attributes + ) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id), + GNUNET_PQ_query_param_uint32 (&measure_index), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_json ( + "jmeasures", + jmeasures), + GNUNET_PQ_result_spec_auto_from_type ( + "h_normalized_payto", + h_payto), + GNUNET_PQ_result_spec_auto_from_type ( + "access_token", + access_token), + GNUNET_PQ_result_spec_bool ( + "is_finished", + is_finished), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_variable_size ( + "encrypted_attributes", + encrypted_attributes, + encrypted_attributes_len), + NULL), + GNUNET_PQ_result_spec_bool ( + "is_wallet", + is_wallet), + GNUNET_PQ_result_spec_end + }; + + *encrypted_attributes_len = 0; + *encrypted_attributes = NULL; + PREPARE (pg, + "lookup_completed_legitimization", + "SELECT " + " lm.jmeasures::TEXT" + ",kt.h_normalized_payto" + ",kt.is_wallet" + ",lm.access_token" + ",lm.is_finished" + ",ka.encrypted_attributes" + " FROM legitimization_measures lm" + " JOIN kyc_targets kt" + " ON (lm.access_token = kt.access_token)" + " LEFT JOIN legitimization_processes lp" + " ON (lm.legitimization_measure_serial_id = lp.legitimization_measure_serial_id)" + " LEFT JOIN kyc_attributes ka" + " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)" + " WHERE lm.legitimization_measure_serial_id=$1" + " AND lp.measure_index=$2;"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "lookup_completed_legitimization", + params, + rs); +} diff --git a/src/exchangedb/lookup_denomination_key.c b/src/exchangedb/lookup_denomination_key.c @@ -0,0 +1,79 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/lookup_denomination_key.c + * @brief Implementation of the lookup_denomination_key function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_denomination_key.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_denomination_key ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_DenominationHashP *h_denom_pub, + struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_denom_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("valid_from", + &meta->start), + GNUNET_PQ_result_spec_timestamp ("expire_withdraw", + &meta->expire_withdraw), + GNUNET_PQ_result_spec_timestamp ("expire_deposit", + &meta->expire_deposit), + GNUNET_PQ_result_spec_timestamp ("expire_legal", + &meta->expire_legal), + TALER_PQ_RESULT_SPEC_AMOUNT ("coin", + &meta->value), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", + &meta->fees.withdraw), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + &meta->fees.deposit), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", + &meta->fees.refresh), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", + &meta->fees.refund), + GNUNET_PQ_result_spec_uint32 ("age_mask", + &meta->age_mask.bits), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "lookup_denomination_key", + "SELECT" + " valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin" + ",fee_withdraw" + ",fee_deposit" + ",fee_refresh" + ",fee_refund" + ",age_mask" + " FROM denominations" + " WHERE denom_pub_hash=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_denomination_key", + params, + rs); +} diff --git a/src/exchangedb/lookup_global_fee_by_time.c b/src/exchangedb/lookup_global_fee_by_time.c @@ -0,0 +1,180 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/lookup_global_fee_by_time.c + * @brief Implementation of the lookup_global_fee_by_time function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_dbevents.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_global_fee_by_time.h" +#include "helper.h" + +/** + * Closure for #global_fee_by_time_helper() + */ +struct GlobalFeeLookupContext +{ + + /** + * Set to the wire fees. Set to invalid if fees conflict over + * the given time period. + */ + struct TALER_GlobalFeeSet *fees; + + /** + * Set to timeout of unmerged purses + */ + struct GNUNET_TIME_Relative *purse_timeout; + + /** + * Set to history expiration for reserves. + */ + struct GNUNET_TIME_Relative *history_expiration; + + /** + * Set to number of free purses per account. + */ + uint32_t *purse_account_limit; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; +}; + + +/** + * Helper function for #TALER_EXCHANGEDB_lookup_global_fee_by_time(). + * Calls the callback with each denomination key. + * + * @param cls a `struct GlobalFeeLookupContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +global_fee_by_time_helper (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct GlobalFeeLookupContext *wlc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = wlc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_GlobalFeeSet fs; + struct GNUNET_TIME_Relative purse_timeout; + struct GNUNET_TIME_Relative history_expiration; + uint32_t purse_account_limit; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee", + &fs.history), + TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee", + &fs.account), + TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", + &fs.purse), + GNUNET_PQ_result_spec_relative_time ("purse_timeout", + &purse_timeout), + GNUNET_PQ_result_spec_relative_time ("history_expiration", + &history_expiration), + GNUNET_PQ_result_spec_uint32 ("purse_account_limit", + &purse_account_limit), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + /* invalidate */ + memset (wlc->fees, + 0, + sizeof (struct TALER_GlobalFeeSet)); + return; + } + if (0 == i) + { + *wlc->fees = fs; + *wlc->purse_timeout = purse_timeout; + *wlc->history_expiration = history_expiration; + *wlc->purse_account_limit = purse_account_limit; + continue; + } + if ( (0 != + TALER_global_fee_set_cmp (&fs, + wlc->fees)) || + (purse_account_limit != *wlc->purse_account_limit) || + (GNUNET_TIME_relative_cmp (purse_timeout, + !=, + *wlc->purse_timeout)) || + (GNUNET_TIME_relative_cmp (history_expiration, + !=, + *wlc->history_expiration)) ) + { + /* invalidate */ + memset (wlc->fees, + 0, + sizeof (struct TALER_GlobalFeeSet)); + return; + } + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_global_fee_by_time ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative *purse_timeout, + struct GNUNET_TIME_Relative *history_expiration, + uint32_t *purse_account_limit) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&start_time), + GNUNET_PQ_query_param_timestamp (&end_time), + GNUNET_PQ_query_param_end + }; + struct GlobalFeeLookupContext wlc = { + .fees = fees, + .purse_timeout = purse_timeout, + .history_expiration = history_expiration, + .purse_account_limit = purse_account_limit, + .pg = pg + }; + + PREPARE (pg, + "lookup_global_fee_by_time", + "SELECT" + " history_fee" + ",account_fee" + ",purse_fee" + ",purse_timeout" + ",history_expiration" + ",purse_account_limit" + " FROM global_fee" + " WHERE end_date > $1" + " AND start_date < $2;"); + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_global_fee_by_time", + params, + &global_fee_by_time_helper, + &wlc); +} diff --git a/src/exchangedb/lookup_h_payto_by_access_token.c b/src/exchangedb/lookup_h_payto_by_access_token.c @@ -0,0 +1,59 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/lookup_h_payto_by_access_token.c + * @brief Implementation of the lookup_h_payto_by_access_token function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_h_payto_by_access_token.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_h_payto_by_access_token ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_AccountAccessTokenP *access_token, + struct TALER_NormalizedPaytoHashP *h_payto, + bool *is_wallet) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (access_token), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ( + "h_normalized_payto", + h_payto), + GNUNET_PQ_result_spec_bool ( + "is_wallet", + is_wallet), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "lookup_h_payto_by_access_token", + "SELECT " + " h_normalized_payto" + " ,is_wallet" + " FROM kyc_targets" + " WHERE (access_token = $1);"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "lookup_h_payto_by_access_token", + params, + rs); +} diff --git a/src/exchangedb/lookup_kyc_history.c b/src/exchangedb/lookup_kyc_history.c @@ -0,0 +1,192 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/lookup_kyc_history.c + * @brief Implementation of the lookup_kyc_history function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_kyc_history.h" +#include "helper.h" + +/** + * Closure for callbacks called from #TALER_EXCHANGEDB_lookup_kyc_history() + */ +struct KycHistoryContext +{ + + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_KycHistoryCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to 'true' if the transaction failed. + */ + bool failed; + +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct KycHistoryContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +handle_kyc_entry (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct KycHistoryContext *khc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + char *provider_name = NULL; + bool finished; + uint32_t error_code; + char *error_message = NULL; + char *provider_user_id = NULL; + char *provider_legitimization_id = NULL; + struct GNUNET_TIME_Timestamp collection_time; + struct GNUNET_TIME_Absolute expiration_time + = GNUNET_TIME_UNIT_ZERO_ABS; + void *encrypted_attributes; + size_t encrypted_attributes_len; + + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("provider_name", + &provider_name), + NULL), + GNUNET_PQ_result_spec_bool ("finished", + &finished), + GNUNET_PQ_result_spec_uint32 ("error_code", + &error_code), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("error_message", + &error_message), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("provider_user_id", + &provider_user_id), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("provider_legitimization_id", + &provider_legitimization_id), + NULL), + GNUNET_PQ_result_spec_timestamp ("collection_time", + &collection_time), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_absolute_time ("expiration_time", + &expiration_time), + NULL), + GNUNET_PQ_result_spec_variable_size ("encrypted_attributes", + &encrypted_attributes, + &encrypted_attributes_len), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + khc->failed = true; + return; + } + khc->cb (khc->cb_cls, + provider_name, + finished, + (enum TALER_ErrorCode) error_code, + error_message, + provider_user_id, + provider_legitimization_id, + collection_time, + expiration_time, + encrypted_attributes_len, + encrypted_attributes); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_kyc_history ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + TALER_EXCHANGEDB_KycHistoryCallback cb, + void *cb_cls) +{ + struct KycHistoryContext khc = { + .pg = pg, + .cb = cb, + .cb_cls = cb_cls + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "lookup_kyc_history", + "SELECT" + " lp.provider_name" + ",lp.finished" + ",lp.error_code" + ",lp.error_message" + ",lp.provider_user_id" + ",lp.provider_legitimization_id" + ",ka.collection_time" + ",ka.expiration_time" + ",ka.encrypted_attributes" + " FROM kyc_attributes ka" + " JOIN legitimization_processes lp" + " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)" + " WHERE ka.h_payto=$1" + " ORDER BY ka.collection_time DESC;"); + + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "lookup_kyc_history", + params, + &handle_kyc_entry, + &khc); + if (qs <= 0) + return qs; + if (khc.failed) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + return qs; +} diff --git a/src/exchangedb/lookup_kyc_process_by_account.c b/src/exchangedb/lookup_kyc_process_by_account.c @@ -0,0 +1,90 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2025 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/> + */ +/** + * @file exchangedb/lookup_kyc_process_by_account.c + * @brief Implementation of the lookup_kyc_process_by_account function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_kyc_process_by_account.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_kyc_process_by_account ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *provider_name, + const struct TALER_NormalizedPaytoHashP *h_payto, + uint64_t *process_row, + struct GNUNET_TIME_Absolute *expiration, + char **provider_account_id, + char **provider_legitimization_id, + bool *is_wallet) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_string (provider_name), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "legitimization_process_serial_id", + process_row), + GNUNET_PQ_result_spec_absolute_time ( + "expiration_time", + expiration), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ( + "provider_user_id", + provider_account_id), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ( + "provider_legitimization_id", + provider_legitimization_id), + NULL), + GNUNET_PQ_result_spec_bool ( + "is_wallet", + is_wallet), + GNUNET_PQ_result_spec_end + }; + + *provider_account_id = NULL; + *provider_legitimization_id = NULL; + PREPARE (pg, + "lookup_kyc_process_by_account", + "SELECT " + " lp.legitimization_process_serial_id" + ",lp.expiration_time" + ",lp.provider_user_id" + ",lp.provider_legitimization_id" + ",kt.is_wallet" + " FROM legitimization_processes lp" + " JOIN kyc_targets kt" + " ON (lp.h_payto = kt.h_normalized_payto)" + " WHERE h_payto=$1" + " AND provider_name=$2" + " AND NOT finished" + /* Note: there *should* only be one unfinished + match, so this is just to be safe(r): */ + " ORDER BY lp.expiration_time DESC" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "lookup_kyc_process_by_account", + params, + rs); +} diff --git a/src/exchangedb/lookup_kyc_requirement_by_row.c b/src/exchangedb/lookup_kyc_requirement_by_row.c @@ -0,0 +1,109 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/lookup_kyc_requirement_by_row.c + * @brief Implementation of the lookup_kyc_requirement_by_row function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_kyc_requirement_by_row.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_kyc_requirement_by_row ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + const union TALER_AccountPublicKeyP *account_pub, + enum GNUNET_GenericReturnValue *is_wallet, + struct TALER_AccountAccessTokenP *access_token, + uint64_t *rule_gen, + json_t **jrules, + bool *aml_review, + bool *kyc_required) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_auto_from_type (account_pub), + GNUNET_PQ_query_param_end + }; + bool bis_wallet; + bool bis_wallet_unknown; + bool not_found; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("access_token", + access_token), + NULL), + GNUNET_PQ_result_spec_allow_null ( + /* can be NULL due to LEFT JOIN */ + TALER_PQ_result_spec_json ("jrules", + jrules), + NULL), + GNUNET_PQ_result_spec_allow_null ( + /* can be NULL due to LEFT JOIN */ + GNUNET_PQ_result_spec_bool ("is_wallet", + &bis_wallet), + &bis_wallet_unknown), + GNUNET_PQ_result_spec_allow_null ( + /* can be NULL due to LEFT JOIN */ + GNUNET_PQ_result_spec_bool ("aml_review", + aml_review), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ("rule_gen", + rule_gen), + NULL), + GNUNET_PQ_result_spec_bool ("kyc_required", + kyc_required), + GNUNET_PQ_result_spec_bool ("not_found", + &not_found), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + *jrules = NULL; + *aml_review = false; + *is_wallet = GNUNET_SYSERR; + *rule_gen = 0; + memset (access_token, + 0, + sizeof (*access_token)); + PREPARE (pg, + "lookup_kyc_requirement_by_row", + "SELECT " + " out_access_token AS access_token" + ",out_jrules::TEXT AS jrules" + ",out_is_wallet AS is_wallet" + ",out_not_found AS not_found" + ",out_aml_review AS aml_review" + ",out_kyc_required AS kyc_required" + ",out_rule_gen AS rule_gen" + " FROM exchange_do_lookup_kyc_requirement_by_row" + " ($1, $2);"); + qs = GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "lookup_kyc_requirement_by_row", + params, + rs); + if (qs <= 0) + return qs; + if (! bis_wallet_unknown) + *is_wallet = (bis_wallet) ? GNUNET_YES : GNUNET_NO; + if (not_found) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + return qs; +} diff --git a/src/exchangedb/lookup_kyc_status_by_token.c b/src/exchangedb/lookup_kyc_status_by_token.c @@ -0,0 +1,61 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/lookup_kyc_status_by_token.c + * @brief Implementation of the lookup_kyc_status_by_token function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_kyc_status_by_token.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_kyc_status_by_token ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_AccountAccessTokenP *access_token, + uint64_t *row, + json_t **jmeasures) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (access_token), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "legitimization_measure_serial_id", + row), + TALER_PQ_result_spec_json ( + "jmeasures", + jmeasures), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "lookup_kyc_status_by_token", + "SELECT" + " legitimization_measure_serial_id" + ",jmeasures::TEXT" + " FROM legitimization_measures" + " WHERE access_token=$1" + " AND NOT is_finished" + " ORDER BY display_priority DESC" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_kyc_status_by_token", + params, + rs); +} diff --git a/src/exchangedb/lookup_pending_legitimization.c b/src/exchangedb/lookup_pending_legitimization.c @@ -0,0 +1,76 @@ +/* + This file is part of TALER + Copyright (C) 2024, 2025 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/> + */ +/** + * @file exchangedb/lookup_pending_legitimization.c + * @brief Implementation of the lookup_pending_legitimization function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_pending_legitimization.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_pending_legitimization ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t legitimization_measure_serial_id, + struct TALER_AccountAccessTokenP *access_token, + struct TALER_NormalizedPaytoHashP *h_payto, + json_t **jmeasures, + bool *is_finished, + bool *is_wallet) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_json ( + "jmeasures", + jmeasures), + GNUNET_PQ_result_spec_auto_from_type ( + "h_normalized_payto", + h_payto), + GNUNET_PQ_result_spec_auto_from_type ( + "access_token", + access_token), + GNUNET_PQ_result_spec_bool ( + "is_finished", + is_finished), + GNUNET_PQ_result_spec_bool ( + "is_wallet", + is_wallet), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "lookup_pending_legitimization", + "SELECT " + " lm.jmeasures::TEXT" + ",kt.h_normalized_payto" + ",kt.is_wallet" + ",lm.access_token" + ",lm.is_finished" + " FROM legitimization_measures lm" + " JOIN kyc_targets kt" + " USING (access_token)" + " WHERE lm.legitimization_measure_serial_id=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "lookup_pending_legitimization", + params, + rs); +} diff --git a/src/exchangedb/lookup_records_by_table.c b/src/exchangedb/lookup_records_by_table.c @@ -0,0 +1,3802 @@ +/* + This file is part of GNUnet + Copyright (C) 2020-2025 Taler Systems SA + + GNUnet 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 Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/** + * @file exchangedb/lookup_records_by_table.c + * @brief implementation of lookup_records_by_table + * @author Christian Grothoff + * @author Özgür Kesim + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_dbevents.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_records_by_table.h" +#include "helper.h" +#include <gnunet/gnunet_pq_lib.h> + + +/** + * Closure for callbacks used by #postgres_lookup_records_by_table. + */ +struct LookupRecordsByTableContext +{ + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Function to call with the results. + */ + TALER_EXCHANGEDB_ReplicationCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * Set to true on errors. + */ + bool error; +}; + + +/** + * Function called with denominations table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_denominations (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_DENOMINATIONS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_uint32 ( + "denom_type", + &td.details.denominations.denom_type), + GNUNET_PQ_result_spec_uint32 ( + "age_mask", + &td.details.denominations.age_mask), + TALER_PQ_result_spec_denom_pub ( + "denom_pub", + &td.details.denominations.denom_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "master_sig", + &td.details.denominations.master_sig), + GNUNET_PQ_result_spec_timestamp ( + "valid_from", + &td.details.denominations.valid_from), + GNUNET_PQ_result_spec_timestamp ( + "expire_withdraw", + &td.details.denominations. + expire_withdraw), + GNUNET_PQ_result_spec_timestamp ( + "expire_deposit", + &td.details.denominations. + expire_deposit), + GNUNET_PQ_result_spec_timestamp ( + "expire_legal", + &td.details.denominations.expire_legal), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "coin", + &td.details.denominations.coin), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "fee_withdraw", + &td.details.denominations.fees.withdraw), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "fee_deposit", + &td.details.denominations.fees.deposit), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "fee_refresh", + &td.details.denominations.fees.refresh), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "fee_refund", + &td.details.denominations.fees.refund), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with denomination_revocations table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_denomination_revocations (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_uint64 ( + "denominations_serial", + &td.details.denomination_revocations.denominations_serial), + GNUNET_PQ_result_spec_auto_from_type ( + "master_sig", + &td.details.denomination_revocations.master_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with wire_targets table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_wire_targets (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_WIRE_TARGETS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_string ( + "payto_uri", + &td.details.wire_targets.full_payto_uri.full_payto), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with wire_targets table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_kyc_targets (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_KYC_TARGETS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "h_normalized_payto", + &td.details.kyc_targets.h_normalized_payto), + GNUNET_PQ_result_spec_auto_from_type ( + "access_token", + &td.details.kyc_targets.access_token), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ( + "target_pub", + &td.details.kyc_targets.target_pub), + &td.details.kyc_targets.no_account), + GNUNET_PQ_result_spec_bool ( + "is_wallet", + &td.details.kyc_targets.is_wallet), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with reserves table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_reserves (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_RESERVES + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &td.details.reserves.reserve_pub), + GNUNET_PQ_result_spec_timestamp ("expiration_date", + &td.details.reserves.expiration_date), + GNUNET_PQ_result_spec_timestamp ("gc_date", + &td.details.reserves.gc_date), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with reserves_in table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_reserves_in (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_RESERVES_IN + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_pub", + &td.details.reserves_in.reserve_pub), + GNUNET_PQ_result_spec_uint64 ( + "wire_reference", + &td.details.reserves_in.wire_reference), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "credit", + &td.details.reserves_in.credit), + GNUNET_PQ_result_spec_auto_from_type ( + "wire_source_h_payto", + &td.details.reserves_in.sender_account_h_payto), + GNUNET_PQ_result_spec_string ( + "exchange_account_section", + &td.details.reserves_in.exchange_account_section), + GNUNET_PQ_result_spec_timestamp ( + "execution_date", + &td.details.reserves_in.execution_date), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with kycauth_in table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_kycauth_in (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_KYCAUTHS_IN + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "account_pub", + &td.details.kycauth_in.account_pub), + GNUNET_PQ_result_spec_uint64 ( + "wire_reference", + &td.details.kycauth_in.wire_reference), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "credit", + &td.details.kycauth_in.credit), + GNUNET_PQ_result_spec_auto_from_type ( + "wire_source_h_payto", + &td.details.kycauth_in.sender_account_h_payto), + GNUNET_PQ_result_spec_string ( + "exchange_account_section", + &td.details.kycauth_in.exchange_account_section), + GNUNET_PQ_result_spec_timestamp ( + "execution_date", + &td.details.kycauth_in.execution_date), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with reserves_close table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_reserves_close (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_RESERVES_CLOSE + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_pub", + &td.details.reserves_close.reserve_pub), + GNUNET_PQ_result_spec_timestamp ( + "execution_date", + &td.details.reserves_close.execution_date), + GNUNET_PQ_result_spec_auto_from_type ( + "wtid", + &td.details.reserves_close.wtid), + GNUNET_PQ_result_spec_auto_from_type ( + "wire_target_h_payto", + &td.details.reserves_close.sender_account_h_payto), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount", + &td.details.reserves_close.amount), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "closing_fee", + &td.details.reserves_close.closing_fee), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with reserves_open_requests table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_reserves_open_requests (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_pub", + &td.details.reserves_open_requests.reserve_pub), + GNUNET_PQ_result_spec_timestamp ( + "request_timestamp", + &td.details.reserves_open_requests.request_timestamp), + GNUNET_PQ_result_spec_timestamp ( + "expiration_date", + &td.details.reserves_open_requests.expiration_date), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_sig", + &td.details.reserves_open_requests.reserve_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "reserve_payment", + &td.details.reserves_open_requests.reserve_payment), + GNUNET_PQ_result_spec_uint32 ( + "requested_purse_limit", + &td.details.reserves_open_requests.requested_purse_limit), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with reserves_open_deposits table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_reserves_open_deposits (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_sig", + &td.details.reserves_open_deposits.reserve_sig), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_pub", + &td.details.reserves_open_deposits.reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "coin_pub", + &td.details.reserves_open_deposits.coin_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "coin_sig", + &td.details.reserves_open_deposits.coin_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "contribution", + &td.details.reserves_open_deposits.contribution), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with auditors table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_auditors (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_AUDITORS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ("auditor_pub", + &td.details.auditors.auditor_pub), + GNUNET_PQ_result_spec_string ("auditor_url", + &td.details.auditors.auditor_url), + GNUNET_PQ_result_spec_string ("auditor_name", + &td.details.auditors.auditor_name), + GNUNET_PQ_result_spec_bool ("is_active", + &td.details.auditors.is_active), + GNUNET_PQ_result_spec_timestamp ("last_change", + &td.details.auditors.last_change), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with auditor_denom_sigs table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_auditor_denom_sigs (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_uint64 ( + "auditor_uuid", + &td.details.auditor_denom_sigs.auditor_uuid), + GNUNET_PQ_result_spec_uint64 ( + "denominations_serial", + &td.details.auditor_denom_sigs.denominations_serial), + GNUNET_PQ_result_spec_auto_from_type ( + "auditor_sig", + &td.details.auditor_denom_sigs.auditor_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with exchange_sign_keys table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_exchange_sign_keys (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ("exchange_pub", + &td.details.exchange_sign_keys. + exchange_pub), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &td.details.exchange_sign_keys. + master_sig), + GNUNET_PQ_result_spec_timestamp ("valid_from", + &td.details.exchange_sign_keys.meta. + start), + GNUNET_PQ_result_spec_timestamp ("expire_sign", + &td.details.exchange_sign_keys.meta. + expire_sign), + GNUNET_PQ_result_spec_timestamp ("expire_legal", + &td.details.exchange_sign_keys.meta. + expire_legal), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with signkey_revocations table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_signkey_revocations (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_uint64 ("esk_serial", + &td.details.signkey_revocations.esk_serial), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &td.details.signkey_revocations. + master_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with known_coins table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_known_coins (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_KNOWN_COINS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "coin_pub", + &td.details.known_coins.coin_pub), + TALER_PQ_result_spec_denom_sig ( + "denom_sig", + &td.details.known_coins.denom_sig), + GNUNET_PQ_result_spec_uint64 ( + "denominations_serial", + &td.details.known_coins.denominations_serial), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with refresh table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_refresh (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_REFRESH + }; + + for (unsigned int i = 0; i<num_results; i++) + { + bool no_cs_r_values; + bool no_cs_r_choices; + size_t num_denom_sigs; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "rc", + &td.details.refresh.rc), + GNUNET_PQ_result_spec_auto_from_type ( + "execution_date", + &td.details.refresh.execution_date), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount_with_fee", + &td.details.refresh.amount_with_fee), + GNUNET_PQ_result_spec_auto_from_type ( + "old_coin_pub", + &td.details.refresh.old_coin_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "old_coin_sig", + &td.details.refresh.old_coin_sig), + GNUNET_PQ_result_spec_auto_from_type ( + "refresh_seed", + &td.details.refresh.refresh_seed), + GNUNET_PQ_result_spec_uint32 ( + "noreveal_index", + &td.details.refresh.noreveal_index), + GNUNET_PQ_result_spec_auto_from_type ( + "planchets_h", + &td.details.refresh.planchets_h), + GNUNET_PQ_result_spec_auto_from_type ( + "selected_h", + &td.details.refresh.selected_h), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ( + "blinding_seed", + &td.details.refresh.blinding_seed), + &td.details.refresh.no_blinding_seed), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_array_cs_r_pub ( + pg->conn, + "cs_r_values", + &td.details.refresh.num_cs_r_values, + &td.details.refresh.cs_r_values), + &no_cs_r_values), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ( + "cs_r_choices", + &td.details.refresh.cs_r_choices), + &no_cs_r_choices), + GNUNET_PQ_result_spec_array_uint64 ( + pg->conn, + "denom_serials", + &td.details.refresh.num_coins, + &td.details.refresh.denom_serials), + TALER_PQ_result_spec_array_blinded_denom_sig ( + pg->conn, + "denom_sigs", + &num_denom_sigs, + &td.details.refresh.denom_sigs), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + GNUNET_PQ_cleanup_result (rs); + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with batch deposits table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_batch_deposits (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_BATCH_DEPOSITS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_uint64 ( + "shard", + &td.details.batch_deposits.shard), + GNUNET_PQ_result_spec_auto_from_type ( + "merchant_pub", + &td.details.batch_deposits.merchant_pub), + GNUNET_PQ_result_spec_timestamp ( + "wallet_timestamp", + &td.details.batch_deposits.wallet_timestamp), + GNUNET_PQ_result_spec_timestamp ( + "exchange_timestamp", + &td.details.batch_deposits.exchange_timestamp), + GNUNET_PQ_result_spec_timestamp ( + "refund_deadline", + &td.details.batch_deposits.refund_deadline), + GNUNET_PQ_result_spec_timestamp ( + "wire_deadline", + &td.details.batch_deposits.wire_deadline), + GNUNET_PQ_result_spec_auto_from_type ( + "h_contract_terms", + &td.details.batch_deposits.h_contract_terms), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ( + "wallet_data_hash", + &td.details.batch_deposits.wallet_data_hash), + &td.details.batch_deposits.no_wallet_data_hash), + GNUNET_PQ_result_spec_auto_from_type ( + "wire_salt", + &td.details.batch_deposits.wire_salt), + GNUNET_PQ_result_spec_auto_from_type ( + "wire_target_h_payto", + &td.details.batch_deposits.wire_target_h_payto), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ( + "policy_details_serial_id", + &td.details.batch_deposits.policy_details_serial_id), + &td.details.batch_deposits.no_policy_details), + GNUNET_PQ_result_spec_bool ( + "policy_blocked", + &td.details.batch_deposits.policy_blocked), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "total_amount", + &td.details.batch_deposits.total_amount), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "total_without_fee", + &td.details.batch_deposits.total_without_fee), + GNUNET_PQ_result_spec_auto_from_type ( + "merchant_sig", + &td.details.batch_deposits.merchant_sig), + GNUNET_PQ_result_spec_bool ( + "done", + &td.details.batch_deposits.done), + GNUNET_PQ_result_spec_end + }; + + td.details.batch_deposits.policy_details_serial_id = 0; + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with coin deposits table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_coin_deposits (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_COIN_DEPOSITS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_uint64 ( + "batch_deposit_serial_id", + &td.details.coin_deposits.batch_deposit_serial_id), + GNUNET_PQ_result_spec_auto_from_type ( + "coin_pub", + &td.details.coin_deposits.coin_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "coin_sig", + &td.details.coin_deposits.coin_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount_with_fee", + &td.details.coin_deposits.amount_with_fee), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with refunds table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_refunds (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_REFUNDS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "coin_pub", + &td.details.refunds.coin_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "merchant_sig", + &td.details.refunds.merchant_sig), + GNUNET_PQ_result_spec_uint64 ( + "rtransaction_id", + &td.details.refunds.rtransaction_id), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount_with_fee", + &td.details.refunds.amount_with_fee), + GNUNET_PQ_result_spec_uint64 ( + "batch_deposit_serial_id", + &td.details.refunds.batch_deposit_serial_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with wire_out table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_wire_out (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_WIRE_OUT + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_timestamp ( + "execution_date", + &td.details.wire_out.execution_date), + GNUNET_PQ_result_spec_auto_from_type ( + "wtid_raw", + &td.details.wire_out.wtid_raw), + GNUNET_PQ_result_spec_auto_from_type ( + "wire_target_h_payto", + &td.details.wire_out.wire_target_h_payto), + GNUNET_PQ_result_spec_string ( + "exchange_account_section", + &td.details.wire_out.exchange_account_section), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount", + &td.details.wire_out.amount), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with aggregation_tracking table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_aggregation_tracking (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_uint64 ( + "batch_deposit_serial_id", + &td.details.aggregation_tracking.batch_deposit_serial_id), + GNUNET_PQ_result_spec_auto_from_type ( + "wtid_raw", + &td.details.aggregation_tracking.wtid_raw), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with wire_fee table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_wire_fee (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_WIRE_FEE + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_string ("wire_method", + &td.details.wire_fee.wire_method), + GNUNET_PQ_result_spec_timestamp ("start_date", + &td.details.wire_fee.start_date), + GNUNET_PQ_result_spec_timestamp ("end_date", + &td.details.wire_fee.end_date), + TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", + &td.details.wire_fee.fees.wire), + TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", + &td.details.wire_fee.fees.closing), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + &td.details.wire_fee.master_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with wire_fee table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_global_fee (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_GLOBAL_FEE + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "serial", + &td.serial), + GNUNET_PQ_result_spec_timestamp ( + "start_date", + &td.details.global_fee.start_date), + GNUNET_PQ_result_spec_timestamp ( + "end_date", + &td.details.global_fee.end_date), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "history_fee", + &td.details.global_fee.fees.history), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "account_fee", + &td.details.global_fee.fees.account), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "purse_fee", + &td.details.global_fee.fees.purse), + GNUNET_PQ_result_spec_relative_time ( + "purse_timeout", + &td.details.global_fee.purse_timeout), + GNUNET_PQ_result_spec_relative_time ( + "history_expiration", + &td.details.global_fee.history_expiration), + GNUNET_PQ_result_spec_uint32 ( + "purse_account_limit", + &td.details.global_fee.purse_account_limit), + GNUNET_PQ_result_spec_auto_from_type ( + "master_sig", + &td.details.global_fee.master_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with recoup table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_recoup (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_RECOUP + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &td.details.recoup.coin_sig), + GNUNET_PQ_result_spec_auto_from_type ("coin_blind", + &td.details.recoup.coin_blind), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &td.details.recoup.amount), + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + &td.details.recoup.timestamp), + GNUNET_PQ_result_spec_auto_from_type ( + "coin_pub", + &td.details.recoup.coin_pub), + GNUNET_PQ_result_spec_uint64 ("withdraw_serial_id", + &td.details.recoup.withdraw_serial_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with recoup_refresh table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_recoup_refresh (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_RECOUP_REFRESH + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &td.details.recoup_refresh.coin_sig) + , + GNUNET_PQ_result_spec_auto_from_type ( + "coin_blind", + &td.details.recoup_refresh.coin_blind), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &td.details.recoup_refresh.amount), + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + &td.details.recoup_refresh.timestamp), + GNUNET_PQ_result_spec_uint64 ("known_coin_id", + &td.details.recoup_refresh.known_coin_id), + GNUNET_PQ_result_spec_auto_from_type ( + "coin_pub", + &td.details.recoup_refresh.coin_pub), + GNUNET_PQ_result_spec_uint64 ("rrc_serial", + &td.details.recoup_refresh.rrc_serial), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with extensions table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_extensions (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_EXTENSIONS + }; + bool no_manifest = false; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("extension_id", + &td.serial), + GNUNET_PQ_result_spec_string ("name", + &td.details.extensions.name), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("manifest", + &td.details.extensions.manifest), + &no_manifest), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with policy_details table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_policy_details (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_POLICY_DETAILS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ("hash_code", + &td.details.policy_details. + hash_code), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("policy_json", + &td.details.policy_details. + policy_json), + &td.details.policy_details.no_policy_json), + GNUNET_PQ_result_spec_timestamp ("deadline", + &td.details.policy_details. + deadline), + TALER_PQ_RESULT_SPEC_AMOUNT ("commitment", + &td.details.policy_details. + commitment), + TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total", + &td.details.policy_details. + accumulated_total), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee", + &td.details.policy_details. + fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("transferable", + &td.details.policy_details. + transferable), + GNUNET_PQ_result_spec_uint16 ("fulfillment_state", + &td.details.policy_details. + fulfillment_state), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ("fulfillment_id", + &td.details.policy_details. + fulfillment_id), + &td.details.policy_details.no_fulfillment_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with policy_fulfillments table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_policy_fulfillments (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + bool no_proof = false; + bool no_timestamp = false; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("fulfillment_id", + &td.serial), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_timestamp ("fulfillment_timestamp", + &td.details.policy_fulfillments. + fulfillment_timestamp), + &no_timestamp), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("fulfillment_proof", + &td.details.policy_fulfillments. + fulfillment_proof), + &no_proof), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with purse_requests table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_purse_requests (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_PURSE_REQUESTS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "purse_requests_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_pub", + &td.details.purse_requests.purse_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "merge_pub", + &td.details.purse_requests.merge_pub), + GNUNET_PQ_result_spec_timestamp ( + "purse_creation", + &td.details.purse_requests.purse_creation), + GNUNET_PQ_result_spec_timestamp ( + "purse_expiration", + &td.details.purse_requests.purse_expiration), + GNUNET_PQ_result_spec_auto_from_type ( + "h_contract_terms", + &td.details.purse_requests.h_contract_terms), + GNUNET_PQ_result_spec_uint32 ( + "age_limit", + &td.details.purse_requests.age_limit), + GNUNET_PQ_result_spec_uint32 ( + "flags", + &td.details.purse_requests.flags), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount_with_fee", + &td.details.purse_requests.amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "purse_fee", + &td.details.purse_requests.purse_fee), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_sig", + &td.details.purse_requests.purse_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with purse_decision table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_purse_decision (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_PURSE_DECISION + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "purse_refunds_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_pub", + &td.details.purse_decision.purse_pub), + GNUNET_PQ_result_spec_timestamp ( + "action_timestamp", + &td.details.purse_decision.action_timestamp), + GNUNET_PQ_result_spec_bool ( + "refunded", + &td.details.purse_decision.refunded), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with purse_merges table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_purse_merges (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_PURSE_MERGES + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "purse_merge_request_serial_id", + &td.serial), + GNUNET_PQ_result_spec_uint64 ( + "partner_serial_id", + &td.details.purse_merges.partner_serial_id), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_pub", + &td.details.purse_merges.reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_pub", + &td.details.purse_merges.purse_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "merge_sig", + &td.details.purse_merges.merge_sig), + GNUNET_PQ_result_spec_timestamp ( + "merge_timestamp", + &td.details.purse_merges.merge_timestamp), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with purse_deposits table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_purse_deposits (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_PURSE_DEPOSITS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "purse_deposit_serial_id", + &td.serial), + GNUNET_PQ_result_spec_uint64 ( + "partner_serial_id", + &td.details.purse_deposits.partner_serial_id), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_pub", + &td.details.purse_deposits.purse_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "coin_pub", + &td.details.purse_deposits.coin_pub), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount_with_fee", + &td.details.purse_deposits.amount_with_fee), + GNUNET_PQ_result_spec_auto_from_type ( + "coin_sig", + &td.details.purse_deposits.coin_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with account_merges table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_account_merges (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_ACCOUNT_MERGES + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "account_merge_request_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_pub", + &td.details.account_merges.reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_sig", + &td.details.account_merges.reserve_sig), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_pub", + &td.details.account_merges.purse_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "wallet_h_payto", + &td.details.account_merges.wallet_h_payto), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with history_requests table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_history_requests (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_HISTORY_REQUESTS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "history_request_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_pub", + &td.details.history_requests.reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_sig", + &td.details.history_requests.reserve_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "history_fee", + &td.details.history_requests.history_fee), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with close_requests table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_close_requests (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_CLOSE_REQUESTS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "close_request_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_pub", + &td.details.close_requests.reserve_pub), + GNUNET_PQ_result_spec_timestamp ( + "close_timestamp", + &td.details.close_requests.close_timestamp), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_sig", + &td.details.close_requests.reserve_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "close", + &td.details.close_requests.close), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "close_fee", + &td.details.close_requests.close_fee), + GNUNET_PQ_result_spec_string ( + "payto_uri", + &td.details.close_requests.payto_uri.full_payto), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with wads_out table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_wads_out (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_WADS_OUT + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "wad_out_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "wad_id", + &td.details.wads_out.wad_id), + GNUNET_PQ_result_spec_uint64 ( + "partner_serial_id", + &td.details.wads_out.partner_serial_id), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount", + &td.details.wads_out.amount), + GNUNET_PQ_result_spec_timestamp ( + "execution_time", + &td.details.wads_out.execution_time), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with wads_out_entries table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_wads_out_entries (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "wad_out_entry_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_pub", + &td.details.wads_out_entries.reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_pub", + &td.details.wads_out_entries.purse_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "h_contract", + &td.details.wads_out_entries.h_contract), + GNUNET_PQ_result_spec_timestamp ( + "purse_expiration", + &td.details.wads_out_entries.purse_expiration), + GNUNET_PQ_result_spec_timestamp ( + "merge_timestamp", + &td.details.wads_out_entries.merge_timestamp), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount_with_fee", + &td.details.wads_out_entries.amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "wad_fee", + &td.details.wads_out_entries.wad_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "deposit_fees", + &td.details.wads_out_entries.deposit_fees), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_sig", + &td.details.wads_out_entries.reserve_sig), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_sig", + &td.details.wads_out_entries.purse_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with wads_in table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_wads_in (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_WADS_IN + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "wad_in_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "wad_id", + &td.details.wads_in.wad_id), + GNUNET_PQ_result_spec_string ( + "origin_exchange_url", + &td.details.wads_in.origin_exchange_url), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount", + &td.details.wads_in.amount), + GNUNET_PQ_result_spec_timestamp ( + "arrival_time", + &td.details.wads_in.arrival_time), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with wads_in_entries table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_wads_in_entries (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "wad_in_entry_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_pub", + &td.details.wads_in_entries.reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_pub", + &td.details.wads_in_entries.purse_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "h_contract", + &td.details.wads_in_entries.h_contract), + GNUNET_PQ_result_spec_timestamp ( + "purse_expiration", + &td.details.wads_in_entries.purse_expiration), + GNUNET_PQ_result_spec_timestamp ( + "merge_timestamp", + &td.details.wads_in_entries.merge_timestamp), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount_with_fee", + &td.details.wads_in_entries.amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "wad_fee", + &td.details.wads_in_entries.wad_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "deposit_fees", + &td.details.wads_in_entries.deposit_fees), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_sig", + &td.details.wads_in_entries.reserve_sig), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_sig", + &td.details.wads_in_entries.purse_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with profit_drains table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_profit_drains (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_PROFIT_DRAINS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "profit_drain_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "wtid", + &td.details.profit_drains.wtid), + GNUNET_PQ_result_spec_string ( + "account_section", + &td.details.profit_drains.account_section), + GNUNET_PQ_result_spec_string ( + "payto_uri", + &td.details.profit_drains.payto_uri.full_payto), + GNUNET_PQ_result_spec_timestamp ( + "trigger_date", + &td.details.profit_drains.trigger_date), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount", + &td.details.profit_drains.amount), + GNUNET_PQ_result_spec_auto_from_type ( + "master_sig", + &td.details.profit_drains.master_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with aml_staff table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_aml_staff (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_AML_STAFF + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "aml_staff_uuid", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "decider_pub", + &td.details.aml_staff.decider_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "master_sig", + &td.details.aml_staff.master_sig), + GNUNET_PQ_result_spec_string ( + "decider_name", + &td.details.aml_staff.decider_name), + GNUNET_PQ_result_spec_bool ( + "is_active", + &td.details.aml_staff.is_active), + GNUNET_PQ_result_spec_bool ( + "read_only", + &td.details.aml_staff.read_only), + GNUNET_PQ_result_spec_timestamp ( + "last_change", + &td.details.aml_staff.last_change), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with purse_deletion table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_purse_deletion (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_PURSE_DELETION + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "purse_deletion_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_sig", + &td.details.purse_deletion.purse_sig), + GNUNET_PQ_result_spec_auto_from_type ( + "purse_pub", + &td.details.purse_deletion.purse_pub), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with withdraw table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_withdraw (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_WITHDRAW + }; + + for (unsigned int i = 0; i<num_results; i++) + { + bool no_max_age; + bool no_noreveal_index; + bool no_selected_h; + bool no_cs_r_values; + bool no_cs_r_choices; + size_t num_sigs; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "withdraw_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "planchets_h", + &td.details.withdraw.planchets_h), + GNUNET_PQ_result_spec_timestamp ( + "execution_date", + &td.details.withdraw.execution_date), + TALER_PQ_RESULT_SPEC_AMOUNT ( + "amount_with_fee", + &td.details.withdraw.amount_with_fee), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_pub", + &td.details.withdraw.reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "reserve_sig", + &td.details.withdraw.reserve_sig), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint16 ( + "max_age", + &td.details.withdraw.max_age), + &no_max_age), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint16 ( + "noreveal_index", + &td.details.withdraw.noreveal_index), + &no_noreveal_index), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ( + "selected_h", + &td.details.withdraw.selected_h), + &no_selected_h), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ( + "blinding_seed", + &td.details.withdraw.blinding_seed), + &td.details.withdraw.no_blinding_seed), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_array_cs_r_pub ( + pg->conn, + "cs_r_values", + &td.details.withdraw.num_cs_r_values, + &td.details.withdraw.cs_r_values), + &no_cs_r_values), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ( + "cs_r_choices", + &td.details.withdraw.cs_r_choices), + &no_cs_r_choices), + GNUNET_PQ_result_spec_array_uint64 ( + pg->conn, + "denom_serials", + &td.details.withdraw.num_coins, + &td.details.withdraw.denom_serials), + TALER_PQ_result_spec_array_blinded_denom_sig ( + pg->conn, + "denom_sigs", + &num_sigs, + &td.details.withdraw.denom_sigs), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + GNUNET_PQ_cleanup_result (rs); + return; + } + if (num_sigs != td.details.withdraw.num_coins) + { + GNUNET_break (0); + ctx->error = true; + GNUNET_PQ_cleanup_result (rs); + return; + } + if (no_max_age != no_noreveal_index) + { + GNUNET_break (0); + ctx->error = true; + GNUNET_PQ_cleanup_result (rs); + return; + } + if (no_max_age != no_selected_h) + { + GNUNET_break (0); + ctx->error = true; + GNUNET_PQ_cleanup_result (rs); + return; + } + if (no_cs_r_values != no_cs_r_choices) + { + GNUNET_break (0); + ctx->error = true; + GNUNET_PQ_cleanup_result (rs); + return; + } + if (no_cs_r_values != td.details.withdraw.no_blinding_seed) + { + GNUNET_break (0); + ctx->error = true; + GNUNET_PQ_cleanup_result (rs); + return; + } + td.details.withdraw.age_proof_required = ! no_max_age; + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with legitimization_measures table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_legitimization_measures (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "access_token", + &td.details.legitimization_measures.target_token), + GNUNET_PQ_result_spec_timestamp ( + "start_time", + &td.details.legitimization_measures.start_time), + TALER_PQ_result_spec_json ( + "jmeasures", + &td.details.legitimization_measures.measures), + GNUNET_PQ_result_spec_uint32 ( + "display_priority", + &td.details.legitimization_measures.display_priority), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with legitimization_outcomes table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_legitimization_outcomes (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "h_payto", + &td.details.legitimization_outcomes.h_payto), + GNUNET_PQ_result_spec_timestamp ( + "decision_time", + &td.details.legitimization_outcomes.decision_time), + GNUNET_PQ_result_spec_timestamp ( + "expiration_time", + &td.details.legitimization_outcomes.expiration_time), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ( + "jproperties", + &td.details.legitimization_outcomes.properties), + NULL), + GNUNET_PQ_result_spec_bool ( + "to_investigate_id", + &td.details.legitimization_outcomes.to_investigate), + TALER_PQ_result_spec_json ( + "jnew_rules", + &td.details.legitimization_outcomes.new_rules), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with legitimization_processes table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_legitimization_processes (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "h_payto", + &td.details.legitimization_processes.h_payto), + GNUNET_PQ_result_spec_timestamp ( + "start_time", + &td.details.legitimization_processes.start_time), + GNUNET_PQ_result_spec_timestamp ( + "expiration_time", + &td.details.legitimization_processes.expiration_time), + GNUNET_PQ_result_spec_uint64 ( + "legitimization_measure_serial_id", + &td.details.legitimization_processes.legitimization_measure_serial_id), + GNUNET_PQ_result_spec_uint32 ( + "measure_index", + &td.details.legitimization_processes.measure_index), + GNUNET_PQ_result_spec_string ( + "provider_name", + &td.details.legitimization_processes.provider_name), + GNUNET_PQ_result_spec_string ( + "provider_user_id", + &td.details.legitimization_processes.provider_user_id), + GNUNET_PQ_result_spec_string ( + "provider_legitimization_id", + &td.details.legitimization_processes.provider_legitimization_id), + GNUNET_PQ_result_spec_string ( + "redirect_url", + &td.details.legitimization_processes.redirect_url), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with kyc_attributes table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_kyc_attributes (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "kyc_attributes_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "h_payto", + &td.details.kyc_attributes.h_payto), + GNUNET_PQ_result_spec_uint64 ( + "legitimization_serial", + &td.details.kyc_attributes.legitimization_serial), + GNUNET_PQ_result_spec_timestamp ( + "collection_time", + &td.details.kyc_attributes.collection_time), + GNUNET_PQ_result_spec_timestamp ( + "expiration_time", + &td.details.kyc_attributes.expiration_time), + GNUNET_PQ_result_spec_uint64 ( + "trigger_outcome_serial", + &td.details.kyc_attributes.trigger_outcome_serial), + GNUNET_PQ_result_spec_variable_size ( + "encrypted_attributes", + &td.details.kyc_attributes.encrypted_attributes, + &td.details.kyc_attributes.encrypted_attributes_size), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with aml_history table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_aml_history (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_AML_HISTORY + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "aml_history_serial_id", + &td.serial), + GNUNET_PQ_result_spec_auto_from_type ( + "h_payto", + &td.details.aml_history.h_payto), + GNUNET_PQ_result_spec_uint64 ( + "outcome_serial_id", + &td.details.aml_history.outcome_serial_id), + GNUNET_PQ_result_spec_string ( + "justification", + &td.details.aml_history.justification), + GNUNET_PQ_result_spec_auto_from_type ( + "decider_pub", + &td.details.aml_history.decider_pub), + GNUNET_PQ_result_spec_auto_from_type ( + "decider_sig", + &td.details.aml_history.decider_sig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Function called with kyc_events table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_kyc_events (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_KYC_EVENTS + }; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "kyc_event_serial_id", + &td.serial), + GNUNET_PQ_result_spec_timestamp ( + "event_timestamp", + &td.details.kyc_events.event_timestamp), + GNUNET_PQ_result_spec_string ( + "event_type", + &td.details.kyc_events.event_type), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->error = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Assign statement to @a n and PREPARE + * @a sql under name @a n. + */ +#define XPREPARE(n,sql) \ + statement = n; \ + PREPARE (pg, n, sql); + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_records_by_table ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + enum TALER_EXCHANGEDB_ReplicatedTable table, + uint64_t serial, + TALER_EXCHANGEDB_ReplicationCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial), + GNUNET_PQ_query_param_end + }; + struct LookupRecordsByTableContext ctx = { + .pg = pg, + .cb = cb, + .cb_cls = cb_cls + }; + GNUNET_PQ_PostgresResultHandler rh = NULL; + const char *statement = NULL; + enum GNUNET_DB_QueryStatus qs; + + switch (table) + { + case TALER_EXCHANGEDB_RT_DENOMINATIONS: + XPREPARE ("select_above_serial_by_table_denominations", + "SELECT" + " denominations_serial AS serial" + ",denom_type" + ",denom_pub" + ",master_sig" + ",valid_from" + ",expire_withdraw" + ",expire_deposit" + ",expire_legal" + ",coin" + ",fee_withdraw" + ",fee_deposit" + ",fee_refresh" + ",fee_refund" + ",age_mask" + " FROM denominations" + " WHERE denominations_serial > $1" + " ORDER BY denominations_serial ASC;"); + rh = &lrbt_cb_table_denominations; + break; + case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS: + XPREPARE ("select_above_serial_by_table_denomination_revocations", + "SELECT" + " denom_revocations_serial_id AS serial" + ",master_sig" + ",denominations_serial" + " FROM denomination_revocations" + " WHERE denom_revocations_serial_id > $1" + " ORDER BY denom_revocations_serial_id ASC;"); + rh = &lrbt_cb_table_denomination_revocations; + break; + case TALER_EXCHANGEDB_RT_WIRE_TARGETS: + XPREPARE ("select_above_serial_by_table_wire_targets", + "SELECT" + " wire_target_serial_id AS serial" + ",payto_uri" + " FROM wire_targets" + " WHERE wire_target_serial_id > $1" + " ORDER BY wire_target_serial_id ASC;"); + rh = &lrbt_cb_table_wire_targets; + break; + case TALER_EXCHANGEDB_RT_KYC_TARGETS: + XPREPARE ("select_above_serial_by_table_kyc_targets", + "SELECT" + " kyc_target_serial_id AS serial" + ",h_normalized_payto" + ",access_token" + ",target_pub" + ",is_wallet" + " FROM kyc_targets" + " WHERE kyc_target_serial_id > $1" + " ORDER BY kyc_target_serial_id ASC;"); + rh = &lrbt_cb_table_kyc_targets; + break; + case TALER_EXCHANGEDB_RT_RESERVES: + XPREPARE ("select_above_serial_by_table_reserves", + "SELECT" + " reserve_uuid AS serial" + ",reserve_pub" + ",expiration_date" + ",gc_date" + " FROM reserves" + " WHERE reserve_uuid > $1" + " ORDER BY reserve_uuid ASC;"); + rh = &lrbt_cb_table_reserves; + break; + case TALER_EXCHANGEDB_RT_RESERVES_IN: + XPREPARE ("select_above_serial_by_table_reserves_in", + "SELECT" + " reserve_in_serial_id AS serial" + ",reserve_pub" + ",wire_reference" + ",credit" + ",wire_source_h_payto" + ",exchange_account_section" + ",execution_date" + " FROM reserves_in" + " WHERE reserve_in_serial_id > $1" + " ORDER BY reserve_in_serial_id ASC;"); + rh = &lrbt_cb_table_reserves_in; + break; + case TALER_EXCHANGEDB_RT_KYCAUTHS_IN: + XPREPARE ("select_above_serial_by_table_kycauth_in", + "SELECT" + " kycauth_in_serial_id AS serial" + ",account_pub" + ",wire_reference" + ",credit" + ",wire_source_h_payto" + ",exchange_account_section" + ",execution_date" + " FROM kycauths_in" + " WHERE kycauth_in_serial_id > $1" + " ORDER BY kycauth_in_serial_id ASC;"); + rh = &lrbt_cb_table_kycauth_in; + break; + case TALER_EXCHANGEDB_RT_RESERVES_CLOSE: + XPREPARE ("select_above_serial_by_table_reserves_close", + "SELECT" + " close_uuid AS serial" + ",reserve_pub" + ",execution_date" + ",wtid" + ",wire_target_h_payto" + ",amount" + ",closing_fee" + " FROM reserves_close" + " WHERE close_uuid > $1" + " ORDER BY close_uuid ASC;"); + rh = &lrbt_cb_table_reserves_close; + break; + case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS: + XPREPARE ("select_above_serial_by_table_reserves_open_requests", + "SELECT" + " open_request_uuid AS serial" + ",reserve_pub" + ",request_timestamp" + ",expiration_date" + ",reserve_sig" + ",reserve_payment" + ",requested_purse_limit" + " FROM reserves_open_requests" + " WHERE open_request_uuid > $1" + " ORDER BY open_request_uuid ASC;"); + rh = &lrbt_cb_table_reserves_open_requests; + break; + case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS: + XPREPARE ("select_above_serial_by_table_reserves_open_deposits", + "SELECT" + " reserves_open_deposit_uuid AS serial" + ",reserve_sig" + ",reserve_pub" + ",coin_pub" + ",coin_sig" + ",contribution" + " FROM reserves_open_deposits" + " WHERE reserves_open_deposit_uuid > $1" + " ORDER BY reserves_open_deposit_uuid ASC;"); + rh = &lrbt_cb_table_reserves_open_deposits; + break; + case TALER_EXCHANGEDB_RT_AUDITORS: + XPREPARE ("select_above_serial_by_table_auditors", + "SELECT" + " auditor_uuid AS serial" + ",auditor_pub" + ",auditor_name" + ",auditor_url" + ",is_active" + ",last_change" + " FROM auditors" + " WHERE auditor_uuid > $1" + " ORDER BY auditor_uuid ASC;"); + rh = &lrbt_cb_table_auditors; + break; + case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS: + XPREPARE ("select_above_serial_by_table_auditor_denom_sigs", + "SELECT" + " auditor_denom_serial AS serial" + ",auditor_uuid" + ",denominations_serial" + ",auditor_sig" + " FROM auditor_denom_sigs" + " WHERE auditor_denom_serial > $1" + " ORDER BY auditor_denom_serial ASC;"); + rh = &lrbt_cb_table_auditor_denom_sigs; + break; + case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS: + XPREPARE ("select_above_serial_by_table_exchange_sign_keys", + "SELECT" + " esk_serial AS serial" + ",exchange_pub" + ",master_sig" + ",valid_from" + ",expire_sign" + ",expire_legal" + " FROM exchange_sign_keys" + " WHERE esk_serial > $1" + " ORDER BY esk_serial ASC;"); + rh = &lrbt_cb_table_exchange_sign_keys; + break; + case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS: + XPREPARE ("select_above_serial_by_table_signkey_revocations", + "SELECT" + " signkey_revocations_serial_id AS serial" + ",esk_serial" + ",master_sig" + " FROM signkey_revocations" + " WHERE signkey_revocations_serial_id > $1" + " ORDER BY signkey_revocations_serial_id ASC;"); + rh = &lrbt_cb_table_signkey_revocations; + break; + case TALER_EXCHANGEDB_RT_KNOWN_COINS: + XPREPARE ("select_above_serial_by_table_known_coins", + "SELECT" + " known_coin_id AS serial" + ",coin_pub" + ",denom_sig" + ",denominations_serial" + " FROM known_coins" + " WHERE known_coin_id > $1" + " ORDER BY known_coin_id ASC;"); + rh = &lrbt_cb_table_known_coins; + break; + case TALER_EXCHANGEDB_RT_REFRESH: + XPREPARE ("select_above_serial_by_table_refresh", + "SELECT" + " refresh_id AS serial" + ",rc" + ",execution_date" + ",amount_with_fee" + ",old_coin_pub" + ",old_coin_sig" + ",refresh_seed" + ",noreveal_index" + ",planchets_h" + ",selected_h" + ",blinding_seed" + ",cs_r_values" + ",cs_r_choices" + ",denom_serials" + ",denom_sigs" + " FROM refresh" + " WHERE refresh_id > $1" + " ORDER BY refresh_id ASC;"); + rh = &lrbt_cb_table_refresh; + break; + case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS: + XPREPARE ("select_above_serial_by_table_batch_deposits", + "SELECT" + " batch_deposit_serial_id AS serial" + ",shard" + ",merchant_pub" + ",wallet_timestamp" + ",exchange_timestamp" + ",refund_deadline" + ",wire_deadline" + ",h_contract_terms" + ",wallet_data_hash" + ",wire_salt" + ",wire_target_h_payto" + ",policy_details_serial_id" + ",policy_blocked" + ",total_amount" + ",total_without_fee" + ",merchant_sig" + ",done" + " FROM batch_deposits" + " WHERE batch_deposit_serial_id > $1" + " ORDER BY batch_deposit_serial_id ASC;"); + rh = &lrbt_cb_table_batch_deposits; + break; + case TALER_EXCHANGEDB_RT_COIN_DEPOSITS: + XPREPARE ("select_above_serial_by_table_coin_deposits", + "SELECT" + " coin_deposit_serial_id AS serial" + ",batch_deposit_serial_id" + ",coin_pub" + ",coin_sig" + ",amount_with_fee" + " FROM coin_deposits" + " WHERE coin_deposit_serial_id > $1" + " ORDER BY coin_deposit_serial_id ASC;"); + rh = &lrbt_cb_table_coin_deposits; + break; + case TALER_EXCHANGEDB_RT_REFUNDS: + XPREPARE ("select_above_serial_by_table_refunds", + "SELECT" + " refund_serial_id AS serial" + ",coin_pub" + ",merchant_sig" + ",rtransaction_id" + ",amount_with_fee" + ",batch_deposit_serial_id" + " FROM refunds" + " WHERE refund_serial_id > $1" + " ORDER BY refund_serial_id ASC;"); + rh = &lrbt_cb_table_refunds; + break; + case TALER_EXCHANGEDB_RT_WIRE_OUT: + XPREPARE ("select_above_serial_by_table_wire_out", + "SELECT" + " wireout_uuid AS serial" + ",execution_date" + ",wtid_raw" + ",wire_target_h_payto" + ",exchange_account_section" + ",amount" + " FROM wire_out" + " WHERE wireout_uuid > $1" + " ORDER BY wireout_uuid ASC;"); + rh = &lrbt_cb_table_wire_out; + break; + case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING: + XPREPARE ("select_above_serial_by_table_aggregation_tracking", + "SELECT" + " aggregation_serial_id AS serial" + ",batch_deposit_serial_id" + ",wtid_raw" + " FROM aggregation_tracking" + " WHERE aggregation_serial_id > $1" + " ORDER BY aggregation_serial_id ASC;"); + rh = &lrbt_cb_table_aggregation_tracking; + break; + case TALER_EXCHANGEDB_RT_WIRE_FEE: + XPREPARE ("select_above_serial_by_table_wire_fee", + "SELECT" + " wire_fee_serial AS serial" + ",wire_method" + ",start_date" + ",end_date" + ",wire_fee" + ",closing_fee" + ",master_sig" + " FROM wire_fee" + " WHERE wire_fee_serial > $1" + " ORDER BY wire_fee_serial ASC;"); + rh = &lrbt_cb_table_wire_fee; + break; + case TALER_EXCHANGEDB_RT_GLOBAL_FEE: + XPREPARE ("select_above_serial_by_table_global_fee", + "SELECT" + " global_fee_serial AS serial" + ",start_date" + ",end_date" + ",history_fee" + ",account_fee" + ",purse_fee" + ",purse_timeout" + ",history_expiration" + ",purse_account_limit" + ",master_sig" + " FROM global_fee" + " WHERE global_fee_serial > $1" + " ORDER BY global_fee_serial ASC;"); + rh = &lrbt_cb_table_global_fee; + break; + case TALER_EXCHANGEDB_RT_RECOUP: + XPREPARE ("select_above_serial_by_table_recoup", + "SELECT" + " recoup_uuid AS serial" + ",coin_sig" + ",coin_blind" + ",amount" + ",recoup_timestamp" + ",coin_pub" + ",reserve_out_serial_id" + " FROM recoup" + " WHERE recoup_uuid > $1" + " ORDER BY recoup_uuid ASC;"); + rh = &lrbt_cb_table_recoup; + break; + case TALER_EXCHANGEDB_RT_RECOUP_REFRESH: + XPREPARE ("select_above_serial_by_table_recoup_refresh", + "SELECT" + " recoup_refresh_uuid AS serial" + ",coin_sig" + ",coin_blind" + ",amount" + ",recoup_timestamp" + ",coin_pub" + ",known_coin_id" + ",rrc_serial" + " FROM recoup_refresh" + " WHERE recoup_refresh_uuid > $1" + " ORDER BY recoup_refresh_uuid ASC;"); + rh = &lrbt_cb_table_recoup_refresh; + break; + case TALER_EXCHANGEDB_RT_EXTENSIONS: + // FIXME: this seems broken! -- where is the SQL!? + statement = "select_above_serial_by_table_extensions"; + rh = &lrbt_cb_table_extensions; + break; + case TALER_EXCHANGEDB_RT_POLICY_DETAILS: + // FIXME: this seems broken! -- where is the SQL!? + statement = "select_above_serial_by_table_policy_details"; + rh = &lrbt_cb_table_policy_details; + break; + case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS: + // FIXME: this seems broken! -- where is the SQL!? + statement = "select_above_serial_by_table_policy_fulfillments"; + rh = &lrbt_cb_table_policy_fulfillments; + break; + case TALER_EXCHANGEDB_RT_PURSE_REQUESTS: + XPREPARE ("select_above_serial_by_table_purse_requests", + "SELECT" + " purse_requests_serial_id" + ",purse_pub" + ",merge_pub" + ",purse_creation" + ",purse_expiration" + ",h_contract_terms" + ",age_limit" + ",flags" + ",amount_with_fee" + ",purse_fee" + ",purse_sig" + " FROM purse_requests" + " WHERE purse_requests_serial_id > $1" + " ORDER BY purse_requests_serial_id ASC;"); + rh = &lrbt_cb_table_purse_requests; + break; + case TALER_EXCHANGEDB_RT_PURSE_DECISION: + XPREPARE ("select_above_serial_by_table_purse_decision", + "SELECT" + " purse_decision_serial_id" + ",action_timestamp" + ",refunded" + ",purse_pub" + " FROM purse_decision" + " WHERE purse_decision_serial_id > $1" + " ORDER BY purse_decision_serial_id ASC;"); + rh = &lrbt_cb_table_purse_decision; + break; + case TALER_EXCHANGEDB_RT_PURSE_MERGES: + XPREPARE ("select_above_serial_by_table_purse_merges", + "SELECT" + " purse_merge_request_serial_id" + ",partner_serial_id" + ",reserve_pub" + ",purse_pub" + ",merge_sig" + ",merge_timestamp" + " FROM purse_merges" + " WHERE purse_merge_request_serial_id > $1" + " ORDER BY purse_merge_request_serial_id ASC;"); + rh = &lrbt_cb_table_purse_merges; + break; + case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS: + XPREPARE ("select_above_serial_by_table_purse_deposits", + "SELECT" + " purse_deposit_serial_id" + ",partner_serial_id" + ",purse_pub" + ",coin_pub" + ",amount_with_fee" + ",coin_sig" + " FROM purse_deposits" + " WHERE purse_deposit_serial_id > $1" + " ORDER BY purse_deposit_serial_id ASC;"); + rh = &lrbt_cb_table_purse_deposits; + break; + case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES: + XPREPARE ("select_above_serial_by_table_account_merges", + "SELECT" + " account_merge_request_serial_id" + ",reserve_pub" + ",reserve_sig" + ",purse_pub" + ",wallet_h_payto" + " FROM account_merges" + " WHERE account_merge_request_serial_id > $1" + " ORDER BY account_merge_request_serial_id ASC;"); + rh = &lrbt_cb_table_account_merges; + break; + case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS: + XPREPARE ("select_above_serial_by_table_history_requests", + "SELECT" + " history_request_serial_id" + ",reserve_pub" + ",request_timestamp" + ",reserve_sig" + ",history_fee" + " FROM history_requests" + " WHERE history_request_serial_id > $1" + " ORDER BY history_request_serial_id ASC;"); + rh = &lrbt_cb_table_history_requests; + break; + case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS: + XPREPARE ("select_above_serial_by_table_close_requests", + "SELECT" + " close_request_serial_id" + ",reserve_pub" + ",close_timestamp" + ",reserve_sig" + ",close" + " FROM close_requests" + " WHERE close_request_serial_id > $1" + " ORDER BY close_request_serial_id ASC;"); + rh = &lrbt_cb_table_close_requests; + break; + case TALER_EXCHANGEDB_RT_WADS_OUT: + XPREPARE ("select_above_serial_by_table_wads_out", + "SELECT" + " wad_out_serial_id" + ",wad_id" + ",partner_serial_id" + ",amount" + ",execution_time" + " FROM wads_out" + " WHERE wad_out_serial_id > $1" + " ORDER BY wad_out_serial_id ASC;"); + rh = &lrbt_cb_table_wads_out; + break; + case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES: + XPREPARE ("select_above_serial_by_table_wads_out_entries", + "SELECT" + " wad_out_entry_serial_id" + ",reserve_pub" + ",purse_pub" + ",h_contract" + ",purse_expiration" + ",merge_timestamp" + ",amount_with_fee" + ",wad_fee" + ",deposit_fees" + ",reserve_sig" + ",purse_sig" + " FROM wad_out_entries" + " WHERE wad_out_entry_serial_id > $1" + " ORDER BY wad_out_entry_serial_id ASC;"); + rh = &lrbt_cb_table_wads_out_entries; + break; + case TALER_EXCHANGEDB_RT_WADS_IN: + XPREPARE ("select_above_serial_by_table_wads_in", + "SELECT" + " wad_in_serial_id" + ",wad_id" + ",origin_exchange_url" + ",amount" + ",arrival_time" + " FROM wads_in" + " WHERE wad_in_serial_id > $1" + " ORDER BY wad_in_serial_id ASC;"); + rh = &lrbt_cb_table_wads_in; + break; + case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES: + XPREPARE ("select_above_serial_by_table_wads_in_entries", + "SELECT" + " wad_in_entry_serial_id" + ",reserve_pub" + ",purse_pub" + ",h_contract" + ",purse_expiration" + ",merge_timestamp" + ",amount_with_fee" + ",wad_fee" + ",deposit_fees" + ",reserve_sig" + ",purse_sig" + " FROM wad_in_entries" + " WHERE wad_in_entry_serial_id > $1" + " ORDER BY wad_in_entry_serial_id ASC;"); + rh = &lrbt_cb_table_wads_in_entries; + break; + case TALER_EXCHANGEDB_RT_PROFIT_DRAINS: + XPREPARE ("select_above_serial_by_table_profit_drains", + "SELECT" + " profit_drain_serial_id" + ",wtid" + ",account_section" + ",payto_uri" + ",trigger_date" + ",amount" + ",master_sig" + " FROM profit_drains" + " WHERE profit_drain_serial_id > $1" + " ORDER BY profit_drain_serial_id ASC;"); + rh = &lrbt_cb_table_profit_drains; + break; + + case TALER_EXCHANGEDB_RT_AML_STAFF: + XPREPARE ("select_above_serial_by_table_aml_staff", + "SELECT" + " aml_staff_uuid" + ",decider_pub" + ",master_sig" + ",decider_name" + ",is_active" + ",read_only" + ",last_change" + " FROM aml_staff" + " WHERE aml_staff_uuid > $1" + " ORDER BY aml_staff_uuid ASC;"); + rh = &lrbt_cb_table_aml_staff; + break; + case TALER_EXCHANGEDB_RT_PURSE_DELETION: + XPREPARE ("select_above_serial_by_table_purse_deletion", + "SELECT" + " purse_deletion_serial_id" + ",purse_pub" + ",purse_sig" + " FROM purse_deletion" + " WHERE purse_deletion_serial_id > $1" + " ORDER BY purse_deletion_serial_id ASC;"); + rh = &lrbt_cb_table_purse_deletion; + break; + case TALER_EXCHANGEDB_RT_WITHDRAW: + XPREPARE ("select_above_serial_by_table_withdraw", + "SELECT" + " withdraw_id" + ",planchets_h" + ",execution_date" + ",amount_with_fee" + ",reserve_pub" + ",reserve_sig" + ",max_age" + ",noreveal_index" + ",selected_h" + ",blinding_seed" + ",cs_r_values" + ",cs_r_choices" + ",denom_serials" + ",denom_sigs" + " FROM withdraw" + " WHERE withdraw_id > $1" + " ORDER BY withdraw_id ASC;"); + rh = &lrbt_cb_table_withdraw; + break; + case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES: + XPREPARE ("select_above_serial_by_table_legitimization_measures", + "SELECT" + " legitimization_measure_serial_id AS serial" + ",access_token" + ",start_time" + ",jmeasures::TEXT" + ",display_priority" + " FROM legitimization_measures" + " WHERE legitimization_measure_serial_id > $1" + " ORDER BY legitimization_measure_serial_id ASC;"); + rh = &lrbt_cb_table_legitimization_measures; + break; + case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES: + XPREPARE ("select_above_serial_by_table_legitimization_outcomes", + "SELECT" + " outcome_serial_id AS serial" + ",h_payto" + ",decision_time" + ",expiration_time" + ",jproperties::TEXT" + ",to_investigate" + ",jnew_rules::TEXT" + " FROM legitimization_outcomes" + " WHERE outcome_serial_id > $1" + " ORDER BY outcome_serial_id ASC;"); + rh = &lrbt_cb_table_legitimization_outcomes; + break; + case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES: + XPREPARE ("select_above_serial_by_table_legitimization_processes", + "SELECT" + " legitimization_process_serial_id AS serial" + ",h_payto" + ",start_time" + ",expiration_time" + ",legitimization_measure_serial_id" + ",measure_index" + ",provider_name" + ",provider_user_id" + ",provider_legitimization_id" + ",redirect_url" + " FROM legitimization_processes" + " WHERE legitimization_process_serial_id > $1" + " ORDER BY legitimization_process_serial_id ASC;"); + rh = &lrbt_cb_table_legitimization_processes; + break; + case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES: + XPREPARE ("select_above_serial_by_table_kyc_attributes", + "SELECT" + " kyc_attributes_serial_id" + ",h_payto" + ",legitimization_serial" + ",collection_time" + ",expiration_time" + ",trigger_outcome_serial" + ",encrypted_attributes" + " FROM kyc_attributes" + " WHERE kyc_attributes_serial_id > $1" + " ORDER BY kyc_attributes_serial_id ASC;"); + rh = &lrbt_cb_table_kyc_attributes; + break; + case TALER_EXCHANGEDB_RT_AML_HISTORY: + XPREPARE ("select_above_serial_by_table_aml_history", + "SELECT" + " aml_history_serial_id" + ",h_payto" + ",outcome_serial_id" + ",justification" + ",decider_pub" + ",decider_sig" + " FROM aml_history" + " WHERE aml_history_serial_id > $1" + " ORDER BY aml_history_serial_id ASC;"); + rh = &lrbt_cb_table_aml_history; + break; + case TALER_EXCHANGEDB_RT_KYC_EVENTS: + XPREPARE ("select_above_serial_by_table_kyc_events", + "SELECT" + " kyc_event_serial_id AS serial" + ",event_timestamp" + ",event_type" + " FROM kyc_events" + " WHERE kyc_event_serial_id > $1" + " ORDER BY kyc_event_serial_id ASC;"); + rh = &lrbt_cb_table_kyc_events; + break; + } + if (NULL == rh) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + statement, + params, + rh, + &ctx); + if (qs < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to run `%s'\n", + statement); + return qs; + } + if (ctx.error) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + return qs; +} + + +#undef XPREPARE + +/* end of lookup_records_by_table.c */ diff --git a/src/exchangedb/lookup_rules_by_access_token.c b/src/exchangedb/lookup_rules_by_access_token.c @@ -0,0 +1,66 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/lookup_rules_by_access_token.c + * @brief Implementation of the lookup_rules_by_access_token function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_rules_by_access_token.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_rules_by_access_token ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + json_t **jnew_rules, + uint64_t *rowid) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ( + "jnew_rules", + jnew_rules), + NULL), + GNUNET_PQ_result_spec_uint64 ( + "row_id", + rowid), + GNUNET_PQ_result_spec_end + }; + + *jnew_rules = NULL; + PREPARE (pg, + "lookup_rules_by_access_token", + "SELECT" + " jnew_rules::TEXT" + ",outcome_serial_id AS row_id" + " FROM legitimization_outcomes" + " WHERE h_payto=$1" + " AND is_active" + " ORDER BY expiration_time DESC," + " outcome_serial_id DESC" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "lookup_rules_by_access_token", + params, + rs); +} diff --git a/src/exchangedb/lookup_serial_by_table.c b/src/exchangedb/lookup_serial_by_table.c @@ -0,0 +1,465 @@ +/* + This file is part of TALER + Copyright (C) 2022-2024 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/> + */ +/** + * @file lookup_serial_by_table.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_serial_by_table.h" +#include "helper.h" + + +/** + * Assign statement to @a n and PREPARE + * @a sql under name @a n. + */ +#define XPREPARE(n,sql) \ + statement = n; \ + PREPARE (pg, n, sql); + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_serial_by_table (struct + TALER_EXCHANGEDB_PostgresContext *pg, + enum TALER_EXCHANGEDB_ReplicatedTable + table, + uint64_t *serial) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial", + serial), + GNUNET_PQ_result_spec_end + }; + const char *statement = NULL; + + switch (table) + { + case TALER_EXCHANGEDB_RT_DENOMINATIONS: + XPREPARE ("select_serial_by_table_denominations", + "SELECT" + " denominations_serial AS serial" + " FROM denominations" + " ORDER BY denominations_serial DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS: + XPREPARE ("select_serial_by_table_denomination_revocations", + "SELECT" + " denom_revocations_serial_id AS serial" + " FROM denomination_revocations" + " ORDER BY denom_revocations_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_WIRE_TARGETS: + XPREPARE ("select_serial_by_table_wire_targets", + "SELECT" + " wire_target_serial_id AS serial" + " FROM wire_targets" + " ORDER BY wire_target_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_KYC_TARGETS: + XPREPARE ("select_serial_by_table_kyc_targets", + "SELECT" + " kyc_target_serial_id AS serial" + " FROM kyc_targets" + " ORDER BY kyc_target_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_RESERVES: + XPREPARE ("select_serial_by_table_reserves", + "SELECT" + " reserve_uuid AS serial" + " FROM reserves" + " ORDER BY reserve_uuid DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_RESERVES_IN: + XPREPARE ("select_serial_by_table_reserves_in", + "SELECT" + " reserve_in_serial_id AS serial" + " FROM reserves_in" + " ORDER BY reserve_in_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_KYCAUTHS_IN: + XPREPARE ("select_serial_by_table_kycauths_in", + "SELECT" + " kycauth_in_serial_id AS serial" + " FROM kycauths_in" + " ORDER BY kycauths_in_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_RESERVES_CLOSE: + XPREPARE ("select_serial_by_table_reserves_close", + "SELECT" + " close_uuid AS serial" + " FROM reserves_close" + " ORDER BY close_uuid DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS: + XPREPARE ("select_serial_by_table_reserves_open_requests", + "SELECT" + " open_request_uuid AS serial" + " FROM reserves_open_requests" + " ORDER BY open_request_uuid DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS: + XPREPARE ("select_serial_by_table_reserves_open_deposits", + "SELECT" + " reserve_open_deposit_uuid AS serial" + " FROM reserves_open_deposits" + " ORDER BY reserve_open_deposit_uuid DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_AUDITORS: + XPREPARE ("select_serial_by_table_auditors", + "SELECT" + " auditor_uuid AS serial" + " FROM auditors" + " ORDER BY auditor_uuid DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS: + XPREPARE ("select_serial_by_table_auditor_denom_sigs", + "SELECT" + " auditor_denom_serial AS serial" + " FROM auditor_denom_sigs" + " ORDER BY auditor_denom_serial DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS: + XPREPARE ("select_serial_by_table_exchange_sign_keys", + "SELECT" + " esk_serial AS serial" + " FROM exchange_sign_keys" + " ORDER BY esk_serial DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS: + XPREPARE ("select_serial_by_table_signkey_revocations", + "SELECT" + " signkey_revocations_serial_id AS serial" + " FROM signkey_revocations" + " ORDER BY signkey_revocations_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_KNOWN_COINS: + XPREPARE ("select_serial_by_table_known_coins", + "SELECT" + " known_coin_id AS serial" + " FROM known_coins" + " ORDER BY known_coin_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_REFRESH: + XPREPARE ("select_serial_by_table_refresh", + "SELECT" + " refresh_id AS serial" + " FROM refresh" + " ORDER BY refresh_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS: + XPREPARE ("select_serial_by_table_batch_deposits", + "SELECT" + " batch_deposit_serial_id AS serial" + " FROM batch_deposits" + " ORDER BY batch_deposit_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_COIN_DEPOSITS: + XPREPARE ("select_serial_by_table_coin_deposits", + "SELECT" + " coin_deposit_serial_id AS serial" + " FROM coin_deposits" + " ORDER BY coin_deposit_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_REFUNDS: + XPREPARE ("select_serial_by_table_refunds", + "SELECT" + " refund_serial_id AS serial" + " FROM refunds" + " ORDER BY refund_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_WIRE_OUT: + XPREPARE ("select_serial_by_table_wire_out", + "SELECT" + " wireout_uuid AS serial" + " FROM wire_out" + " ORDER BY wireout_uuid DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING: + XPREPARE ("select_serial_by_table_aggregation_tracking", + "SELECT" + " aggregation_serial_id AS serial" + " FROM aggregation_tracking" + " ORDER BY aggregation_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_WIRE_FEE: + XPREPARE ("select_serial_by_table_wire_fee", + "SELECT" + " wire_fee_serial AS serial" + " FROM wire_fee" + " ORDER BY wire_fee_serial DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_GLOBAL_FEE: + XPREPARE ("select_serial_by_table_global_fee", + "SELECT" + " global_fee_serial AS serial" + " FROM global_fee" + " ORDER BY global_fee_serial DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_RECOUP: + XPREPARE ("select_serial_by_table_recoup", + "SELECT" + " recoup_uuid AS serial" + " FROM recoup" + " ORDER BY recoup_uuid DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_RECOUP_REFRESH: + XPREPARE ("select_serial_by_table_recoup_refresh", + "SELECT" + " recoup_refresh_uuid AS serial" + " FROM recoup_refresh" + " ORDER BY recoup_refresh_uuid DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_EXTENSIONS: + XPREPARE ("select_serial_by_table_extensions", + "SELECT" + " extension_id AS serial" + " FROM extensions" + " ORDER BY extension_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_POLICY_DETAILS: + XPREPARE ("select_serial_by_table_policy_details", + "SELECT" + " policy_details_serial_id AS serial" + " FROM policy_details" + " ORDER BY policy_details_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS: + XPREPARE ("select_serial_by_table_policy_fulfillments", + "SELECT" + " fulfillment_id AS serial" + " FROM policy_fulfillments" + " ORDER BY fulfillment_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_PURSE_REQUESTS: + XPREPARE ("select_serial_by_table_purse_requests", + "SELECT" + " purse_requests_serial_id AS serial" + " FROM purse_requests" + " ORDER BY purse_requests_serial_id DESC" + " LIMIT 1;") + break; + case TALER_EXCHANGEDB_RT_PURSE_DECISION: + XPREPARE ("select_serial_by_table_purse_decision", + "SELECT" + " purse_decision_serial_id AS serial" + " FROM purse_decision" + " ORDER BY purse_decision_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_PURSE_MERGES: + XPREPARE ("select_serial_by_table_purse_merges", + "SELECT" + " purse_merge_request_serial_id AS serial" + " FROM purse_merges" + " ORDER BY purse_merge_request_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS: + XPREPARE ("select_serial_by_table_purse_deposits", + "SELECT" + " purse_deposit_serial_id AS serial" + " FROM purse_deposits" + " ORDER BY purse_deposit_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES: + XPREPARE ("select_serial_by_table_account_merges", + "SELECT" + " account_merge_request_serial_id AS serial" + " FROM account_merges" + " ORDER BY account_merge_request_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS: + XPREPARE ("select_serial_by_table_history_requests", + "SELECT" + " history_request_serial_id AS serial" + " FROM history_requests" + " ORDER BY history_request_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS: + XPREPARE ("select_serial_by_table_close_requests", + "SELECT" + " close_request_serial_id AS serial" + " FROM close_requests" + " ORDER BY close_request_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_WADS_OUT: + XPREPARE ("select_serial_by_table_wads_out", + "SELECT" + " wad_out_serial_id AS serial" + " FROM wads_out" + " ORDER BY wad_out_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES: + XPREPARE ("select_serial_by_table_wads_out_entries", + "SELECT" + " wad_out_entry_serial_id AS serial" + " FROM wad_out_entries" + " ORDER BY wad_out_entry_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_WADS_IN: + XPREPARE ("select_serial_by_table_wads_in", + "SELECT" + " wad_in_serial_id AS serial" + " FROM wads_in" + " ORDER BY wad_in_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES: + XPREPARE ("select_serial_by_table_wads_in_entries", + "SELECT" + " wad_in_entry_serial_id AS serial" + " FROM wad_in_entries" + " ORDER BY wad_in_entry_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_PROFIT_DRAINS: + XPREPARE ("select_serial_by_table_profit_drains", + "SELECT" + " profit_drain_serial_id AS serial" + " FROM profit_drains" + " ORDER BY profit_drain_serial_id DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_profit_drains"; + break; + case TALER_EXCHANGEDB_RT_AML_STAFF: + XPREPARE ("select_serial_by_table_aml_staff", + "SELECT" + " aml_staff_uuid AS serial" + " FROM aml_staff" + " ORDER BY aml_staff_uuid DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_aml_staff"; + break; + case TALER_EXCHANGEDB_RT_PURSE_DELETION: + XPREPARE ("select_serial_by_table_purse_deletion", + "SELECT" + " purse_deletion_serial_id AS serial" + " FROM purse_deletion" + " ORDER BY purse_deletion_serial_id DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_purse_deletion"; + break; + case TALER_EXCHANGEDB_RT_WITHDRAW: + XPREPARE ("select_serial_by_table_withdraw", + "SELECT" + " withdraw_id AS serial" + " FROM withdraw" + " ORDER BY withdraw_id DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_withdraw"; + break; + case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES: + XPREPARE ("select_serial_by_table_legitimization_measures", + "SELECT" + " legitimization_measure_serial_id AS serial" + " FROM legitimization_measures" + " ORDER BY legitimization_measure_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES: + XPREPARE ("select_serial_by_table_legitimization_outcomes", + "SELECT" + " outcome_serial_id AS serial" + " FROM legitimization_outcomes" + " ORDER BY outcome_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES: + XPREPARE ("select_serial_by_table_legitimization_processes", + "SELECT" + " legitimization_process_serial_id AS serial" + " FROM legitimization_processes" + " ORDER BY legitimization_process_serial_id DESC" + " LIMIT 1;"); + break; + case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES: + XPREPARE ("select_serial_by_table_kyc_attributes", + "SELECT" + " kyc_attributes_serial_id AS serial" + " FROM kyc_attributes" + " ORDER BY kyc_attributes_serial_id DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_kyc_attributes"; + break; + case TALER_EXCHANGEDB_RT_AML_HISTORY: + XPREPARE ("select_serial_by_table_aml_history", + "SELECT" + " aml_history_serial_id AS serial" + " FROM aml_history" + " ORDER BY aml_history_serial_id DESC" + " LIMIT 1;"); + statement = "select_serial_by_table_aml_history"; + break; + case TALER_EXCHANGEDB_RT_KYC_EVENTS: + XPREPARE ("select_serial_by_table_kyc_events", + "SELECT" + " kyc_event_serial_id AS serial" + " FROM kyc_events" + " ORDER BY kyc_event_serial_id DESC" + " LIMIT 1;"); + break; + } + if (NULL == statement) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + statement, + params, + rs); +} + + +#undef XPREPARE diff --git a/src/exchangedb/lookup_signing_key.c b/src/exchangedb/lookup_signing_key.c @@ -0,0 +1,60 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/lookup_signing_key.c + * @brief Implementation of the lookup_signing_key function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_signing_key.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_signing_key ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct TALER_EXCHANGEDB_SignkeyMetaData *meta) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (exchange_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("valid_from", + &meta->start), + GNUNET_PQ_result_spec_timestamp ("expire_sign", + &meta->expire_sign), + GNUNET_PQ_result_spec_timestamp ("expire_legal", + &meta->expire_legal), + GNUNET_PQ_result_spec_end + }; + + + PREPARE (pg, + "lookup_signing_key", + "SELECT" + " valid_from" + ",expire_sign" + ",expire_legal" + " FROM exchange_sign_keys" + " WHERE exchange_pub=$1"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_signing_key", + params, + rs); +} diff --git a/src/exchangedb/lookup_signkey_revocation.c b/src/exchangedb/lookup_signkey_revocation.c @@ -0,0 +1,55 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/lookup_signkey_revocation.c + * @brief Implementation of the lookup_signkey_revocation function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_signkey_revocation.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_signkey_revocation ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct TALER_MasterSignatureP *master_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (exchange_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "lookup_signkey_revocation", + "SELECT " + " master_sig" + " FROM signkey_revocations" + " WHERE esk_serial=" + " (SELECT esk_serial" + " FROM exchange_sign_keys" + " WHERE exchange_pub=$1);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_signkey_revocation", + params, + rs); +} diff --git a/src/exchangedb/lookup_transfer_by_deposit.c b/src/exchangedb/lookup_transfer_by_deposit.c @@ -0,0 +1,220 @@ +/* + This file is part of TALER + Copyright (C) 2022-2024 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/> + */ +/** + * @file exchangedb/lookup_transfer_by_deposit.c + * @brief Implementation of the lookup_transfer_by_deposit function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_transfer_by_deposit.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_transfer_by_deposit ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + bool *pending, + struct TALER_WireTransferIdentifierRawP *wtid, + struct GNUNET_TIME_Timestamp *exec_time, + struct TALER_Amount *amount_with_fee, + struct TALER_Amount *deposit_fee, + struct TALER_EXCHANGEDB_KycStatus *kyc, + union TALER_AccountPublicKeyP *account_pub) +{ + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_auto_from_type (h_contract_terms), + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_end + }; + struct TALER_FullPayto payto_uri; + struct TALER_WireSaltP wire_salt; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", + wtid), + GNUNET_PQ_result_spec_auto_from_type ("wire_salt", + &wire_salt), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri.full_payto), + GNUNET_PQ_result_spec_timestamp ("execution_date", + exec_time), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + deposit_fee), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("target_pub", + account_pub), + NULL), + GNUNET_PQ_result_spec_end + }; + + memset (kyc, + 0, + sizeof (*kyc)); + /* check if the aggregation record exists and get it */ + PREPARE (pg, + "lookup_deposit_wtid", + "SELECT" + " atr.wtid_raw" + ",wire_out.execution_date" + ",cdep.amount_with_fee" + ",bdep.wire_salt" + ",wt.payto_uri" + ",kt.target_pub" + ",denom.fee_deposit" + " FROM coin_deposits cdep" + " JOIN batch_deposits bdep" + " USING (batch_deposit_serial_id)" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + /* kyc_targets might not match; then target_pub will be NULL */ + " LEFT JOIN kyc_targets kt" + " USING (h_normalized_payto)" + " JOIN aggregation_tracking atr" + " ON (cdep.batch_deposit_serial_id = atr.batch_deposit_serial_id)" + " JOIN known_coins kc" + " ON (kc.coin_pub = cdep.coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " JOIN wire_out" + " USING (wtid_raw)" + " WHERE cdep.coin_pub=$1" + " AND bdep.merchant_pub=$3" + " AND bdep.h_contract_terms=$2"); + /* NOTE: above query might be more efficient if we computed the shard + from the merchant_pub and included that in the query */ + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_deposit_wtid", + params, + rs); + if (0 > qs) + return qs; + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + struct TALER_MerchantWireHashP wh; + + TALER_merchant_wire_signature_hash (payto_uri, + &wire_salt, + &wh); + if (0 == + GNUNET_memcmp (&wh, + h_wire)) + { + *pending = false; + kyc->ok = true; + GNUNET_PQ_cleanup_result (rs); + return qs; + } + qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + GNUNET_PQ_cleanup_result (rs); + } + *pending = true; + memset (wtid, + 0, + sizeof (*wtid)); + GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "lookup_deposit_wtid returned 0 matching rows\n"); + { + /* Check if transaction exists in deposits, so that we just + do not have a WTID yet. In that case, return without wtid + (by setting 'pending' true). */ + struct GNUNET_PQ_ResultSpec rs2[] = { + GNUNET_PQ_result_spec_auto_from_type ("wire_salt", + &wire_salt), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri.full_payto), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + deposit_fee), + GNUNET_PQ_result_spec_timestamp ("wire_deadline", + exec_time), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ("legitimization_requirement_serial_id", + &kyc->requirement_row), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("target_pub", + account_pub), + NULL), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_deposit_without_wtid", + "SELECT" + " bdep.wire_salt" + ",wt.payto_uri" + ",cdep.amount_with_fee" + ",denom.fee_deposit" + ",bdep.wire_deadline" + ",agt.legitimization_requirement_serial_id" + ",kt.target_pub" + " FROM coin_deposits cdep" + " JOIN batch_deposits bdep" + " USING (batch_deposit_serial_id)" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + /* kyc_targets might not match; then target_pub will be NULL */ + " LEFT JOIN kyc_targets kt" + " USING (h_normalized_payto)" + " JOIN known_coins kc" + " ON (kc.coin_pub = cdep.coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " LEFT JOIN aggregation_transient agt " + " ON ( (bdep.wire_target_h_payto = agt.wire_target_h_payto) AND" + " (bdep.merchant_pub = agt.merchant_pub) )" + " WHERE cdep.coin_pub=$1" + " AND bdep.merchant_pub=$3" + " AND bdep.h_contract_terms=$2" + " LIMIT 1;"); + /* NOTE: above query might be more efficient if we computed the shard + from the merchant_pub and included that in the query */ + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_deposit_without_wtid", + params, + rs2); + if (0 > qs) + return qs; + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + struct TALER_MerchantWireHashP wh; + + TALER_merchant_wire_signature_hash (payto_uri, + &wire_salt, + &wh); + if (0 != + GNUNET_memcmp (&wh, + h_wire)) + { + GNUNET_PQ_cleanup_result (rs2); + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + GNUNET_PQ_cleanup_result (rs2); + if (0 == kyc->requirement_row) + kyc->ok = true; /* technically: unknown */ + } + return qs; + } +} diff --git a/src/exchangedb/lookup_wire_fee_by_time.c b/src/exchangedb/lookup_wire_fee_by_time.c @@ -0,0 +1,152 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/lookup_wire_fee_by_time.c + * @brief Implementation of the lookup_wire_fee_by_time function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_wire_fee_by_time.h" +#include "helper.h" + + +/** + * Closure for #wire_fee_by_time_helper() + */ +struct WireFeeLookupContext +{ + + /** + * Set to the wire fees. Set to invalid if fees conflict over + * the given time period. + */ + struct TALER_WireFeeSet *fees; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; +}; + + +/** + * Helper function for #TALER_EXCHANGEDB_lookup_wire_fee_by_time(). + * Calls the callback with the wire fee structure. + * + * @param cls a `struct WireFeeLookupContext` + * @param result db results + * @param num_results number of results in @a result + */ +static void +wire_fee_by_time_helper (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct WireFeeLookupContext *wlc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = wlc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_WireFeeSet fs; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", + &fs.wire), + TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", + &fs.closing), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + /* invalidate */ + memset (wlc->fees, + 0, + sizeof (struct TALER_WireFeeSet)); + return; + } + if (0 == i) + { + *wlc->fees = fs; + continue; + } + if (0 != + TALER_wire_fee_set_cmp (&fs, + wlc->fees)) + { + /* invalidate */ + memset (wlc->fees, + 0, + sizeof (struct TALER_WireFeeSet)); + return; + } + } +} + + +/** + * Lookup information about known wire fees. Finds all applicable + * fees in the given range. If they are identical, returns the + * respective @a fees. If any of the fees + * differ between @a start_time and @a end_time, the transaction + * succeeds BUT returns an invalid amount for both fees. + * + * @param pg the database context + * @param wire_method the wire method to lookup fees for + * @param start_time starting time of fee + * @param end_time end time of fee + * @param[out] fees wire fees for that time period; if + * different fees exists within this time + * period, an 'invalid' amount is returned. + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_wire_fee_by_time ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *wire_method, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + struct TALER_WireFeeSet *fees) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (wire_method), + GNUNET_PQ_query_param_timestamp (&start_time), + GNUNET_PQ_query_param_timestamp (&end_time), + GNUNET_PQ_query_param_end + }; + struct WireFeeLookupContext wlc = { + .fees = fees, + .pg = pg + }; + + PREPARE (pg, + "lookup_wire_fee_by_time", + "SELECT" + " wire_fee" + ",closing_fee" + " FROM wire_fee" + " WHERE wire_method=$1" + " AND end_date > $2" + " AND start_date < $3;"); + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_wire_fee_by_time", + params, + &wire_fee_by_time_helper, + &wlc); +} diff --git a/src/exchangedb/lookup_wire_timestamp.c b/src/exchangedb/lookup_wire_timestamp.c @@ -0,0 +1,52 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/lookup_wire_timestamp.c + * @brief Implementation of the lookup_wire_timestamp function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_wire_timestamp.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_wire_timestamp (struct + TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_FullPayto payto_uri, + struct GNUNET_TIME_Timestamp *last_date) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (payto_uri.full_payto), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("last_change", + last_date), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "lookup_wire_timestamp", + "SELECT" + " last_change" + " FROM wire_accounts" + " WHERE payto_uri=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_wire_timestamp", + params, + rs); +} diff --git a/src/exchangedb/lookup_wire_transfer.c b/src/exchangedb/lookup_wire_transfer.c @@ -0,0 +1,184 @@ +/* + This file is part of TALER + Copyright (C) 2022-2024 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/> + */ +/** + * @file exchangedb/lookup_wire_transfer.c + * @brief Implementation of the lookup_wire_transfer function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/lookup_wire_transfer.h" +#include "helper.h" + +/** + * Closure for #handle_wt_result. + */ +struct WireTransferResultContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_AggregationDataCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on serious errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. Helper function + * for #TALER_EXCHANGEDB_lookup_wire_transfer(). + * + * @param cls closure of type `struct WireTransferResultContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +handle_wt_result (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct WireTransferResultContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + struct TALER_PrivateContractHashP h_contract_terms; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_FullPaytoHashP h_payto; + struct TALER_MerchantPublicKeyP merchant_pub; + struct GNUNET_TIME_Timestamp exec_time; + struct TALER_Amount amount_with_fee; + struct TALER_Amount deposit_fee; + struct TALER_DenominationPublicKey denom_pub; + struct TALER_FullPayto payto_uri; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", + &rowid), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + &h_contract_terms), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri.full_payto), + GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto", + &h_payto), + TALER_PQ_result_spec_denom_pub ("denom_pub", + &denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &coin_pub), + GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", + &merchant_pub), + GNUNET_PQ_result_spec_timestamp ("execution_date", + &exec_time), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + &deposit_fee), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ctx->cb (ctx->cb_cls, + rowid, + &merchant_pub, + payto_uri, + &h_payto, + exec_time, + &h_contract_terms, + &denom_pub, + &coin_pub, + &amount_with_fee, + &deposit_fee); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_lookup_wire_transfer ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_WireTransferIdentifierRawP *wtid, + TALER_EXCHANGEDB_AggregationDataCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_end + }; + struct WireTransferResultContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "lookup_transactions", + "SELECT" + " aggregation_serial_id" + ",bdep.h_contract_terms" + ",payto_uri" + ",wt.wire_target_h_payto" + ",kc.coin_pub" + ",bdep.merchant_pub" + ",wire_out.execution_date" + ",cdep.amount_with_fee" + ",denom.fee_deposit" + ",denom.denom_pub" + " FROM aggregation_tracking" + " JOIN batch_deposits bdep" + " USING (batch_deposit_serial_id)" + " JOIN coin_deposits cdep" + " USING (batch_deposit_serial_id)" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " JOIN known_coins kc" + " USING (coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " JOIN wire_out" + " USING (wtid_raw)" + " WHERE wtid_raw=$1;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_transactions", + params, + &handle_wt_result, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/mark_refresh_reveal_success.c b/src/exchangedb/mark_refresh_reveal_success.c @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/mark_refresh_reveal_success.c + * @brief Implementation of the mark_refresh_reveal_success function for Postgres + * @author Özgür Kesim + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/mark_refresh_reveal_success.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_mark_refresh_reveal_success ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_RefreshCommitmentP *rc) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (rc), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "mark_refresh_reveal_success", + "UPDATE refresh" + " SET revealed=true" + " WHERE rc = $1"); + + return GNUNET_PQ_eval_prepared_non_select ( + pg->conn, + "mark_refresh_reveal_success", + params); +} diff --git a/src/exchangedb/meson.build b/src/exchangedb/meson.build @@ -78,214 +78,214 @@ libtalerexchangedb = library( 'free_coin_transaction_list.c', 'free_reserve_history.c', 'persist_aml_program_result.c', - 'pg_abort_shard.c', - 'pg_activate_signing_key.c', - 'pg_add_denomination_key.c', - 'pg_add_policy_fulfillment_proof.c', - 'pg_aggregate.c', - 'pg_batch_ensure_coin_known.c', - 'pg_begin_revolving_shard.c', - 'pg_begin_shard.c', + 'abort_shard.c', + 'activate_signing_key.c', + 'add_denomination_key.c', + 'add_policy_fulfillment_proof.c', + 'aggregate.c', + 'batch_ensure_coin_known.c', + 'begin_revolving_shard.c', + 'begin_shard.c', 'pg.c', - 'pg_clear_aml_lock.c', - 'pg_commit.c', - 'pg_complete_shard.c', - 'pg_compute_shard.c', - 'pg_count_known_coins.c', - 'pg_create_aggregation_transient.c', - 'pg_create_tables.c', - 'pg_delete_aggregation_transient.c', - 'pg_delete_shard_locks.c', - 'pg_disable_rules.c', - 'pg_do_check_deposit_idempotent.c', - 'pg_do_deposit.c', - 'pg_do_purse_delete.c', - 'pg_do_purse_deposit.c', - 'pg_do_purse_merge.c', - 'pg_do_recoup.c', - 'pg_do_recoup_refresh.c', - 'pg_do_refresh.c', - 'pg_do_refund.c', - 'pg_do_reserve_open.c', - 'pg_do_reserve_purse.c', - 'pg_do_withdraw.c', - 'pg_drain_kyc_alert.c', - 'pg_drop_tables.c', - 'pg_enable_rules.c', - 'pg_ensure_coin_known.c', - 'pg_event_listen.c', - 'pg_event_listen_cancel.c', - 'pg_event_notify.c', - 'pg_expire_purse.c', - 'pg_find_aggregation_transient.c', - 'pg_gc.c', - 'pg_get_coin_denomination.c', - 'pg_get_coin_transactions.c', - 'pg_get_denomination_by_serial.c', - 'pg_get_denomination_info.c', - 'pg_get_denomination_revocation.c', - 'pg_get_drain_profit.c', - 'pg_get_expired_reserves.c', - 'pg_get_extension_manifest.c', - 'pg_get_global_fee.c', - 'pg_get_global_fees.c', - 'pg_get_known_coin.c', - 'pg_get_kyc_rules.c', - 'pg_get_old_coin_by_h_blind.c', - 'pg_get_pending_kyc_requirement_process.c', - 'pg_get_policy_details.c', - 'pg_get_purse_deposit.c', - 'pg_get_purse_request.c', - 'pg_get_ready_deposit.c', - 'pg_get_refresh.c', - 'pg_get_reserve_balance.c', - 'pg_get_reserve_by_h_planchets.c', - 'pg_get_reserve_history.c', - 'pg_get_signature_for_known_coin.c', - 'pg_get_unfinished_close_requests.c', - 'pg_get_wire_accounts.c', - 'pg_get_wire_fee.c', - 'pg_get_wire_fees.c', - 'pg_get_wire_hash_for_contract.c', - 'pg_get_withdraw.c', - 'pg_have_deposit2.c', - 'pg_inject_auditor_triggers.c', - 'pg_insert_active_legitimization_measure.c', - 'pg_insert_aml_decision.c', - 'pg_insert_aml_officer.c', - 'pg_insert_aml_program_failure.c', - 'pg_insert_auditor.c', - 'pg_insert_auditor_denom_sig.c', - 'pg_insert_close_request.c', - 'pg_insert_contract.c', - 'pg_insert_denomination_info.c', - 'pg_insert_denomination_revocation.c', - 'pg_insert_drain_profit.c', - 'pg_insert_global_fee.c', - 'pg_insert_kyc_failure.c', - 'pg_insert_kyc_requirement_process.c', - 'pg_insert_partner.c', - 'pg_insert_purse_request.c', - 'pg_insert_records_by_table.c', - 'pg_insert_refund.c', - 'pg_insert_reserve_closed.c', - 'pg_insert_reserve_open_deposit.c', - 'pg_insert_sanction_list_hit.c', - 'pg_insert_signkey_revocation.c', - 'pg_insert_successor_measure.c', - 'pg_insert_wire.c', - 'pg_insert_wire_fee.c', - 'pg_iterate_active_auditors.c', - 'pg_iterate_active_signkeys.c', - 'pg_iterate_auditor_denominations.c', - 'pg_iterate_denomination_info.c', - 'pg_iterate_denominations.c', - 'pg_iterate_kyc_reference.c', - 'pg_iterate_reserve_close_info.c', - 'pg_kycauth_in_insert.c', - 'pg_kyc_provider_account_lookup.c', - 'pg_lookup_active_legitimization.c', - 'pg_lookup_aml_file_number.c', - 'pg_lookup_aml_history.c', - 'pg_lookup_aml_officer.c', - 'pg_lookup_auditor_status.c', - 'pg_lookup_auditor_timestamp.c', - 'pg_lookup_completed_legitimization.c', - 'pg_lookup_denomination_key.c', - 'pg_lookup_global_fee_by_time.c', - 'pg_lookup_h_payto_by_access_token.c', - 'pg_lookup_kyc_history.c', - 'pg_lookup_kyc_process_by_account.c', - 'pg_lookup_kyc_requirement_by_row.c', - 'pg_lookup_kyc_status_by_token.c', - 'pg_lookup_pending_legitimization.c', - 'pg_lookup_records_by_table.c', - 'pg_lookup_rules_by_access_token.c', - 'pg_lookup_serial_by_table.c', - 'pg_lookup_signing_key.c', - 'pg_lookup_signkey_revocation.c', - 'pg_lookup_transfer_by_deposit.c', - 'pg_lookup_wire_fee_by_time.c', - 'pg_lookup_wire_timestamp.c', - 'pg_lookup_wire_transfer.c', - 'pg_mark_refresh_reveal_success.c', - 'pg_persist_kyc_attributes.c', - 'pg_persist_policy_details.c', - 'pg_preflight.c', - 'pg_profit_drains_get_pending.c', - 'pg_profit_drains_set_finished.c', - 'pg_release_revolving_shard.c', - 'pg_reserves_get.c', - 'pg_reserves_get_origin.c', - 'pg_reserves_in_insert.c', - 'pg_reserves_update.c', - 'pg_rollback.c', - 'pg_select_account_merges_above_serial_id.c', - 'pg_select_aggregation_amounts_for_kyc_check.c', - 'pg_select_aggregations_above_serial.c', - 'pg_select_aggregation_transient.c', - 'pg_select_all_kyc_attributes.c', - 'pg_select_all_purse_decisions_above_serial_id.c', - 'pg_select_all_purse_deletions_above_serial_id.c', - 'pg_select_aml_attributes.c', - 'pg_select_aml_decisions.c', - 'pg_select_aml_measures.c', - 'pg_select_aml_statistics.c', - 'pg_select_auditor_denom_sig.c', - 'pg_select_batch_deposits_missing_wire.c', - 'pg_select_coin_deposits_above_serial_id.c', - 'pg_select_contract_by_purse.c', - 'pg_select_contract.c', - 'pg_select_deposit_amounts_for_kyc_check.c', - 'pg_select_exchange_credit_transfers.c', - 'pg_select_exchange_debit_transfers.c', - 'pg_select_exchange_kycauth_transfers.c', - 'pg_select_kyc_accounts.c', - 'pg_select_kyc_attributes.c', - 'pg_select_merge_amounts_for_kyc_check.c', - 'pg_select_purse_by_merge_pub.c', - 'pg_select_purse.c', - 'pg_select_purse_decisions_above_serial_id.c', - 'pg_select_purse_deposits_above_serial_id.c', - 'pg_select_purse_deposits_by_purse.c', - 'pg_select_purse_merge.c', - 'pg_select_purse_merges_above_serial_id.c', - 'pg_select_purse_requests_above_serial_id.c', - 'pg_select_recoup_above_serial_id.c', - 'pg_select_recoup_refresh_above_serial_id.c', - 'pg_select_refreshes_above_serial_id.c', - 'pg_select_refunds_above_serial_id.c', - 'pg_select_refunds_by_coin.c', - 'pg_select_reserve_closed_above_serial_id.c', - 'pg_select_reserve_close_info.c', - 'pg_select_reserve_close_request_info.c', - 'pg_select_reserve_open_above_serial_id.c', - 'pg_select_reserves_in_above_serial_id_by_account.c', - 'pg_select_reserves_in_above_serial_id.c', - 'pg_select_wire_out_above_serial_id_by_account.c', - 'pg_select_wire_out_above_serial_id.c', - 'pg_select_withdrawals_above_serial_id.c', - 'pg_select_withdraw_amounts_for_kyc_check.c', - 'pg_set_aml_lock.c', - 'pg_set_extension_manifest.c', - 'pg_set_purse_balance.c', - 'pg_start.c', - 'pg_start_deferred_wire_out.c', - 'pg_start_read_committed.c', - 'pg_start_read_only.c', - 'pg_store_wire_transfer_out.c', - 'pg_template.c', - 'pg_test_aml_officer.c', - 'pg_trigger_kyc_rule_for_account.c', - 'pg_update_aggregation_transient.c', - 'pg_update_auditor.c', - 'pg_update_kyc_process_by_row.c', - 'pg_update_wire.c', - 'pg_wad_in_insert.c', - 'pg_wire_prepare_data_get.c', - 'pg_wire_prepare_data_insert.c', - 'pg_wire_prepare_data_mark_failed.c', - 'pg_wire_prepare_data_mark_finished.c', + 'clear_aml_lock.c', + 'commit.c', + 'complete_shard.c', + 'compute_shard.c', + 'count_known_coins.c', + 'create_aggregation_transient.c', + 'create_tables.c', + 'delete_aggregation_transient.c', + 'delete_shard_locks.c', + 'disable_rules.c', + 'do_check_deposit_idempotent.c', + 'do_deposit.c', + 'do_purse_delete.c', + 'do_purse_deposit.c', + 'do_purse_merge.c', + 'do_recoup.c', + 'do_recoup_refresh.c', + 'do_refresh.c', + 'do_refund.c', + 'do_reserve_open.c', + 'do_reserve_purse.c', + 'do_withdraw.c', + 'drain_kyc_alert.c', + 'drop_tables.c', + 'enable_rules.c', + 'ensure_coin_known.c', + 'event_listen.c', + 'event_listen_cancel.c', + 'event_notify.c', + 'expire_purse.c', + 'find_aggregation_transient.c', + 'gc.c', + 'get_coin_denomination.c', + 'get_coin_transactions.c', + 'get_denomination_by_serial.c', + 'get_denomination_info.c', + 'get_denomination_revocation.c', + 'get_drain_profit.c', + 'get_expired_reserves.c', + 'get_extension_manifest.c', + 'get_global_fee.c', + 'get_global_fees.c', + 'get_known_coin.c', + 'get_kyc_rules.c', + 'get_old_coin_by_h_blind.c', + 'get_pending_kyc_requirement_process.c', + 'get_policy_details.c', + 'get_purse_deposit.c', + 'get_purse_request.c', + 'get_ready_deposit.c', + 'get_refresh.c', + 'get_reserve_balance.c', + 'get_reserve_by_h_planchets.c', + 'get_reserve_history.c', + 'get_signature_for_known_coin.c', + 'get_unfinished_close_requests.c', + 'get_wire_accounts.c', + 'get_wire_fee.c', + 'get_wire_fees.c', + 'get_wire_hash_for_contract.c', + 'get_withdraw.c', + 'have_deposit2.c', + 'inject_auditor_triggers.c', + 'insert_active_legitimization_measure.c', + 'insert_aml_decision.c', + 'insert_aml_officer.c', + 'insert_aml_program_failure.c', + 'insert_auditor.c', + 'insert_auditor_denom_sig.c', + 'insert_close_request.c', + 'insert_contract.c', + 'insert_denomination_info.c', + 'insert_denomination_revocation.c', + 'insert_drain_profit.c', + 'insert_global_fee.c', + 'insert_kyc_failure.c', + 'insert_kyc_requirement_process.c', + 'insert_partner.c', + 'insert_purse_request.c', + 'insert_records_by_table.c', + 'insert_refund.c', + 'insert_reserve_closed.c', + 'insert_reserve_open_deposit.c', + 'insert_sanction_list_hit.c', + 'insert_signkey_revocation.c', + 'insert_successor_measure.c', + 'insert_wire.c', + 'insert_wire_fee.c', + 'iterate_active_auditors.c', + 'iterate_active_signkeys.c', + 'iterate_auditor_denominations.c', + 'iterate_denomination_info.c', + 'iterate_denominations.c', + 'iterate_kyc_reference.c', + 'iterate_reserve_close_info.c', + 'kycauth_in_insert.c', + 'kyc_provider_account_lookup.c', + 'lookup_active_legitimization.c', + 'lookup_aml_file_number.c', + 'lookup_aml_history.c', + 'lookup_aml_officer.c', + 'lookup_auditor_status.c', + 'lookup_auditor_timestamp.c', + 'lookup_completed_legitimization.c', + 'lookup_denomination_key.c', + 'lookup_global_fee_by_time.c', + 'lookup_h_payto_by_access_token.c', + 'lookup_kyc_history.c', + 'lookup_kyc_process_by_account.c', + 'lookup_kyc_requirement_by_row.c', + 'lookup_kyc_status_by_token.c', + 'lookup_pending_legitimization.c', + 'lookup_records_by_table.c', + 'lookup_rules_by_access_token.c', + 'lookup_serial_by_table.c', + 'lookup_signing_key.c', + 'lookup_signkey_revocation.c', + 'lookup_transfer_by_deposit.c', + 'lookup_wire_fee_by_time.c', + 'lookup_wire_timestamp.c', + 'lookup_wire_transfer.c', + 'mark_refresh_reveal_success.c', + 'persist_kyc_attributes.c', + 'persist_policy_details.c', + 'preflight.c', + 'profit_drains_get_pending.c', + 'profit_drains_set_finished.c', + 'release_revolving_shard.c', + 'reserves_get.c', + 'reserves_get_origin.c', + 'reserves_in_insert.c', + 'reserves_update.c', + 'rollback.c', + 'select_account_merges_above_serial_id.c', + 'select_aggregation_amounts_for_kyc_check.c', + 'select_aggregations_above_serial.c', + 'select_aggregation_transient.c', + 'select_all_kyc_attributes.c', + 'select_all_purse_decisions_above_serial_id.c', + 'select_all_purse_deletions_above_serial_id.c', + 'select_aml_attributes.c', + 'select_aml_decisions.c', + 'select_aml_measures.c', + 'select_aml_statistics.c', + 'select_auditor_denom_sig.c', + 'select_batch_deposits_missing_wire.c', + 'select_coin_deposits_above_serial_id.c', + 'select_contract_by_purse.c', + 'select_contract.c', + 'select_deposit_amounts_for_kyc_check.c', + 'select_exchange_credit_transfers.c', + 'select_exchange_debit_transfers.c', + 'select_exchange_kycauth_transfers.c', + 'select_kyc_accounts.c', + 'select_kyc_attributes.c', + 'select_merge_amounts_for_kyc_check.c', + 'select_purse_by_merge_pub.c', + 'select_purse.c', + 'select_purse_decisions_above_serial_id.c', + 'select_purse_deposits_above_serial_id.c', + 'select_purse_deposits_by_purse.c', + 'select_purse_merge.c', + 'select_purse_merges_above_serial_id.c', + 'select_purse_requests_above_serial_id.c', + 'select_recoup_above_serial_id.c', + 'select_recoup_refresh_above_serial_id.c', + 'select_refreshes_above_serial_id.c', + 'select_refunds_above_serial_id.c', + 'select_refunds_by_coin.c', + 'select_reserve_closed_above_serial_id.c', + 'select_reserve_close_info.c', + 'select_reserve_close_request_info.c', + 'select_reserve_open_above_serial_id.c', + 'select_reserves_in_above_serial_id_by_account.c', + 'select_reserves_in_above_serial_id.c', + 'select_wire_out_above_serial_id_by_account.c', + 'select_wire_out_above_serial_id.c', + 'select_withdrawals_above_serial_id.c', + 'select_withdraw_amounts_for_kyc_check.c', + 'set_aml_lock.c', + 'set_extension_manifest.c', + 'set_purse_balance.c', + 'start.c', + 'start_deferred_wire_out.c', + 'start_read_committed.c', + 'start_read_only.c', + 'store_wire_transfer_out.c', + 'template.c', + 'test_aml_officer.c', + 'trigger_kyc_rule_for_account.c', + 'update_aggregation_transient.c', + 'update_auditor.c', + 'update_kyc_process_by_row.c', + 'update_wire.c', + 'wad_in_insert.c', + 'wire_prepare_data_get.c', + 'wire_prepare_data_insert.c', + 'wire_prepare_data_mark_failed.c', + 'wire_prepare_data_mark_finished.c', 'update_rules.c', ], soversion: solibversions['libtalerexchangedb']['soversion'], diff --git a/src/exchangedb/persist_kyc_attributes.c b/src/exchangedb/persist_kyc_attributes.c @@ -0,0 +1,103 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/persist_kyc_attributes.c + * @brief Implementation of the persist_kyc_attributes function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/persist_kyc_attributes.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_persist_kyc_attributes ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t process_row, + const struct TALER_NormalizedPaytoHashP *h_payto, + const char *provider_name, + const char *provider_account_id, + const char *provider_legitimization_id, + uint32_t birthday, + struct GNUNET_TIME_Absolute expiration_time, + const char *form_name, + size_t enc_attributes_size, + const void *enc_attributes) +{ + struct GNUNET_TIME_Timestamp collection_time + = GNUNET_TIME_timestamp_get (); + struct GNUNET_TIME_Timestamp expiration + = GNUNET_TIME_absolute_to_timestamp (expiration_time); + struct TALER_EXCHANGEDB_KycCompletedEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), + .h_payto = *h_payto + }; + char *kyc_completed_notify_s + = GNUNET_PQ_get_event_notify_channel (&rep.header); + struct GNUNET_PQ_QueryParam params[] = { + (0 == process_row) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 (&process_row), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_uint32 (&birthday), + GNUNET_PQ_query_param_string (provider_name), + (NULL == provider_account_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (provider_account_id), + (NULL == provider_legitimization_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (provider_legitimization_id), + GNUNET_PQ_query_param_timestamp (&collection_time), + GNUNET_PQ_query_param_absolute_time (&expiration_time), + GNUNET_PQ_query_param_timestamp (&expiration), + (NULL == enc_attributes) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_fixed_size (enc_attributes, + enc_attributes_size), + GNUNET_PQ_query_param_string (kyc_completed_notify_s), + (NULL == form_name) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (form_name), + GNUNET_PQ_query_param_end + }; + bool ok; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("out_ok", + &ok), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Inserting KYC attributes, wake up on %s\n", + kyc_completed_notify_s); + GNUNET_break (NULL != h_payto); + PREPARE (pg, + "persist_kyc_attributes", + "SELECT " + " out_ok" + " FROM exchange_do_persist_kyc_attributes " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "persist_kyc_attributes", + params, + rs); + GNUNET_PQ_cleanup_query_params_closures (params); + GNUNET_free (kyc_completed_notify_s); + GNUNET_PQ_event_do_poll (pg->conn); + return qs; +} diff --git a/src/exchangedb/persist_policy_details.c b/src/exchangedb/persist_policy_details.c @@ -0,0 +1,74 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/persist_policy_details.c + * @brief Implementation of the persist_policy_details function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/persist_policy_details.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_persist_policy_details ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PolicyDetails *details, + uint64_t *policy_details_serial_id, + struct TALER_Amount *accumulated_total, + enum TALER_PolicyFulfillmentState *fulfillment_state) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&details->hash_code), + TALER_PQ_query_param_json (details->policy_json), + GNUNET_PQ_query_param_timestamp (&details->deadline), + TALER_PQ_query_param_amount (pg->conn, + &details->commitment), + TALER_PQ_query_param_amount (pg->conn, + &details->accumulated_total), + TALER_PQ_query_param_amount (pg->conn, + &details->policy_fee), + TALER_PQ_query_param_amount (pg->conn, + &details->transferable_amount), + GNUNET_PQ_query_param_auto_from_type (&details->fulfillment_state), + (details->no_policy_fulfillment_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 (&details->policy_fulfillment_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id", + policy_details_serial_id), + TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total", + accumulated_total), + GNUNET_PQ_result_spec_uint32 ("fulfillment_state", + fulfillment_state), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "call_insert_or_update_policy_details", + "SELECT" + " out_policy_details_serial_id AS policy_details_serial_id" + ",out_accumulated_total AS accumulated_total" + ",out_fulfillment_state AS fulfillment_state" + " FROM exchange_do_insert_or_update_policy_details" + "($1, $2, $3, $4, $5, $6, $7, $8, $9);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "call_insert_or_update_policy_details", + params, + rs); +} diff --git a/src/exchangedb/pg_abort_shard.c b/src/exchangedb/pg_abort_shard.c @@ -1,49 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_abort_shard.c - * @brief Implementation of the abort_shard function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/abort_shard.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_abort_shard (struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *job_name, - uint64_t start_row, - uint64_t end_row) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_uint64 (&start_row), - GNUNET_PQ_query_param_uint64 (&end_row), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "abort_shard", - "UPDATE work_shards" - " SET last_attempt=0" - " WHERE job_name=$1" - " AND start_row=$2" - " AND end_row=$3;"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "abort_shard", - params); -} diff --git a/src/exchangedb/pg_activate_signing_key.c b/src/exchangedb/pg_activate_signing_key.c @@ -1,54 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_activate_signing_key.c - * @brief Implementation of the activate_signing_key function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/activate_signing_key.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_activate_signing_key ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_EXCHANGEDB_SignkeyMetaData *meta, - const struct TALER_MasterSignatureP *master_sig) -{ - struct GNUNET_PQ_QueryParam iparams[] = { - GNUNET_PQ_query_param_auto_from_type (exchange_pub), - GNUNET_PQ_query_param_timestamp (&meta->start), - GNUNET_PQ_query_param_timestamp (&meta->expire_sign), - GNUNET_PQ_query_param_timestamp (&meta->expire_legal), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_signkey", - "INSERT INTO exchange_sign_keys " - "(exchange_pub" - ",valid_from" - ",expire_sign" - ",expire_legal" - ",master_sig" - ") VALUES " - "($1, $2, $3, $4, $5);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_signkey", - iparams); -} diff --git a/src/exchangedb/pg_add_denomination_key.c b/src/exchangedb/pg_add_denomination_key.c @@ -1,83 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_add_denomination_key.c - * @brief Implementation of the add_denomination_key function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/add_denomination_key.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_add_denomination_key ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_DenominationHashP *h_denom_pub, - const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta, - const struct TALER_MasterSignatureP *master_sig) -{ - struct GNUNET_PQ_QueryParam iparams[] = { - GNUNET_PQ_query_param_auto_from_type (h_denom_pub), - TALER_PQ_query_param_denom_pub (denom_pub), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_timestamp (&meta->start), - GNUNET_PQ_query_param_timestamp (&meta->expire_withdraw), - GNUNET_PQ_query_param_timestamp (&meta->expire_deposit), - GNUNET_PQ_query_param_timestamp (&meta->expire_legal), - TALER_PQ_query_param_amount (pg->conn, - &meta->value), - TALER_PQ_query_param_amount (pg->conn, - &meta->fees.withdraw), - TALER_PQ_query_param_amount (pg->conn, - &meta->fees.deposit), - TALER_PQ_query_param_amount (pg->conn, - &meta->fees.refresh), - TALER_PQ_query_param_amount (pg->conn, - &meta->fees.refund), - GNUNET_PQ_query_param_uint32 (&meta->age_mask.bits), - GNUNET_PQ_query_param_end - }; - - /* Sanity check: ensure fees match coin currency */ - GNUNET_assert (GNUNET_YES == - TALER_denom_fee_check_currency (meta->value.currency, - &meta->fees)); - PREPARE (pg, - "denomination_insert", - "INSERT INTO denominations " - "(denom_pub_hash" - ",denom_pub" - ",master_sig" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin" /* value of this denom */ - ",fee_withdraw" - ",fee_deposit" - ",fee_refresh" - ",fee_refund" - ",age_mask" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," - " $11, $12, $13);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "denomination_insert", - iparams); -} diff --git a/src/exchangedb/pg_add_policy_fulfillment_proof.c b/src/exchangedb/pg_add_policy_fulfillment_proof.c @@ -1,158 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_add_policy_fulfillment_proof.c - * @brief Implementation of the add_policy_fulfillment_proof function for Postgres - * @author Christian Grothoff - */ -#include "taler/platform.h" /* UNNECESSARY? */ -#include "taler/taler_error_codes.h" /* UNNECESSARY? */ -#include "taler/taler_dbevents.h" /* UNNECESSARY? */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/add_policy_fulfillment_proof.h" -#include "helper.h" - - -/** - * Compares two indices into an array of hash codes according to - * GNUNET_CRYPTO_hash_cmp of the content at those index positions. - * - * Used in a call qsort_t in order to generate sorted policy_hash_codes. - */ -static int -hash_code_cmp ( - const void *hc1, - const void *hc2, - void *arg) -{ - size_t i1 = *(size_t *) hc1; - size_t i2 = *(size_t *) hc2; - const struct TALER_PolicyDetails *d = arg; - - return GNUNET_CRYPTO_hash_cmp (&d[i1].hash_code, - &d[i2].hash_code); -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_add_policy_fulfillment_proof ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - struct TALER_PolicyFulfillmentTransactionData *fulfillment) -{ - enum GNUNET_DB_QueryStatus qs; - size_t count = fulfillment->details_count; - /* FIXME[Oec]: this seems to be prone to VLA attacks */ - struct GNUNET_HashCode hcs[GNUNET_NZL (count)]; - - /* Create the sorted policy_hash_codes */ - { - size_t idx[GNUNET_NZL (count)]; - for (size_t i = 0; i < count; i++) - idx[i] = i; - - /* Sort the indices according to the hash codes of the corresponding - * details. */ - qsort_r (idx, - count, - sizeof(size_t), - hash_code_cmp, - fulfillment->details); - - /* Finally, concatenate all hash_codes in sorted order */ - for (size_t i = 0; i < count; i++) - hcs[i] = fulfillment->details[idx[i]].hash_code; - } - - - /* Now, add the proof to the policy_fulfillments table, retrieve the - * record_id */ - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&fulfillment->timestamp), - TALER_PQ_query_param_json (fulfillment->proof), - GNUNET_PQ_query_param_auto_from_type (&fulfillment->h_proof), - TALER_PQ_query_param_array_hash_code (count, hcs, pg->conn), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("fulfillment_id", - &fulfillment->fulfillment_id), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "insert_proof_into_policy_fulfillments", - "INSERT INTO policy_fulfillments" - "(fulfillment_timestamp" - ",fulfillment_proof" - ",h_fulfillment_proof" - ",policy_hash_codes" - ") VALUES ($1, $2::TEXT::JSON, $3, $4)" - " ON CONFLICT DO NOTHING;"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "insert_proof_into_policy_fulfillments", - params, - rs); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) - return qs; - } - - /* Now, set the states of each entry corresponding to the hash_codes in - * policy_details accordingly */ - for (size_t i = 0; i < count; i++) - { - struct TALER_PolicyDetails *pos = &fulfillment->details[i]; - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&pos->hash_code), - GNUNET_PQ_query_param_timestamp (&pos->deadline), - TALER_PQ_query_param_amount (pg->conn, - &pos->commitment), - TALER_PQ_query_param_amount (pg->conn, - &pos->accumulated_total), - TALER_PQ_query_param_amount (pg->conn, - &pos->policy_fee), - TALER_PQ_query_param_amount (pg->conn, - &pos->transferable_amount), - GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "update_policy_details", - "UPDATE policy_details SET" - " deadline=$2" - ",commitment=$3" - ",accumulated_total=$4" - ",fee=$5" - ",transferable=$6" - ",fulfillment_state=$7" - " WHERE policy_hash_code=$1;"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_policy_details", - params); - if (qs < 0) - return qs; - } - } - - /* - * FIXME[oec]-#7999: When all policies of a deposit are fulfilled, - * unblock it and trigger a wire-transfer. - */ - - return qs; -} diff --git a/src/exchangedb/pg_aggregate.c b/src/exchangedb/pg_aggregate.c @@ -1,201 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2023 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/> - */ -/** - * @file exchangedb/pg_aggregate.c - * @brief Implementation of the aggregate function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/compute_shard.h" -#include "taler/exchange-database/aggregate.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_aggregate ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_FullPaytoHashP *h_payto, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_WireTransferIdentifierRawP *wtid, - struct TALER_Amount *total) -{ - uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (merchant_pub); - struct GNUNET_TIME_Absolute now = {0}; - uint64_t sum_deposit_value; - uint64_t sum_deposit_frac; - uint64_t sum_refund_value; - uint64_t sum_refund_frac; - uint64_t sum_fee_value; - uint64_t sum_fee_frac; - enum GNUNET_DB_QueryStatus qs; - struct TALER_Amount sum_deposit; - struct TALER_Amount sum_refund; - struct TALER_Amount sum_fee; - struct TALER_Amount delta; - - now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (), - pg->aggregator_shift); - PREPARE (pg, - "aggregate", - "WITH bdep AS (" /* restrict to our merchant and account and mark as done */ - " UPDATE batch_deposits" - " SET done=TRUE" - " WHERE NOT (done OR policy_blocked)" /* only actually executable deposits */ - " AND refund_deadline<$1" - " AND shard=$5" /* only for efficiency, merchant_pub is what we really filter by */ - " AND merchant_pub=$2" /* filter by target merchant */ - " AND wire_target_h_payto=$3" /* merchant could have a 2nd bank account */ - " RETURNING" - " batch_deposit_serial_id)" - " ,cdep AS (" - " SELECT" - " coin_deposit_serial_id" - " ,batch_deposit_serial_id" - " ,coin_pub" - " ,amount_with_fee AS amount" - " FROM coin_deposits" - " WHERE batch_deposit_serial_id IN (SELECT batch_deposit_serial_id FROM bdep))" - " ,ref AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ - " SELECT" - " amount_with_fee AS refund" - " ,coin_pub" - " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ - " FROM refunds" - " WHERE coin_pub IN (SELECT coin_pub FROM cdep)" - " AND batch_deposit_serial_id IN (SELECT batch_deposit_serial_id FROM bdep))" - " ,ref_by_coin AS (" /* total up refunds by coin */ - " SELECT" - " SUM((ref.refund).val) AS sum_refund_val" - " ,SUM((ref.refund).frac) AS sum_refund_frac" - " ,coin_pub" - " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ - " FROM ref" - " GROUP BY coin_pub, batch_deposit_serial_id)" - " ,norm_ref_by_coin AS (" /* normalize */ - " SELECT" - " sum_refund_val + sum_refund_frac / 100000000 AS norm_refund_val" - " ,sum_refund_frac % 100000000 AS norm_refund_frac" - " ,coin_pub" - " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */ - " FROM ref_by_coin)" - " ,fully_refunded_coins AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ - " SELECT" - " cdep.coin_pub" - " FROM norm_ref_by_coin norm" - " JOIN cdep" - " ON (norm.coin_pub = cdep.coin_pub" - " AND norm.batch_deposit_serial_id = cdep.batch_deposit_serial_id" - " AND norm.norm_refund_val = (cdep.amount).val" - " AND norm.norm_refund_frac = (cdep.amount).frac))" - " ,fees AS (" /* find deposit fees for not fully refunded deposits */ - " SELECT" - " denom.fee_deposit AS fee" - " ,cs.batch_deposit_serial_id" /* ensures we get the fee for each coin, not once per denomination */ - " FROM cdep cs" - " JOIN known_coins kc" /* NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */ - " USING (coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " WHERE coin_pub NOT IN (SELECT coin_pub FROM fully_refunded_coins))" - " ,dummy AS (" /* add deposits to aggregation_tracking */ - " INSERT INTO aggregation_tracking" - " (batch_deposit_serial_id" - " ,wtid_raw)" - " SELECT batch_deposit_serial_id,$4" - " FROM bdep)" - "SELECT" /* calculate totals (deposits, refunds and fees) */ - " CAST(COALESCE(SUM((cdep.amount).val),0) AS INT8) AS sum_deposit_value" - /* cast needed, otherwise we get NUMBER */ - " ,COALESCE(SUM((cdep.amount).frac),0) AS sum_deposit_fraction" /* SUM over INT returns INT8 */ - " ,CAST(COALESCE(SUM((ref.refund).val),0) AS INT8) AS sum_refund_value" - " ,COALESCE(SUM((ref.refund).frac),0) AS sum_refund_fraction" - " ,CAST(COALESCE(SUM((fees.fee).val),0) AS INT8) AS sum_fee_value" - " ,COALESCE(SUM((fees.fee).frac),0) AS sum_fee_fraction" - " FROM cdep " - " FULL OUTER JOIN ref ON (FALSE)" /* We just want all sums */ - " FULL OUTER JOIN fees ON (FALSE);"); - - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_auto_from_type (wtid), - GNUNET_PQ_query_param_uint64 (&deposit_shard), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("sum_deposit_value", - &sum_deposit_value), - GNUNET_PQ_result_spec_uint64 ("sum_deposit_fraction", - &sum_deposit_frac), - GNUNET_PQ_result_spec_uint64 ("sum_refund_value", - &sum_refund_value), - GNUNET_PQ_result_spec_uint64 ("sum_refund_fraction", - &sum_refund_frac), - GNUNET_PQ_result_spec_uint64 ("sum_fee_value", - &sum_fee_value), - GNUNET_PQ_result_spec_uint64 ("sum_fee_fraction", - &sum_fee_frac), - GNUNET_PQ_result_spec_end - }; - - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "aggregate", - params, - rs); - } - if (qs < 0) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return qs; - } - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) - { - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pg->currency, - total)); - return qs; - } - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pg->currency, - &sum_deposit)); - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pg->currency, - &sum_refund)); - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pg->currency, - &sum_fee)); - sum_deposit.value = sum_deposit_frac / TALER_AMOUNT_FRAC_BASE - + sum_deposit_value; - sum_deposit.fraction = sum_deposit_frac % TALER_AMOUNT_FRAC_BASE; - sum_refund.value = sum_refund_frac / TALER_AMOUNT_FRAC_BASE - + sum_refund_value; - sum_refund.fraction = sum_refund_frac % TALER_AMOUNT_FRAC_BASE; - sum_fee.value = sum_fee_frac / TALER_AMOUNT_FRAC_BASE - + sum_fee_value; - sum_fee.fraction = sum_fee_frac % TALER_AMOUNT_FRAC_BASE; \ - GNUNET_assert (0 <= - TALER_amount_subtract (&delta, - &sum_deposit, - &sum_refund)); - GNUNET_assert (0 <= - TALER_amount_subtract (total, - &delta, - &sum_fee)); - return qs; -} diff --git a/src/exchangedb/pg_batch_ensure_coin_known.c b/src/exchangedb/pg_batch_ensure_coin_known.c @@ -1,457 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_batch_ensure_coin_known.c - * @brief Implementation of the batch_ensure_coin_known function for Postgres - * @author Christian Grothoff - * - * FIXME-#9373: use the array support for postgres to simplify this code! - * - */ -#include "taler/taler_exchangedb_lib.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/batch_ensure_coin_known.h" -#include "helper.h" - - -static enum GNUNET_DB_QueryStatus -insert1 (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_CoinPublicInfo coin[1], - struct TALER_EXCHANGEDB_CoinInfo result[1]) -{ - enum GNUNET_DB_QueryStatus qs; - bool is_denom_pub_hash_null = false; - bool is_age_hash_null = false; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), - GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), - GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), - TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("existed", - &result[0].existed), - GNUNET_PQ_result_spec_uint64 ("known_coin_id", - &result[0].known_coin_id), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &result[0].denom_hash), - &is_denom_pub_hash_null), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &result[0].h_age_commitment), - &is_age_hash_null), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "batch1_known_coin", - "SELECT" - " existed1 AS existed" - ",known_coin_id1 AS known_coin_id" - ",denom_pub_hash1 AS denom_hash" - ",age_commitment_hash1 AS h_age_commitment" - " FROM exchange_do_batch1_known_coin" - " ($1, $2, $3, $4);" - ); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "batch1_known_coin", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - return qs; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - GNUNET_break (0); /* should be impossible */ - return GNUNET_DB_STATUS_HARD_ERROR; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - break; /* continued below */ - } - - if ( (! is_denom_pub_hash_null) && - (0 != GNUNET_memcmp (&result[0].denom_hash, - &coin->denom_pub_hash)) ) - { - GNUNET_break_op (0); - result[0].denom_conflict = true; - } - - if ( (! is_denom_pub_hash_null) && - (0 != GNUNET_memcmp (&result[0].denom_hash, - &coin[0].denom_pub_hash)) ) - { - GNUNET_break_op (0); - result[0].denom_conflict = true; - } - - result[0].age_conflict = TALER_AgeCommitmentHashP_NoConflict; - - if (is_age_hash_null != coin[0].no_age_commitment) - { - if (is_age_hash_null) - { - GNUNET_break_op (0); - result[0].age_conflict = TALER_AgeCommitmentHashP_NullExpected; - } - else - { - GNUNET_break_op (0); - result[0].age_conflict = TALER_AgeCommitmentHashP_ValueExpected; - } - } - else if ( (! is_age_hash_null) && - (0 != GNUNET_memcmp (&result[0].h_age_commitment, - &coin[0].h_age_commitment)) ) - { - GNUNET_break_op (0); - result[0].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers; - } - - return qs; -} - - -static enum GNUNET_DB_QueryStatus -insert2 (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_CoinPublicInfo coin[2], - struct TALER_EXCHANGEDB_CoinInfo result[2]) -{ - enum GNUNET_DB_QueryStatus qs; - bool is_denom_pub_hash_null[2] = {false, false}; - bool is_age_hash_null[2] = {false, false}; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), - GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), - GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), - TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), - - GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub), - GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash), - GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment), - TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("existed", - &result[0].existed), - GNUNET_PQ_result_spec_uint64 ("known_coin_id", - &result[0].known_coin_id), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &result[0].denom_hash), - &is_denom_pub_hash_null[0]), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &result[0].h_age_commitment), - &is_age_hash_null[0]), - GNUNET_PQ_result_spec_bool ("existed2", - &result[1].existed), - GNUNET_PQ_result_spec_uint64 ("known_coin_id2", - &result[1].known_coin_id), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2", - &result[1].denom_hash), - &is_denom_pub_hash_null[1]), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2", - &result[1].h_age_commitment), - &is_age_hash_null[1]), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "batch2_known_coin", - "SELECT" - " existed1 AS existed" - ",known_coin_id1 AS known_coin_id" - ",denom_pub_hash1 AS denom_hash" - ",age_commitment_hash1 AS h_age_commitment" - ",existed2 AS existed2" - ",known_coin_id2 AS known_coin_id2" - ",denom_pub_hash2 AS denom_hash2" - ",age_commitment_hash2 AS h_age_commitment2" - " FROM exchange_do_batch2_known_coin" - " ($1, $2, $3, $4, $5, $6, $7, $8);" - ); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "batch2_known_coin", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - return qs; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - GNUNET_break (0); /* should be impossible */ - return GNUNET_DB_STATUS_HARD_ERROR; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - break; /* continued below */ - } - - for (int i = 0; i < 2; i++) - { - if ( (! is_denom_pub_hash_null[i]) && - (0 != GNUNET_memcmp (&result[i].denom_hash, - &coin[i].denom_pub_hash)) ) - { - GNUNET_break_op (0); - result[i].denom_conflict = true; - } - - result[i].age_conflict = TALER_AgeCommitmentHashP_NoConflict; - - if (is_age_hash_null[i] != coin[i].no_age_commitment) - { - if (is_age_hash_null[i]) - { - GNUNET_break_op (0); - result[i].age_conflict = TALER_AgeCommitmentHashP_NullExpected; - } - else - { - GNUNET_break_op (0); - result[i].age_conflict = TALER_AgeCommitmentHashP_ValueExpected; - } - } - else if ( (! is_age_hash_null[i]) && - (0 != GNUNET_memcmp (&result[i].h_age_commitment, - &coin[i].h_age_commitment)) ) - { - GNUNET_break_op (0); - result[i].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers; - } - } - - return qs; -} - - -static enum GNUNET_DB_QueryStatus -insert4 (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_CoinPublicInfo coin[4], - struct TALER_EXCHANGEDB_CoinInfo result[4]) -{ - enum GNUNET_DB_QueryStatus qs; - bool is_denom_pub_hash_null[4] = {false, false, false, false}; - bool is_age_hash_null[4] = {false, false, false, false}; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub), - GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash), - GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment), - TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), - - GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub), - GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash), - GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment), - TALER_PQ_query_param_denom_sig (&coin[0].denom_sig), - - GNUNET_PQ_query_param_auto_from_type (&coin[2].coin_pub), - GNUNET_PQ_query_param_auto_from_type (&coin[2].denom_pub_hash), - GNUNET_PQ_query_param_auto_from_type (&coin[2].h_age_commitment), - TALER_PQ_query_param_denom_sig (&coin[2].denom_sig), - - GNUNET_PQ_query_param_auto_from_type (&coin[3].coin_pub), - GNUNET_PQ_query_param_auto_from_type (&coin[3].denom_pub_hash), - GNUNET_PQ_query_param_auto_from_type (&coin[3].h_age_commitment), - TALER_PQ_query_param_denom_sig (&coin[3].denom_sig), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("existed", - &result[0].existed), - GNUNET_PQ_result_spec_uint64 ("known_coin_id", - &result[0].known_coin_id), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &result[0].denom_hash), - &is_denom_pub_hash_null[0]), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &result[0].h_age_commitment), - &is_age_hash_null[0]), - GNUNET_PQ_result_spec_bool ("existed2", - &result[1].existed), - GNUNET_PQ_result_spec_uint64 ("known_coin_id2", - &result[1].known_coin_id), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2", - &result[1].denom_hash), - &is_denom_pub_hash_null[1]), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2", - &result[1].h_age_commitment), - &is_age_hash_null[1]), - GNUNET_PQ_result_spec_bool ("existed3", - &result[2].existed), - GNUNET_PQ_result_spec_uint64 ("known_coin_id3", - &result[2].known_coin_id), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash3", - &result[2].denom_hash), - &is_denom_pub_hash_null[2]), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash3", - &result[2].h_age_commitment), - &is_age_hash_null[2]), - GNUNET_PQ_result_spec_bool ("existed4", - &result[3].existed), - GNUNET_PQ_result_spec_uint64 ("known_coin_id4", - &result[3].known_coin_id), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash4", - &result[3].denom_hash), - &is_denom_pub_hash_null[3]), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash4", - &result[3].h_age_commitment), - &is_age_hash_null[3]), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "batch4_known_coin", - "SELECT" - " existed1 AS existed" - ",known_coin_id1 AS known_coin_id" - ",denom_pub_hash1 AS denom_hash" - ",age_commitment_hash1 AS h_age_commitment" - ",existed2 AS existed2" - ",known_coin_id2 AS known_coin_id2" - ",denom_pub_hash2 AS denom_hash2" - ",age_commitment_hash2 AS h_age_commitment2" - ",existed3 AS existed3" - ",known_coin_id3 AS known_coin_id3" - ",denom_pub_hash3 AS denom_hash3" - ",age_commitment_hash3 AS h_age_commitment3" - ",existed4 AS existed4" - ",known_coin_id4 AS known_coin_id4" - ",denom_pub_hash4 AS denom_hash4" - ",age_commitment_hash4 AS h_age_commitment4" - " FROM exchange_do_batch2_known_coin" - " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16);" - ); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "batch4_known_coin", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - return qs; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - GNUNET_break (0); /* should be impossible */ - return GNUNET_DB_STATUS_HARD_ERROR; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - break; /* continued below */ - } - - for (int i = 0; i < 4; i++) - { - if ( (! is_denom_pub_hash_null[i]) && - (0 != GNUNET_memcmp (&result[i].denom_hash, - &coin[i].denom_pub_hash)) ) - { - GNUNET_break_op (0); - result[i].denom_conflict = true; - } - - result[i].age_conflict = TALER_AgeCommitmentHashP_NoConflict; - - if (is_age_hash_null[i] != coin[i].no_age_commitment) - { - if (is_age_hash_null[i]) - { - GNUNET_break_op (0); - result[i].age_conflict = TALER_AgeCommitmentHashP_NullExpected; - } - else - { - GNUNET_break_op (0); - result[i].age_conflict = TALER_AgeCommitmentHashP_ValueExpected; - } - } - else if ( (! is_age_hash_null[i]) && - (0 != GNUNET_memcmp (&result[i].h_age_commitment, - &coin[i].h_age_commitment)) ) - { - GNUNET_break_op (0); - result[i].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers; - } - } - - return qs; -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_batch_ensure_coin_known ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_CoinPublicInfo *coin, - struct TALER_EXCHANGEDB_CoinInfo *result, - unsigned int coin_length, - unsigned int batch_size) -{ - enum GNUNET_DB_QueryStatus qs = 0; - unsigned int i = 0; - - while ( (qs >= 0) && - (i < coin_length) ) - { - unsigned int bs = GNUNET_MIN (batch_size, - coin_length - i); - if (bs >= 4) - { - qs = insert4 (pg, - &coin[i], - &result[i]); - i += 4; - continue; - } - switch (bs) - { - case 3: - case 2: - qs = insert2 (pg, - &coin[i], - &result[i]); - i += 2; - break; - case 1: - qs = insert1 (pg, - &coin[i], - &result[i]); - i += 1; - break; - case 0: - GNUNET_assert (0); - break; - } - } /* end while */ - if (qs < 0) - return qs; - return i; -} diff --git a/src/exchangedb/pg_begin_revolving_shard.c b/src/exchangedb/pg_begin_revolving_shard.c @@ -1,258 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_begin_revolving_shard.c - * @brief Implementation of the begin_revolving_shard function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/begin_revolving_shard.h" -#include "taler/exchange-database/commit.h" -#include "helper.h" -#include "taler/exchange-database/start.h" -#include "taler/exchange-database/rollback.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_begin_revolving_shard (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const char *job_name, - uint32_t shard_size, - uint32_t shard_limit, - uint32_t *start_row, - uint32_t *end_row) -{ - - GNUNET_assert (shard_limit <= 1U + (uint32_t) INT_MAX); - GNUNET_assert (shard_limit > 0); - GNUNET_assert (shard_size > 0); - for (unsigned int retries = 0; retries<3; retries++) - { - if (GNUNET_OK != - TALER_EXCHANGEDB_start (pg, - "begin_revolving_shard")) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - - /* First, find last 'end_row' */ - { - enum GNUNET_DB_QueryStatus qs; - uint32_t last_end; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint32 ("end_row", - &last_end), - GNUNET_PQ_result_spec_end - }; - /* Used in #postgres_begin_revolving_shard() */ - PREPARE (pg, - "get_last_revolving_shard", - "SELECT" - " end_row" - " FROM revolving_work_shards" - " WHERE job_name=$1" - " ORDER BY end_row DESC" - " LIMIT 1;"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_last_revolving_shard", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - *start_row = 1U + last_end; - break; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - *start_row = 0; /* base-case: no shards yet */ - break; /* continued below */ - } - } /* get_last_shard */ - - if (*start_row < shard_limit) - { - /* Claim fresh shard */ - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Absolute now; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_uint32 (start_row), - GNUNET_PQ_query_param_uint32 (end_row), - GNUNET_PQ_query_param_end - }; - - *end_row = GNUNET_MIN (shard_limit, - *start_row + shard_size - 1); - now = GNUNET_TIME_absolute_get (); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Trying to claim shard %llu-%llu\n", - (unsigned long long) *start_row, - (unsigned long long) *end_row); - - /* Used in #postgres_claim_revolving_shard() */ - PREPARE (pg, - "create_revolving_shard", - "INSERT INTO revolving_work_shards" - "(job_name" - ",last_attempt" - ",start_row" - ",end_row" - ",active" - ") VALUES " - "($1, $2, $3, $4, TRUE);"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "create_revolving_shard", - params); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - /* continued below (with commit) */ - break; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - /* someone else got this shard already, - try again */ - TALER_EXCHANGEDB_rollback (pg); - continue; - } - } /* end create fresh reovlving shard */ - else - { - /* claim oldest existing shard */ - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint32 ("start_row", - start_row), - GNUNET_PQ_result_spec_uint32 ("end_row", - end_row), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "get_open_revolving_shard", - "SELECT" - " start_row" - ",end_row" - " FROM revolving_work_shards" - " WHERE job_name=$1" - " AND active=FALSE" - " ORDER BY last_attempt ASC" - " LIMIT 1;"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_open_revolving_shard", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - /* no open shards available */ - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - { - enum GNUNET_DB_QueryStatus qsz; - struct GNUNET_TIME_Timestamp now; - struct GNUNET_PQ_QueryParam iparams[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_timestamp (&now), - GNUNET_PQ_query_param_uint32 (start_row), - GNUNET_PQ_query_param_uint32 (end_row), - GNUNET_PQ_query_param_end - }; - - now = GNUNET_TIME_timestamp_get (); - PREPARE (pg, - "reclaim_revolving_shard", - "UPDATE revolving_work_shards" - " SET last_attempt=$2" - " ,active=TRUE" - " WHERE job_name=$1" - " AND start_row=$3" - " AND end_row=$4"); - qsz = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "reclaim_revolving_shard", - iparams); - switch (qsz) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - break; /* continue with commit */ - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - GNUNET_break (0); /* logic error, should be impossible */ - TALER_EXCHANGEDB_rollback (pg); - return GNUNET_DB_STATUS_HARD_ERROR; - } - } - break; /* continue with commit */ - } - } /* end claim oldest existing shard */ - - /* commit */ - { - enum GNUNET_DB_QueryStatus qs; - - qs = TALER_EXCHANGEDB_commit (pg); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } - } - } /* retry 'for' loop */ - return GNUNET_DB_STATUS_SOFT_ERROR; -} diff --git a/src/exchangedb/pg_begin_shard.c b/src/exchangedb/pg_begin_shard.c @@ -1,262 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_begin_shard.c - * @brief Implementation of the begin_shard function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/begin_shard.h" -#include "helper.h" -#include "taler/exchange-database/start.h" -#include "taler/exchange-database/rollback.h" -#include "taler/exchange-database/commit.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_begin_shard (struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *job_name, - struct GNUNET_TIME_Relative delay, - uint64_t shard_size, - uint64_t *start_row, - uint64_t *end_row) -{ - - for (unsigned int retries = 0; retries<10; retries++) - { - if (GNUNET_OK != - TALER_EXCHANGEDB_start (pg, - "begin_shard")) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - - { - struct GNUNET_TIME_Absolute past; - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_absolute_time (&past), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("start_row", - start_row), - GNUNET_PQ_result_spec_uint64 ("end_row", - end_row), - GNUNET_PQ_result_spec_end - }; - - past = GNUNET_TIME_absolute_get (); - PREPARE (pg, - "get_open_shard", - "SELECT" - " start_row" - ",end_row" - " FROM work_shards" - " WHERE job_name=$1" - " AND completed=FALSE" - " AND last_attempt<$2" - " ORDER BY last_attempt ASC" - " LIMIT 1;"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_open_shard", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Serialization error on getting open shard\n"); - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - { - enum GNUNET_DB_QueryStatus qsz; - struct GNUNET_TIME_Absolute now; - struct GNUNET_PQ_QueryParam iparams[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_uint64 (start_row), - GNUNET_PQ_query_param_uint64 (end_row), - GNUNET_PQ_query_param_end - }; - - now = GNUNET_TIME_relative_to_absolute (delay); - PREPARE (pg, - "reclaim_shard", - "UPDATE work_shards" - " SET last_attempt=$2" - " WHERE job_name=$1" - " AND start_row=$3" - " AND end_row=$4"); - qsz = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "reclaim_shard", - iparams); - switch (qsz) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TALER_EXCHANGEDB_rollback (pg); - return qsz; - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Serialization error on claiming open shard\n"); - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - goto commit; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - GNUNET_break (0); /* logic error, should be impossible */ - TALER_EXCHANGEDB_rollback (pg); - return GNUNET_DB_STATUS_HARD_ERROR; - } - } - break; /* actually unreachable */ - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - break; /* continued below */ - } - } /* get_open_shard */ - - /* No open shard, find last 'end_row' */ - { - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("end_row", - start_row), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "get_last_shard", - "SELECT" - " end_row" - " FROM work_shards" - " WHERE job_name=$1" - " ORDER BY end_row DESC" - " LIMIT 1;"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_last_shard", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Serialization error on getting last shard\n"); - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - break; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - *start_row = 0; /* base-case: no shards yet */ - break; /* continued below */ - } - *end_row = *start_row + shard_size; - } /* get_last_shard */ - - /* Claim fresh shard */ - { - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Absolute now; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_uint64 (start_row), - GNUNET_PQ_query_param_uint64 (end_row), - GNUNET_PQ_query_param_end - }; - - now = GNUNET_TIME_relative_to_absolute (delay); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Trying to claim shard (%llu-%llu]\n", - (unsigned long long) *start_row, - (unsigned long long) *end_row); - - PREPARE (pg, - "claim_next_shard", - "INSERT INTO work_shards" - "(job_name" - ",last_attempt" - ",start_row" - ",end_row" - ") VALUES " - "($1, $2, $3, $4);"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "claim_next_shard", - params); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Serialization error on claiming next shard\n"); - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - /* continued below */ - break; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - /* someone else got this shard already, - try again */ - TALER_EXCHANGEDB_rollback (pg); - continue; - } - } /* claim_next_shard */ - - /* commit */ -commit: - { - enum GNUNET_DB_QueryStatus qs; - - qs = TALER_EXCHANGEDB_commit (pg); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Serialization error on commit for beginning shard\n"); - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Claimed new shard\n"); - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } - } - } /* retry 'for' loop */ - return GNUNET_DB_STATUS_SOFT_ERROR; -} diff --git a/src/exchangedb/pg_clear_aml_lock.c b/src/exchangedb/pg_clear_aml_lock.c @@ -1,45 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_clear_aml_lock.c - * @brief Implementation of the clear_aml_lock function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/clear_aml_lock.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_clear_aml_lock ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "clear_aml_lock", - "UPDATE kyc_targets" - " SET aml_program_lock_timeout=NULL" - " WHERE h_normalized_payto=$1"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "clear_aml_lock", - params); -} diff --git a/src/exchangedb/pg_commit.c b/src/exchangedb/pg_commit.c @@ -1,52 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_commit.c - * @brief Implementation of the commit function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/commit.h" -#include "helper.h" - - -/** - * Commit the current transaction of a database connection. - * - * @param pg the database context - * @return final transaction status - */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_commit (struct TALER_EXCHANGEDB_PostgresContext *pg) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - GNUNET_break (NULL != pg->transaction_name); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Committing transaction `%s'\n", - pg->transaction_name); - PREPARE (pg, - "do_commit", - "COMMIT"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "do_commit", - params); - pg->transaction_name = NULL; - return qs; -} diff --git a/src/exchangedb/pg_complete_shard.c b/src/exchangedb/pg_complete_shard.c @@ -1,52 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_complete_shard.c - * @brief Implementation of the complete_shard function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/complete_shard.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_complete_shard (struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *job_name, - uint64_t start_row, - uint64_t end_row) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_uint64 (&start_row), - GNUNET_PQ_query_param_uint64 (&end_row), - GNUNET_PQ_query_param_end - }; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Completing shard %llu-%llu\n", - (unsigned long long) start_row, - (unsigned long long) end_row); - PREPARE (pg, - "complete_shard", - "UPDATE work_shards" - " SET completed=TRUE" - " WHERE job_name=$1" - " AND start_row=$2" - " AND end_row=$3"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "complete_shard", - params); -} diff --git a/src/exchangedb/pg_compute_shard.c b/src/exchangedb/pg_compute_shard.c @@ -1,46 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_compute_shard.c - * @brief Implementation of the compute_shard function for Postgres - * @author Christian Grothoff - */ -#include "taler/exchange-database/compute_shard.h" -#include "helper.h" - - -uint64_t -TALER_EXCHANGEDB_compute_shard (const struct TALER_MerchantPublicKeyP * - merchant_pub) -{ - uint32_t res; - - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_hkdf_gnunet ( - &res, - sizeof (res), - merchant_pub, - sizeof (*merchant_pub), - "VOID", - 4)); - /* interpret hash result as NBO for platform independence, - convert to HBO and map to [0..2^31-1] range */ - res = ntohl (res); - if (res > INT32_MAX) - res += INT32_MIN; - GNUNET_assert (res <= INT32_MAX); - return (uint64_t) res; -} diff --git a/src/exchangedb/pg_count_known_coins.c b/src/exchangedb/pg_count_known_coins.c @@ -1,59 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_count_known_coins.c - * @brief Implementation of the count_known_coins function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/count_known_coins.h" -#include "helper.h" - -long long -TALER_EXCHANGEDB_count_known_coins (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct - TALER_DenominationHashP *denom_pub_hash) -{ - uint64_t count; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("count", - &count), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - - PREPARE (pg, - "count_known_coins", - "SELECT" - " COUNT(*) AS count" - " FROM known_coins" - " WHERE denominations_serial=" - " (SELECT denominations_serial" - " FROM denominations" - " WHERE denom_pub_hash=$1);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "count_known_coins", - params, - rs); - if (0 > qs) - return (long long) qs; - return (long long) count; -} diff --git a/src/exchangedb/pg_create_aggregation_transient.c b/src/exchangedb/pg_create_aggregation_transient.c @@ -1,61 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_create_aggregation_transient.c - * @brief Implementation of the create_aggregation_transient function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/create_aggregation_transient.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_create_aggregation_transient ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_FullPaytoHashP *h_payto, - const char *exchange_account_section, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_WireTransferIdentifierRawP *wtid, - uint64_t kyc_requirement_row, - const struct TALER_Amount *total) -{ - struct GNUNET_PQ_QueryParam params[] = { - TALER_PQ_query_param_amount (pg->conn, - total), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_uint64 (&kyc_requirement_row), - GNUNET_PQ_query_param_string (exchange_account_section), - GNUNET_PQ_query_param_auto_from_type (wtid), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "create_aggregation_transient", - "INSERT INTO aggregation_transient" - " (amount" - " ,merchant_pub" - " ,wire_target_h_payto" - " ,legitimization_requirement_serial_id" - " ,exchange_account_section" - " ,wtid_raw)" - " VALUES ($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "create_aggregation_transient", - params); -} diff --git a/src/exchangedb/pg_create_tables.c b/src/exchangedb/pg_create_tables.c @@ -1,78 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_create_tables.c - * @brief Implementation of the create_tables function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/create_tables.h" -#include "helper.h" - - -enum GNUNET_GenericReturnValue -TALER_EXCHANGEDB_create_tables (struct TALER_EXCHANGEDB_PostgresContext *pg, - bool support_partitions, - uint32_t num_partitions) -{ - struct GNUNET_PQ_Context *conn; - enum GNUNET_GenericReturnValue ret; - struct GNUNET_PQ_QueryParam params[] = { - support_partitions - ? GNUNET_PQ_query_param_uint32 (&num_partitions) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - - conn = GNUNET_PQ_connect_with_cfg (pg->cfg, - "exchangedb-postgres", - "exchange-", - es, - NULL); - if (NULL == conn) - return GNUNET_SYSERR; - ret = GNUNET_PQ_exec_sql (conn, - "procedures"); - GNUNET_break (GNUNET_OK == ret); - if (GNUNET_OK == ret) - { - struct GNUNET_PQ_Context *tconn; - - tconn = pg->conn; - pg->prep_gen++; - pg->conn = conn; - PREPARE (pg, - "create_tables", - "SELECT" - " exchange_do_create_tables" - " ($1::INTEGER);"); - pg->conn = tconn; - if (0 > - GNUNET_PQ_eval_prepared_non_select (conn, - "create_tables", - params)) - { - GNUNET_break (0); - ret = GNUNET_SYSERR; - } - } - GNUNET_PQ_disconnect (conn); - return ret; -} diff --git a/src/exchangedb/pg_delete_aggregation_transient.c b/src/exchangedb/pg_delete_aggregation_transient.c @@ -1,46 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_delete_aggregation_transient.c - * @brief Implementation of the delete_aggregation_transient function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/delete_aggregation_transient.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_delete_aggregation_transient ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_FullPaytoHashP *h_payto, - const struct TALER_WireTransferIdentifierRawP *wtid) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_auto_from_type (wtid), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "delete_aggregation_transient", - "DELETE FROM aggregation_transient" - " WHERE wire_target_h_payto=$1" - " AND wtid_raw=$2"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "delete_aggregation_transient", - params); -} diff --git a/src/exchangedb/pg_delete_shard_locks.c b/src/exchangedb/pg_delete_shard_locks.c @@ -1,37 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_delete_shard_locks.c - * @brief Implementation of the delete_shard_locks function for Postgres - * @author Christian Grothoff - */ -#include "taler/exchange-database/delete_shard_locks.h" -#include "helper.h" - - -enum GNUNET_GenericReturnValue -TALER_EXCHANGEDB_delete_shard_locks (struct TALER_EXCHANGEDB_PostgresContext *pg - ) -{ - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_execute ("DELETE FROM work_shards;"), - GNUNET_PQ_make_execute ("DELETE FROM revolving_work_shards;"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - - return GNUNET_PQ_exec_statements (pg->conn, - es); -} diff --git a/src/exchangedb/pg_disable_rules.c b/src/exchangedb/pg_disable_rules.c @@ -1,57 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_disable_rules.c - * @brief Implementation of the disable_rules function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/disable_rules.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_disable_rules ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *schema) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (schema), - GNUNET_PQ_query_param_end - }; - bool found; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("out_found", - &found), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "call_exchange_drop_customization", - "SELECT out_found" - " FROM exchange_drop_customization" - " ($1);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_exchange_drop_customization", - params, - rs); - if (qs < 0) - return qs; - if (found) - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; -} diff --git a/src/exchangedb/pg_do_check_deposit_idempotent.c b/src/exchangedb/pg_do_check_deposit_idempotent.c @@ -1,109 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2023 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/> - */ -/** - * @file exchangedb/pg_do_deposit.c - * @brief Implementation of the do_deposit function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_check_deposit_idempotent.h" -#include "helper.h" -#include "taler/exchange-database/compute_shard.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_do_check_deposit_idempotent ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_BatchDeposit *bd, - struct GNUNET_TIME_Timestamp *exchange_timestamp, - bool *is_idempotent) -{ - uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&bd->merchant_pub); - const struct TALER_CoinSpendPublicKeyP *coin_pubs[GNUNET_NZL (bd->num_cdis)]; - const struct TALER_CoinSpendSignatureP *coin_sigs[GNUNET_NZL (bd->num_cdis)]; - struct TALER_Amount amounts_with_fee[GNUNET_NZL (bd->num_cdis)]; - struct TALER_NormalizedPaytoHashP h_normalized_payto; - struct GNUNET_PQ_QueryParam params[] = { - /* data for batch_deposits */ - GNUNET_PQ_query_param_uint64 (&deposit_shard), - GNUNET_PQ_query_param_auto_from_type (&bd->merchant_pub), - GNUNET_PQ_query_param_timestamp (&bd->wallet_timestamp), - GNUNET_PQ_query_param_timestamp (exchange_timestamp), - GNUNET_PQ_query_param_timestamp (&bd->refund_deadline), - GNUNET_PQ_query_param_timestamp (&bd->wire_deadline), - GNUNET_PQ_query_param_auto_from_type (&bd->h_contract_terms), - (bd->no_wallet_data_hash) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (&bd->wallet_data_hash), - GNUNET_PQ_query_param_auto_from_type (&bd->wire_salt), - GNUNET_PQ_query_param_auto_from_type (&bd->wire_target_h_payto), - (0 == bd->policy_details_serial_id) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 (&bd->policy_details_serial_id), - GNUNET_PQ_query_param_bool (bd->policy_blocked), - /* arrays for coin_deposits */ - GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis, - coin_pubs, - pg->conn), - GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis, - coin_sigs, - pg->conn), - TALER_PQ_query_param_array_amount (bd->num_cdis, - amounts_with_fee, - pg->conn), - GNUNET_PQ_query_param_end - }; - bool no_time; - 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_bool ("is_idempotent", - is_idempotent), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - TALER_full_payto_normalize_and_hash (bd->receiver_wire_account, - &h_normalized_payto); - for (unsigned int i = 0; i < bd->num_cdis; i++) - { - const struct TALER_EXCHANGEDB_CoinDepositInformation *cdi - = &bd->cdis[i]; - - amounts_with_fee[i] = cdi->amount_with_fee; - coin_pubs[i] = &cdi->coin.coin_pub; - coin_sigs[i] = &cdi->csig; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Do deposit %u = %s\n", - i, - TALER_B2S (&cdi->coin.coin_pub)); - } - PREPARE (pg, - "call_check_deposit_idempotent", - "SELECT " - " out_exchange_timestamp AS exchange_timestamp" - ",out_is_idempotent AS is_idempotent" - " FROM exchange_do_check_deposit_idempotent" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_check_deposit_idempotent", - params, - rs); - GNUNET_PQ_cleanup_query_params_closures (params); - return qs; -} diff --git a/src/exchangedb/pg_do_deposit.c b/src/exchangedb/pg_do_deposit.c @@ -1,171 +0,0 @@ -/* - This file is part of TALER - 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 - 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/> - */ -/** - * @file exchangedb/pg_do_deposit.c - * @brief Implementation of the do_deposit function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_deposit.h" -#include "helper.h" -#include "taler/exchange-database/compute_shard.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_do_deposit ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - 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) -{ - uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&bd->merchant_pub); - const struct TALER_CoinSpendPublicKeyP *coin_pubs[GNUNET_NZL (bd->num_cdis)]; - 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 */ - GNUNET_PQ_query_param_uint64 (&deposit_shard), - GNUNET_PQ_query_param_auto_from_type (&bd->merchant_pub), - GNUNET_PQ_query_param_auto_from_type (&bd->merchant_sig), - GNUNET_PQ_query_param_timestamp (&bd->wallet_timestamp), - GNUNET_PQ_query_param_timestamp (exchange_timestamp), - GNUNET_PQ_query_param_timestamp (&bd->refund_deadline), - GNUNET_PQ_query_param_timestamp (&bd->wire_deadline), - GNUNET_PQ_query_param_auto_from_type (&bd->h_contract_terms), - (bd->no_wallet_data_hash) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (&bd->wallet_data_hash), - GNUNET_PQ_query_param_auto_from_type (&bd->wire_salt), - GNUNET_PQ_query_param_auto_from_type (&bd->wire_target_h_payto), - GNUNET_PQ_query_param_auto_from_type (&h_normalized_payto), - (0 == bd->policy_details_serial_id) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 (&bd->policy_details_serial_id), - GNUNET_PQ_query_param_bool (bd->policy_blocked), - /* to create entry in wire_targets */ - GNUNET_PQ_query_param_string (bd->receiver_wire_account.full_payto), - /* arrays for coin_deposits */ - GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis, - coin_pubs, - pg->conn), - GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis, - coin_sigs, - pg->conn), - 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 - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (bd->extra_wire_subject_metadata), - 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), - GNUNET_PQ_result_spec_bool ("conflicted", - ctr_conflict), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - GNUNET_assert (0 < bd->num_cdis); - TALER_full_payto_normalize_and_hash (bd->receiver_wire_account, - &h_normalized_payto); - for (unsigned int i = 0; i < bd->num_cdis; i++) - { - const struct TALER_EXCHANGEDB_CoinDepositInformation *cdi - = &bd->cdis[i]; - - if (0 == i) - { - total_amount = cdi->amount_with_fee; - total_without_fee = cdi->amount_with_fee; - } - else - { - GNUNET_assert (0 <= - 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; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Do deposit %u = %s\n", - i, - TALER_B2S (&cdi->coin.coin_pub)); - } - PREPARE (pg, - "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,$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_purse_delete.c b/src/exchangedb/pg_do_purse_delete.c @@ -1,60 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_do_purse_delete.c - * @brief Implementation of the do_purse_delete function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_purse_delete.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_do_purse_delete ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_PurseContractSignatureP *purse_sig, - bool *decided, - bool *found) -{ - struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - GNUNET_PQ_query_param_auto_from_type (purse_sig), - GNUNET_PQ_query_param_timestamp (&now), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("decided", - decided), - GNUNET_PQ_result_spec_bool ("found", - found), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "call_purse_delete", - "SELECT " - " out_decided AS decided" - ",out_found AS found" - " FROM exchange_do_purse_delete" - " ($1,$2,$3);"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_purse_delete", - params, - rs); -} diff --git a/src/exchangedb/pg_do_purse_deposit.c b/src/exchangedb/pg_do_purse_deposit.c @@ -1,86 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_do_purse_deposit.c - * @brief Implementation of the do_purse_deposit function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_purse_deposit.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_do_purse_deposit ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount, - const struct TALER_CoinSpendSignatureP *coin_sig, - const struct TALER_Amount *amount_minus_fee, - bool *balance_ok, - bool *too_late, - bool *conflict) -{ - struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get (); - struct GNUNET_TIME_Timestamp reserve_expiration; - uint64_t partner_id = 0; /* FIXME #7271: WAD support... */ - struct GNUNET_PQ_QueryParam params[] = { - (0 == partner_id) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 (&partner_id), - GNUNET_PQ_query_param_auto_from_type (purse_pub), - TALER_PQ_query_param_amount ( - pg->conn, - amount), - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_auto_from_type (coin_sig), - TALER_PQ_query_param_amount ( - pg->conn, - amount_minus_fee), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), - GNUNET_PQ_query_param_timestamp (&now), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("balance_ok", - balance_ok), - GNUNET_PQ_result_spec_bool ("too_late", - too_late), - GNUNET_PQ_result_spec_bool ("conflict", - conflict), - GNUNET_PQ_result_spec_end - }; - - reserve_expiration - = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), - pg->legal_reserve_expiration_time)); - - PREPARE (pg, - "call_purse_deposit", - "SELECT " - " out_balance_ok AS balance_ok" - ",out_conflict AS conflict" - ",out_late AS too_late" - " FROM exchange_do_purse_deposit" - " ($1,$2,$3,$4,$5,$6,$7,$8);"); - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_purse_deposit", - params, - rs); -} diff --git a/src/exchangedb/pg_do_purse_merge.c b/src/exchangedb/pg_do_purse_merge.c @@ -1,87 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_do_purse_merge.c - * @brief Implementation of the do_purse_merge function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_purse_merge.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_do_purse_merge ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_PurseMergeSignatureP *merge_sig, - const struct GNUNET_TIME_Timestamp merge_timestamp, - const struct TALER_ReserveSignatureP *reserve_sig, - const char *partner_url, - const struct TALER_ReservePublicKeyP *reserve_pub, - bool *no_partner, - bool *no_balance, - bool *in_conflict) -{ - struct TALER_NormalizedPaytoHashP h_payto; - struct GNUNET_TIME_Timestamp expiration - = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - GNUNET_PQ_query_param_auto_from_type (merge_sig), - GNUNET_PQ_query_param_timestamp (&merge_timestamp), - GNUNET_PQ_query_param_auto_from_type (reserve_sig), - (NULL == partner_url) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (partner_url), - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_auto_from_type (&h_payto), - GNUNET_PQ_query_param_timestamp (&expiration), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("no_partner", - no_partner), - GNUNET_PQ_result_spec_bool ("no_balance", - no_balance), - GNUNET_PQ_result_spec_bool ("conflict", - in_conflict), - GNUNET_PQ_result_spec_end - }; - - { - struct TALER_NormalizedPayto payto_uri; - - payto_uri = TALER_reserve_make_payto (pg->exchange_url, - reserve_pub); - TALER_normalized_payto_hash (payto_uri, - &h_payto); - GNUNET_free (payto_uri.normalized_payto); - } - PREPARE (pg, - "call_purse_merge", - "SELECT" - " out_no_partner AS no_partner" - ",out_no_balance AS no_balance" - ",out_conflict AS conflict" - " FROM exchange_do_purse_merge" - " ($1, $2, $3, $4, $5, $6, $7, $8);"); - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_purse_merge", - params, - rs); -} diff --git a/src/exchangedb/pg_do_recoup.c b/src/exchangedb/pg_do_recoup.c @@ -1,81 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_do_recoup.c - * @brief Implementation of the do_recoup function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_recoup.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_do_recoup ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ReservePublicKeyP *reserve_pub, - uint64_t withdraw_id, - const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t known_coin_id, - const struct TALER_CoinSpendSignatureP *coin_sig, - struct GNUNET_TIME_Timestamp *recoup_timestamp, - bool *recoup_ok, - bool *internal_failure) -{ - struct GNUNET_TIME_Timestamp reserve_gc - = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time); - struct GNUNET_TIME_Timestamp reserve_expiration - = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_uint64 (&withdraw_id), - GNUNET_PQ_query_param_auto_from_type (coin_bks), - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_uint64 (&known_coin_id), - GNUNET_PQ_query_param_auto_from_type (coin_sig), - GNUNET_PQ_query_param_timestamp (&reserve_gc), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), - GNUNET_PQ_query_param_timestamp (recoup_timestamp), - GNUNET_PQ_query_param_end - }; - bool is_null; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", - recoup_timestamp), - &is_null), - GNUNET_PQ_result_spec_bool ("recoup_ok", - recoup_ok), - GNUNET_PQ_result_spec_bool ("internal_failure", - internal_failure), - GNUNET_PQ_result_spec_end - }; - - - PREPARE (pg, - "call_recoup", - "SELECT " - " out_recoup_timestamp AS recoup_timestamp" - ",out_recoup_ok AS recoup_ok" - ",out_internal_failure AS internal_failure" - " FROM exchange_do_recoup_to_reserve" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9);"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_recoup", - params, - rs); -} diff --git a/src/exchangedb/pg_do_recoup_refresh.c b/src/exchangedb/pg_do_recoup_refresh.c @@ -1,76 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2025 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/> - */ -/** - * @file exchangedb/pg_do_recoup_refresh.c - * @brief Implementation of the do_recoup_refresh function for Postgres - * @author Christian Grothoff - * @author Özgür Kesim - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_recoup_refresh.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_do_recoup_refresh ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_CoinSpendPublicKeyP *old_coin_pub, - uint64_t refresh_id, - const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t known_coin_id, - const struct TALER_CoinSpendSignatureP *coin_sig, - struct GNUNET_TIME_Timestamp *recoup_timestamp, - bool *recoup_ok, - bool *internal_failure) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (old_coin_pub), - GNUNET_PQ_query_param_uint64 (&refresh_id), - GNUNET_PQ_query_param_auto_from_type (coin_bks), - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_uint64 (&known_coin_id), - GNUNET_PQ_query_param_auto_from_type (coin_sig), - GNUNET_PQ_query_param_timestamp (recoup_timestamp), - GNUNET_PQ_query_param_end - }; - bool is_null; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", - recoup_timestamp), - &is_null), - GNUNET_PQ_result_spec_bool ("recoup_ok", - recoup_ok), - GNUNET_PQ_result_spec_bool ("internal_failure", - internal_failure), - GNUNET_PQ_result_spec_end - }; - - - PREPARE (pg, - "call_recoup_refresh", - "SELECT " - " out_recoup_timestamp AS recoup_timestamp" - ",out_recoup_ok AS recoup_ok" - ",out_internal_failure AS internal_failure" - " FROM exchange_do_recoup_to_coin" - " ($1,$2,$3,$4,$5,$6,$7);"); - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_recoup_refresh", - params, - rs); -} diff --git a/src/exchangedb/pg_do_refresh.c b/src/exchangedb/pg_do_refresh.c @@ -1,138 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_do_refresh.c - * @brief Implementation of the do_refresh function for Postgres - * @author Özgür Kesim - */ -#include "taler/taler_exchangedb_lib.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_refresh.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_do_refresh ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh, - const struct GNUNET_TIME_Timestamp *timestamp, - bool *found, - uint32_t *noreveal_index, - bool *zombie_required, - bool *nonce_reuse, - bool *balance_ok, - struct TALER_Amount *coin_balance) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&refresh->rc), - GNUNET_PQ_query_param_timestamp (timestamp), - GNUNET_PQ_query_param_auto_from_type (&refresh->refresh_seed), /* 3 */ - (refresh->is_v27_refresh) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_array_auto_from_type (refresh->num_coins, - refresh->transfer_pubs, - pg->conn), - GNUNET_PQ_query_param_auto_from_type (&refresh->planchets_h), - TALER_PQ_query_param_amount (pg->conn, /* 6 */ - &refresh->amount_with_fee), - (refresh->no_blinding_seed) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (&refresh->blinding_seed), - (0 < refresh->num_cs_r_values) - ? TALER_PQ_query_param_array_cs_r_pub (refresh->num_cs_r_values, - refresh->cs_r_values, - pg->conn) - : GNUNET_PQ_query_param_null (), - (0 < refresh->num_cs_r_values) - ? GNUNET_PQ_query_param_uint64 (&refresh->cs_r_choices) /* 9 */ - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_auto_from_type (&refresh->selected_h), - TALER_PQ_query_param_array_blinded_denom_sig (refresh->num_coins, - refresh->denom_sigs, - pg->conn), - GNUNET_PQ_query_param_array_uint64 (refresh->num_coins, /* 12 */ - refresh->denom_serials, - pg->conn), - GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub), - GNUNET_PQ_query_param_auto_from_type (&refresh->coin_sig), - GNUNET_PQ_query_param_uint32 (&refresh->noreveal_index), /* 15 */ - GNUNET_PQ_query_param_bool (*zombie_required), - GNUNET_PQ_query_param_end - }; - bool coin_found; - bool no_noreveal_index; - bool no_coin_balance; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("coin_found", - &coin_found), - GNUNET_PQ_result_spec_bool ("balance_ok", - balance_ok), - GNUNET_PQ_result_spec_bool ("zombie_required", - zombie_required), - GNUNET_PQ_result_spec_bool ("nonce_reuse", - nonce_reuse), - GNUNET_PQ_result_spec_bool ("found", - found), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint32 ("noreveal_index", - noreveal_index), - &no_noreveal_index), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_RESULT_SPEC_AMOUNT ("coin_balance", - coin_balance), - &no_coin_balance), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "call_refresh", - "SELECT " - " out_coin_found AS coin_found" - ",out_balance_ok AS balance_ok" - ",out_zombie_bad AS zombie_required" - ",out_nonce_reuse AS nonce_reuse" - ",out_idempotent AS found" - ",out_noreveal_index AS noreveal_index" - ",out_coin_balance AS coin_balance" - " FROM exchange_do_refresh" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_refresh", - params, - rs); - GNUNET_PQ_cleanup_query_params_closures (params); - if (0 > qs) - { - GNUNET_break (0); - return qs; - } - if (! coin_found) - { - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - if (*found && no_noreveal_index) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if (! balance_ok && no_coin_balance) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - return qs; -} diff --git a/src/exchangedb/pg_do_refund.c b/src/exchangedb/pg_do_refund.c @@ -1,91 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_do_refund.c - * @brief Implementation of the do_refund function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_refund.h" -#include "helper.h" -#include "taler/exchange-database/compute_shard.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_do_refund ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_Refund *refund, - const struct TALER_Amount *deposit_fee, - uint64_t known_coin_id, - bool *not_found, - bool *refund_ok, - bool *gone, - bool *conflict) -{ - uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&refund->details. - merchant_pub); - struct TALER_Amount amount_without_fee; - struct GNUNET_PQ_QueryParam params[] = { - TALER_PQ_query_param_amount (pg->conn, - &refund->details.refund_amount), - TALER_PQ_query_param_amount (pg->conn, - &amount_without_fee), - TALER_PQ_query_param_amount (pg->conn, - deposit_fee), - GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms), - GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id), - GNUNET_PQ_query_param_uint64 (&deposit_shard), - GNUNET_PQ_query_param_uint64 (&known_coin_id), - GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub), - GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub), - GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("not_found", - not_found), - GNUNET_PQ_result_spec_bool ("refund_ok", - refund_ok), - GNUNET_PQ_result_spec_bool ("gone", - gone), - GNUNET_PQ_result_spec_bool ("conflict", - conflict), - GNUNET_PQ_result_spec_end - }; - - if (0 > - TALER_amount_subtract (&amount_without_fee, - &refund->details.refund_amount, - &refund->details.refund_fee)) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - PREPARE (pg, - "call_refund", - "SELECT " - " out_not_found AS not_found" - ",out_refund_ok AS refund_ok" - ",out_gone AS gone" - ",out_conflict AS conflict" - " FROM exchange_do_refund" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_refund", - params, - rs); -} diff --git a/src/exchangedb/pg_do_reserve_open.c b/src/exchangedb/pg_do_reserve_open.c @@ -1,97 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_do_reserve_open.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_reserve_open.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_do_reserve_open ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *total_paid, - const struct TALER_Amount *reserve_payment, - uint32_t min_purse_limit, - const struct TALER_ReserveSignatureP *reserve_sig, - struct GNUNET_TIME_Timestamp desired_expiration, - struct GNUNET_TIME_Timestamp now, - const struct TALER_Amount *open_fee, - bool *no_funds, - struct TALER_Amount *reserve_balance, - struct TALER_Amount *open_cost, - struct GNUNET_TIME_Timestamp *final_expiration) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - TALER_PQ_query_param_amount ( - pg->conn, - total_paid), - TALER_PQ_query_param_amount ( - pg->conn, - reserve_payment), - GNUNET_PQ_query_param_uint32 (&min_purse_limit), - GNUNET_PQ_query_param_uint32 (&pg->def_purse_limit), - GNUNET_PQ_query_param_auto_from_type (reserve_sig), - GNUNET_PQ_query_param_timestamp (&desired_expiration), - GNUNET_PQ_query_param_relative_time (&pg->legal_reserve_expiration_time), - GNUNET_PQ_query_param_timestamp (&now), - TALER_PQ_query_param_amount (pg->conn, - open_fee), - GNUNET_PQ_query_param_end - }; - bool no_reserve = true; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_amount ("out_open_cost", - pg->currency, - open_cost), - TALER_PQ_result_spec_amount ("out_reserve_balance", - pg->currency, - reserve_balance), - GNUNET_PQ_result_spec_timestamp ("out_final_expiration", - final_expiration), - GNUNET_PQ_result_spec_bool ("out_no_reserve", - &no_reserve), - GNUNET_PQ_result_spec_bool ("out_no_funds", - no_funds), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "do_reserve_open", - "SELECT " - " out_open_cost" - ",out_final_expiration" - ",out_no_funds" - ",out_no_reserve" - ",out_reserve_balance" - " FROM exchange_do_reserve_open" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "do_reserve_open", - params, - rs); - if (qs <= 0) - return qs; - if (no_reserve) - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - return qs; -} diff --git a/src/exchangedb/pg_do_reserve_purse.c b/src/exchangedb/pg_do_reserve_purse.c @@ -1,118 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_do_reserve_purse.c - * @brief Implementation of the do_reserve_purse function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_reserve_purse.h" -#include "helper.h" - - -/** - * Function called insert request to merge a purse into a reserve by the - * respective purse merge key. The purse must not have been merged into a - * different reserve. - * - * @param pg the database context - * @param purse_pub purse to merge - * @param merge_sig signature affirming the merge - * @param merge_timestamp time of the merge - * @param reserve_sig signature of the reserve affirming the merge - * @param purse_fee amount to charge the reserve for the purse creation, NULL to use the quota - * @param reserve_pub public key of the reserve to credit - * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already - * @param[out] no_reserve set to true if @a reserve_pub is not a known reserve - * @param[out] insufficient_funds set to true if @a reserve_pub has insufficient capacity to create another purse - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_do_reserve_purse ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_PurseMergeSignatureP *merge_sig, - const struct GNUNET_TIME_Timestamp merge_timestamp, - const struct TALER_ReserveSignatureP *reserve_sig, - const struct TALER_Amount *purse_fee, - const struct TALER_ReservePublicKeyP *reserve_pub, - bool *in_conflict, - bool *no_reserve, - bool *insufficient_funds) -{ - struct TALER_Amount zero_fee; - struct TALER_NormalizedPaytoHashP h_payto; - struct GNUNET_TIME_Timestamp reserve_expiration - = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), - pg->idle_reserve_expiration_time)); - struct GNUNET_TIME_Timestamp reserve_gc - = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), - pg->legal_reserve_expiration_time)); - - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - GNUNET_PQ_query_param_auto_from_type (merge_sig), - GNUNET_PQ_query_param_timestamp (&merge_timestamp), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), - GNUNET_PQ_query_param_timestamp (&reserve_gc), - GNUNET_PQ_query_param_auto_from_type (reserve_sig), - GNUNET_PQ_query_param_bool (NULL == purse_fee), - TALER_PQ_query_param_amount (pg->conn, - NULL == purse_fee - ? &zero_fee - : purse_fee), - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_auto_from_type (&h_payto), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("insufficient_funds", - insufficient_funds), - GNUNET_PQ_result_spec_bool ("conflict", - in_conflict), - GNUNET_PQ_result_spec_bool ("no_reserve", - no_reserve), - GNUNET_PQ_result_spec_end - }; - - { - struct TALER_NormalizedPayto payto_uri; - - payto_uri = TALER_reserve_make_payto (pg->exchange_url, - reserve_pub); - TALER_normalized_payto_hash (payto_uri, - &h_payto); - GNUNET_free (payto_uri.normalized_payto); - } - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pg->currency, - &zero_fee)); - PREPARE (pg, - "call_reserve_purse", - "SELECT" - " out_no_funds AS insufficient_funds" - ",out_no_reserve AS no_reserve" - ",out_conflict AS conflict" - " FROM exchange_do_reserve_purse" - " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"); - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_reserve_purse", - params, - rs); -} diff --git a/src/exchangedb/pg_do_withdraw.c b/src/exchangedb/pg_do_withdraw.c @@ -1,140 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023-2025 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/> - */ -/** - * @file exchangedb/pg_do_withdraw.c - * @brief Implementation of the do_withdraw function for Postgres - * @author Özgür Kesim - */ -#include "taler/taler_exchangedb_lib.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/do_withdraw.h" -#include "helper.h" -#include <gnunet/gnunet_time_lib.h> - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_do_withdraw ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_Withdraw *withdraw, - const struct GNUNET_TIME_Timestamp *timestamp, - bool *balance_ok, - struct TALER_Amount *reserve_balance, - bool *age_ok, - uint16_t *required_age, - uint32_t *reserve_birthday, - bool *idempotent, - uint16_t *noreveal_index, - bool *nonce_reuse) -{ - struct GNUNET_TIME_Timestamp gc; - struct GNUNET_PQ_QueryParam params[] = { - TALER_PQ_query_param_amount (pg->conn, - &withdraw->amount_with_fee), - GNUNET_PQ_query_param_auto_from_type (&withdraw->reserve_pub), - GNUNET_PQ_query_param_auto_from_type (&withdraw->reserve_sig), - GNUNET_PQ_query_param_timestamp (timestamp), - GNUNET_PQ_query_param_timestamp (&gc), - GNUNET_PQ_query_param_auto_from_type (&withdraw->planchets_h), - (withdraw->age_proof_required) - ? GNUNET_PQ_query_param_uint16 (&withdraw->max_age) - : GNUNET_PQ_query_param_null (), - (withdraw->age_proof_required) - ? GNUNET_PQ_query_param_uint16 (&withdraw->noreveal_index) - : GNUNET_PQ_query_param_null (), - (withdraw->age_proof_required) - ? GNUNET_PQ_query_param_auto_from_type (&withdraw->selected_h) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_array_uint64 (withdraw->num_coins, - withdraw->denom_serials, - pg->conn), - TALER_PQ_query_param_array_blinded_denom_sig (withdraw->num_coins, - withdraw->denom_sigs, - pg->conn), - (withdraw->no_blinding_seed) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (&withdraw->blinding_seed), - (withdraw->no_blinding_seed) - ? GNUNET_PQ_query_param_null () - : TALER_PQ_query_param_array_cs_r_pub (withdraw->num_cs_r_values, - withdraw->cs_r_values, - pg->conn), - (withdraw->no_blinding_seed) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 (&withdraw->cs_r_choices), - GNUNET_PQ_query_param_end - }; - bool reserve_found; - bool no_noreveal_index; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("out_reserve_found", - &reserve_found), - GNUNET_PQ_result_spec_bool ("out_balance_ok", - balance_ok), - TALER_PQ_RESULT_SPEC_AMOUNT ("out_reserve_balance", - reserve_balance), - GNUNET_PQ_result_spec_bool ("out_age_ok", - age_ok), - GNUNET_PQ_result_spec_uint16 ("out_required_age", - required_age), - GNUNET_PQ_result_spec_uint32 ("out_reserve_birthday", - reserve_birthday), - GNUNET_PQ_result_spec_bool ("out_idempotent", - idempotent), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint16 ("out_noreveal_index", - noreveal_index), - &no_noreveal_index), - GNUNET_PQ_result_spec_bool ("out_nonce_reuse", - nonce_reuse), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - GNUNET_assert ((! withdraw->no_blinding_seed) || - (0 == withdraw->num_cs_r_values)); - - gc = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_add (timestamp->abs_time, - pg->legal_reserve_expiration_time)); - PREPARE (pg, - "call_withdraw", - "SELECT " - " out_reserve_found" - ",out_balance_ok" - ",out_reserve_balance" - ",out_age_ok" - ",out_required_age" - ",out_reserve_birthday" - ",out_idempotent" - ",out_noreveal_index" - ",out_nonce_reuse" - " FROM exchange_do_withdraw" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_withdraw", - params, - rs); - GNUNET_PQ_cleanup_query_params_closures (params); - - if (0 > qs) - return qs; - if (! reserve_found) - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - if ((withdraw->age_proof_required) && - (idempotent && no_noreveal_index)) - GNUNET_break (0); - return qs; -} diff --git a/src/exchangedb/pg_drain_kyc_alert.c b/src/exchangedb/pg_drain_kyc_alert.c @@ -1,55 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_drain_kyc_alert.c - * @brief Implementation of the drain_kyc_alert function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/drain_kyc_alert.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_drain_kyc_alert (struct TALER_EXCHANGEDB_PostgresContext *pg, - uint32_t trigger_type, - struct TALER_NormalizedPaytoHashP *h_payto) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint32 (&trigger_type), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("h_payto", - h_payto), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "drain_kyc_alert", - "DELETE FROM kyc_alerts" - " WHERE trigger_type=$1" - " AND h_payto = " - " (SELECT h_payto " - " FROM kyc_alerts" - " WHERE trigger_type=$1" - " LIMIT 1)" - " RETURNING h_payto;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "drain_kyc_alert", - params, - rs); -} diff --git a/src/exchangedb/pg_drop_tables.c b/src/exchangedb/pg_drop_tables.c @@ -1,54 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_drop_tables.c - * @brief Implementation of the drop_tables function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/drop_tables.h" -#include "helper.h" - - -/** - * Drop all Taler tables. This should only be used by testcases. - * - * @param pg the database context - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -enum GNUNET_GenericReturnValue -TALER_EXCHANGEDB_drop_tables (struct TALER_EXCHANGEDB_PostgresContext *pg) -{ - struct GNUNET_PQ_Context *conn; - enum GNUNET_GenericReturnValue ret; - - if (NULL != pg->conn) - { - GNUNET_PQ_disconnect (pg->conn); - pg->conn = NULL; - } - conn = GNUNET_PQ_connect_with_cfg (pg->cfg, - "exchangedb-postgres", - NULL, - NULL, - NULL); - if (NULL == conn) - return GNUNET_SYSERR; - ret = GNUNET_PQ_exec_sql (conn, - "drop"); - GNUNET_PQ_disconnect (conn); - return ret; -} diff --git a/src/exchangedb/pg_enable_rules.c b/src/exchangedb/pg_enable_rules.c @@ -1,74 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_enable_rules.c - * @brief Implementation of the enable_rules function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/enable_rules.h" -#include "helper.h" - - -enum GNUNET_GenericReturnValue -TALER_EXCHANGEDB_enable_rules ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *schema) -{ - struct GNUNET_PQ_Context *conn; - enum GNUNET_GenericReturnValue ret; - char *sp; - - GNUNET_asprintf (&sp, - "SET search_path TO %s,exchange;", - schema); - { - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_try_execute (sp), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - char *schemadash; - - GNUNET_asprintf (&schemadash, - "%s-", - schema); - conn = GNUNET_PQ_connect_with_cfg (pg->cfg, - "exchangedb-postgres", - schemadash, - es, - NULL); - GNUNET_free (schemadash); - } - GNUNET_free (sp); - if (NULL == conn) - return GNUNET_SYSERR; - { - char *procfile; - - GNUNET_asprintf (&procfile, - "%s-procedures", - schema); - ret = GNUNET_PQ_exec_sql (conn, - procfile); - /* $SCHEMA-procedures MAY not exist, so only check for hard error */ - GNUNET_break (GNUNET_SYSERR != ret); - if (GNUNET_NO == ret) - ret = GNUNET_OK; - GNUNET_free (procfile); - } - GNUNET_PQ_disconnect (conn); - return ret; -} diff --git a/src/exchangedb/pg_ensure_coin_known.c b/src/exchangedb/pg_ensure_coin_known.c @@ -1,166 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_ensure_coin_known.c - * @brief Implementation of the ensure_coin_known function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_exchangedb_lib.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/ensure_coin_known.h" -#include "helper.h" - - -enum TALER_EXCHANGEDB_CoinKnownStatus -TALER_EXCHANGEDB_ensure_coin_known ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_CoinPublicInfo *coin, - uint64_t *known_coin_id, - struct TALER_DenominationHashP *denom_hash, - struct TALER_AgeCommitmentHashP *h_age_commitment) -{ - enum GNUNET_DB_QueryStatus qs; - bool existed; - bool no_denom_pub_hash; - bool no_age_commitment_hash; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub), - GNUNET_PQ_query_param_auto_from_type (&coin->denom_pub_hash), - coin->no_age_commitment - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (&coin->h_age_commitment), - TALER_PQ_query_param_denom_sig (&coin->denom_sig), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("existed", - &existed), - GNUNET_PQ_result_spec_uint64 ("known_coin_id", - known_coin_id), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - denom_hash), - &no_denom_pub_hash), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - h_age_commitment), - &no_age_commitment_hash), - GNUNET_PQ_result_spec_end - }; - - /* - See also: - https://stackoverflow.com/questions/34708509/how-to-use-returning-with-on-conflict-in-postgresql/37543015#37543015 - */ - PREPARE (pg, - "insert_known_coin", - "WITH dd" - " (denominations_serial" - " ,coin" - " ) AS (" - " SELECT " - " denominations_serial" - " ,coin" - " FROM denominations" - " WHERE denom_pub_hash=$2" - " ), input_rows" - " (coin_pub) AS (" - " VALUES ($1::BYTEA)" - " ), ins AS (" - " INSERT INTO known_coins " - " (coin_pub" - " ,denominations_serial" - " ,age_commitment_hash" - " ,denom_sig" - " ,remaining" - " ) SELECT " - " $1" - " ,denominations_serial" - " ,$3" - " ,$4" - " ,coin" - " FROM dd" - " ON CONFLICT DO NOTHING" /* CONFLICT on (coin_pub) */ - " RETURNING " - " known_coin_id" - " ) " - "SELECT " - " FALSE AS existed" - " ,known_coin_id" - " ,NULL AS denom_pub_hash" - " ,NULL AS age_commitment_hash" - " FROM ins " - "UNION ALL " - "SELECT " - " TRUE AS existed" - " ,known_coin_id" - " ,denom_pub_hash" - " ,kc.age_commitment_hash" - " FROM input_rows" - " JOIN known_coins kc USING (coin_pub)" - " JOIN denominations USING (denominations_serial)" - " LIMIT 1"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "insert_known_coin", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - return TALER_EXCHANGEDB_CKS_HARD_FAIL; - case GNUNET_DB_STATUS_SOFT_ERROR: - return TALER_EXCHANGEDB_CKS_SOFT_FAIL; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - GNUNET_break (0); /* should be impossible */ - return TALER_EXCHANGEDB_CKS_HARD_FAIL; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - if (! existed) - return TALER_EXCHANGEDB_CKS_ADDED; - break; /* continued below */ - } - - if ( (! no_denom_pub_hash) && - (0 != GNUNET_memcmp (denom_hash, - &coin->denom_pub_hash)) ) - { - GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; - } - - if (no_age_commitment_hash != coin->no_age_commitment) - { - if (no_age_commitment_hash) - { - GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NULL; - } - else - { - GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NON_NULL; - } - } - else if ( (! no_age_commitment_hash) && - (0 != GNUNET_memcmp (h_age_commitment, - &coin->h_age_commitment)) ) - { - GNUNET_break_op (0); - return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_VALUE_DIFFERS; - } - - return TALER_EXCHANGEDB_CKS_PRESENT; -} diff --git a/src/exchangedb/pg_event_listen.c b/src/exchangedb/pg_event_listen.c @@ -1,49 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_event_listen.c - * @brief Implementation of the event_listen function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_dbevents.h" -#include "taler/exchange-database/event_listen.h" -#include "helper.h" - -/** - * Register callback to be invoked on events of type @a es. - * - * @param pg the database context - * @param timeout how long until to generate a timeout event - * @param es specification of the event to listen for - * @param cb function to call when the event happens, possibly - * multiple times (until cancel is invoked) - * @param cb_cls closure for @a cb - * @return handle useful to cancel the listener - */ -struct GNUNET_DB_EventHandler * -TALER_EXCHANGEDB_event_listen (struct TALER_EXCHANGEDB_PostgresContext *pg, - struct GNUNET_TIME_Relative timeout, - const struct GNUNET_DB_EventHeaderP *es, - GNUNET_DB_EventCallback cb, - void *cb_cls) -{ - - return GNUNET_PQ_event_listen (pg->conn, - es, - timeout, - cb, - cb_cls); -} diff --git a/src/exchangedb/pg_event_listen_cancel.c b/src/exchangedb/pg_event_listen_cancel.c @@ -1,34 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_event_listen_cancel.c - * @brief Implementation of the event_listen_cancel function for Postgres - * @author Christian Grothoff - */ -#include "taler/exchange-database/event_listen_cancel.h" -#include "helper.h" - - -void -TALER_TALER_EXCHANGEDB_event_listen_cancel (struct - TALER_EXCHANGEDB_PostgresContext *pg - , - struct GNUNET_DB_EventHandler *eh) - -{ - (void) pg; - GNUNET_PQ_event_listen_cancel (eh); -} diff --git a/src/exchangedb/pg_event_notify.c b/src/exchangedb/pg_event_notify.c @@ -1,37 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_event_notify.c - * @brief Implementation of the event_notify function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_dbevents.h" -#include "taler/exchange-database/event_notify.h" -#include "helper.h" - - -void -TALER_EXCHANGEDB_event_notify (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct GNUNET_DB_EventHeaderP *es, - const void *extra, - size_t extra_size) -{ - - GNUNET_PQ_event_notify (pg->conn, - es, - extra, - extra_size); -} diff --git a/src/exchangedb/pg_expire_purse.c b/src/exchangedb/pg_expire_purse.c @@ -1,65 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_expire_purse.c - * @brief Implementation of the expire_purse function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/expire_purse.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_expire_purse ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - struct GNUNET_TIME_Absolute start_time, - struct GNUNET_TIME_Absolute end_time) -{ - struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_absolute_time (&start_time), - GNUNET_PQ_query_param_absolute_time (&end_time), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_end - }; - bool found = false; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("found", - &found), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - - PREPARE (pg, - "call_expire_purse", - "SELECT " - " out_found AS found" - " FROM exchange_do_expire_purse" - " ($1,$2,$3);"); - - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_expire_purse", - params, - rs); - if (qs < 0) - return qs; - GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); - return found - ? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT - : GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; -} diff --git a/src/exchangedb/pg_find_aggregation_transient.c b/src/exchangedb/pg_find_aggregation_transient.c @@ -1,69 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024, 2025 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/> - */ -/** - * @file exchangedb/pg_find_aggregation_transient.c - * @brief Implementation of the find_aggregation_transient function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/find_aggregation_transient.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_find_aggregation_transient ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - struct TALER_FullPayto *payto_uri, - struct TALER_WireTransferIdentifierRawP *wtid, - struct TALER_MerchantPublicKeyP *merchant_pub, - struct TALER_Amount *total) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", - merchant_pub), - GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", - wtid), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri->full_payto), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - total), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "find_transient_aggregations", - "SELECT" - " atr.amount" - " ,atr.wtid_raw" - " ,atr.merchant_pub" - " ,wt.payto_uri" - " FROM wire_targets wt" - " JOIN aggregation_transient atr" - " USING (wire_target_h_payto)" - " WHERE wt.h_normalized_payto=$1" - " LIMIT 1;"); /* Note: there should really be only 1 match */ - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "find_transient_aggregations", - params, - rs); -} diff --git a/src/exchangedb/pg_gc.c b/src/exchangedb/pg_gc.c @@ -1,75 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_gc.c - * @brief Implementation of the gc function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/gc.h" -#include "helper.h" - - -enum GNUNET_GenericReturnValue -TALER_EXCHANGEDB_gc (struct TALER_EXCHANGEDB_PostgresContext *pg) -{ - struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); - struct GNUNET_TIME_Absolute long_ago; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_absolute_time (&long_ago), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_Context *conn; - enum GNUNET_GenericReturnValue ret; - - /* Keep wire fees for 10 years, that should always - be enough _and_ they are tiny so it does not - matter to make this tight */ - long_ago = GNUNET_TIME_absolute_subtract ( - now, - GNUNET_TIME_relative_multiply ( - GNUNET_TIME_UNIT_YEARS, - 10)); - { - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - struct GNUNET_PQ_PreparedStatement ps[] = { - GNUNET_PQ_make_prepare ("run_gc", - "CALL" - " exchange_do_gc" - " ($1,$2);"), - GNUNET_PQ_PREPARED_STATEMENT_END - }; - - conn = GNUNET_PQ_connect_with_cfg (pg->cfg, - "exchangedb-postgres", - NULL, - es, - ps); - } - if (NULL == conn) - return GNUNET_SYSERR; - ret = GNUNET_OK; - if (0 > GNUNET_PQ_eval_prepared_non_select (conn, - "run_gc", - params)) - ret = GNUNET_SYSERR; - GNUNET_PQ_disconnect (conn); - return ret; -} diff --git a/src/exchangedb/pg_get_coin_denomination.c b/src/exchangedb/pg_get_coin_denomination.c @@ -1,65 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_coin_denomination.c - * @brief Implementation of the get_coin_denomination function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_coin_denomination.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_coin_denomination ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t *known_coin_id, - struct TALER_DenominationHashP *denom_hash) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - denom_hash), - GNUNET_PQ_result_spec_uint64 ("known_coin_id", - known_coin_id), - GNUNET_PQ_result_spec_end - }; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Getting coin denomination of coin %s\n", - TALER_B2S (coin_pub)); - - /* Used in #postgres_get_coin_denomination() to fetch - the denomination public key hash for - a coin known to the exchange. */ - PREPARE (pg, - "get_coin_denomination", - "SELECT" - " denominations.denom_pub_hash" - ",known_coin_id" - " FROM known_coins" - " JOIN denominations USING (denominations_serial)" - " WHERE coin_pub=$1" - " FOR SHARE;"); - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_coin_denomination", - params, - rs); -} diff --git a/src/exchangedb/pg_get_coin_transactions.c b/src/exchangedb/pg_get_coin_transactions.c @@ -1,1184 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2023 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/> - */ -/** - * @file pg_get_coin_transactions.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_exchangedb_lib.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_coin_transactions.h" -#include "helper.h" -#include "taler/exchange-database/start_read_committed.h" -#include "taler/exchange-database/commit.h" -#include "taler/exchange-database/rollback.h" - - -/** - * How often do we re-try when encountering DB serialization issues? - * (We are read-only, so can only happen due to concurrent insert, - * which should be very rare.) - */ -#define RETRIES 3 - -/** - * Closure for callbacks called from #TALER_EXCHANGEDB_get_coin_transactions() - */ -struct CoinHistoryContext -{ - /** - * Head of the coin's history list. - */ - struct TALER_EXCHANGEDB_TransactionList *head; - - /** - * Public key of the coin we are building the history for. - */ - const struct TALER_CoinSpendPublicKeyP *coin_pub; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Our current offset in the coin history. - */ - uint64_t chid; - - /** - * Set to 'true' if the transaction failed. - */ - bool failed; - -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct CoinHistoryContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -add_coin_deposit (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CoinHistoryContext *chc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; - - for (unsigned int i = 0; i < num_results; i++) - { - struct TALER_EXCHANGEDB_DepositListEntry *deposit; - struct TALER_EXCHANGEDB_TransactionList *tl; - uint64_t serial_id; - - deposit = GNUNET_new (struct TALER_EXCHANGEDB_DepositListEntry); - { - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &deposit->amount_with_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &deposit->deposit_fee), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &deposit->h_denom_pub), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &deposit->h_age_commitment), - &deposit->no_age_commitment), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("wallet_data_hash", - &deposit->wallet_data_hash), - &deposit->no_wallet_data_hash), - GNUNET_PQ_result_spec_timestamp ("wallet_timestamp", - &deposit->timestamp), - GNUNET_PQ_result_spec_timestamp ("refund_deadline", - &deposit->refund_deadline), - GNUNET_PQ_result_spec_timestamp ("wire_deadline", - &deposit->wire_deadline), - GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", - &deposit->merchant_pub), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - &deposit->h_contract_terms), - GNUNET_PQ_result_spec_auto_from_type ("wire_salt", - &deposit->wire_salt), - GNUNET_PQ_result_spec_string ("payto_uri", - &deposit->receiver_wire_account.full_payto - ), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &deposit->csig), - GNUNET_PQ_result_spec_uint64 ("coin_deposit_serial_id", - &serial_id), - GNUNET_PQ_result_spec_auto_from_type ("done", - &deposit->done), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - GNUNET_free (deposit); - chc->failed = true; - return; - } - } - tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); - tl->next = chc->head; - tl->type = TALER_EXCHANGEDB_TT_DEPOSIT; - tl->details.deposit = deposit; - tl->serial_id = serial_id; - tl->coin_history_id = chc->chid; - chc->head = tl; - } -} - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct CoinHistoryContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -add_coin_purse_deposit (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CoinHistoryContext *chc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; - - for (unsigned int i = 0; i < num_results; i++) - { - struct TALER_EXCHANGEDB_PurseDepositListEntry *deposit; - struct TALER_EXCHANGEDB_TransactionList *tl; - uint64_t serial_id; - - deposit = GNUNET_new (struct TALER_EXCHANGEDB_PurseDepositListEntry); - { - bool not_finished; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &deposit->amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &deposit->deposit_fee), - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - &deposit->purse_pub), - GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id", - &serial_id), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("partner_base_url", - &deposit->exchange_base_url), - NULL), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &deposit->coin_sig), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &deposit->h_age_commitment), - &deposit->no_age_commitment), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_bool ("refunded", - &deposit->refunded), - &not_finished), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &deposit->h_denom_pub), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - GNUNET_free (deposit); - chc->failed = true; - return; - } - if (not_finished) - deposit->refunded = false; - /* double-check for all-zeros age commitment */ - if (! deposit->no_age_commitment) - deposit->no_age_commitment - = GNUNET_is_zero (&deposit->h_age_commitment); - } - tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); - tl->next = chc->head; - tl->type = TALER_EXCHANGEDB_TT_PURSE_DEPOSIT; - tl->details.purse_deposit = deposit; - tl->serial_id = serial_id; - tl->coin_history_id = chc->chid; - chc->head = tl; - } -} - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct CoinHistoryContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -add_coin_melt (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CoinHistoryContext *chc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_MeltListEntry *melt; - struct TALER_EXCHANGEDB_TransactionList *tl; - uint64_t serial_id; - - melt = GNUNET_new (struct TALER_EXCHANGEDB_MeltListEntry); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("rc", - &melt->rc), - /* oldcoin_index not needed */ - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &melt->h_denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", - &melt->coin_sig), - GNUNET_PQ_result_spec_auto_from_type ("refresh_seed", - &melt->refresh_seed), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("blinding_seed", - &melt->blinding_seed), - &melt->no_blinding_seed), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &melt->amount_with_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", - &melt->melt_fee), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &melt->h_age_commitment), - &melt->no_age_commitment), - GNUNET_PQ_result_spec_uint64 ("refresh_id", - &serial_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - GNUNET_free (melt); - chc->failed = true; - return; - } - } - tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); - tl->next = chc->head; - tl->type = TALER_EXCHANGEDB_TT_MELT; - tl->details.melt = melt; - tl->serial_id = serial_id; - tl->coin_history_id = chc->chid; - chc->head = tl; - } -} - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct CoinHistoryContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -add_coin_refund (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CoinHistoryContext *chc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_RefundListEntry *refund; - struct TALER_EXCHANGEDB_TransactionList *tl; - uint64_t serial_id; - - refund = GNUNET_new (struct TALER_EXCHANGEDB_RefundListEntry); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", - &refund->merchant_pub), - GNUNET_PQ_result_spec_auto_from_type ("merchant_sig", - &refund->merchant_sig), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - &refund->h_contract_terms), - GNUNET_PQ_result_spec_uint64 ("rtransaction_id", - &refund->rtransaction_id), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &refund->refund_amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", - &refund->refund_fee), - GNUNET_PQ_result_spec_uint64 ("refund_serial_id", - &serial_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - GNUNET_free (refund); - chc->failed = true; - return; - } - } - tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); - tl->next = chc->head; - tl->type = TALER_EXCHANGEDB_TT_REFUND; - tl->details.refund = refund; - tl->serial_id = serial_id; - tl->coin_history_id = chc->chid; - chc->head = tl; - } -} - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct CoinHistoryContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -add_coin_purse_decision (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CoinHistoryContext *chc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_PurseRefundListEntry *prefund; - struct TALER_EXCHANGEDB_TransactionList *tl; - uint64_t serial_id; - - prefund = GNUNET_new (struct TALER_EXCHANGEDB_PurseRefundListEntry); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - &prefund->purse_pub), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &prefund->refund_amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", - &prefund->refund_fee), - GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id", - &serial_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - GNUNET_free (prefund); - chc->failed = true; - return; - } - } - tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); - tl->next = chc->head; - tl->type = TALER_EXCHANGEDB_TT_PURSE_REFUND; - tl->details.purse_refund = prefund; - tl->serial_id = serial_id; - tl->coin_history_id = chc->chid; - chc->head = tl; - } -} - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct CoinHistoryContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -add_old_coin_recoup (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CoinHistoryContext *chc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup; - struct TALER_EXCHANGEDB_TransactionList *tl; - uint64_t serial_id; - - recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupRefreshListEntry); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &recoup->coin.coin_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &recoup->coin_sig), - GNUNET_PQ_result_spec_auto_from_type ("coin_blind", - &recoup->coin_blind), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &recoup->value), - GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", - &recoup->timestamp), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &recoup->coin.denom_pub_hash), - TALER_PQ_result_spec_denom_sig ("denom_sig", - &recoup->coin.denom_sig), - GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid", - &serial_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - GNUNET_free (recoup); - chc->failed = true; - return; - } - recoup->old_coin_pub = *chc->coin_pub; - } - tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); - tl->next = chc->head; - tl->type = TALER_EXCHANGEDB_TT_RECOUP_REFRESH_RECEIVER; - tl->details.old_coin_recoup = recoup; - tl->serial_id = serial_id; - tl->coin_history_id = chc->chid; - chc->head = tl; - } -} - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct CoinHistoryContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -add_coin_recoup (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CoinHistoryContext *chc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_RecoupListEntry *recoup; - struct TALER_EXCHANGEDB_TransactionList *tl; - uint64_t serial_id; - - recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupListEntry); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &recoup->reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &recoup->coin_sig), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &recoup->h_denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_blind", - &recoup->coin_blind), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &recoup->value), - GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", - &recoup->timestamp), - GNUNET_PQ_result_spec_uint64 ("recoup_uuid", - &serial_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - GNUNET_free (recoup); - chc->failed = true; - return; - } - } - tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); - tl->next = chc->head; - tl->type = TALER_EXCHANGEDB_TT_RECOUP_WITHDRAW; - tl->details.recoup = recoup; - tl->serial_id = serial_id; - tl->coin_history_id = chc->chid; - chc->head = tl; - } -} - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct CoinHistoryContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -add_coin_recoup_refresh (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CoinHistoryContext *chc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup; - struct TALER_EXCHANGEDB_TransactionList *tl; - uint64_t serial_id; - - recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupRefreshListEntry); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", - &recoup->old_coin_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &recoup->coin_sig), - GNUNET_PQ_result_spec_auto_from_type ("coin_blind", - &recoup->coin_blind), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &recoup->value), - GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", - &recoup->timestamp), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &recoup->coin.denom_pub_hash), - TALER_PQ_result_spec_denom_sig ("denom_sig", - &recoup->coin.denom_sig), - GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid", - &serial_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - GNUNET_free (recoup); - chc->failed = true; - return; - } - recoup->coin.coin_pub = *chc->coin_pub; - } - tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); - tl->next = chc->head; - tl->type = TALER_EXCHANGEDB_TT_RECOUP_REFRESH; - tl->details.recoup_refresh = recoup; - tl->serial_id = serial_id; - tl->coin_history_id = chc->chid; - chc->head = tl; - } -} - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct CoinHistoryContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -add_coin_reserve_open (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CoinHistoryContext *chc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_ReserveOpenListEntry *role; - struct TALER_EXCHANGEDB_TransactionList *tl; - uint64_t serial_id; - - role = GNUNET_new (struct TALER_EXCHANGEDB_ReserveOpenListEntry); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &role->reserve_sig), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &role->coin_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ("contribution", - &role->coin_contribution), - GNUNET_PQ_result_spec_uint64 ("reserve_open_deposit_uuid", - &serial_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - GNUNET_free (role); - chc->failed = true; - return; - } - } - tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); - tl->next = chc->head; - tl->type = TALER_EXCHANGEDB_TT_RESERVE_OPEN; - tl->details.reserve_open = role; - tl->serial_id = serial_id; - tl->coin_history_id = chc->chid; - chc->head = tl; - } -} - - -/** - * Work we need to do. - */ -struct Work -{ - /** - * Name of the table. - */ - const char *table; - - /** - * SQL prepared statement name. - */ - const char *statement; - - /** - * Function to call to handle the result(s). - */ - GNUNET_PQ_PostgresResultHandler cb; -}; - - -/** - * We found a coin history entry. Lookup details - * from the respective table and store in @a cls. - * - * @param[in,out] cls a `struct CoinHistoryContext` - * @param result a coin history entry result set - * @param num_results total number of results in @a results - */ -static void -handle_history_entry (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CoinHistoryContext *chc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg; - static const struct Work work[] = { - [TALER_EXCHANGEDB_TT_DEPOSIT] = - { "coin_deposits", - "get_deposit_with_coin_pub", - &add_coin_deposit }, - [TALER_EXCHANGEDB_TT_MELT] = - { "refresh", - "get_refresh_by_coin", - &add_coin_melt }, - [TALER_EXCHANGEDB_TT_PURSE_DEPOSIT] = - { "purse_deposits", - "get_purse_deposit_by_coin_pub", - &add_coin_purse_deposit }, - [TALER_EXCHANGEDB_TT_PURSE_REFUND] = - { "purse_decision", - "get_purse_decision_by_coin_pub", - &add_coin_purse_decision }, - [TALER_EXCHANGEDB_TT_REFUND] = - { "refunds", - "get_refunds_by_coin", - &add_coin_refund }, - [TALER_EXCHANGEDB_TT_RECOUP_WITHDRAW] = - { "recoup", - "recoup_by_coin", - &add_coin_recoup }, - [TALER_EXCHANGEDB_TT_RECOUP_REFRESH] = - { "recoup_refresh::NEW", - "recoup_by_refreshed_coin", - &add_coin_recoup_refresh }, - [TALER_EXCHANGEDB_TT_RECOUP_REFRESH_RECEIVER] = - { "recoup_refresh::OLD", - "recoup_by_old_coin", - &add_old_coin_recoup }, - [TALER_EXCHANGEDB_TT_RESERVE_OPEN] = - { "reserves_open_deposits", - "reserve_open_by_coin", - &add_coin_reserve_open }, - { NULL, NULL, NULL } - }; - char *table_name; - uint64_t serial_id; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("table_name", - &table_name), - GNUNET_PQ_result_spec_uint64 ("serial_id", - &serial_id), - GNUNET_PQ_result_spec_uint64 ("coin_history_serial_id", - &chc->chid), - GNUNET_PQ_result_spec_end - }; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (chc->coin_pub), - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - - for (unsigned int i = 0; i<num_results; i++) - { - enum GNUNET_DB_QueryStatus qs; - bool found = false; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - chc->failed = true; - return; - } - - for (unsigned int s = 0; - NULL != work[s].statement; - s++) - { - if (0 != strcmp (table_name, - work[s].table)) - continue; - found = true; - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - work[s].statement, - params, - work[s].cb, - chc); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Coin %s had %d transactions at %llu in table %s\n", - TALER_B2S (chc->coin_pub), - (int) qs, - (unsigned long long) serial_id, - table_name); - if (0 > qs) - chc->failed = true; - break; - } - if (! found) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Coin history includes unsupported table `%s`\n", - table_name); - chc->failed = true; - } - GNUNET_PQ_cleanup_result (rs); - if (chc->failed) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_coin_transactions ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - bool begin_transaction, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t start_off, - uint64_t etag_in, - uint64_t *etag_out, - struct TALER_Amount *balance, - struct TALER_DenominationHashP *h_denom_pub, - struct TALER_EXCHANGEDB_TransactionList **tlp) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_QueryParam lparams[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_uint64 (&start_off), - GNUNET_PQ_query_param_end - }; - struct CoinHistoryContext chc = { - .head = NULL, - .coin_pub = coin_pub, - .pg = pg - }; - - *tlp = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Getting transactions for coin %s\n", - TALER_B2S (coin_pub)); - PREPARE (pg, - "get_coin_history_etag_balance", - "SELECT" - " ch.coin_history_serial_id" - ",kc.remaining" - ",denom.denom_pub_hash" - " FROM coin_history ch" - " JOIN known_coins kc" - " USING (coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " WHERE coin_pub=$1" - " ORDER BY coin_history_serial_id DESC" - " LIMIT 1;"); - PREPARE (pg, - "get_coin_history", - "SELECT" - " table_name" - ",serial_id" - ",coin_history_serial_id" - " FROM coin_history" - " WHERE coin_pub=$1" - " AND coin_history_serial_id > $2" - " ORDER BY coin_history_serial_id DESC;"); - PREPARE (pg, - "get_deposit_with_coin_pub", - "SELECT" - " cdep.amount_with_fee" - ",denoms.fee_deposit" - ",denoms.denom_pub_hash" - ",kc.age_commitment_hash" - ",bdep.wallet_timestamp" - ",bdep.refund_deadline" - ",bdep.wire_deadline" - ",bdep.merchant_pub" - ",bdep.h_contract_terms" - ",bdep.wallet_data_hash" - ",bdep.wire_salt" - ",wt.payto_uri" - ",cdep.coin_sig" - ",cdep.coin_deposit_serial_id" - ",bdep.done" - " FROM coin_deposits cdep" - " JOIN batch_deposits bdep" - " USING (batch_deposit_serial_id)" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " JOIN known_coins kc" - " ON (kc.coin_pub = cdep.coin_pub)" - " JOIN denominations denoms" - " USING (denominations_serial)" - " WHERE cdep.coin_pub=$1" - " AND cdep.coin_deposit_serial_id=$2;"); - PREPARE (pg, - "get_refresh_by_coin", - "SELECT" - " rc" - ",refresh_seed" - ",blinding_seed" - ",old_coin_sig" - ",amount_with_fee" - ",denoms.denom_pub_hash" - ",denoms.fee_refresh" - ",kc.age_commitment_hash" - ",refresh_id" - " FROM refresh" - " JOIN known_coins kc" - " ON (refresh.old_coin_pub = kc.coin_pub)" - " JOIN denominations denoms" - " USING (denominations_serial)" - " WHERE old_coin_pub=$1" - " AND refresh_id=$2;"); - PREPARE (pg, - "get_purse_deposit_by_coin_pub", - "SELECT" - " partner_base_url" - ",pd.amount_with_fee" - ",denoms.fee_deposit" - ",denoms.denom_pub_hash" - ",pd.purse_pub" - ",kc.age_commitment_hash" - ",pd.coin_sig" - ",pd.purse_deposit_serial_id" - ",pdes.refunded" - " FROM purse_deposits pd" - " LEFT JOIN partners" - " USING (partner_serial_id)" - " JOIN purse_requests pr" - " USING (purse_pub)" - " LEFT JOIN purse_decision pdes" - " USING (purse_pub)" - " JOIN known_coins kc" - " ON (pd.coin_pub = kc.coin_pub)" - " JOIN denominations denoms" - " USING (denominations_serial)" - " WHERE pd.purse_deposit_serial_id=$2" - " AND pd.coin_pub=$1;"); - PREPARE (pg, - "get_purse_decision_by_coin_pub", - "SELECT" - " pdes.purse_pub" - ",pd.amount_with_fee" - ",denom.fee_refund" - ",pdes.purse_decision_serial_id" - " FROM purse_decision pdes" - " JOIN purse_deposits pd" - " USING (purse_pub)" - " JOIN known_coins kc" - " ON (pd.coin_pub = kc.coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " WHERE pd.coin_pub=$1" - " AND pdes.purse_decision_serial_id=$2" - " AND pdes.refunded;"); - PREPARE (pg, - "get_refunds_by_coin", - "SELECT" - " bdep.merchant_pub" - ",ref.merchant_sig" - ",bdep.h_contract_terms" - ",ref.rtransaction_id" - ",ref.amount_with_fee" - ",denom.fee_refund" - ",ref.refund_serial_id" - " FROM refunds ref" - " JOIN coin_deposits cdep" - " ON (ref.coin_pub = cdep.coin_pub AND ref.batch_deposit_serial_id = cdep.batch_deposit_serial_id)" - " JOIN batch_deposits bdep" - " ON (ref.batch_deposit_serial_id = bdep.batch_deposit_serial_id)" - " JOIN known_coins kc" - " ON (ref.coin_pub = kc.coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " WHERE ref.coin_pub=$1" - " AND ref.refund_serial_id=$2;"); - PREPARE (pg, - "recoup_by_old_coin", - "SELECT" - " coins.coin_pub" - ",rr.coin_sig" - ",rr.coin_blind" - ",rr.amount" - ",rr.recoup_timestamp" - ",denoms.denom_pub_hash" - ",coins.denom_sig" - ",rr.recoup_refresh_uuid" - " FROM recoup_refresh rr" - " JOIN known_coins coins" - " USING (coin_pub)" - " JOIN denominations denoms" - " USING (denominations_serial)" - " WHERE recoup_refresh_uuid=$2" - " AND refresh_id IN" - " (SELECT refresh_id" - " FROM refresh" - " WHERE refresh.old_coin_pub=$1);"); - PREPARE (pg, - "recoup_by_coin", - "SELECT" - " res.reserve_pub" - ",denoms.denom_pub_hash" - ",rcp.coin_sig" - ",rcp.coin_blind" - ",rcp.amount" - ",rcp.recoup_timestamp" - ",rcp.recoup_uuid" - " FROM recoup rcp" - " JOIN withdraw ro" - " USING (withdraw_id)" - " JOIN reserves res" - " USING (reserve_pub)" - " JOIN known_coins coins" - " USING (coin_pub)" - " JOIN denominations denoms" - " ON (denoms.denominations_serial = coins.denominations_serial)" - " WHERE rcp.recoup_uuid=$2" - " AND coins.coin_pub=$1;"); - /* Used to obtain recoup transactions - for a refreshed coin */ - PREPARE (pg, - "recoup_by_refreshed_coin", - "SELECT" - " old_coins.coin_pub AS old_coin_pub" - ",rr.coin_sig" - ",rr.coin_blind" - ",rr.amount" - ",rr.recoup_timestamp" - ",denoms.denom_pub_hash" - ",coins.denom_sig" - ",recoup_refresh_uuid" - " FROM recoup_refresh rr" - " JOIN refresh rfc" - " ON (rr.refresh_id = rfc.refresh_id)" - " JOIN known_coins old_coins" - " ON (rfc.old_coin_pub = old_coins.coin_pub)" - " JOIN known_coins coins" - " ON (rr.coin_pub = coins.coin_pub)" - " JOIN denominations denoms" - " ON (denoms.denominations_serial = coins.denominations_serial)" - " WHERE rr.recoup_refresh_uuid=$2" - " AND coins.coin_pub=$1;"); - PREPARE (pg, - "reserve_open_by_coin", - "SELECT" - " reserve_open_deposit_uuid" - ",coin_sig" - ",reserve_sig" - ",contribution" - " FROM reserves_open_deposits" - " WHERE coin_pub=$1" - " AND reserve_open_deposit_uuid=$2;"); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - " --- landed here 1\n"); - for (unsigned int i = 0; i<RETRIES; i++) - { - enum GNUNET_DB_QueryStatus qs; - uint64_t end; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("coin_history_serial_id", - &end), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - h_denom_pub), - TALER_PQ_RESULT_SPEC_AMOUNT ("remaining", - balance), - GNUNET_PQ_result_spec_end - }; - - if (begin_transaction) - { - if (GNUNET_OK != - TALER_TALER_EXCHANGEDB_start_read_committed (pg, - "get-coin-transactions")) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - } - /* First only check the last item, to see if - we even need to iterate */ - qs = GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "get_coin_history_etag_balance", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - if (begin_transaction) - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - if (begin_transaction) - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - if (begin_transaction) - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - *etag_out = end; - if (end == etag_in) - return qs; - } - /* We indeed need to iterate over the history */ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Current ETag for coin %s is %llu\n", - TALER_B2S (coin_pub), - (unsigned long long) end); - - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "get_coin_history", - lparams, - &handle_history_entry, - &chc); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - if (begin_transaction) - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - if (begin_transaction) - TALER_EXCHANGEDB_rollback (pg); - continue; - default: - break; - } - if (chc.failed) - { - if (begin_transaction) - TALER_EXCHANGEDB_rollback (pg); - TALER_EXCHANGEDB_free_coin_transaction_list (chc.head); - return GNUNET_DB_STATUS_SOFT_ERROR; - } - if (! begin_transaction) - { - *tlp = chc.head; - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } - qs = TALER_EXCHANGEDB_commit (pg); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - TALER_EXCHANGEDB_free_coin_transaction_list (chc.head); - chc.head = NULL; - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TALER_EXCHANGEDB_free_coin_transaction_list (chc.head); - chc.head = NULL; - continue; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - *tlp = chc.head; - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - " --- landed here 2\n"); - return GNUNET_DB_STATUS_SOFT_ERROR; -} diff --git a/src/exchangedb/pg_get_denomination_by_serial.c b/src/exchangedb/pg_get_denomination_by_serial.c @@ -1,87 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_get_denomination_by_serial.c - * @brief Implementation of the get_denomination_by_serial function for Postgres - * @author Özgür Kesim - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_denomination_by_serial.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_denomination_by_serial ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t denom_serial, - struct TALER_EXCHANGEDB_DenominationKeyInformation *issue) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&denom_serial), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &issue->signature), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &issue->denom_hash), - GNUNET_PQ_result_spec_timestamp ("valid_from", - &issue->start), - GNUNET_PQ_result_spec_timestamp ("expire_withdraw", - &issue->expire_withdraw), - GNUNET_PQ_result_spec_timestamp ("expire_deposit", - &issue->expire_deposit), - GNUNET_PQ_result_spec_timestamp ("expire_legal", - &issue->expire_legal), - TALER_PQ_RESULT_SPEC_AMOUNT ("coin", - &issue->value), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", - &issue->fees.withdraw), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &issue->fees.deposit), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", - &issue->fees.refresh), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", - &issue->fees.refund), - GNUNET_PQ_result_spec_uint32 ("age_mask", - &issue->age_mask.bits), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "denomination_get_by_serial", - "SELECT" - " master_sig" - ",denom_pub_hash" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin" /* value of this denom */ - ",fee_withdraw" - ",fee_deposit" - ",fee_refresh" - ",fee_refund" - ",age_mask" - " FROM denominations" - " WHERE denominations_serial=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "denomination_get_by_serial", - params, - rs); -} diff --git a/src/exchangedb/pg_get_denomination_info.c b/src/exchangedb/pg_get_denomination_info.c @@ -1,96 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022,2025 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/> - */ -/** - * @file exchangedb/pg_get_denomination_info.c - * @brief Implementation of the get_denomination_info function for Postgres - * @author Christian Grothoff - * @author Özgür Kesim - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_denomination_info.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_denomination_info ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_DenominationHashP *denom_pub_hash, - uint64_t *denom_serial, - struct TALER_EXCHANGEDB_DenominationKeyInformation *issue) -{ - enum GNUNET_DB_QueryStatus qs; - uint64_t serial; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("denominations_serial", - &serial), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &issue->signature), - GNUNET_PQ_result_spec_timestamp ("valid_from", - &issue->start), - GNUNET_PQ_result_spec_timestamp ("expire_withdraw", - &issue->expire_withdraw), - GNUNET_PQ_result_spec_timestamp ("expire_deposit", - &issue->expire_deposit), - GNUNET_PQ_result_spec_timestamp ("expire_legal", - &issue->expire_legal), - TALER_PQ_RESULT_SPEC_AMOUNT ("coin", - &issue->value), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", - &issue->fees.withdraw), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &issue->fees.deposit), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", - &issue->fees.refresh), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", - &issue->fees.refund), - GNUNET_PQ_result_spec_uint32 ("age_mask", - &issue->age_mask.bits), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "denomination_get", - "SELECT" - " denominations_serial" - ",master_sig" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin" /* value of this denom */ - ",fee_withdraw" - ",fee_deposit" - ",fee_refresh" - ",fee_refund" - ",age_mask" - " FROM denominations" - " WHERE denom_pub_hash=$1;"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "denomination_get", - params, - rs); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) - return qs; - issue->denom_hash = *denom_pub_hash; - if (NULL != denom_serial) - *denom_serial = serial; - return qs; -} diff --git a/src/exchangedb/pg_get_denomination_revocation.c b/src/exchangedb/pg_get_denomination_revocation.c @@ -1,59 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_denomination_revocation.c - * @brief Implementation of the get_denomination_revocation function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_denomination_revocation.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_denomination_revocation ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_DenominationHashP *denom_pub_hash, - struct TALER_MasterSignatureP *master_sig, - uint64_t *rowid) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - master_sig), - GNUNET_PQ_result_spec_uint64 ("denom_revocations_serial_id", - rowid), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "denomination_revocation_get", - "SELECT" - " master_sig" - ",denom_revocations_serial_id" - " FROM denomination_revocations" - " WHERE denominations_serial=" - " (SELECT denominations_serial" - " FROM denominations" - " WHERE denom_pub_hash=$1);"); - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "denomination_revocation_get", - params, - rs); -} diff --git a/src/exchangedb/pg_get_drain_profit.c b/src/exchangedb/pg_get_drain_profit.c @@ -1,72 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_drain_profit.c - * @brief Implementation of the get_drain_profit function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_drain_profit.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_drain_profit ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_WireTransferIdentifierRawP *wtid, - uint64_t *serial, - char **account_section, - struct TALER_FullPayto *payto_uri, - struct GNUNET_TIME_Timestamp *request_timestamp, - struct TALER_Amount *amount, - struct TALER_MasterSignatureP *master_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (wtid), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("profit_drain_serial_id", - serial), - GNUNET_PQ_result_spec_string ("account_section", - account_section), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri->full_payto), - GNUNET_PQ_result_spec_timestamp ("trigger_date", - request_timestamp), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - amount), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - master_sig), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "get_profit_drain", - "SELECT" - " profit_drain_serial_id" - ",account_section" - ",payto_uri" - ",trigger_date" - ",amount" - ",master_sig" - " FROM profit_drains" - " WHERE wtid=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_profit_drain", - params, - rs); -} diff --git a/src/exchangedb/pg_get_expired_reserves.c b/src/exchangedb/pg_get_expired_reserves.c @@ -1,169 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file pg_get_expired_reserves.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_expired_reserves.h" -#include "helper.h" - - -/** - * Closure for #reserve_expired_cb(). - */ -struct ExpiredReserveContext -{ - /** - * Function to call for each expired reserve. - */ - TALER_EXCHANGEDB_ReserveExpiredCallback rec; - - /** - * Closure to give to @e rec. - */ - void *rec_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on error. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -reserve_expired_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ExpiredReserveContext *erc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = erc->pg; - enum GNUNET_GenericReturnValue ret = GNUNET_OK; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_TIME_Timestamp exp_date; - struct TALER_FullPayto account_details; - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_Amount remaining_balance; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("expiration_date", - &exp_date), - GNUNET_PQ_result_spec_string ("account_details", - &account_details.full_payto), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - TALER_PQ_result_spec_amount ("current_balance", - pg->currency, - &remaining_balance), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ret = GNUNET_SYSERR; - break; - } - ret = erc->rec (erc->rec_cls, - &reserve_pub, - &remaining_balance, - account_details, - exp_date, - 0); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } - erc->status = ret; -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_expired_reserves ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - struct GNUNET_TIME_Timestamp now, - TALER_EXCHANGEDB_ReserveExpiredCallback rec, - void *rec_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&now), - GNUNET_PQ_query_param_end - }; - struct ExpiredReserveContext ectx = { - .rec = rec, - .rec_cls = rec_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "get_expired_reserves", - "WITH ed AS MATERIALIZED ( " - " SELECT expiration_date" - " ,wire_source_h_payto" - " ,current_balance" - " ,r.reserve_pub" - " FROM reserves r" - " JOIN reserves_in" - " USING (reserve_pub)" - " WHERE expiration_date <= $1 " - " AND ((current_balance).val != 0 OR (current_balance).frac != 0) " - " ORDER BY expiration_date ASC " - " LIMIT 1 " - ") " - "SELECT" - " wt.payto_uri AS account_details" - " ,ed.expiration_date" - " ,ed.reserve_pub" - " ,ed.current_balance" - " FROM wire_targets wt" - " JOIN ed" - " ON (ed.wire_source_h_payto=wt.wire_target_h_payto);"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "get_expired_reserves", - params, - &reserve_expired_cb, - &ectx); - switch (ectx.status) - { - case GNUNET_SYSERR: - return GNUNET_DB_STATUS_HARD_ERROR; - case GNUNET_NO: - return GNUNET_DB_STATUS_SOFT_ERROR; - case GNUNET_OK: - break; - } - return qs; -} diff --git a/src/exchangedb/pg_get_extension_manifest.c b/src/exchangedb/pg_get_extension_manifest.c @@ -1,64 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_extension_manifest.c - * @brief Implementation of the get_extension_manifest function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_extension_manifest.h" -#include "helper.h" - -/** - * Function called to get the manifest of an extension - * (age-restriction, policy_extension_...) - * - * @param pg the database context - * @param extension_name the name of the extension - * @param[out] manifest JSON object of the manifest as string - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_extension_manifest (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const char *extension_name, - char **manifest) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (extension_name), - GNUNET_PQ_query_param_end - }; - bool is_null; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("manifest", - manifest), - &is_null), - GNUNET_PQ_result_spec_end - }; - - *manifest = NULL; - PREPARE (pg, - "get_extension_manifest", - "SELECT" - " manifest" - " FROM extensions" - " WHERE name=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_extension_manifest", - params, - rs); -} diff --git a/src/exchangedb/pg_get_global_fee.c b/src/exchangedb/pg_get_global_fee.c @@ -1,85 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_global_fee.c - * @brief Implementation of the get_global_fee function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_dbevents.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_global_fee.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg, - struct GNUNET_TIME_Timestamp date, - struct GNUNET_TIME_Timestamp *start_date, - struct GNUNET_TIME_Timestamp *end_date, - struct TALER_GlobalFeeSet *fees, - struct GNUNET_TIME_Relative *purse_timeout, - struct GNUNET_TIME_Relative *history_expiration - , - uint32_t *purse_account_limit, - struct TALER_MasterSignatureP *master_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&date), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("start_date", - start_date), - GNUNET_PQ_result_spec_timestamp ("end_date", - end_date), - TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee", - &fees->history), - TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee", - &fees->account), - TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", - &fees->purse), - GNUNET_PQ_result_spec_relative_time ("purse_timeout", - purse_timeout), - GNUNET_PQ_result_spec_relative_time ("history_expiration", - history_expiration), - GNUNET_PQ_result_spec_uint32 ("purse_account_limit", - purse_account_limit), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - master_sig), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "get_global_fee", - "SELECT " - " start_date" - ",end_date" - ",history_fee" - ",account_fee" - ",purse_fee" - ",purse_timeout" - ",history_expiration" - ",purse_account_limit" - ",master_sig" - " FROM global_fee" - " WHERE start_date <= $1" - " AND end_date > $1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_global_fee", - params, - rs); -} diff --git a/src/exchangedb/pg_get_global_fees.c b/src/exchangedb/pg_get_global_fees.c @@ -1,164 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_global_fees.c - * @brief Implementation of the get_global_fees function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_dbevents.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_global_fees.h" -#include "helper.h" - - -/** - * Closure for #global_fees_cb(). - */ -struct GlobalFeeContext -{ - /** - * Function to call for each global fee block. - */ - TALER_EXCHANGEDB_GlobalFeeCallback cb; - - /** - * Closure to give to @e rec. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on error. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -global_fees_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct GlobalFeeContext *gctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = gctx->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_GlobalFeeSet fees; - struct GNUNET_TIME_Relative purse_timeout; - struct GNUNET_TIME_Relative history_expiration; - uint32_t purse_account_limit; - struct GNUNET_TIME_Timestamp start_date; - struct GNUNET_TIME_Timestamp end_date; - struct TALER_MasterSignatureP master_sig; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("start_date", - &start_date), - GNUNET_PQ_result_spec_timestamp ("end_date", - &end_date), - TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee", - &fees.history), - TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee", - &fees.account), - TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", - &fees.purse), - GNUNET_PQ_result_spec_relative_time ("purse_timeout", - &purse_timeout), - GNUNET_PQ_result_spec_relative_time ("history_expiration", - &history_expiration), - GNUNET_PQ_result_spec_uint32 ("purse_account_limit", - &purse_account_limit), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &master_sig), - GNUNET_PQ_result_spec_end - }; - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - gctx->status = GNUNET_SYSERR; - break; - } - gctx->cb (gctx->cb_cls, - &fees, - purse_timeout, - history_expiration, - purse_account_limit, - start_date, - end_date, - &master_sig); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_get_global_fees (struct - TALER_EXCHANGEDB_PostgresContext *pg, - TALER_EXCHANGEDB_GlobalFeeCallback cb, - void *cb_cls) -{ - struct GNUNET_TIME_Timestamp date - = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_subtract ( - GNUNET_TIME_absolute_get (), - GNUNET_TIME_UNIT_YEARS)); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&date), - GNUNET_PQ_query_param_end - }; - struct GlobalFeeContext gctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - - PREPARE (pg, - "get_global_fees", - "SELECT " - " start_date" - ",end_date" - ",history_fee" - ",account_fee" - ",purse_fee" - ",purse_timeout" - ",history_expiration" - ",purse_account_limit" - ",master_sig" - " FROM global_fee" - " WHERE start_date >= $1"); - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "get_global_fees", - params, - &global_fees_cb, - &gctx); -} diff --git a/src/exchangedb/pg_get_known_coin.c b/src/exchangedb/pg_get_known_coin.c @@ -1,64 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_known_coin.c - * @brief Implementation of the get_known_coin function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_known_coin.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_known_coin (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_CoinSpendPublicKeyP * - coin_pub, - struct TALER_CoinPublicInfo *coin_info) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &coin_info->denom_pub_hash), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &coin_info->h_age_commitment), - &coin_info->no_age_commitment), - TALER_PQ_result_spec_denom_sig ("denom_sig", - &coin_info->denom_sig), - GNUNET_PQ_result_spec_end - }; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Getting known coin data for coin %s\n", - TALER_B2S (coin_pub)); - coin_info->coin_pub = *coin_pub; - PREPARE (pg, - "get_known_coin", - "SELECT" - " denominations.denom_pub_hash" - ",age_commitment_hash" - ",denom_sig" - " FROM known_coins" - " JOIN denominations USING (denominations_serial)" - " WHERE coin_pub=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_known_coin", - params, - rs); -} diff --git a/src/exchangedb/pg_get_kyc_rules.c b/src/exchangedb/pg_get_kyc_rules.c @@ -1,124 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2025 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/> - */ -/** - * @file exchangedb/pg_get_kyc_rules.c - * @brief Implementation of the get_kyc_rules function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_kyc_rules.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_kyc_rules ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - const struct TALER_MerchantPublicKeyP *merchant_pub, - bool *no_account_pub, - union TALER_AccountPublicKeyP *account_pub, - bool *no_reserve_pub, - struct TALER_ReservePublicKeyP *reserve_pub, - json_t **jrules) -{ - struct GNUNET_TIME_Timestamp now - = GNUNET_TIME_timestamp_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_timestamp (&now), - NULL != merchant_pub - ? GNUNET_PQ_query_param_auto_from_type (merchant_pub) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("target_pub", - account_pub), - no_account_pub), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - reserve_pub), - no_reserve_pub), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ("jnew_rules", - jrules), - NULL), - GNUNET_PQ_result_spec_end - }; - - *jrules = NULL; - *no_account_pub = true; - *no_reserve_pub = true; - memset (account_pub, - 0, - sizeof (*account_pub)); - memset (reserve_pub, - 0, - sizeof (*reserve_pub)); - PREPARE (pg, - "get_kyc_rules", - "SELECT" - " out_target_pub AS target_pub" - " ,out_jnew_rules::TEXT AS jnew_rules" - " ,out_reserve_pub AS reserve_pub" - " FROM exchange_do_get_kyc_rules ($1,$2,$3);"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "get_kyc_rules", - params, - rs); -} - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_get_kyc_rules2 ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - json_t **jrules) -{ - struct GNUNET_TIME_Timestamp now - = GNUNET_TIME_timestamp_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_timestamp (&now), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ("jnew_rules", - jrules), - NULL), - GNUNET_PQ_result_spec_end - }; - - *jrules = NULL; - PREPARE (pg, - "get_kyc_rules2", - "SELECT" - " jnew_rules::TEXT" - " FROM legitimization_outcomes" - " WHERE h_payto=$1" - " AND expiration_time >= $2" - " AND is_active" - " ORDER BY expiration_time DESC" - " LIMIT 1;"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "get_kyc_rules2", - params, - rs); -} diff --git a/src/exchangedb/pg_get_old_coin_by_h_blind.c b/src/exchangedb/pg_get_old_coin_by_h_blind.c @@ -1,60 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2025 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/> - */ -/** - * @file exchangedb/pg_get_old_coin_by_h_blind.c - * @brief Implementation of the get_old_coin_by_h_blind function for Postgres - * @author Christian Grothoff - * @author Özgür Kesim - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_old_coin_by_h_blind.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_old_coin_by_h_blind ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_BlindedCoinHashP *h_blind_ev, - struct TALER_CoinSpendPublicKeyP *old_coin_pub, - uint64_t *refresh_id) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_blind_ev), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", - old_coin_pub), - GNUNET_PQ_result_spec_uint64 ("refresh_id", - refresh_id), - GNUNET_PQ_result_spec_end - }; - - /* Used in #postgres_get_old_coin_by_h_blind() */ - PREPARE (pg, - "old_coin_by_h_blind", - "SELECT" - " okc.coin_pub AS old_coin_pub" - ",refresh_id" - " FROM refresh " - " JOIN known_coins okc ON (refresh.old_coin_pub = okc.coin_pub)" - " WHERE $1=ANY(h_blind_evs)" - " LIMIT 1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "old_coin_by_h_blind", - params, - rs); -} diff --git a/src/exchangedb/pg_get_pending_kyc_requirement_process.c b/src/exchangedb/pg_get_pending_kyc_requirement_process.c @@ -1,62 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023 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/> - */ -/** - * @file exchangedb/pg_get_pending_kyc_requirement_process.c - * @brief Implementation of the get_pending_kyc_requirement_process function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_pending_kyc_requirement_process.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_pending_kyc_requirement_process ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - const char *provider_name, - char **redirect_url) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (provider_name), - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("redirect_url", - redirect_url), - NULL), - GNUNET_PQ_result_spec_end - }; - - *redirect_url = NULL; - PREPARE (pg, - "get_pending_kyc_requirement_process", - "SELECT" - " redirect_url" - " FROM legitimization_processes" - " WHERE provider_name=$1" - " AND h_payto=$2" - " AND NOT finished" - " ORDER BY start_time DESC" - " LIMIT 1"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "get_pending_kyc_requirement_process", - params, - rs); -} diff --git a/src/exchangedb/pg_get_policy_details.c b/src/exchangedb/pg_get_policy_details.c @@ -1,60 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_policy_details.c - * @brief Implementation of the get_policy_details function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_policy_details.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_policy_details ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct GNUNET_HashCode *hc, - struct TALER_PolicyDetails *details) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (hc), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("deadline", - &details->deadline), - TALER_PQ_RESULT_SPEC_AMOUNT ("commitment", - &details->commitment), - TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total", - &details->accumulated_total), - TALER_PQ_RESULT_SPEC_AMOUNT ("policy_fee", - &details->policy_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("transferable_amount", - &details->transferable_amount), - GNUNET_PQ_result_spec_auto_from_type ("state", - &details->fulfillment_state), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ("policy_fulfillment_id", - &details->policy_fulfillment_id), - &details->no_policy_fulfillment_id), - GNUNET_PQ_result_spec_end - }; - - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_policy_details", - params, - rs); -} diff --git a/src/exchangedb/pg_get_purse_deposit.c b/src/exchangedb/pg_get_purse_deposit.c @@ -1,80 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_purse_deposit.c - * @brief Implementation of the get_purse_deposit function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_purse_deposit.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_purse_deposit ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_Amount *amount, - struct TALER_DenominationHashP *h_denom_pub, - struct TALER_AgeCommitmentHashP *phac, - struct TALER_CoinSpendSignatureP *coin_sig, - char **partner_url) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_end - }; - bool is_null; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - h_denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - phac), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - coin_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - amount), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("partner_base_url", - partner_url), - &is_null), - GNUNET_PQ_result_spec_end - }; - - *partner_url = NULL; - PREPARE (pg, - "select_purse_deposit_by_coin_pub", - "SELECT " - " coin_sig" - ",amount_with_fee" - ",denom_pub_hash" - ",age_commitment_hash" - ",partner_base_url" - " FROM purse_deposits" - " LEFT JOIN partners" - " USING (partner_serial_id)" - " JOIN known_coins kc" - " USING (coin_pub)" - " JOIN denominations" - " USING (denominations_serial)" - " WHERE purse_pub=$1" - " AND coin_pub=$2;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "select_purse_deposit_by_coin_pub", - params, - rs); -} diff --git a/src/exchangedb/pg_get_purse_request.c b/src/exchangedb/pg_get_purse_request.c @@ -1,75 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_template.c - * @brief Implementation of the template function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_purse_request.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_purse_request ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - struct TALER_PurseMergePublicKeyP *merge_pub, - struct GNUNET_TIME_Timestamp *purse_expiration, - struct TALER_PrivateContractHashP *h_contract_terms, - uint32_t *age_limit, - struct TALER_Amount *target_amount, - struct TALER_Amount *balance, - struct TALER_PurseContractSignatureP *purse_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("merge_pub", - merge_pub), - GNUNET_PQ_result_spec_timestamp ("purse_expiration", - purse_expiration), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - h_contract_terms), - GNUNET_PQ_result_spec_uint32 ("age_limit", - age_limit), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - target_amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("balance", - balance), - GNUNET_PQ_result_spec_auto_from_type ("purse_sig", - purse_sig), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "get_purse_request", - "SELECT " - " merge_pub" - ",purse_expiration" - ",h_contract_terms" - ",age_limit" - ",amount_with_fee" - ",balance" - ",purse_sig" - " FROM purse_requests" - " WHERE purse_pub=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_purse_request", - params, - rs); -} diff --git a/src/exchangedb/pg_get_ready_deposit.c b/src/exchangedb/pg_get_ready_deposit.c @@ -1,78 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2023 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/> - */ -/** - * @file exchangedb/pg_get_ready_deposit.c - * @brief Implementation of the get_ready_deposit function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_ready_deposit.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_ready_deposit (struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t start_shard_row, - uint64_t end_shard_row, - struct TALER_MerchantPublicKeyP * - merchant_pub, - struct TALER_FullPayto *payto_uri, - char **extra_wire_subject_metadata) -{ - struct GNUNET_TIME_Absolute now - = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_uint64 (&start_shard_row), - GNUNET_PQ_query_param_uint64 (&end_shard_row), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", - merchant_pub), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri->full_payto), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("extra_wire_subject_metadata", - extra_wire_subject_metadata), - NULL), - GNUNET_PQ_result_spec_end - }; - const char *query = "deposits_get_ready"; - - *extra_wire_subject_metadata = NULL; - PREPARE (pg, - query, - "SELECT" - " wts.payto_uri" - ",bdep.merchant_pub" - ",bdep.extra_wire_subject_metadata" - " FROM batch_deposits bdep" - " JOIN wire_targets wts" - " USING (wire_target_h_payto)" - " WHERE NOT (bdep.done OR bdep.policy_blocked)" - " AND bdep.wire_deadline<=$1" - " AND bdep.shard >= $2" - " AND bdep.shard <= $3" - " ORDER BY " - " bdep.wire_deadline ASC" - " ,bdep.shard ASC" - " LIMIT 1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - query, - params, - rs); -} diff --git a/src/exchangedb/pg_get_refresh.c b/src/exchangedb/pg_get_refresh.c @@ -1,205 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_refresh.c - * @brief Implementation of the get_refresh function for Postgres - * @author get_refresh - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_refresh.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_RefreshCommitmentP *rc, - struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh - ) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (rc), - GNUNET_PQ_query_param_end - }; - bool no_cs_r_values; - bool no_cs_r_choices; - bool no_transfer_pubs; - size_t num_denom_sigs; - size_t num_transfer_pubs; - struct TALER_BlindedDenominationSignature *denom_sigs = NULL; - struct GNUNET_CRYPTO_CSPublicRPairP *cs_r_values = NULL; - struct TALER_TransferPublicKeyP *transfer_pubs = NULL; - uint64_t *denom_serials = NULL; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &refresh->amount_with_fee), - GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", - &refresh->coin.coin_pub), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &refresh->coin.h_age_commitment), - &refresh->coin.no_age_commitment), - GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", - &refresh->coin_sig), - GNUNET_PQ_result_spec_auto_from_type ("refresh_seed", - &refresh->refresh_seed), - GNUNET_PQ_result_spec_uint32 ("noreveal_index", - &refresh->noreveal_index), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("blinding_seed", - &refresh->blinding_seed), - &refresh->no_blinding_seed), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_array_cs_r_pub (pg->conn, - "cs_r_values", - &refresh->num_cs_r_values, - &cs_r_values), - &no_cs_r_values), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ("cs_r_choices", - &refresh->cs_r_choices), - &no_cs_r_choices), - GNUNET_PQ_result_spec_auto_from_type ("planchets_h", - &refresh->planchets_h), - GNUNET_PQ_result_spec_auto_from_type ("selected_h", - &refresh->selected_h), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_array_fixed_size (pg->conn, - "transfer_pubs", - sizeof(*transfer_pubs), - &num_transfer_pubs, - (void **) &transfer_pubs), - &no_transfer_pubs), - GNUNET_PQ_result_spec_array_uint64 (pg->conn, - "denom_serials", - &refresh->num_coins, - &denom_serials), - TALER_PQ_result_spec_array_blinded_denom_sig (pg->conn, - "denom_sigs", - &num_denom_sigs, - &denom_sigs), - GNUNET_PQ_result_spec_bool ("revealed", - &refresh->revealed), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - memset (&refresh->coin.denom_sig, - 0, - sizeof (refresh->coin.denom_sig)); - PREPARE (pg, - "get_refresh", - "SELECT" - " amount_with_fee" - ",old_coin_pub" - ",kc.age_commitment_hash AS age_commitment_hash" - ",old_coin_sig" - ",refresh_seed" - ",noreveal_index" - ",blinding_seed" - ",cs_r_values" - ",cs_r_choices" - ",planchets_h" - ",transfer_pubs" - ",selected_h" - ",denom_serials" - ",denom_sigs" - ",revealed" - " FROM refresh" - " JOIN known_coins kc" - " ON (old_coin_pub = kc.coin_pub)" - " WHERE rc = $1;" - ); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_refresh", - params, - rs); - GNUNET_PQ_cleanup_query_params_closures (params); - if (0 > qs) - { - GNUNET_break (0); - GNUNET_PQ_cleanup_result (rs); - return qs; - } - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) - { - GNUNET_PQ_cleanup_result (rs); - return qs; - } - if (refresh->num_coins != num_denom_sigs) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "got inconsistent number of entries in refresh from DB: " - "num_coins=%ld, num_denom_sigs=%ld\n", - refresh->num_coins, - num_denom_sigs); - GNUNET_PQ_cleanup_result (rs); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if (no_transfer_pubs) - { - refresh->is_v27_refresh = true; - refresh->transfer_pubs = NULL; - } - else - { - if (num_transfer_pubs != refresh->num_coins) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "got inconsistent number of transfer_pubs in refresh from DB: " - "num_coins=%ld, num_transfer_pubs=%ld\n", - refresh->num_coins, - num_transfer_pubs); - GNUNET_PQ_cleanup_result (rs); - return GNUNET_DB_STATUS_HARD_ERROR; - } - refresh->is_v27_refresh = false; - refresh->transfer_pubs = transfer_pubs; - } - if (refresh->no_blinding_seed != no_cs_r_values) - { - GNUNET_break (0); - GNUNET_PQ_cleanup_result (rs); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if (no_cs_r_choices != no_cs_r_values) - { - GNUNET_break (0); - GNUNET_PQ_cleanup_result (rs); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if (no_cs_r_values) - { - refresh->cs_r_values = NULL; - refresh->num_cs_r_values = 0; - } - if (refresh->coin.no_age_commitment) - memset (&refresh->coin.h_age_commitment, - 0, - sizeof(refresh->coin.h_age_commitment)); - refresh->rc = *rc; - /* move the result arrays */ - refresh->denom_sigs = denom_sigs; - refresh->denom_serials = denom_serials; - refresh->cs_r_values = cs_r_values; - transfer_pubs = NULL; - denom_sigs = NULL; - denom_serials = NULL; - cs_r_values = NULL; - GNUNET_PQ_cleanup_result (rs); - return qs; -} diff --git a/src/exchangedb/pg_get_reserve_balance.c b/src/exchangedb/pg_get_reserve_balance.c @@ -1,65 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_reserve_balance.c - * @brief Implementation of the get_reserve_balance function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_reserve_balance.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_reserve_balance ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct TALER_Amount *balance, - struct TALER_FullPayto *origin_account) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_amount ("current_balance", - pg->currency, - balance), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("payto_uri", - &origin_account->full_payto), - NULL), - GNUNET_PQ_result_spec_end - }; - - origin_account->full_payto = NULL; - PREPARE (pg, - "get_reserve_balance", - "SELECT" - " r.current_balance" - " ,wt.payto_uri" - " FROM reserves r" - " LEFT JOIN reserves_in ri" - " USING (reserve_pub)" - " LEFT JOIN wire_targets wt" - " ON (wt.wire_target_h_payto = ri.wire_source_h_payto)" - " WHERE r.reserve_pub=$1" - " LIMIT 1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_reserve_balance", - params, - rs); -} diff --git a/src/exchangedb/pg_get_reserve_by_h_planchets.c b/src/exchangedb/pg_get_reserve_by_h_planchets.c @@ -1,58 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022,2025 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/> - */ -/** - * @file exchangedb/pg_get_reserve_by_h_planchets.c - * @brief Implementation of the get_reserve_by_h_planchets function for Postgres - * @author Christian Grothoff - * @author Özgür Kesim - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_reserve_by_h_planchets.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_reserve_by_h_planchets ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_HashBlindedPlanchetsP *h_planchets, - struct TALER_ReservePublicKeyP *reserve_pub, - uint64_t *withdraw_serial_id) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_planchets), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - reserve_pub), - GNUNET_PQ_result_spec_uint64 ("withdraw_id", - withdraw_serial_id), - GNUNET_PQ_result_spec_end - }; - /* Used in #postgres_get_reserve_by_h_planchets() */ - PREPARE (pg, - "reserve_by_h_planchets", - "SELECT" - " reserve_pub" - ",withdraw_id" - " FROM withdraw" - " WHERE planchets_h=$1" - " LIMIT 1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "reserve_by_h_planchets", - params, - rs); -} diff --git a/src/exchangedb/pg_get_reserve_history.c b/src/exchangedb/pg_get_reserve_history.c @@ -1,994 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2023 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/> - */ -/** - * @file pg_get_reserve_history.c - * @brief Obtain (parts of) the history of a reserve. - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_reserve_history.h" -#include "taler/exchange-database/start_read_committed.h" -#include "taler/exchange-database/commit.h" -#include "taler/exchange-database/rollback.h" -#include "helper.h" - -/** - * How often do we re-try when encountering DB serialization issues? - * (We are read-only, so can only happen due to concurrent insert, - * which should be very rare.) - */ -#define RETRIES 3 - - -/** - * Closure for callbacks invoked via #TALER_EXCHANGEDB_get_reserve_history(). - */ -struct ReserveHistoryContext -{ - - /** - * Which reserve are we building the history for? - */ - const struct TALER_ReservePublicKeyP *reserve_pub; - - /** - * Where we build the history. - */ - struct TALER_EXCHANGEDB_ReserveHistory *rh; - - /** - * Tail of @e rh list. - */ - struct TALER_EXCHANGEDB_ReserveHistory *rh_tail; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Sum of all credit transactions. - */ - struct TALER_Amount balance_in; - - /** - * Sum of all debit transactions. - */ - struct TALER_Amount balance_out; - - /** - * Current reserve_history_serial_id being processed, - * set before each sub-table callback. - */ - uint64_t current_history_offset; - - /** - * Set to true on serious internal errors during - * the callbacks. - */ - bool failed; -}; - - -/** - * Append and return a fresh element to the reserve - * history kept in @a rhc. - * - * @param rhc where the history is kept - * @return the fresh element that was added - */ -static struct TALER_EXCHANGEDB_ReserveHistory * -append_rh (struct ReserveHistoryContext *rhc) -{ - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - tail = GNUNET_new (struct TALER_EXCHANGEDB_ReserveHistory); - tail->history_offset = rhc->current_history_offset; - if (NULL != rhc->rh_tail) - { - rhc->rh_tail->next = tail; - rhc->rh_tail = tail; - } - else - { - rhc->rh_tail = tail; - rhc->rh = tail; - } - return tail; -} - - -/** - * Add bank transfers to result set for #TALER_EXCHANGEDB_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_bank_to_exchange (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_BankTransfer *bt; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - bt = GNUNET_new (struct TALER_EXCHANGEDB_BankTransfer); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("wire_reference", - &bt->wire_reference), - TALER_PQ_RESULT_SPEC_AMOUNT ("credit", - &bt->amount), - GNUNET_PQ_result_spec_timestamp ("execution_date", - &bt->execution_date), - GNUNET_PQ_result_spec_string ("sender_account_details", - &bt->sender_account_details.full_payto), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (bt); - rhc->failed = true; - return; - } - } - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_in, - &rhc->balance_in, - &bt->amount)); - bt->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE; - tail->details.bank = bt; - } /* end of 'while (0 < rows)' */ -} - - -/** - * Add coin withdrawals to result set for #TALER_EXCHANGEDB_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_withdraw (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_Withdraw *wd; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - wd = GNUNET_new (struct TALER_EXCHANGEDB_Withdraw); - { - bool no_noreveal_index; - bool no_max_age; - bool no_selected_h; - size_t num_denom_hs; - size_t num_denom_serials; - uint64_t *my_denom_serials = NULL; - struct TALER_DenominationHashP *my_denom_pub_hashes = NULL; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("planchets_h", - &wd->planchets_h), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &wd->reserve_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &wd->amount_with_fee), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint16 ("max_age", - &wd->max_age), - &no_max_age), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint16 ("noreveal_index", - &wd->noreveal_index), - &no_noreveal_index), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("blinding_seed", - &wd->blinding_seed), - &wd->no_blinding_seed), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("selected_h", - &wd->selected_h), - &no_selected_h), - TALER_PQ_result_spec_array_denom_hash (pg->conn, - "denom_pub_hashes", - &num_denom_hs, - &my_denom_pub_hashes), - GNUNET_PQ_result_spec_array_uint64 (pg->conn, - "denom_serials", - &num_denom_serials, - &my_denom_serials), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (wd); - rhc->failed = true; - GNUNET_PQ_cleanup_result (rs); - return; - } - - if (num_denom_hs != num_denom_serials) - { - GNUNET_break (0); - GNUNET_free (wd); - rhc->failed = true; - GNUNET_PQ_cleanup_result (rs); - return; - } - - if ((no_noreveal_index != no_max_age) || - (no_noreveal_index != no_selected_h)) - { - GNUNET_break (0); - GNUNET_free (wd); - rhc->failed = true; - GNUNET_PQ_cleanup_result (rs); - return; - } - wd->age_proof_required = ! no_max_age; - wd->num_coins = num_denom_serials; - wd->reserve_pub = *rhc->reserve_pub; - wd->denom_serials = my_denom_serials; - wd->denom_pub_hashes = my_denom_pub_hashes; - /* prevent cleanup from destroying our actual result */ - my_denom_serials = NULL; - my_denom_pub_hashes = NULL; - GNUNET_PQ_cleanup_result (rs); - } - - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_WITHDRAW_COINS; - tail->details.withdraw = wd; - } -} - - -/** - * Add recoups to result set for #TALER_EXCHANGEDB_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_recoup (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_Recoup *recoup; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - recoup = GNUNET_new (struct TALER_EXCHANGEDB_Recoup); - { - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &recoup->value), - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &recoup->coin.coin_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_blind", - &recoup->coin_blind), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &recoup->coin_sig), - GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", - &recoup->timestamp), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &recoup->coin.denom_pub_hash), - TALER_PQ_result_spec_denom_sig ( - "denom_sig", - &recoup->coin.denom_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (recoup); - rhc->failed = true; - return; - } - } - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_in, - &rhc->balance_in, - &recoup->value)); - recoup->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_RECOUP_COIN; - tail->details.recoup = recoup; - } /* end of 'while (0 < rows)' */ -} - - -/** - * Add exchange-to-bank transfers to result set for - * #TALER_EXCHANGEDB_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_exchange_to_bank (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_ClosingTransfer *closing; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - closing = GNUNET_new (struct TALER_EXCHANGEDB_ClosingTransfer); - { - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &closing->amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", - &closing->closing_fee), - GNUNET_PQ_result_spec_timestamp ("execution_date", - &closing->execution_date), - GNUNET_PQ_result_spec_string ("receiver_account", - &closing->receiver_account_details. - full_payto), - GNUNET_PQ_result_spec_auto_from_type ("wtid", - &closing->wtid), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (closing); - rhc->failed = true; - return; - } - } - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_out, - &rhc->balance_out, - &closing->amount)); - closing->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK; - tail->details.closing = closing; - } /* end of 'while (0 < rows)' */ -} - - -/** - * Add purse merge transfers to result set for - * #TALER_EXCHANGEDB_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_p2p_merge (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_PurseMerge *merge; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - merge = GNUNET_new (struct TALER_EXCHANGEDB_PurseMerge); - { - uint32_t flags32; - struct TALER_Amount balance; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", - &merge->purse_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("balance", - &balance), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &merge->amount_with_fee), - GNUNET_PQ_result_spec_timestamp ("merge_timestamp", - &merge->merge_timestamp), - GNUNET_PQ_result_spec_timestamp ("purse_expiration", - &merge->purse_expiration), - GNUNET_PQ_result_spec_uint32 ("age_limit", - &merge->min_age), - GNUNET_PQ_result_spec_uint32 ("flags", - &flags32), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - &merge->h_contract_terms), - GNUNET_PQ_result_spec_auto_from_type ("merge_pub", - &merge->merge_pub), - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - &merge->purse_pub), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &merge->reserve_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (merge); - rhc->failed = true; - return; - } - merge->flags = (enum TALER_WalletAccountMergeFlags) flags32; - if ( (! GNUNET_TIME_absolute_is_future ( - merge->merge_timestamp.abs_time)) && - (-1 != TALER_amount_cmp (&balance, - &merge->amount_with_fee)) ) - merge->merged = true; - } - if (merge->merged) - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_in, - &rhc->balance_in, - &merge->amount_with_fee)); - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_out, - &rhc->balance_out, - &merge->purse_fee)); - merge->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_PURSE_MERGE; - tail->details.merge = merge; - } -} - - -/** - * Add paid for history requests to result set for - * #TALER_EXCHANGEDB_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_open_requests (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_OpenRequest *orq; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - orq = GNUNET_new (struct TALER_EXCHANGEDB_OpenRequest); - { - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("open_fee", - &orq->open_fee), - GNUNET_PQ_result_spec_timestamp ("request_timestamp", - &orq->request_timestamp), - GNUNET_PQ_result_spec_timestamp ("expiration_date", - &orq->reserve_expiration), - GNUNET_PQ_result_spec_uint32 ("requested_purse_limit", - &orq->purse_limit), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &orq->reserve_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (orq); - rhc->failed = true; - return; - } - } - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_out, - &rhc->balance_out, - &orq->open_fee)); - orq->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_OPEN_REQUEST; - tail->details.open_request = orq; - } -} - - -/** - * Add paid for history requests to result set for - * #TALER_EXCHANGEDB_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_close_requests (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_CloseRequest *crq; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - crq = GNUNET_new (struct TALER_EXCHANGEDB_CloseRequest); - { - struct TALER_FullPayto payto_uri; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("close_timestamp", - &crq->request_timestamp), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri.full_payto), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &crq->reserve_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (crq); - rhc->failed = true; - return; - } - TALER_full_payto_hash (payto_uri, - &crq->target_account_h_payto); - GNUNET_free (payto_uri.full_payto); - } - crq->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_CLOSE_REQUEST; - tail->details.close_request = crq; - } -} - - -/** - * Add reserve history entries found. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -handle_history_entry (void *cls, - PGresult *result, - unsigned int num_results) -{ - static const struct - { - /** - * Table with reserve history entry we are responsible for. - */ - const char *table; - /** - * Name of the prepared statement to run. - */ - const char *statement; - /** - * Function to use to process the results. - */ - GNUNET_PQ_PostgresResultHandler cb; - } work[] = { - /** #TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE */ - { "reserves_in", - "reserves_in_get_transactions", - add_bank_to_exchange }, - /** #TALER_EXCHANGEDB_RO_WITHDRAW_COINS */ - { "withdraw", - "get_withdraw_details", - &add_withdraw }, - /** #TALER_EXCHANGEDB_RO_RECOUP_COIN */ - { "recoup", - "recoup_by_reserve", - &add_recoup }, - /** #TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK */ - { "reserves_close", - "close_by_reserve", - &add_exchange_to_bank }, - /** #TALER_EXCHANGEDB_RO_PURSE_MERGE */ - { "purse_decision", - "merge_by_reserve", - &add_p2p_merge }, - /** #TALER_EXCHANGEDB_RO_OPEN_REQUEST */ - { "reserves_open_requests", - "open_request_by_reserve", - &add_open_requests }, - /** #TALER_EXCHANGEDB_RO_CLOSE_REQUEST */ - { "close_requests", - "close_request_by_reserve", - &add_close_requests }, - /* List terminator */ - { NULL, NULL, NULL } - }; - struct ReserveHistoryContext *rhc = cls; - char *table_name; - uint64_t serial_id; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("table_name", - &table_name), - GNUNET_PQ_result_spec_uint64 ("serial_id", - &serial_id), - GNUNET_PQ_result_spec_uint64 ("reserve_history_serial_id", - &rhc->current_history_offset), - GNUNET_PQ_result_spec_end - }; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (rhc->reserve_pub), - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - - while (0 < num_results--) - { - enum GNUNET_DB_QueryStatus qs; - bool found = false; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - num_results)) - { - GNUNET_break (0); - rhc->failed = true; - return; - } - - for (unsigned int i = 0; - NULL != work[i].cb; - i++) - { - if (0 != strcmp (table_name, - work[i].table)) - continue; - found = true; - qs = GNUNET_PQ_eval_prepared_multi_select (rhc->pg->conn, - work[i].statement, - params, - work[i].cb, - rhc); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Reserve %s had %d transactions at %llu in table %s\n", - TALER_B2S (rhc->reserve_pub), - (int) qs, - (unsigned long long) serial_id, - table_name); - if (0 >= qs) - rhc->failed = true; - break; - } - if (! found) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Reserve history includes unsupported table `%s`\n", - table_name); - rhc->failed = true; - } - GNUNET_PQ_cleanup_result (rs); - if (rhc->failed) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_reserve_history ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ReservePublicKeyP *reserve_pub, - uint64_t start_off, - uint64_t etag_in, - uint64_t *etag_out, - struct TALER_Amount *balance, - struct TALER_EXCHANGEDB_ReserveHistory **rhp) -{ - struct ReserveHistoryContext rhc = { - .pg = pg, - .reserve_pub = reserve_pub - }; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_QueryParam lparams[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_uint64 (&start_off), - GNUNET_PQ_query_param_end - }; - - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pg->currency, - &rhc.balance_in)); - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pg->currency, - &rhc.balance_out)); - - *rhp = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Getting transactions for reserve %s\n", - TALER_B2S (reserve_pub)); - PREPARE (pg, - "get_reserve_history_etag", - "SELECT" - " his.reserve_history_serial_id" - ",r.current_balance" - " FROM reserve_history his" - " JOIN reserves r USING (reserve_pub)" - " WHERE his.reserve_pub=$1" - " ORDER BY reserve_history_serial_id DESC" - " LIMIT 1;"); - PREPARE (pg, - "get_reserve_history", - "SELECT" - " table_name" - ",serial_id" - ",reserve_history_serial_id" - " FROM reserve_history" - " WHERE reserve_pub=$1" - " AND reserve_history_serial_id > $2" - " ORDER BY reserve_history_serial_id DESC;"); - PREPARE (pg, - "reserves_in_get_transactions", - "SELECT" - " ri.wire_reference" - ",ri.credit" - ",ri.execution_date" - ",wt.payto_uri AS sender_account_details" - " FROM reserves_in ri" - " JOIN wire_targets wt" - " ON (wire_source_h_payto = wire_target_h_payto)" - " WHERE ri.reserve_pub=$1" - " AND ri.reserve_in_serial_id=$2;"); - PREPARE (pg, - "get_withdraw_details", - "SELECT" - " planchets_h" - ",amount_with_fee" - ",reserve_sig" - ",max_age" - ",noreveal_index" - ",selected_h" - ",blinding_seed" - ",denom_serials" - ",ARRAY(" - " SELECT denominations.denom_pub_hash FROM (" - " SELECT UNNEST(denom_serials) AS id," - " generate_subscripts(denom_serials, 1) AS nr" /* for order */ - " ) AS denoms" - " LEFT JOIN denominations ON denominations.denominations_serial=denoms.id" - ") AS denom_pub_hashes" - " FROM withdraw " - " WHERE withdraw_id=$2" - " AND reserve_pub=$1;"); - PREPARE (pg, - "recoup_by_reserve", - "SELECT" - " rec.coin_pub" - ",rec.coin_sig" - ",rec.coin_blind" - ",rec.amount" - ",rec.recoup_timestamp" - ",denom.denom_pub_hash" - ",kc.denom_sig" - " FROM recoup rec" - " JOIN withdraw ro" - " USING (withdraw_id)" - " JOIN reserves res" - " USING (reserve_pub)" - " JOIN known_coins kc" - " USING (coin_pub)" - " JOIN denominations denom" - " ON (denom.denominations_serial = kc.denominations_serial)" - " WHERE rec.recoup_uuid=$2" - " AND res.reserve_pub=$1;"); - PREPARE (pg, - "close_by_reserve", - "SELECT" - " rc.amount" - ",rc.closing_fee" - ",rc.execution_date" - ",wt.payto_uri AS receiver_account" - ",rc.wtid" - " FROM reserves_close rc" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " WHERE reserve_pub=$1" - " AND close_uuid=$2;"); - PREPARE (pg, - "merge_by_reserve", - "SELECT" - " pr.amount_with_fee" - ",pr.balance" - ",pr.purse_fee" - ",pr.h_contract_terms" - ",pr.merge_pub" - ",am.reserve_sig" - ",pm.purse_pub" - ",pm.merge_timestamp" - ",pr.purse_expiration" - ",pr.age_limit" - ",pr.flags" - " FROM purse_decision pdes" - " JOIN purse_requests pr" - " ON (pr.purse_pub = pdes.purse_pub)" - " JOIN purse_merges pm" - " ON (pm.purse_pub = pdes.purse_pub)" - " JOIN account_merges am" - " ON (am.purse_pub = pm.purse_pub AND" - " am.reserve_pub = pm.reserve_pub)" - " WHERE pdes.purse_decision_serial_id=$2" - " AND pm.reserve_pub=$1" - " AND COALESCE(pm.partner_serial_id,0)=0" /* must be local! */ - " AND NOT pdes.refunded;"); - PREPARE (pg, - "open_request_by_reserve", - "SELECT" - " reserve_payment" - ",request_timestamp" - ",expiration_date" - ",requested_purse_limit" - ",reserve_sig" - " FROM reserves_open_requests" - " WHERE reserve_pub=$1" - " AND open_request_uuid=$2;"); - PREPARE (pg, - "close_request_by_reserve", - "SELECT" - " close_timestamp" - ",payto_uri" - ",reserve_sig" - " FROM close_requests" - " WHERE reserve_pub=$1" - " AND close_request_serial_id=$2;"); - - for (unsigned int i = 0; i<RETRIES; i++) - { - enum GNUNET_DB_QueryStatus qs; - uint64_t end; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("reserve_history_serial_id", - &end), - TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance", - balance), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - TALER_TALER_EXCHANGEDB_start_read_committed (pg, - "get-reserve-transactions") - ) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - /* First only check the last item, to see if - we even need to iterate */ - qs = GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "get_reserve_history_etag", - params, - rs); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TALER_EXCHANGEDB_rollback (pg); - continue; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - *etag_out = end; - if (end == etag_in) - return qs; - } - /* We indeed need to iterate over the history */ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Current ETag for reserve %s is %llu\n", - TALER_B2S (reserve_pub), - (unsigned long long) end); - - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "get_reserve_history", - lparams, - &handle_history_entry, - &rhc); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - TALER_EXCHANGEDB_rollback (pg); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TALER_EXCHANGEDB_rollback (pg); - continue; - default: - break; - } - if (rhc.failed) - { - TALER_EXCHANGEDB_rollback (pg); - TALER_EXCHANGEDB_free_reserve_history (rhc.rh); - return GNUNET_DB_STATUS_SOFT_ERROR; - } - qs = TALER_EXCHANGEDB_commit (pg); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - TALER_EXCHANGEDB_free_reserve_history (rhc.rh); - return qs; - case GNUNET_DB_STATUS_SOFT_ERROR: - TALER_EXCHANGEDB_free_reserve_history (rhc.rh); - rhc.rh = NULL; - continue; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - *rhp = rhc.rh; - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } - } - return GNUNET_DB_STATUS_SOFT_ERROR; -} diff --git a/src/exchangedb/pg_get_signature_for_known_coin.c b/src/exchangedb/pg_get_signature_for_known_coin.c @@ -1,59 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023 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/> - */ -/** - * @file exchangedb/pg_get_signature_for_known_coin.c - * @brief Implementation of the get_signature_for_known_coin function for Postgres - * @author Özgür Kesim - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_signature_for_known_coin.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_signature_for_known_coin ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_DenominationPublicKey *denom_pub, - struct TALER_DenominationSignature *denom_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_denom_pub ("denom_pub", - denom_pub), - TALER_PQ_result_spec_denom_sig ("denom_sig", - denom_sig), - GNUNET_PQ_result_spec_end - }; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Getting denomination and signature for (potentially) known coin %s\n", - TALER_B2S (coin_pub)); - PREPARE (pg, - "get_signature_for_known_coin", - "SELECT" - " denominations.denom_pub" - ",denom_sig" - " FROM known_coins" - " JOIN denominations USING (denominations_serial)" - " WHERE coin_pub=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_signature_for_known_coin", - params, - rs); -} diff --git a/src/exchangedb/pg_get_unfinished_close_requests.c b/src/exchangedb/pg_get_unfinished_close_requests.c @@ -1,162 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file pg_get_unfinished_close_requests.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_unfinished_close_requests.h" -#include "helper.h" - - -/** - * Closure for #reserve_close_cb(). - */ -struct CloseReserveContext -{ - /** - * Function to call for each to be closed reserve. - */ - TALER_EXCHANGEDB_ReserveExpiredCallback rec; - - /** - * Closure to give to @e rec. - */ - void *rec_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on error. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -reserve_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CloseReserveContext *erc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = erc->pg; - enum GNUNET_GenericReturnValue ret = GNUNET_OK; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_TIME_Timestamp exp_date; - struct TALER_FullPayto account_details; - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_Amount remaining_balance; - uint64_t close_request_row; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("expiration_date", - &exp_date), - GNUNET_PQ_result_spec_string ("account_details", - &account_details.full_payto), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - TALER_PQ_RESULT_SPEC_AMOUNT ("close", - &remaining_balance), - GNUNET_PQ_result_spec_uint64 ("close_request_serial_id", - &close_request_row), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ret = GNUNET_SYSERR; - break; - } - ret = erc->rec (erc->rec_cls, - &reserve_pub, - &remaining_balance, - account_details, - exp_date, - close_request_row); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } - erc->status = ret; -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_unfinished_close_requests ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - TALER_EXCHANGEDB_ReserveExpiredCallback rec, - void *rec_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - struct CloseReserveContext ectx = { - .rec = rec, - .rec_cls = rec_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "get_unfinished_close_requests", - "UPDATE close_requests AS rc" - " SET done=TRUE" - " WHERE NOT done" - " RETURNING" - " reserve_pub" - " ,close_request_serial_id" - " ,close_timestamp AS expiration_date" - " ,close" - " ,(SELECT payto_uri" - " FROM reserves_in ri" - " JOIN wire_targets wt" - " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)" - " WHERE ri.reserve_pub=rc.reserve_pub)" - " AS account_details;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "get_unfinished_close_requests", - params, - &reserve_cb, - &ectx); - switch (ectx.status) - { - case GNUNET_SYSERR: - return GNUNET_DB_STATUS_HARD_ERROR; - case GNUNET_NO: - return GNUNET_DB_STATUS_SOFT_ERROR; - case GNUNET_OK: - break; - } - return qs; -} diff --git a/src/exchangedb/pg_get_wire_accounts.c b/src/exchangedb/pg_get_wire_accounts.c @@ -1,179 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_get_wire_accounts.c - * @brief Implementation of the get_wire_accounts function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_wire_accounts.h" -#include "helper.h" - - -/** - * Closure for #get_wire_accounts_cb(). - */ -struct GetWireAccountsContext -{ - /** - * Function to call per result. - */ - TALER_EXCHANGEDB_WireAccountCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Flag set to #GNUNET_OK as long as everything is fine. - */ - enum GNUNET_GenericReturnValue status; - -}; - - -/** - * Invoke the callback for each result. - * - * @param cls a `struct MissingWireContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -get_wire_accounts_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct GetWireAccountsContext *ctx = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - struct TALER_FullPayto payto_uri; - char *conversion_url = NULL; - char *open_banking_gateway = NULL; - char *wire_transfer_gateway = NULL; - json_t *debit_restrictions = NULL; - json_t *credit_restrictions = NULL; - struct TALER_MasterSignatureP master_sig; - char *bank_label = NULL; - int64_t priority; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri.full_payto), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("conversion_url", - &conversion_url), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("open_banking_gateway", - &open_banking_gateway), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("wire_transfer_gateway", - &wire_transfer_gateway), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("bank_label", - &bank_label), - NULL), - GNUNET_PQ_result_spec_int64 ("priority", - &priority), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ("debit_restrictions", - &debit_restrictions), - NULL), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ("credit_restrictions", - &credit_restrictions), - NULL), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &master_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - if (NULL == debit_restrictions) - { - debit_restrictions = json_array (); - GNUNET_assert (NULL != debit_restrictions); - } - if (NULL == credit_restrictions) - { - credit_restrictions = json_array (); - GNUNET_assert (NULL != credit_restrictions); - } - ctx->cb (ctx->cb_cls, - payto_uri, - conversion_url, - open_banking_gateway, - wire_transfer_gateway, - debit_restrictions, - credit_restrictions, - &master_sig, - bank_label, - priority); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_wire_accounts (struct TALER_EXCHANGEDB_PostgresContext *pg, - TALER_EXCHANGEDB_WireAccountCallback cb, - void *cb_cls) -{ - struct GetWireAccountsContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .status = GNUNET_OK - }; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "get_wire_accounts", - "SELECT" - " payto_uri" - ",conversion_url" - ",open_banking_gateway" - ",wire_transfer_gateway" - ",debit_restrictions::TEXT" - ",credit_restrictions::TEXT" - ",master_sig" - ",bank_label" - ",priority" - " FROM wire_accounts" - " WHERE is_active"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "get_wire_accounts", - params, - &get_wire_accounts_cb, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_get_wire_fee.c b/src/exchangedb/pg_get_wire_fee.c @@ -1,74 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_wire_fee.c - * @brief Implementation of the get_wire_fee function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_wire_fee.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_wire_fee ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *type, - struct GNUNET_TIME_Timestamp date, - uint64_t *rowid, - struct GNUNET_TIME_Timestamp *start_date, - struct GNUNET_TIME_Timestamp *end_date, - struct TALER_WireFeeSet *fees, - struct TALER_MasterSignatureP *master_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (type), - GNUNET_PQ_query_param_timestamp (&date), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("wire_fee_serial", - rowid), - GNUNET_PQ_result_spec_timestamp ("start_date", - start_date), - GNUNET_PQ_result_spec_timestamp ("end_date", - end_date), - TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", - &fees->wire), - TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", - &fees->closing), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - master_sig), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "get_wire_fee", - "SELECT" - " wire_fee_serial" - ",start_date" - ",end_date" - ",wire_fee" - ",closing_fee" - ",master_sig" - " FROM wire_fee" - " WHERE wire_method=$1" - " AND start_date <= $2" - " AND end_date > $2;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_wire_fee", - params, - rs); -} diff --git a/src/exchangedb/pg_get_wire_fees.c b/src/exchangedb/pg_get_wire_fees.c @@ -1,144 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_get_wire_fees.c - * @brief Implementation of the get_wire_fees function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_wire_fees.h" -#include "helper.h" - -/** - * Closure for #get_wire_fees_cb(). - */ -struct GetWireFeesContext -{ - /** - * Function to call per result. - */ - TALER_EXCHANGEDB_WireFeeCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Flag set to #GNUNET_OK as long as everything is fine. - */ - enum GNUNET_GenericReturnValue status; - -}; - - -/** - * Invoke the callback for each result. - * - * @param cls a `struct GetWireFeesContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -get_wire_fees_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct GetWireFeesContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - - for (unsigned int i = 0; i < num_results; i++) - { - struct TALER_MasterSignatureP master_sig; - struct TALER_WireFeeSet fees; - struct GNUNET_TIME_Timestamp start_date; - struct GNUNET_TIME_Timestamp end_date; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", - &fees.wire), - TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", - &fees.closing), - GNUNET_PQ_result_spec_timestamp ("start_date", - &start_date), - GNUNET_PQ_result_spec_timestamp ("end_date", - &end_date), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &master_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ctx->cb (ctx->cb_cls, - &fees, - start_date, - end_date, - &master_sig); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_get_wire_fees (struct TALER_EXCHANGEDB_PostgresContext * - pg, - const char *wire_method, - TALER_EXCHANGEDB_WireFeeCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (wire_method), - GNUNET_PQ_query_param_end - }; - struct GetWireFeesContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "get_wire_fees", - "SELECT" - " wire_fee" - ",closing_fee" - ",start_date" - ",end_date" - ",master_sig" - " FROM wire_fee" - " WHERE wire_method=$1"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "get_wire_fees", - params, - &get_wire_fees_cb, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_get_wire_hash_for_contract.c b/src/exchangedb/pg_get_wire_hash_for_contract.c @@ -1,77 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023, 2024 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/> - */ -/** - * @file exchangedb/pg_get_wire_hash_for_contract.c - * @brief Implementation of the get_wire_hash_for_contract function for Postgres - * @author Özgür Kesim - */ -#include "taler/taler_exchangedb_lib.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_wire_hash_for_contract.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_wire_hash_for_contract ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_PrivateContractHashP *h_contract_terms, - struct TALER_MerchantWireHashP *h_wire) -{ - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_end - }; - struct TALER_FullPayto payto_uri; - struct TALER_WireSaltP wire_salt; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("wire_salt", - &wire_salt), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri.full_payto), - GNUNET_PQ_result_spec_end - }; - - /* check if the necessary records exist and get them */ - PREPARE (pg, - "get_wire_hash_for_contract", - "SELECT" - " bdep.wire_salt" - " ,wt.payto_uri" - " FROM coin_deposits" - " JOIN batch_deposits bdep" - " USING (batch_deposit_serial_id)" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " WHERE bdep.merchant_pub=$1" - " AND bdep.h_contract_terms=$2"); - /* NOTE: above query might be more efficient if we computed the shard - from the merchant_pub and included that in the query */ - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_wire_hash_for_contract", - params, - rs); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) - { - TALER_merchant_wire_signature_hash (payto_uri, - &wire_salt, - h_wire); - GNUNET_PQ_cleanup_result (rs); - } - return qs; -} diff --git a/src/exchangedb/pg_get_withdraw.c b/src/exchangedb/pg_get_withdraw.c @@ -1,191 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023, 2025 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/> - */ -/** - * @file exchangedb/pg_get_withdraw.c - * @brief Implementation of the get_withdraw function for Postgres - * @author Özgür Kesim - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/get_withdraw.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_withdraw ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_HashBlindedPlanchetsP *wch, - struct TALER_EXCHANGEDB_Withdraw *wd) -{ - enum GNUNET_DB_QueryStatus ret; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (wch), - GNUNET_PQ_query_param_end - }; - struct TALER_BlindedDenominationSignature *my_denom_sigs = NULL; - uint64_t *my_denom_serials = NULL; - struct GNUNET_CRYPTO_CSPublicRPairP *my_cs_r_values = NULL; - size_t num_sigs = 0; - size_t num_coins = 0; - size_t num_cs_r_values = 0; - bool no_noreveal_index; - bool no_max_age; - bool no_selected_h; - bool no_blinding_seed; - bool no_cs_r_values; - bool no_cs_r_choices; - - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("planchets_h", - &wd->planchets_h), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &wd->reserve_sig), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &wd->reserve_pub), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint16 ("max_age", - &wd->max_age), - &no_max_age), - TALER_PQ_result_spec_amount ("amount_with_fee", - pg->currency, - &wd->amount_with_fee), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint16 ("noreveal_index", - &wd->noreveal_index), - &no_noreveal_index), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("selected_h", - &wd->selected_h), - &no_selected_h), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("blinding_seed", - &wd->blinding_seed), - &no_blinding_seed), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_array_cs_r_pub ( - pg->conn, - "cs_r_values", - &num_cs_r_values, - &my_cs_r_values), - &no_cs_r_values), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ("cs_r_choices", - &wd->cs_r_choices), - &no_cs_r_choices), - TALER_PQ_result_spec_array_blinded_denom_sig ( - pg->conn, - "denom_sigs", - &num_sigs, - &my_denom_sigs), - GNUNET_PQ_result_spec_array_uint64 ( - pg->conn, - "denom_serials", - &num_coins, - &my_denom_serials), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "get_withdraw", - "SELECT" - " planchets_h" - ",blinding_seed" - ",reserve_sig" - ",reserve_pub" - ",max_age" - ",amount_with_fee" - ",noreveal_index" - ",selected_h" - ",blinding_seed" - ",cs_r_values" - ",cs_r_choices" - ",denom_sigs" - ",denom_serials" - " FROM withdraw" - " WHERE planchets_h=$1;"); - ret = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_withdraw", - params, - rs); - if (0 > ret) - { - GNUNET_break (0); - GNUNET_PQ_cleanup_result (rs); - return ret; - } - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == ret) - { - GNUNET_PQ_cleanup_result (rs); - return ret; - } - - if ((no_max_age != no_noreveal_index) || - (no_max_age != no_selected_h)) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "got inconsistent state for max_age, noreveal_index and planchets_h in DB: " - "no_max_age=%s, no_noreveal_index=%s, no_selected_h=%s\n", - no_max_age ? "true" : "false", - no_noreveal_index ? "true" : "false", - no_selected_h ? "true" : "false"); - GNUNET_PQ_cleanup_result (rs); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if (no_blinding_seed != no_cs_r_values) - { - GNUNET_break (0); - GNUNET_PQ_cleanup_result (rs); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if (no_cs_r_choices != no_cs_r_values) - { - GNUNET_break (0); - GNUNET_PQ_cleanup_result (rs); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if (num_coins != num_sigs) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "got inconsistent number of entries in withdraw from DB: " - "num_coins=%ld, num_sigs=%ld\n", - num_coins, - num_sigs); - GNUNET_PQ_cleanup_result (rs); - return GNUNET_DB_STATUS_HARD_ERROR; - } - wd->age_proof_required = ! no_max_age; - if (no_cs_r_values) - { - wd->cs_r_values = NULL; - wd->num_cs_r_values = 0; - wd->cs_r_choices = 0; - } - wd->denom_sigs = my_denom_sigs; - wd->num_coins = num_coins; - wd->denom_serials = my_denom_serials; - wd->cs_r_values = my_cs_r_values; - wd->num_cs_r_values = num_cs_r_values; - /* ensure cleanup_result does not trash data we care about */ - my_denom_sigs = NULL; - my_denom_serials = NULL; - my_cs_r_values = NULL; - num_sigs = 0; - num_coins = 0; - num_cs_r_values = 0; - GNUNET_PQ_cleanup_result (rs); - return ret; -} diff --git a/src/exchangedb/pg_have_deposit2.c b/src/exchangedb/pg_have_deposit2.c @@ -1,113 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_have_deposit2.c - * @brief Implementation of the have_deposit2 function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/have_deposit2.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_have_deposit2 ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PrivateContractHashP *h_contract_terms, - const struct TALER_MerchantWireHashP *h_wire, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_MerchantPublicKeyP *merchant, - struct GNUNET_TIME_Timestamp refund_deadline, - struct TALER_Amount *deposit_fee, - struct GNUNET_TIME_Timestamp *exchange_timestamp) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (merchant), - GNUNET_PQ_query_param_end - }; - struct TALER_EXCHANGEDB_Deposit deposit2; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &deposit2.amount_with_fee), - GNUNET_PQ_result_spec_timestamp ("wallet_timestamp", - &deposit2.timestamp), - GNUNET_PQ_result_spec_timestamp ("exchange_timestamp", - exchange_timestamp), - GNUNET_PQ_result_spec_timestamp ("refund_deadline", - &deposit2.refund_deadline), - GNUNET_PQ_result_spec_timestamp ("wire_deadline", - &deposit2.wire_deadline), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - deposit_fee), - GNUNET_PQ_result_spec_auto_from_type ("wire_salt", - &deposit2.wire_salt), - GNUNET_PQ_result_spec_string ("receiver_wire_account", - &deposit2.receiver_wire_account.full_payto), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - struct TALER_MerchantWireHashP h_wire2; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Getting deposits for coin %s\n", - TALER_B2S (coin_pub)); - PREPARE (pg, - "get_deposit", - "SELECT" - " cdep.amount_with_fee" - ",denominations.fee_deposit" - ",bdep.wallet_timestamp" - ",bdep.exchange_timestamp" - ",bdep.refund_deadline" - ",bdep.wire_deadline" - ",bdep.h_contract_terms" - ",bdep.wire_salt" - ",wt.payto_uri AS receiver_wire_account" - " FROM coin_deposits cdep" - " JOIN batch_deposits bdep USING (batch_deposit_serial_id)" - " JOIN known_coins kc ON (kc.coin_pub = cdep.coin_pub)" - " JOIN denominations USING (denominations_serial)" - " JOIN wire_targets wt USING (wire_target_h_payto)" - " WHERE cdep.coin_pub=$1" - " AND bdep.merchant_pub=$3" - " AND bdep.h_contract_terms=$2;"); - /* Note: query might be made more efficient if we computed the 'shard' - from merchant_pub and included that as a constraint on bdep! */ - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_deposit", - params, - rs); - if (0 >= qs) - return qs; - TALER_merchant_wire_signature_hash (deposit2.receiver_wire_account, - &deposit2.wire_salt, - &h_wire2); - GNUNET_free (deposit2.receiver_wire_account.full_payto); - /* Now we check that the other information in @a deposit - also matches, and if not report inconsistencies. */ - if ( (GNUNET_TIME_timestamp_cmp (refund_deadline, - !=, - deposit2.refund_deadline)) || - (0 != GNUNET_memcmp (h_wire, - &h_wire2) ) ) - { - /* Inconsistencies detected! Does not match! */ - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; -} diff --git a/src/exchangedb/pg_inject_auditor_triggers.c b/src/exchangedb/pg_inject_auditor_triggers.c @@ -1,55 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_inject_auditor_triggers.c - * @brief Implementation of the inject_auditor_triggers function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/gc.h" -#include "helper.h" -#include "taler/exchange-database/inject_auditor_triggers.h" - - -/** - * Function called to inject auditor triggers into the - * database, triggering the real-time auditor upon - * relevant INSERTs. - * - * @param pg the database context - * @return #GNUNET_OK on success, - * #GNUNET_SYSERR on DB errors - */ -enum GNUNET_GenericReturnValue -TALER_EXCHANGEDB_inject_auditor_triggers (struct - TALER_EXCHANGEDB_PostgresContext *pg) -{ - struct GNUNET_PQ_Context *conn; - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - - conn = GNUNET_PQ_connect_with_cfg (pg->cfg, - "exchangedb-postgres", - "auditor-triggers-", - es, - NULL); - if (NULL == conn) - return GNUNET_SYSERR; - GNUNET_PQ_disconnect (conn); - return GNUNET_OK; -} diff --git a/src/exchangedb/pg_insert_active_legitimization_measure.c b/src/exchangedb/pg_insert_active_legitimization_measure.c @@ -1,58 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_insert_active_legitimization_measure.c - * @brief Implementation of the insert_active_legitimization_measure function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_active_legitimization_measure.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_active_legitimization_measure ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_AccountAccessTokenP *access_token, - const json_t *jmeasures, - uint64_t *legitimization_measure_serial_id) -{ - struct GNUNET_TIME_Timestamp now - = GNUNET_TIME_timestamp_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (access_token), - GNUNET_PQ_query_param_timestamp (&now), - TALER_PQ_query_param_json (jmeasures), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("out_legitimization_measure_serial_id", - legitimization_measure_serial_id), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "do_insert_active_legitimization_measure", - "SELECT" - " out_legitimization_measure_serial_id" - " FROM exchange_do_insert_active_legitimization_measure" - "($1, $2, $3::TEXT::JSONB);"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "do_insert_active_legitimization_measure", - params, - rs); -} diff --git a/src/exchangedb/pg_insert_aml_decision.c b/src/exchangedb/pg_insert_aml_decision.c @@ -1,185 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2023, 2024 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/> - */ -/** - * @file exchangedb/pg_insert_aml_decision.c - * @brief Implementation of the insert_aml_decision function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_aml_decision.h" -#include "helper.h" -#include <gnunet/gnunet_pq_lib.h> - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_aml_decision ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_FullPayto payto_uri, - const struct TALER_NormalizedPaytoHashP *h_payto, - struct GNUNET_TIME_Timestamp decision_time, - struct GNUNET_TIME_Timestamp expiration_time, - const json_t *properties, - const json_t *new_rules, - bool to_investigate, - const char *new_measure_name, - const json_t *jmeasures, - const char *justification, - const struct TALER_AmlOfficerPublicKeyP *decider_pub, - const struct TALER_AmlOfficerSignatureP *decider_sig, - size_t num_events, - const char *events[static num_events], - const char *form_name, - size_t enc_attributes_size, - const void *enc_attributes, - struct GNUNET_HashCode *attributes_hash, - struct GNUNET_TIME_Timestamp attributes_expiration_time, - bool *invalid_officer, - bool *unknown_account, - struct GNUNET_TIME_Timestamp *last_date, - uint64_t *legitimization_measure_serial_id, - bool *is_wallet) -{ - struct TALER_EXCHANGEDB_KycCompletedEventP rep = { - .header.size = htons (sizeof (rep)), - .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), - .h_payto = *h_payto - }; - struct TALER_FullPaytoHashP h_full_payto; - char *notify_s - = GNUNET_PQ_get_event_notify_channel (&rep.header); - bool account_unknown; - struct GNUNET_PQ_QueryParam params[] = { - /* $1: in_payto_uri */ - NULL == payto_uri.full_payto - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (payto_uri.full_payto), - /* $2: in_h_normalized_payto */ - GNUNET_PQ_query_param_auto_from_type (h_payto), - /* $3: in_h_full_payto */ - NULL == payto_uri.full_payto - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (&h_full_payto), - /* $4: in_decision_time */ - GNUNET_PQ_query_param_timestamp (&decision_time), - /* $5: in_expiration_time*/ - GNUNET_PQ_query_param_timestamp (&expiration_time), - /* $6: in_properties */ - NULL != properties - ? TALER_PQ_query_param_json (properties) - : GNUNET_PQ_query_param_null (), - /* $7: in_kyc_attributes_enc */ - NULL != enc_attributes - ? GNUNET_PQ_query_param_fixed_size (enc_attributes, - enc_attributes_size) - : GNUNET_PQ_query_param_null (), - /* $8: in_kyc_attributes_hash */ - NULL != attributes_hash - ? GNUNET_PQ_query_param_auto_from_type (attributes_hash) - : GNUNET_PQ_query_param_null (), - /* $9: in_kyc_attributes_expiration */ - GNUNET_PQ_query_param_timestamp (&attributes_expiration_time), - /* $10: in_new_rules */ - TALER_PQ_query_param_json (new_rules), - /* $11: in_to_investigate */ - GNUNET_PQ_query_param_bool (to_investigate), - /* $12: in_new_measure_name */ - NULL != new_measure_name - ? GNUNET_PQ_query_param_string (new_measure_name) - : GNUNET_PQ_query_param_null (), - /* $13: in_jmeasures */ - NULL != jmeasures - ? TALER_PQ_query_param_json (jmeasures) - : GNUNET_PQ_query_param_null (), - /* $14: in_justification */ - NULL != justification - ? GNUNET_PQ_query_param_string (justification) - : GNUNET_PQ_query_param_null (), - /* $15: in_decider_pub */ - NULL != decider_pub - ? GNUNET_PQ_query_param_auto_from_type (decider_pub) - : GNUNET_PQ_query_param_null (), - /* $16: in_decider_sig */ - NULL != decider_sig - ? GNUNET_PQ_query_param_auto_from_type (decider_sig) - : GNUNET_PQ_query_param_null (), - /* $17: in_notify_s*/ - GNUNET_PQ_query_param_string (notify_s), - /* $18: ina_events */ - GNUNET_PQ_query_param_array_ptrs_string (num_events, - events, - pg->conn), - (NULL == form_name) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (form_name), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("out_invalid_officer", - invalid_officer), - GNUNET_PQ_result_spec_bool ("out_account_unknown", - unknown_account), - GNUNET_PQ_result_spec_timestamp ("out_last_date", - last_date), - GNUNET_PQ_result_spec_uint64 ("out_legitimization_measure_serial_id", - legitimization_measure_serial_id), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_bool ("out_is_wallet", - is_wallet), - &account_unknown), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - *is_wallet = false; - GNUNET_assert ( ( (NULL == decider_pub) && - (NULL == decider_sig) && - (NULL == justification) ) || - ( (NULL != decider_pub) && - (NULL != decider_sig) && - (NULL != justification) ) ); - - if (NULL != payto_uri.full_payto) - TALER_full_payto_hash (payto_uri, - &h_full_payto); - PREPARE (pg, - "do_insert_aml_decision", - "SELECT" - " out_invalid_officer" - ",out_account_unknown" - ",out_last_date" - ",out_legitimization_measure_serial_id" - ",out_is_wallet" - " FROM exchange_do_insert_aml_decision" - "($1,$2,$3,$4,$5,$6::TEXT::JSONB,$7,$8,$9,$10::TEXT::JSONB" - ",$11,$12,$13::TEXT::JSONB,$14,$15,$16,$17,$18,$19);"); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Inserting LEGI OUTCOME from AML decision with notification on %s\n", - notify_s); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "do_insert_aml_decision", - params, - rs); - GNUNET_PQ_cleanup_query_params_closures (params); - GNUNET_free (notify_s); - GNUNET_PQ_event_do_poll (pg->conn); - if (qs <= 0) - return qs; - if (account_unknown) - { - GNUNET_assert ((*invalid_officer) || (*unknown_account)); - } - return qs; -} diff --git a/src/exchangedb/pg_insert_aml_officer.c b/src/exchangedb/pg_insert_aml_officer.c @@ -1,62 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2023 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/> - */ -/** - * @file exchangedb/pg_insert_aml_officer.c - * @brief Implementation of the insert_aml_officer function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_aml_officer.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_aml_officer ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_AmlOfficerPublicKeyP *decider_pub, - const struct TALER_MasterSignatureP *master_sig, - const char *decider_name, - bool is_active, - bool read_only, - struct GNUNET_TIME_Timestamp last_change, - struct GNUNET_TIME_Timestamp *previous_change) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (decider_pub), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_string (decider_name), - GNUNET_PQ_query_param_bool (is_active), - GNUNET_PQ_query_param_bool (read_only), - GNUNET_PQ_query_param_timestamp (&last_change), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("out_last_change", - previous_change), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "do_insert_aml_staff", - "SELECT" - " out_last_change" - " FROM exchange_do_insert_aml_officer" - "($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "do_insert_aml_staff", - params, - rs); -} diff --git a/src/exchangedb/pg_insert_aml_program_failure.c b/src/exchangedb/pg_insert_aml_program_failure.c @@ -1,66 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_insert_aml_program_failure.c - * @brief Implementation of the insert_aml_program_failure function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_aml_program_failure.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_aml_program_failure ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t process_row, - const struct TALER_NormalizedPaytoHashP *h_payto, - const char *error_message, - enum TALER_ErrorCode ec) -{ - uint32_t ec32 = (uint32_t) ec; - struct TALER_EXCHANGEDB_KycCompletedEventP rep = { - .header.size = htons (sizeof (rep)), - .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), - .h_payto = *h_payto - }; - struct GNUNET_TIME_Timestamp now - = GNUNET_TIME_timestamp_get (); - char *kyc_completed_notify_s - = GNUNET_PQ_get_event_notify_channel (&rep.header); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&process_row), - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_timestamp (&now), - GNUNET_PQ_query_param_uint32 (&ec32), - GNUNET_PQ_query_param_string (error_message), - GNUNET_PQ_query_param_string (kyc_completed_notify_s), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "insert_aml_program_failure", - "SELECT out_update" - " FROM exchange_do_insert_aml_program_failure" - " ($1, $2, $3, $4, $5, $6);"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_aml_program_failure", - params); - GNUNET_free (kyc_completed_notify_s); - return qs; -} diff --git a/src/exchangedb/pg_insert_auditor.c b/src/exchangedb/pg_insert_auditor.c @@ -1,55 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_auditor.c - * @brief Implementation of the insert_auditor function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_auditor.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_auditor (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_AuditorPublicKeyP * - auditor_pub, - const char *auditor_url, - const char *auditor_name, - struct GNUNET_TIME_Timestamp start_date) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (auditor_pub), - GNUNET_PQ_query_param_string (auditor_name), - GNUNET_PQ_query_param_string (auditor_url), - GNUNET_PQ_query_param_timestamp (&start_date), - GNUNET_PQ_query_param_end - }; - - /* used in #postgres_insert_auditor() */ - PREPARE (pg, - "insert_auditor", - "INSERT INTO auditors " - "(auditor_pub" - ",auditor_name" - ",auditor_url" - ",is_active" - ",last_change" - ") VALUES " - "($1, $2, $3, true, $4);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_auditor", - params); -} diff --git a/src/exchangedb/pg_insert_auditor_denom_sig.c b/src/exchangedb/pg_insert_auditor_denom_sig.c @@ -1,58 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_auditor_denom_sig.c - * @brief Implementation of the insert_auditor_denom_sig function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_auditor_denom_sig.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_insert_auditor_denom_sig ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_DenominationHashP *h_denom_pub, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const struct TALER_AuditorSignatureP *auditor_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (auditor_pub), - GNUNET_PQ_query_param_auto_from_type (h_denom_pub), - GNUNET_PQ_query_param_auto_from_type (auditor_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_auditor_denom_sig", - "WITH ax AS" - " (SELECT auditor_uuid" - " FROM auditors" - " WHERE auditor_pub=$1)" - "INSERT INTO auditor_denom_sigs " - "(auditor_uuid" - ",denominations_serial" - ",auditor_sig" - ") SELECT ax.auditor_uuid, denominations_serial, $3 " - " FROM denominations" - " CROSS JOIN ax" - " WHERE denom_pub_hash=$2" - " ON CONFLICT DO NOTHING;"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_auditor_denom_sig", - params); -} diff --git a/src/exchangedb/pg_insert_close_request.c b/src/exchangedb/pg_insert_close_request.c @@ -1,64 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_insert_close_request.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_close_request.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_close_request ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_FullPayto payto_uri, - const struct TALER_ReserveSignatureP *reserve_sig, - struct GNUNET_TIME_Timestamp request_timestamp, - const struct TALER_Amount *balance, - const struct TALER_Amount *closing_fee) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_timestamp (&request_timestamp), - GNUNET_PQ_query_param_auto_from_type (reserve_sig), - TALER_PQ_query_param_amount (pg->conn, - balance), - TALER_PQ_query_param_amount (pg->conn, - closing_fee), - GNUNET_PQ_query_param_string (payto_uri.full_payto), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_account_close", - "INSERT INTO close_requests" - "(reserve_pub" - ",close_timestamp" - ",reserve_sig" - ",close" - ",close_fee" - ",payto_uri" - ")" - "VALUES " - "($1, $2, $3, $4, $5, $6)" - " ON CONFLICT DO NOTHING;"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_account_close", - params); -} diff --git a/src/exchangedb/pg_insert_contract.c b/src/exchangedb/pg_insert_contract.c @@ -1,89 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_contract.c - * @brief Implementation of the insert_contract function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_contract.h" -#include "taler/exchange-database/select_contract_by_purse.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_contract ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_EncryptedContract *econtract, - bool *in_conflict) -{ - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - GNUNET_PQ_query_param_auto_from_type (&econtract->contract_pub), - GNUNET_PQ_query_param_fixed_size (econtract->econtract, - econtract->econtract_size), - GNUNET_PQ_query_param_auto_from_type (&econtract->econtract_sig), - GNUNET_PQ_query_param_end - }; - - *in_conflict = false; - /* Used in #postgres_insert_contract() */ - PREPARE (pg, - "insert_contract", - "INSERT INTO contracts" - " (purse_pub" - " ,pub_ckey" - " ,e_contract" - " ,contract_sig" - " ,purse_expiration" - " ) SELECT " - " $1, $2, $3, $4, purse_expiration" - " FROM purse_requests" - " WHERE purse_pub=$1" - " ON CONFLICT DO NOTHING;"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_contract", - params); - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs) - return qs; - { - struct TALER_EncryptedContract econtract2; - - qs = TALER_TALER_EXCHANGEDB_select_contract_by_purse (pg, - purse_pub, - &econtract2); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if ( (0 == GNUNET_memcmp (&econtract->contract_pub, - &econtract2.contract_pub)) && - (econtract2.econtract_size == - econtract->econtract_size) && - (0 == memcmp (econtract2.econtract, - econtract->econtract, - econtract->econtract_size)) ) - { - GNUNET_free (econtract2.econtract); - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - GNUNET_free (econtract2.econtract); - *in_conflict = true; - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } -} diff --git a/src/exchangedb/pg_insert_denomination_info.c b/src/exchangedb/pg_insert_denomination_info.c @@ -1,98 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_denomination_info.c - * @brief Implementation of the insert_denomination_info function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_denomination_info.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_denomination_info ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue) -{ - struct TALER_DenominationHashP denom_hash; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&issue->denom_hash), - TALER_PQ_query_param_denom_pub (denom_pub), - GNUNET_PQ_query_param_auto_from_type (&issue->signature), - GNUNET_PQ_query_param_timestamp (&issue->start), - GNUNET_PQ_query_param_timestamp (&issue->expire_withdraw), - GNUNET_PQ_query_param_timestamp (&issue->expire_deposit), - GNUNET_PQ_query_param_timestamp (&issue->expire_legal), - TALER_PQ_query_param_amount (pg->conn, - &issue->value), - TALER_PQ_query_param_amount (pg->conn, - &issue->fees.withdraw), - TALER_PQ_query_param_amount (pg->conn, - &issue->fees.deposit), - TALER_PQ_query_param_amount (pg->conn, - &issue->fees.refresh), - TALER_PQ_query_param_amount (pg->conn, - &issue->fees.refund), - GNUNET_PQ_query_param_uint32 (&denom_pub->age_mask.bits), - GNUNET_PQ_query_param_end - }; - - GNUNET_assert (denom_pub->age_mask.bits == - issue->age_mask.bits); - TALER_denom_pub_hash (denom_pub, - &denom_hash); - GNUNET_assert (0 == - GNUNET_memcmp (&denom_hash, - &issue->denom_hash)); - GNUNET_assert (! GNUNET_TIME_absolute_is_zero ( - issue->start.abs_time)); - GNUNET_assert (! GNUNET_TIME_absolute_is_zero ( - issue->expire_withdraw.abs_time)); - GNUNET_assert (! GNUNET_TIME_absolute_is_zero ( - issue->expire_deposit.abs_time)); - GNUNET_assert (! GNUNET_TIME_absolute_is_zero ( - issue->expire_legal.abs_time)); - /* check fees match denomination currency */ - GNUNET_assert (GNUNET_YES == - TALER_denom_fee_check_currency ( - issue->value.currency, - &issue->fees)); - PREPARE (pg, - "denomination_insert", - "INSERT INTO denominations " - "(denom_pub_hash" - ",denom_pub" - ",master_sig" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin" /* value of this denom */ - ",fee_withdraw" - ",fee_deposit" - ",fee_refresh" - ",fee_refund" - ",age_mask" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," - " $11, $12, $13);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "denomination_insert", - params); -} diff --git a/src/exchangedb/pg_insert_denomination_revocation.c b/src/exchangedb/pg_insert_denomination_revocation.c @@ -1,50 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_denomination_revocation.c - * @brief Implementation of the insert_denomination_revocation function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_denomination_revocation.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_denomination_revocation ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_DenominationHashP *denom_pub_hash, - const struct TALER_MasterSignatureP *master_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_end - }; - - /* Used in #postgres_insert_denomination_revocation() */ - PREPARE (pg, - "denomination_revocation_insert", - "INSERT INTO denomination_revocations " - "(denominations_serial" - ",master_sig" - ") SELECT denominations_serial,$2" - " FROM denominations" - " WHERE denom_pub_hash=$1;"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "denomination_revocation_insert", - params); -} diff --git a/src/exchangedb/pg_insert_drain_profit.c b/src/exchangedb/pg_insert_drain_profit.c @@ -1,60 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_drain_profit.c - * @brief Implementation of the insert_drain_profit function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_drain_profit.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_drain_profit ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_WireTransferIdentifierRawP *wtid, - const char *account_section, - const struct TALER_FullPayto payto_uri, - struct GNUNET_TIME_Timestamp request_timestamp, - const struct TALER_Amount *amount, - const struct TALER_MasterSignatureP *master_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (wtid), - GNUNET_PQ_query_param_string (account_section), - GNUNET_PQ_query_param_string (payto_uri.full_payto), - GNUNET_PQ_query_param_timestamp (&request_timestamp), - TALER_PQ_query_param_amount (pg->conn, - amount), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "drain_profit_insert", - "INSERT INTO profit_drains " - "(wtid" - ",account_section" - ",payto_uri" - ",trigger_date" - ",amount" - ",master_sig" - ") VALUES ($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "drain_profit_insert", - params); -} diff --git a/src/exchangedb/pg_insert_global_fee.c b/src/exchangedb/pg_insert_global_fee.c @@ -1,137 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_global_fee.c - * @brief Implementation of the insert_global_fee function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_dbevents.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_global_fee.h" -#include "helper.h" -#include "taler/exchange-database/get_global_fee.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - const struct TALER_GlobalFeeSet *fees, - struct GNUNET_TIME_Relative purse_timeout, - struct GNUNET_TIME_Relative - history_expiration, - uint32_t purse_account_limit, - const struct TALER_MasterSignatureP * - master_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&start_date), - GNUNET_PQ_query_param_timestamp (&end_date), - TALER_PQ_query_param_amount (pg->conn, - &fees->history), - TALER_PQ_query_param_amount (pg->conn, - &fees->account), - TALER_PQ_query_param_amount (pg->conn, - &fees->purse), - GNUNET_PQ_query_param_relative_time (&purse_timeout), - GNUNET_PQ_query_param_relative_time (&history_expiration), - GNUNET_PQ_query_param_uint32 (&purse_account_limit), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_end - }; - struct TALER_GlobalFeeSet wx; - struct TALER_MasterSignatureP sig; - struct GNUNET_TIME_Timestamp sd; - struct GNUNET_TIME_Timestamp ed; - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Relative pt; - struct GNUNET_TIME_Relative he; - uint32_t pal; - - qs = TALER_EXCHANGEDB_get_global_fee (pg, - start_date, - &sd, - &ed, - &wx, - &pt, - &he, - &pal, - &sig); - if (qs < 0) - return qs; - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) - { - if (0 != GNUNET_memcmp (&sig, - master_sig)) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if (0 != - TALER_global_fee_set_cmp (fees, - &wx)) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if ( (GNUNET_TIME_timestamp_cmp (sd, - !=, - start_date)) || - (GNUNET_TIME_timestamp_cmp (ed, - !=, - end_date)) ) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if ( (GNUNET_TIME_relative_cmp (purse_timeout, - !=, - pt)) || - (GNUNET_TIME_relative_cmp (history_expiration, - !=, - he)) ) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if (purse_account_limit != pal) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - /* equal record already exists */ - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - - /* Used in #postgres_insert_global_fee */ - PREPARE (pg, - "insert_global_fee", - "INSERT INTO global_fee " - "(start_date" - ",end_date" - ",history_fee" - ",account_fee" - ",purse_fee" - ",purse_timeout" - ",history_expiration" - ",purse_account_limit" - ",master_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_global_fee", - params); -} diff --git a/src/exchangedb/pg_insert_kyc_failure.c b/src/exchangedb/pg_insert_kyc_failure.c @@ -1,90 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_insert_kyc_failure.c - * @brief Implementation of the insert_kyc_failure function for Postgres - * @author Christian Grothoff - */ -#include "taler/platform.h" /* UNNECESSARY? */ -#include "taler/taler_error_codes.h" -#include "taler/taler_dbevents.h" /* UNNECESSARY? */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_kyc_failure.h" -#include "helper.h" -#include "taler/exchange-database/event_notify.h" /* UNNECESSARY? */ - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_kyc_failure ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t process_row, - const struct TALER_NormalizedPaytoHashP *h_payto, - const char *provider_name, - const char *provider_account_id, - const char *provider_legitimization_id, - const char *error_message, - enum TALER_ErrorCode ec) -{ - uint32_t ec32 = (uint32_t) ec; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&process_row), - GNUNET_PQ_query_param_auto_from_type (h_payto), - NULL != provider_name - ? GNUNET_PQ_query_param_string (provider_name) - : GNUNET_PQ_query_param_null (), - NULL != provider_account_id - ? GNUNET_PQ_query_param_string (provider_account_id) - : GNUNET_PQ_query_param_null (), - NULL != provider_legitimization_id - ? GNUNET_PQ_query_param_string (provider_legitimization_id) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_uint32 (&ec32), - GNUNET_PQ_query_param_string (error_message), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "insert_kyc_failure", - "UPDATE legitimization_processes" - " SET" - " finished=TRUE" - " ,provider_user_id=$4" - " ,provider_legitimization_id=$5" - " ,error_code=$6" - " ,error_message=$7" - " WHERE h_payto=$2" - " AND legitimization_process_serial_id=$1" - " AND provider_name=$3;"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_kyc_failure", - params); - if (qs > 0) - { - /* FIXME-#9419: might want to do this eventually in the same transaction... */ - struct TALER_EXCHANGEDB_KycCompletedEventP rep = { - .header.size = htons (sizeof (rep)), - .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), - .h_payto = *h_payto - }; - - TALER_EXCHANGEDB_event_notify (pg, - &rep.header, - NULL, - 0); - } - return qs; -} diff --git a/src/exchangedb/pg_insert_kyc_requirement_process.c b/src/exchangedb/pg_insert_kyc_requirement_process.c @@ -1,85 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_kyc_requirement_process.c - * @brief Implementation of the insert_kyc_requirement_process function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_kyc_requirement_process.h" -#include "helper.h" -#include <gnunet/gnunet_pq_lib.h> - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_kyc_requirement_process ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - uint32_t measure_index, - uint64_t legitimization_measure_serial_id, - const char *provider_name, - const char *provider_account_id, - const char *provider_legitimization_id, - uint64_t *process_row) -{ - struct GNUNET_TIME_Absolute now - = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_string (provider_name), - (NULL != provider_account_id) - ? GNUNET_PQ_query_param_string (provider_account_id) - : GNUNET_PQ_query_param_null (), - (NULL != provider_legitimization_id) - ? GNUNET_PQ_query_param_string (provider_legitimization_id) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id), - GNUNET_PQ_query_param_uint32 (&measure_index), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("legitimization_process_serial_id", - process_row), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "insert_kyc_requirement_process", - "INSERT INTO legitimization_processes" - " (h_payto" - " ,start_time" - " ,provider_name" - " ,provider_user_id" - " ,provider_legitimization_id" - " ,legitimization_measure_serial_id" - " ,measure_index" - " ) VALUES " - " ($1, $2, $3, $4, $5, $6, $7)" - " ON CONFLICT (legitimization_measure_serial_id,measure_index)" - " DO UPDATE" - " SET h_payto=$1" - " ,start_time=$2" - " ,provider_name=$3" - " ,provider_user_id=$4" - " ,provider_legitimization_id=$5" - " RETURNING legitimization_process_serial_id"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "insert_kyc_requirement_process", - params, - rs); -} diff --git a/src/exchangedb/pg_insert_partner.c b/src/exchangedb/pg_insert_partner.c @@ -1,67 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_partner.c - * @brief Implementation of the insert_partner function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_partner.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_partner (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_MasterPublicKeyP *master_pub - , - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - struct GNUNET_TIME_Relative wad_frequency, - const struct TALER_Amount *wad_fee, - const char *partner_base_url, - const struct TALER_MasterSignatureP *master_sig - ) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (master_pub), - GNUNET_PQ_query_param_timestamp (&start_date), - GNUNET_PQ_query_param_timestamp (&end_date), - GNUNET_PQ_query_param_relative_time (&wad_frequency), - TALER_PQ_query_param_amount (pg->conn, - wad_fee), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_string (partner_base_url), - GNUNET_PQ_query_param_end - }; - - - PREPARE (pg, - "insert_partner", - "INSERT INTO partners" - " (partner_master_pub" - " ,start_date" - " ,end_date" - " ,wad_frequency" - " ,wad_fee" - " ,master_sig" - " ,partner_base_url" - " ) VALUES " - " ($1, $2, $3, $4, $5, $6, $7)" - " ON CONFLICT DO NOTHING;"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_partner", - params); -} diff --git a/src/exchangedb/pg_insert_purse_request.c b/src/exchangedb/pg_insert_purse_request.c @@ -1,122 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_purse_request.c - * @brief Implementation of the insert_purse_request function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_purse_request.h" -#include "taler/exchange-database/get_purse_request.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_purse_request ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_PurseMergePublicKeyP *merge_pub, - struct GNUNET_TIME_Timestamp purse_expiration, - const struct TALER_PrivateContractHashP *h_contract_terms, - uint32_t age_limit, - enum TALER_WalletAccountMergeFlags flags, - const struct TALER_Amount *purse_fee, - const struct TALER_Amount *amount, - const struct TALER_PurseContractSignatureP *purse_sig, - bool *in_conflict) -{ - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get (); - uint32_t flags32 = (uint32_t) flags; - bool in_reserve_quota = (TALER_WAMF_MODE_CREATE_FROM_PURSE_QUOTA - == (flags & TALER_WAMF_MERGE_MODE_MASK)); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - GNUNET_PQ_query_param_auto_from_type (merge_pub), - GNUNET_PQ_query_param_timestamp (&now), - GNUNET_PQ_query_param_timestamp (&purse_expiration), - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_uint32 (&age_limit), - GNUNET_PQ_query_param_uint32 (&flags32), - GNUNET_PQ_query_param_bool (in_reserve_quota), - TALER_PQ_query_param_amount (pg->conn, - amount), - TALER_PQ_query_param_amount (pg->conn, - purse_fee), - GNUNET_PQ_query_param_auto_from_type (purse_sig), - GNUNET_PQ_query_param_end - }; - - *in_conflict = false; - PREPARE (pg, - "insert_purse_request", - "INSERT INTO purse_requests" - " (purse_pub" - " ,merge_pub" - " ,purse_creation" - " ,purse_expiration" - " ,h_contract_terms" - " ,age_limit" - " ,flags" - " ,in_reserve_quota" - " ,amount_with_fee" - " ,purse_fee" - " ,purse_sig" - " ) VALUES " - " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)" - " ON CONFLICT DO NOTHING;"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_purse_request", - params); - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs) - return qs; - { - struct TALER_PurseMergePublicKeyP merge_pub2; - struct GNUNET_TIME_Timestamp purse_expiration2; - struct TALER_PrivateContractHashP h_contract_terms2; - uint32_t age_limit2; - struct TALER_Amount amount2; - struct TALER_Amount balance; - struct TALER_PurseContractSignatureP purse_sig2; - - qs = TALER_EXCHANGEDB_get_purse_request (pg, - purse_pub, - &merge_pub2, - &purse_expiration2, - &h_contract_terms2, - &age_limit2, - &amount2, - &balance, - &purse_sig2); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if ( (age_limit2 == age_limit) && - (0 == TALER_amount_cmp (amount, - &amount2)) && - (0 == GNUNET_memcmp (&h_contract_terms2, - h_contract_terms)) && - (0 == GNUNET_memcmp (&merge_pub2, - merge_pub)) ) - { - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - *in_conflict = true; - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } -} diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c @@ -1,2453 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2020-2025 Taler Systems SA - - GNUnet 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 Foundation, either version 3 of the License, - or (at your option) any later version. - - GNUnet 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file exchangedb/pg_insert_records_by_table.c - * @brief replicate_records_by_table implementation - * @author Christian Grothoff - * @author Özgür Kesim - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_dbevents.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_records_by_table.h" -#include "helper.h" -#include <gnunet/gnunet_pq_lib.h> - - -/** - * Signature of helper functions of #TALER_EXCHANGEDB_insert_records_by_table(). - * - * @param pg plugin context - * @param td record to insert - * @return transaction status code - */ -typedef enum GNUNET_DB_QueryStatus -(*InsertRecordCallback)(struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td); - - -/** - * Function called with denominations records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_denominations (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct TALER_DenominationHashP denom_hash; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type (&denom_hash), - GNUNET_PQ_query_param_uint32 ( - &td->details.denominations.denom_type), - GNUNET_PQ_query_param_uint32 ( - &td->details.denominations.age_mask), - TALER_PQ_query_param_denom_pub ( - &td->details.denominations.denom_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.denominations.master_sig), - GNUNET_PQ_query_param_timestamp ( - &td->details.denominations.valid_from), - GNUNET_PQ_query_param_timestamp ( - &td->details.denominations.expire_withdraw), - GNUNET_PQ_query_param_timestamp ( - &td->details.denominations.expire_deposit), - GNUNET_PQ_query_param_timestamp ( - &td->details.denominations.expire_legal), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.denominations.coin), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.denominations.fees.withdraw), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.denominations.fees.deposit), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.denominations.fees.refresh), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.denominations.fees.refund), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_denominations", - "INSERT INTO denominations" - "(denominations_serial" - ",denom_pub_hash" - ",denom_type" - ",age_mask" - ",denom_pub" - ",master_sig" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin" - ",fee_withdraw" - ",fee_deposit" - ",fee_refresh" - ",fee_refund" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," - " $11, $12, $13, $14, $15);"); - - TALER_denom_pub_hash ( - &td->details.denominations.denom_pub, - &denom_hash); - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_denominations", - params); -} - - -/** - * Function called with denomination_revocations records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_denomination_revocations ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.denomination_revocations.master_sig), - GNUNET_PQ_query_param_uint64 ( - &td->details.denomination_revocations.denominations_serial), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_denomination_revocations", - "INSERT INTO denomination_revocations" - "(denom_revocations_serial_id" - ",master_sig" - ",denominations_serial" - ") VALUES " - "($1, $2, $3);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_denomination_revocations", - params); -} - - -/** - * Function called with wire target records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_wire_targets (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct TALER_NormalizedPaytoHashP normalized_payto_hash; - struct TALER_FullPaytoHashP full_payto_hash; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type (&full_payto_hash), - GNUNET_PQ_query_param_auto_from_type (&normalized_payto_hash), - GNUNET_PQ_query_param_string ( - td->details.wire_targets.full_payto_uri.full_payto), - GNUNET_PQ_query_param_end - }; - - TALER_full_payto_hash ( - td->details.wire_targets.full_payto_uri, - &full_payto_hash); - TALER_full_payto_normalize_and_hash ( - td->details.wire_targets.full_payto_uri, - &normalized_payto_hash); - PREPARE (pg, - "insert_into_table_wire_targets", - "INSERT INTO wire_targets" - "(wire_target_serial_id" - ",wire_target_h_payto" - ",h_normalized_payto" - ",payto_uri" - ") VALUES " - "($1, $2, $3, $4);"); - return GNUNET_PQ_eval_prepared_non_select ( - pg->conn, - "insert_into_table_wire_targets", - params); -} - - -/** - * Function called with kyc target records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_kyc_targets (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.kyc_targets.h_normalized_payto), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.kyc_targets.access_token), - td->details.kyc_targets.no_account - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type ( - &td->details.kyc_targets.target_pub), - GNUNET_PQ_query_param_bool ( - td->details.kyc_targets.is_wallet), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_kyc_targets", - "INSERT INTO kyc_targets" - "(kyc_target_serial_id" - ",h_normalized_payto" - ",access_token" - ",target_pub" - ",is_wallet" - ") VALUES " - "($1, $2, $3, $4, $5);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_kyc_targets", - params); -} - - -/** - * Function called with records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_legitimization_measures ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.legitimization_measures.target_token), - GNUNET_PQ_query_param_timestamp ( - &td->details.legitimization_measures.start_time), - TALER_PQ_query_param_json ( - td->details.legitimization_measures.measures), - GNUNET_PQ_query_param_uint32 ( - &td->details.legitimization_measures.display_priority), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_legitimization_measures", - "INSERT INTO legitimization_measures" - "(legitimization_measure_serial_id" - ",access_token" - ",start_time" - ",jmeasures" - ",display_priority" - ") VALUES " - "($1, $2, $3, $4::TEXT::JSONB, $5);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_legitimization_measures", - params); -} - - -/** - * Function called with records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_legitimization_outcomes ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.legitimization_outcomes.h_payto), - GNUNET_PQ_query_param_timestamp ( - &td->details.legitimization_outcomes.decision_time), - GNUNET_PQ_query_param_timestamp ( - &td->details.legitimization_outcomes.expiration_time), - TALER_PQ_query_param_json ( - td->details.legitimization_outcomes.properties), - GNUNET_PQ_query_param_bool ( - td->details.legitimization_outcomes.to_investigate), - TALER_PQ_query_param_json ( - td->details.legitimization_outcomes.new_rules), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_legitimization_outcomes", - "INSERT INTO legitimization_outcomes" - "(outcome_serial_id" - ",h_payto" - ",decision_time" - ",expiration_time" - ",jproperties" - ",to_investigate" - ",jnew_rules" - ") VALUES " - "($1, $2, $3, $4, $5::TEXT::JSONB, $6, $7::TEXT::JSONB);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_legitimization_outcomes", - params); -} - - -/** - * Function called with records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_legitimization_processes ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.legitimization_processes.h_payto), - GNUNET_PQ_query_param_timestamp ( - &td->details.legitimization_processes.start_time), - GNUNET_PQ_query_param_timestamp ( - &td->details.legitimization_processes.expiration_time), - GNUNET_PQ_query_param_uint64 ( - &td->details.legitimization_processes.legitimization_measure_serial_id), - GNUNET_PQ_query_param_uint32 ( - &td->details.legitimization_processes.measure_index), - GNUNET_PQ_query_param_string ( - td->details.legitimization_processes.provider_name), - GNUNET_PQ_query_param_string ( - td->details.legitimization_processes.provider_user_id), - GNUNET_PQ_query_param_string ( - td->details.legitimization_processes.provider_legitimization_id), - GNUNET_PQ_query_param_string ( - td->details.legitimization_processes.redirect_url), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_legitimization_processes", - "INSERT INTO legitimization_processes" - "(legitimization_process_serial_id" - ",h_payto" - ",start_time" - ",expiration_time" - ",legitimization_measure_serial_id" - ",measure_index" - ",provider_name" - ",provider_user_id" - ",provider_legitimization_id" - ",redirect_url" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_legitimization_processes", - params); -} - - -/** - * Function called with reserves records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_reserves (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type (&td->details.reserves.reserve_pub), - GNUNET_PQ_query_param_timestamp (&td->details.reserves.expiration_date), - GNUNET_PQ_query_param_timestamp (&td->details.reserves.gc_date), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_reserves", - "INSERT INTO reserves" - "(reserve_uuid" - ",reserve_pub" - ",expiration_date" - ",gc_date" - ") VALUES " - "($1, $2, $3, $4);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_reserves", - params); -} - - -/** - * Function called with reserves_in records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_reserves_in (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_uint64 (&td->details.reserves_in.wire_reference), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.reserves_in.credit), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.reserves_in.sender_account_h_payto), - GNUNET_PQ_query_param_string ( - td->details.reserves_in.exchange_account_section), - GNUNET_PQ_query_param_timestamp ( - &td->details.reserves_in.execution_date), - GNUNET_PQ_query_param_auto_from_type (&td->details.reserves_in.reserve_pub), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_reserves_in", - "INSERT INTO reserves_in" - "(reserve_in_serial_id" - ",wire_reference" - ",credit" - ",wire_source_h_payto" - ",exchange_account_section" - ",execution_date" - ",reserve_pub" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_reserves_in", - params); -} - - -/** - * Function called with kycauth_in records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_kycauths_in (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_uint64 (&td->details.kycauth_in.wire_reference), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.reserves_in.credit), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.reserves_in.sender_account_h_payto), - GNUNET_PQ_query_param_string ( - td->details.reserves_in.exchange_account_section), - GNUNET_PQ_query_param_timestamp ( - &td->details.reserves_in.execution_date), - GNUNET_PQ_query_param_auto_from_type (&td->details.kycauth_in.account_pub), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_kycauth_in", - "INSERT INTO kycauths_in" - "(kycauth_in_serial_id" - ",wire_reference" - ",credit" - ",wire_source_h_payto" - ",exchange_account_section" - ",execution_date" - ",account_pub" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_kycauth_in", - params); -} - - -/** - * Function called with reserves_open_requests records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_reserves_open_requests (struct TALER_EXCHANGEDB_PostgresContext * - pg, - const struct - TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_timestamp ( - &td->details.reserves_open_requests.expiration_date), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.reserves_open_requests.reserve_sig), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.reserves_open_requests.reserve_payment), - GNUNET_PQ_query_param_uint32 ( - &td->details.reserves_open_requests.requested_purse_limit), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_reserves_open_requests", - "INSERT INTO reserves_open_requests" - "(open_request_uuid" - ",reserve_pub" - ",request_timestamp" - ",expiration_date" - ",reserve_sig" - ",reserve_payment" - ",requested_purse_limit" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_reserves_open_requests", - params); -} - - -/** - * Function called with reserves_open_requests records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_reserves_open_deposits ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.reserves_open_deposits.coin_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.reserves_open_deposits.coin_sig), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.reserves_open_deposits.reserve_sig), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.reserves_open_deposits.contribution), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_reserves_open_deposits", - "INSERT INTO reserves_open_deposits" - "(reserve_open_deposit_uuid" - ",reserve_sig" - ",reserve_pub" - ",coin_pub" - ",coin_sig" - ",contribution" - ") VALUES " - "($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_reserves_open_deposits", - params); -} - - -/** - * Function called with reserves_close records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_reserves_close (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_timestamp ( - &td->details.reserves_close.execution_date), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.reserves_close.wtid), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.reserves_close.sender_account_h_payto), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.reserves_close.amount), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.reserves_close.closing_fee), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.reserves_close.reserve_pub), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_reserves_close", - "INSERT INTO reserves_close" - "(close_uuid" - ",execution_date" - ",wtid" - ",wire_target_h_payto" - ",amount" - ",closing_fee" - ",reserve_pub" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_reserves_close", - params); -} - - -/** - * Function called with auditors records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_auditors (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type (&td->details.auditors.auditor_pub), - GNUNET_PQ_query_param_string (td->details.auditors.auditor_name), - GNUNET_PQ_query_param_string (td->details.auditors.auditor_url), - GNUNET_PQ_query_param_bool (td->details.auditors.is_active), - GNUNET_PQ_query_param_timestamp (&td->details.auditors.last_change), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_auditors", - "INSERT INTO auditors" - "(auditor_uuid" - ",auditor_pub" - ",auditor_name" - ",auditor_url" - ",is_active" - ",last_change" - ") VALUES " - "($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_auditors", - params); -} - - -/** - * Function called with auditor_denom_sigs records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_auditor_denom_sigs (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_uint64 (&td->details.auditor_denom_sigs.auditor_uuid), - GNUNET_PQ_query_param_uint64 ( - &td->details.auditor_denom_sigs.denominations_serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.auditor_denom_sigs.auditor_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_auditor_denom_sigs", - "INSERT INTO auditor_denom_sigs" - "(auditor_denom_serial" - ",auditor_uuid" - ",denominations_serial" - ",auditor_sig" - ") VALUES " - "($1, $2, $3, $4);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_auditor_denom_sigs", - params); -} - - -/** - * Function called with exchange_sign_keys records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_exchange_sign_keys (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.exchange_sign_keys.exchange_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.exchange_sign_keys.master_sig), - GNUNET_PQ_query_param_timestamp ( - &td->details.exchange_sign_keys.meta.start), - GNUNET_PQ_query_param_timestamp ( - &td->details.exchange_sign_keys.meta.expire_sign), - GNUNET_PQ_query_param_timestamp ( - &td->details.exchange_sign_keys.meta.expire_legal), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_exchange_sign_keys", - "INSERT INTO exchange_sign_keys" - "(esk_serial" - ",exchange_pub" - ",master_sig" - ",valid_from" - ",expire_sign" - ",expire_legal" - ") VALUES " - "($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_exchange_sign_keys", - params); -} - - -/** - * Function called with signkey_revocations records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_signkey_revocations (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_uint64 (&td->details.signkey_revocations.esk_serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.signkey_revocations.master_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_signkey_revocations", - "INSERT INTO signkey_revocations" - "(signkey_revocations_serial_id" - ",esk_serial" - ",master_sig" - ") VALUES " - "($1, $2, $3);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_signkey_revocations", - params); -} - - -/** - * Function called with known_coins records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_known_coins (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.known_coins.coin_pub), - TALER_PQ_query_param_denom_sig ( - &td->details.known_coins.denom_sig), - GNUNET_PQ_query_param_uint64 ( - &td->details.known_coins.denominations_serial), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_known_coins", - "INSERT INTO known_coins" - "(known_coin_id" - ",coin_pub" - ",denom_sig" - ",denominations_serial" - ") VALUES " - "($1, $2, $3, $4);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_known_coins", - params); -} - - -/** - * Function called with refresh records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type (&td->details.refresh.rc), - GNUNET_PQ_query_param_auto_from_type (&td->details.refresh.execution_date), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.refresh.amount_with_fee), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.refresh.old_coin_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.refresh.old_coin_sig), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.refresh.refresh_seed), - GNUNET_PQ_query_param_uint32 ( - &td->details.refresh.noreveal_index), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.refresh.planchets_h), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.refresh.selected_h), - td->details.refresh.no_blinding_seed - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type ( - &td->details.refresh.blinding_seed), - td->details.refresh.no_blinding_seed - ? GNUNET_PQ_query_param_null () - : TALER_PQ_query_param_array_cs_r_pub ( - td->details.refresh.num_cs_r_values, - td->details.refresh.cs_r_values, - pg->conn), - td->details.refresh.no_blinding_seed - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 ( - &td->details.refresh.cs_r_choices), - GNUNET_PQ_query_param_array_uint64 ( - td->details.refresh.num_coins, - td->details.refresh.denom_serials, - pg->conn), - TALER_PQ_query_param_array_blinded_denom_sig ( - td->details.refresh.num_coins, - td->details.refresh.denom_sigs, - pg->conn), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_refresh", - "INSERT INTO refresh" - "(refresh_id" - ",rc" - ",execution_date" - ",amount_with_fee" - ",old_coin_pub" - ",old_coin_sig" - ",refresh_seed" - ",noreveal_index" - ",planchets_h" - ",selected_h" - ",blinding_seed" - ",cs_r_values" - ",cs_r_choices" - ",denom_serials" - ",denom_sigs" - ") VALUES " - "($1, $2, $3, $4, $5, $6,$7,$8,$9,$10,$11,$12,$13,$14,$15);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_refresh", - params); -} - - -/** - * Function called with batch deposits records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_batch_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_uint64 (&td->details.batch_deposits.shard), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.batch_deposits.merchant_pub), - GNUNET_PQ_query_param_timestamp ( - &td->details.batch_deposits.wallet_timestamp), - GNUNET_PQ_query_param_timestamp ( - &td->details.batch_deposits.exchange_timestamp), - GNUNET_PQ_query_param_timestamp ( - &td->details.batch_deposits.refund_deadline), - GNUNET_PQ_query_param_timestamp (&td->details.batch_deposits.wire_deadline), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.batch_deposits.h_contract_terms), - td->details.batch_deposits.no_wallet_data_hash - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type ( - &td->details.batch_deposits.wallet_data_hash), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.batch_deposits.wire_salt), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.batch_deposits.wire_target_h_payto), - td->details.batch_deposits.no_policy_details - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 ( - &td->details.batch_deposits.policy_details_serial_id), - GNUNET_PQ_query_param_bool (td->details.batch_deposits.policy_blocked), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.batch_deposits.total_amount), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.batch_deposits.total_without_fee), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.batch_deposits.merchant_sig), - GNUNET_PQ_query_param_bool (td->details.batch_deposits.done), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_batch_deposits", - "INSERT INTO batch_deposits" - "(batch_deposit_serial_id" - ",shard" - ",merchant_pub" - ",wallet_timestamp" - ",exchange_timestamp" - ",refund_deadline" - ",wire_deadline" - ",h_contract_terms" - ",wallet_data_hash" - ",wire_salt" - ",wire_target_h_payto" - ",policy_details_serial_id" - ",policy_blocked" - ",total_amount" - ",total_without_fee" - ",merchant_sig" - ",done" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," - " $11, $12, $13, $14, $15, $16, $17);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_batch_deposits", - params); -} - - -/** - * Function called with deposits records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_coin_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_uint64 ( - &td->details.coin_deposits.batch_deposit_serial_id), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.coin_deposits.coin_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.coin_deposits.coin_sig), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.coin_deposits.amount_with_fee), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_coin_deposits", - "INSERT INTO coin_deposits" - "(coin_deposit_serial_id" - ",batch_deposit_serial_id" - ",coin_pub" - ",coin_sig" - ",amount_with_fee" - ") VALUES " - "($1, $2, $3, $4, $5);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_coin_deposits", - params); -} - - -/** - * Function called with refunds records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_refunds (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type (&td->details.refunds.coin_pub), - GNUNET_PQ_query_param_auto_from_type (&td->details.refunds.merchant_sig), - GNUNET_PQ_query_param_uint64 (&td->details.refunds.rtransaction_id), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.refunds.amount_with_fee), - GNUNET_PQ_query_param_uint64 ( - &td->details.refunds.batch_deposit_serial_id), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_refunds", - "INSERT INTO refunds" - "(refund_serial_id" - ",coin_pub" - ",merchant_sig" - ",rtransaction_id" - ",amount_with_fee" - ",batch_deposit_serial_id" - ") VALUES " - "($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_refunds", - params); -} - - -/** - * Function called with wire_out records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_wire_out (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_timestamp (&td->details.wire_out.execution_date), - GNUNET_PQ_query_param_auto_from_type (&td->details.wire_out.wtid_raw), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wire_out.wire_target_h_payto), - GNUNET_PQ_query_param_string ( - td->details.wire_out.exchange_account_section), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.wire_out.amount), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_wire_out", - "INSERT INTO wire_out" - "(wireout_uuid" - ",execution_date" - ",wtid_raw" - ",wire_target_h_payto" - ",exchange_account_section" - ",amount" - ") VALUES " - "($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_wire_out", - params); -} - - -/** - * Function called with aggregation_tracking records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_aggregation_tracking (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_uint64 ( - &td->details.aggregation_tracking.batch_deposit_serial_id), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.aggregation_tracking.wtid_raw), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_aggregation_tracking", - "INSERT INTO aggregation_tracking" - "(aggregation_serial_id" - ",batch_deposit_serial_id" - ",wtid_raw" - ") VALUES " - "($1, $2, $3);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_aggregation_tracking", - params); -} - - -/** - * Function called with wire_fee records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_wire_fee (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_string (td->details.wire_fee.wire_method), - GNUNET_PQ_query_param_timestamp (&td->details.wire_fee.start_date), - GNUNET_PQ_query_param_timestamp (&td->details.wire_fee.end_date), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.wire_fee.fees.wire), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.wire_fee.fees.closing), - GNUNET_PQ_query_param_auto_from_type (&td->details.wire_fee.master_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_wire_fee", - "INSERT INTO wire_fee" - "(wire_fee_serial" - ",wire_method" - ",start_date" - ",end_date" - ",wire_fee" - ",closing_fee" - ",master_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_wire_fee", - params); -} - - -/** - * Function called with wire_fee records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 ( - &td->serial), - GNUNET_PQ_query_param_timestamp ( - &td->details.global_fee.start_date), - GNUNET_PQ_query_param_timestamp ( - &td->details.global_fee.end_date), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.global_fee.fees.history), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.global_fee.fees.account), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.global_fee.fees.purse), - GNUNET_PQ_query_param_relative_time ( - &td->details.global_fee.purse_timeout), - GNUNET_PQ_query_param_relative_time ( - &td->details.global_fee.history_expiration), - GNUNET_PQ_query_param_uint32 ( - &td->details.global_fee.purse_account_limit), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.global_fee.master_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_global_fee", - "INSERT INTO global_fee" - "(global_fee_serial" - ",start_date" - ",end_date" - ",history_fee" - ",account_fee" - ",purse_fee" - ",purse_timeout" - ",history_expiration" - ",purse_account_limit" - ",master_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_global_fee", - params); -} - - -/** - * Function called with recoup records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_recoup (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type (&td->details.recoup.coin_sig), - GNUNET_PQ_query_param_auto_from_type (&td->details.recoup.coin_blind), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.recoup.amount), - GNUNET_PQ_query_param_timestamp (&td->details.recoup.timestamp), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.recoup.coin_pub), - GNUNET_PQ_query_param_uint64 (&td->details.recoup.withdraw_serial_id), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_recoup", - "INSERT INTO recoup" - "(recoup_uuid" - ",coin_sig" - ",coin_blind" - ",amount" - ",recoup_timestamp" - ",coin_pub" - ",withdraw_serial_id" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_recoup", - params); -} - - -/** - * Function called with recoup_refresh records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_recoup_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type (&td->details.recoup_refresh.coin_sig), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.recoup_refresh.coin_blind), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.recoup_refresh.amount), - GNUNET_PQ_query_param_timestamp (&td->details.recoup_refresh.timestamp), - GNUNET_PQ_query_param_uint64 (&td->details.recoup_refresh.known_coin_id), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.recoup.coin_pub), - GNUNET_PQ_query_param_uint64 (&td->details.recoup_refresh.rrc_serial), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_recoup_refresh", - "INSERT INTO recoup_refresh" - "(recoup_refresh_uuid" - ",coin_sig" - ",coin_blind" - ",amount" - ",recoup_timestamp" - ",known_coin_id" - ",coin_pub" - ",rrc_serial" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_recoup_refresh", - params); -} - - -/** - * Function called with extensions records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_extensions (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_string (td->details.extensions.name), - NULL == td->details.extensions.manifest ? - GNUNET_PQ_query_param_null () : - GNUNET_PQ_query_param_string (td->details.extensions.manifest), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_extensions", - "INSERT INTO extensions" - "(extension_id" - ",name" - ",manifest" - ") VALUES " - "($1, $2, $3);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_extensions", - params); -} - - -/** - * Function called with policy_details records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_policy_details (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.policy_details.hash_code), - (td->details.policy_details.no_policy_json) - ? GNUNET_PQ_query_param_null () - : TALER_PQ_query_param_json (td->details.policy_details.policy_json), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.policy_details.commitment), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.policy_details.accumulated_total), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.policy_details.fee), - TALER_PQ_query_param_amount (pg->conn, - &td->details.policy_details.transferable), - GNUNET_PQ_query_param_timestamp (&td->details.policy_details.deadline), - GNUNET_PQ_query_param_uint16 ( - &td->details.policy_details.fulfillment_state), - (td->details.policy_details.no_fulfillment_id) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 ( - &td->details.policy_details.fulfillment_id), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_policy_details", - "INSERT INTO policy_details" - "(policy_details_serial_id" - ",policy_hash_code" - ",policy_json" - ",deadline" - ",commitment" - ",accumulated_total" - ",fee" - ",transferable" - ",fulfillment_state" - ",fulfillment_id" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_policy_details", - params); -} - - -/** - * Function called with policy_fulfillment records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_policy_fulfillments (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_timestamp ( - &td->details.policy_fulfillments.fulfillment_timestamp), - (NULL == td->details.policy_fulfillments.fulfillment_proof) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string ( - td->details.policy_fulfillments.fulfillment_proof), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.policy_fulfillments.h_fulfillment_proof), - GNUNET_PQ_query_param_fixed_size ( - td->details.policy_fulfillments.policy_hash_codes, - td->details.policy_fulfillments.policy_hash_codes_count), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_policy_fulfillments", - "INSERT INTO policy_fulfillments " - "(fulfillment_id" - ",fulfillment_timestamp" - ",fulfillment_proof" - ",h_fulfillment_proof" - ",policy_hash_codes" - ") VALUES " - "($1, $2, $3::TEXT::JSONB, $4, $5);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_policy_fulfillments", - params); -} - - -/** - * Function called with purse_requests records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_purse_requests (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.purse_requests.purse_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.purse_requests.merge_pub), - GNUNET_PQ_query_param_timestamp ( - &td->details.purse_requests.purse_creation), - GNUNET_PQ_query_param_timestamp ( - &td->details.purse_requests.purse_expiration), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.purse_requests.h_contract_terms), - GNUNET_PQ_query_param_uint32 (&td->details.purse_requests.age_limit), - GNUNET_PQ_query_param_uint32 (&td->details.purse_requests.flags), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.purse_requests.amount_with_fee), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.purse_requests.purse_fee), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.purse_requests.purse_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_purse_requests", - "INSERT INTO purse_requests" - "(purse_requests_serial_id" - ",purse_pub" - ",merge_pub" - ",purse_creation" - ",purse_expiration" - ",h_contract_terms" - ",age_limit" - ",flags" - ",amount_with_fee" - ",purse_fee" - ",purse_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_purse_requests", - params); -} - - -/** - * Function called with purse_decision records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_purse_decision (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.purse_decision.purse_pub), - GNUNET_PQ_query_param_timestamp ( - &td->details.purse_decision.action_timestamp), - GNUNET_PQ_query_param_bool ( - td->details.purse_decision.refunded), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_purse_refunds", - "INSERT INTO purse_refunds" - "(purse_refunds_serial_id" - ",purse_pub" - ",action_timestamp" - ",refunded" - ") VALUES " - "($1, $2, $3, $4);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_purse_decision", - params); -} - - -/** - * Function called with purse_merges records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_purse_merges (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_uint64 (&td->details.purse_merges.partner_serial_id), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.purse_merges.reserve_pub), - GNUNET_PQ_query_param_auto_from_type (&td->details.purse_merges.purse_pub), - GNUNET_PQ_query_param_auto_from_type (&td->details.purse_merges.merge_sig), - GNUNET_PQ_query_param_timestamp (&td->details.purse_merges.merge_timestamp), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_purse_merges", - "INSERT INTO purse_merges" - "(purse_merge_request_serial_id" - ",partner_serial_id" - ",reserve_pub" - ",purse_pub" - ",merge_sig" - ",merge_timestamp" - ") VALUES " - "($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_purse_merges", - params); -} - - -/** - * Function called with purse_deposits records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_purse_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_uint64 ( - &td->details.purse_deposits.partner_serial_id), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.purse_deposits.purse_pub), - GNUNET_PQ_query_param_auto_from_type (&td->details.purse_deposits.coin_pub), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.purse_deposits.amount_with_fee), - GNUNET_PQ_query_param_auto_from_type (&td->details.purse_deposits.coin_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_purse_deposits", - "INSERT INTO purse_deposits" - "(purse_deposit_serial_id" - ",partner_serial_id" - ",purse_pub" - ",coin_pub" - ",amount_with_fee" - ",coin_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_purse_deposits", - params); -} - - -/** -x * Function called with account_mergers records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_account_mergers (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.account_merges.reserve_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.account_merges.reserve_sig), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.account_merges.purse_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.account_merges.wallet_h_payto), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_account_merges", - "INSERT INTO account_merges" - "(account_merge_request_serial_id" - ",reserve_pub" - ",reserve_sig" - ",purse_pub" - ",wallet_h_payto" - ") VALUES " - "($1, $2, $3, $4, $5);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_account_merges", - params); -} - - -/** - * Function called with history_requests records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_history_requests (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.history_requests.reserve_pub), - GNUNET_PQ_query_param_timestamp ( - &td->details.history_requests.request_timestamp), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.history_requests.reserve_sig), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.history_requests.history_fee), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_history_requests", - "INSERT INTO history_requests" - "(history_request_serial_id" - ",reserve_pub" - ",request_timestamp" - ",reserve_sig" - ",history_fee" - ") VALUES " - "($1, $2, $3, $4, $5);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_history_requests", - params); -} - - -/** - * Function called with close_requests records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_close_requests (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.close_requests.reserve_pub), - GNUNET_PQ_query_param_timestamp ( - &td->details.close_requests.close_timestamp), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.close_requests.reserve_sig), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.close_requests.close), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.close_requests.close_fee), - GNUNET_PQ_query_param_string ( - td->details.close_requests.payto_uri.full_payto), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_close_requests", - "INSERT INTO close_requests" - "(close_request_serial_id" - ",reserve_pub" - ",close_timestamp" - ",reserve_sig" - ",close" - ",close_fee" - ",payto_uri" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_close_requests", - params); -} - - -/** - * Function called with wads_out records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_wads_out (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type (&td->details.wads_out.wad_id), - GNUNET_PQ_query_param_uint64 (&td->details.wads_out.partner_serial_id), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.wads_out.amount), - GNUNET_PQ_query_param_timestamp (&td->details.wads_out.execution_time), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_wads_out", - "INSERT INTO wads_out" - "(wad_out_serial_id" - ",wad_id" - ",partner_serial_id" - ",amount" - ",execution_time" - ") VALUES " - "($1, $2, $3, $4, $5);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_wads_out", - params); -} - - -/** - * Function called with wads_out_entries records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_wads_out_entries (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_uint64 ( - &td->details.wads_out_entries.wad_out_serial_id), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wads_out_entries.reserve_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wads_out_entries.purse_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wads_out_entries.h_contract), - GNUNET_PQ_query_param_timestamp ( - &td->details.wads_out_entries.purse_expiration), - GNUNET_PQ_query_param_timestamp ( - &td->details.wads_out_entries.merge_timestamp), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.wads_out_entries.amount_with_fee), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.wads_out_entries.wad_fee), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.wads_out_entries.deposit_fees), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wads_out_entries.reserve_sig), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wads_out_entries.purse_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_wad_out_entries", - "INSERT INTO wad_out_entries" - "(wad_out_entry_serial_id" - ",wad_out_serial_id" - ",reserve_pub" - ",purse_pub" - ",h_contract" - ",purse_expiration" - ",merge_timestamp" - ",amount_with_fee" - ",wad_fee" - ",deposit_fees" - ",reserve_sig" - ",purse_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_wads_out_entries", - params); -} - - -/** - * Function called with wads_in records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_wads_in (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type (&td->details.wads_in.wad_id), - GNUNET_PQ_query_param_string (td->details.wads_in.origin_exchange_url), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.wads_in.amount), - GNUNET_PQ_query_param_timestamp (&td->details.wads_in.arrival_time), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_wads_in", - "INSERT INTO wads_in" - "(wad_in_serial_id" - ",wad_id" - ",origin_exchange_url" - ",amount" - ",arrival_time" - ") VALUES " - "($1, $2, $3, $4, $5);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_wads_in", - params); -} - - -/** - * Function called with wads_in_entries records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_wads_in_entries (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wads_in_entries.reserve_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wads_in_entries.purse_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wads_in_entries.h_contract), - GNUNET_PQ_query_param_timestamp ( - &td->details.wads_in_entries.purse_expiration), - GNUNET_PQ_query_param_timestamp ( - &td->details.wads_in_entries.merge_timestamp), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.wads_in_entries.amount_with_fee), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.wads_in_entries.wad_fee), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.wads_in_entries.deposit_fees), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wads_in_entries.reserve_sig), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.wads_in_entries.purse_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_wad_in_entries", - "INSERT INTO wad_in_entries" - "(wad_in_entry_serial_id" - ",wad_in_serial_id" - ",reserve_pub" - ",purse_pub" - ",h_contract" - ",purse_expiration" - ",merge_timestamp" - ",amount_with_fee" - ",wad_fee" - ",deposit_fees" - ",reserve_sig" - ",purse_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_wads_in_entries", - params); -} - - -/** - * Function called with profit_drains records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_profit_drains (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.profit_drains.wtid), - GNUNET_PQ_query_param_string ( - td->details.profit_drains.account_section), - GNUNET_PQ_query_param_string ( - td->details.profit_drains.payto_uri.full_payto), - GNUNET_PQ_query_param_timestamp ( - &td->details.profit_drains.trigger_date), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.profit_drains.amount), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.profit_drains.master_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_profit_drains", - "INSERT INTO profit_drains" - "(profit_drain_serial_id" - ",wtid" - ",account_section" - ",payto_uri" - ",trigger_date" - ",amount" - ",master_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_profit_drains", - params); -} - - -/** - * Function called with aml_staff records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_aml_staff (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.aml_staff.decider_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.aml_staff.master_sig), - GNUNET_PQ_query_param_string ( - td->details.aml_staff.decider_name), - GNUNET_PQ_query_param_bool ( - td->details.aml_staff.is_active), - GNUNET_PQ_query_param_bool ( - td->details.aml_staff.read_only), - GNUNET_PQ_query_param_timestamp ( - &td->details.aml_staff.last_change), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_aml_staff", - "INSERT INTO aml_staff" - "(aml_staff_uuid" - ",decider_pub" - ",master_sig" - ",decider_name" - ",is_active" - ",read_only" - ",last_change" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_aml_staff", - params); -} - - -/** - * Function called with kyc_attributes records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_kyc_attributes (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.kyc_attributes.h_payto), - GNUNET_PQ_query_param_uint64 ( - &td->details.kyc_attributes.legitimization_serial), - GNUNET_PQ_query_param_timestamp ( - &td->details.kyc_attributes.collection_time), - GNUNET_PQ_query_param_timestamp ( - &td->details.kyc_attributes.expiration_time), - GNUNET_PQ_query_param_uint64 ( - &td->details.kyc_attributes.trigger_outcome_serial), - GNUNET_PQ_query_param_fixed_size ( - &td->details.kyc_attributes.encrypted_attributes, - td->details.kyc_attributes.encrypted_attributes_size), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_kyc_attributes", - "INSERT INTO kyc_attributes" - "(kyc_attributes_serial_id" - ",h_payto" - ",legitimization_serial" - ",collection_time" - ",expiration_time" - ",trigger_outcome_serial" - ",encrypted_attributes" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_kyc_attributes", - params); -} - - -/** - * Function called with aml_history records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_aml_history (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.aml_history.h_payto), - GNUNET_PQ_query_param_uint64 ( - &td->details.aml_history.outcome_serial_id), - GNUNET_PQ_query_param_string ( - td->details.aml_history.justification), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.aml_history.decider_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.aml_history.decider_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_aml_history", - "INSERT INTO aml_history" - "(aml_history_serial_id" - ",h_payto" - ",outcome_serial_id" - ",justification" - ",decider_pub" - ",decider_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_aml_history", - params); -} - - -/** - * Function called with kyc_event records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_kyc_events (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_timestamp ( - &td->details.kyc_events.event_timestamp), - GNUNET_PQ_query_param_string ( - td->details.kyc_events.event_type), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_kyc_events", - "INSERT INTO kyc_events" - "(kyc_event_serial_id" - ",event_timestamp" - ",event_type" - ") VALUES " - "($1, $2, $3);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_kyc_events", - params); -} - - -/** - * Function called with purse_deletion records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_purse_deletion (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.purse_deletion.purse_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.purse_deletion.purse_sig), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_into_table_purse_deletion", - "INSERT INTO purse_deletion" - "(purse_deletion_serial_id" - ",purse_pub" - ",purse_sig" - ") VALUES " - "($1, $2, $3);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_purse_deletion", - params); -} - - -/** - * Function called with withdraw records to insert into table. - * - * @param pg plugin context - * @param td record to insert - */ -static enum GNUNET_DB_QueryStatus -irbt_cb_table_withdraw ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_TableData *td) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&td->serial), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.withdraw.planchets_h), - GNUNET_PQ_query_param_timestamp ( - &td->details.withdraw.execution_date), - TALER_PQ_query_param_amount ( - pg->conn, - &td->details.withdraw.amount_with_fee), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.withdraw.reserve_pub), - GNUNET_PQ_query_param_auto_from_type ( - &td->details.withdraw.reserve_sig), - td->details.withdraw.age_proof_required - ? GNUNET_PQ_query_param_uint16 ( - &td->details.withdraw.max_age) - : GNUNET_PQ_query_param_null (), - td->details.withdraw.age_proof_required - ? GNUNET_PQ_query_param_uint16 ( - &td->details.withdraw.noreveal_index) - : GNUNET_PQ_query_param_null (), - td->details.withdraw.age_proof_required - ? GNUNET_PQ_query_param_auto_from_type ( - &td->details.withdraw.selected_h) - : GNUNET_PQ_query_param_null (), - td->details.withdraw.no_blinding_seed - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type ( - &td->details.withdraw.blinding_seed), - (0 < td->details.withdraw.num_cs_r_values) - ? TALER_PQ_query_param_array_cs_r_pub ( - td->details.withdraw.num_cs_r_values, - td->details.withdraw.cs_r_values, - pg->conn) - : GNUNET_PQ_query_param_null (), - (0 < td->details.withdraw.num_cs_r_values) - ? GNUNET_PQ_query_param_uint64 ( - &td->details.withdraw.cs_r_choices) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_array_uint64 ( - td->details.withdraw.num_coins, - td->details.withdraw.denom_serials, - pg->conn), - TALER_PQ_query_param_array_blinded_denom_sig ( - td->details.withdraw.num_coins, - td->details.withdraw.denom_sigs, - pg->conn), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "insert_into_table_withdraw", - "INSERT INTO withdraw" - "(withdraw_id" - ",planchets_h" - ",execution_date" - ",amount_with_fee" - ",reserve_pub" - ",reserve_sig" - ",max_age" - ",noreveal_index" - ",selected_h" - ",blinding_seed" - ",cs_r_values" - ",cs_r_choices" - ",denom_serials" - ",denom_sigs" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14);"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_withdraw", - params); - GNUNET_PQ_cleanup_query_params_closures (params); - return qs; -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_records_by_table (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const struct - TALER_EXCHANGEDB_TableData *td) -{ - InsertRecordCallback rh = NULL; - - switch (td->table) - { - case TALER_EXCHANGEDB_RT_DENOMINATIONS: - rh = &irbt_cb_table_denominations; - break; - case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS: - rh = &irbt_cb_table_denomination_revocations; - break; - case TALER_EXCHANGEDB_RT_WIRE_TARGETS: - rh = &irbt_cb_table_wire_targets; - break; - case TALER_EXCHANGEDB_RT_KYC_TARGETS: - rh = &irbt_cb_table_kyc_targets; - break; - case TALER_EXCHANGEDB_RT_RESERVES: - rh = &irbt_cb_table_reserves; - break; - case TALER_EXCHANGEDB_RT_RESERVES_IN: - rh = &irbt_cb_table_reserves_in; - break; - case TALER_EXCHANGEDB_RT_KYCAUTHS_IN: - rh = &irbt_cb_table_kycauths_in; - break; - case TALER_EXCHANGEDB_RT_RESERVES_CLOSE: - rh = &irbt_cb_table_reserves_close; - break; - case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS: - rh = &irbt_cb_table_reserves_open_requests; - break; - case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS: - rh = &irbt_cb_table_reserves_open_deposits; - break; - case TALER_EXCHANGEDB_RT_AUDITORS: - rh = &irbt_cb_table_auditors; - break; - case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS: - rh = &irbt_cb_table_auditor_denom_sigs; - break; - case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS: - rh = &irbt_cb_table_exchange_sign_keys; - break; - case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS: - rh = &irbt_cb_table_signkey_revocations; - break; - case TALER_EXCHANGEDB_RT_KNOWN_COINS: - rh = &irbt_cb_table_known_coins; - break; - case TALER_EXCHANGEDB_RT_REFRESH: - rh = &irbt_cb_table_refresh; - break; - case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS: - rh = &irbt_cb_table_batch_deposits; - break; - case TALER_EXCHANGEDB_RT_COIN_DEPOSITS: - rh = &irbt_cb_table_coin_deposits; - break; - case TALER_EXCHANGEDB_RT_REFUNDS: - rh = &irbt_cb_table_refunds; - break; - case TALER_EXCHANGEDB_RT_WIRE_OUT: - rh = &irbt_cb_table_wire_out; - break; - case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING: - rh = &irbt_cb_table_aggregation_tracking; - break; - case TALER_EXCHANGEDB_RT_WIRE_FEE: - rh = &irbt_cb_table_wire_fee; - break; - case TALER_EXCHANGEDB_RT_GLOBAL_FEE: - rh = &irbt_cb_table_global_fee; - break; - case TALER_EXCHANGEDB_RT_RECOUP: - rh = &irbt_cb_table_recoup; - break; - case TALER_EXCHANGEDB_RT_RECOUP_REFRESH: - rh = &irbt_cb_table_recoup_refresh; - break; - case TALER_EXCHANGEDB_RT_EXTENSIONS: - rh = &irbt_cb_table_extensions; - break; - case TALER_EXCHANGEDB_RT_POLICY_DETAILS: - rh = &irbt_cb_table_policy_details; - break; - case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS: - rh = &irbt_cb_table_policy_fulfillments; - break; - case TALER_EXCHANGEDB_RT_PURSE_REQUESTS: - rh = &irbt_cb_table_purse_requests; - break; - case TALER_EXCHANGEDB_RT_PURSE_DECISION: - rh = &irbt_cb_table_purse_decision; - break; - case TALER_EXCHANGEDB_RT_PURSE_MERGES: - rh = &irbt_cb_table_purse_merges; - break; - case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS: - rh = &irbt_cb_table_purse_deposits; - break; - case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES: - rh = &irbt_cb_table_account_mergers; - break; - case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS: - rh = &irbt_cb_table_history_requests; - break; - case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS: - rh = &irbt_cb_table_close_requests; - break; - case TALER_EXCHANGEDB_RT_WADS_OUT: - rh = &irbt_cb_table_wads_out; - break; - case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES: - rh = &irbt_cb_table_wads_out_entries; - break; - case TALER_EXCHANGEDB_RT_WADS_IN: - rh = &irbt_cb_table_wads_in; - break; - case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES: - rh = &irbt_cb_table_wads_in_entries; - break; - case TALER_EXCHANGEDB_RT_PROFIT_DRAINS: - rh = &irbt_cb_table_profit_drains; - break; - case TALER_EXCHANGEDB_RT_AML_STAFF: - rh = &irbt_cb_table_aml_staff; - break; - case TALER_EXCHANGEDB_RT_PURSE_DELETION: - rh = &irbt_cb_table_purse_deletion; - break; - case TALER_EXCHANGEDB_RT_WITHDRAW: - rh = &irbt_cb_table_withdraw; - break; - case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES: - rh = &irbt_cb_table_legitimization_measures; - break; - case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES: - rh = &irbt_cb_table_legitimization_outcomes; - break; - case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES: - rh = &irbt_cb_table_legitimization_processes; - break; - case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES: - rh = &irbt_cb_table_kyc_attributes; - break; - case TALER_EXCHANGEDB_RT_AML_HISTORY: - rh = &irbt_cb_table_aml_history; - break; - case TALER_EXCHANGEDB_RT_KYC_EVENTS: - rh = &irbt_cb_table_kyc_events; - break; - } - if (NULL == rh) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - return rh (pg, - td); -} - - -/* end of pg_insert_records_by_table.c */ diff --git a/src/exchangedb/pg_insert_refund.c b/src/exchangedb/pg_insert_refund.c @@ -1,62 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2023 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/> - */ -/** - * @file exchangedb/pg_insert_refund.c - * @brief Implementation of the insert_refund function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_refund.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_refund (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_Refund *refund) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub), - GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub), - GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig), - GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms), - GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id), - TALER_PQ_query_param_amount (pg->conn, - &refund->details.refund_amount), - GNUNET_PQ_query_param_end - }; - - GNUNET_assert (GNUNET_YES == - TALER_amount_cmp_currency (&refund->details.refund_amount, - &refund->details.refund_fee)); - PREPARE (pg, - "insert_refund", - "INSERT INTO refunds " - "(coin_pub" - ",batch_deposit_serial_id" - ",merchant_sig" - ",rtransaction_id" - ",amount_with_fee" - ") SELECT $1, cdep.batch_deposit_serial_id, $3, $5, $6" - " FROM coin_deposits cdep" - " JOIN batch_deposits bdep USING (batch_deposit_serial_id)" - " WHERE coin_pub=$1" - " AND h_contract_terms=$4" - " AND merchant_pub=$2"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_refund", - params); -} diff --git a/src/exchangedb/pg_insert_reserve_closed.c b/src/exchangedb/pg_insert_reserve_closed.c @@ -1,109 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_insert_reserve_closed.c - * @brief Implementation of the insert_reserve_closed function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_reserve_closed.h" -#include "helper.h" -#include "taler/exchange-database/reserves_get.h" -#include "taler/exchange-database/reserves_update.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_reserve_closed ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct GNUNET_TIME_Timestamp execution_date, - const struct TALER_FullPayto receiver_account, - const struct TALER_WireTransferIdentifierRawP *wtid, - const struct TALER_Amount *amount_with_fee, - const struct TALER_Amount *closing_fee, - uint64_t close_request_row) -{ - struct TALER_EXCHANGEDB_Reserve reserve; - enum GNUNET_DB_QueryStatus qs; - struct TALER_FullPaytoHashP h_payto; - - TALER_full_payto_hash (receiver_account, - &h_payto); - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_timestamp (&execution_date), - GNUNET_PQ_query_param_auto_from_type (wtid), - GNUNET_PQ_query_param_auto_from_type (&h_payto), - TALER_PQ_query_param_amount (pg->conn, - amount_with_fee), - TALER_PQ_query_param_amount (pg->conn, - closing_fee), - GNUNET_PQ_query_param_uint64 (&close_request_row), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "reserves_close_insert", - "INSERT INTO reserves_close " - "(reserve_pub" - ",execution_date" - ",wtid" - ",wire_target_h_payto" - ",amount" - ",closing_fee" - ",close_request_row" - ") VALUES ($1, $2, $3, $4, $5, $6, $7);"); - - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "reserves_close_insert", - params); - } - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) - return qs; - - /* update reserve balance */ - reserve.pub = *reserve_pub; - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - (qs = TALER_EXCHANGEDB_reserves_get (pg, - &reserve))) - { - /* Existence should have been checked before we got here... */ - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) - qs = GNUNET_DB_STATUS_HARD_ERROR; - return qs; - } - { - enum TALER_AmountArithmeticResult ret; - - ret = TALER_amount_subtract (&reserve.balance, - &reserve.balance, - amount_with_fee); - if (ret < 0) - { - /* The reserve history was checked to make sure there is enough of a balance - left before we tried this; however, concurrent operations may have changed - the situation by now. We should re-try the transaction. */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Closing of reserve `%s' refused due to balance mismatch. Retrying.\n", - TALER_B2S (reserve_pub)); - return GNUNET_DB_STATUS_HARD_ERROR; - } - GNUNET_break (TALER_AAR_RESULT_ZERO == ret); - } - return TALER_EXCHANGEDB_reserves_update (pg, - &reserve); -} diff --git a/src/exchangedb/pg_insert_reserve_open_deposit.c b/src/exchangedb/pg_insert_reserve_open_deposit.c @@ -1,63 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_insert_reserve_open_deposit.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_reserve_open_deposit.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_reserve_open_deposit ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_CoinPublicInfo *cpi, - const struct TALER_CoinSpendSignatureP *coin_sig, - uint64_t known_coin_id, - const struct TALER_Amount *coin_total, - const struct TALER_ReserveSignatureP *reserve_sig, - const struct TALER_ReservePublicKeyP *reserve_pub, - bool *insufficient_funds) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&cpi->coin_pub), - GNUNET_PQ_query_param_uint64 (&known_coin_id), - GNUNET_PQ_query_param_auto_from_type (coin_sig), - GNUNET_PQ_query_param_auto_from_type (reserve_sig), - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - TALER_PQ_query_param_amount (pg->conn, - coin_total), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("out_insufficient_funds", - insufficient_funds), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "insert_reserve_open_deposit", - "SELECT " - " out_insufficient_funds" - " FROM exchange_do_reserve_open_deposit" - " ($1,$2,$3,$4,$5,$6);"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "insert_reserve_open_deposit", - params, - rs); -} diff --git a/src/exchangedb/pg_insert_sanction_list_hit.c b/src/exchangedb/pg_insert_sanction_list_hit.c @@ -1,90 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_insert_sanction_list_hit.c - * @brief Implementation of the insert_sanction_list_hit function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_sanction_list_hit.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_sanction_list_hit ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - bool to_investigate, - const json_t *new_rules, - const json_t *account_properties, - unsigned int num_events, - const char **events) -{ - struct GNUNET_TIME_Timestamp never - = GNUNET_TIME_UNIT_FOREVER_TS; - struct GNUNET_TIME_Timestamp now - = GNUNET_TIME_timestamp_get (); - struct TALER_EXCHANGEDB_KycCompletedEventP rep = { - .header.size = htons (sizeof (rep)), - .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), - .h_payto = *h_payto - }; - char *notify_s - = GNUNET_PQ_get_event_notify_channel (&rep.header); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_timestamp (&now), - GNUNET_PQ_query_param_timestamp (&never), - NULL != account_properties - ? TALER_PQ_query_param_json (account_properties) - : GNUNET_PQ_query_param_null (), - NULL != new_rules - ? TALER_PQ_query_param_json (new_rules) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_bool (to_investigate), - GNUNET_PQ_query_param_string (notify_s), - GNUNET_PQ_query_param_array_ptrs_string (num_events, - events, - pg->conn), - GNUNET_PQ_query_param_end - }; - uint64_t outcome_serial_id; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("outcome_serial_id", - &outcome_serial_id), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "do_insert_sanction_list_hit", - "SELECT" - " out_outcome_serial_id AS outcome_serial_id" - " FROM exchange_do_insert_sanction_list_hit" - "($1,$2,$3,$4::TEXT::JSONB,$5::TEXT::JSONB,$6,$7,$8);"); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Inserting LEGI OUTCOME from sanction list hit\n"); - qs = GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "do_insert_sanction_list_hit", - params, - rs); - (void) outcome_serial_id; - GNUNET_PQ_cleanup_query_params_closures (params); - GNUNET_free (notify_s); - GNUNET_PQ_event_do_poll (pg->conn); - return qs; -} diff --git a/src/exchangedb/pg_insert_signkey_revocation.c b/src/exchangedb/pg_insert_signkey_revocation.c @@ -1,49 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_signkey_revocation.c - * @brief Implementation of the insert_signkey_revocation function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_signkey_revocation.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_signkey_revocation ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_MasterSignatureP *master_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (exchange_pub), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_end - }; - - - PREPARE (pg, - "insert_signkey_revocation", - "INSERT INTO signkey_revocations " - "(esk_serial" - ",master_sig" - ") SELECT esk_serial, $2 " - " FROM exchange_sign_keys" - " WHERE exchange_pub=$1;"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_signkey_revocation", - params); -} diff --git a/src/exchangedb/pg_insert_successor_measure.c b/src/exchangedb/pg_insert_successor_measure.c @@ -1,84 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2023, 2024 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/> - */ -/** - * @file exchangedb/pg_insert_successor_measure.c - * @brief Implementation of the insert_succesor_measure function for Postgres - * @author Florian Dold - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_successor_measure.h" -#include "helper.h" -#include <gnunet/gnunet_pq_lib.h> - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_successor_measure ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - struct GNUNET_TIME_Timestamp decision_time, - const char *new_measure_name, - const json_t *jmeasures, - bool *unknown_account, - struct GNUNET_TIME_Timestamp *last_date) -{ - struct TALER_EXCHANGEDB_KycCompletedEventP rep = { - .header.size = htons (sizeof (rep)), - .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), - .h_payto = *h_payto - }; - /* We're reverting back to default rules => never expires.*/ - struct GNUNET_TIME_Timestamp expiration_time = { - .abs_time = GNUNET_TIME_UNIT_FOREVER_ABS, - }; - char *notify_s - = GNUNET_PQ_get_event_notify_channel (&rep.header); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_timestamp (&decision_time), - GNUNET_PQ_query_param_timestamp (&expiration_time), - NULL != new_measure_name - ? GNUNET_PQ_query_param_string (new_measure_name) - : GNUNET_PQ_query_param_null (), - NULL != jmeasures - ? TALER_PQ_query_param_json (jmeasures) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("out_account_unknown", - unknown_account), - GNUNET_PQ_result_spec_timestamp ("out_last_date", - last_date), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "do_insert_successor_measure", - "SELECT" - " out_account_unknown" - ",out_last_date" - ",out_legitimization_measure_serial_id" - " FROM exchange_do_insert_successor_measure" - "($1, $2, $3, $4, $5::TEXT::JSONB);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "do_insert_successor_measure", - params, - rs); - GNUNET_free (notify_s); - GNUNET_PQ_event_do_poll (pg->conn); - return qs; -} diff --git a/src/exchangedb/pg_insert_wire.c b/src/exchangedb/pg_insert_wire.c @@ -1,81 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2023, 2024 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/> - */ -/** - * @file exchangedb/pg_insert_wire.c - * @brief Implementation of the insert_wire function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_wire.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_insert_wire ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_FullPayto payto_uri, - const char *conversion_url, - const char *open_banking_gateway, - const char *wire_transfer_gateway, - const json_t *debit_restrictions, - const json_t *credit_restrictions, - struct GNUNET_TIME_Timestamp start_date, - const struct TALER_MasterSignatureP *master_sig, - const char *bank_label, - int64_t priority) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (payto_uri.full_payto), - NULL == conversion_url - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (conversion_url), - TALER_PQ_query_param_json (debit_restrictions), - TALER_PQ_query_param_json (credit_restrictions), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_timestamp (&start_date), - NULL == bank_label - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (bank_label), - GNUNET_PQ_query_param_int64 (&priority), - NULL == open_banking_gateway - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (open_banking_gateway), - NULL == wire_transfer_gateway - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (wire_transfer_gateway), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_wire", - "INSERT INTO wire_accounts " - "(payto_uri" - ",conversion_url" - ",debit_restrictions" - ",credit_restrictions" - ",master_sig" - ",is_active" - ",last_change" - ",bank_label" - ",priority" - ",open_banking_gateway" - ",wire_transfer_gateway" - ") VALUES " - "($1,$2,$3::TEXT::JSONB,$4::TEXT::JSONB,$5,true,$6,$7,$8,$9,$10);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_wire", - params); -} diff --git a/src/exchangedb/pg_insert_wire_fee.c b/src/exchangedb/pg_insert_wire_fee.c @@ -1,108 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_insert_wire_fee.c - * @brief Implementation of the insert_wire_fee function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/insert_wire_fee.h" -#include "helper.h" -#include "taler/exchange-database/get_wire_fee.h" - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_insert_wire_fee (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const char *type, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - const struct TALER_WireFeeSet *fees, - const struct TALER_MasterSignatureP * - master_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (type), - GNUNET_PQ_query_param_timestamp (&start_date), - GNUNET_PQ_query_param_timestamp (&end_date), - TALER_PQ_query_param_amount (pg->conn, - &fees->wire), - TALER_PQ_query_param_amount (pg->conn, - &fees->closing), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_end - }; - struct TALER_WireFeeSet wx; - struct TALER_MasterSignatureP sig; - struct GNUNET_TIME_Timestamp sd; - struct GNUNET_TIME_Timestamp ed; - enum GNUNET_DB_QueryStatus qs; - uint64_t rowid; - - qs = TALER_EXCHANGEDB_get_wire_fee (pg, - type, - start_date, - &rowid, - &sd, - &ed, - &wx, - &sig); - if (qs < 0) - return qs; - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) - { - if (0 != GNUNET_memcmp (&sig, - master_sig)) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if (0 != - TALER_wire_fee_set_cmp (fees, - &wx)) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if ( (GNUNET_TIME_timestamp_cmp (sd, - !=, - start_date)) || - (GNUNET_TIME_timestamp_cmp (ed, - !=, - end_date)) ) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - /* equal record already exists */ - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - - PREPARE (pg, - "insert_wire_fee", - "INSERT INTO wire_fee " - "(wire_method" - ",start_date" - ",end_date" - ",wire_fee" - ",closing_fee" - ",master_sig" - ") VALUES " - "($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_wire_fee", - params); -} diff --git a/src/exchangedb/pg_iterate_active_auditors.c b/src/exchangedb/pg_iterate_active_auditors.c @@ -1,120 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_iterate_active_auditors.c - * @brief Implementation of the iterate_active_auditors function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/iterate_active_auditors.h" -#include "helper.h" - - -/** - * Closure for #auditors_cb_helper() - */ -struct AuditorsIteratorContext -{ - /** - * Function to call with the results. - */ - TALER_EXCHANGEDB_AuditorsCallback cb; - - /** - * Closure to pass to @e cb - */ - void *cb_cls; - -}; - - -/** - * Helper function for #TALER_EXCHANGEDB_iterate_active_auditors(). - * Calls the callback with each auditor. - * - * @param cls a `struct SignkeysIteratorContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -auditors_cb_helper (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct AuditorsIteratorContext *dic = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_AuditorPublicKeyP auditor_pub; - char *auditor_url; - char *auditor_name; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("auditor_pub", - &auditor_pub), - GNUNET_PQ_result_spec_string ("auditor_url", - &auditor_url), - GNUNET_PQ_result_spec_string ("auditor_name", - &auditor_name), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - return; - } - dic->cb (dic->cb_cls, - &auditor_pub, - auditor_url, - auditor_name); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_iterate_active_auditors (struct - TALER_EXCHANGEDB_PostgresContext *pg, - TALER_EXCHANGEDB_AuditorsCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - struct AuditorsIteratorContext dic = { - .cb = cb, - .cb_cls = cb_cls, - }; - - PREPARE (pg, - "select_auditors", - "SELECT" - " auditor_pub" - ",auditor_url" - ",auditor_name" - " FROM auditors" - " WHERE" - " is_active;"); - - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "select_auditors", - params, - &auditors_cb_helper, - &dic); -} diff --git a/src/exchangedb/pg_iterate_active_signkeys.c b/src/exchangedb/pg_iterate_active_signkeys.c @@ -1,142 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_iterate_active_signkeys.c - * @brief Implementation of the iterate_active_signkeys function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/iterate_active_signkeys.h" -#include "helper.h" - - -/** - * Closure for #signkeys_cb_helper() - */ -struct SignkeysIteratorContext -{ - /** - * Function to call with the results. - */ - TALER_EXCHANGEDB_ActiveSignkeysCallback cb; - - /** - * Closure to pass to @e cb - */ - void *cb_cls; - -}; - - -/** - * Helper function for #TALER_EXCHANGEDB_iterate_active_signkeys(). - * Calls the callback with each signkey. - * - * @param cls a `struct SignkeysIteratorContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -signkeys_cb_helper (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct SignkeysIteratorContext *dic = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_SignkeyMetaData meta; - struct TALER_ExchangePublicKeyP exchange_pub; - struct TALER_MasterSignatureP master_sig; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &master_sig), - GNUNET_PQ_result_spec_auto_from_type ("exchange_pub", - &exchange_pub), - GNUNET_PQ_result_spec_timestamp ("valid_from", - &meta.start), - GNUNET_PQ_result_spec_timestamp ("expire_sign", - &meta.expire_sign), - GNUNET_PQ_result_spec_timestamp ("expire_legal", - &meta.expire_legal), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - return; - } - dic->cb (dic->cb_cls, - &exchange_pub, - &meta, - &master_sig); - } -} - - -/** - * Function called to invoke @a cb on every non-revoked exchange signing key - * that has been signed by the master key. Revoked and (for signing!) - * expired keys are skipped. Runs in its own read-only transaction. - * - * @param pg the database context - * @param cb function to call on each signing key - * @param cb_cls closure for @a cb - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_iterate_active_signkeys (struct - TALER_EXCHANGEDB_PostgresContext *pg, - TALER_EXCHANGEDB_ActiveSignkeysCallback - cb, - void *cb_cls) -{ - struct GNUNET_TIME_Absolute now = {0}; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_end - }; - struct SignkeysIteratorContext dic = { - .cb = cb, - .cb_cls = cb_cls, - }; - - PREPARE (pg, - "select_signkeys", - "SELECT" - " master_sig" - ",exchange_pub" - ",valid_from" - ",expire_sign" - ",expire_legal" - " FROM exchange_sign_keys esk" - " WHERE" - " expire_sign > $1" - " AND NOT EXISTS " - " (SELECT esk_serial " - " FROM signkey_revocations skr" - " WHERE esk.esk_serial = skr.esk_serial);"); - now = GNUNET_TIME_absolute_get (); - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "select_signkeys", - params, - &signkeys_cb_helper, - &dic); -} diff --git a/src/exchangedb/pg_iterate_auditor_denominations.c b/src/exchangedb/pg_iterate_auditor_denominations.c @@ -1,117 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_iterate_auditor_denominations.c - * @brief Implementation of the iterate_auditor_denominations function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/iterate_auditor_denominations.h" -#include "helper.h" - -/** - * Closure for #auditor_denoms_cb_helper() - */ -struct AuditorDenomsIteratorContext -{ - /** - * Function to call with the results. - */ - TALER_EXCHANGEDB_AuditorDenominationsCallback cb; - - /** - * Closure to pass to @e cb - */ - void *cb_cls; -}; - - -/** - * Helper function for #TALER_EXCHANGEDB_iterate_auditor_denominations(). - * Calls the callback with each auditor and denomination pair. - * - * @param cls a `struct AuditorDenomsIteratorContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -auditor_denoms_cb_helper (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct AuditorDenomsIteratorContext *dic = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_AuditorPublicKeyP auditor_pub; - struct TALER_DenominationHashP h_denom_pub; - struct TALER_AuditorSignatureP auditor_sig; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("auditor_pub", - &auditor_pub), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &h_denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("auditor_sig", - &auditor_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - return; - } - dic->cb (dic->cb_cls, - &auditor_pub, - &h_denom_pub, - &auditor_sig); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_iterate_auditor_denominations ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - TALER_EXCHANGEDB_AuditorDenominationsCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - struct AuditorDenomsIteratorContext dic = { - .cb = cb, - .cb_cls = cb_cls, - }; - /* Used in #postgres_iterate_auditor_denominations() */ - PREPARE (pg, - "select_auditor_denoms", - "SELECT" - " auditors.auditor_pub" - ",denominations.denom_pub_hash" - ",auditor_denom_sigs.auditor_sig" - " FROM auditor_denom_sigs" - " JOIN auditors USING (auditor_uuid)" - " JOIN denominations USING (denominations_serial)" - " WHERE auditors.is_active;"); - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "select_auditor_denoms", - params, - &auditor_denoms_cb_helper, - &dic); -} diff --git a/src/exchangedb/pg_iterate_denomination_info.c b/src/exchangedb/pg_iterate_denomination_info.c @@ -1,185 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_iterate_denomination_info.c - * @brief Implementation of the iterate_denomination_info function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/iterate_denomination_info.h" -#include "helper.h" - - -/** - * Closure for #domination_cb_helper() - */ -struct DenomIteratorContext -{ - /** - * Function to call with the results. - */ - TALER_EXCHANGEDB_DenominationCallback cb; - - /** - * Closure to pass to @e cb - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; -}; - - -/** - * Helper function for #TALER_EXCHANGEDB_iterate_denomination_info(). - * Calls the callback with each denomination key. - * - * @param cls a `struct DenomIteratorContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -domination_cb_helper (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct DenomIteratorContext *dic = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = dic->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_DenominationKeyInformation issue; - struct TALER_DenominationPublicKey denom_pub; - struct TALER_DenominationHashP denom_hash; - uint64_t denom_serial; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("denominations_serial", - &denom_serial), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &issue.signature), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &denom_hash), - GNUNET_PQ_result_spec_timestamp ("valid_from", - &issue.start), - GNUNET_PQ_result_spec_timestamp ("expire_withdraw", - &issue.expire_withdraw), - GNUNET_PQ_result_spec_timestamp ("expire_deposit", - &issue.expire_deposit), - GNUNET_PQ_result_spec_timestamp ("expire_legal", - &issue.expire_legal), - TALER_PQ_RESULT_SPEC_AMOUNT ("coin", - &issue.value), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", - &issue.fees.withdraw), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &issue.fees.deposit), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", - &issue.fees.refresh), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", - &issue.fees.refund), - TALER_PQ_result_spec_denom_pub ("denom_pub", - &denom_pub), - GNUNET_PQ_result_spec_uint32 ("age_mask", - &issue.age_mask.bits), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - return; - } - - /* Unfortunately we have to carry the age mask in both, the - * TALER_DenominationPublicKey and - * TALER_EXCHANGEDB_DenominationKeyInformation at different times. - * Here we use _both_ so let's make sure the values are the same. */ - denom_pub.age_mask = issue.age_mask; - TALER_denom_pub_hash (&denom_pub, - &issue.denom_hash); - if (0 != - GNUNET_memcmp (&issue.denom_hash, - &denom_hash)) - { - GNUNET_break (0); - } - else - { - dic->cb (dic->cb_cls, - denom_serial, - &denom_pub, - &issue); - } - TALER_denom_pub_free (&denom_pub); - } -} - - -/** - * Fetch information about all known denomination keys. - * - * @param pg the database context - * @param cb function to call on each denomination key - * @param cb_cls closure for @a cb - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_iterate_denomination_info (struct - TALER_EXCHANGEDB_PostgresContext *pg - , - TALER_EXCHANGEDB_DenominationCallback - cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - struct DenomIteratorContext dic = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg - }; - - PREPARE (pg, - "denomination_iterate", - "SELECT" - " denominations_serial" - ",master_sig" - ",denom_pub_hash" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin" /* value of this denom */ - ",fee_withdraw" - ",fee_deposit" - ",fee_refresh" - ",fee_refund" - ",denom_pub" - ",age_mask" - " FROM denominations;"); - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "denomination_iterate", - params, - &domination_cb_helper, - &dic); -} diff --git a/src/exchangedb/pg_iterate_denominations.c b/src/exchangedb/pg_iterate_denominations.c @@ -1,175 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_iterate_denominations.c - * @brief Implementation of the iterate_denominations function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/iterate_denominations.h" -#include "helper.h" - - -/** - * Closure for #dominations_cb_helper() - */ -struct DenomsIteratorContext -{ - /** - * Function to call with the results. - */ - TALER_EXCHANGEDB_DenominationsCallback cb; - - /** - * Closure to pass to @e cb - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; -}; - - -/** - * Helper function for #TALER_EXCHANGEDB_iterate_denominations(). - * Calls the callback with each denomination key. - * - * @param cls a `struct DenomsIteratorContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -dominations_cb_helper (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct DenomsIteratorContext *dic = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = dic->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0}; - struct TALER_DenominationPublicKey denom_pub = {0}; - struct TALER_MasterSignatureP master_sig = {0}; - struct TALER_DenominationHashP h_denom_pub = {0}; - bool revoked; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("denominations_serial", - &meta.serial), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &master_sig), - GNUNET_PQ_result_spec_bool ("revoked", - &revoked), - GNUNET_PQ_result_spec_timestamp ("valid_from", - &meta.start), - GNUNET_PQ_result_spec_timestamp ("expire_withdraw", - &meta.expire_withdraw), - GNUNET_PQ_result_spec_timestamp ("expire_deposit", - &meta.expire_deposit), - GNUNET_PQ_result_spec_timestamp ("expire_legal", - &meta.expire_legal), - TALER_PQ_RESULT_SPEC_AMOUNT ("coin", - &meta.value), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", - &meta.fees.withdraw), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &meta.fees.deposit), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", - &meta.fees.refresh), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", - &meta.fees.refund), - TALER_PQ_result_spec_denom_pub ("denom_pub", - &denom_pub), - GNUNET_PQ_result_spec_uint32 ("age_mask", - &meta.age_mask.bits), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - return; - } - - /* make sure the mask information is the same */ - denom_pub.age_mask = meta.age_mask; - - TALER_denom_pub_hash (&denom_pub, - &h_denom_pub); - dic->cb (dic->cb_cls, - &denom_pub, - &h_denom_pub, - &meta, - &master_sig, - revoked); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_iterate_denominations (struct - TALER_EXCHANGEDB_PostgresContext *pg, - TALER_EXCHANGEDB_DenominationsCallback - cb, - void *cb_cls) -{ - struct GNUNET_TIME_Absolute now - = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_end - }; - struct DenomsIteratorContext dic = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg - }; - - PREPARE (pg, - "select_denominations", - "SELECT" - " denominations_serial" - ",denominations.master_sig" - ",denom_revocations_serial_id IS NOT NULL AS revoked" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin" /* value of this denom */ - ",fee_withdraw" - ",fee_deposit" - ",fee_refresh" - ",fee_refund" - ",denom_type" - ",age_mask" - ",denom_pub" - " FROM denominations" - " LEFT JOIN " - " denomination_revocations USING (denominations_serial)" - " WHERE expire_deposit > $1;"); - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "select_denominations", - params, - &dominations_cb_helper, - &dic); -} diff --git a/src/exchangedb/pg_iterate_kyc_reference.c b/src/exchangedb/pg_iterate_kyc_reference.c @@ -1,126 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_iterate_kyc_reference.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/iterate_kyc_reference.h" -#include "helper.h" - - -/** - * Closure for #iterate_kyc_reference_cb() - */ -struct IteratorContext -{ - /** - * Function to call with the results. - */ - TALER_EXCHANGEDB_LegitimizationProcessCallback cb; - - /** - * Closure to pass to @e cb - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; -}; - - -/** - * Helper function for #TALER_EXCHANGEDB_iterate_kyc_reference(). - * Calls the callback with each denomination key. - * - * @param cls a `struct IteratorContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -iterate_kyc_reference_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct IteratorContext *ic = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - char *kyc_provider_name_name; - char *provider_user_id; - char *legitimization_id; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("provider_name", - &kyc_provider_name_name), - GNUNET_PQ_result_spec_string ("provider_user_id", - &provider_user_id), - GNUNET_PQ_result_spec_string ("provider_legitimization_id", - &legitimization_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - return; - } - ic->cb (ic->cb_cls, - kyc_provider_name_name, - provider_user_id, - legitimization_id); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_iterate_kyc_reference ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - TALER_EXCHANGEDB_LegitimizationProcessCallback lpc, - void *lpc_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_end - }; - struct IteratorContext ic = { - .cb = lpc, - .cb_cls = lpc_cls, - .pg = pg - }; - - PREPARE (pg, - "iterate_kyc_reference", - "SELECT " - " provider_name" - ",provider_user_id" - ",provider_legitimization_id" - " FROM legitimization_processes" - " WHERE h_payto=$1;"); - return GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "iterate_kyc_reference", - params, - &iterate_kyc_reference_cb, - &ic); -} diff --git a/src/exchangedb/pg_iterate_reserve_close_info.c b/src/exchangedb/pg_iterate_reserve_close_info.c @@ -1,127 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_iterate_reserve_close_info.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/iterate_reserve_close_info.h" -#include "helper.h" - -/** - * Closure for #iterate_reserve_close_info_cb() - */ -struct IteratorContext -{ - /** - * Function to call with the results. - */ - TALER_KYCLOGIC_KycAmountCallback cb; - - /** - * Closure to pass to @e cb - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; -}; - - -/** - * Helper function for #TALER_EXCHANGEDB_iterate_reserve_close_info(). - * Calls the callback with each denomination key. - * - * @param cls a `struct IteratorContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -iterate_reserve_close_info_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct IteratorContext *ic = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ic->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_Amount amount; - struct GNUNET_TIME_Absolute ts; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_absolute_time ("execution_date", - &ts), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - return; - } - ic->cb (ic->cb_cls, - &amount, - ts); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_iterate_reserve_close_info ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - struct GNUNET_TIME_Absolute time_limit, - TALER_KYCLOGIC_KycAmountCallback kac, - void *kac_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_absolute_time (&time_limit), - GNUNET_PQ_query_param_end - }; - struct IteratorContext ic = { - .cb = kac, - .cb_cls = kac_cls, - .pg = pg - }; - - PREPARE (pg, - "iterate_reserve_close_info", - "SELECT amount" - " ,execution_date" - " FROM reserves_close" - " WHERE wire_target_h_payto IN (" - " SELECT wire_target_h_payto" - " FROM wire_targets" - " WHERE h_normalized_payto=$1" - " )" - " AND execution_date >= $2" - " ORDER BY execution_date DESC"); - return GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "iterate_reserve_close_info", - params, - &iterate_reserve_close_info_cb, - &ic); -} diff --git a/src/exchangedb/pg_kyc_provider_account_lookup.c b/src/exchangedb/pg_kyc_provider_account_lookup.c @@ -1,66 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2025 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/> - */ -/** - * @file exchangedb/pg_kyc_provider_account_lookup.c - * @brief Implementation of the kyc_provider_account_lookup function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/kyc_provider_account_lookup.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_kyc_provider_account_lookup ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *provider_name, - const char *provider_legitimization_id, - struct TALER_NormalizedPaytoHashP *h_payto, - bool *is_wallet, - uint64_t *process_row) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (provider_legitimization_id), - GNUNET_PQ_query_param_string (provider_name), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("h_payto", - h_payto), - GNUNET_PQ_result_spec_bool ("is_wallet", - is_wallet), - GNUNET_PQ_result_spec_uint64 ("legitimization_process_serial_id", - process_row), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "get_wire_target_by_legitimization_id", - "SELECT " - " lp.h_payto" - ",kt.is_wallet" - ",lp.legitimization_process_serial_id" - " FROM legitimization_processes lp" - " JOIN kyc_targets kt" - " ON (lp.h_payto = kt.h_normalized_payto)" - " WHERE provider_legitimization_id=$1" - " AND provider_name=$2;"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "get_wire_target_by_legitimization_id", - params, - rs); -} diff --git a/src/exchangedb/pg_kycauth_in_insert.c b/src/exchangedb/pg_kycauth_in_insert.c @@ -1,78 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_kycauth_in_insert.c - * @brief Implementation of the kycauth_in_insert function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/kycauth_in_insert.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_kycauth_in_insert ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const union TALER_AccountPublicKeyP *account_pub, - const struct TALER_Amount *credit_amount, - struct GNUNET_TIME_Timestamp execution_date, - const struct TALER_FullPayto debit_account_uri, - const char *section_name, - uint64_t serial_id) -{ - struct TALER_NormalizedPaytoHashP h_normalized_payto; - struct TALER_FullPaytoHashP h_full_payto; - - TALER_full_payto_hash (debit_account_uri, - &h_full_payto); - TALER_full_payto_normalize_and_hash (debit_account_uri, - &h_normalized_payto); - { - struct TALER_EXCHANGEDB_KycCompletedEventP rep = { - .header.size = htons (sizeof (rep)), - .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), - .h_payto = h_normalized_payto - }; - char *notify_s - = GNUNET_PQ_get_event_notify_channel (&rep.header); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (account_pub), - GNUNET_PQ_query_param_uint64 (&serial_id), - TALER_PQ_query_param_amount (pg->conn, - credit_amount), - GNUNET_PQ_query_param_auto_from_type (&h_full_payto), - GNUNET_PQ_query_param_auto_from_type (&h_normalized_payto), - GNUNET_PQ_query_param_string (debit_account_uri.full_payto), - GNUNET_PQ_query_param_string (section_name), - GNUNET_PQ_query_param_timestamp (&execution_date), - GNUNET_PQ_query_param_string (notify_s), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "kycauth_in_insert", - "CALL" - " exchange_do_kycauth_in_insert" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9);"); - qs = GNUNET_PQ_eval_prepared_non_select ( - pg->conn, - "kycauth_in_insert", - params); - GNUNET_free (notify_s); - return qs; - } -} diff --git a/src/exchangedb/pg_lookup_active_legitimization.c b/src/exchangedb/pg_lookup_active_legitimization.c @@ -1,62 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_lookup_pending_legitimization.c - * @brief Implementation of the lookup_pending_legitimization function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_active_legitimization.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_active_legitimization ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t legitimization_process_serial_id, - uint32_t *measure_index, - json_t **jmeasures) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&legitimization_process_serial_id), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_json ( - "jmeasures", - jmeasures), - GNUNET_PQ_result_spec_uint32 ( - "measure_index", - measure_index), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "lookup_active_legitimization", - "SELECT " - " lm.jmeasures::TEXT" - ",lp.measure_index" - " FROM legitimization_processes lp" - " JOIN legitimization_measures lm" - " USING (legitimization_measure_serial_id)" - " WHERE lp.legitimization_process_serial_id=$1" - " AND NOT lm.is_finished;"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "lookup_active_legitimization", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_aml_file_number.c b/src/exchangedb/pg_lookup_aml_file_number.c @@ -1,59 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_lookup_aml_file_number.c - * @brief Implementation of the lookup_aml_file_number function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_aml_file_number.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_aml_file_number ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - uint64_t *kyc_target_row, - bool *is_wallet) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "kyc_target_serial_id", - kyc_target_row), - GNUNET_PQ_result_spec_bool ( - "is_wallet", - is_wallet), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "lookup_aml_file_number", - "SELECT " - " kyc_target_serial_id" - ",is_wallet" - " FROM kyc_targets" - " WHERE h_normalized_payto=$1"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "lookup_aml_file_number", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_aml_history.c b/src/exchangedb/pg_lookup_aml_history.c @@ -1,200 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_lookup_aml_history.c - * @brief Implementation of the lookup_aml_history function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_aml_history.h" -#include "helper.h" - - -/** - * Closure for callbacks called from #TALER_EXCHANGEDB_lookup_aml_history() - */ -struct AmlHistoryContext -{ - - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_AmlHistoryCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to 'true' if the transaction failed. - */ - bool failed; - -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct AmlHistoryContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -handle_aml_entry (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct AmlHistoryContext *ahc = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - uint64_t outcome_serial_id; - struct GNUNET_TIME_Timestamp decision_time; - char *justification; - struct TALER_AmlOfficerPublicKeyP decider_pub; - json_t *jproperties; - json_t *jnew_rules = NULL; - bool to_investigate; - bool is_active; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("outcome_serial_id", - &outcome_serial_id), - GNUNET_PQ_result_spec_timestamp ("decision_time", - &decision_time), - GNUNET_PQ_result_spec_string ("justification", - &justification), - GNUNET_PQ_result_spec_auto_from_type ("decider_pub", - &decider_pub), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ("jproperties", - &jproperties), - NULL), - TALER_PQ_result_spec_json ("jnew_rules", - &jnew_rules), - GNUNET_PQ_result_spec_bool ("to_investigate", - &to_investigate), - GNUNET_PQ_result_spec_bool ("is_active", - &is_active), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ahc->failed = true; - return; - } - ahc->cb (ahc->cb_cls, - outcome_serial_id, - decision_time, - justification, - &decider_pub, - jproperties, - jnew_rules, - to_investigate, - is_active); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_aml_history ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - uint64_t offset, - int64_t limit, - TALER_EXCHANGEDB_AmlHistoryCallback cb, - void *cb_cls) -{ - struct AmlHistoryContext ahc = { - .pg = pg, - .cb = cb, - .cb_cls = cb_cls - }; - uint64_t ulimit = (limit < 0) ? (-limit) : limit; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_uint64 (&offset), - GNUNET_PQ_query_param_uint64 (&ulimit), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "lookup_aml_history_desc", - "SELECT" - " lo.decision_time" - ",lo.outcome_serial_id" - ",ah.justification" - ",ah.decider_pub" - ",lo.jproperties::TEXT" - ",lo.jnew_rules::TEXT" - ",lo.to_investigate" - ",lo.is_active" - " FROM aml_history ah" - " JOIN legitimization_outcomes lo" - " USING (outcome_serial_id)" - " WHERE ah.h_payto=$1" - " AND lo.outcome_serial_id < $2" - " ORDER BY outcome_serial_id DESC" - " LIMIT $3;"); - PREPARE (pg, - "lookup_aml_history_asc", - "SELECT" - " lo.decision_time" - ",lo.outcome_serial_id" - ",ah.justification" - ",ah.decider_pub" - ",lo.jproperties::TEXT" - ",lo.jnew_rules::TEXT" - ",lo.to_investigate" - ",lo.is_active" - " FROM aml_history ah" - " JOIN legitimization_outcomes lo" - " USING (outcome_serial_id)" - " WHERE ah.h_payto=$1" - " AND lo.outcome_serial_id > $2" - " ORDER BY outcome_serial_id ASC" - " LIMIT $3;"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - (limit < 0) - ? "lookup_aml_history_desc" - : "lookup_aml_history_asc", - params, - &handle_aml_entry, - &ahc); - if (qs <= 0) - return qs; - if (ahc.failed) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - return qs; -} diff --git a/src/exchangedb/pg_lookup_aml_officer.c b/src/exchangedb/pg_lookup_aml_officer.c @@ -1,68 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_lookup_aml_officer.c - * @brief Implementation of the lookup_aml_officer function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_aml_officer.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_aml_officer ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_AmlOfficerPublicKeyP *decider_pub, - struct TALER_MasterSignatureP *master_sig, - char **decider_name, - bool *is_active, - bool *read_only, - struct GNUNET_TIME_Absolute *last_change) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (decider_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - master_sig), - GNUNET_PQ_result_spec_string ("decider_name", - decider_name), - GNUNET_PQ_result_spec_bool ("is_active", - is_active), - GNUNET_PQ_result_spec_bool ("read_only", - read_only), - GNUNET_PQ_result_spec_absolute_time ("last_change", - last_change), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "lookup_aml_officer", - "SELECT " - " master_sig" - ",decider_name" - ",is_active" - ",read_only" - ",last_change" - " FROM aml_staff" - " WHERE decider_pub=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "lookup_aml_officer", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_auditor_status.c b/src/exchangedb/pg_lookup_auditor_status.c @@ -1,57 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_lookup_auditor_status.c - * @brief Implementation of the lookup_auditor_status function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_auditor_status.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_auditor_status ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_AuditorPublicKeyP *auditor_pub, - char **auditor_url, - bool *enabled) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (auditor_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("auditor_url", - auditor_url), - GNUNET_PQ_result_spec_bool ("is_active", - enabled), - GNUNET_PQ_result_spec_end - }; - - /* Used in #postgres_lookup_auditor_status() */ - PREPARE (pg, - "lookup_auditor_status", - "SELECT" - " auditor_url" - ",is_active" - " FROM auditors" - " WHERE auditor_pub=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_auditor_status", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_auditor_timestamp.c b/src/exchangedb/pg_lookup_auditor_timestamp.c @@ -1,53 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_lookup_auditor_timestamp.c - * @brief Implementation of the lookup_auditor_timestamp function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_auditor_timestamp.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_auditor_timestamp ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_AuditorPublicKeyP *auditor_pub, - struct GNUNET_TIME_Timestamp *last_date) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (auditor_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("last_change", - last_date), - GNUNET_PQ_result_spec_end - }; - - /* Used in #postgres_lookup_auditor_timestamp() */ - PREPARE (pg, - "lookup_auditor_timestamp", - "SELECT" - " last_change" - " FROM auditors" - " WHERE auditor_pub=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_auditor_timestamp", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_completed_legitimization.c b/src/exchangedb/pg_lookup_completed_legitimization.c @@ -1,95 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_lookup_completed_legitimization.c - * @brief Implementation of the lookup_pending_legitimization function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_completed_legitimization.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_completed_legitimization ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t legitimization_measure_serial_id, - uint32_t measure_index, - struct TALER_AccountAccessTokenP *access_token, - struct TALER_NormalizedPaytoHashP *h_payto, - bool *is_wallet, - json_t **jmeasures, - bool *is_finished, - size_t *encrypted_attributes_len, - void **encrypted_attributes - ) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id), - GNUNET_PQ_query_param_uint32 (&measure_index), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_json ( - "jmeasures", - jmeasures), - GNUNET_PQ_result_spec_auto_from_type ( - "h_normalized_payto", - h_payto), - GNUNET_PQ_result_spec_auto_from_type ( - "access_token", - access_token), - GNUNET_PQ_result_spec_bool ( - "is_finished", - is_finished), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_variable_size ( - "encrypted_attributes", - encrypted_attributes, - encrypted_attributes_len), - NULL), - GNUNET_PQ_result_spec_bool ( - "is_wallet", - is_wallet), - GNUNET_PQ_result_spec_end - }; - - *encrypted_attributes_len = 0; - *encrypted_attributes = NULL; - PREPARE (pg, - "lookup_completed_legitimization", - "SELECT " - " lm.jmeasures::TEXT" - ",kt.h_normalized_payto" - ",kt.is_wallet" - ",lm.access_token" - ",lm.is_finished" - ",ka.encrypted_attributes" - " FROM legitimization_measures lm" - " JOIN kyc_targets kt" - " ON (lm.access_token = kt.access_token)" - " LEFT JOIN legitimization_processes lp" - " ON (lm.legitimization_measure_serial_id = lp.legitimization_measure_serial_id)" - " LEFT JOIN kyc_attributes ka" - " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)" - " WHERE lm.legitimization_measure_serial_id=$1" - " AND lp.measure_index=$2;"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "lookup_completed_legitimization", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_denomination_key.c b/src/exchangedb/pg_lookup_denomination_key.c @@ -1,79 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_lookup_denomination_key.c - * @brief Implementation of the lookup_denomination_key function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_denomination_key.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_denomination_key ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_DenominationHashP *h_denom_pub, - struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_denom_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("valid_from", - &meta->start), - GNUNET_PQ_result_spec_timestamp ("expire_withdraw", - &meta->expire_withdraw), - GNUNET_PQ_result_spec_timestamp ("expire_deposit", - &meta->expire_deposit), - GNUNET_PQ_result_spec_timestamp ("expire_legal", - &meta->expire_legal), - TALER_PQ_RESULT_SPEC_AMOUNT ("coin", - &meta->value), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", - &meta->fees.withdraw), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &meta->fees.deposit), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh", - &meta->fees.refresh), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund", - &meta->fees.refund), - GNUNET_PQ_result_spec_uint32 ("age_mask", - &meta->age_mask.bits), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "lookup_denomination_key", - "SELECT" - " valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin" - ",fee_withdraw" - ",fee_deposit" - ",fee_refresh" - ",fee_refund" - ",age_mask" - " FROM denominations" - " WHERE denom_pub_hash=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_denomination_key", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_global_fee_by_time.c b/src/exchangedb/pg_lookup_global_fee_by_time.c @@ -1,180 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_lookup_global_fee_by_time.c - * @brief Implementation of the lookup_global_fee_by_time function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_dbevents.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_global_fee_by_time.h" -#include "helper.h" - -/** - * Closure for #global_fee_by_time_helper() - */ -struct GlobalFeeLookupContext -{ - - /** - * Set to the wire fees. Set to invalid if fees conflict over - * the given time period. - */ - struct TALER_GlobalFeeSet *fees; - - /** - * Set to timeout of unmerged purses - */ - struct GNUNET_TIME_Relative *purse_timeout; - - /** - * Set to history expiration for reserves. - */ - struct GNUNET_TIME_Relative *history_expiration; - - /** - * Set to number of free purses per account. - */ - uint32_t *purse_account_limit; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; -}; - - -/** - * Helper function for #TALER_EXCHANGEDB_lookup_global_fee_by_time(). - * Calls the callback with each denomination key. - * - * @param cls a `struct GlobalFeeLookupContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -global_fee_by_time_helper (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct GlobalFeeLookupContext *wlc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = wlc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_GlobalFeeSet fs; - struct GNUNET_TIME_Relative purse_timeout; - struct GNUNET_TIME_Relative history_expiration; - uint32_t purse_account_limit; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee", - &fs.history), - TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee", - &fs.account), - TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", - &fs.purse), - GNUNET_PQ_result_spec_relative_time ("purse_timeout", - &purse_timeout), - GNUNET_PQ_result_spec_relative_time ("history_expiration", - &history_expiration), - GNUNET_PQ_result_spec_uint32 ("purse_account_limit", - &purse_account_limit), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - /* invalidate */ - memset (wlc->fees, - 0, - sizeof (struct TALER_GlobalFeeSet)); - return; - } - if (0 == i) - { - *wlc->fees = fs; - *wlc->purse_timeout = purse_timeout; - *wlc->history_expiration = history_expiration; - *wlc->purse_account_limit = purse_account_limit; - continue; - } - if ( (0 != - TALER_global_fee_set_cmp (&fs, - wlc->fees)) || - (purse_account_limit != *wlc->purse_account_limit) || - (GNUNET_TIME_relative_cmp (purse_timeout, - !=, - *wlc->purse_timeout)) || - (GNUNET_TIME_relative_cmp (history_expiration, - !=, - *wlc->history_expiration)) ) - { - /* invalidate */ - memset (wlc->fees, - 0, - sizeof (struct TALER_GlobalFeeSet)); - return; - } - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_global_fee_by_time ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - struct GNUNET_TIME_Timestamp start_time, - struct GNUNET_TIME_Timestamp end_time, - struct TALER_GlobalFeeSet *fees, - struct GNUNET_TIME_Relative *purse_timeout, - struct GNUNET_TIME_Relative *history_expiration, - uint32_t *purse_account_limit) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&start_time), - GNUNET_PQ_query_param_timestamp (&end_time), - GNUNET_PQ_query_param_end - }; - struct GlobalFeeLookupContext wlc = { - .fees = fees, - .purse_timeout = purse_timeout, - .history_expiration = history_expiration, - .purse_account_limit = purse_account_limit, - .pg = pg - }; - - PREPARE (pg, - "lookup_global_fee_by_time", - "SELECT" - " history_fee" - ",account_fee" - ",purse_fee" - ",purse_timeout" - ",history_expiration" - ",purse_account_limit" - " FROM global_fee" - " WHERE end_date > $1" - " AND start_date < $2;"); - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "lookup_global_fee_by_time", - params, - &global_fee_by_time_helper, - &wlc); -} diff --git a/src/exchangedb/pg_lookup_h_payto_by_access_token.c b/src/exchangedb/pg_lookup_h_payto_by_access_token.c @@ -1,59 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_lookup_h_payto_by_access_token.c - * @brief Implementation of the lookup_h_payto_by_access_token function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_h_payto_by_access_token.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_h_payto_by_access_token ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_AccountAccessTokenP *access_token, - struct TALER_NormalizedPaytoHashP *h_payto, - bool *is_wallet) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (access_token), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ( - "h_normalized_payto", - h_payto), - GNUNET_PQ_result_spec_bool ( - "is_wallet", - is_wallet), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "lookup_h_payto_by_access_token", - "SELECT " - " h_normalized_payto" - " ,is_wallet" - " FROM kyc_targets" - " WHERE (access_token = $1);"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "lookup_h_payto_by_access_token", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_kyc_history.c b/src/exchangedb/pg_lookup_kyc_history.c @@ -1,192 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_lookup_kyc_history.c - * @brief Implementation of the lookup_kyc_history function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_kyc_history.h" -#include "helper.h" - -/** - * Closure for callbacks called from #TALER_EXCHANGEDB_lookup_kyc_history() - */ -struct KycHistoryContext -{ - - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_KycHistoryCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to 'true' if the transaction failed. - */ - bool failed; - -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct KycHistoryContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -handle_kyc_entry (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct KycHistoryContext *khc = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - char *provider_name = NULL; - bool finished; - uint32_t error_code; - char *error_message = NULL; - char *provider_user_id = NULL; - char *provider_legitimization_id = NULL; - struct GNUNET_TIME_Timestamp collection_time; - struct GNUNET_TIME_Absolute expiration_time - = GNUNET_TIME_UNIT_ZERO_ABS; - void *encrypted_attributes; - size_t encrypted_attributes_len; - - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("provider_name", - &provider_name), - NULL), - GNUNET_PQ_result_spec_bool ("finished", - &finished), - GNUNET_PQ_result_spec_uint32 ("error_code", - &error_code), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("error_message", - &error_message), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("provider_user_id", - &provider_user_id), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("provider_legitimization_id", - &provider_legitimization_id), - NULL), - GNUNET_PQ_result_spec_timestamp ("collection_time", - &collection_time), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_absolute_time ("expiration_time", - &expiration_time), - NULL), - GNUNET_PQ_result_spec_variable_size ("encrypted_attributes", - &encrypted_attributes, - &encrypted_attributes_len), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - khc->failed = true; - return; - } - khc->cb (khc->cb_cls, - provider_name, - finished, - (enum TALER_ErrorCode) error_code, - error_message, - provider_user_id, - provider_legitimization_id, - collection_time, - expiration_time, - encrypted_attributes_len, - encrypted_attributes); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_kyc_history ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - TALER_EXCHANGEDB_KycHistoryCallback cb, - void *cb_cls) -{ - struct KycHistoryContext khc = { - .pg = pg, - .cb = cb, - .cb_cls = cb_cls - }; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "lookup_kyc_history", - "SELECT" - " lp.provider_name" - ",lp.finished" - ",lp.error_code" - ",lp.error_message" - ",lp.provider_user_id" - ",lp.provider_legitimization_id" - ",ka.collection_time" - ",ka.expiration_time" - ",ka.encrypted_attributes" - " FROM kyc_attributes ka" - " JOIN legitimization_processes lp" - " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)" - " WHERE ka.h_payto=$1" - " ORDER BY ka.collection_time DESC;"); - - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "lookup_kyc_history", - params, - &handle_kyc_entry, - &khc); - if (qs <= 0) - return qs; - if (khc.failed) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - return qs; -} diff --git a/src/exchangedb/pg_lookup_kyc_process_by_account.c b/src/exchangedb/pg_lookup_kyc_process_by_account.c @@ -1,90 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2025 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/> - */ -/** - * @file exchangedb/pg_lookup_kyc_process_by_account.c - * @brief Implementation of the lookup_kyc_process_by_account function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_kyc_process_by_account.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_kyc_process_by_account ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *provider_name, - const struct TALER_NormalizedPaytoHashP *h_payto, - uint64_t *process_row, - struct GNUNET_TIME_Absolute *expiration, - char **provider_account_id, - char **provider_legitimization_id, - bool *is_wallet) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_string (provider_name), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "legitimization_process_serial_id", - process_row), - GNUNET_PQ_result_spec_absolute_time ( - "expiration_time", - expiration), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ( - "provider_user_id", - provider_account_id), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ( - "provider_legitimization_id", - provider_legitimization_id), - NULL), - GNUNET_PQ_result_spec_bool ( - "is_wallet", - is_wallet), - GNUNET_PQ_result_spec_end - }; - - *provider_account_id = NULL; - *provider_legitimization_id = NULL; - PREPARE (pg, - "lookup_kyc_process_by_account", - "SELECT " - " lp.legitimization_process_serial_id" - ",lp.expiration_time" - ",lp.provider_user_id" - ",lp.provider_legitimization_id" - ",kt.is_wallet" - " FROM legitimization_processes lp" - " JOIN kyc_targets kt" - " ON (lp.h_payto = kt.h_normalized_payto)" - " WHERE h_payto=$1" - " AND provider_name=$2" - " AND NOT finished" - /* Note: there *should* only be one unfinished - match, so this is just to be safe(r): */ - " ORDER BY lp.expiration_time DESC" - " LIMIT 1;"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "lookup_kyc_process_by_account", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.c b/src/exchangedb/pg_lookup_kyc_requirement_by_row.c @@ -1,109 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_lookup_kyc_requirement_by_row.c - * @brief Implementation of the lookup_kyc_requirement_by_row function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_kyc_requirement_by_row.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_kyc_requirement_by_row ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - const union TALER_AccountPublicKeyP *account_pub, - enum GNUNET_GenericReturnValue *is_wallet, - struct TALER_AccountAccessTokenP *access_token, - uint64_t *rule_gen, - json_t **jrules, - bool *aml_review, - bool *kyc_required) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_auto_from_type (account_pub), - GNUNET_PQ_query_param_end - }; - bool bis_wallet; - bool bis_wallet_unknown; - bool not_found; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("access_token", - access_token), - NULL), - GNUNET_PQ_result_spec_allow_null ( - /* can be NULL due to LEFT JOIN */ - TALER_PQ_result_spec_json ("jrules", - jrules), - NULL), - GNUNET_PQ_result_spec_allow_null ( - /* can be NULL due to LEFT JOIN */ - GNUNET_PQ_result_spec_bool ("is_wallet", - &bis_wallet), - &bis_wallet_unknown), - GNUNET_PQ_result_spec_allow_null ( - /* can be NULL due to LEFT JOIN */ - GNUNET_PQ_result_spec_bool ("aml_review", - aml_review), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ("rule_gen", - rule_gen), - NULL), - GNUNET_PQ_result_spec_bool ("kyc_required", - kyc_required), - GNUNET_PQ_result_spec_bool ("not_found", - &not_found), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - *jrules = NULL; - *aml_review = false; - *is_wallet = GNUNET_SYSERR; - *rule_gen = 0; - memset (access_token, - 0, - sizeof (*access_token)); - PREPARE (pg, - "lookup_kyc_requirement_by_row", - "SELECT " - " out_access_token AS access_token" - ",out_jrules::TEXT AS jrules" - ",out_is_wallet AS is_wallet" - ",out_not_found AS not_found" - ",out_aml_review AS aml_review" - ",out_kyc_required AS kyc_required" - ",out_rule_gen AS rule_gen" - " FROM exchange_do_lookup_kyc_requirement_by_row" - " ($1, $2);"); - qs = GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "lookup_kyc_requirement_by_row", - params, - rs); - if (qs <= 0) - return qs; - if (! bis_wallet_unknown) - *is_wallet = (bis_wallet) ? GNUNET_YES : GNUNET_NO; - if (not_found) - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - return qs; -} diff --git a/src/exchangedb/pg_lookup_kyc_status_by_token.c b/src/exchangedb/pg_lookup_kyc_status_by_token.c @@ -1,61 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_lookup_kyc_status_by_token.c - * @brief Implementation of the lookup_kyc_status_by_token function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_kyc_status_by_token.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_kyc_status_by_token ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_AccountAccessTokenP *access_token, - uint64_t *row, - json_t **jmeasures) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (access_token), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "legitimization_measure_serial_id", - row), - TALER_PQ_result_spec_json ( - "jmeasures", - jmeasures), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "lookup_kyc_status_by_token", - "SELECT" - " legitimization_measure_serial_id" - ",jmeasures::TEXT" - " FROM legitimization_measures" - " WHERE access_token=$1" - " AND NOT is_finished" - " ORDER BY display_priority DESC" - " LIMIT 1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_kyc_status_by_token", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_pending_legitimization.c b/src/exchangedb/pg_lookup_pending_legitimization.c @@ -1,76 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024, 2025 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/> - */ -/** - * @file exchangedb/pg_lookup_pending_legitimization.c - * @brief Implementation of the lookup_pending_legitimization function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_pending_legitimization.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_pending_legitimization ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t legitimization_measure_serial_id, - struct TALER_AccountAccessTokenP *access_token, - struct TALER_NormalizedPaytoHashP *h_payto, - json_t **jmeasures, - bool *is_finished, - bool *is_wallet) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_json ( - "jmeasures", - jmeasures), - GNUNET_PQ_result_spec_auto_from_type ( - "h_normalized_payto", - h_payto), - GNUNET_PQ_result_spec_auto_from_type ( - "access_token", - access_token), - GNUNET_PQ_result_spec_bool ( - "is_finished", - is_finished), - GNUNET_PQ_result_spec_bool ( - "is_wallet", - is_wallet), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "lookup_pending_legitimization", - "SELECT " - " lm.jmeasures::TEXT" - ",kt.h_normalized_payto" - ",kt.is_wallet" - ",lm.access_token" - ",lm.is_finished" - " FROM legitimization_measures lm" - " JOIN kyc_targets kt" - " USING (access_token)" - " WHERE lm.legitimization_measure_serial_id=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "lookup_pending_legitimization", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_records_by_table.c b/src/exchangedb/pg_lookup_records_by_table.c @@ -1,3802 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2020-2025 Taler Systems SA - - GNUnet 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 Foundation, either version 3 of the License, - or (at your option) any later version. - - GNUnet 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/** - * @file exchangedb/pg_lookup_records_by_table.c - * @brief implementation of lookup_records_by_table - * @author Christian Grothoff - * @author Özgür Kesim - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_dbevents.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_records_by_table.h" -#include "helper.h" -#include <gnunet/gnunet_pq_lib.h> - - -/** - * Closure for callbacks used by #postgres_lookup_records_by_table. - */ -struct LookupRecordsByTableContext -{ - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Function to call with the results. - */ - TALER_EXCHANGEDB_ReplicationCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Set to true on errors. - */ - bool error; -}; - - -/** - * Function called with denominations table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_denominations (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_DENOMINATIONS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_uint32 ( - "denom_type", - &td.details.denominations.denom_type), - GNUNET_PQ_result_spec_uint32 ( - "age_mask", - &td.details.denominations.age_mask), - TALER_PQ_result_spec_denom_pub ( - "denom_pub", - &td.details.denominations.denom_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "master_sig", - &td.details.denominations.master_sig), - GNUNET_PQ_result_spec_timestamp ( - "valid_from", - &td.details.denominations.valid_from), - GNUNET_PQ_result_spec_timestamp ( - "expire_withdraw", - &td.details.denominations. - expire_withdraw), - GNUNET_PQ_result_spec_timestamp ( - "expire_deposit", - &td.details.denominations. - expire_deposit), - GNUNET_PQ_result_spec_timestamp ( - "expire_legal", - &td.details.denominations.expire_legal), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "coin", - &td.details.denominations.coin), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "fee_withdraw", - &td.details.denominations.fees.withdraw), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "fee_deposit", - &td.details.denominations.fees.deposit), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "fee_refresh", - &td.details.denominations.fees.refresh), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "fee_refund", - &td.details.denominations.fees.refund), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with denomination_revocations table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_denomination_revocations (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_uint64 ( - "denominations_serial", - &td.details.denomination_revocations.denominations_serial), - GNUNET_PQ_result_spec_auto_from_type ( - "master_sig", - &td.details.denomination_revocations.master_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with wire_targets table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_wire_targets (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_WIRE_TARGETS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_string ( - "payto_uri", - &td.details.wire_targets.full_payto_uri.full_payto), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with wire_targets table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_kyc_targets (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_KYC_TARGETS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "h_normalized_payto", - &td.details.kyc_targets.h_normalized_payto), - GNUNET_PQ_result_spec_auto_from_type ( - "access_token", - &td.details.kyc_targets.access_token), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ( - "target_pub", - &td.details.kyc_targets.target_pub), - &td.details.kyc_targets.no_account), - GNUNET_PQ_result_spec_bool ( - "is_wallet", - &td.details.kyc_targets.is_wallet), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with reserves table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_reserves (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_RESERVES - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &td.details.reserves.reserve_pub), - GNUNET_PQ_result_spec_timestamp ("expiration_date", - &td.details.reserves.expiration_date), - GNUNET_PQ_result_spec_timestamp ("gc_date", - &td.details.reserves.gc_date), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with reserves_in table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_reserves_in (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_RESERVES_IN - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_pub", - &td.details.reserves_in.reserve_pub), - GNUNET_PQ_result_spec_uint64 ( - "wire_reference", - &td.details.reserves_in.wire_reference), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "credit", - &td.details.reserves_in.credit), - GNUNET_PQ_result_spec_auto_from_type ( - "wire_source_h_payto", - &td.details.reserves_in.sender_account_h_payto), - GNUNET_PQ_result_spec_string ( - "exchange_account_section", - &td.details.reserves_in.exchange_account_section), - GNUNET_PQ_result_spec_timestamp ( - "execution_date", - &td.details.reserves_in.execution_date), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with kycauth_in table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_kycauth_in (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_KYCAUTHS_IN - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "account_pub", - &td.details.kycauth_in.account_pub), - GNUNET_PQ_result_spec_uint64 ( - "wire_reference", - &td.details.kycauth_in.wire_reference), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "credit", - &td.details.kycauth_in.credit), - GNUNET_PQ_result_spec_auto_from_type ( - "wire_source_h_payto", - &td.details.kycauth_in.sender_account_h_payto), - GNUNET_PQ_result_spec_string ( - "exchange_account_section", - &td.details.kycauth_in.exchange_account_section), - GNUNET_PQ_result_spec_timestamp ( - "execution_date", - &td.details.kycauth_in.execution_date), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with reserves_close table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_reserves_close (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_RESERVES_CLOSE - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_pub", - &td.details.reserves_close.reserve_pub), - GNUNET_PQ_result_spec_timestamp ( - "execution_date", - &td.details.reserves_close.execution_date), - GNUNET_PQ_result_spec_auto_from_type ( - "wtid", - &td.details.reserves_close.wtid), - GNUNET_PQ_result_spec_auto_from_type ( - "wire_target_h_payto", - &td.details.reserves_close.sender_account_h_payto), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount", - &td.details.reserves_close.amount), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "closing_fee", - &td.details.reserves_close.closing_fee), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with reserves_open_requests table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_reserves_open_requests (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_pub", - &td.details.reserves_open_requests.reserve_pub), - GNUNET_PQ_result_spec_timestamp ( - "request_timestamp", - &td.details.reserves_open_requests.request_timestamp), - GNUNET_PQ_result_spec_timestamp ( - "expiration_date", - &td.details.reserves_open_requests.expiration_date), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_sig", - &td.details.reserves_open_requests.reserve_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "reserve_payment", - &td.details.reserves_open_requests.reserve_payment), - GNUNET_PQ_result_spec_uint32 ( - "requested_purse_limit", - &td.details.reserves_open_requests.requested_purse_limit), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with reserves_open_deposits table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_reserves_open_deposits (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_sig", - &td.details.reserves_open_deposits.reserve_sig), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_pub", - &td.details.reserves_open_deposits.reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "coin_pub", - &td.details.reserves_open_deposits.coin_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "coin_sig", - &td.details.reserves_open_deposits.coin_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "contribution", - &td.details.reserves_open_deposits.contribution), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with auditors table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_auditors (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_AUDITORS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ("auditor_pub", - &td.details.auditors.auditor_pub), - GNUNET_PQ_result_spec_string ("auditor_url", - &td.details.auditors.auditor_url), - GNUNET_PQ_result_spec_string ("auditor_name", - &td.details.auditors.auditor_name), - GNUNET_PQ_result_spec_bool ("is_active", - &td.details.auditors.is_active), - GNUNET_PQ_result_spec_timestamp ("last_change", - &td.details.auditors.last_change), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with auditor_denom_sigs table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_auditor_denom_sigs (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_uint64 ( - "auditor_uuid", - &td.details.auditor_denom_sigs.auditor_uuid), - GNUNET_PQ_result_spec_uint64 ( - "denominations_serial", - &td.details.auditor_denom_sigs.denominations_serial), - GNUNET_PQ_result_spec_auto_from_type ( - "auditor_sig", - &td.details.auditor_denom_sigs.auditor_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with exchange_sign_keys table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_exchange_sign_keys (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ("exchange_pub", - &td.details.exchange_sign_keys. - exchange_pub), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &td.details.exchange_sign_keys. - master_sig), - GNUNET_PQ_result_spec_timestamp ("valid_from", - &td.details.exchange_sign_keys.meta. - start), - GNUNET_PQ_result_spec_timestamp ("expire_sign", - &td.details.exchange_sign_keys.meta. - expire_sign), - GNUNET_PQ_result_spec_timestamp ("expire_legal", - &td.details.exchange_sign_keys.meta. - expire_legal), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with signkey_revocations table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_signkey_revocations (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_uint64 ("esk_serial", - &td.details.signkey_revocations.esk_serial), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &td.details.signkey_revocations. - master_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with known_coins table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_known_coins (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_KNOWN_COINS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "coin_pub", - &td.details.known_coins.coin_pub), - TALER_PQ_result_spec_denom_sig ( - "denom_sig", - &td.details.known_coins.denom_sig), - GNUNET_PQ_result_spec_uint64 ( - "denominations_serial", - &td.details.known_coins.denominations_serial), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with refresh table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_refresh (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_REFRESH - }; - - for (unsigned int i = 0; i<num_results; i++) - { - bool no_cs_r_values; - bool no_cs_r_choices; - size_t num_denom_sigs; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "rc", - &td.details.refresh.rc), - GNUNET_PQ_result_spec_auto_from_type ( - "execution_date", - &td.details.refresh.execution_date), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount_with_fee", - &td.details.refresh.amount_with_fee), - GNUNET_PQ_result_spec_auto_from_type ( - "old_coin_pub", - &td.details.refresh.old_coin_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "old_coin_sig", - &td.details.refresh.old_coin_sig), - GNUNET_PQ_result_spec_auto_from_type ( - "refresh_seed", - &td.details.refresh.refresh_seed), - GNUNET_PQ_result_spec_uint32 ( - "noreveal_index", - &td.details.refresh.noreveal_index), - GNUNET_PQ_result_spec_auto_from_type ( - "planchets_h", - &td.details.refresh.planchets_h), - GNUNET_PQ_result_spec_auto_from_type ( - "selected_h", - &td.details.refresh.selected_h), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ( - "blinding_seed", - &td.details.refresh.blinding_seed), - &td.details.refresh.no_blinding_seed), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_array_cs_r_pub ( - pg->conn, - "cs_r_values", - &td.details.refresh.num_cs_r_values, - &td.details.refresh.cs_r_values), - &no_cs_r_values), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ( - "cs_r_choices", - &td.details.refresh.cs_r_choices), - &no_cs_r_choices), - GNUNET_PQ_result_spec_array_uint64 ( - pg->conn, - "denom_serials", - &td.details.refresh.num_coins, - &td.details.refresh.denom_serials), - TALER_PQ_result_spec_array_blinded_denom_sig ( - pg->conn, - "denom_sigs", - &num_denom_sigs, - &td.details.refresh.denom_sigs), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - GNUNET_PQ_cleanup_result (rs); - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with batch deposits table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_batch_deposits (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_BATCH_DEPOSITS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_uint64 ( - "shard", - &td.details.batch_deposits.shard), - GNUNET_PQ_result_spec_auto_from_type ( - "merchant_pub", - &td.details.batch_deposits.merchant_pub), - GNUNET_PQ_result_spec_timestamp ( - "wallet_timestamp", - &td.details.batch_deposits.wallet_timestamp), - GNUNET_PQ_result_spec_timestamp ( - "exchange_timestamp", - &td.details.batch_deposits.exchange_timestamp), - GNUNET_PQ_result_spec_timestamp ( - "refund_deadline", - &td.details.batch_deposits.refund_deadline), - GNUNET_PQ_result_spec_timestamp ( - "wire_deadline", - &td.details.batch_deposits.wire_deadline), - GNUNET_PQ_result_spec_auto_from_type ( - "h_contract_terms", - &td.details.batch_deposits.h_contract_terms), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ( - "wallet_data_hash", - &td.details.batch_deposits.wallet_data_hash), - &td.details.batch_deposits.no_wallet_data_hash), - GNUNET_PQ_result_spec_auto_from_type ( - "wire_salt", - &td.details.batch_deposits.wire_salt), - GNUNET_PQ_result_spec_auto_from_type ( - "wire_target_h_payto", - &td.details.batch_deposits.wire_target_h_payto), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ( - "policy_details_serial_id", - &td.details.batch_deposits.policy_details_serial_id), - &td.details.batch_deposits.no_policy_details), - GNUNET_PQ_result_spec_bool ( - "policy_blocked", - &td.details.batch_deposits.policy_blocked), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "total_amount", - &td.details.batch_deposits.total_amount), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "total_without_fee", - &td.details.batch_deposits.total_without_fee), - GNUNET_PQ_result_spec_auto_from_type ( - "merchant_sig", - &td.details.batch_deposits.merchant_sig), - GNUNET_PQ_result_spec_bool ( - "done", - &td.details.batch_deposits.done), - GNUNET_PQ_result_spec_end - }; - - td.details.batch_deposits.policy_details_serial_id = 0; - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with coin deposits table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_coin_deposits (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_COIN_DEPOSITS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_uint64 ( - "batch_deposit_serial_id", - &td.details.coin_deposits.batch_deposit_serial_id), - GNUNET_PQ_result_spec_auto_from_type ( - "coin_pub", - &td.details.coin_deposits.coin_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "coin_sig", - &td.details.coin_deposits.coin_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount_with_fee", - &td.details.coin_deposits.amount_with_fee), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with refunds table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_refunds (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_REFUNDS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "coin_pub", - &td.details.refunds.coin_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "merchant_sig", - &td.details.refunds.merchant_sig), - GNUNET_PQ_result_spec_uint64 ( - "rtransaction_id", - &td.details.refunds.rtransaction_id), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount_with_fee", - &td.details.refunds.amount_with_fee), - GNUNET_PQ_result_spec_uint64 ( - "batch_deposit_serial_id", - &td.details.refunds.batch_deposit_serial_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with wire_out table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_wire_out (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_WIRE_OUT - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_timestamp ( - "execution_date", - &td.details.wire_out.execution_date), - GNUNET_PQ_result_spec_auto_from_type ( - "wtid_raw", - &td.details.wire_out.wtid_raw), - GNUNET_PQ_result_spec_auto_from_type ( - "wire_target_h_payto", - &td.details.wire_out.wire_target_h_payto), - GNUNET_PQ_result_spec_string ( - "exchange_account_section", - &td.details.wire_out.exchange_account_section), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount", - &td.details.wire_out.amount), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with aggregation_tracking table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_aggregation_tracking (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_uint64 ( - "batch_deposit_serial_id", - &td.details.aggregation_tracking.batch_deposit_serial_id), - GNUNET_PQ_result_spec_auto_from_type ( - "wtid_raw", - &td.details.aggregation_tracking.wtid_raw), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with wire_fee table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_wire_fee (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_WIRE_FEE - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_string ("wire_method", - &td.details.wire_fee.wire_method), - GNUNET_PQ_result_spec_timestamp ("start_date", - &td.details.wire_fee.start_date), - GNUNET_PQ_result_spec_timestamp ("end_date", - &td.details.wire_fee.end_date), - TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", - &td.details.wire_fee.fees.wire), - TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", - &td.details.wire_fee.fees.closing), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - &td.details.wire_fee.master_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with wire_fee table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_global_fee (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_GLOBAL_FEE - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "serial", - &td.serial), - GNUNET_PQ_result_spec_timestamp ( - "start_date", - &td.details.global_fee.start_date), - GNUNET_PQ_result_spec_timestamp ( - "end_date", - &td.details.global_fee.end_date), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "history_fee", - &td.details.global_fee.fees.history), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "account_fee", - &td.details.global_fee.fees.account), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "purse_fee", - &td.details.global_fee.fees.purse), - GNUNET_PQ_result_spec_relative_time ( - "purse_timeout", - &td.details.global_fee.purse_timeout), - GNUNET_PQ_result_spec_relative_time ( - "history_expiration", - &td.details.global_fee.history_expiration), - GNUNET_PQ_result_spec_uint32 ( - "purse_account_limit", - &td.details.global_fee.purse_account_limit), - GNUNET_PQ_result_spec_auto_from_type ( - "master_sig", - &td.details.global_fee.master_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with recoup table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_recoup (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_RECOUP - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &td.details.recoup.coin_sig), - GNUNET_PQ_result_spec_auto_from_type ("coin_blind", - &td.details.recoup.coin_blind), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &td.details.recoup.amount), - GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", - &td.details.recoup.timestamp), - GNUNET_PQ_result_spec_auto_from_type ( - "coin_pub", - &td.details.recoup.coin_pub), - GNUNET_PQ_result_spec_uint64 ("withdraw_serial_id", - &td.details.recoup.withdraw_serial_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with recoup_refresh table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_recoup_refresh (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_RECOUP_REFRESH - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &td.details.recoup_refresh.coin_sig) - , - GNUNET_PQ_result_spec_auto_from_type ( - "coin_blind", - &td.details.recoup_refresh.coin_blind), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &td.details.recoup_refresh.amount), - GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", - &td.details.recoup_refresh.timestamp), - GNUNET_PQ_result_spec_uint64 ("known_coin_id", - &td.details.recoup_refresh.known_coin_id), - GNUNET_PQ_result_spec_auto_from_type ( - "coin_pub", - &td.details.recoup_refresh.coin_pub), - GNUNET_PQ_result_spec_uint64 ("rrc_serial", - &td.details.recoup_refresh.rrc_serial), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with extensions table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_extensions (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_EXTENSIONS - }; - bool no_manifest = false; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("extension_id", - &td.serial), - GNUNET_PQ_result_spec_string ("name", - &td.details.extensions.name), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("manifest", - &td.details.extensions.manifest), - &no_manifest), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with policy_details table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_policy_details (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_POLICY_DETAILS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ("hash_code", - &td.details.policy_details. - hash_code), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ("policy_json", - &td.details.policy_details. - policy_json), - &td.details.policy_details.no_policy_json), - GNUNET_PQ_result_spec_timestamp ("deadline", - &td.details.policy_details. - deadline), - TALER_PQ_RESULT_SPEC_AMOUNT ("commitment", - &td.details.policy_details. - commitment), - TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total", - &td.details.policy_details. - accumulated_total), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee", - &td.details.policy_details. - fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("transferable", - &td.details.policy_details. - transferable), - GNUNET_PQ_result_spec_uint16 ("fulfillment_state", - &td.details.policy_details. - fulfillment_state), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ("fulfillment_id", - &td.details.policy_details. - fulfillment_id), - &td.details.policy_details.no_fulfillment_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with policy_fulfillments table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_policy_fulfillments (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - bool no_proof = false; - bool no_timestamp = false; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("fulfillment_id", - &td.serial), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_timestamp ("fulfillment_timestamp", - &td.details.policy_fulfillments. - fulfillment_timestamp), - &no_timestamp), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("fulfillment_proof", - &td.details.policy_fulfillments. - fulfillment_proof), - &no_proof), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with purse_requests table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_purse_requests (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_PURSE_REQUESTS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "purse_requests_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_pub", - &td.details.purse_requests.purse_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "merge_pub", - &td.details.purse_requests.merge_pub), - GNUNET_PQ_result_spec_timestamp ( - "purse_creation", - &td.details.purse_requests.purse_creation), - GNUNET_PQ_result_spec_timestamp ( - "purse_expiration", - &td.details.purse_requests.purse_expiration), - GNUNET_PQ_result_spec_auto_from_type ( - "h_contract_terms", - &td.details.purse_requests.h_contract_terms), - GNUNET_PQ_result_spec_uint32 ( - "age_limit", - &td.details.purse_requests.age_limit), - GNUNET_PQ_result_spec_uint32 ( - "flags", - &td.details.purse_requests.flags), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount_with_fee", - &td.details.purse_requests.amount_with_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "purse_fee", - &td.details.purse_requests.purse_fee), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_sig", - &td.details.purse_requests.purse_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with purse_decision table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_purse_decision (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_PURSE_DECISION - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "purse_refunds_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_pub", - &td.details.purse_decision.purse_pub), - GNUNET_PQ_result_spec_timestamp ( - "action_timestamp", - &td.details.purse_decision.action_timestamp), - GNUNET_PQ_result_spec_bool ( - "refunded", - &td.details.purse_decision.refunded), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with purse_merges table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_purse_merges (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_PURSE_MERGES - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "purse_merge_request_serial_id", - &td.serial), - GNUNET_PQ_result_spec_uint64 ( - "partner_serial_id", - &td.details.purse_merges.partner_serial_id), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_pub", - &td.details.purse_merges.reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_pub", - &td.details.purse_merges.purse_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "merge_sig", - &td.details.purse_merges.merge_sig), - GNUNET_PQ_result_spec_timestamp ( - "merge_timestamp", - &td.details.purse_merges.merge_timestamp), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with purse_deposits table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_purse_deposits (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_PURSE_DEPOSITS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "purse_deposit_serial_id", - &td.serial), - GNUNET_PQ_result_spec_uint64 ( - "partner_serial_id", - &td.details.purse_deposits.partner_serial_id), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_pub", - &td.details.purse_deposits.purse_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "coin_pub", - &td.details.purse_deposits.coin_pub), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount_with_fee", - &td.details.purse_deposits.amount_with_fee), - GNUNET_PQ_result_spec_auto_from_type ( - "coin_sig", - &td.details.purse_deposits.coin_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with account_merges table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_account_merges (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_ACCOUNT_MERGES - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "account_merge_request_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_pub", - &td.details.account_merges.reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_sig", - &td.details.account_merges.reserve_sig), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_pub", - &td.details.account_merges.purse_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "wallet_h_payto", - &td.details.account_merges.wallet_h_payto), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with history_requests table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_history_requests (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_HISTORY_REQUESTS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "history_request_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_pub", - &td.details.history_requests.reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_sig", - &td.details.history_requests.reserve_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "history_fee", - &td.details.history_requests.history_fee), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with close_requests table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_close_requests (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_CLOSE_REQUESTS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "close_request_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_pub", - &td.details.close_requests.reserve_pub), - GNUNET_PQ_result_spec_timestamp ( - "close_timestamp", - &td.details.close_requests.close_timestamp), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_sig", - &td.details.close_requests.reserve_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "close", - &td.details.close_requests.close), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "close_fee", - &td.details.close_requests.close_fee), - GNUNET_PQ_result_spec_string ( - "payto_uri", - &td.details.close_requests.payto_uri.full_payto), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with wads_out table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_wads_out (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_WADS_OUT - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "wad_out_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "wad_id", - &td.details.wads_out.wad_id), - GNUNET_PQ_result_spec_uint64 ( - "partner_serial_id", - &td.details.wads_out.partner_serial_id), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount", - &td.details.wads_out.amount), - GNUNET_PQ_result_spec_timestamp ( - "execution_time", - &td.details.wads_out.execution_time), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with wads_out_entries table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_wads_out_entries (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "wad_out_entry_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_pub", - &td.details.wads_out_entries.reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_pub", - &td.details.wads_out_entries.purse_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "h_contract", - &td.details.wads_out_entries.h_contract), - GNUNET_PQ_result_spec_timestamp ( - "purse_expiration", - &td.details.wads_out_entries.purse_expiration), - GNUNET_PQ_result_spec_timestamp ( - "merge_timestamp", - &td.details.wads_out_entries.merge_timestamp), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount_with_fee", - &td.details.wads_out_entries.amount_with_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "wad_fee", - &td.details.wads_out_entries.wad_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "deposit_fees", - &td.details.wads_out_entries.deposit_fees), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_sig", - &td.details.wads_out_entries.reserve_sig), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_sig", - &td.details.wads_out_entries.purse_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with wads_in table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_wads_in (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_WADS_IN - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "wad_in_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "wad_id", - &td.details.wads_in.wad_id), - GNUNET_PQ_result_spec_string ( - "origin_exchange_url", - &td.details.wads_in.origin_exchange_url), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount", - &td.details.wads_in.amount), - GNUNET_PQ_result_spec_timestamp ( - "arrival_time", - &td.details.wads_in.arrival_time), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with wads_in_entries table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_wads_in_entries (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "wad_in_entry_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_pub", - &td.details.wads_in_entries.reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_pub", - &td.details.wads_in_entries.purse_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "h_contract", - &td.details.wads_in_entries.h_contract), - GNUNET_PQ_result_spec_timestamp ( - "purse_expiration", - &td.details.wads_in_entries.purse_expiration), - GNUNET_PQ_result_spec_timestamp ( - "merge_timestamp", - &td.details.wads_in_entries.merge_timestamp), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount_with_fee", - &td.details.wads_in_entries.amount_with_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "wad_fee", - &td.details.wads_in_entries.wad_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "deposit_fees", - &td.details.wads_in_entries.deposit_fees), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_sig", - &td.details.wads_in_entries.reserve_sig), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_sig", - &td.details.wads_in_entries.purse_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with profit_drains table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_profit_drains (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_PROFIT_DRAINS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "profit_drain_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "wtid", - &td.details.profit_drains.wtid), - GNUNET_PQ_result_spec_string ( - "account_section", - &td.details.profit_drains.account_section), - GNUNET_PQ_result_spec_string ( - "payto_uri", - &td.details.profit_drains.payto_uri.full_payto), - GNUNET_PQ_result_spec_timestamp ( - "trigger_date", - &td.details.profit_drains.trigger_date), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount", - &td.details.profit_drains.amount), - GNUNET_PQ_result_spec_auto_from_type ( - "master_sig", - &td.details.profit_drains.master_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with aml_staff table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_aml_staff (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_AML_STAFF - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "aml_staff_uuid", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "decider_pub", - &td.details.aml_staff.decider_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "master_sig", - &td.details.aml_staff.master_sig), - GNUNET_PQ_result_spec_string ( - "decider_name", - &td.details.aml_staff.decider_name), - GNUNET_PQ_result_spec_bool ( - "is_active", - &td.details.aml_staff.is_active), - GNUNET_PQ_result_spec_bool ( - "read_only", - &td.details.aml_staff.read_only), - GNUNET_PQ_result_spec_timestamp ( - "last_change", - &td.details.aml_staff.last_change), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with purse_deletion table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_purse_deletion (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_PURSE_DELETION - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "purse_deletion_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_sig", - &td.details.purse_deletion.purse_sig), - GNUNET_PQ_result_spec_auto_from_type ( - "purse_pub", - &td.details.purse_deletion.purse_pub), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with withdraw table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_withdraw (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_WITHDRAW - }; - - for (unsigned int i = 0; i<num_results; i++) - { - bool no_max_age; - bool no_noreveal_index; - bool no_selected_h; - bool no_cs_r_values; - bool no_cs_r_choices; - size_t num_sigs; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "withdraw_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "planchets_h", - &td.details.withdraw.planchets_h), - GNUNET_PQ_result_spec_timestamp ( - "execution_date", - &td.details.withdraw.execution_date), - TALER_PQ_RESULT_SPEC_AMOUNT ( - "amount_with_fee", - &td.details.withdraw.amount_with_fee), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_pub", - &td.details.withdraw.reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "reserve_sig", - &td.details.withdraw.reserve_sig), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint16 ( - "max_age", - &td.details.withdraw.max_age), - &no_max_age), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint16 ( - "noreveal_index", - &td.details.withdraw.noreveal_index), - &no_noreveal_index), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ( - "selected_h", - &td.details.withdraw.selected_h), - &no_selected_h), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ( - "blinding_seed", - &td.details.withdraw.blinding_seed), - &td.details.withdraw.no_blinding_seed), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_array_cs_r_pub ( - pg->conn, - "cs_r_values", - &td.details.withdraw.num_cs_r_values, - &td.details.withdraw.cs_r_values), - &no_cs_r_values), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ( - "cs_r_choices", - &td.details.withdraw.cs_r_choices), - &no_cs_r_choices), - GNUNET_PQ_result_spec_array_uint64 ( - pg->conn, - "denom_serials", - &td.details.withdraw.num_coins, - &td.details.withdraw.denom_serials), - TALER_PQ_result_spec_array_blinded_denom_sig ( - pg->conn, - "denom_sigs", - &num_sigs, - &td.details.withdraw.denom_sigs), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - GNUNET_PQ_cleanup_result (rs); - return; - } - if (num_sigs != td.details.withdraw.num_coins) - { - GNUNET_break (0); - ctx->error = true; - GNUNET_PQ_cleanup_result (rs); - return; - } - if (no_max_age != no_noreveal_index) - { - GNUNET_break (0); - ctx->error = true; - GNUNET_PQ_cleanup_result (rs); - return; - } - if (no_max_age != no_selected_h) - { - GNUNET_break (0); - ctx->error = true; - GNUNET_PQ_cleanup_result (rs); - return; - } - if (no_cs_r_values != no_cs_r_choices) - { - GNUNET_break (0); - ctx->error = true; - GNUNET_PQ_cleanup_result (rs); - return; - } - if (no_cs_r_values != td.details.withdraw.no_blinding_seed) - { - GNUNET_break (0); - ctx->error = true; - GNUNET_PQ_cleanup_result (rs); - return; - } - td.details.withdraw.age_proof_required = ! no_max_age; - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with legitimization_measures table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_legitimization_measures (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "access_token", - &td.details.legitimization_measures.target_token), - GNUNET_PQ_result_spec_timestamp ( - "start_time", - &td.details.legitimization_measures.start_time), - TALER_PQ_result_spec_json ( - "jmeasures", - &td.details.legitimization_measures.measures), - GNUNET_PQ_result_spec_uint32 ( - "display_priority", - &td.details.legitimization_measures.display_priority), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with legitimization_outcomes table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_legitimization_outcomes (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "h_payto", - &td.details.legitimization_outcomes.h_payto), - GNUNET_PQ_result_spec_timestamp ( - "decision_time", - &td.details.legitimization_outcomes.decision_time), - GNUNET_PQ_result_spec_timestamp ( - "expiration_time", - &td.details.legitimization_outcomes.expiration_time), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ( - "jproperties", - &td.details.legitimization_outcomes.properties), - NULL), - GNUNET_PQ_result_spec_bool ( - "to_investigate_id", - &td.details.legitimization_outcomes.to_investigate), - TALER_PQ_result_spec_json ( - "jnew_rules", - &td.details.legitimization_outcomes.new_rules), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with legitimization_processes table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_legitimization_processes (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "h_payto", - &td.details.legitimization_processes.h_payto), - GNUNET_PQ_result_spec_timestamp ( - "start_time", - &td.details.legitimization_processes.start_time), - GNUNET_PQ_result_spec_timestamp ( - "expiration_time", - &td.details.legitimization_processes.expiration_time), - GNUNET_PQ_result_spec_uint64 ( - "legitimization_measure_serial_id", - &td.details.legitimization_processes.legitimization_measure_serial_id), - GNUNET_PQ_result_spec_uint32 ( - "measure_index", - &td.details.legitimization_processes.measure_index), - GNUNET_PQ_result_spec_string ( - "provider_name", - &td.details.legitimization_processes.provider_name), - GNUNET_PQ_result_spec_string ( - "provider_user_id", - &td.details.legitimization_processes.provider_user_id), - GNUNET_PQ_result_spec_string ( - "provider_legitimization_id", - &td.details.legitimization_processes.provider_legitimization_id), - GNUNET_PQ_result_spec_string ( - "redirect_url", - &td.details.legitimization_processes.redirect_url), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with kyc_attributes table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_kyc_attributes (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "kyc_attributes_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "h_payto", - &td.details.kyc_attributes.h_payto), - GNUNET_PQ_result_spec_uint64 ( - "legitimization_serial", - &td.details.kyc_attributes.legitimization_serial), - GNUNET_PQ_result_spec_timestamp ( - "collection_time", - &td.details.kyc_attributes.collection_time), - GNUNET_PQ_result_spec_timestamp ( - "expiration_time", - &td.details.kyc_attributes.expiration_time), - GNUNET_PQ_result_spec_uint64 ( - "trigger_outcome_serial", - &td.details.kyc_attributes.trigger_outcome_serial), - GNUNET_PQ_result_spec_variable_size ( - "encrypted_attributes", - &td.details.kyc_attributes.encrypted_attributes, - &td.details.kyc_attributes.encrypted_attributes_size), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with aml_history table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_aml_history (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_AML_HISTORY - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "aml_history_serial_id", - &td.serial), - GNUNET_PQ_result_spec_auto_from_type ( - "h_payto", - &td.details.aml_history.h_payto), - GNUNET_PQ_result_spec_uint64 ( - "outcome_serial_id", - &td.details.aml_history.outcome_serial_id), - GNUNET_PQ_result_spec_string ( - "justification", - &td.details.aml_history.justification), - GNUNET_PQ_result_spec_auto_from_type ( - "decider_pub", - &td.details.aml_history.decider_pub), - GNUNET_PQ_result_spec_auto_from_type ( - "decider_sig", - &td.details.aml_history.decider_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Function called with kyc_events table entries. - * - * @param cls closure - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lrbt_cb_table_kyc_events (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRecordsByTableContext *ctx = cls; - struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_KYC_EVENTS - }; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "kyc_event_serial_id", - &td.serial), - GNUNET_PQ_result_spec_timestamp ( - "event_timestamp", - &td.details.kyc_events.event_timestamp), - GNUNET_PQ_result_spec_string ( - "event_type", - &td.details.kyc_events.event_type), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->error = true; - return; - } - ctx->cb (ctx->cb_cls, - &td); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Assign statement to @a n and PREPARE - * @a sql under name @a n. - */ -#define XPREPARE(n,sql) \ - statement = n; \ - PREPARE (pg, n, sql); - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_records_by_table ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - enum TALER_EXCHANGEDB_ReplicatedTable table, - uint64_t serial, - TALER_EXCHANGEDB_ReplicationCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial), - GNUNET_PQ_query_param_end - }; - struct LookupRecordsByTableContext ctx = { - .pg = pg, - .cb = cb, - .cb_cls = cb_cls - }; - GNUNET_PQ_PostgresResultHandler rh = NULL; - const char *statement = NULL; - enum GNUNET_DB_QueryStatus qs; - - switch (table) - { - case TALER_EXCHANGEDB_RT_DENOMINATIONS: - XPREPARE ("select_above_serial_by_table_denominations", - "SELECT" - " denominations_serial AS serial" - ",denom_type" - ",denom_pub" - ",master_sig" - ",valid_from" - ",expire_withdraw" - ",expire_deposit" - ",expire_legal" - ",coin" - ",fee_withdraw" - ",fee_deposit" - ",fee_refresh" - ",fee_refund" - ",age_mask" - " FROM denominations" - " WHERE denominations_serial > $1" - " ORDER BY denominations_serial ASC;"); - rh = &lrbt_cb_table_denominations; - break; - case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS: - XPREPARE ("select_above_serial_by_table_denomination_revocations", - "SELECT" - " denom_revocations_serial_id AS serial" - ",master_sig" - ",denominations_serial" - " FROM denomination_revocations" - " WHERE denom_revocations_serial_id > $1" - " ORDER BY denom_revocations_serial_id ASC;"); - rh = &lrbt_cb_table_denomination_revocations; - break; - case TALER_EXCHANGEDB_RT_WIRE_TARGETS: - XPREPARE ("select_above_serial_by_table_wire_targets", - "SELECT" - " wire_target_serial_id AS serial" - ",payto_uri" - " FROM wire_targets" - " WHERE wire_target_serial_id > $1" - " ORDER BY wire_target_serial_id ASC;"); - rh = &lrbt_cb_table_wire_targets; - break; - case TALER_EXCHANGEDB_RT_KYC_TARGETS: - XPREPARE ("select_above_serial_by_table_kyc_targets", - "SELECT" - " kyc_target_serial_id AS serial" - ",h_normalized_payto" - ",access_token" - ",target_pub" - ",is_wallet" - " FROM kyc_targets" - " WHERE kyc_target_serial_id > $1" - " ORDER BY kyc_target_serial_id ASC;"); - rh = &lrbt_cb_table_kyc_targets; - break; - case TALER_EXCHANGEDB_RT_RESERVES: - XPREPARE ("select_above_serial_by_table_reserves", - "SELECT" - " reserve_uuid AS serial" - ",reserve_pub" - ",expiration_date" - ",gc_date" - " FROM reserves" - " WHERE reserve_uuid > $1" - " ORDER BY reserve_uuid ASC;"); - rh = &lrbt_cb_table_reserves; - break; - case TALER_EXCHANGEDB_RT_RESERVES_IN: - XPREPARE ("select_above_serial_by_table_reserves_in", - "SELECT" - " reserve_in_serial_id AS serial" - ",reserve_pub" - ",wire_reference" - ",credit" - ",wire_source_h_payto" - ",exchange_account_section" - ",execution_date" - " FROM reserves_in" - " WHERE reserve_in_serial_id > $1" - " ORDER BY reserve_in_serial_id ASC;"); - rh = &lrbt_cb_table_reserves_in; - break; - case TALER_EXCHANGEDB_RT_KYCAUTHS_IN: - XPREPARE ("select_above_serial_by_table_kycauth_in", - "SELECT" - " kycauth_in_serial_id AS serial" - ",account_pub" - ",wire_reference" - ",credit" - ",wire_source_h_payto" - ",exchange_account_section" - ",execution_date" - " FROM kycauths_in" - " WHERE kycauth_in_serial_id > $1" - " ORDER BY kycauth_in_serial_id ASC;"); - rh = &lrbt_cb_table_kycauth_in; - break; - case TALER_EXCHANGEDB_RT_RESERVES_CLOSE: - XPREPARE ("select_above_serial_by_table_reserves_close", - "SELECT" - " close_uuid AS serial" - ",reserve_pub" - ",execution_date" - ",wtid" - ",wire_target_h_payto" - ",amount" - ",closing_fee" - " FROM reserves_close" - " WHERE close_uuid > $1" - " ORDER BY close_uuid ASC;"); - rh = &lrbt_cb_table_reserves_close; - break; - case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS: - XPREPARE ("select_above_serial_by_table_reserves_open_requests", - "SELECT" - " open_request_uuid AS serial" - ",reserve_pub" - ",request_timestamp" - ",expiration_date" - ",reserve_sig" - ",reserve_payment" - ",requested_purse_limit" - " FROM reserves_open_requests" - " WHERE open_request_uuid > $1" - " ORDER BY open_request_uuid ASC;"); - rh = &lrbt_cb_table_reserves_open_requests; - break; - case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS: - XPREPARE ("select_above_serial_by_table_reserves_open_deposits", - "SELECT" - " reserves_open_deposit_uuid AS serial" - ",reserve_sig" - ",reserve_pub" - ",coin_pub" - ",coin_sig" - ",contribution" - " FROM reserves_open_deposits" - " WHERE reserves_open_deposit_uuid > $1" - " ORDER BY reserves_open_deposit_uuid ASC;"); - rh = &lrbt_cb_table_reserves_open_deposits; - break; - case TALER_EXCHANGEDB_RT_AUDITORS: - XPREPARE ("select_above_serial_by_table_auditors", - "SELECT" - " auditor_uuid AS serial" - ",auditor_pub" - ",auditor_name" - ",auditor_url" - ",is_active" - ",last_change" - " FROM auditors" - " WHERE auditor_uuid > $1" - " ORDER BY auditor_uuid ASC;"); - rh = &lrbt_cb_table_auditors; - break; - case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS: - XPREPARE ("select_above_serial_by_table_auditor_denom_sigs", - "SELECT" - " auditor_denom_serial AS serial" - ",auditor_uuid" - ",denominations_serial" - ",auditor_sig" - " FROM auditor_denom_sigs" - " WHERE auditor_denom_serial > $1" - " ORDER BY auditor_denom_serial ASC;"); - rh = &lrbt_cb_table_auditor_denom_sigs; - break; - case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS: - XPREPARE ("select_above_serial_by_table_exchange_sign_keys", - "SELECT" - " esk_serial AS serial" - ",exchange_pub" - ",master_sig" - ",valid_from" - ",expire_sign" - ",expire_legal" - " FROM exchange_sign_keys" - " WHERE esk_serial > $1" - " ORDER BY esk_serial ASC;"); - rh = &lrbt_cb_table_exchange_sign_keys; - break; - case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS: - XPREPARE ("select_above_serial_by_table_signkey_revocations", - "SELECT" - " signkey_revocations_serial_id AS serial" - ",esk_serial" - ",master_sig" - " FROM signkey_revocations" - " WHERE signkey_revocations_serial_id > $1" - " ORDER BY signkey_revocations_serial_id ASC;"); - rh = &lrbt_cb_table_signkey_revocations; - break; - case TALER_EXCHANGEDB_RT_KNOWN_COINS: - XPREPARE ("select_above_serial_by_table_known_coins", - "SELECT" - " known_coin_id AS serial" - ",coin_pub" - ",denom_sig" - ",denominations_serial" - " FROM known_coins" - " WHERE known_coin_id > $1" - " ORDER BY known_coin_id ASC;"); - rh = &lrbt_cb_table_known_coins; - break; - case TALER_EXCHANGEDB_RT_REFRESH: - XPREPARE ("select_above_serial_by_table_refresh", - "SELECT" - " refresh_id AS serial" - ",rc" - ",execution_date" - ",amount_with_fee" - ",old_coin_pub" - ",old_coin_sig" - ",refresh_seed" - ",noreveal_index" - ",planchets_h" - ",selected_h" - ",blinding_seed" - ",cs_r_values" - ",cs_r_choices" - ",denom_serials" - ",denom_sigs" - " FROM refresh" - " WHERE refresh_id > $1" - " ORDER BY refresh_id ASC;"); - rh = &lrbt_cb_table_refresh; - break; - case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS: - XPREPARE ("select_above_serial_by_table_batch_deposits", - "SELECT" - " batch_deposit_serial_id AS serial" - ",shard" - ",merchant_pub" - ",wallet_timestamp" - ",exchange_timestamp" - ",refund_deadline" - ",wire_deadline" - ",h_contract_terms" - ",wallet_data_hash" - ",wire_salt" - ",wire_target_h_payto" - ",policy_details_serial_id" - ",policy_blocked" - ",total_amount" - ",total_without_fee" - ",merchant_sig" - ",done" - " FROM batch_deposits" - " WHERE batch_deposit_serial_id > $1" - " ORDER BY batch_deposit_serial_id ASC;"); - rh = &lrbt_cb_table_batch_deposits; - break; - case TALER_EXCHANGEDB_RT_COIN_DEPOSITS: - XPREPARE ("select_above_serial_by_table_coin_deposits", - "SELECT" - " coin_deposit_serial_id AS serial" - ",batch_deposit_serial_id" - ",coin_pub" - ",coin_sig" - ",amount_with_fee" - " FROM coin_deposits" - " WHERE coin_deposit_serial_id > $1" - " ORDER BY coin_deposit_serial_id ASC;"); - rh = &lrbt_cb_table_coin_deposits; - break; - case TALER_EXCHANGEDB_RT_REFUNDS: - XPREPARE ("select_above_serial_by_table_refunds", - "SELECT" - " refund_serial_id AS serial" - ",coin_pub" - ",merchant_sig" - ",rtransaction_id" - ",amount_with_fee" - ",batch_deposit_serial_id" - " FROM refunds" - " WHERE refund_serial_id > $1" - " ORDER BY refund_serial_id ASC;"); - rh = &lrbt_cb_table_refunds; - break; - case TALER_EXCHANGEDB_RT_WIRE_OUT: - XPREPARE ("select_above_serial_by_table_wire_out", - "SELECT" - " wireout_uuid AS serial" - ",execution_date" - ",wtid_raw" - ",wire_target_h_payto" - ",exchange_account_section" - ",amount" - " FROM wire_out" - " WHERE wireout_uuid > $1" - " ORDER BY wireout_uuid ASC;"); - rh = &lrbt_cb_table_wire_out; - break; - case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING: - XPREPARE ("select_above_serial_by_table_aggregation_tracking", - "SELECT" - " aggregation_serial_id AS serial" - ",batch_deposit_serial_id" - ",wtid_raw" - " FROM aggregation_tracking" - " WHERE aggregation_serial_id > $1" - " ORDER BY aggregation_serial_id ASC;"); - rh = &lrbt_cb_table_aggregation_tracking; - break; - case TALER_EXCHANGEDB_RT_WIRE_FEE: - XPREPARE ("select_above_serial_by_table_wire_fee", - "SELECT" - " wire_fee_serial AS serial" - ",wire_method" - ",start_date" - ",end_date" - ",wire_fee" - ",closing_fee" - ",master_sig" - " FROM wire_fee" - " WHERE wire_fee_serial > $1" - " ORDER BY wire_fee_serial ASC;"); - rh = &lrbt_cb_table_wire_fee; - break; - case TALER_EXCHANGEDB_RT_GLOBAL_FEE: - XPREPARE ("select_above_serial_by_table_global_fee", - "SELECT" - " global_fee_serial AS serial" - ",start_date" - ",end_date" - ",history_fee" - ",account_fee" - ",purse_fee" - ",purse_timeout" - ",history_expiration" - ",purse_account_limit" - ",master_sig" - " FROM global_fee" - " WHERE global_fee_serial > $1" - " ORDER BY global_fee_serial ASC;"); - rh = &lrbt_cb_table_global_fee; - break; - case TALER_EXCHANGEDB_RT_RECOUP: - XPREPARE ("select_above_serial_by_table_recoup", - "SELECT" - " recoup_uuid AS serial" - ",coin_sig" - ",coin_blind" - ",amount" - ",recoup_timestamp" - ",coin_pub" - ",reserve_out_serial_id" - " FROM recoup" - " WHERE recoup_uuid > $1" - " ORDER BY recoup_uuid ASC;"); - rh = &lrbt_cb_table_recoup; - break; - case TALER_EXCHANGEDB_RT_RECOUP_REFRESH: - XPREPARE ("select_above_serial_by_table_recoup_refresh", - "SELECT" - " recoup_refresh_uuid AS serial" - ",coin_sig" - ",coin_blind" - ",amount" - ",recoup_timestamp" - ",coin_pub" - ",known_coin_id" - ",rrc_serial" - " FROM recoup_refresh" - " WHERE recoup_refresh_uuid > $1" - " ORDER BY recoup_refresh_uuid ASC;"); - rh = &lrbt_cb_table_recoup_refresh; - break; - case TALER_EXCHANGEDB_RT_EXTENSIONS: - // FIXME: this seems broken! -- where is the SQL!? - statement = "select_above_serial_by_table_extensions"; - rh = &lrbt_cb_table_extensions; - break; - case TALER_EXCHANGEDB_RT_POLICY_DETAILS: - // FIXME: this seems broken! -- where is the SQL!? - statement = "select_above_serial_by_table_policy_details"; - rh = &lrbt_cb_table_policy_details; - break; - case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS: - // FIXME: this seems broken! -- where is the SQL!? - statement = "select_above_serial_by_table_policy_fulfillments"; - rh = &lrbt_cb_table_policy_fulfillments; - break; - case TALER_EXCHANGEDB_RT_PURSE_REQUESTS: - XPREPARE ("select_above_serial_by_table_purse_requests", - "SELECT" - " purse_requests_serial_id" - ",purse_pub" - ",merge_pub" - ",purse_creation" - ",purse_expiration" - ",h_contract_terms" - ",age_limit" - ",flags" - ",amount_with_fee" - ",purse_fee" - ",purse_sig" - " FROM purse_requests" - " WHERE purse_requests_serial_id > $1" - " ORDER BY purse_requests_serial_id ASC;"); - rh = &lrbt_cb_table_purse_requests; - break; - case TALER_EXCHANGEDB_RT_PURSE_DECISION: - XPREPARE ("select_above_serial_by_table_purse_decision", - "SELECT" - " purse_decision_serial_id" - ",action_timestamp" - ",refunded" - ",purse_pub" - " FROM purse_decision" - " WHERE purse_decision_serial_id > $1" - " ORDER BY purse_decision_serial_id ASC;"); - rh = &lrbt_cb_table_purse_decision; - break; - case TALER_EXCHANGEDB_RT_PURSE_MERGES: - XPREPARE ("select_above_serial_by_table_purse_merges", - "SELECT" - " purse_merge_request_serial_id" - ",partner_serial_id" - ",reserve_pub" - ",purse_pub" - ",merge_sig" - ",merge_timestamp" - " FROM purse_merges" - " WHERE purse_merge_request_serial_id > $1" - " ORDER BY purse_merge_request_serial_id ASC;"); - rh = &lrbt_cb_table_purse_merges; - break; - case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS: - XPREPARE ("select_above_serial_by_table_purse_deposits", - "SELECT" - " purse_deposit_serial_id" - ",partner_serial_id" - ",purse_pub" - ",coin_pub" - ",amount_with_fee" - ",coin_sig" - " FROM purse_deposits" - " WHERE purse_deposit_serial_id > $1" - " ORDER BY purse_deposit_serial_id ASC;"); - rh = &lrbt_cb_table_purse_deposits; - break; - case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES: - XPREPARE ("select_above_serial_by_table_account_merges", - "SELECT" - " account_merge_request_serial_id" - ",reserve_pub" - ",reserve_sig" - ",purse_pub" - ",wallet_h_payto" - " FROM account_merges" - " WHERE account_merge_request_serial_id > $1" - " ORDER BY account_merge_request_serial_id ASC;"); - rh = &lrbt_cb_table_account_merges; - break; - case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS: - XPREPARE ("select_above_serial_by_table_history_requests", - "SELECT" - " history_request_serial_id" - ",reserve_pub" - ",request_timestamp" - ",reserve_sig" - ",history_fee" - " FROM history_requests" - " WHERE history_request_serial_id > $1" - " ORDER BY history_request_serial_id ASC;"); - rh = &lrbt_cb_table_history_requests; - break; - case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS: - XPREPARE ("select_above_serial_by_table_close_requests", - "SELECT" - " close_request_serial_id" - ",reserve_pub" - ",close_timestamp" - ",reserve_sig" - ",close" - " FROM close_requests" - " WHERE close_request_serial_id > $1" - " ORDER BY close_request_serial_id ASC;"); - rh = &lrbt_cb_table_close_requests; - break; - case TALER_EXCHANGEDB_RT_WADS_OUT: - XPREPARE ("select_above_serial_by_table_wads_out", - "SELECT" - " wad_out_serial_id" - ",wad_id" - ",partner_serial_id" - ",amount" - ",execution_time" - " FROM wads_out" - " WHERE wad_out_serial_id > $1" - " ORDER BY wad_out_serial_id ASC;"); - rh = &lrbt_cb_table_wads_out; - break; - case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES: - XPREPARE ("select_above_serial_by_table_wads_out_entries", - "SELECT" - " wad_out_entry_serial_id" - ",reserve_pub" - ",purse_pub" - ",h_contract" - ",purse_expiration" - ",merge_timestamp" - ",amount_with_fee" - ",wad_fee" - ",deposit_fees" - ",reserve_sig" - ",purse_sig" - " FROM wad_out_entries" - " WHERE wad_out_entry_serial_id > $1" - " ORDER BY wad_out_entry_serial_id ASC;"); - rh = &lrbt_cb_table_wads_out_entries; - break; - case TALER_EXCHANGEDB_RT_WADS_IN: - XPREPARE ("select_above_serial_by_table_wads_in", - "SELECT" - " wad_in_serial_id" - ",wad_id" - ",origin_exchange_url" - ",amount" - ",arrival_time" - " FROM wads_in" - " WHERE wad_in_serial_id > $1" - " ORDER BY wad_in_serial_id ASC;"); - rh = &lrbt_cb_table_wads_in; - break; - case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES: - XPREPARE ("select_above_serial_by_table_wads_in_entries", - "SELECT" - " wad_in_entry_serial_id" - ",reserve_pub" - ",purse_pub" - ",h_contract" - ",purse_expiration" - ",merge_timestamp" - ",amount_with_fee" - ",wad_fee" - ",deposit_fees" - ",reserve_sig" - ",purse_sig" - " FROM wad_in_entries" - " WHERE wad_in_entry_serial_id > $1" - " ORDER BY wad_in_entry_serial_id ASC;"); - rh = &lrbt_cb_table_wads_in_entries; - break; - case TALER_EXCHANGEDB_RT_PROFIT_DRAINS: - XPREPARE ("select_above_serial_by_table_profit_drains", - "SELECT" - " profit_drain_serial_id" - ",wtid" - ",account_section" - ",payto_uri" - ",trigger_date" - ",amount" - ",master_sig" - " FROM profit_drains" - " WHERE profit_drain_serial_id > $1" - " ORDER BY profit_drain_serial_id ASC;"); - rh = &lrbt_cb_table_profit_drains; - break; - - case TALER_EXCHANGEDB_RT_AML_STAFF: - XPREPARE ("select_above_serial_by_table_aml_staff", - "SELECT" - " aml_staff_uuid" - ",decider_pub" - ",master_sig" - ",decider_name" - ",is_active" - ",read_only" - ",last_change" - " FROM aml_staff" - " WHERE aml_staff_uuid > $1" - " ORDER BY aml_staff_uuid ASC;"); - rh = &lrbt_cb_table_aml_staff; - break; - case TALER_EXCHANGEDB_RT_PURSE_DELETION: - XPREPARE ("select_above_serial_by_table_purse_deletion", - "SELECT" - " purse_deletion_serial_id" - ",purse_pub" - ",purse_sig" - " FROM purse_deletion" - " WHERE purse_deletion_serial_id > $1" - " ORDER BY purse_deletion_serial_id ASC;"); - rh = &lrbt_cb_table_purse_deletion; - break; - case TALER_EXCHANGEDB_RT_WITHDRAW: - XPREPARE ("select_above_serial_by_table_withdraw", - "SELECT" - " withdraw_id" - ",planchets_h" - ",execution_date" - ",amount_with_fee" - ",reserve_pub" - ",reserve_sig" - ",max_age" - ",noreveal_index" - ",selected_h" - ",blinding_seed" - ",cs_r_values" - ",cs_r_choices" - ",denom_serials" - ",denom_sigs" - " FROM withdraw" - " WHERE withdraw_id > $1" - " ORDER BY withdraw_id ASC;"); - rh = &lrbt_cb_table_withdraw; - break; - case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES: - XPREPARE ("select_above_serial_by_table_legitimization_measures", - "SELECT" - " legitimization_measure_serial_id AS serial" - ",access_token" - ",start_time" - ",jmeasures::TEXT" - ",display_priority" - " FROM legitimization_measures" - " WHERE legitimization_measure_serial_id > $1" - " ORDER BY legitimization_measure_serial_id ASC;"); - rh = &lrbt_cb_table_legitimization_measures; - break; - case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES: - XPREPARE ("select_above_serial_by_table_legitimization_outcomes", - "SELECT" - " outcome_serial_id AS serial" - ",h_payto" - ",decision_time" - ",expiration_time" - ",jproperties::TEXT" - ",to_investigate" - ",jnew_rules::TEXT" - " FROM legitimization_outcomes" - " WHERE outcome_serial_id > $1" - " ORDER BY outcome_serial_id ASC;"); - rh = &lrbt_cb_table_legitimization_outcomes; - break; - case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES: - XPREPARE ("select_above_serial_by_table_legitimization_processes", - "SELECT" - " legitimization_process_serial_id AS serial" - ",h_payto" - ",start_time" - ",expiration_time" - ",legitimization_measure_serial_id" - ",measure_index" - ",provider_name" - ",provider_user_id" - ",provider_legitimization_id" - ",redirect_url" - " FROM legitimization_processes" - " WHERE legitimization_process_serial_id > $1" - " ORDER BY legitimization_process_serial_id ASC;"); - rh = &lrbt_cb_table_legitimization_processes; - break; - case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES: - XPREPARE ("select_above_serial_by_table_kyc_attributes", - "SELECT" - " kyc_attributes_serial_id" - ",h_payto" - ",legitimization_serial" - ",collection_time" - ",expiration_time" - ",trigger_outcome_serial" - ",encrypted_attributes" - " FROM kyc_attributes" - " WHERE kyc_attributes_serial_id > $1" - " ORDER BY kyc_attributes_serial_id ASC;"); - rh = &lrbt_cb_table_kyc_attributes; - break; - case TALER_EXCHANGEDB_RT_AML_HISTORY: - XPREPARE ("select_above_serial_by_table_aml_history", - "SELECT" - " aml_history_serial_id" - ",h_payto" - ",outcome_serial_id" - ",justification" - ",decider_pub" - ",decider_sig" - " FROM aml_history" - " WHERE aml_history_serial_id > $1" - " ORDER BY aml_history_serial_id ASC;"); - rh = &lrbt_cb_table_aml_history; - break; - case TALER_EXCHANGEDB_RT_KYC_EVENTS: - XPREPARE ("select_above_serial_by_table_kyc_events", - "SELECT" - " kyc_event_serial_id AS serial" - ",event_timestamp" - ",event_type" - " FROM kyc_events" - " WHERE kyc_event_serial_id > $1" - " ORDER BY kyc_event_serial_id ASC;"); - rh = &lrbt_cb_table_kyc_events; - break; - } - if (NULL == rh) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - statement, - params, - rh, - &ctx); - if (qs < 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to run `%s'\n", - statement); - return qs; - } - if (ctx.error) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - return qs; -} - - -#undef XPREPARE - -/* end of pg_lookup_records_by_table.c */ diff --git a/src/exchangedb/pg_lookup_rules_by_access_token.c b/src/exchangedb/pg_lookup_rules_by_access_token.c @@ -1,66 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_lookup_rules_by_access_token.c - * @brief Implementation of the lookup_rules_by_access_token function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_rules_by_access_token.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_rules_by_access_token ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - json_t **jnew_rules, - uint64_t *rowid) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ( - "jnew_rules", - jnew_rules), - NULL), - GNUNET_PQ_result_spec_uint64 ( - "row_id", - rowid), - GNUNET_PQ_result_spec_end - }; - - *jnew_rules = NULL; - PREPARE (pg, - "lookup_rules_by_access_token", - "SELECT" - " jnew_rules::TEXT" - ",outcome_serial_id AS row_id" - " FROM legitimization_outcomes" - " WHERE h_payto=$1" - " AND is_active" - " ORDER BY expiration_time DESC," - " outcome_serial_id DESC" - " LIMIT 1;"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "lookup_rules_by_access_token", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_serial_by_table.c b/src/exchangedb/pg_lookup_serial_by_table.c @@ -1,465 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2024 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/> - */ -/** - * @file pg_lookup_serial_by_table.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_serial_by_table.h" -#include "helper.h" - - -/** - * Assign statement to @a n and PREPARE - * @a sql under name @a n. - */ -#define XPREPARE(n,sql) \ - statement = n; \ - PREPARE (pg, n, sql); - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_serial_by_table (struct - TALER_EXCHANGEDB_PostgresContext *pg, - enum TALER_EXCHANGEDB_ReplicatedTable - table, - uint64_t *serial) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial", - serial), - GNUNET_PQ_result_spec_end - }; - const char *statement = NULL; - - switch (table) - { - case TALER_EXCHANGEDB_RT_DENOMINATIONS: - XPREPARE ("select_serial_by_table_denominations", - "SELECT" - " denominations_serial AS serial" - " FROM denominations" - " ORDER BY denominations_serial DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS: - XPREPARE ("select_serial_by_table_denomination_revocations", - "SELECT" - " denom_revocations_serial_id AS serial" - " FROM denomination_revocations" - " ORDER BY denom_revocations_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_WIRE_TARGETS: - XPREPARE ("select_serial_by_table_wire_targets", - "SELECT" - " wire_target_serial_id AS serial" - " FROM wire_targets" - " ORDER BY wire_target_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_KYC_TARGETS: - XPREPARE ("select_serial_by_table_kyc_targets", - "SELECT" - " kyc_target_serial_id AS serial" - " FROM kyc_targets" - " ORDER BY kyc_target_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_RESERVES: - XPREPARE ("select_serial_by_table_reserves", - "SELECT" - " reserve_uuid AS serial" - " FROM reserves" - " ORDER BY reserve_uuid DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_RESERVES_IN: - XPREPARE ("select_serial_by_table_reserves_in", - "SELECT" - " reserve_in_serial_id AS serial" - " FROM reserves_in" - " ORDER BY reserve_in_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_KYCAUTHS_IN: - XPREPARE ("select_serial_by_table_kycauths_in", - "SELECT" - " kycauth_in_serial_id AS serial" - " FROM kycauths_in" - " ORDER BY kycauths_in_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_RESERVES_CLOSE: - XPREPARE ("select_serial_by_table_reserves_close", - "SELECT" - " close_uuid AS serial" - " FROM reserves_close" - " ORDER BY close_uuid DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS: - XPREPARE ("select_serial_by_table_reserves_open_requests", - "SELECT" - " open_request_uuid AS serial" - " FROM reserves_open_requests" - " ORDER BY open_request_uuid DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS: - XPREPARE ("select_serial_by_table_reserves_open_deposits", - "SELECT" - " reserve_open_deposit_uuid AS serial" - " FROM reserves_open_deposits" - " ORDER BY reserve_open_deposit_uuid DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_AUDITORS: - XPREPARE ("select_serial_by_table_auditors", - "SELECT" - " auditor_uuid AS serial" - " FROM auditors" - " ORDER BY auditor_uuid DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS: - XPREPARE ("select_serial_by_table_auditor_denom_sigs", - "SELECT" - " auditor_denom_serial AS serial" - " FROM auditor_denom_sigs" - " ORDER BY auditor_denom_serial DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS: - XPREPARE ("select_serial_by_table_exchange_sign_keys", - "SELECT" - " esk_serial AS serial" - " FROM exchange_sign_keys" - " ORDER BY esk_serial DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS: - XPREPARE ("select_serial_by_table_signkey_revocations", - "SELECT" - " signkey_revocations_serial_id AS serial" - " FROM signkey_revocations" - " ORDER BY signkey_revocations_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_KNOWN_COINS: - XPREPARE ("select_serial_by_table_known_coins", - "SELECT" - " known_coin_id AS serial" - " FROM known_coins" - " ORDER BY known_coin_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_REFRESH: - XPREPARE ("select_serial_by_table_refresh", - "SELECT" - " refresh_id AS serial" - " FROM refresh" - " ORDER BY refresh_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS: - XPREPARE ("select_serial_by_table_batch_deposits", - "SELECT" - " batch_deposit_serial_id AS serial" - " FROM batch_deposits" - " ORDER BY batch_deposit_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_COIN_DEPOSITS: - XPREPARE ("select_serial_by_table_coin_deposits", - "SELECT" - " coin_deposit_serial_id AS serial" - " FROM coin_deposits" - " ORDER BY coin_deposit_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_REFUNDS: - XPREPARE ("select_serial_by_table_refunds", - "SELECT" - " refund_serial_id AS serial" - " FROM refunds" - " ORDER BY refund_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_WIRE_OUT: - XPREPARE ("select_serial_by_table_wire_out", - "SELECT" - " wireout_uuid AS serial" - " FROM wire_out" - " ORDER BY wireout_uuid DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING: - XPREPARE ("select_serial_by_table_aggregation_tracking", - "SELECT" - " aggregation_serial_id AS serial" - " FROM aggregation_tracking" - " ORDER BY aggregation_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_WIRE_FEE: - XPREPARE ("select_serial_by_table_wire_fee", - "SELECT" - " wire_fee_serial AS serial" - " FROM wire_fee" - " ORDER BY wire_fee_serial DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_GLOBAL_FEE: - XPREPARE ("select_serial_by_table_global_fee", - "SELECT" - " global_fee_serial AS serial" - " FROM global_fee" - " ORDER BY global_fee_serial DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_RECOUP: - XPREPARE ("select_serial_by_table_recoup", - "SELECT" - " recoup_uuid AS serial" - " FROM recoup" - " ORDER BY recoup_uuid DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_RECOUP_REFRESH: - XPREPARE ("select_serial_by_table_recoup_refresh", - "SELECT" - " recoup_refresh_uuid AS serial" - " FROM recoup_refresh" - " ORDER BY recoup_refresh_uuid DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_EXTENSIONS: - XPREPARE ("select_serial_by_table_extensions", - "SELECT" - " extension_id AS serial" - " FROM extensions" - " ORDER BY extension_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_POLICY_DETAILS: - XPREPARE ("select_serial_by_table_policy_details", - "SELECT" - " policy_details_serial_id AS serial" - " FROM policy_details" - " ORDER BY policy_details_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS: - XPREPARE ("select_serial_by_table_policy_fulfillments", - "SELECT" - " fulfillment_id AS serial" - " FROM policy_fulfillments" - " ORDER BY fulfillment_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_PURSE_REQUESTS: - XPREPARE ("select_serial_by_table_purse_requests", - "SELECT" - " purse_requests_serial_id AS serial" - " FROM purse_requests" - " ORDER BY purse_requests_serial_id DESC" - " LIMIT 1;") - break; - case TALER_EXCHANGEDB_RT_PURSE_DECISION: - XPREPARE ("select_serial_by_table_purse_decision", - "SELECT" - " purse_decision_serial_id AS serial" - " FROM purse_decision" - " ORDER BY purse_decision_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_PURSE_MERGES: - XPREPARE ("select_serial_by_table_purse_merges", - "SELECT" - " purse_merge_request_serial_id AS serial" - " FROM purse_merges" - " ORDER BY purse_merge_request_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS: - XPREPARE ("select_serial_by_table_purse_deposits", - "SELECT" - " purse_deposit_serial_id AS serial" - " FROM purse_deposits" - " ORDER BY purse_deposit_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES: - XPREPARE ("select_serial_by_table_account_merges", - "SELECT" - " account_merge_request_serial_id AS serial" - " FROM account_merges" - " ORDER BY account_merge_request_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS: - XPREPARE ("select_serial_by_table_history_requests", - "SELECT" - " history_request_serial_id AS serial" - " FROM history_requests" - " ORDER BY history_request_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS: - XPREPARE ("select_serial_by_table_close_requests", - "SELECT" - " close_request_serial_id AS serial" - " FROM close_requests" - " ORDER BY close_request_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_WADS_OUT: - XPREPARE ("select_serial_by_table_wads_out", - "SELECT" - " wad_out_serial_id AS serial" - " FROM wads_out" - " ORDER BY wad_out_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES: - XPREPARE ("select_serial_by_table_wads_out_entries", - "SELECT" - " wad_out_entry_serial_id AS serial" - " FROM wad_out_entries" - " ORDER BY wad_out_entry_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_WADS_IN: - XPREPARE ("select_serial_by_table_wads_in", - "SELECT" - " wad_in_serial_id AS serial" - " FROM wads_in" - " ORDER BY wad_in_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES: - XPREPARE ("select_serial_by_table_wads_in_entries", - "SELECT" - " wad_in_entry_serial_id AS serial" - " FROM wad_in_entries" - " ORDER BY wad_in_entry_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_PROFIT_DRAINS: - XPREPARE ("select_serial_by_table_profit_drains", - "SELECT" - " profit_drain_serial_id AS serial" - " FROM profit_drains" - " ORDER BY profit_drain_serial_id DESC" - " LIMIT 1;"); - statement = "select_serial_by_table_profit_drains"; - break; - case TALER_EXCHANGEDB_RT_AML_STAFF: - XPREPARE ("select_serial_by_table_aml_staff", - "SELECT" - " aml_staff_uuid AS serial" - " FROM aml_staff" - " ORDER BY aml_staff_uuid DESC" - " LIMIT 1;"); - statement = "select_serial_by_table_aml_staff"; - break; - case TALER_EXCHANGEDB_RT_PURSE_DELETION: - XPREPARE ("select_serial_by_table_purse_deletion", - "SELECT" - " purse_deletion_serial_id AS serial" - " FROM purse_deletion" - " ORDER BY purse_deletion_serial_id DESC" - " LIMIT 1;"); - statement = "select_serial_by_table_purse_deletion"; - break; - case TALER_EXCHANGEDB_RT_WITHDRAW: - XPREPARE ("select_serial_by_table_withdraw", - "SELECT" - " withdraw_id AS serial" - " FROM withdraw" - " ORDER BY withdraw_id DESC" - " LIMIT 1;"); - statement = "select_serial_by_table_withdraw"; - break; - case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES: - XPREPARE ("select_serial_by_table_legitimization_measures", - "SELECT" - " legitimization_measure_serial_id AS serial" - " FROM legitimization_measures" - " ORDER BY legitimization_measure_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES: - XPREPARE ("select_serial_by_table_legitimization_outcomes", - "SELECT" - " outcome_serial_id AS serial" - " FROM legitimization_outcomes" - " ORDER BY outcome_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES: - XPREPARE ("select_serial_by_table_legitimization_processes", - "SELECT" - " legitimization_process_serial_id AS serial" - " FROM legitimization_processes" - " ORDER BY legitimization_process_serial_id DESC" - " LIMIT 1;"); - break; - case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES: - XPREPARE ("select_serial_by_table_kyc_attributes", - "SELECT" - " kyc_attributes_serial_id AS serial" - " FROM kyc_attributes" - " ORDER BY kyc_attributes_serial_id DESC" - " LIMIT 1;"); - statement = "select_serial_by_table_kyc_attributes"; - break; - case TALER_EXCHANGEDB_RT_AML_HISTORY: - XPREPARE ("select_serial_by_table_aml_history", - "SELECT" - " aml_history_serial_id AS serial" - " FROM aml_history" - " ORDER BY aml_history_serial_id DESC" - " LIMIT 1;"); - statement = "select_serial_by_table_aml_history"; - break; - case TALER_EXCHANGEDB_RT_KYC_EVENTS: - XPREPARE ("select_serial_by_table_kyc_events", - "SELECT" - " kyc_event_serial_id AS serial" - " FROM kyc_events" - " ORDER BY kyc_event_serial_id DESC" - " LIMIT 1;"); - break; - } - if (NULL == statement) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - statement, - params, - rs); -} - - -#undef XPREPARE diff --git a/src/exchangedb/pg_lookup_signing_key.c b/src/exchangedb/pg_lookup_signing_key.c @@ -1,60 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_lookup_signing_key.c - * @brief Implementation of the lookup_signing_key function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_signing_key.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_signing_key ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ExchangePublicKeyP *exchange_pub, - struct TALER_EXCHANGEDB_SignkeyMetaData *meta) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (exchange_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("valid_from", - &meta->start), - GNUNET_PQ_result_spec_timestamp ("expire_sign", - &meta->expire_sign), - GNUNET_PQ_result_spec_timestamp ("expire_legal", - &meta->expire_legal), - GNUNET_PQ_result_spec_end - }; - - - PREPARE (pg, - "lookup_signing_key", - "SELECT" - " valid_from" - ",expire_sign" - ",expire_legal" - " FROM exchange_sign_keys" - " WHERE exchange_pub=$1"); - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_signing_key", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_signkey_revocation.c b/src/exchangedb/pg_lookup_signkey_revocation.c @@ -1,55 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_lookup_signkey_revocation.c - * @brief Implementation of the lookup_signkey_revocation function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_signkey_revocation.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_signkey_revocation ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ExchangePublicKeyP *exchange_pub, - struct TALER_MasterSignatureP *master_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (exchange_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - master_sig), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "lookup_signkey_revocation", - "SELECT " - " master_sig" - " FROM signkey_revocations" - " WHERE esk_serial=" - " (SELECT esk_serial" - " FROM exchange_sign_keys" - " WHERE exchange_pub=$1);"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_signkey_revocation", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_transfer_by_deposit.c b/src/exchangedb/pg_lookup_transfer_by_deposit.c @@ -1,220 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2024 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/> - */ -/** - * @file exchangedb/pg_lookup_transfer_by_deposit.c - * @brief Implementation of the lookup_transfer_by_deposit function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_transfer_by_deposit.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_transfer_by_deposit ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PrivateContractHashP *h_contract_terms, - const struct TALER_MerchantWireHashP *h_wire, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_MerchantPublicKeyP *merchant_pub, - bool *pending, - struct TALER_WireTransferIdentifierRawP *wtid, - struct GNUNET_TIME_Timestamp *exec_time, - struct TALER_Amount *amount_with_fee, - struct TALER_Amount *deposit_fee, - struct TALER_EXCHANGEDB_KycStatus *kyc, - union TALER_AccountPublicKeyP *account_pub) -{ - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_end - }; - struct TALER_FullPayto payto_uri; - struct TALER_WireSaltP wire_salt; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", - wtid), - GNUNET_PQ_result_spec_auto_from_type ("wire_salt", - &wire_salt), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri.full_payto), - GNUNET_PQ_result_spec_timestamp ("execution_date", - exec_time), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - amount_with_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - deposit_fee), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("target_pub", - account_pub), - NULL), - GNUNET_PQ_result_spec_end - }; - - memset (kyc, - 0, - sizeof (*kyc)); - /* check if the aggregation record exists and get it */ - PREPARE (pg, - "lookup_deposit_wtid", - "SELECT" - " atr.wtid_raw" - ",wire_out.execution_date" - ",cdep.amount_with_fee" - ",bdep.wire_salt" - ",wt.payto_uri" - ",kt.target_pub" - ",denom.fee_deposit" - " FROM coin_deposits cdep" - " JOIN batch_deposits bdep" - " USING (batch_deposit_serial_id)" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - /* kyc_targets might not match; then target_pub will be NULL */ - " LEFT JOIN kyc_targets kt" - " USING (h_normalized_payto)" - " JOIN aggregation_tracking atr" - " ON (cdep.batch_deposit_serial_id = atr.batch_deposit_serial_id)" - " JOIN known_coins kc" - " ON (kc.coin_pub = cdep.coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " JOIN wire_out" - " USING (wtid_raw)" - " WHERE cdep.coin_pub=$1" - " AND bdep.merchant_pub=$3" - " AND bdep.h_contract_terms=$2"); - /* NOTE: above query might be more efficient if we computed the shard - from the merchant_pub and included that in the query */ - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_deposit_wtid", - params, - rs); - if (0 > qs) - return qs; - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) - { - struct TALER_MerchantWireHashP wh; - - TALER_merchant_wire_signature_hash (payto_uri, - &wire_salt, - &wh); - if (0 == - GNUNET_memcmp (&wh, - h_wire)) - { - *pending = false; - kyc->ok = true; - GNUNET_PQ_cleanup_result (rs); - return qs; - } - qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - GNUNET_PQ_cleanup_result (rs); - } - *pending = true; - memset (wtid, - 0, - sizeof (*wtid)); - GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "lookup_deposit_wtid returned 0 matching rows\n"); - { - /* Check if transaction exists in deposits, so that we just - do not have a WTID yet. In that case, return without wtid - (by setting 'pending' true). */ - struct GNUNET_PQ_ResultSpec rs2[] = { - GNUNET_PQ_result_spec_auto_from_type ("wire_salt", - &wire_salt), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri.full_payto), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - amount_with_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - deposit_fee), - GNUNET_PQ_result_spec_timestamp ("wire_deadline", - exec_time), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ("legitimization_requirement_serial_id", - &kyc->requirement_row), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("target_pub", - account_pub), - NULL), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "get_deposit_without_wtid", - "SELECT" - " bdep.wire_salt" - ",wt.payto_uri" - ",cdep.amount_with_fee" - ",denom.fee_deposit" - ",bdep.wire_deadline" - ",agt.legitimization_requirement_serial_id" - ",kt.target_pub" - " FROM coin_deposits cdep" - " JOIN batch_deposits bdep" - " USING (batch_deposit_serial_id)" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - /* kyc_targets might not match; then target_pub will be NULL */ - " LEFT JOIN kyc_targets kt" - " USING (h_normalized_payto)" - " JOIN known_coins kc" - " ON (kc.coin_pub = cdep.coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " LEFT JOIN aggregation_transient agt " - " ON ( (bdep.wire_target_h_payto = agt.wire_target_h_payto) AND" - " (bdep.merchant_pub = agt.merchant_pub) )" - " WHERE cdep.coin_pub=$1" - " AND bdep.merchant_pub=$3" - " AND bdep.h_contract_terms=$2" - " LIMIT 1;"); - /* NOTE: above query might be more efficient if we computed the shard - from the merchant_pub and included that in the query */ - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_deposit_without_wtid", - params, - rs2); - if (0 > qs) - return qs; - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) - { - struct TALER_MerchantWireHashP wh; - - TALER_merchant_wire_signature_hash (payto_uri, - &wire_salt, - &wh); - if (0 != - GNUNET_memcmp (&wh, - h_wire)) - { - GNUNET_PQ_cleanup_result (rs2); - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - GNUNET_PQ_cleanup_result (rs2); - if (0 == kyc->requirement_row) - kyc->ok = true; /* technically: unknown */ - } - return qs; - } -} diff --git a/src/exchangedb/pg_lookup_wire_fee_by_time.c b/src/exchangedb/pg_lookup_wire_fee_by_time.c @@ -1,152 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_lookup_wire_fee_by_time.c - * @brief Implementation of the lookup_wire_fee_by_time function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_wire_fee_by_time.h" -#include "helper.h" - - -/** - * Closure for #wire_fee_by_time_helper() - */ -struct WireFeeLookupContext -{ - - /** - * Set to the wire fees. Set to invalid if fees conflict over - * the given time period. - */ - struct TALER_WireFeeSet *fees; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; -}; - - -/** - * Helper function for #TALER_EXCHANGEDB_lookup_wire_fee_by_time(). - * Calls the callback with the wire fee structure. - * - * @param cls a `struct WireFeeLookupContext` - * @param result db results - * @param num_results number of results in @a result - */ -static void -wire_fee_by_time_helper (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct WireFeeLookupContext *wlc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = wlc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_WireFeeSet fs; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", - &fs.wire), - TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", - &fs.closing), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - /* invalidate */ - memset (wlc->fees, - 0, - sizeof (struct TALER_WireFeeSet)); - return; - } - if (0 == i) - { - *wlc->fees = fs; - continue; - } - if (0 != - TALER_wire_fee_set_cmp (&fs, - wlc->fees)) - { - /* invalidate */ - memset (wlc->fees, - 0, - sizeof (struct TALER_WireFeeSet)); - return; - } - } -} - - -/** - * Lookup information about known wire fees. Finds all applicable - * fees in the given range. If they are identical, returns the - * respective @a fees. If any of the fees - * differ between @a start_time and @a end_time, the transaction - * succeeds BUT returns an invalid amount for both fees. - * - * @param pg the database context - * @param wire_method the wire method to lookup fees for - * @param start_time starting time of fee - * @param end_time end time of fee - * @param[out] fees wire fees for that time period; if - * different fees exists within this time - * period, an 'invalid' amount is returned. - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_wire_fee_by_time ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *wire_method, - struct GNUNET_TIME_Timestamp start_time, - struct GNUNET_TIME_Timestamp end_time, - struct TALER_WireFeeSet *fees) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (wire_method), - GNUNET_PQ_query_param_timestamp (&start_time), - GNUNET_PQ_query_param_timestamp (&end_time), - GNUNET_PQ_query_param_end - }; - struct WireFeeLookupContext wlc = { - .fees = fees, - .pg = pg - }; - - PREPARE (pg, - "lookup_wire_fee_by_time", - "SELECT" - " wire_fee" - ",closing_fee" - " FROM wire_fee" - " WHERE wire_method=$1" - " AND end_date > $2" - " AND start_date < $3;"); - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "lookup_wire_fee_by_time", - params, - &wire_fee_by_time_helper, - &wlc); -} diff --git a/src/exchangedb/pg_lookup_wire_timestamp.c b/src/exchangedb/pg_lookup_wire_timestamp.c @@ -1,52 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_lookup_wire_timestamp.c - * @brief Implementation of the lookup_wire_timestamp function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_wire_timestamp.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_wire_timestamp (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_FullPayto payto_uri, - struct GNUNET_TIME_Timestamp *last_date) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (payto_uri.full_payto), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("last_change", - last_date), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "lookup_wire_timestamp", - "SELECT" - " last_change" - " FROM wire_accounts" - " WHERE payto_uri=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_wire_timestamp", - params, - rs); -} diff --git a/src/exchangedb/pg_lookup_wire_transfer.c b/src/exchangedb/pg_lookup_wire_transfer.c @@ -1,184 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2024 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/> - */ -/** - * @file exchangedb/pg_lookup_wire_transfer.c - * @brief Implementation of the lookup_wire_transfer function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/lookup_wire_transfer.h" -#include "helper.h" - -/** - * Closure for #handle_wt_result. - */ -struct WireTransferResultContext -{ - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_AggregationDataCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on serious errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. Helper function - * for #TALER_EXCHANGEDB_lookup_wire_transfer(). - * - * @param cls closure of type `struct WireTransferResultContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -handle_wt_result (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct WireTransferResultContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - struct TALER_PrivateContractHashP h_contract_terms; - struct TALER_CoinSpendPublicKeyP coin_pub; - struct TALER_FullPaytoHashP h_payto; - struct TALER_MerchantPublicKeyP merchant_pub; - struct GNUNET_TIME_Timestamp exec_time; - struct TALER_Amount amount_with_fee; - struct TALER_Amount deposit_fee; - struct TALER_DenominationPublicKey denom_pub; - struct TALER_FullPayto payto_uri; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", - &rowid), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - &h_contract_terms), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri.full_payto), - GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto", - &h_payto), - TALER_PQ_result_spec_denom_pub ("denom_pub", - &denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &coin_pub), - GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", - &merchant_pub), - GNUNET_PQ_result_spec_timestamp ("execution_date", - &exec_time), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &amount_with_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &deposit_fee), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ctx->cb (ctx->cb_cls, - rowid, - &merchant_pub, - payto_uri, - &h_payto, - exec_time, - &h_contract_terms, - &denom_pub, - &coin_pub, - &amount_with_fee, - &deposit_fee); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_lookup_wire_transfer ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_WireTransferIdentifierRawP *wtid, - TALER_EXCHANGEDB_AggregationDataCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (wtid), - GNUNET_PQ_query_param_end - }; - struct WireTransferResultContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "lookup_transactions", - "SELECT" - " aggregation_serial_id" - ",bdep.h_contract_terms" - ",payto_uri" - ",wt.wire_target_h_payto" - ",kc.coin_pub" - ",bdep.merchant_pub" - ",wire_out.execution_date" - ",cdep.amount_with_fee" - ",denom.fee_deposit" - ",denom.denom_pub" - " FROM aggregation_tracking" - " JOIN batch_deposits bdep" - " USING (batch_deposit_serial_id)" - " JOIN coin_deposits cdep" - " USING (batch_deposit_serial_id)" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " JOIN known_coins kc" - " USING (coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " JOIN wire_out" - " USING (wtid_raw)" - " WHERE wtid_raw=$1;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "lookup_transactions", - params, - &handle_wt_result, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_mark_refresh_reveal_success.c b/src/exchangedb/pg_mark_refresh_reveal_success.c @@ -1,45 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_mark_refresh_reveal_success.c - * @brief Implementation of the mark_refresh_reveal_success function for Postgres - * @author Özgür Kesim - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/mark_refresh_reveal_success.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_mark_refresh_reveal_success ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_RefreshCommitmentP *rc) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (rc), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "mark_refresh_reveal_success", - "UPDATE refresh" - " SET revealed=true" - " WHERE rc = $1"); - - return GNUNET_PQ_eval_prepared_non_select ( - pg->conn, - "mark_refresh_reveal_success", - params); -} diff --git a/src/exchangedb/pg_persist_kyc_attributes.c b/src/exchangedb/pg_persist_kyc_attributes.c @@ -1,103 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_persist_kyc_attributes.c - * @brief Implementation of the persist_kyc_attributes function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/persist_kyc_attributes.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_persist_kyc_attributes ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t process_row, - const struct TALER_NormalizedPaytoHashP *h_payto, - const char *provider_name, - const char *provider_account_id, - const char *provider_legitimization_id, - uint32_t birthday, - struct GNUNET_TIME_Absolute expiration_time, - const char *form_name, - size_t enc_attributes_size, - const void *enc_attributes) -{ - struct GNUNET_TIME_Timestamp collection_time - = GNUNET_TIME_timestamp_get (); - struct GNUNET_TIME_Timestamp expiration - = GNUNET_TIME_absolute_to_timestamp (expiration_time); - struct TALER_EXCHANGEDB_KycCompletedEventP rep = { - .header.size = htons (sizeof (rep)), - .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), - .h_payto = *h_payto - }; - char *kyc_completed_notify_s - = GNUNET_PQ_get_event_notify_channel (&rep.header); - struct GNUNET_PQ_QueryParam params[] = { - (0 == process_row) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 (&process_row), - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_uint32 (&birthday), - GNUNET_PQ_query_param_string (provider_name), - (NULL == provider_account_id) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (provider_account_id), - (NULL == provider_legitimization_id) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (provider_legitimization_id), - GNUNET_PQ_query_param_timestamp (&collection_time), - GNUNET_PQ_query_param_absolute_time (&expiration_time), - GNUNET_PQ_query_param_timestamp (&expiration), - (NULL == enc_attributes) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_fixed_size (enc_attributes, - enc_attributes_size), - GNUNET_PQ_query_param_string (kyc_completed_notify_s), - (NULL == form_name) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (form_name), - GNUNET_PQ_query_param_end - }; - bool ok; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("out_ok", - &ok), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Inserting KYC attributes, wake up on %s\n", - kyc_completed_notify_s); - GNUNET_break (NULL != h_payto); - PREPARE (pg, - "persist_kyc_attributes", - "SELECT " - " out_ok" - " FROM exchange_do_persist_kyc_attributes " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "persist_kyc_attributes", - params, - rs); - GNUNET_PQ_cleanup_query_params_closures (params); - GNUNET_free (kyc_completed_notify_s); - GNUNET_PQ_event_do_poll (pg->conn); - return qs; -} diff --git a/src/exchangedb/pg_persist_policy_details.c b/src/exchangedb/pg_persist_policy_details.c @@ -1,74 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_persist_policy_details.c - * @brief Implementation of the persist_policy_details function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/persist_policy_details.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_persist_policy_details ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PolicyDetails *details, - uint64_t *policy_details_serial_id, - struct TALER_Amount *accumulated_total, - enum TALER_PolicyFulfillmentState *fulfillment_state) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&details->hash_code), - TALER_PQ_query_param_json (details->policy_json), - GNUNET_PQ_query_param_timestamp (&details->deadline), - TALER_PQ_query_param_amount (pg->conn, - &details->commitment), - TALER_PQ_query_param_amount (pg->conn, - &details->accumulated_total), - TALER_PQ_query_param_amount (pg->conn, - &details->policy_fee), - TALER_PQ_query_param_amount (pg->conn, - &details->transferable_amount), - GNUNET_PQ_query_param_auto_from_type (&details->fulfillment_state), - (details->no_policy_fulfillment_id) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 (&details->policy_fulfillment_id), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id", - policy_details_serial_id), - TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total", - accumulated_total), - GNUNET_PQ_result_spec_uint32 ("fulfillment_state", - fulfillment_state), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "call_insert_or_update_policy_details", - "SELECT" - " out_policy_details_serial_id AS policy_details_serial_id" - ",out_accumulated_total AS accumulated_total" - ",out_fulfillment_state AS fulfillment_state" - " FROM exchange_do_insert_or_update_policy_details" - "($1, $2, $3, $4, $5, $6, $7, $8, $9);"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_insert_or_update_policy_details", - params, - rs); -} diff --git a/src/exchangedb/pg_preflight.c b/src/exchangedb/pg_preflight.c @@ -1,111 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_preflight.c - * @brief Implementation of the preflight function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/preflight.h" -#include "helper.h" - - -static enum GNUNET_GenericReturnValue -internal_setup (struct TALER_EXCHANGEDB_PostgresContext *pg) -{ - if (NULL == pg->conn) - { -#if AUTO_EXPLAIN - /* Enable verbose logging to see where queries do not - properly use indices */ - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_try_execute ("LOAD 'auto_explain';"), - GNUNET_PQ_make_try_execute ("SET auto_explain.log_min_duration=50;"), - GNUNET_PQ_make_try_execute ("SET auto_explain.log_timing=TRUE;"), - GNUNET_PQ_make_try_execute ("SET auto_explain.log_analyze=TRUE;"), - /* https://wiki.postgresql.org/wiki/Serializable suggests to really - force the default to 'serializable' if SSI is to be used. */ - GNUNET_PQ_make_try_execute ( - "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"), - GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"), - GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"), - GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), - /* Mergejoin causes issues, see Postgres #18380 */ - GNUNET_PQ_make_try_execute ("SET enable_mergejoin=OFF;"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; -#else - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_try_execute ( - "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"), - GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"), - GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"), - /* Mergejoin causes issues, see Postgres #18380 */ - GNUNET_PQ_make_try_execute ("SET enable_mergejoin=OFF;"), - GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; -#endif - struct GNUNET_PQ_Context *db_conn; - - db_conn = GNUNET_PQ_connect_with_cfg2 (pg->cfg, - "exchangedb-postgres", - "exchange-", /* load_path_suffix */ - es, - NULL /* prepared statements */, - GNUNET_PQ_FLAG_CHECK_CURRENT); - if (NULL == db_conn) - return GNUNET_SYSERR; - - pg->prep_gen++; - pg->conn = db_conn; - } - if (NULL == pg->transaction_name) - GNUNET_PQ_reconnect_if_down (pg->conn); - return GNUNET_OK; -} - - -enum GNUNET_GenericReturnValue -TALER_EXCHANGEDB_preflight (struct TALER_EXCHANGEDB_PostgresContext *pg) -{ - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_execute ("ROLLBACK"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - - if (GNUNET_OK != - internal_setup (pg)) - return GNUNET_SYSERR; - if (NULL == pg->transaction_name) - return GNUNET_OK; /* all good */ - if (GNUNET_OK == - GNUNET_PQ_exec_statements (pg->conn, - es)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "BUG: Preflight check rolled back transaction `%s'!\n", - pg->transaction_name); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "BUG: Preflight check failed to rollback transaction `%s'!\n", - pg->transaction_name); - } - pg->transaction_name = NULL; - return GNUNET_NO; -} diff --git a/src/exchangedb/pg_profit_drains_get_pending.c b/src/exchangedb/pg_profit_drains_get_pending.c @@ -1,75 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_profit_drains_get_pending.c - * @brief Implementation of the profit_drains_get_pending function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/profit_drains_get_pending.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_profit_drains_get_pending ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t *serial, - struct TALER_WireTransferIdentifierRawP *wtid, - char **account_section, - struct TALER_FullPayto *payto_uri, - struct GNUNET_TIME_Timestamp *request_timestamp, - struct TALER_Amount *amount, - struct TALER_MasterSignatureP *master_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("profit_drain_serial_id", - serial), - GNUNET_PQ_result_spec_auto_from_type ("wtid", - wtid), - GNUNET_PQ_result_spec_string ("account_section", - account_section), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri->full_payto), - GNUNET_PQ_result_spec_timestamp ("trigger_date", - request_timestamp), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - amount), - GNUNET_PQ_result_spec_auto_from_type ("master_sig", - master_sig), - GNUNET_PQ_result_spec_end - }; - /* Used in #postgres_profit_drains_get_pending() */ - PREPARE (pg, - "get_ready_profit_drain", - "SELECT" - " profit_drain_serial_id" - ",wtid" - ",account_section" - ",payto_uri" - ",trigger_date" - ",amount" - ",master_sig" - " FROM profit_drains" - " WHERE NOT executed" - " ORDER BY trigger_date ASC;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_ready_profit_drain", - params, - rs); -} diff --git a/src/exchangedb/pg_profit_drains_set_finished.c b/src/exchangedb/pg_profit_drains_set_finished.c @@ -1,45 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_profit_drains_set_finished.c - * @brief Implementation of the profit_drains_set_finished function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/profit_drains_set_finished.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_profit_drains_set_finished ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "drain_profit_set_finished", - "UPDATE profit_drains" - " SET" - " executed=TRUE" - " WHERE profit_drain_serial_id=$1;"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "drain_profit_set_finished", - params); -} diff --git a/src/exchangedb/pg_release_revolving_shard.c b/src/exchangedb/pg_release_revolving_shard.c @@ -1,56 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_release_revolving_shard.c - * @brief Implementation of the release_revolving_shard function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/release_revolving_shard.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_release_revolving_shard (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const char *job_name, - uint32_t start_row, - uint32_t end_row) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (job_name), - GNUNET_PQ_query_param_uint32 (&start_row), - GNUNET_PQ_query_param_uint32 (&end_row), - GNUNET_PQ_query_param_end - }; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Releasing revolving shard %s %u-%u\n", - job_name, - (unsigned int) start_row, - (unsigned int) end_row); - - - PREPARE (pg, - "release_revolving_shard", - "UPDATE revolving_work_shards" - " SET active=FALSE" - " WHERE job_name=$1" - " AND start_row=$2" - " AND end_row=$3"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "release_revolving_shard", - params); -} diff --git a/src/exchangedb/pg_reserves_get.c b/src/exchangedb/pg_reserves_get.c @@ -1,57 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_reserves_get.c - * @brief Implementation of the reserves_get function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/reserves_get.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_reserves_get (struct TALER_EXCHANGEDB_PostgresContext *pg, - struct TALER_EXCHANGEDB_Reserve *reserve) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&reserve->pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_amount ("current_balance", - pg->currency, - &reserve->balance), - GNUNET_PQ_result_spec_timestamp ("expiration_date", - &reserve->expiry), - GNUNET_PQ_result_spec_timestamp ("gc_date", - &reserve->gc), - GNUNET_PQ_result_spec_end - }; - /* Used in #postgres_reserves_get() */ - PREPARE (pg, - "reserves_get", - "SELECT" - " current_balance" - ",expiration_date" - ",gc_date" - " FROM reserves" - " WHERE reserve_pub=$1" - " LIMIT 1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "reserves_get", - params, - rs); -} diff --git a/src/exchangedb/pg_reserves_get_origin.c b/src/exchangedb/pg_reserves_get_origin.c @@ -1,61 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024, 2025 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/> - */ -/** - * @file exchangedb/pg_reserves_get_origin.c - * @brief Implementation of the reserves_get_origin function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/reserves_get_origin.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_reserves_get_origin ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct TALER_FullPaytoHashP *h_payto, - struct TALER_FullPayto *payto_uri) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ( - "wire_source_h_payto", - h_payto), - GNUNET_PQ_result_spec_string ( - "payto_uri", - &payto_uri->full_payto), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "get_h_wire_source_of_reserve", - "SELECT" - " rt.wire_source_h_payto" - ",wt.payto_uri" - " FROM reserves_in rt" - " JOIN wire_targets wt" - " ON (rt.wire_source_h_payto = wt.wire_target_h_payto)" - " WHERE rt.reserve_pub=$1"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "get_h_wire_source_of_reserve", - params, - rs); -} diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c @@ -1,374 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2024 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/> - */ -/** - * @file exchangedb/pg_reserves_in_insert.c - * @brief Implementation of the reserves_in_insert function for Postgres - * @author Christian Grothoff - * @author Joseph Xu - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/reserves_in_insert.h" -#include "helper.h" -#include "taler/exchange-database/start.h" -#include "taler/exchange-database/start_read_committed.h" -#include "taler/exchange-database/commit.h" -#include "taler/exchange-database/preflight.h" -#include "taler/exchange-database/rollback.h" - - -/** - * Generate event notification for the reserve change. - * - * @param reserve_pub reserve to notfiy on - * @return string to pass to postgres for the notification - */ -static char * -compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub) -{ - struct TALER_EXCHANGEDB_ReserveEventP rep = { - .header.size = htons (sizeof (rep)), - .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING), - .reserve_pub = *reserve_pub - }; - - return GNUNET_PQ_get_event_notify_channel (&rep.header); -} - - -/** - * Closure for our helper_cb() - */ -struct Context -{ - /** - * Array of reserve UUIDs to initialize. - */ - uint64_t *reserve_uuids; - - /** - * Array with entries set to 'true' for duplicate transactions. - */ - bool *transaction_duplicates; - - /** - * Array with entries set to 'true' for rows with conflicts. - */ - bool *conflicts; - - /** - * Set to #GNUNET_SYSERR on failures. - */ - enum GNUNET_GenericReturnValue status; - - /** - * Single value (no array) set to true if we need - * to follow-up with an update. - */ - bool needs_update; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct Context *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct Context *ctx = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ( - "transaction_duplicate", - &ctx->transaction_duplicates[i]), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ("ruuid", - &ctx->reserve_uuids[i]), - &ctx->conflicts[i]), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - if (! ctx->transaction_duplicates[i]) - ctx->needs_update |= ctx->conflicts[i]; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_reserves_in_insert ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, - unsigned int reserves_length, - enum GNUNET_DB_QueryStatus *results) -{ - unsigned int dups = 0; - - struct TALER_FullPaytoHashP h_full_paytos[ - GNUNET_NZL (reserves_length)]; - struct TALER_NormalizedPaytoHashP h_normalized_paytos[ - GNUNET_NZL (reserves_length)]; - char *notify_s[GNUNET_NZL (reserves_length)]; - struct TALER_ReservePublicKeyP reserve_pubs[GNUNET_NZL (reserves_length)]; - struct TALER_Amount balances[GNUNET_NZL (reserves_length)]; - struct GNUNET_TIME_Timestamp execution_times[GNUNET_NZL (reserves_length)]; - const char *sender_account_details[GNUNET_NZL (reserves_length)]; - const char *exchange_account_names[GNUNET_NZL (reserves_length)]; - uint64_t wire_references[GNUNET_NZL (reserves_length)]; - uint64_t reserve_uuids[GNUNET_NZL (reserves_length)]; - bool transaction_duplicates[GNUNET_NZL (reserves_length)]; - bool conflicts[GNUNET_NZL (reserves_length)]; - struct GNUNET_TIME_Timestamp reserve_expiration - = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time); - struct GNUNET_TIME_Timestamp gc - = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time); - enum GNUNET_DB_QueryStatus qs; - bool need_update; - - for (unsigned int i = 0; i<reserves_length; i++) - { - const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i]; - - TALER_full_payto_hash (reserve->sender_account_details, - &h_full_paytos[i]); - TALER_full_payto_normalize_and_hash (reserve->sender_account_details, - &h_normalized_paytos[i]); - notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub); - reserve_pubs[i] = *reserve->reserve_pub; - balances[i] = *reserve->balance; - execution_times[i] = reserve->execution_time; - sender_account_details[i] = reserve->sender_account_details.full_payto; - exchange_account_names[i] = reserve->exchange_account_name; - wire_references[i] = reserve->wire_reference; - } - - /* NOTE: kind-of pointless to explicitly start a transaction here... */ - if (GNUNET_OK != - TALER_EXCHANGEDB_preflight (pg)) - { - GNUNET_break (0); - qs = GNUNET_DB_STATUS_HARD_ERROR; - goto finished; - } - if (GNUNET_OK != - TALER_TALER_EXCHANGEDB_start_read_committed (pg, - "READ_COMMITED")) - { - GNUNET_break (0); - qs = GNUNET_DB_STATUS_HARD_ERROR; - goto finished; - } - PREPARE (pg, - "reserves_insert_with_array", - "SELECT" - " transaction_duplicate" - ",ruuid" - " FROM exchange_do_array_reserves_insert" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);"); - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&gc), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), - GNUNET_PQ_query_param_array_auto_from_type (reserves_length, - reserve_pubs, - pg->conn), - GNUNET_PQ_query_param_array_uint64 (reserves_length, - wire_references, - pg->conn), - TALER_PQ_query_param_array_amount ( - reserves_length, - balances, - pg->conn), - GNUNET_PQ_query_param_array_ptrs_string ( - reserves_length, - (const char **) exchange_account_names, - pg->conn), - GNUNET_PQ_query_param_array_timestamp ( - reserves_length, - execution_times, - pg->conn), - GNUNET_PQ_query_param_array_auto_from_type ( - reserves_length, - h_full_paytos, - pg->conn), - GNUNET_PQ_query_param_array_auto_from_type ( - reserves_length, - h_normalized_paytos, - pg->conn), - GNUNET_PQ_query_param_array_ptrs_string ( - reserves_length, - (const char **) sender_account_details, - pg->conn), - GNUNET_PQ_query_param_array_ptrs_string ( - reserves_length, - (const char **) notify_s, - pg->conn), - GNUNET_PQ_query_param_end - }; - struct Context ctx = { - .reserve_uuids = reserve_uuids, - .transaction_duplicates = transaction_duplicates, - .conflicts = conflicts, - .needs_update = false, - .status = GNUNET_OK - }; - - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "reserves_insert_with_array", - params, - &helper_cb, - &ctx); - GNUNET_PQ_cleanup_query_params_closures (params); - if ( (qs < 0) || - (GNUNET_OK != ctx.status) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to insert into reserves (%d)\n", - qs); - goto finished; - } - need_update = ctx.needs_update; - } - - { - enum GNUNET_DB_QueryStatus cs; - - cs = TALER_EXCHANGEDB_commit (pg); - if (cs < 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to commit\n"); - qs = cs; - goto finished; - } - } - - for (unsigned int i = 0; i<reserves_length; i++) - { - if (transaction_duplicates[i]) - dups++; - results[i] = transaction_duplicates[i] - ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } - - if (! need_update) - { - qs = reserves_length; - goto finished; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Reserve update needed for some reserves in the batch\n"); - PREPARE (pg, - "reserves_update", - "SELECT" - " out_duplicate AS duplicate " - "FROM exchange_do_batch_reserves_update" - " ($1,$2,$3,$4,$5,$6,$7);"); - - if (GNUNET_OK != - TALER_EXCHANGEDB_start (pg, - "reserve-insert-continued")) - { - GNUNET_break (0); - qs = GNUNET_DB_STATUS_HARD_ERROR; - goto finished; - } - - for (unsigned int i = 0; i<reserves_length; i++) - { - if (transaction_duplicates[i]) - continue; - if (! conflicts[i]) - continue; - { - bool duplicate; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&reserve_pubs[i]), - GNUNET_PQ_query_param_timestamp (&reserve_expiration), - GNUNET_PQ_query_param_uint64 (&wire_references[i]), - TALER_PQ_query_param_amount (pg->conn, - &balances[i]), - GNUNET_PQ_query_param_string (exchange_account_names[i]), - GNUNET_PQ_query_param_auto_from_type (&h_full_paytos[i]), - GNUNET_PQ_query_param_string (notify_s[i]), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("duplicate", - &duplicate), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qsi; - - qsi = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "reserves_update", - params, - rs); - if (qsi < 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to update reserves (%d)\n", - qsi); - results[i] = qsi; - goto finished; - } - results[i] = duplicate - ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; - } - } - { - enum GNUNET_DB_QueryStatus cs; - - cs = TALER_EXCHANGEDB_commit (pg); - if (cs < 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to commit\n"); - qs = cs; - goto finished; - } - } -finished: - for (unsigned int i = 0; i<reserves_length; i++) - GNUNET_free (notify_s[i]); - if (qs < 0) - return qs; - GNUNET_PQ_event_do_poll (pg->conn); - if (0 != dups) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "%u/%u duplicates among incoming transactions. Try increasing WIREWATCH_IDLE_SLEEP_INTERVAL in the [exchange] configuration section (if this happens a lot).\n", - dups, - reserves_length); - return qs; -} diff --git a/src/exchangedb/pg_reserves_update.c b/src/exchangedb/pg_reserves_update.c @@ -1,50 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_reserves_update.c - * @brief Implementation of the reserves_update function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/reserves_update.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_reserves_update (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_EXCHANGEDB_Reserve *reserve - ) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&reserve->expiry), - GNUNET_PQ_query_param_timestamp (&reserve->gc), - TALER_PQ_query_param_amount (pg->conn, - &reserve->balance), - GNUNET_PQ_query_param_auto_from_type (&reserve->pub), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "reserve_update", - "UPDATE reserves" - " SET" - " expiration_date=$1" - ",gc_date=$2" - ",current_balance=$3" - " WHERE reserve_pub=$4;"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "reserve_update", - params); -} diff --git a/src/exchangedb/pg_rollback.c b/src/exchangedb/pg_rollback.c @@ -1,45 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_rollback.c - * @brief Implementation of the rollback function for Postgres - * @author Christian Grothoff - */ -#include "taler/exchange-database/rollback.h" -#include "helper.h" - - -void -TALER_EXCHANGEDB_rollback (struct TALER_EXCHANGEDB_PostgresContext *pg) -{ - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_execute ("ROLLBACK"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - - if (NULL == pg->transaction_name) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Skipping rollback, no transaction active\n"); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Rolling back transaction\n"); - GNUNET_break (GNUNET_OK == - GNUNET_PQ_exec_statements (pg->conn, - es)); - pg->transaction_name = NULL; -} diff --git a/src/exchangedb/pg_select_account_merges_above_serial_id.c b/src/exchangedb/pg_select_account_merges_above_serial_id.c @@ -1,188 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_select_account_merges_above_serial_id.c - * @brief Implementation of the select_account_merges_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_account_merges_above_serial_id.h" -#include "helper.h" - - -/** - * Closure for #account_merge_serial_helper_cb(). - */ -struct AccountMergeSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_AccountMergeCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct AccountMergeSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -account_merge_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct AccountMergeSerialContext *dsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_PurseContractPublicKeyP purse_pub; - struct TALER_PrivateContractHashP h_contract_terms; - struct GNUNET_TIME_Timestamp purse_expiration; - struct TALER_Amount amount; - uint32_t min_age; - uint32_t flags32; - enum TALER_WalletAccountMergeFlags flags; - struct TALER_Amount purse_fee; - struct GNUNET_TIME_Timestamp merge_timestamp; - struct TALER_ReserveSignatureP reserve_sig; - uint64_t rowid; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", - &purse_fee), - GNUNET_PQ_result_spec_uint32 ("flags", - &flags32), - GNUNET_PQ_result_spec_uint32 ("age_limit", - &min_age), - GNUNET_PQ_result_spec_timestamp ("purse_expiration", - &purse_expiration), - GNUNET_PQ_result_spec_timestamp ("merge_timestamp", - &merge_timestamp), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - &h_contract_terms), - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - &purse_pub), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &reserve_sig), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - GNUNET_PQ_result_spec_uint64 ("account_merge_request_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - dsc->status = GNUNET_SYSERR; - return; - } - flags = (enum TALER_WalletAccountMergeFlags) flags32; - ret = dsc->cb (dsc->cb_cls, - rowid, - &reserve_pub, - &purse_pub, - &h_contract_terms, - purse_expiration, - &amount, - min_age, - flags, - &purse_fee, - merge_timestamp, - &reserve_sig); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_account_merges_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_AccountMergeCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct AccountMergeSerialContext dsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "audit_get_account_merge_incr", - "SELECT" - " am.account_merge_request_serial_id" - ",am.reserve_pub" - ",am.purse_pub" - ",pr.h_contract_terms" - ",pr.purse_expiration" - ",pr.amount_with_fee" - ",pr.age_limit" - ",pr.flags" - ",pr.purse_fee" - ",pm.merge_timestamp" - ",am.reserve_sig" - " FROM account_merges am" - " JOIN purse_requests pr USING (purse_pub)" - " JOIN purse_merges pm USING (purse_pub)" - " WHERE (" - " (account_merge_request_serial_id>=$1)" - " )" - " ORDER BY account_merge_request_serial_id ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_get_account_merge_incr", - params, - &account_merge_serial_helper_cb, - &dsc); - if (GNUNET_OK != dsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.c b/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.c @@ -1,154 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_select_aggregation_amounts_for_kyc_check.c - * @brief Implementation of the select_aggregation_amounts_for_kyc_check function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_aggregation_amounts_for_kyc_check.h" -#include "helper.h" - - -/** - * Closure for #get_kyc_amounts_cb(). - */ -struct KycAmountCheckContext -{ - /** - * Function to call per result. - */ - TALER_KYCLOGIC_KycAmountCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Flag set to #GNUNET_OK as long as everything is fine. - */ - enum GNUNET_GenericReturnValue status; - -}; - - -/** - * Invoke the callback for each result. - * - * @param cls a `struct KycAmountCheckContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -get_kyc_amounts_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct KycAmountCheckContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - - for (unsigned int i = 0; i < num_results; i++) - { - struct GNUNET_TIME_Absolute date; - struct TALER_Amount amount; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_absolute_time ("date", - &date), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ret = ctx->cb (ctx->cb_cls, - &amount, - date); - GNUNET_PQ_cleanup_result (rs); - switch (ret) - { - case GNUNET_OK: - continue; - case GNUNET_NO: - break; - case GNUNET_SYSERR: - ctx->status = GNUNET_SYSERR; - break; - } - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_aggregation_amounts_for_kyc_check ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - struct GNUNET_TIME_Absolute time_limit, - TALER_KYCLOGIC_KycAmountCallback kac, - void *kac_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_absolute_time (&time_limit), - GNUNET_PQ_query_param_end - }; - struct KycAmountCheckContext ctx = { - .cb = kac, - .cb_cls = kac_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_kyc_relevant_aggregation_events", - "SELECT" - " amount" - ",execution_date AS date" - " FROM wire_out" - " WHERE wire_target_h_payto IN" - " (SELECT wire_target_h_payto" - " FROM wire_targets" - " WHERE h_normalized_payto=$1" - " )" - " AND execution_date >= $2" - " ORDER BY execution_date DESC"); - - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_kyc_relevant_aggregation_events", - params, - &get_kyc_amounts_cb, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_aggregation_transient.c b/src/exchangedb/pg_select_aggregation_transient.c @@ -1,63 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_aggregation_transient.c - * @brief Implementation of the select_aggregation_transient function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_aggregation_transient.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_aggregation_transient ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_FullPaytoHashP *h_payto, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const char *exchange_account_section, - struct TALER_WireTransferIdentifierRawP *wtid, - struct TALER_Amount *total) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_string (exchange_account_section), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - total), - GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", - wtid), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "select_aggregation_transient", - "SELECT" - " amount" - " ,wtid_raw" - " FROM aggregation_transient" - " WHERE wire_target_h_payto=$1" - " AND merchant_pub=$2" - " AND exchange_account_section=$3;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "select_aggregation_transient", - params, - rs); -} diff --git a/src/exchangedb/pg_select_aggregations_above_serial.c b/src/exchangedb/pg_select_aggregations_above_serial.c @@ -1,137 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023, 2024 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/> - */ -/** - * @file exchangedb/pg_select_aggregations_above_serial.c - * @brief Implementation of the select_aggregations_above_serial function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_aggregations_above_serial.h" -#include "helper.h" - -/** - * Closure for #aggregation_serial_helper_cb(). - */ -struct AggregationSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_AggregationCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct AggregationSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -aggregation_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct AggregationSerialContext *dsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t tracking_rowid; - uint64_t batch_deposit_serial_id; - struct TALER_Amount amount; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("total_amount", - &amount), - GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", - &tracking_rowid), - GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id", - &batch_deposit_serial_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - dsc->status = GNUNET_SYSERR; - return; - } - dsc->cb (dsc->cb_cls, - &amount, - tracking_rowid, - batch_deposit_serial_id); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_aggregations_above_serial ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t min_tracking_serial_id, - TALER_EXCHANGEDB_AggregationCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&min_tracking_serial_id), - GNUNET_PQ_query_param_end - }; - struct AggregationSerialContext asc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - /* Fetch aggregations with rowid '\geq' the given parameter */ - PREPARE (pg, - "select_aggregations_above_serial", - "SELECT" - " aggregation_serial_id" - ",batch_deposit_serial_id" - ",total_amount" - " FROM exchange_do_select_aggregations_above_serial($1);"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "select_aggregations_above_serial", - params, - &aggregation_serial_helper_cb, - &asc); - if (GNUNET_OK != asc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_all_kyc_attributes.c b/src/exchangedb/pg_select_all_kyc_attributes.c @@ -1,168 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_select_all_kyc_attributes.c - * @brief Implementation of the select_all_kyc_attributes function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_all_kyc_attributes.h" -#include "helper.h" - -/** - * Closure for #get_all_attributes_cb(). - */ -struct GetAttributesContext -{ - /** - * Function to call per result. - */ - TALER_EXCHANGEDB_AllAttributesCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Flag set to #GNUNET_OK as long as everything is fine. - */ - enum GNUNET_GenericReturnValue status; - -}; - -/** - * Invoke the callback for each result. - * - * @param cls a `struct GetAttributesContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -get_attributes_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct GetAttributesContext *ctx = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - uint64_t rowid; - struct GNUNET_TIME_Timestamp collection_time; - struct GNUNET_TIME_Timestamp expiration_time; - struct TALER_NormalizedPaytoHashP h_payto; - json_t *properties = NULL; - size_t enc_attributes_size; - void *enc_attributes; - char *provider; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("provider_name", - &provider), - GNUNET_PQ_result_spec_uint64 ("kyc_attributes_serial_id", - &rowid), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ("jproperties", - &properties), - NULL), - GNUNET_PQ_result_spec_timestamp ("collection_time", - &collection_time), - GNUNET_PQ_result_spec_timestamp ("expiration_time", - &expiration_time), - GNUNET_PQ_result_spec_auto_from_type ("h_payto", - &h_payto), - GNUNET_PQ_result_spec_variable_size ("encrypted_attributes", - &enc_attributes, - &enc_attributes_size), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ctx->cb (ctx->cb_cls, - rowid, - &h_payto, - provider, - collection_time, - expiration_time, - properties, - enc_attributes_size, - enc_attributes); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_all_kyc_attributes ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t min_row_id, - TALER_EXCHANGEDB_AllAttributesCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&min_row_id), - GNUNET_PQ_query_param_end - }; - struct GetAttributesContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_all_kyc_attributes", - "SELECT " - " lp.provider_name" - ",ka.h_payto" - ",ka.kyc_attributes_serial_id" - ",lo.jproperties::TEXT" - ",ka.collection_time" - ",ka.expiration_time" - ",ka.encrypted_attributes" - " FROM kyc_attributes ka" - " JOIN legitimization_processes lp" - " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)" - " LEFT JOIN legitimization_outcomes lo" - " ON (ka.h_payto = lo.h_payto)" - /* **IF** we joined with 'lo', the lo must be active */ - " WHERE COALESCE(lo.is_active,TRUE)" - " AND kyc_attributes_serial_id > $1" - " ORDER BY kyc_attributes_serial_id ASC" - ); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_all_kyc_attributes", - params, - &get_attributes_cb, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_all_purse_decisions_above_serial_id.c b/src/exchangedb/pg_select_all_purse_decisions_above_serial_id.c @@ -1,142 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_select_all_purse_decisions_above_serial_id.c - * @brief Implementation of the select_all_purse_decisions_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_all_purse_decisions_above_serial_id.h" -#include "helper.h" - - -/** - * Closure for #all_purse_decision_serial_helper_cb(). - */ -struct AllPurseDecisionSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_AllPurseDecisionCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct PurseRefundSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -all_purse_decision_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct AllPurseDecisionSerialContext *dsc = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_PurseContractPublicKeyP purse_pub; - bool refunded; - uint64_t rowid; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - &purse_pub), - GNUNET_PQ_result_spec_bool ("refunded", - &refunded), - GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - dsc->status = GNUNET_SYSERR; - return; - } - ret = dsc->cb (dsc->cb_cls, - rowid, - &purse_pub, - refunded); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_all_purse_decisions_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_AllPurseDecisionCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct AllPurseDecisionSerialContext dsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "audit_select_all_purse_decisions_above_serial_id", - "SELECT" - " purse_pub" - ",refunded" - ",purse_decision_serial_id" - " FROM purse_decision" - " WHERE purse_decision_serial_id>=$1" - " ORDER BY purse_decision_serial_id ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "audit_select_all_purse_decisions_above_serial_id", - params, - &all_purse_decision_serial_helper_cb, - &dsc); - if (GNUNET_OK != dsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_all_purse_deletions_above_serial_id.c b/src/exchangedb/pg_select_all_purse_deletions_above_serial_id.c @@ -1,142 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_select_all_purse_deletions_above_serial_id.c - * @brief Implementation of the select_all_purse_deletions_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_all_purse_deletions_above_serial_id.h" -#include "helper.h" - - -/** - * Closure for #all_purse_deletion_serial_helper_cb(). - */ -struct AllPurseDeletionSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_AllPurseDeletionsCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct PurseRefundSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -all_purse_deletion_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct AllPurseDeletionSerialContext *dsc = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_PurseContractPublicKeyP purse_pub; - struct TALER_PurseContractSignatureP purse_sig; - uint64_t rowid; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - &purse_pub), - GNUNET_PQ_result_spec_auto_from_type ("purse_sig", - &purse_sig), - GNUNET_PQ_result_spec_uint64 ("purse_deletion_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - dsc->status = GNUNET_SYSERR; - return; - } - ret = dsc->cb (dsc->cb_cls, - rowid, - &purse_pub, - &purse_sig); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_all_purse_deletions_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_AllPurseDeletionsCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct AllPurseDeletionSerialContext dsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "audit_select_all_purse_deletions_above_serial_id", - "SELECT" - " purse_pub" - ",purse_sig" - ",purse_deletion_serial_id" - " FROM purse_deletion" - " WHERE purse_deletion_serial_id>=$1" - " ORDER BY purse_deletion_serial_id ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "audit_select_all_purse_deletions_above_serial_id", - params, - &all_purse_deletion_serial_helper_cb, - &dsc); - if (GNUNET_OK != dsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_aml_attributes.c b/src/exchangedb/pg_select_aml_attributes.c @@ -1,189 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_select_aml_attributes.c - * @brief Implementation of the select_aml_attributes function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_aml_attributes.h" -#include "helper.h" - - -/** - * Closure for #handle_aml_result. - */ -struct AmlAttributeResultContext -{ - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_AmlAttributeCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on serious errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. Helper function - * for #TALER_EXCHANGEDB_select_aml_attributes(). - * - * @param cls closure of type `struct AmlAttributeResultContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -handle_aml_attributes (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct AmlAttributeResultContext *ctx = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - struct GNUNET_TIME_Timestamp collection_time; - char *officer_name = NULL; - bool by_aml_officer; - size_t enc_attributes_size; - void *enc_attributes; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("kyc_attributes_serial_id", - &rowid), - GNUNET_PQ_result_spec_timestamp ("collection_time", - &collection_time), - GNUNET_PQ_result_spec_bool ("by_aml_officer", - &by_aml_officer), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("decider_name", - &officer_name), - NULL), - GNUNET_PQ_result_spec_variable_size ("encrypted_attributes", - &enc_attributes, - &enc_attributes_size), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - - ctx->cb (ctx->cb_cls, - rowid, - collection_time, - by_aml_officer, - officer_name, - enc_attributes_size, - enc_attributes); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_aml_attributes ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - uint64_t offset, - int64_t limit, - TALER_EXCHANGEDB_AmlAttributeCallback cb, - void *cb_cls) -{ - uint64_t ulimit = (limit > 0) ? limit : -limit; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_uint64 (&offset), - GNUNET_PQ_query_param_uint64 (&ulimit), - GNUNET_PQ_query_param_end - }; - struct AmlAttributeResultContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - const char *stmt = (limit > 0) - ? "select_aml_attributes_inc" - : "select_aml_attributes_dec"; - - PREPARE (pg, - "select_aml_attributes_inc", - "SELECT" - " ka.kyc_attributes_serial_id" - ",ka.collection_time" - ",ka.by_aml_officer" - ",astaff.decider_name" - ",ka.encrypted_attributes" - " FROM kyc_attributes ka" - " LEFT JOIN legitimization_processes lp" - " ON (ka.by_aml_officer AND" - " (ka.legitimization_serial = lp.legitimization_process_serial_id))" - " LEFT JOIN aml_staff astaff" - " ON (ka.by_aml_officer AND" - " (DECODE(lp.provider_user_id, 'base64') = astaff.decider_pub))" - " WHERE ka.h_payto=$1" - " AND ka.kyc_attributes_serial_id > $2" - " ORDER BY ka.kyc_attributes_serial_id ASC" - " LIMIT $3"); - PREPARE (pg, - "select_aml_attributes_dec", - "SELECT" - " ka.kyc_attributes_serial_id" - ",ka.collection_time" - ",ka.by_aml_officer" - ",astaff.decider_name" - ",ka.encrypted_attributes" - " FROM kyc_attributes ka" - " LEFT JOIN legitimization_processes lp" - " ON (ka.by_aml_officer AND" - " (ka.legitimization_serial = lp.legitimization_process_serial_id))" - " LEFT JOIN aml_staff astaff" - " ON (ka.by_aml_officer AND" - " (DECODE(lp.provider_user_id, 'base64') = astaff.decider_pub))" - " WHERE ka.h_payto=$1" - " AND ka.kyc_attributes_serial_id < $2" - " ORDER BY ka.kyc_attributes_serial_id DESC" - " LIMIT $3"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - stmt, - params, - &handle_aml_attributes, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_aml_decisions.c b/src/exchangedb/pg_select_aml_decisions.c @@ -1,248 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_select_aml_decisions.c - * @brief Implementation of the select_aml_decisions function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_aml_decisions.h" -#include "helper.h" - - -/** - * Closure for #handle_aml_result. - */ -struct AmlProcessResultContext -{ - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_AmlDecisionCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on serious errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. Helper function - * for #TALER_EXCHANGEDB_select_aml_decisions(). - * - * @param cls closure of type `struct AmlProcessResultContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -handle_aml_result (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct AmlProcessResultContext *ctx = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_NormalizedPaytoHashP h_payto; - uint64_t rowid; - char *justification = NULL; - struct GNUNET_TIME_Timestamp decision_time; - struct GNUNET_TIME_Absolute expiration_time; - json_t *jproperties = NULL; - bool is_wallet; - bool to_investigate; - bool is_active; - json_t *account_rules; - struct TALER_FullPayto payto; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("outcome_serial_id", - &rowid), - GNUNET_PQ_result_spec_auto_from_type ("h_payto", - &h_payto), - GNUNET_PQ_result_spec_bool ("is_wallet", - &is_wallet), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("justification", - &justification), - NULL), - GNUNET_PQ_result_spec_timestamp ("decision_time", - &decision_time), - GNUNET_PQ_result_spec_absolute_time ("expiration_time", - &expiration_time), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ("jproperties", - &jproperties), - NULL), - TALER_PQ_result_spec_json ("jnew_rules", - &account_rules), - GNUNET_PQ_result_spec_bool ("to_investigate", - &to_investigate), - GNUNET_PQ_result_spec_bool ("is_active", - &is_active), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto.full_payto), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - if (GNUNET_TIME_absolute_is_past (expiration_time)) - is_active = false; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Returning AML decisions for `%s' (%s)\n", - TALER_B2S (&h_payto), - is_wallet - ? "wallet" - : "account"); - ctx->cb (ctx->cb_cls, - rowid, - justification, - &h_payto, - decision_time, - expiration_time, - jproperties, - to_investigate, - is_active, - is_wallet, - payto, - account_rules); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_aml_decisions ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - enum TALER_EXCHANGE_YesNoAll investigation_only, - enum TALER_EXCHANGE_YesNoAll active_only, - uint64_t offset, - int64_t limit, - TALER_EXCHANGEDB_AmlDecisionCallback cb, - void *cb_cls) -{ - uint64_t ulimit = (limit > 0) ? limit : -limit; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_bool (NULL == h_payto), - NULL == h_payto - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == - investigation_only)), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == - investigation_only)), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == - active_only)), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == - active_only)), - GNUNET_PQ_query_param_uint64 (&offset), - GNUNET_PQ_query_param_uint64 (&ulimit), - GNUNET_PQ_query_param_end - }; - struct AmlProcessResultContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - const char *stmt = (limit > 0) - ? "select_aml_decisions_inc" - : "select_aml_decisions_dec"; - - PREPARE (pg, - "select_aml_decisions_inc", - "SELECT" - " lo.outcome_serial_id" - ",lo.h_payto" - ",ah.justification" - ",lo.decision_time" - ",lo.expiration_time" - ",lo.jproperties::TEXT" - ",lo.to_investigate" - ",lo.is_active" - ",lo.jnew_rules::TEXT" - ",kt.is_wallet" - ",wt.payto_uri" - " FROM legitimization_outcomes lo" - " JOIN kyc_targets kt" - " ON (lo.h_payto = kt.h_normalized_payto)" - " JOIN wire_targets wt" - " ON (lo.h_payto = wt.h_normalized_payto)" - " LEFT JOIN aml_history ah" - " USING (outcome_serial_id)" - " WHERE (outcome_serial_id > $7)" - " AND ($1 OR (lo.h_payto = $2))" - " AND ($3 OR (lo.to_investigate = $4))" - " AND ($5 OR (lo.is_active = $6))" - " ORDER BY lo.outcome_serial_id ASC" - " LIMIT $8"); - PREPARE (pg, - "select_aml_decisions_dec", - "SELECT" - " lo.outcome_serial_id" - ",lo.h_payto" - ",ah.justification" - ",lo.decision_time" - ",lo.expiration_time" - ",lo.jproperties::TEXT" - ",lo.to_investigate" - ",lo.is_active" - ",lo.jnew_rules::TEXT" - ",kt.is_wallet" - ",wt.payto_uri" - " FROM legitimization_outcomes lo" - " JOIN kyc_targets kt" - " ON (lo.h_payto = kt.h_normalized_payto)" - " JOIN wire_targets wt" - " ON (lo.h_payto = wt.h_normalized_payto)" - " LEFT JOIN aml_history ah" - " USING (outcome_serial_id)" - " WHERE lo.outcome_serial_id < $7" - " AND ($1 OR (lo.h_payto = $2))" - " AND ($3 OR (lo.to_investigate = $4))" - " AND ($5 OR (lo.is_active = $6))" - " ORDER BY lo.outcome_serial_id DESC" - " LIMIT $8"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - stmt, - params, - &handle_aml_result, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_aml_measures.c b/src/exchangedb/pg_select_aml_measures.c @@ -1,185 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024, 2025 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/> - */ -/** - * @file exchangedb/pg_select_aml_measures.c - * @brief Implementation of the select_aml_measures function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_aml_measures.h" -#include "helper.h" - - -/** - * Closure for #handle_aml_result. - */ -struct LegiMeasureResultContext -{ - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_LegitimizationMeasureCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on serious errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. Helper function - * for #TALER_EXCHANGEDB_select_aml_measures(). - * - * @param cls closure of type `struct LegiMeasureResultContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -handle_aml_result (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LegiMeasureResultContext *ctx = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_NormalizedPaytoHashP h_payto; - uint64_t rowid; - struct GNUNET_TIME_Absolute start_time; - json_t *jmeasures; - bool is_finished; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("legitimization_measure_serial_id", - &rowid), - GNUNET_PQ_result_spec_auto_from_type ("h_normalized_payto", - &h_payto), - GNUNET_PQ_result_spec_absolute_time ("start_time", - &start_time), - TALER_PQ_result_spec_json ("jmeasures", - &jmeasures), - GNUNET_PQ_result_spec_bool ("is_finished", - &is_finished), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ctx->cb (ctx->cb_cls, - &h_payto, - start_time, - jmeasures, - is_finished, - rowid); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_aml_measures ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - enum TALER_EXCHANGE_YesNoAll active_only, - uint64_t offset, - int64_t limit, - TALER_EXCHANGEDB_LegitimizationMeasureCallback cb, - void *cb_cls) -{ - uint64_t ulimit = (limit > 0) ? limit : -limit; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_bool (NULL == h_payto), - NULL == h_payto - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == - active_only)), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_NO == - active_only)), - GNUNET_PQ_query_param_uint64 (&offset), - GNUNET_PQ_query_param_uint64 (&ulimit), - GNUNET_PQ_query_param_end - }; - struct LegiMeasureResultContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - const char *stmt = (limit > 0) - ? "select_aml_measures_inc" - : "select_aml_measures_dec"; - - PREPARE (pg, - "select_aml_measures_inc", - "SELECT" - " lm.legitimization_measure_serial_id" - ",kt.h_normalized_payto" - ",lm.jmeasures::TEXT" - ",lm.start_time" - ",lm.is_finished" - " FROM kyc_targets kt" - " JOIN legitimization_measures lm" - " USING (access_token)" - " WHERE (legitimization_measure_serial_id > $5)" - " AND ($1 OR (kt.h_normalized_payto = $2))" - " AND ($3 OR (lm.is_finished = $4))" - " ORDER BY lm.legitimization_measure_serial_id ASC" - " LIMIT $6"); - PREPARE (pg, - "select_aml_measures_dec", - "SELECT" - " lm.legitimization_measure_serial_id" - ",kt.h_normalized_payto" - ",lm.jmeasures::TEXT" - ",lm.start_time" - ",lm.is_finished" - " FROM kyc_targets kt" - " JOIN legitimization_measures lm" - " USING (access_token)" - " WHERE (legitimization_measure_serial_id < $5)" - " AND ($1 OR (kt.h_normalized_payto = $2))" - " AND ($3 OR (lm.is_finished = $4))" - " ORDER BY lm.legitimization_measure_serial_id DESC" - " LIMIT $6"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - stmt, - params, - &handle_aml_result, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_aml_statistics.c b/src/exchangedb/pg_select_aml_statistics.c @@ -1,142 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024, 2025 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/> - */ -/** - * @file exchangedb/pg_select_aml_statistics.c - * @brief Implementation of the select_aml_statistics function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_aml_statistics.h" -#include "helper.h" - - -/** - * Closure for #get_statistics_cb(). - */ -struct GetStatisticsContext -{ - /** - * Function to call per result. - */ - TALER_EXCHANGEDB_AmlStatisticsCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Flag set to #GNUNET_OK as long as everything is fine. - */ - enum GNUNET_GenericReturnValue status; - -}; - - -/** - * Invoke the callback for each result. - * - * @param cls a `struct GetStatisticsContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -get_statistics_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct GetStatisticsContext *ctx = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - uint64_t val; - char *name; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("name", - &name), - GNUNET_PQ_result_spec_uint64 ("value", - &val), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ctx->cb (ctx->cb_cls, - name, - val); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_aml_statistics ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - size_t num_names, - const char *names[static num_names], - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - TALER_EXCHANGEDB_AmlStatisticsCallback cb, - void *cb_cls) -{ - struct GetStatisticsContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_array_ptrs_string (num_names, - names, - pg->conn), - GNUNET_PQ_query_param_timestamp (&start_date), - GNUNET_PQ_query_param_timestamp (&end_date), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_aml_statistics", - "SELECT " - " event_type AS name" - ",COUNT(*) AS value" - " FROM kyc_events" - " WHERE event_type = ANY ($1)" - " AND event_timestamp >= $2" - " AND event_timestamp < $3" - " GROUP BY event_type;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "select_aml_statistics", - params, - &get_statistics_cb, - &ctx); - GNUNET_PQ_cleanup_query_params_closures (params); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_auditor_denom_sig.c b/src/exchangedb/pg_select_auditor_denom_sig.c @@ -1,62 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_auditor_denom_sig.c - * @brief Implementation of the select_auditor_denom_sig function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_auditor_denom_sig.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_auditor_denom_sig ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_DenominationHashP *h_denom_pub, - const struct TALER_AuditorPublicKeyP *auditor_pub, - struct TALER_AuditorSignatureP *auditor_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (auditor_pub), - GNUNET_PQ_query_param_auto_from_type (h_denom_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("auditor_sig", - auditor_sig), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "select_auditor_denom_sig", - "SELECT" - " auditor_sig" - " FROM auditor_denom_sigs" - " WHERE auditor_uuid=" - " (SELECT auditor_uuid" - " FROM auditors" - " WHERE auditor_pub=$1)" - " AND denominations_serial=" - " (SELECT denominations_serial" - " FROM denominations" - " WHERE denom_pub_hash=$2);"); - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "select_auditor_denom_sig", - params, - rs); -} diff --git a/src/exchangedb/pg_select_batch_deposits_missing_wire.c b/src/exchangedb/pg_select_batch_deposits_missing_wire.c @@ -1,140 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2023 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/> - */ -/** - * @file exchangedb/pg_select_batch_deposits_missing_wire.c - * @brief Implementation of the select_batch_deposits_missing_wire function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_batch_deposits_missing_wire.h" -#include "helper.h" - -/** - * Closure for #missing_wire_cb(). - */ -struct MissingWireContext -{ - /** - * Function to call per result. - */ - TALER_EXCHANGEDB_WireMissingCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on error. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Invoke the callback for each result. - * - * @param cls a `struct MissingWireContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -missing_wire_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct MissingWireContext *mwc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = mwc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t batch_deposit_serial_id; - struct GNUNET_TIME_Timestamp deadline; - struct TALER_FullPaytoHashP wire_target_h_payto; - struct TALER_Amount total_amount; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id", - &batch_deposit_serial_id), - GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto", - &wire_target_h_payto), - GNUNET_PQ_result_spec_timestamp ("deadline", - &deadline), - TALER_PQ_RESULT_SPEC_AMOUNT ("total_amount", - &total_amount), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - mwc->status = GNUNET_SYSERR; - return; - } - mwc->cb (mwc->cb_cls, - batch_deposit_serial_id, - &total_amount, - &wire_target_h_payto, - deadline); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_batch_deposits_missing_wire ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t min_batch_deposit_serial_id, - TALER_EXCHANGEDB_WireMissingCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&min_batch_deposit_serial_id), - GNUNET_PQ_query_param_end - }; - struct MissingWireContext mwc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "deposits_get_deposits_missing_wire", - "SELECT" - " batch_deposit_serial_id" - ",wire_target_h_payto" - ",deadline" - ",total_amount" - " FROM exchange_do_select_deposits_missing_wire" - " ($1);"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "deposits_get_deposits_missing_wire", - params, - &missing_wire_cb, - &mwc); - if (GNUNET_OK != mwc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_coin_deposits_above_serial_id.c b/src/exchangedb/pg_select_coin_deposits_above_serial_id.c @@ -1,200 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2023 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/> - */ -/** - * @file exchangedb/pg_select_coin_deposits_above_serial_id.c - * @brief Implementation of the select_coin_deposits_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_coin_deposits_above_serial_id.h" -#include "helper.h" - -/** - * Closure for #deposit_serial_helper_cb(). - */ -struct CoinDepositSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_DepositCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct CoinDepositSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -coin_deposit_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct CoinDepositSerialContext *dsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_Deposit deposit; - struct GNUNET_TIME_Timestamp exchange_timestamp; - struct TALER_DenominationPublicKey denom_pub; - bool done; - uint64_t rowid; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &deposit.amount_with_fee), - GNUNET_PQ_result_spec_timestamp ("wallet_timestamp", - &deposit.timestamp), - GNUNET_PQ_result_spec_timestamp ("exchange_timestamp", - &exchange_timestamp), - GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", - &deposit.merchant_pub), - TALER_PQ_result_spec_denom_pub ("denom_pub", - &denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &deposit.coin.coin_pub), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &deposit.coin.h_age_commitment), - &deposit.coin.no_age_commitment), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("wallet_data_hash", - &deposit.wallet_data_hash), - &deposit.no_wallet_data_hash), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &deposit.csig), - GNUNET_PQ_result_spec_timestamp ("refund_deadline", - &deposit.refund_deadline), - GNUNET_PQ_result_spec_timestamp ("wire_deadline", - &deposit.wire_deadline), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - &deposit.h_contract_terms), - GNUNET_PQ_result_spec_auto_from_type ("wire_salt", - &deposit.wire_salt), - GNUNET_PQ_result_spec_string ("receiver_wire_account", - &deposit.receiver_wire_account.full_payto), - GNUNET_PQ_result_spec_bool ("done", - &done), - GNUNET_PQ_result_spec_uint64 ("coin_deposit_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - memset (&deposit, - 0, - sizeof (deposit)); - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - dsc->status = GNUNET_SYSERR; - return; - } - ret = dsc->cb (dsc->cb_cls, - rowid, - exchange_timestamp, - &deposit, - &denom_pub, - done); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_coin_deposits_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_DepositCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct CoinDepositSerialContext dsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - /* Fetch deposits with rowid '\geq' the given parameter */ - PREPARE (pg, - "audit_get_coin_deposits_incr", - "SELECT" - " cdep.amount_with_fee" - ",bdep.wallet_timestamp" - ",bdep.exchange_timestamp" - ",bdep.merchant_pub" - ",bdep.wallet_data_hash" - ",denom.denom_pub" - ",kc.coin_pub" - ",kc.age_commitment_hash" - ",cdep.coin_sig" - ",bdep.refund_deadline" - ",bdep.wire_deadline" - ",bdep.h_contract_terms" - ",bdep.wire_salt" - ",wt.payto_uri AS receiver_wire_account" - ",bdep.done" - ",cdep.coin_deposit_serial_id" - " FROM coin_deposits cdep" - " JOIN batch_deposits bdep" - " USING (batch_deposit_serial_id)" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " JOIN known_coins kc" - " USING (coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " WHERE (coin_deposit_serial_id>=$1)" - " ORDER BY coin_deposit_serial_id ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_get_coin_deposits_incr", - params, - &coin_deposit_serial_helper_cb, - &dsc); - if (GNUNET_OK != dsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_contract.c b/src/exchangedb/pg_select_contract.c @@ -1,65 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_contract.c - * @brief Implementation of the select_contract function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_contract.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_contract (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ContractDiffiePublicP * - pub_ckey, - struct TALER_PurseContractPublicKeyP * - purse_pub, - struct TALER_PurseContractSignatureP * - econtract_sig, - size_t *econtract_size, - void **econtract) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (pub_ckey), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - purse_pub), - GNUNET_PQ_result_spec_auto_from_type ("contract_sig", - econtract_sig), - GNUNET_PQ_result_spec_variable_size ("e_contract", - econtract, - econtract_size), - GNUNET_PQ_result_spec_end - }; - - /* Used in #postgres_select_contract */ - PREPARE (pg, - "select_contract", - "SELECT " - " purse_pub" - ",e_contract" - ",contract_sig" - " FROM contracts" - " WHERE pub_ckey=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "select_contract", - params, - rs); - -} diff --git a/src/exchangedb/pg_select_contract_by_purse.c b/src/exchangedb/pg_select_contract_by_purse.c @@ -1,59 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_contract_by_purse.c - * @brief Implementation of the select_contract_by_purse function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_contract_by_purse.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_select_contract_by_purse ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - struct TALER_EncryptedContract *econtract) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("pub_ckey", - &econtract->contract_pub), - GNUNET_PQ_result_spec_auto_from_type ("contract_sig", - &econtract->econtract_sig), - GNUNET_PQ_result_spec_variable_size ("e_contract", - &econtract->econtract, - &econtract->econtract_size), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "select_contract_by_purse", - "SELECT " - " pub_ckey" - ",e_contract" - ",contract_sig" - " FROM contracts" - " WHERE purse_pub=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "select_contract_by_purse", - params, - rs); - -} diff --git a/src/exchangedb/pg_select_deposit_amounts_for_kyc_check.c b/src/exchangedb/pg_select_deposit_amounts_for_kyc_check.c @@ -1,153 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_select_deposit_amounts_for_kyc_check.c - * @brief Implementation of the select_deposit_amounts_for_kyc_check function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_deposit_amounts_for_kyc_check.h" -#include "helper.h" - -/** - * Closure for #get_kyc_amounts_cb(). - */ -struct KycAmountCheckContext -{ - /** - * Function to call per result. - */ - TALER_KYCLOGIC_KycAmountCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Flag set to #GNUNET_OK as long as everything is fine. - */ - enum GNUNET_GenericReturnValue status; - -}; - -/** - * Invoke the callback for each result. - * - * @param cls a `struct KycAmountCheckContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -get_kyc_amounts_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct KycAmountCheckContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - - for (unsigned int i = 0; i < num_results; i++) - { - struct GNUNET_TIME_Absolute date; - struct TALER_Amount amount; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_absolute_time ("date", - &date), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ret = ctx->cb (ctx->cb_cls, - &amount, - date); - GNUNET_PQ_cleanup_result (rs); - switch (ret) - { - case GNUNET_OK: - continue; - case GNUNET_NO: - break; - case GNUNET_SYSERR: - ctx->status = GNUNET_SYSERR; - break; - } - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_deposit_amounts_for_kyc_check ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - struct GNUNET_TIME_Absolute time_limit, - TALER_KYCLOGIC_KycAmountCallback kac, - void *kac_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_absolute_time (&time_limit), - GNUNET_PQ_query_param_end - }; - struct KycAmountCheckContext ctx = { - .cb = kac, - .cb_cls = kac_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_kyc_relevant_deposit_events", - "SELECT" - " cd.amount_with_fee AS amount" - ",bd.exchange_timestamp AS date" - " FROM batch_deposits bd" - " JOIN coin_deposits cd" - " USING (batch_deposit_serial_id)" - " WHERE wire_target_h_payto IN (" - " SELECT wire_target_h_payto" - " FROM wire_targets" - " WHERE h_normalized_payto=$1" - " )" - " AND bd.exchange_timestamp >= $2" - " ORDER BY bd.exchange_timestamp DESC"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_kyc_relevant_deposit_events", - params, - &get_kyc_amounts_cb, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_exchange_credit_transfers.c b/src/exchangedb/pg_select_exchange_credit_transfers.c @@ -1,180 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_select_exchange_credit_transfers.c - * @brief Implementation of the select_exchange_credit_transfers function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_exchange_credit_transfers.h" -#include "helper.h" - -/** - * Closure for #handle_aml_result. - */ -struct SelectTransferContext -{ - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_AmlTransferCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on serious errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. Helper function - * for #TALER_EXCHANGEDB_select_exchange_debit_transfers(). - * - * @param cls closure of type `struct SelectTransferContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -handle_transfer_result (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct SelectTransferContext *stc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - char *payto_uri; - uint64_t rowid; - struct GNUNET_TIME_Absolute execution_time; - struct TALER_Amount amount; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial_id", - &rowid), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri), - GNUNET_PQ_result_spec_absolute_time ("execution_time", - &execution_time), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - stc->status = GNUNET_SYSERR; - return; - } - stc->cb (stc->cb_cls, - rowid, - payto_uri, - execution_time, - &amount); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_exchange_credit_transfers ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_Amount *threshold, - uint64_t offset, - int64_t limit, - const struct TALER_NormalizedPaytoHashP *h_payto, - TALER_EXCHANGEDB_AmlTransferCallback cb, - void *cb_cls) -{ - struct SelectTransferContext stc = { - .pg = pg, - .cb = cb, - .cb_cls = cb_cls, - .status = GNUNET_OK - }; - uint64_t ulimit = (limit > 0) ? limit : -limit; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&offset), - GNUNET_PQ_query_param_uint64 (&ulimit), - TALER_PQ_query_param_amount (pg->conn, - threshold), - NULL != h_payto - ? GNUNET_PQ_query_param_auto_from_type (h_payto) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_exchange_credit_transfers_inc", - "SELECT" - " ri.reserve_in_serial_id AS serial_id" - ",wt.payto_uri" - ",ri.execution_date AS execution_time" - ",ri.credit AS amount" - " FROM reserves_in ri" - " LEFT JOIN wire_targets wt" - " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)" - " WHERE (ri.reserve_in_serial_id > $1)" - " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" - " AND ( ( (ri.credit).val > ($3::taler_amount).val)" - " OR ( ( (ri.credit).val >= ($3::taler_amount).val)" - " AND ( (ri.credit).frac >= ($3::taler_amount).frac) ) )" - " ORDER BY ri.reserve_in_serial_id ASC" - " LIMIT $2"); - PREPARE (pg, - "select_exchange_credit_transfers_dec", - "SELECT" - " ri.reserve_in_serial_id AS serial_id" - ",wt.payto_uri" - ",ri.execution_date AS execution_time" - ",ri.credit AS amount" - " FROM reserves_in ri" - " LEFT JOIN wire_targets wt" - " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)" - " WHERE (ri.reserve_in_serial_id < $1)" - " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" - " AND ( ( (ri.credit).val > ($3::taler_amount).val)" - " OR ( ( (ri.credit).val >= ($3::taler_amount).val)" - " AND ( (ri.credit).frac >= ($3::taler_amount).frac) ) )" - " ORDER BY ri.reserve_in_serial_id DESC" - " LIMIT $2"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - (limit > 0) - ? "select_exchange_credit_transfers_inc" - : "select_exchange_credit_transfers_dec", - params, - &handle_transfer_result, - &stc); - if (GNUNET_OK != stc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_exchange_debit_transfers.c b/src/exchangedb/pg_select_exchange_debit_transfers.c @@ -1,181 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_select_exchange_debit_transfers.c - * @brief Implementation of the select_exchange_debit_transfers function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_exchange_debit_transfers.h" -#include "helper.h" - - -/** - * Closure for #handle_aml_result. - */ -struct SelectTransferContext -{ - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_AmlTransferCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on serious errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. Helper function - * for #TALER_EXCHANGEDB_select_exchange_debit_transfers(). - * - * @param cls closure of type `struct SelectTransferContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -handle_transfer_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct SelectTransferContext *stc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - char *payto_uri; - uint64_t rowid; - struct GNUNET_TIME_Absolute execution_time; - struct TALER_Amount amount; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial_id", - &rowid), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri), - GNUNET_PQ_result_spec_absolute_time ("execution_time", - &execution_time), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - stc->status = GNUNET_SYSERR; - return; - } - stc->cb (stc->cb_cls, - rowid, - payto_uri, - execution_time, - &amount); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_exchange_debit_transfers ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_Amount *threshold, - uint64_t offset, - int64_t limit, - const struct TALER_NormalizedPaytoHashP *h_payto, - TALER_EXCHANGEDB_AmlTransferCallback cb, - void *cb_cls) -{ - struct SelectTransferContext stc = { - .pg = pg, - .cb = cb, - .cb_cls = cb_cls, - .status = GNUNET_OK - }; - uint64_t ulimit = (limit > 0) ? limit : -limit; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&offset), - GNUNET_PQ_query_param_uint64 (&ulimit), - TALER_PQ_query_param_amount (pg->conn, - threshold), - NULL != h_payto - ? GNUNET_PQ_query_param_auto_from_type (h_payto) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_exchange_debit_transfers_inc", - "SELECT" - " wo.wireout_uuid AS serial_id" - ",wt.payto_uri" - ",wo.execution_date AS execution_time" - ",wo.amount" - " FROM wire_out wo" - " LEFT JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " WHERE (wo.wireout_uuid > $1)" - " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" - " AND ( ( (wo.amount).val > ($3::taler_amount).val)" - " OR ( ( (wo.amount).val >= ($3::taler_amount).val)" - " AND ( (wo.amount).frac >= ($3::taler_amount).frac) ) )" - " ORDER BY wo.wireout_uuid ASC" - " LIMIT $2"); - PREPARE (pg, - "select_exchange_debit_transfers_dec", - "SELECT" - " wo.wireout_uuid AS serial_id" - ",wt.payto_uri" - ",wo.execution_date AS execution_time" - ",wo.amount" - " FROM wire_out wo" - " LEFT JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " WHERE (wo.wireout_uuid < $1)" - " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" - " AND ( ( (wo.amount).val > ($3::taler_amount).val)" - " OR ( ( (wo.amount).val >= ($3::taler_amount).val)" - " AND ( (wo.amount).frac >= ($3::taler_amount).frac) ) )" - " ORDER BY wo.wireout_uuid DESC" - " LIMIT $2"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - (limit > 0) - ? "select_exchange_debit_transfers_inc" - : "select_exchange_debit_transfers_dec", - params, - &handle_transfer_cb, - &stc); - if (GNUNET_OK != stc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_exchange_kycauth_transfers.c b/src/exchangedb/pg_select_exchange_kycauth_transfers.c @@ -1,180 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_select_exchange_kycauth_transfers.c - * @brief Implementation of the select_exchange_kycauth_transfers function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_exchange_kycauth_transfers.h" -#include "helper.h" - -/** - * Closure for #handle_aml_result. - */ -struct SelectTransferContext -{ - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_AmlTransferCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on serious errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. Helper function - * for #TALER_EXCHANGEDB_select_exchange_debit_transfers(). - * - * @param cls closure of type `struct SelectTransferContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -handle_transfer_result (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct SelectTransferContext *stc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - char *payto_uri; - uint64_t rowid; - struct GNUNET_TIME_Absolute execution_time; - struct TALER_Amount amount; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("serial_id", - &rowid), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri), - GNUNET_PQ_result_spec_absolute_time ("execution_time", - &execution_time), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - stc->status = GNUNET_SYSERR; - return; - } - stc->cb (stc->cb_cls, - rowid, - payto_uri, - execution_time, - &amount); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_exchange_kycauth_transfers ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_Amount *threshold, - uint64_t offset, - int64_t limit, - const struct TALER_NormalizedPaytoHashP *h_payto, - TALER_EXCHANGEDB_AmlTransferCallback cb, - void *cb_cls) -{ - struct SelectTransferContext stc = { - .pg = pg, - .cb = cb, - .cb_cls = cb_cls, - .status = GNUNET_OK - }; - uint64_t ulimit = (limit > 0) ? limit : -limit; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&offset), - GNUNET_PQ_query_param_uint64 (&ulimit), - TALER_PQ_query_param_amount (pg->conn, - threshold), - NULL != h_payto - ? GNUNET_PQ_query_param_auto_from_type (h_payto) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_exchange_kycauth_transfers_inc", - "SELECT" - " ki.kycauth_in_serial_id AS serial_id" - ",wt.payto_uri" - ",ki.execution_date AS execution_time" - ",ki.credit AS amount" - " FROM kycauths_in ki" - " LEFT JOIN wire_targets wt" - " ON (ki.wire_source_h_payto = wt.wire_target_h_payto)" - " WHERE (ki.kycauth_in_serial_id > $1)" - " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" - " AND ( ( (ki.credit).val > ($3::taler_amount).val)" - " OR ( ( (ki.credit).val >= ($3::taler_amount).val)" - " AND ( (ki.credit).frac >= ($3::taler_amount).frac) ) )" - " ORDER BY ki.kycauth_in_serial_id ASC" - " LIMIT $2"); - PREPARE (pg, - "select_exchange_kycauth_transfers_dec", - "SELECT" - " ki.kycauth_in_serial_id AS serial_id" - ",wt.payto_uri" - ",ki.execution_date AS execution_time" - ",ki.credit AS amount" - " FROM kycauths_in ki" - " LEFT JOIN wire_targets wt" - " ON (ki.wire_source_h_payto = wt.wire_target_h_payto)" - " WHERE (ki.kycauth_in_serial_id < $1)" - " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" - " AND ( ( (ki.credit).val > ($3::taler_amount).val)" - " OR ( ( (ki.credit).val >= ($3::taler_amount).val)" - " AND ( (ki.credit).frac >= ($3::taler_amount).frac) ) )" - " ORDER BY ki.kycauth_in_serial_id DESC" - " LIMIT $2"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - (limit > 0) - ? "select_exchange_kycauth_transfers_inc" - : "select_exchange_kycauth_transfers_dec", - params, - &handle_transfer_result, - &stc); - if (GNUNET_OK != stc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_kyc_accounts.c b/src/exchangedb/pg_select_kyc_accounts.c @@ -1,235 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_select_kyc_accounts.c - * @brief Implementation of the select_kyc_accounts function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_kyc_accounts.h" -#include "helper.h" - - -/** - * Closure for #handle_aml_result. - */ -struct KycAccountResultContext -{ - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_AmlAccountListCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on serious errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. Helper function - * for #TALER_EXCHANGEDB_select_kyc_accounts(). - * - * @param cls closure of type `struct KycAccountResultContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -handle_kyc_account_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct KycAccountResultContext *ctx = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - struct TALER_NormalizedPaytoHashP h_payto; - char *comments = NULL; - struct GNUNET_TIME_Timestamp open_time - = GNUNET_TIME_UNIT_FOREVER_TS; - struct GNUNET_TIME_Timestamp close_time - = GNUNET_TIME_UNIT_FOREVER_TS; - bool to_investigate; - bool high_risk; - struct TALER_FullPayto payto; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("kyc_target_serial_id", - &rowid), - GNUNET_PQ_result_spec_auto_from_type ("h_payto", - &h_payto), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("comments", - &comments), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_timestamp ("open_time", - &open_time), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_timestamp ("close_time", - &close_time), - NULL), - GNUNET_PQ_result_spec_bool ("to_investigate", - &to_investigate), - GNUNET_PQ_result_spec_bool ("high_risk", - &high_risk), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto.full_payto), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ctx->cb (ctx->cb_cls, - rowid, - &h_payto, - open_time, - close_time, - comments, - high_risk, - to_investigate, - payto); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_kyc_accounts ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - enum TALER_EXCHANGE_YesNoAll investigation_only, - enum TALER_EXCHANGE_YesNoAll open_only, - enum TALER_EXCHANGE_YesNoAll high_risk_only, - uint64_t offset, - int64_t limit, - TALER_EXCHANGEDB_AmlAccountListCallback cb, - void *cb_cls) -{ - uint64_t ulimit = (limit > 0) ? limit : -limit; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&offset), - GNUNET_PQ_query_param_uint64 (&ulimit), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == - investigation_only)), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == - investigation_only)), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == - open_only)), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == - open_only)), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == - high_risk_only)), - GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == - high_risk_only)), - GNUNET_PQ_query_param_end - }; - struct KycAccountResultContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - const char *stmt = (limit > 0) - ? "select_kyc_accounts_inc" - : "select_kyc_accounts_dec"; - - PREPARE (pg, - "select_kyc_accounts_inc", - "SELECT" - " kt.kyc_target_serial_id" - ",kt.h_normalized_payto AS h_payto" - ",kt.open_time" - ",kt.close_time" - ",lo.jproperties ->> 'FILE_NOTE' AS comments" - ",lo.jproperties ->> 'open_date' AS open_time" - ",COALESCE(lo.to_investigate,FALSE) AS to_investigate" - ",COALESCE((lo.jproperties ->> 'HIGH_RISK_CUSTOMER')::bool,FALSE) AS high_risk" - ",wt.payto_uri" - " FROM kyc_targets kt" - " JOIN wire_targets wt" - " ON (wt.h_normalized_payto = kt.h_normalized_payto)" - " LEFT JOIN legitimization_outcomes lo" - " ON (lo.h_payto = kt.h_normalized_payto)" - " WHERE (kyc_target_serial_id > $1)" - // select most recent outcomes only - " AND COALESCE (lo.is_active, TRUE)" - " AND ($3 OR (COALESCE(lo.to_investigate,FALSE) = $4))" - // Account is open if we had an AML outcome - " AND ($5 OR ((lo.outcome_serial_id IS NULL) = $6))" - " AND ($7 OR ((COALESCE((lo.jproperties ->>'high_risk')::bool,FALSE) = $8)))" - " ORDER BY kt.kyc_target_serial_id ASC" - " LIMIT $2"); - PREPARE (pg, - "select_kyc_accounts_dec", - "SELECT" - " kt.kyc_target_serial_id" - ",kt.h_normalized_payto AS h_payto" - ",kt.open_time" - ",kt.close_time" - ",lo.jproperties ->> 'FILE_NOTE' AS comments" - ",lo.jproperties ->> 'open_date' AS open_time" - ",COALESCE(lo.to_investigate,FALSE) AS to_investigate" - ",COALESCE((lo.jproperties ->> 'HIGH_RISK_CUSTOMER')::bool,FALSE) AS high_risk" - ",wt.payto_uri" - " FROM kyc_targets kt" - " LEFT JOIN legitimization_outcomes lo" - " ON (lo.h_payto = kt.h_normalized_payto)" - " LEFT JOIN LATERAL (" - " SELECT payto_uri" - " FROM wire_targets" - " WHERE h_normalized_payto = kt.h_normalized_payto" - " ORDER BY wire_target_serial_id DESC" - " LIMIT 1" - " ) wt ON true" - " WHERE (kyc_target_serial_id < $1)" - // select most recent outcomes only - " AND COALESCE (lo.is_active, TRUE)" - " AND ($3 OR (COALESCE(lo.to_investigate,FALSE) = $4))" - // Account is open if we had an AML outcome - " AND ($5 OR ((lo.outcome_serial_id IS NULL) = $6))" - " AND ($7 OR ((COALESCE((lo.jproperties ->>'high_risk')::bool,FALSE) = $8)))" - " ORDER BY kt.kyc_target_serial_id DESC" - " LIMIT $2"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - stmt, - params, - &handle_kyc_account_cb, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_kyc_attributes.c b/src/exchangedb/pg_select_kyc_attributes.c @@ -1,154 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_select_kyc_attributes.c - * @brief Implementation of the select_kyc_attributes function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_kyc_attributes.h" -#include "helper.h" - - -/** - * Closure for #get_attributes_cb(). - */ -struct GetAttributesContext -{ - /** - * Function to call per result. - */ - TALER_EXCHANGEDB_AttributeCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Key of our query. - */ - const struct TALER_NormalizedPaytoHashP *h_payto; - - /** - * Flag set to #GNUNET_OK as long as everything is fine. - */ - enum GNUNET_GenericReturnValue status; - -}; - - -/** - * Invoke the callback for each result. - * - * @param cls a `struct GetAttributesContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -get_attributes_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct GetAttributesContext *ctx = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - struct GNUNET_TIME_Timestamp collection_time; - struct GNUNET_TIME_Timestamp expiration_time; - size_t enc_attributes_size; - void *enc_attributes; - char *provider; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("provider_name", - &provider), - GNUNET_PQ_result_spec_timestamp ("collection_time", - &collection_time), - GNUNET_PQ_result_spec_timestamp ("expiration_time", - &expiration_time), - GNUNET_PQ_result_spec_variable_size ("encrypted_attributes", - &enc_attributes, - &enc_attributes_size), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ctx->cb (ctx->cb_cls, - ctx->h_payto, - provider, - collection_time, - expiration_time, - enc_attributes_size, - enc_attributes); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_kyc_attributes ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - TALER_EXCHANGEDB_AttributeCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_end - }; - struct GetAttributesContext ctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .h_payto = h_payto, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_kyc_attributes", - "SELECT " - " lp.provider_name" - ",ka.collection_time" - ",ka.expiration_time" - ",ka.encrypted_attributes" - " FROM kyc_attributes ka" - " JOIN legitimization_processes lp" - " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)" - " WHERE ka.h_payto=$1"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_kyc_attributes", - params, - &get_attributes_cb, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_merge_amounts_for_kyc_check.c b/src/exchangedb/pg_select_merge_amounts_for_kyc_check.c @@ -1,152 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_select_merge_amounts_for_kyc_check.c - * @brief Implementation of the select_merge_amounts_for_kyc_check function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_merge_amounts_for_kyc_check.h" -#include "helper.h" - - -/** - * Closure for #get_kyc_amounts_cb(). - */ -struct KycAmountCheckContext -{ - /** - * Function to call per result. - */ - TALER_KYCLOGIC_KycAmountCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Flag set to #GNUNET_OK as long as everything is fine. - */ - enum GNUNET_GenericReturnValue status; - -}; - -/** - * Invoke the callback for each result. - * - * @param cls a `struct KycAmountCheckContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -get_kyc_amounts_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct KycAmountCheckContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - - for (unsigned int i = 0; i < num_results; i++) - { - struct GNUNET_TIME_Absolute date; - struct TALER_Amount amount; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_absolute_time ("date", - &date), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ret = ctx->cb (ctx->cb_cls, - &amount, - date); - GNUNET_PQ_cleanup_result (rs); - switch (ret) - { - case GNUNET_OK: - continue; - case GNUNET_NO: - break; - case GNUNET_SYSERR: - ctx->status = GNUNET_SYSERR; - break; - } - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_merge_amounts_for_kyc_check ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - struct GNUNET_TIME_Absolute time_limit, - TALER_KYCLOGIC_KycAmountCallback kac, - void *kac_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_absolute_time (&time_limit), - GNUNET_PQ_query_param_end - }; - struct KycAmountCheckContext ctx = { - .cb = kac, - .cb_cls = kac_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_kyc_relevant_merge_events", - "SELECT" - " amount_with_fee AS amount" - ",merge_timestamp AS date" - " FROM account_merges" - " JOIN purse_merges USING (purse_pub)" - " JOIN purse_requests USING (purse_pub)" - " JOIN purse_decision USING (purse_pub)" - " WHERE wallet_h_payto=$1" - " AND merge_timestamp >= $2" - " AND NOT refunded" - " ORDER BY merge_timestamp DESC"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_kyc_relevant_merge_events", - params, - &get_kyc_amounts_cb, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_purse.c b/src/exchangedb/pg_select_purse.c @@ -1,90 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_select_purse.c - * @brief Implementation of the select_purse function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_purse.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_purse ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - struct GNUNET_TIME_Timestamp *purse_creation, - struct GNUNET_TIME_Timestamp *purse_expiration, - struct TALER_Amount *amount, - struct TALER_Amount *deposited, - struct TALER_PrivateContractHashP *h_contract_terms, - struct GNUNET_TIME_Timestamp *merge_timestamp, - bool *purse_deleted, - bool *purse_refunded) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("purse_expiration", - purse_expiration), - GNUNET_PQ_result_spec_timestamp ("purse_creation", - purse_creation), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("balance", - deposited), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - h_contract_terms), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_timestamp ("merge_timestamp", - merge_timestamp), - NULL), - GNUNET_PQ_result_spec_bool ("purse_deleted", - purse_deleted), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_bool ("purse_refunded", - purse_refunded), - NULL), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "select_purse", - "SELECT " - " pr.merge_pub" - ",pr.purse_creation" - ",pr.purse_expiration" - ",pr.h_contract_terms" - ",pr.amount_with_fee" - ",pr.balance" - ",pm.merge_timestamp" - ",pd.purse_sig IS NOT NULL AS purse_deleted" - ",pc.refunded AS purse_refunded" - " FROM purse_requests pr" - " LEFT JOIN purse_merges pm ON (pm.purse_pub = pr.purse_pub)" - " LEFT JOIN purse_decision pc ON (pc.purse_pub = pr.purse_pub)" - " LEFT JOIN purse_deletion pd ON (pd.purse_pub = pr.purse_pub)" - " WHERE pr.purse_pub=$1;"); - *merge_timestamp = GNUNET_TIME_UNIT_FOREVER_TS; - *purse_refunded = false; - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "select_purse", - params, - rs); -} diff --git a/src/exchangedb/pg_select_purse_by_merge_pub.c b/src/exchangedb/pg_select_purse_by_merge_pub.c @@ -1,75 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_purse_by_merge_pub.c - * @brief Implementation of the select_purse_by_merge_pub function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_purse_by_merge_pub.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_select_purse_by_merge_pub ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseMergePublicKeyP *merge_pub, - struct TALER_PurseContractPublicKeyP *purse_pub, - struct GNUNET_TIME_Timestamp *purse_expiration, - struct TALER_PrivateContractHashP *h_contract_terms, - uint32_t *age_limit, - struct TALER_Amount *target_amount, - struct TALER_Amount *balance, - struct TALER_PurseContractSignatureP *purse_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (merge_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - purse_pub), - GNUNET_PQ_result_spec_timestamp ("purse_expiration", - purse_expiration), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - h_contract_terms), - GNUNET_PQ_result_spec_uint32 ("age_limit", - age_limit), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - target_amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("balance", - balance), - GNUNET_PQ_result_spec_auto_from_type ("purse_sig", - purse_sig), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "select_purse_by_merge_pub", - "SELECT " - " purse_pub" - ",purse_expiration" - ",h_contract_terms" - ",age_limit" - ",amount_with_fee" - ",balance" - ",purse_sig" - " FROM purse_requests" - " WHERE merge_pub=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "select_purse_by_merge_pub", - params, - rs); -} diff --git a/src/exchangedb/pg_select_purse_decisions_above_serial_id.c b/src/exchangedb/pg_select_purse_decisions_above_serial_id.c @@ -1,158 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_purse_decisions_above_serial_id.c - * @brief Implementation of the select_purse_decisions_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_purse_decisions_above_serial_id.h" -#include "helper.h" - -/** - * Closure for #purse_decision_serial_helper_cb(). - */ -struct PurseDecisionSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_PurseDecisionCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct PurseRefundSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -purse_decision_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct PurseDecisionSerialContext *dsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_PurseContractPublicKeyP purse_pub; - struct TALER_ReservePublicKeyP reserve_pub; - bool no_reserve = true; - uint64_t rowid; - struct TALER_Amount val; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - &purse_pub), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - &no_reserve), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &val), - GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - dsc->status = GNUNET_SYSERR; - return; - } - ret = dsc->cb (dsc->cb_cls, - rowid, - &purse_pub, - no_reserve ? NULL : &reserve_pub, - &val); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_select_purse_decisions_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - bool refunded, - TALER_EXCHANGEDB_PurseDecisionCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_bool (refunded), - GNUNET_PQ_query_param_end - }; - struct PurseDecisionSerialContext dsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "audit_get_purse_decisions_incr", - "SELECT" - " pd.purse_pub" - ",pm.reserve_pub" - ",pd.purse_decision_serial_id" - ",pr.amount_with_fee" - " FROM purse_decision pd" - " JOIN purse_requests pr ON (pd.purse_pub = pr.purse_pub)" - " LEFT JOIN purse_merges pm ON (pm.purse_pub = pd.purse_pub)" - " WHERE (" - " (purse_decision_serial_id>=$1) AND " - " (refunded=$2)" - " )" - " ORDER BY purse_decision_serial_id ASC;"); - - - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_get_purse_decisions_incr", - params, - &purse_decision_serial_helper_cb, - &dsc); - if (GNUNET_OK != dsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_purse_deposits_above_serial_id.c b/src/exchangedb/pg_select_purse_deposits_above_serial_id.c @@ -1,198 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_select_purse_deposits_above_serial_id.c - * @brief Implementation of the select_purse_deposits_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_purse_deposits_above_serial_id.h" -#include "helper.h" - -/** - * Closure for #purse_deposit_serial_helper_cb(). - */ -struct PurseDepositSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_PurseDepositCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct DepositSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -purse_deposit_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct PurseDepositSerialContext *dsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_PurseDeposit deposit = { - .exchange_base_url = NULL - }; - struct TALER_DenominationPublicKey denom_pub; - uint64_t rowid; - uint32_t flags32; - struct TALER_ReservePublicKeyP reserve_pub; - bool not_merged = false; - struct TALER_Amount purse_balance; - struct TALER_Amount purse_total; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &deposit.amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("balance", - &purse_balance), - TALER_PQ_RESULT_SPEC_AMOUNT ("total", - &purse_total), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", - &deposit.deposit_fee), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("partner_base_url", - &deposit.exchange_base_url), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - &not_merged), - TALER_PQ_result_spec_denom_pub ("denom_pub", - &denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - &deposit.purse_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &deposit.coin_sig), - GNUNET_PQ_result_spec_uint32 ("flags", - &flags32), - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &deposit.coin_pub), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &deposit.h_age_commitment), - &deposit.no_age_commitment), - GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - memset (&deposit, - 0, - sizeof (deposit)); - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - dsc->status = GNUNET_SYSERR; - return; - } - ret = dsc->cb (dsc->cb_cls, - rowid, - &deposit, - not_merged ? NULL : &reserve_pub, - (enum TALER_WalletAccountMergeFlags) flags32, - &purse_balance, - &purse_total, - &denom_pub); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_select_purse_deposits_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_PurseDepositCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct PurseDepositSerialContext dsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "audit_get_purse_deposits_incr", - "SELECT" - " pd.amount_with_fee" - ",pr.amount_with_fee AS total" - ",pr.balance" - ",pr.flags" - ",pd.purse_pub" - ",pd.coin_sig" - ",partner_base_url" - ",denom.denom_pub" - ",denom.fee_deposit" - ",pm.reserve_pub" - ",kc.coin_pub" - ",kc.age_commitment_hash" - ",pd.purse_deposit_serial_id" - " FROM purse_deposits pd" - " LEFT JOIN partners USING (partner_serial_id)" - " LEFT JOIN purse_merges pm USING (purse_pub)" - " JOIN purse_requests pr USING (purse_pub)" - " JOIN known_coins kc USING (coin_pub)" - " JOIN denominations denom USING (denominations_serial)" - " WHERE (" - " (purse_deposit_serial_id>=$1)" - " )" - " ORDER BY purse_deposit_serial_id ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_get_purse_deposits_incr", - params, - &purse_deposit_serial_helper_cb, - &dsc); - if (GNUNET_OK != dsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_purse_deposits_by_purse.c b/src/exchangedb/pg_select_purse_deposits_by_purse.c @@ -1,149 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_purse_deposits_by_purse.c - * @brief Implementation of the select_purse_deposits_by_purse function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_purse_deposits_by_purse.h" -#include "helper.h" - -/** - * Closure for #purse_refund_coin_helper_cb(). - */ -struct PurseRefundCoinContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_PurseRefundCoinCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct PurseRefundCoinContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -purse_refund_coin_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct PurseRefundCoinContext *dsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_Amount amount_with_fee; - struct TALER_CoinSpendPublicKeyP coin_pub; - struct TALER_DenominationPublicKey denom_pub; - uint64_t rowid; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_denom_pub ("denom_pub", - &denom_pub), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &amount_with_fee), - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &coin_pub), - GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - dsc->status = GNUNET_SYSERR; - return; - } - ret = dsc->cb (dsc->cb_cls, - rowid, - &amount_with_fee, - &coin_pub, - &denom_pub); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_select_purse_deposits_by_purse ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - TALER_EXCHANGEDB_PurseRefundCoinCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - GNUNET_PQ_query_param_end - }; - struct PurseRefundCoinContext dsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "audit_get_purse_deposits_by_purse", - "SELECT" - " pd.purse_deposit_serial_id" - ",pd.amount_with_fee" - ",pd.coin_pub" - ",denom.denom_pub" - " FROM purse_deposits pd" - " JOIN known_coins kc" - " USING (coin_pub)" - " JOIN denominations denom" - " USING (denominations_serial)" - " WHERE purse_pub=$1;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_get_purse_deposits_by_purse", - params, - &purse_refund_coin_helper_cb, - &dsc); - if (GNUNET_OK != dsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_purse_merge.c b/src/exchangedb/pg_select_purse_merge.c @@ -1,76 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_purse_merge.c - * @brief Implementation of the select_purse_merge function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_purse_merge.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_select_purse_merge ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - struct TALER_PurseMergeSignatureP *merge_sig, - struct GNUNET_TIME_Timestamp *merge_timestamp, - char **partner_url, - struct TALER_ReservePublicKeyP *reserve_pub, - bool *refunded) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("merge_sig", - merge_sig), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - reserve_pub), - GNUNET_PQ_result_spec_timestamp ("merge_timestamp", - merge_timestamp), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("partner_base_url", - partner_url), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_bool ("refunded", - refunded), - NULL), - GNUNET_PQ_result_spec_end - }; - - *partner_url = NULL; - *refunded = false; - PREPARE (pg, - "select_purse_merge", - "SELECT " - " pm.reserve_pub" - ",pm.merge_sig" - ",pm.merge_timestamp" - ",pr.partner_base_url" - ",pd.refunded" - " FROM purse_merges pm" - " LEFT JOIN purse_decision pd USING (purse_pub)" - " LEFT JOIN partners pr USING (partner_serial_id)" - " WHERE pm.purse_pub=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "select_purse_merge", - params, - rs); -} diff --git a/src/exchangedb/pg_select_purse_merges_above_serial_id.c b/src/exchangedb/pg_select_purse_merges_above_serial_id.c @@ -1,186 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_select_purse_merges_above_serial_id.c - * @brief Implementation of the select_purse_merges_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_purse_merges_above_serial_id.h" -#include "helper.h" - - -/** - * Closure for #purse_deposit_serial_helper_cb(). - */ -struct PurseMergeSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_PurseMergeCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct PurseMergeSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -purse_merges_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct PurseMergeSerialContext *dsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - char *partner_base_url = NULL; - struct TALER_Amount amount; - struct TALER_Amount balance; - uint32_t flags32; - enum TALER_WalletAccountMergeFlags flags; - struct TALER_PurseMergePublicKeyP merge_pub; - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_PurseMergeSignatureP merge_sig; - struct TALER_PurseContractPublicKeyP purse_pub; - struct GNUNET_TIME_Timestamp merge_timestamp; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("balance", - &balance), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("partner_base_url", - &partner_base_url), - NULL), - GNUNET_PQ_result_spec_uint32 ("flags", - &flags32), - GNUNET_PQ_result_spec_timestamp ("merge_timestamp", - &merge_timestamp), - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - &purse_pub), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ("merge_sig", - &merge_sig), - GNUNET_PQ_result_spec_auto_from_type ("merge_pub", - &merge_pub), - GNUNET_PQ_result_spec_uint64 ("purse_merge_request_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - dsc->status = GNUNET_SYSERR; - return; - } - flags = (enum TALER_WalletAccountMergeFlags) flags32; - ret = dsc->cb (dsc->cb_cls, - rowid, - partner_base_url, - &amount, - &balance, - flags, - &merge_pub, - &reserve_pub, - &merge_sig, - &purse_pub, - merge_timestamp); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_TALER_TALER_EXCHANGEDB_select_purse_merges_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_PurseMergeCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct PurseMergeSerialContext dsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "audit_get_purse_merge_incr", - "SELECT" - " pm.purse_merge_request_serial_id" - ",partner_base_url" - ",pr.amount_with_fee" - ",pr.balance" - ",pr.flags" - ",pr.merge_pub" - ",pm.reserve_pub" - ",pm.merge_sig" - ",pm.purse_pub" - ",pm.merge_timestamp" - " FROM purse_merges pm" - " JOIN purse_requests pr USING (purse_pub)" - " LEFT JOIN partners USING (partner_serial_id)" - " WHERE (" - " (purse_merge_request_serial_id>=$1)" - " )" - " ORDER BY purse_merge_request_serial_id ASC;"); - - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_get_purse_merge_incr", - params, - &purse_merges_serial_helper_cb, - &dsc); - if (GNUNET_OK != dsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_purse_requests_above_serial_id.c b/src/exchangedb/pg_select_purse_requests_above_serial_id.c @@ -1,174 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_select_purse_requests_above_serial_id.c - * @brief Implementation of the select_purse_requests_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_purse_requests_above_serial_id.h" -#include "helper.h" - - -/** - * Closure for #purse_deposit_serial_helper_cb(). - */ -struct PurseRequestsSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_PurseRequestCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct PurseRequestsSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -purse_requests_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct PurseRequestsSerialContext *dsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - struct TALER_Amount target_amount; - uint32_t age_limit; - struct TALER_PurseMergePublicKeyP merge_pub; - struct TALER_PurseContractPublicKeyP purse_pub; - struct TALER_PrivateContractHashP h_contract_terms; - struct TALER_PurseContractSignatureP purse_sig; - struct GNUNET_TIME_Timestamp purse_creation; - struct GNUNET_TIME_Timestamp purse_expiration; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &target_amount), - GNUNET_PQ_result_spec_uint32 ("age_limit", - &age_limit), - GNUNET_PQ_result_spec_timestamp ("purse_creation", - &purse_creation), - GNUNET_PQ_result_spec_timestamp ("purse_expiration", - &purse_expiration), - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - &purse_pub), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - &h_contract_terms), - GNUNET_PQ_result_spec_auto_from_type ("purse_sig", - &purse_sig), - GNUNET_PQ_result_spec_auto_from_type ("merge_pub", - &merge_pub), - GNUNET_PQ_result_spec_uint64 ("purse_requests_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - dsc->status = GNUNET_SYSERR; - return; - } - ret = dsc->cb (dsc->cb_cls, - rowid, - &purse_pub, - &merge_pub, - purse_creation, - purse_expiration, - &h_contract_terms, - age_limit, - &target_amount, - &purse_sig); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_select_purse_requests_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_PurseRequestCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct PurseRequestsSerialContext dsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "audit_get_purse_requests_incr", - "SELECT" - " purse_requests_serial_id" - ",purse_pub" - ",amount_with_fee" - ",age_limit" - ",h_contract_terms" - ",purse_creation" - ",purse_expiration" - ",merge_pub" - ",purse_sig" - " FROM purse_requests" - " WHERE (" - " (purse_requests_serial_id>=$1)" - " )" - " ORDER BY purse_requests_serial_id ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_get_purse_requests_incr", - params, - &purse_requests_serial_helper_cb, - &dsc); - if (GNUNET_OK != dsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_recoup_above_serial_id.c b/src/exchangedb/pg_select_recoup_above_serial_id.c @@ -1,184 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_recoup_above_serial_id.c - * @brief Implementation of the select_recoup_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_recoup_above_serial_id.h" -#include "helper.h" - - -/** - * Closure for #recoup_serial_helper_cb(). - */ -struct RecoupSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_RecoupCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct RecoupSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -recoup_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct RecoupSerialContext *psc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = psc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_CoinPublicInfo coin; - struct TALER_CoinSpendSignatureP coin_sig; - union GNUNET_CRYPTO_BlindingSecretP coin_blind; - struct TALER_Amount amount; - struct TALER_DenominationPublicKey denom_pub; - struct GNUNET_TIME_Timestamp timestamp; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("recoup_uuid", - &rowid), - GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", - &timestamp), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &coin.coin_pub), - TALER_PQ_result_spec_denom_pub ("denom_pub", - &denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &coin_sig), - GNUNET_PQ_result_spec_auto_from_type ("coin_blind", - &coin_blind), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &coin.denom_pub_hash), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &coin.h_age_commitment), - &coin.no_age_commitment), - TALER_PQ_result_spec_denom_sig ("denom_sig", - &coin.denom_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_end - }; - int ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - psc->status = GNUNET_SYSERR; - return; - } - ret = psc->cb (psc->cb_cls, - rowid, - timestamp, - &amount, - &reserve_pub, - &coin, - &denom_pub, - &coin_sig, - &coin_blind); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_recoup_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_RecoupCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct RecoupSerialContext psc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "recoup_get_incr", - "SELECT" - " recoup_uuid" - ",recoup_timestamp" - ",withdraw.reserve_pub" - ",coins.coin_pub" - ",coin_sig" - ",coin_blind" - ",denoms.denom_pub_hash" - ",coins.denom_sig" - ",coins.age_commitment_hash" - ",denoms.denom_pub" - ",amount" - " FROM recoup" - " JOIN known_coins coins" - " USING (coin_pub)" - " JOIN withdraw" - " USING (withdraw_id)" - " JOIN denominations denoms" - " ON (coins.denominations_serial = denoms.denominations_serial)" - " WHERE recoup_uuid>=$1" - " ORDER BY recoup_uuid ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "recoup_get_incr", - params, - &recoup_serial_helper_cb, - &psc); - if (GNUNET_OK != psc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c @@ -1,204 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_recoup_refresh_above_serial_id.c - * @brief Implementation of the select_recoup_refresh_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_recoup_refresh_above_serial_id.h" -#include "helper.h" - - -/** - * Closure for #recoup_refresh_serial_helper_cb(). - */ -struct RecoupRefreshSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_RecoupRefreshCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct RecoupRefreshSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -recoup_refresh_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct RecoupRefreshSerialContext *psc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = psc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - struct TALER_CoinSpendPublicKeyP old_coin_pub; - struct TALER_CoinPublicInfo coin; - struct TALER_CoinSpendSignatureP coin_sig; - union GNUNET_CRYPTO_BlindingSecretP coin_blind; - struct TALER_DenominationPublicKey denom_pub; - struct TALER_DenominationHashP old_denom_pub_hash; - struct TALER_Amount amount; - struct TALER_BlindedCoinHashP h_blind_ev; - struct GNUNET_TIME_Timestamp timestamp; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid", - &rowid), - GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", - &timestamp), - GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", - &old_coin_pub), - GNUNET_PQ_result_spec_auto_from_type ("old_denom_pub_hash", - &old_denom_pub_hash), - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &coin.coin_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &coin_sig), - GNUNET_PQ_result_spec_auto_from_type ("coin_blind", - &coin_blind), - TALER_PQ_result_spec_denom_pub ("denom_pub", - &denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", - &h_blind_ev), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &coin.denom_pub_hash), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &coin.h_age_commitment), - &coin.no_age_commitment), - TALER_PQ_result_spec_denom_sig ("denom_sig", - &coin.denom_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - psc->status = GNUNET_SYSERR; - return; - } - ret = psc->cb (psc->cb_cls, - rowid, - timestamp, - &amount, - &old_coin_pub, - &old_denom_pub_hash, - &coin, - &denom_pub, - &coin_sig, - &coin_blind); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_recoup_refresh_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_RecoupRefreshCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct RecoupRefreshSerialContext psc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_recoup_refresh_above_serial_id", - "SELECT" - " rr.recoup_refresh_uuid" - ",rr.recoup_timestamp" - ",rr.coin_sig" - ",rr.coin_blind" - ",rr.amount" - ",rrc.h_coin_ev AS h_blind_ev" // FIXME:-#9828 r.rc? r.selected_h? Old logic wanted a TALER_BlindedCoinHash, which we now need to derive (from rr.coin_blind) - ",new_coins.age_commitment_hash" - ",new_coins.coin_pub AS coin_pub" - ",new_denoms.denom_pub AS denom_pub" - ",new_denoms.denom_pub_hash" - ",new_coins.denom_sig AS denom_sig" - ",old_coins.coin_pub AS old_coin_pub" - ",old_denoms.denom_pub_hash AS old_denom_pub_hash" - " FROM recoup_refresh rr" - " INNER JOIN refresh_revealed_coins rrc" // FIXME-#9828: no such table anymore! - // but we have 'refresh_id" which is an FK into 'refresh'! - " USING (rrc_serial)" - " INNER JOIN refresh r" - // but we have 'refresh_id" which is an FK into 'refresh'! - " USING (refresh_id)" - " INNER JOIN known_coins old_coins" - " ON (r.old_coin_pub = old_coins.coin_pub)" - " INNER JOIN known_coins new_coins" - " ON (rr.coin_pub == new_coins.coin_pub)" - " INNER JOIN refresh_commitments rfc" - " ON (rrc.melt_serial_id = rfc.melt_serial_id)" - " INNER JOIN denominations new_denoms" - " ON (new_coins.denominations_serial = new_denoms.denominations_serial)" - " INNER JOIN denominations old_denoms" - " ON (old_coins.denominations_serial = old_denoms.denominations_serial)" - " WHERE recoup_refresh_uuid>=$1" - " ORDER BY recoup_refresh_uuid ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_recoup_refresh_above_serial_id", - params, - &recoup_refresh_serial_helper_cb, - &psc); - if (GNUNET_OK != psc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_refreshes_above_serial_id.c b/src/exchangedb/pg_select_refreshes_above_serial_id.c @@ -1,180 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2025 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/> - */ -/** - * @file exchangedb/pg_select_refreshes_above_serial_id.c - * @brief Implementation of the select_refreshes_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_refreshes_above_serial_id.h" -#include "helper.h" - - -/** - * Closure for #refreshs_serial_helper_cb(). - */ -struct RefreshsSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_RefreshesCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct RefreshsSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -refreshs_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct RefreshsSerialContext *rsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = rsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_DenominationPublicKey old_denom_pub; - struct TALER_CoinSpendPublicKeyP coin_pub; - struct TALER_CoinSpendSignatureP coin_sig; - struct TALER_AgeCommitmentHashP h_age_commitment; - bool ac_isnull; - struct TALER_Amount amount_with_fee; - uint64_t rowid; - struct TALER_RefreshCommitmentP rc; - size_t num_nds; - uint64_t *nds; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_denom_pub ("old_denom_pub", - &old_denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", - &coin_pub), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", - &h_age_commitment), - &ac_isnull), - GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", - &coin_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &amount_with_fee), - GNUNET_PQ_result_spec_uint64 ("refresh_id", - &rowid), - GNUNET_PQ_result_spec_auto_from_type ("rc", - &rc), - GNUNET_PQ_result_spec_array_uint64 (pg->conn, - "new_denominations_serials", - &num_nds, - &nds), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - rsc->status = GNUNET_SYSERR; - return; - } - - ret = rsc->cb (rsc->cb_cls, - rowid, - &old_denom_pub, - &coin_pub, - &coin_sig, - ac_isnull ? NULL : &h_age_commitment, - &amount_with_fee, - num_nds, - nds, - &rc); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_refreshes_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_RefreshesCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct RefreshsSerialContext rsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_refreshes_above_serial_id", - "SELECT" - " denom.denom_pub AS old_denom_pub" - ",r.old_coin_pub" - ",kc.age_commitment_hash" - ",r.old_coin_sig" - ",r.amount_with_fee" - ",r.refresh_id" - ",r.rc" - ",r.denom_serials AS new_denominations_serials" - " FROM refresh r" - " JOIN known_coins kc" - " ON (r.old_coin_pub = kc.coin_pub)" - " JOIN denominations denom" - " ON (kc.denominations_serial = denom.denominations_serial)" - " WHERE refresh_id>=$1" - " ORDER BY refresh_id ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_refreshes_above_serial_id", - params, - &refreshs_serial_helper_cb, - &rsc); - if (GNUNET_OK != rsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_refunds_above_serial_id.c b/src/exchangedb/pg_select_refunds_above_serial_id.c @@ -1,220 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_refunds_above_serial_id.c - * @brief Implementation of the select_refunds_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_refunds_above_serial_id.h" -#include "helper.h" - -/** - * Closure for #refunds_serial_helper_cb(). - */ -struct RefundsSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_RefundCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct RefundsSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -refunds_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct RefundsSerialContext *rsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = rsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_EXCHANGEDB_Refund refund; - struct TALER_DenominationPublicKey denom_pub; - uint64_t rowid; - bool full_refund; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", - &refund.details.merchant_pub), - GNUNET_PQ_result_spec_auto_from_type ("merchant_sig", - &refund.details.merchant_sig), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - &refund.details.h_contract_terms), - GNUNET_PQ_result_spec_uint64 ("rtransaction_id", - &refund.details.rtransaction_id), - TALER_PQ_result_spec_denom_pub ("denom_pub", - &denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &refund.coin.coin_pub), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &refund.details.refund_amount), - GNUNET_PQ_result_spec_uint64 ("refund_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - rsc->status = GNUNET_SYSERR; - return; - } - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&rowid), - GNUNET_PQ_query_param_end - }; - struct TALER_Amount amount_with_fee; - uint64_t s_f; - uint64_t s_v; - struct GNUNET_PQ_ResultSpec rs2[] = { - GNUNET_PQ_result_spec_uint64 ("s_v", - &s_v), - GNUNET_PQ_result_spec_uint64 ("s_f", - &s_f), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &amount_with_fee), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - qs = GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "test_refund_full", - params, - rs2); - if (qs <= 0) - { - GNUNET_break (0); - rsc->status = GNUNET_SYSERR; - return; - } - /* normalize */ - s_v += s_f / TALER_AMOUNT_FRAC_BASE; - s_f %= TALER_AMOUNT_FRAC_BASE; - full_refund = (s_v >= amount_with_fee.value) && - (s_f >= amount_with_fee.fraction); - } - ret = rsc->cb (rsc->cb_cls, - rowid, - &denom_pub, - &refund.coin.coin_pub, - &refund.details.merchant_pub, - &refund.details.merchant_sig, - &refund.details.h_contract_terms, - refund.details.rtransaction_id, - full_refund, - &refund.details.refund_amount); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_refunds_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_RefundCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct RefundsSerialContext rsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - /* Fetch refunds with rowid '\geq' the given parameter */ - PREPARE (pg, - "audit_get_refunds_incr", - "SELECT" - " bdep.merchant_pub" - ",ref.merchant_sig" - ",bdep.h_contract_terms" - ",ref.rtransaction_id" - ",denom.denom_pub" - ",kc.coin_pub" - ",ref.amount_with_fee" - ",ref.refund_serial_id" - " FROM refunds ref" - " JOIN batch_deposits bdep" - " ON (ref.batch_deposit_serial_id=bdep.batch_deposit_serial_id)" - " JOIN coin_deposits cdep" - " ON (ref.coin_pub=cdep.coin_pub AND ref.batch_deposit_serial_id=cdep.batch_deposit_serial_id)" - " JOIN known_coins kc" - " ON (cdep.coin_pub=kc.coin_pub)" - " JOIN denominations denom" - " ON (kc.denominations_serial=denom.denominations_serial)" - " WHERE ref.refund_serial_id>=$1" - " ORDER BY ref.refund_serial_id ASC;"); - PREPARE (pg, - "test_refund_full", - "SELECT" - " CAST(SUM(CAST((ref.amount_with_fee).frac AS INT8)) AS INT8) AS s_f" - ",CAST(SUM((ref.amount_with_fee).val) AS INT8) AS s_v" - ",cdep.amount_with_fee" - " FROM refunds ref" - " JOIN coin_deposits cdep" - " ON (ref.coin_pub=cdep.coin_pub AND ref.batch_deposit_serial_id=cdep.batch_deposit_serial_id)" - " WHERE ref.refund_serial_id=$1" - " GROUP BY (cdep.amount_with_fee);"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_get_refunds_incr", - params, - &refunds_serial_helper_cb, - &rsc); - if (GNUNET_OK != rsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_refunds_by_coin.c b/src/exchangedb/pg_select_refunds_by_coin.c @@ -1,139 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2023 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/> - */ -/** - * @file exchangedb/pg_select_refunds_by_coin.c - * @brief Implementation of the select_refunds_by_coin function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_refunds_by_coin.h" -#include "helper.h" - - -/** - * Closure for #get_refunds_cb(). - */ -struct SelectRefundContext -{ - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_RefundCoinCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Set to #GNUNET_SYSERR on error. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct SelectRefundContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -get_refunds_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct SelectRefundContext *srctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = srctx->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_Amount amount_with_fee; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &amount_with_fee), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - srctx->status = GNUNET_SYSERR; - return; - } - if (GNUNET_OK != - srctx->cb (srctx->cb_cls, - &amount_with_fee)) - return; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_refunds_by_coin ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_PrivateContractHashP *h_contract, - TALER_EXCHANGEDB_RefundCoinCallback cb, - void *cb_cls) -{ - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (h_contract), - GNUNET_PQ_query_param_end - }; - struct SelectRefundContext srctx = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - const char *query = "get_refunds_by_coin_and_contract"; - - PREPARE (pg, - query, - "SELECT" - " ref.amount_with_fee" - " FROM refunds ref" - " JOIN coin_deposits cdep" - " USING (coin_pub,batch_deposit_serial_id)" - " JOIN batch_deposits bdep" - " ON (ref.batch_deposit_serial_id = bdep.batch_deposit_serial_id)" - " WHERE ref.coin_pub=$1" - " AND bdep.merchant_pub=$2" - " AND bdep.h_contract_terms=$3;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - query, - params, - &get_refunds_cb, - &srctx); - if (GNUNET_SYSERR == srctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_reserve_close_info.c b/src/exchangedb/pg_select_reserve_close_info.c @@ -1,62 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_select_reserve_close_info.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_reserve_close_info.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_reserve_close_info ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct TALER_Amount *balance, - struct TALER_FullPayto *payto_uri) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_amount ("current_balance", - pg->currency, - balance), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri->full_payto), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "select_reserve_close_info", - "SELECT " - " r.current_balance" - ",wt.payto_uri" - " FROM reserves r" - " LEFT JOIN reserves_in ri" - " USING (reserve_pub)" - " LEFT JOIN wire_targets wt" - " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)" - " WHERE r.reserve_pub=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "select_reserve_close_info", - params, - rs); -} diff --git a/src/exchangedb/pg_select_reserve_close_request_info.c b/src/exchangedb/pg_select_reserve_close_request_info.c @@ -1,73 +0,0 @@ -/* - This file is part of TALER - 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 - 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/> - */ -/** - * @file pg_select_reserve_close_request_info.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_reserve_close_request_info.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_reserve_close_request_info ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_ReservePublicKeyP *reserve_pub, - uint64_t rowid, - struct TALER_ReserveSignatureP *reserve_sig, - struct GNUNET_TIME_Timestamp *request_timestamp, - struct TALER_Amount *close_balance, - struct TALER_Amount *close_fee, - struct TALER_FullPayto *payto_uri) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_uint64 (&rowid), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - reserve_sig), - GNUNET_PQ_result_spec_timestamp ("request_timestamp", - request_timestamp), - TALER_PQ_result_spec_amount ("close_balance", - pg->currency, - close_balance), - TALER_PQ_result_spec_amount ("close_fee", - pg->currency, - close_fee), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri->full_payto), - GNUNET_PQ_result_spec_end - }; - - // FIXME: this SQL query is still complete nonsense! - PREPARE (pg, - "select_reserve_close_request_info", - "SELECT " - " r.current_balance" - ",wt.payto_uri" - " FROM reserves r" - " LEFT JOIN reserves_in ri" - " USING (reserve_pub)" - " WHERE r.reserve_pub=$1" - " AND r.row_id=$2;"); - return GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "select_reserve_close_request_info", - params, - rs); -} diff --git a/src/exchangedb/pg_select_reserve_closed_above_serial_id.c b/src/exchangedb/pg_select_reserve_closed_above_serial_id.c @@ -1,172 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_select_reserve_closed_above_serial_id.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_reserve_closed_above_serial_id.h" -#include "helper.h" - -/** - * Closure for #reserve_closed_serial_helper_cb(). - */ -struct ReserveClosedSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_ReserveClosedCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin's context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct ReserveClosedSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -reserve_closed_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveClosedSerialContext *rcsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = rcsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_FullPayto receiver_account; - struct TALER_WireTransferIdentifierRawP wtid; - struct TALER_Amount amount_with_fee; - struct TALER_Amount closing_fee; - struct GNUNET_TIME_Timestamp execution_date; - uint64_t close_request_row; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("close_uuid", - &rowid), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - GNUNET_PQ_result_spec_timestamp ("execution_date", - &execution_date), - GNUNET_PQ_result_spec_auto_from_type ("wtid", - &wtid), - GNUNET_PQ_result_spec_string ("receiver_account", - &receiver_account.full_payto), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount_with_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", - &closing_fee), - GNUNET_PQ_result_spec_uint64 ("close_request_row", - &close_request_row), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - rcsc->status = GNUNET_SYSERR; - return; - } - ret = rcsc->cb (rcsc->cb_cls, - rowid, - execution_date, - &amount_with_fee, - &closing_fee, - &reserve_pub, - receiver_account, - &wtid, - close_request_row); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_reserve_closed_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_ReserveClosedCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct ReserveClosedSerialContext rcsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE ( - pg, - "reserves_close_get_incr", - "SELECT" - " close_uuid" - ",reserves.reserve_pub" - ",execution_date" - ",wtid" - ",wt.payto_uri AS receiver_account" - ",amount" - ",closing_fee" - ",close_request_row" - " FROM reserves_close" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " JOIN reserves" - " USING (reserve_pub)" - " WHERE close_uuid>=$1" - " ORDER BY close_uuid ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "reserves_close_get_incr", - params, - &reserve_closed_serial_helper_cb, - &rcsc); - if (GNUNET_OK != rcsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_reserve_open_above_serial_id.c b/src/exchangedb/pg_select_reserve_open_above_serial_id.c @@ -1,163 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file pg_select_reserve_open_above_serial_id.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_reserve_open_above_serial_id.h" -#include "helper.h" - - -/** - * Closure for #reserve_open_serial_helper_cb(). - */ -struct ReserveOpenSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_ReserveOpenCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin's context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct ReserveOpenSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -reserve_open_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveOpenSerialContext *rcsc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = rcsc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_ReserveSignatureP reserve_sig; - uint32_t requested_purse_limit; - struct GNUNET_TIME_Timestamp request_timestamp; - struct GNUNET_TIME_Timestamp reserve_expiration; - struct TALER_Amount reserve_payment; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("open_request_uuid", - &rowid), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &reserve_sig), - GNUNET_PQ_result_spec_timestamp ("request_timestamp", - &request_timestamp), - GNUNET_PQ_result_spec_timestamp ("expiration_date", - &reserve_expiration), - GNUNET_PQ_result_spec_uint32 ("requested_purse_limit", - &requested_purse_limit), - TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_payment", - &reserve_payment), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - rcsc->status = GNUNET_SYSERR; - return; - } - ret = rcsc->cb (rcsc->cb_cls, - rowid, - &reserve_payment, - request_timestamp, - reserve_expiration, - requested_purse_limit, - &reserve_pub, - &reserve_sig); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_reserve_open_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_ReserveOpenCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct ReserveOpenSerialContext rcsc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE ( - pg, - "reserves_open_get_incr", - "SELECT" - " open_request_uuid" - ",reserve_pub" - ",request_timestamp" - ",expiration_date" - ",reserve_sig" - ",reserve_payment" - ",requested_purse_limit" - " FROM reserves_open_requests" - " WHERE open_request_uuid>=$1" - " ORDER BY open_request_uuid ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "reserves_open_get_incr", - params, - &reserve_open_serial_helper_cb, - &rcsc); - if (GNUNET_OK != rcsc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id.c b/src/exchangedb/pg_select_reserves_in_above_serial_id.c @@ -1,163 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_reserves_in_above_serial_id.c - * @brief Implementation of the select_reserves_in_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_reserves_in_above_serial_id.h" -#include "helper.h" - -/** - * Closure for #reserves_in_serial_helper_cb(). - */ -struct ReservesInSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_ReserveInCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct ReservesInSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -reserves_in_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReservesInSerialContext *risc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = risc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_Amount credit; - struct TALER_FullPayto sender_account_details; - struct GNUNET_TIME_Timestamp execution_date; - uint64_t rowid; - uint64_t wire_reference; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - GNUNET_PQ_result_spec_uint64 ("wire_reference", - &wire_reference), - TALER_PQ_RESULT_SPEC_AMOUNT ("credit", - &credit), - GNUNET_PQ_result_spec_timestamp ("execution_date", - &execution_date), - GNUNET_PQ_result_spec_string ("sender_account_details", - &sender_account_details.full_payto), - GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - risc->status = GNUNET_SYSERR; - return; - } - ret = risc->cb (risc->cb_cls, - rowid, - &reserve_pub, - &credit, - sender_account_details, - wire_reference, - execution_date); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_reserves_in_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_ReserveInCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct ReservesInSerialContext risc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_reserves_in_above_serial_id", - "SELECT" - " reserves.reserve_pub" - ",wire_reference" - ",credit" - ",execution_date" - ",wt.payto_uri AS sender_account_details" - ",reserve_in_serial_id" - " FROM reserves_in" - " JOIN reserves" - " USING (reserve_pub)" - " JOIN wire_targets wt" - " ON (wire_source_h_payto = wire_target_h_payto)" - " WHERE reserve_in_serial_id>=$1" - " ORDER BY reserve_in_serial_id;"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_reserves_in_above_serial_id", - params, - &reserves_in_serial_helper_cb, - &risc); - if (GNUNET_DB_STATUS_SOFT_ERROR == qs) - return qs; - if (GNUNET_OK != risc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c b/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c @@ -1,166 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_select_reserves_in_above_serial_id_by_account.c - * @brief Implementation of the select_reserves_in_above_serial_id_by_account function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include \ - "taler/exchange-database/select_reserves_in_above_serial_id_by_account.h" -#include "helper.h" - - -/** - * Closure for #reserves_in_serial_helper_cb(). - */ -struct ReservesInSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_ReserveInCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct ReservesInSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -reserves_in_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReservesInSerialContext *risc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = risc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_Amount credit; - struct TALER_FullPayto sender_account_details; - struct GNUNET_TIME_Timestamp execution_date; - uint64_t rowid; - uint64_t wire_reference; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - GNUNET_PQ_result_spec_uint64 ("wire_reference", - &wire_reference), - TALER_PQ_RESULT_SPEC_AMOUNT ("credit", - &credit), - GNUNET_PQ_result_spec_timestamp ("execution_date", - &execution_date), - GNUNET_PQ_result_spec_string ("sender_account_details", - &sender_account_details.full_payto), - GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id", - &rowid), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - risc->status = GNUNET_SYSERR; - return; - } - ret = risc->cb (risc->cb_cls, - rowid, - &reserve_pub, - &credit, - sender_account_details, - wire_reference, - execution_date); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_select_reserves_in_above_serial_id_by_account ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *account_name, - uint64_t serial_id, - TALER_EXCHANGEDB_ReserveInCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_string (account_name), - GNUNET_PQ_query_param_end - }; - struct ReservesInSerialContext risc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_reserves_in_above_serial_id_by_account", - "SELECT" - " reserves.reserve_pub" - ",wire_reference" - ",credit" - ",execution_date" - ",wt.payto_uri AS sender_account_details" - ",reserve_in_serial_id" - " FROM reserves_in" - " JOIN reserves " - " USING (reserve_pub)" - " JOIN wire_targets wt" - " ON (wire_source_h_payto = wire_target_h_payto)" - " WHERE reserve_in_serial_id>=$1" - " AND exchange_account_section=$2" - " ORDER BY reserve_in_serial_id ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_reserves_in_above_serial_id_by_account", - params, - &reserves_in_serial_helper_cb, - &risc); - if (GNUNET_OK != risc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id.c b/src/exchangedb/pg_select_wire_out_above_serial_id.c @@ -1,154 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_select_wire_out_above_serial_id.c - * @brief Implementation of the select_wire_out_above_serial_id function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_wire_out_above_serial_id.h" -#include "helper.h" - -/** - * Closure for #wire_out_serial_helper_cb(). - */ -struct WireOutSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_WireTransferOutCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - int status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct WireOutSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -wire_out_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct WireOutSerialContext *wosc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = wosc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - struct GNUNET_TIME_Timestamp date; - struct TALER_WireTransferIdentifierRawP wtid; - struct TALER_FullPayto payto_uri; - struct TALER_Amount amount; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("wireout_uuid", - &rowid), - GNUNET_PQ_result_spec_timestamp ("execution_date", - &date), - GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", - &wtid), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri.full_payto), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_end - }; - int ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - wosc->status = GNUNET_SYSERR; - return; - } - ret = wosc->cb (wosc->cb_cls, - rowid, - date, - &wtid, - payto_uri, - &amount); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_wire_out_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_WireTransferOutCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct WireOutSerialContext wosc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_wire_out_above_serial_id", - "SELECT" - " wo.wireout_uuid" - ",wo.execution_date" - ",wo.wtid_raw" - ",wt.payto_uri" - ",wo.amount" - " FROM wire_out wo" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " WHERE wireout_uuid>=$1" - " ORDER BY wireout_uuid ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_wire_out_above_serial_id", - params, - &wire_out_serial_helper_cb, - &wosc); - if (GNUNET_OK != wosc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c @@ -1,157 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_select_wire_out_above_serial_id_by_account.c - * @brief Implementation of the select_wire_out_above_serial_id_by_account function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_wire_out_above_serial_id_by_account.h" -#include "helper.h" - -/** - * Closure for #wire_out_serial_helper_cb(). - */ -struct WireOutSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_WireTransferOutCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - int status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct WireOutSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -wire_out_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct WireOutSerialContext *wosc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = wosc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - struct GNUNET_TIME_Timestamp date; - struct TALER_WireTransferIdentifierRawP wtid; - struct TALER_FullPayto payto_uri; - struct TALER_Amount amount; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("wireout_uuid", - &rowid), - GNUNET_PQ_result_spec_timestamp ("execution_date", - &date), - GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", - &wtid), - GNUNET_PQ_result_spec_string ("payto_uri", - &payto_uri.full_payto), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_end - }; - int ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - wosc->status = GNUNET_SYSERR; - return; - } - ret = wosc->cb (wosc->cb_cls, - rowid, - date, - &wtid, - payto_uri, - &amount); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_TALER_EXCHANGEDB_select_wire_out_above_serial_id_by_account ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *account_name, - uint64_t serial_id, - TALER_EXCHANGEDB_WireTransferOutCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_string (account_name), - GNUNET_PQ_query_param_end - }; - struct WireOutSerialContext wosc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_wire_out_above_serial_id_by_account", - "SELECT" - " wo.wireout_uuid" - ",wo.execution_date" - ",wo.wtid_raw" - ",wt.payto_uri" - ",wo.amount" - " FROM wire_out wo" - " JOIN wire_targets wt" - " USING (wire_target_h_payto)" - " WHERE wo.wireout_uuid>=$1 " - " AND wo.exchange_account_section=$2" - " ORDER BY wo.wireout_uuid ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_wire_out_above_serial_id_by_account", - params, - &wire_out_serial_helper_cb, - &wosc); - if (GNUNET_OK != wosc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.c b/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.c @@ -1,158 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_select_withdraw_amounts_for_kyc_check.c - * @brief Implementation of the select_withdraw_amounts_for_kyc_check function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_withdraw_amounts_for_kyc_check.h" -#include "taler/exchange-database/select_aggregation_amounts_for_kyc_check.h" -#include "helper.h" - - -/** - * Closure for #get_kyc_amounts_cb(). - */ -struct KycAmountCheckContext -{ - /** - * Function to call per result. - */ - TALER_KYCLOGIC_KycAmountCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Flag set to #GNUNET_OK as long as everything is fine. - */ - enum GNUNET_GenericReturnValue status; - -}; - -/** - * Invoke the callback for each result. - * - * @param cls a `struct KycAmountCheckContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -get_kyc_amounts_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct KycAmountCheckContext *ctx = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; - - for (unsigned int i = 0; i < num_results; i++) - { - struct GNUNET_TIME_Absolute date; - struct TALER_Amount amount; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &amount), - GNUNET_PQ_result_spec_absolute_time ("date", - &date), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->status = GNUNET_SYSERR; - return; - } - ret = ctx->cb (ctx->cb_cls, - &amount, - date); - GNUNET_PQ_cleanup_result (rs); - switch (ret) - { - case GNUNET_OK: - continue; - case GNUNET_NO: - break; - case GNUNET_SYSERR: - ctx->status = GNUNET_SYSERR; - break; - } - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_withdraw_amounts_for_kyc_check ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - struct GNUNET_TIME_Absolute time_limit, - TALER_KYCLOGIC_KycAmountCallback kac, - void *kac_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_absolute_time (&time_limit), - GNUNET_PQ_query_param_end - }; - struct KycAmountCheckContext ctx = { - .cb = kac, - .cb_cls = kac_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "select_withdraw_amounts_for_kyc_check", - "SELECT" - " wd.amount_with_fee AS amount" - ",wd.execution_date AS date" - " FROM reserves_in ri" - " JOIN reserve_history rh" - " ON (rh.reserve_pub = ri.reserve_pub)" - " JOIN withdraw wd" - " ON (wd.withdraw_id = rh.serial_id)" - " WHERE ri.wire_source_h_payto IN (" - " SELECT wire_target_h_payto" - " FROM wire_targets" - " WHERE h_normalized_payto=$1" - " )" - " AND rh.table_name='withdraw'" - " AND wd.execution_date >= $2" - " ORDER BY rh.reserve_history_serial_id DESC"); - qs = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "select_withdraw_amounts_for_kyc_check", - params, - &get_kyc_amounts_cb, - &ctx); - if (GNUNET_OK != ctx.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_select_withdrawals_above_serial_id.c b/src/exchangedb/pg_select_withdrawals_above_serial_id.c @@ -1,212 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_select_withdrawals_above_serial_id.c - * @brief Implementation of the select_withdrawals_above_serial_id function for Postgres - * @author Christian Grothoff - * @author Özgür Kesim - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/select_withdrawals_above_serial_id.h" -#include "helper.h" - -/** - * Closure for #withdraw_serial_helper_cb(). - */ -struct WithdrawSerialContext -{ - - /** - * Callback to call. - */ - TALER_EXCHANGEDB_WithdrawCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Plugin context. - */ - struct TALER_EXCHANGEDB_PostgresContext *pg; - - /** - * Status code, set to #GNUNET_SYSERR on hard errors. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Helper function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure of type `struct WithdrawSerialContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -withdraw_serial_helper_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct WithdrawSerialContext *rosc = cls; - struct TALER_EXCHANGEDB_PostgresContext *pg = rosc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - uint64_t rowid; - struct TALER_HashBlindedPlanchetsP h_planchets; - struct GNUNET_TIME_Timestamp execution_date; - struct TALER_Amount amount_with_fee; - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_ReserveSignatureP reserve_sig; - uint16_t max_age; - bool no_max_age; - uint16_t noreveal_index; - bool no_noreveal_index; - struct TALER_HashBlindedPlanchetsP selected_h; - bool no_selected_h; - struct TALER_BlindingMasterSeedP blinding_seed; - bool no_blinding_seed; - size_t num_denom_serials; - uint64_t *denom_serials = NULL; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("withdraw_id", - &rowid), - GNUNET_PQ_result_spec_auto_from_type ("planchets_h", - &h_planchets), - GNUNET_PQ_result_spec_timestamp ("execution_date", - &execution_date), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &amount_with_fee), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &reserve_sig), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint16 ("max_age", - &max_age), - &no_max_age), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint16 ("noreveal_index", - &noreveal_index), - &no_noreveal_index), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ( - "selected_h", - &selected_h), - &no_selected_h), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_auto_from_type ( - "blinding_seed", - &blinding_seed), - &no_blinding_seed), - GNUNET_PQ_result_spec_array_uint64 ( - pg->conn, - "denom_serials", - &num_denom_serials, - &denom_serials), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_GenericReturnValue ret; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - rosc->status = GNUNET_SYSERR; - GNUNET_PQ_cleanup_result (rs); - return; - } - if ((! no_max_age) && - ((255 <= noreveal_index) || (255 <= max_age))) - { - GNUNET_break (0); - rosc->status = GNUNET_SYSERR; - GNUNET_PQ_cleanup_result (rs); - return; - } - ret = rosc->cb (rosc->cb_cls, - rowid, - num_denom_serials, - denom_serials, - no_selected_h ? NULL : &selected_h, - &h_planchets, - no_blinding_seed ? NULL : &blinding_seed, - ! no_max_age, - (uint8_t) max_age, - (uint8_t) noreveal_index, - &reserve_pub, - &reserve_sig, - execution_date, - &amount_with_fee); - GNUNET_PQ_cleanup_result (rs); - if (GNUNET_OK != ret) - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_select_withdrawals_above_serial_id ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t serial_id, - TALER_EXCHANGEDB_WithdrawCallback cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&serial_id), - GNUNET_PQ_query_param_end - }; - struct WithdrawSerialContext rosc = { - .cb = cb, - .cb_cls = cb_cls, - .pg = pg, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - /* Fetch deposits with rowid '\geq' the given parameter */ - PREPARE (pg, - "audit_get_withdraw_incr", - "SELECT" - " withdraw_id" - ",planchets_h" - ",execution_date" - ",amount_with_fee" - ",reserve_pub" - ",reserve_sig" - ",max_age" - ",noreveal_index" - ",selected_h" - ",blinding_seed" - ",denom_serials" - " FROM withdraw" - " WHERE withdraw_id>=$1" - " ORDER BY withdraw_id ASC;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "audit_get_withdraw_incr", - params, - &withdraw_serial_helper_cb, - &rosc); - if (GNUNET_OK != rosc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_set_aml_lock.c b/src/exchangedb/pg_set_aml_lock.c @@ -1,70 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_set_aml_lock.c - * @brief Implementation of the set_aml_lock function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/set_aml_lock.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_set_aml_lock ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_NormalizedPaytoHashP *h_payto, - struct GNUNET_TIME_Relative lock_duration, - struct GNUNET_TIME_Absolute *existing_lock) -{ - - struct GNUNET_TIME_Absolute expires - = GNUNET_TIME_relative_to_absolute (lock_duration); - struct GNUNET_TIME_Absolute now - = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_absolute_time (&expires), - GNUNET_PQ_query_param_end - }; - bool nx; /* true if the *account* is not known */ - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_absolute_time ("out_aml_program_lock_timeout", - existing_lock), - &nx), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "set_aml_lock", - "SELECT out_aml_program_lock_timeout" - " FROM exchange_do_set_aml_lock($1,$2,$3);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "set_aml_lock", - params, - rs); - if (qs <= 0) - return qs; - if (nx) - { - *existing_lock = GNUNET_TIME_UNIT_ZERO_ABS; - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - return qs; -} diff --git a/src/exchangedb/pg_set_extension_manifest.c b/src/exchangedb/pg_set_extension_manifest.c @@ -1,53 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_set_extension_manifest.c - * @brief Implementation of the set_extension_manifest function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/set_extension_manifest.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_set_extension_manifest (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const char *extension_name, - const char *manifest) -{ - struct GNUNET_PQ_QueryParam pcfg = - (NULL == manifest || 0 == *manifest) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (manifest); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (extension_name), - pcfg, - GNUNET_PQ_query_param_end - }; - - - PREPARE (pg, - "set_extension_manifest", - "INSERT INTO extensions (name, manifest) VALUES ($1, $2) " - "ON CONFLICT (name) " - "DO UPDATE SET manifest=$2"); - - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "set_extension_manifest", - params); -} diff --git a/src/exchangedb/pg_set_purse_balance.c b/src/exchangedb/pg_set_purse_balance.c @@ -1,48 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_set_purse_balance.c - * @brief Implementation of the set_purse_balance function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/set_purse_balance.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_set_purse_balance ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_Amount *balance) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (purse_pub), - TALER_PQ_query_param_amount (pg->conn, - balance), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "set_purse_balance", - "UPDATE purse_requests" - " SET balance=$2" - " WHERE purse_pub=$1;"); - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "set_purse_balance", - params); -} diff --git a/src/exchangedb/pg_start.c b/src/exchangedb/pg_start.c @@ -1,51 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_start.c - * @brief Implementation of the start function for Postgres - * @author Christian Grothoff - */ -#include "taler/exchange-database/preflight.h" -#include "taler/exchange-database/start.h" -#include "helper.h" - -enum GNUNET_GenericReturnValue -TALER_EXCHANGEDB_start (struct TALER_EXCHANGEDB_PostgresContext *pg, - const char *name) -{ - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL SERIALIZABLE"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - - GNUNET_assert (NULL != name); - if (GNUNET_SYSERR == - TALER_EXCHANGEDB_preflight (pg)) - return GNUNET_SYSERR; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Starting transaction `%s'\n", - name); - if (GNUNET_OK != - GNUNET_PQ_exec_statements (pg->conn, - es)) - { - TALER_LOG_ERROR ("Failed to start transaction\n"); - GNUNET_break (0); - return GNUNET_SYSERR; - } - pg->transaction_name = name; - return GNUNET_OK; -} diff --git a/src/exchangedb/pg_start_deferred_wire_out.c b/src/exchangedb/pg_start_deferred_wire_out.c @@ -1,56 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_start_deferred_wire_out.c - * @brief Implementation of the start_deferred_wire_out function for Postgres - * @author Christian Grothoff - */ -#include "taler/exchange-database/start_deferred_wire_out.h" -#include "helper.h" -#include "taler/exchange-database/preflight.h" -#include "taler/exchange-database/rollback.h" - -enum GNUNET_GenericReturnValue -TALER_TALER_EXCHANGEDB_start_deferred_wire_out (struct - TALER_EXCHANGEDB_PostgresContext - *pg) -{ - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_execute ( - "START TRANSACTION ISOLATION LEVEL READ COMMITTED;"), - GNUNET_PQ_make_execute ("SET CONSTRAINTS ALL DEFERRED;"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - - if (GNUNET_SYSERR == - TALER_EXCHANGEDB_preflight (pg)) - return GNUNET_SYSERR; - if (GNUNET_OK != - GNUNET_PQ_exec_statements (pg->conn, - es)) - { - TALER_LOG_ERROR ( - "Failed to defer wire_out_ref constraint on transaction\n"); - GNUNET_break (0); - TALER_EXCHANGEDB_rollback (pg); - return GNUNET_SYSERR; - } - pg->transaction_name = "deferred wire out"; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Starting READ COMMITTED DEFERRED transaction `%s'\n", - pg->transaction_name); - return GNUNET_OK; -} diff --git a/src/exchangedb/pg_start_read_committed.c b/src/exchangedb/pg_start_read_committed.c @@ -1,53 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_start_read_committed.c - * @brief Implementation of the start_read_committed function for Postgres - * @author Christian Grothoff - */ -#include "taler/exchange-database/start_read_committed.h" -#include "taler/exchange-database/preflight.h" -#include "helper.h" - -enum GNUNET_GenericReturnValue -TALER_TALER_EXCHANGEDB_start_read_committed (struct - TALER_EXCHANGEDB_PostgresContext * - pg, - const char *name) -{ - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL READ COMMITTED"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - - GNUNET_assert (NULL != name); - if (GNUNET_SYSERR == - TALER_EXCHANGEDB_preflight (pg)) - return GNUNET_SYSERR; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Starting READ COMMITTED transaction `%s`\n", - name); - if (GNUNET_OK != - GNUNET_PQ_exec_statements (pg->conn, - es)) - { - TALER_LOG_ERROR ("Failed to start transaction\n"); - GNUNET_break (0); - return GNUNET_SYSERR; - } - pg->transaction_name = name; - return GNUNET_OK; -} diff --git a/src/exchangedb/pg_start_read_only.c b/src/exchangedb/pg_start_read_only.c @@ -1,53 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_start_read_only.c - * @brief Implementation of the start_read_only function for Postgres - * @author Christian Grothoff - */ -#include "taler/exchange-database/start_read_only.h" -#include "taler/exchange-database/preflight.h" -#include "helper.h" - -enum GNUNET_GenericReturnValue -TALER_TALER_EXCHANGEDB_start_read_only (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const char *name) -{ - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_execute ( - "START TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - - GNUNET_assert (NULL != name); - if (GNUNET_SYSERR == - TALER_EXCHANGEDB_preflight (pg)) - return GNUNET_SYSERR; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Starting READ ONLY transaction `%s`\n", - name); - if (GNUNET_OK != - GNUNET_PQ_exec_statements (pg->conn, - es)) - { - TALER_LOG_ERROR ("Failed to start transaction\n"); - GNUNET_break (0); - return GNUNET_SYSERR; - } - pg->transaction_name = name; - return GNUNET_OK; -} diff --git a/src/exchangedb/pg_store_wire_transfer_out.c b/src/exchangedb/pg_store_wire_transfer_out.c @@ -1,63 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_store_wire_transfer_out.c - * @brief Implementation of the store_wire_transfer_out function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/store_wire_transfer_out.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_store_wire_transfer_out ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - struct GNUNET_TIME_Timestamp date, - const struct TALER_WireTransferIdentifierRawP *wtid, - const struct TALER_FullPaytoHashP *h_payto, - const char *exchange_account_section, - const struct TALER_Amount *amount, - const char *extra_wire_subject_metadata) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&date), - GNUNET_PQ_query_param_auto_from_type (wtid), - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_string (exchange_account_section), - TALER_PQ_query_param_amount (pg->conn, - amount), - NULL == extra_wire_subject_metadata - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (extra_wire_subject_metadata), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_wire_out", - "INSERT INTO wire_out " - "(execution_date" - ",wtid_raw" - ",wire_target_h_payto" - ",exchange_account_section" - ",amount" - ",extra_wire_subject_metadata" - ") VALUES " - "($1, $2, $3, $4, $5, $6);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_wire_out", - params); -} diff --git a/src/exchangedb/pg_template.c b/src/exchangedb/pg_template.c @@ -1,20 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 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/> - */ -/** - * @file exchangedb/pg_template.c - * @brief Implementation of the template function for Postgres - * @author Christian Grothoff - */ diff --git a/src/exchangedb/pg_test_aml_officer.c b/src/exchangedb/pg_test_aml_officer.c @@ -1,52 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_test_aml_officer.c - * @brief Implementation of the test_aml_officer function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/test_aml_officer.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_test_aml_officer ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_AmlOfficerPublicKeyP *decider_pub, - bool *read_only) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (decider_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("read_only", - read_only), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "test_aml_staff", - "SELECT read_only" - " FROM aml_staff" - " WHERE decider_pub=$1" - " AND is_active;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "test_aml_staff", - params, - rs); -} diff --git a/src/exchangedb/pg_trigger_kyc_rule_for_account.c b/src/exchangedb/pg_trigger_kyc_rule_for_account.c @@ -1,98 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_trigger_kyc_rule_for_account.c - * @brief Implementation of the trigger_kyc_rule_for_account function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/trigger_kyc_rule_for_account.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_trigger_kyc_rule_for_account ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_FullPayto payto_uri, - const struct TALER_NormalizedPaytoHashP *h_payto, - const union TALER_AccountPublicKeyP *set_account_pub, - const struct TALER_MerchantPublicKeyP *check_merchant_pub, - const json_t *jmeasures, - uint32_t display_priority, - uint64_t *requirement_row, - bool *bad_kyc_auth) -{ - struct GNUNET_TIME_Absolute now - = GNUNET_TIME_absolute_get (); - struct TALER_EXCHANGEDB_KycCompletedEventP rep = { - .header.size = htons (sizeof (rep)), - .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), - .h_payto = *h_payto - }; - char *notify_str - = GNUNET_PQ_get_event_notify_channel (&rep.header); - struct TALER_FullPaytoHashP h_full_payto; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - NULL == set_account_pub - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (set_account_pub), - NULL == check_merchant_pub - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (check_merchant_pub), - NULL == payto_uri.full_payto - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (payto_uri.full_payto), - NULL == payto_uri.full_payto - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (&h_full_payto), - GNUNET_PQ_query_param_absolute_time (&now), - TALER_PQ_query_param_json (jmeasures), - GNUNET_PQ_query_param_uint32 (&display_priority), - GNUNET_PQ_query_param_string (notify_str), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ( - "legitimization_measure_serial_id", - requirement_row), - GNUNET_PQ_result_spec_bool ( - "bad_kyc_auth", - bad_kyc_auth), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "trigger_kyc_rule_for_account", - "SELECT" - " out_legitimization_measure_serial_id" - " AS legitimization_measure_serial_id" - " ,out_bad_kyc_auth" - " AS bad_kyc_auth" - " FROM exchange_do_trigger_kyc_rule_for_account" - "($1, $2, $3, $4, $5, $6, $7::TEXT::JSONB, $8, $9);"); - if (NULL != payto_uri.full_payto) - TALER_full_payto_hash (payto_uri, - &h_full_payto); - qs = GNUNET_PQ_eval_prepared_singleton_select ( - pg->conn, - "trigger_kyc_rule_for_account", - params, - rs); - GNUNET_free (notify_str); - return qs; -} diff --git a/src/exchangedb/pg_update_aggregation_transient.c b/src/exchangedb/pg_update_aggregation_transient.c @@ -1,54 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_update_aggregation_transient.c - * @brief Implementation of the update_aggregation_transient function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/update_aggregation_transient.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_update_aggregation_transient ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_FullPaytoHashP *h_payto, - const struct TALER_WireTransferIdentifierRawP *wtid, - uint64_t kyc_requirement_row, - const struct TALER_Amount *total) -{ - struct GNUNET_PQ_QueryParam params[] = { - TALER_PQ_query_param_amount (pg->conn, - total), - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_auto_from_type (wtid), - GNUNET_PQ_query_param_uint64 (&kyc_requirement_row), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "update_aggregation_transient", - "UPDATE aggregation_transient" - " SET amount=$1" - " ,legitimization_requirement_serial_id=$4" - " WHERE wire_target_h_payto=$2" - " AND wtid_raw=$3"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_aggregation_transient", - params); -} diff --git a/src/exchangedb/pg_update_auditor.c b/src/exchangedb/pg_update_auditor.c @@ -1,56 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_update_auditor.c - * @brief Implementation of the update_auditor function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/update_auditor.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_update_auditor (struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_AuditorPublicKeyP * - auditor_pub, - const char *auditor_url, - const char *auditor_name, - struct GNUNET_TIME_Timestamp change_date, - bool enabled) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (auditor_pub), - GNUNET_PQ_query_param_string (auditor_url), - GNUNET_PQ_query_param_string (auditor_name), - GNUNET_PQ_query_param_bool (enabled), - GNUNET_PQ_query_param_timestamp (&change_date), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "update_auditor", - "UPDATE auditors" - " SET" - " auditor_url=$2" - " ,auditor_name=$3" - " ,is_active=$4" - " ,last_change=$5" - " WHERE auditor_pub=$1"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_auditor", - params); -} diff --git a/src/exchangedb/pg_update_kyc_process_by_row.c b/src/exchangedb/pg_update_kyc_process_by_row.c @@ -1,131 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2024 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/> - */ -/** - * @file exchangedb/pg_update_kyc_process_by_row.c - * @brief Implementation of the update_kyc_process_by_row function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_error_codes.h" -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/update_kyc_process_by_row.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_update_kyc_process_by_row ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t process_row, - const char *provider_name, - const struct TALER_NormalizedPaytoHashP *h_payto, - const char *provider_account_id, - const char *provider_legitimization_id, - const char *redirect_url, - struct GNUNET_TIME_Absolute expiration, - enum TALER_ErrorCode ec, - const char *error_message_hint, - bool finished) -{ - uint32_t ec32 = (uint32_t) ec; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&process_row), - GNUNET_PQ_query_param_string (provider_name), - GNUNET_PQ_query_param_auto_from_type (h_payto), /*3*/ - (NULL != provider_account_id) - ? GNUNET_PQ_query_param_string (provider_account_id) - : GNUNET_PQ_query_param_null (), /*4*/ - (NULL != provider_legitimization_id) - ? GNUNET_PQ_query_param_string (provider_legitimization_id) - : GNUNET_PQ_query_param_null (), /*5*/ - (NULL != redirect_url) - ? GNUNET_PQ_query_param_string (redirect_url) - : GNUNET_PQ_query_param_null (), /*6*/ - GNUNET_PQ_query_param_absolute_time (&expiration), - GNUNET_PQ_query_param_uint32 (&ec32), /* 8 */ - (NULL != error_message_hint) - ? GNUNET_PQ_query_param_string (error_message_hint) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_bool (finished), /* 10 */ - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Updating KYC data for %llu (%s)\n", - (unsigned long long) process_row, - provider_name); - PREPARE (pg, - "update_legitimization_process", - "UPDATE legitimization_processes" - " SET provider_user_id=$4" - " ,provider_legitimization_id=$5" - " ,redirect_url=$6" - " ,expiration_time=GREATEST(expiration_time,$7)" - " ,error_code=$8" - " ,error_message=$9" - " ,finished=$10" - " WHERE" - " h_payto=$3" - " AND legitimization_process_serial_id=$1" - " AND provider_name=$2;"); - qs = GNUNET_PQ_eval_prepared_non_select ( - pg->conn, - "update_legitimization_process", - params); - if (qs <= 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to update legitimization process %llu: %d\n", - (unsigned long long) process_row, - qs); - return qs; - } - if (GNUNET_TIME_absolute_is_future (expiration)) - { - enum GNUNET_DB_QueryStatus qs2; - struct TALER_EXCHANGEDB_KycCompletedEventP rep = { - .header.size = htons (sizeof (rep)), - .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), - .h_payto = *h_payto - }; - uint32_t trigger_type = 1; - struct GNUNET_PQ_QueryParam params2[] = { - GNUNET_PQ_query_param_auto_from_type (h_payto), - GNUNET_PQ_query_param_uint32 (&trigger_type), - GNUNET_PQ_query_param_end - }; - - GNUNET_PQ_event_notify (pg->conn, - &rep.header, - NULL, - 0); - PREPARE (pg, - "alert_kyc_status_change", - "INSERT INTO kyc_alerts" - " (h_payto" - " ,trigger_type)" - " VALUES" - " ($1,$2);"); - qs2 = GNUNET_PQ_eval_prepared_non_select ( - pg->conn, - "alert_kyc_status_change", - params2); - if (qs2 < 0) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to store KYC alert: %d\n", - qs2); - } - return qs; -} diff --git a/src/exchangedb/pg_update_wire.c b/src/exchangedb/pg_update_wire.c @@ -1,88 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022, 2023, 2024 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/> - */ -/** - * @file exchangedb/pg_update_wire.c - * @brief Implementation of the update_wire function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/update_wire.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_update_wire ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_FullPayto payto_uri, - const char *conversion_url, - const char *open_banking_gateway, - const char *wire_transfer_gateway, - const json_t *debit_restrictions, - const json_t *credit_restrictions, - struct GNUNET_TIME_Timestamp change_date, - const struct TALER_MasterSignatureP *master_sig, - const char *bank_label, - int64_t priority, - bool enabled) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (payto_uri.full_payto), - GNUNET_PQ_query_param_bool (enabled), - NULL == conversion_url - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (conversion_url), - enabled - ? TALER_PQ_query_param_json (debit_restrictions) - : GNUNET_PQ_query_param_null (), - enabled - ? TALER_PQ_query_param_json (credit_restrictions) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_timestamp (&change_date), - NULL == master_sig - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_auto_from_type (master_sig), - NULL == bank_label - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (bank_label), - GNUNET_PQ_query_param_int64 (&priority), - NULL == open_banking_gateway - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (open_banking_gateway), - NULL == wire_transfer_gateway - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (wire_transfer_gateway), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "update_wire", - "UPDATE wire_accounts" - " SET" - " is_active=$2" - " ,conversion_url=$3" - " ,debit_restrictions=$4::TEXT::JSONB" - " ,credit_restrictions=$5::TEXT::JSONB" - " ,last_change=$6" - " ,master_sig=$7" - " ,bank_label=$8" - " ,priority=$9" - " ,open_banking_gateway=$10" - " ,wire_transfer_gateway=$11" - " WHERE payto_uri=$1"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_wire", - params); -} diff --git a/src/exchangedb/pg_wad_in_insert.c b/src/exchangedb/pg_wad_in_insert.c @@ -1,58 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 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/> - */ -/** - * @file exchangedb/pg_wad_in_insert.c - * @brief Implementation of the wad_in_insert function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/wad_in_insert.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_wad_in_insert ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_WadIdentifierP *wad_id, - const char *origin_exchange_url, - const struct TALER_Amount *amount, - struct GNUNET_TIME_Timestamp execution_date, - const struct TALER_FullPayto debit_account_uri, - const char *section_name, - uint64_t serial_id) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (wad_id), - GNUNET_PQ_query_param_string (origin_exchange_url), - TALER_PQ_query_param_amount (pg->conn, - amount), - GNUNET_PQ_query_param_timestamp (&execution_date), - GNUNET_PQ_query_param_end - }; - - // FIXME-#7271: should we keep the account data + serial_id? - PREPARE (pg, - "wad_in_insert", - "INSERT INTO wads_in " - "(wad_id" - ",origin_exchange_url" - ",amount" - ",arrival_time" - ") VALUES " - "($1, $2, $3, $4);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "wad_in_insert", - params); -} diff --git a/src/exchangedb/pg_wire_prepare_data_get.c b/src/exchangedb/pg_wire_prepare_data_get.c @@ -1,138 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_wire_prepare_data_get.c - * @brief Implementation of the wire_prepare_data_get function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/wire_prepare_data_get.h" -#include "helper.h" - -/** - * Closure for #prewire_cb(). - */ -struct PrewireContext -{ - /** - * Function to call on each result. - */ - TALER_EXCHANGEDB_WirePreparationIterator cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * #GNUNET_OK if everything went fine. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Invoke the callback for each result. - * - * @param cls a `struct MissingWireContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -prewire_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct PrewireContext *pc = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - uint64_t prewire_uuid; - char *wire_method; - void *buf = NULL; - size_t buf_size; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("prewire_uuid", - &prewire_uuid), - GNUNET_PQ_result_spec_string ("wire_method", - &wire_method), - GNUNET_PQ_result_spec_variable_size ("buf", - &buf, - &buf_size), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - pc->status = GNUNET_SYSERR; - return; - } - pc->cb (pc->cb_cls, - prewire_uuid, - wire_method, - buf, - buf_size); - GNUNET_PQ_cleanup_result (rs); - } -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_wire_prepare_data_get (struct - TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t start_row, - uint64_t limit, - TALER_EXCHANGEDB_WirePreparationIterator - cb, - void *cb_cls) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&start_row), - GNUNET_PQ_query_param_uint64 (&limit), - GNUNET_PQ_query_param_end - }; - struct PrewireContext pc = { - .cb = cb, - .cb_cls = cb_cls, - .status = GNUNET_OK - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "wire_prepare_data_get", - "SELECT" - " prewire_uuid" - ",wire_method" - ",buf" - " FROM prewire" - " WHERE prewire_uuid >= $1" - " AND finished=FALSE" - " AND failed=FALSE" - " ORDER BY prewire_uuid ASC" - " LIMIT $2;"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "wire_prepare_data_get", - params, - &prewire_cb, - &pc); - if (GNUNET_OK != pc.status) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} diff --git a/src/exchangedb/pg_wire_prepare_data_insert.c b/src/exchangedb/pg_wire_prepare_data_insert.c @@ -1,51 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_wire_prepare_data_insert.c - * @brief Implementation of the wire_prepare_data_insert function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/wire_prepare_data_insert.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_wire_prepare_data_insert (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const char *type, - const char *buf, - size_t buf_size) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (type), - GNUNET_PQ_query_param_fixed_size (buf, buf_size), - GNUNET_PQ_query_param_end - }; - - - /* Used in #postgres_wire_prepare_data_insert() to store - wire transfer information before actually committing it with the bank */ - PREPARE (pg, - "wire_prepare_data_insert", - "INSERT INTO prewire " - "(wire_method" - ",buf" - ") VALUES " - "($1, $2);"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "wire_prepare_data_insert", - params); -} diff --git a/src/exchangedb/pg_wire_prepare_data_mark_failed.c b/src/exchangedb/pg_wire_prepare_data_mark_failed.c @@ -1,44 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_wire_prepare_data_mark_failed.c - * @brief Implementation of the wire_prepare_data_mark_failed function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/wire_prepare_data_mark_failed.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_wire_prepare_data_mark_failed ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t rowid) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&rowid), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "wire_prepare_data_mark_failed", - "UPDATE prewire" - " SET failed=TRUE" - " WHERE prewire_uuid=$1;"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "wire_prepare_data_mark_failed", - params); -} diff --git a/src/exchangedb/pg_wire_prepare_data_mark_finished.c b/src/exchangedb/pg_wire_prepare_data_mark_finished.c @@ -1,43 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 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/> - */ -/** - * @file exchangedb/pg_wire_prepare_data_mark_finished.c - * @brief Implementation of the wire_prepare_data_mark_finished function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "taler/exchange-database/wire_prepare_data_mark_finished.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_wire_prepare_data_mark_finished ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - uint64_t rowid) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&rowid), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "wire_prepare_data_mark_done", - "UPDATE prewire" - " SET finished=TRUE" - " WHERE prewire_uuid=$1;"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "wire_prepare_data_mark_done", - params); -} diff --git a/src/exchangedb/preflight.c b/src/exchangedb/preflight.c @@ -0,0 +1,111 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/preflight.c + * @brief Implementation of the preflight function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/preflight.h" +#include "helper.h" + + +static enum GNUNET_GenericReturnValue +internal_setup (struct TALER_EXCHANGEDB_PostgresContext *pg) +{ + if (NULL == pg->conn) + { +#if AUTO_EXPLAIN + /* Enable verbose logging to see where queries do not + properly use indices */ + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_try_execute ("LOAD 'auto_explain';"), + GNUNET_PQ_make_try_execute ("SET auto_explain.log_min_duration=50;"), + GNUNET_PQ_make_try_execute ("SET auto_explain.log_timing=TRUE;"), + GNUNET_PQ_make_try_execute ("SET auto_explain.log_analyze=TRUE;"), + /* https://wiki.postgresql.org/wiki/Serializable suggests to really + force the default to 'serializable' if SSI is to be used. */ + GNUNET_PQ_make_try_execute ( + "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"), + GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"), + GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"), + GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), + /* Mergejoin causes issues, see Postgres #18380 */ + GNUNET_PQ_make_try_execute ("SET enable_mergejoin=OFF;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; +#else + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_try_execute ( + "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"), + GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"), + GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"), + /* Mergejoin causes issues, see Postgres #18380 */ + GNUNET_PQ_make_try_execute ("SET enable_mergejoin=OFF;"), + GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; +#endif + struct GNUNET_PQ_Context *db_conn; + + db_conn = GNUNET_PQ_connect_with_cfg2 (pg->cfg, + "exchangedb-postgres", + "exchange-", /* load_path_suffix */ + es, + NULL /* prepared statements */, + GNUNET_PQ_FLAG_CHECK_CURRENT); + if (NULL == db_conn) + return GNUNET_SYSERR; + + pg->prep_gen++; + pg->conn = db_conn; + } + if (NULL == pg->transaction_name) + GNUNET_PQ_reconnect_if_down (pg->conn); + return GNUNET_OK; +} + + +enum GNUNET_GenericReturnValue +TALER_EXCHANGEDB_preflight (struct TALER_EXCHANGEDB_PostgresContext *pg) +{ + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_execute ("ROLLBACK"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + if (GNUNET_OK != + internal_setup (pg)) + return GNUNET_SYSERR; + if (NULL == pg->transaction_name) + return GNUNET_OK; /* all good */ + if (GNUNET_OK == + GNUNET_PQ_exec_statements (pg->conn, + es)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "BUG: Preflight check rolled back transaction `%s'!\n", + pg->transaction_name); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "BUG: Preflight check failed to rollback transaction `%s'!\n", + pg->transaction_name); + } + pg->transaction_name = NULL; + return GNUNET_NO; +} diff --git a/src/exchangedb/profit_drains_get_pending.c b/src/exchangedb/profit_drains_get_pending.c @@ -0,0 +1,75 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/profit_drains_get_pending.c + * @brief Implementation of the profit_drains_get_pending function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/profit_drains_get_pending.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_profit_drains_get_pending ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t *serial, + struct TALER_WireTransferIdentifierRawP *wtid, + char **account_section, + struct TALER_FullPayto *payto_uri, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *amount, + struct TALER_MasterSignatureP *master_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("profit_drain_serial_id", + serial), + GNUNET_PQ_result_spec_auto_from_type ("wtid", + wtid), + GNUNET_PQ_result_spec_string ("account_section", + account_section), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri->full_payto), + GNUNET_PQ_result_spec_timestamp ("trigger_date", + request_timestamp), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + amount), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), + GNUNET_PQ_result_spec_end + }; + /* Used in #postgres_profit_drains_get_pending() */ + PREPARE (pg, + "get_ready_profit_drain", + "SELECT" + " profit_drain_serial_id" + ",wtid" + ",account_section" + ",payto_uri" + ",trigger_date" + ",amount" + ",master_sig" + " FROM profit_drains" + " WHERE NOT executed" + " ORDER BY trigger_date ASC;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "get_ready_profit_drain", + params, + rs); +} diff --git a/src/exchangedb/profit_drains_set_finished.c b/src/exchangedb/profit_drains_set_finished.c @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/profit_drains_set_finished.c + * @brief Implementation of the profit_drains_set_finished function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/profit_drains_set_finished.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_profit_drains_set_finished ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "drain_profit_set_finished", + "UPDATE profit_drains" + " SET" + " executed=TRUE" + " WHERE profit_drain_serial_id=$1;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "drain_profit_set_finished", + params); +} diff --git a/src/exchangedb/release_revolving_shard.c b/src/exchangedb/release_revolving_shard.c @@ -0,0 +1,56 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/release_revolving_shard.c + * @brief Implementation of the release_revolving_shard function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/release_revolving_shard.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_release_revolving_shard (struct + TALER_EXCHANGEDB_PostgresContext *pg, + const char *job_name, + uint32_t start_row, + uint32_t end_row) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (job_name), + GNUNET_PQ_query_param_uint32 (&start_row), + GNUNET_PQ_query_param_uint32 (&end_row), + GNUNET_PQ_query_param_end + }; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Releasing revolving shard %s %u-%u\n", + job_name, + (unsigned int) start_row, + (unsigned int) end_row); + + + PREPARE (pg, + "release_revolving_shard", + "UPDATE revolving_work_shards" + " SET active=FALSE" + " WHERE job_name=$1" + " AND start_row=$2" + " AND end_row=$3"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "release_revolving_shard", + params); +} diff --git a/src/exchangedb/reserves_get.c b/src/exchangedb/reserves_get.c @@ -0,0 +1,57 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/reserves_get.c + * @brief Implementation of the reserves_get function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/reserves_get.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_reserves_get (struct TALER_EXCHANGEDB_PostgresContext *pg, + struct TALER_EXCHANGEDB_Reserve *reserve) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&reserve->pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_amount ("current_balance", + pg->currency, + &reserve->balance), + GNUNET_PQ_result_spec_timestamp ("expiration_date", + &reserve->expiry), + GNUNET_PQ_result_spec_timestamp ("gc_date", + &reserve->gc), + GNUNET_PQ_result_spec_end + }; + /* Used in #postgres_reserves_get() */ + PREPARE (pg, + "reserves_get", + "SELECT" + " current_balance" + ",expiration_date" + ",gc_date" + " FROM reserves" + " WHERE reserve_pub=$1" + " LIMIT 1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "reserves_get", + params, + rs); +} diff --git a/src/exchangedb/reserves_get_origin.c b/src/exchangedb/reserves_get_origin.c @@ -0,0 +1,61 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024, 2025 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/> + */ +/** + * @file exchangedb/reserves_get_origin.c + * @brief Implementation of the reserves_get_origin function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/reserves_get_origin.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_reserves_get_origin ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_FullPaytoHashP *h_payto, + struct TALER_FullPayto *payto_uri) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ( + "wire_source_h_payto", + h_payto), + GNUNET_PQ_result_spec_string ( + "payto_uri", + &payto_uri->full_payto), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "get_h_wire_source_of_reserve", + "SELECT" + " rt.wire_source_h_payto" + ",wt.payto_uri" + " FROM reserves_in rt" + " JOIN wire_targets wt" + " ON (rt.wire_source_h_payto = wt.wire_target_h_payto)" + " WHERE rt.reserve_pub=$1"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "get_h_wire_source_of_reserve", + params, + rs); +} diff --git a/src/exchangedb/reserves_in_insert.c b/src/exchangedb/reserves_in_insert.c @@ -0,0 +1,374 @@ +/* + This file is part of TALER + Copyright (C) 2022-2024 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/> + */ +/** + * @file exchangedb/reserves_in_insert.c + * @brief Implementation of the reserves_in_insert function for Postgres + * @author Christian Grothoff + * @author Joseph Xu + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/reserves_in_insert.h" +#include "helper.h" +#include "taler/exchange-database/start.h" +#include "taler/exchange-database/start_read_committed.h" +#include "taler/exchange-database/commit.h" +#include "taler/exchange-database/preflight.h" +#include "taler/exchange-database/rollback.h" + + +/** + * Generate event notification for the reserve change. + * + * @param reserve_pub reserve to notfiy on + * @return string to pass to postgres for the notification + */ +static char * +compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub) +{ + struct TALER_EXCHANGEDB_ReserveEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING), + .reserve_pub = *reserve_pub + }; + + return GNUNET_PQ_get_event_notify_channel (&rep.header); +} + + +/** + * Closure for our helper_cb() + */ +struct Context +{ + /** + * Array of reserve UUIDs to initialize. + */ + uint64_t *reserve_uuids; + + /** + * Array with entries set to 'true' for duplicate transactions. + */ + bool *transaction_duplicates; + + /** + * Array with entries set to 'true' for rows with conflicts. + */ + bool *conflicts; + + /** + * Set to #GNUNET_SYSERR on failures. + */ + enum GNUNET_GenericReturnValue status; + + /** + * Single value (no array) set to true if we need + * to follow-up with an update. + */ + bool needs_update; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct Context *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct Context *ctx = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ( + "transaction_duplicate", + &ctx->transaction_duplicates[i]), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint64 ("ruuid", + &ctx->reserve_uuids[i]), + &ctx->conflicts[i]), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + if (! ctx->transaction_duplicates[i]) + ctx->needs_update |= ctx->conflicts[i]; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_reserves_in_insert ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, + unsigned int reserves_length, + enum GNUNET_DB_QueryStatus *results) +{ + unsigned int dups = 0; + + struct TALER_FullPaytoHashP h_full_paytos[ + GNUNET_NZL (reserves_length)]; + struct TALER_NormalizedPaytoHashP h_normalized_paytos[ + GNUNET_NZL (reserves_length)]; + char *notify_s[GNUNET_NZL (reserves_length)]; + struct TALER_ReservePublicKeyP reserve_pubs[GNUNET_NZL (reserves_length)]; + struct TALER_Amount balances[GNUNET_NZL (reserves_length)]; + struct GNUNET_TIME_Timestamp execution_times[GNUNET_NZL (reserves_length)]; + const char *sender_account_details[GNUNET_NZL (reserves_length)]; + const char *exchange_account_names[GNUNET_NZL (reserves_length)]; + uint64_t wire_references[GNUNET_NZL (reserves_length)]; + uint64_t reserve_uuids[GNUNET_NZL (reserves_length)]; + bool transaction_duplicates[GNUNET_NZL (reserves_length)]; + bool conflicts[GNUNET_NZL (reserves_length)]; + struct GNUNET_TIME_Timestamp reserve_expiration + = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time); + struct GNUNET_TIME_Timestamp gc + = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time); + enum GNUNET_DB_QueryStatus qs; + bool need_update; + + for (unsigned int i = 0; i<reserves_length; i++) + { + const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i]; + + TALER_full_payto_hash (reserve->sender_account_details, + &h_full_paytos[i]); + TALER_full_payto_normalize_and_hash (reserve->sender_account_details, + &h_normalized_paytos[i]); + notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub); + reserve_pubs[i] = *reserve->reserve_pub; + balances[i] = *reserve->balance; + execution_times[i] = reserve->execution_time; + sender_account_details[i] = reserve->sender_account_details.full_payto; + exchange_account_names[i] = reserve->exchange_account_name; + wire_references[i] = reserve->wire_reference; + } + + /* NOTE: kind-of pointless to explicitly start a transaction here... */ + if (GNUNET_OK != + TALER_EXCHANGEDB_preflight (pg)) + { + GNUNET_break (0); + qs = GNUNET_DB_STATUS_HARD_ERROR; + goto finished; + } + if (GNUNET_OK != + TALER_TALER_EXCHANGEDB_start_read_committed (pg, + "READ_COMMITED")) + { + GNUNET_break (0); + qs = GNUNET_DB_STATUS_HARD_ERROR; + goto finished; + } + PREPARE (pg, + "reserves_insert_with_array", + "SELECT" + " transaction_duplicate" + ",ruuid" + " FROM exchange_do_array_reserves_insert" + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);"); + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&gc), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_array_auto_from_type (reserves_length, + reserve_pubs, + pg->conn), + GNUNET_PQ_query_param_array_uint64 (reserves_length, + wire_references, + pg->conn), + TALER_PQ_query_param_array_amount ( + reserves_length, + balances, + pg->conn), + GNUNET_PQ_query_param_array_ptrs_string ( + reserves_length, + (const char **) exchange_account_names, + pg->conn), + GNUNET_PQ_query_param_array_timestamp ( + reserves_length, + execution_times, + pg->conn), + GNUNET_PQ_query_param_array_auto_from_type ( + reserves_length, + h_full_paytos, + pg->conn), + GNUNET_PQ_query_param_array_auto_from_type ( + reserves_length, + h_normalized_paytos, + pg->conn), + GNUNET_PQ_query_param_array_ptrs_string ( + reserves_length, + (const char **) sender_account_details, + pg->conn), + GNUNET_PQ_query_param_array_ptrs_string ( + reserves_length, + (const char **) notify_s, + pg->conn), + GNUNET_PQ_query_param_end + }; + struct Context ctx = { + .reserve_uuids = reserve_uuids, + .transaction_duplicates = transaction_duplicates, + .conflicts = conflicts, + .needs_update = false, + .status = GNUNET_OK + }; + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "reserves_insert_with_array", + params, + &helper_cb, + &ctx); + GNUNET_PQ_cleanup_query_params_closures (params); + if ( (qs < 0) || + (GNUNET_OK != ctx.status) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to insert into reserves (%d)\n", + qs); + goto finished; + } + need_update = ctx.needs_update; + } + + { + enum GNUNET_DB_QueryStatus cs; + + cs = TALER_EXCHANGEDB_commit (pg); + if (cs < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to commit\n"); + qs = cs; + goto finished; + } + } + + for (unsigned int i = 0; i<reserves_length; i++) + { + if (transaction_duplicates[i]) + dups++; + results[i] = transaction_duplicates[i] + ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + + if (! need_update) + { + qs = reserves_length; + goto finished; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Reserve update needed for some reserves in the batch\n"); + PREPARE (pg, + "reserves_update", + "SELECT" + " out_duplicate AS duplicate " + "FROM exchange_do_batch_reserves_update" + " ($1,$2,$3,$4,$5,$6,$7);"); + + if (GNUNET_OK != + TALER_EXCHANGEDB_start (pg, + "reserve-insert-continued")) + { + GNUNET_break (0); + qs = GNUNET_DB_STATUS_HARD_ERROR; + goto finished; + } + + for (unsigned int i = 0; i<reserves_length; i++) + { + if (transaction_duplicates[i]) + continue; + if (! conflicts[i]) + continue; + { + bool duplicate; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&reserve_pubs[i]), + GNUNET_PQ_query_param_timestamp (&reserve_expiration), + GNUNET_PQ_query_param_uint64 (&wire_references[i]), + TALER_PQ_query_param_amount (pg->conn, + &balances[i]), + GNUNET_PQ_query_param_string (exchange_account_names[i]), + GNUNET_PQ_query_param_auto_from_type (&h_full_paytos[i]), + GNUNET_PQ_query_param_string (notify_s[i]), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("duplicate", + &duplicate), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qsi; + + qsi = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "reserves_update", + params, + rs); + if (qsi < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to update reserves (%d)\n", + qsi); + results[i] = qsi; + goto finished; + } + results[i] = duplicate + ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; + } + } + { + enum GNUNET_DB_QueryStatus cs; + + cs = TALER_EXCHANGEDB_commit (pg); + if (cs < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to commit\n"); + qs = cs; + goto finished; + } + } +finished: + for (unsigned int i = 0; i<reserves_length; i++) + GNUNET_free (notify_s[i]); + if (qs < 0) + return qs; + GNUNET_PQ_event_do_poll (pg->conn); + if (0 != dups) + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "%u/%u duplicates among incoming transactions. Try increasing WIREWATCH_IDLE_SLEEP_INTERVAL in the [exchange] configuration section (if this happens a lot).\n", + dups, + reserves_length); + return qs; +} diff --git a/src/exchangedb/reserves_update.c b/src/exchangedb/reserves_update.c @@ -0,0 +1,50 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/reserves_update.c + * @brief Implementation of the reserves_update function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/reserves_update.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_reserves_update (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_EXCHANGEDB_Reserve *reserve + ) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&reserve->expiry), + GNUNET_PQ_query_param_timestamp (&reserve->gc), + TALER_PQ_query_param_amount (pg->conn, + &reserve->balance), + GNUNET_PQ_query_param_auto_from_type (&reserve->pub), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "reserve_update", + "UPDATE reserves" + " SET" + " expiration_date=$1" + ",gc_date=$2" + ",current_balance=$3" + " WHERE reserve_pub=$4;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "reserve_update", + params); +} diff --git a/src/exchangedb/rollback.c b/src/exchangedb/rollback.c @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/rollback.c + * @brief Implementation of the rollback function for Postgres + * @author Christian Grothoff + */ +#include "taler/exchange-database/rollback.h" +#include "helper.h" + + +void +TALER_EXCHANGEDB_rollback (struct TALER_EXCHANGEDB_PostgresContext *pg) +{ + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_execute ("ROLLBACK"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + if (NULL == pg->transaction_name) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Skipping rollback, no transaction active\n"); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Rolling back transaction\n"); + GNUNET_break (GNUNET_OK == + GNUNET_PQ_exec_statements (pg->conn, + es)); + pg->transaction_name = NULL; +} diff --git a/src/exchangedb/select_account_merges_above_serial_id.c b/src/exchangedb/select_account_merges_above_serial_id.c @@ -0,0 +1,188 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file select_account_merges_above_serial_id.c + * @brief Implementation of the select_account_merges_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_account_merges_above_serial_id.h" +#include "helper.h" + + +/** + * Closure for #account_merge_serial_helper_cb(). + */ +struct AccountMergeSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_AccountMergeCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct AccountMergeSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +account_merge_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct AccountMergeSerialContext *dsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PrivateContractHashP h_contract_terms; + struct GNUNET_TIME_Timestamp purse_expiration; + struct TALER_Amount amount; + uint32_t min_age; + uint32_t flags32; + enum TALER_WalletAccountMergeFlags flags; + struct TALER_Amount purse_fee; + struct GNUNET_TIME_Timestamp merge_timestamp; + struct TALER_ReserveSignatureP reserve_sig; + uint64_t rowid; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &amount), + TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", + &purse_fee), + GNUNET_PQ_result_spec_uint32 ("flags", + &flags32), + GNUNET_PQ_result_spec_uint32 ("age_limit", + &min_age), + GNUNET_PQ_result_spec_timestamp ("purse_expiration", + &purse_expiration), + GNUNET_PQ_result_spec_timestamp ("merge_timestamp", + &merge_timestamp), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + &h_contract_terms), + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + &purse_pub), + GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", + &reserve_sig), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + GNUNET_PQ_result_spec_uint64 ("account_merge_request_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + dsc->status = GNUNET_SYSERR; + return; + } + flags = (enum TALER_WalletAccountMergeFlags) flags32; + ret = dsc->cb (dsc->cb_cls, + rowid, + &reserve_pub, + &purse_pub, + &h_contract_terms, + purse_expiration, + &amount, + min_age, + flags, + &purse_fee, + merge_timestamp, + &reserve_sig); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_account_merges_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_AccountMergeCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct AccountMergeSerialContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "audit_get_account_merge_incr", + "SELECT" + " am.account_merge_request_serial_id" + ",am.reserve_pub" + ",am.purse_pub" + ",pr.h_contract_terms" + ",pr.purse_expiration" + ",pr.amount_with_fee" + ",pr.age_limit" + ",pr.flags" + ",pr.purse_fee" + ",pm.merge_timestamp" + ",am.reserve_sig" + " FROM account_merges am" + " JOIN purse_requests pr USING (purse_pub)" + " JOIN purse_merges pm USING (purse_pub)" + " WHERE (" + " (account_merge_request_serial_id>=$1)" + " )" + " ORDER BY account_merge_request_serial_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_account_merge_incr", + params, + &account_merge_serial_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_aggregation_amounts_for_kyc_check.c b/src/exchangedb/select_aggregation_amounts_for_kyc_check.c @@ -0,0 +1,154 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/select_aggregation_amounts_for_kyc_check.c + * @brief Implementation of the select_aggregation_amounts_for_kyc_check function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_aggregation_amounts_for_kyc_check.h" +#include "helper.h" + + +/** + * Closure for #get_kyc_amounts_cb(). + */ +struct KycAmountCheckContext +{ + /** + * Function to call per result. + */ + TALER_KYCLOGIC_KycAmountCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Flag set to #GNUNET_OK as long as everything is fine. + */ + enum GNUNET_GenericReturnValue status; + +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct KycAmountCheckContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_kyc_amounts_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct KycAmountCheckContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + + for (unsigned int i = 0; i < num_results; i++) + { + struct GNUNET_TIME_Absolute date; + struct TALER_Amount amount; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_absolute_time ("date", + &date), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ret = ctx->cb (ctx->cb_cls, + &amount, + date); + GNUNET_PQ_cleanup_result (rs); + switch (ret) + { + case GNUNET_OK: + continue; + case GNUNET_NO: + break; + case GNUNET_SYSERR: + ctx->status = GNUNET_SYSERR; + break; + } + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_aggregation_amounts_for_kyc_check ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_KYCLOGIC_KycAmountCallback kac, + void *kac_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_absolute_time (&time_limit), + GNUNET_PQ_query_param_end + }; + struct KycAmountCheckContext ctx = { + .cb = kac, + .cb_cls = kac_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_kyc_relevant_aggregation_events", + "SELECT" + " amount" + ",execution_date AS date" + " FROM wire_out" + " WHERE wire_target_h_payto IN" + " (SELECT wire_target_h_payto" + " FROM wire_targets" + " WHERE h_normalized_payto=$1" + " )" + " AND execution_date >= $2" + " ORDER BY execution_date DESC"); + + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_kyc_relevant_aggregation_events", + params, + &get_kyc_amounts_cb, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_aggregation_transient.c b/src/exchangedb/select_aggregation_transient.c @@ -0,0 +1,63 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_aggregation_transient.c + * @brief Implementation of the select_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_aggregation_transient.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_aggregation_transient ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_FullPaytoHashP *h_payto, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *exchange_account_section, + struct TALER_WireTransferIdentifierRawP *wtid, + struct TALER_Amount *total) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_string (exchange_account_section), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + total), + GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", + wtid), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "select_aggregation_transient", + "SELECT" + " amount" + " ,wtid_raw" + " FROM aggregation_transient" + " WHERE wire_target_h_payto=$1" + " AND merchant_pub=$2" + " AND exchange_account_section=$3;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_aggregation_transient", + params, + rs); +} diff --git a/src/exchangedb/select_aggregations_above_serial.c b/src/exchangedb/select_aggregations_above_serial.c @@ -0,0 +1,137 @@ +/* + This file is part of TALER + Copyright (C) 2023, 2024 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/> + */ +/** + * @file exchangedb/select_aggregations_above_serial.c + * @brief Implementation of the select_aggregations_above_serial function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_aggregations_above_serial.h" +#include "helper.h" + +/** + * Closure for #aggregation_serial_helper_cb(). + */ +struct AggregationSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_AggregationCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct AggregationSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +aggregation_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct AggregationSerialContext *dsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t tracking_rowid; + uint64_t batch_deposit_serial_id; + struct TALER_Amount amount; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("total_amount", + &amount), + GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", + &tracking_rowid), + GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id", + &batch_deposit_serial_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + dsc->status = GNUNET_SYSERR; + return; + } + dsc->cb (dsc->cb_cls, + &amount, + tracking_rowid, + batch_deposit_serial_id); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_aggregations_above_serial ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t min_tracking_serial_id, + TALER_EXCHANGEDB_AggregationCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&min_tracking_serial_id), + GNUNET_PQ_query_param_end + }; + struct AggregationSerialContext asc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Fetch aggregations with rowid '\geq' the given parameter */ + PREPARE (pg, + "select_aggregations_above_serial", + "SELECT" + " aggregation_serial_id" + ",batch_deposit_serial_id" + ",total_amount" + " FROM exchange_do_select_aggregations_above_serial($1);"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "select_aggregations_above_serial", + params, + &aggregation_serial_helper_cb, + &asc); + if (GNUNET_OK != asc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_all_kyc_attributes.c b/src/exchangedb/select_all_kyc_attributes.c @@ -0,0 +1,168 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/select_all_kyc_attributes.c + * @brief Implementation of the select_all_kyc_attributes function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_all_kyc_attributes.h" +#include "helper.h" + +/** + * Closure for #get_all_attributes_cb(). + */ +struct GetAttributesContext +{ + /** + * Function to call per result. + */ + TALER_EXCHANGEDB_AllAttributesCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Flag set to #GNUNET_OK as long as everything is fine. + */ + enum GNUNET_GenericReturnValue status; + +}; + +/** + * Invoke the callback for each result. + * + * @param cls a `struct GetAttributesContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_attributes_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct GetAttributesContext *ctx = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + uint64_t rowid; + struct GNUNET_TIME_Timestamp collection_time; + struct GNUNET_TIME_Timestamp expiration_time; + struct TALER_NormalizedPaytoHashP h_payto; + json_t *properties = NULL; + size_t enc_attributes_size; + void *enc_attributes; + char *provider; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("provider_name", + &provider), + GNUNET_PQ_result_spec_uint64 ("kyc_attributes_serial_id", + &rowid), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("jproperties", + &properties), + NULL), + GNUNET_PQ_result_spec_timestamp ("collection_time", + &collection_time), + GNUNET_PQ_result_spec_timestamp ("expiration_time", + &expiration_time), + GNUNET_PQ_result_spec_auto_from_type ("h_payto", + &h_payto), + GNUNET_PQ_result_spec_variable_size ("encrypted_attributes", + &enc_attributes, + &enc_attributes_size), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ctx->cb (ctx->cb_cls, + rowid, + &h_payto, + provider, + collection_time, + expiration_time, + properties, + enc_attributes_size, + enc_attributes); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_all_kyc_attributes ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t min_row_id, + TALER_EXCHANGEDB_AllAttributesCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&min_row_id), + GNUNET_PQ_query_param_end + }; + struct GetAttributesContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_all_kyc_attributes", + "SELECT " + " lp.provider_name" + ",ka.h_payto" + ",ka.kyc_attributes_serial_id" + ",lo.jproperties::TEXT" + ",ka.collection_time" + ",ka.expiration_time" + ",ka.encrypted_attributes" + " FROM kyc_attributes ka" + " JOIN legitimization_processes lp" + " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)" + " LEFT JOIN legitimization_outcomes lo" + " ON (ka.h_payto = lo.h_payto)" + /* **IF** we joined with 'lo', the lo must be active */ + " WHERE COALESCE(lo.is_active,TRUE)" + " AND kyc_attributes_serial_id > $1" + " ORDER BY kyc_attributes_serial_id ASC" + ); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_all_kyc_attributes", + params, + &get_attributes_cb, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_all_purse_decisions_above_serial_id.c b/src/exchangedb/select_all_purse_decisions_above_serial_id.c @@ -0,0 +1,142 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file select_all_purse_decisions_above_serial_id.c + * @brief Implementation of the select_all_purse_decisions_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_all_purse_decisions_above_serial_id.h" +#include "helper.h" + + +/** + * Closure for #all_purse_decision_serial_helper_cb(). + */ +struct AllPurseDecisionSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_AllPurseDecisionCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct PurseRefundSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +all_purse_decision_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct AllPurseDecisionSerialContext *dsc = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_PurseContractPublicKeyP purse_pub; + bool refunded; + uint64_t rowid; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + &purse_pub), + GNUNET_PQ_result_spec_bool ("refunded", + &refunded), + GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + dsc->status = GNUNET_SYSERR; + return; + } + ret = dsc->cb (dsc->cb_cls, + rowid, + &purse_pub, + refunded); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_all_purse_decisions_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_AllPurseDecisionCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct AllPurseDecisionSerialContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "audit_select_all_purse_decisions_above_serial_id", + "SELECT" + " purse_pub" + ",refunded" + ",purse_decision_serial_id" + " FROM purse_decision" + " WHERE purse_decision_serial_id>=$1" + " ORDER BY purse_decision_serial_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "audit_select_all_purse_decisions_above_serial_id", + params, + &all_purse_decision_serial_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_all_purse_deletions_above_serial_id.c b/src/exchangedb/select_all_purse_deletions_above_serial_id.c @@ -0,0 +1,142 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/select_all_purse_deletions_above_serial_id.c + * @brief Implementation of the select_all_purse_deletions_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_all_purse_deletions_above_serial_id.h" +#include "helper.h" + + +/** + * Closure for #all_purse_deletion_serial_helper_cb(). + */ +struct AllPurseDeletionSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_AllPurseDeletionsCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct PurseRefundSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +all_purse_deletion_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct AllPurseDeletionSerialContext *dsc = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PurseContractSignatureP purse_sig; + uint64_t rowid; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + &purse_pub), + GNUNET_PQ_result_spec_auto_from_type ("purse_sig", + &purse_sig), + GNUNET_PQ_result_spec_uint64 ("purse_deletion_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + dsc->status = GNUNET_SYSERR; + return; + } + ret = dsc->cb (dsc->cb_cls, + rowid, + &purse_pub, + &purse_sig); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_all_purse_deletions_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_AllPurseDeletionsCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct AllPurseDeletionSerialContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "audit_select_all_purse_deletions_above_serial_id", + "SELECT" + " purse_pub" + ",purse_sig" + ",purse_deletion_serial_id" + " FROM purse_deletion" + " WHERE purse_deletion_serial_id>=$1" + " ORDER BY purse_deletion_serial_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "audit_select_all_purse_deletions_above_serial_id", + params, + &all_purse_deletion_serial_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_aml_attributes.c b/src/exchangedb/select_aml_attributes.c @@ -0,0 +1,189 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/select_aml_attributes.c + * @brief Implementation of the select_aml_attributes function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_aml_attributes.h" +#include "helper.h" + + +/** + * Closure for #handle_aml_result. + */ +struct AmlAttributeResultContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_AmlAttributeCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on serious errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. Helper function + * for #TALER_EXCHANGEDB_select_aml_attributes(). + * + * @param cls closure of type `struct AmlAttributeResultContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +handle_aml_attributes (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct AmlAttributeResultContext *ctx = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + struct GNUNET_TIME_Timestamp collection_time; + char *officer_name = NULL; + bool by_aml_officer; + size_t enc_attributes_size; + void *enc_attributes; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("kyc_attributes_serial_id", + &rowid), + GNUNET_PQ_result_spec_timestamp ("collection_time", + &collection_time), + GNUNET_PQ_result_spec_bool ("by_aml_officer", + &by_aml_officer), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("decider_name", + &officer_name), + NULL), + GNUNET_PQ_result_spec_variable_size ("encrypted_attributes", + &enc_attributes, + &enc_attributes_size), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + + ctx->cb (ctx->cb_cls, + rowid, + collection_time, + by_aml_officer, + officer_name, + enc_attributes_size, + enc_attributes); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_aml_attributes ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + uint64_t offset, + int64_t limit, + TALER_EXCHANGEDB_AmlAttributeCallback cb, + void *cb_cls) +{ + uint64_t ulimit = (limit > 0) ? limit : -limit; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&ulimit), + GNUNET_PQ_query_param_end + }; + struct AmlAttributeResultContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + const char *stmt = (limit > 0) + ? "select_aml_attributes_inc" + : "select_aml_attributes_dec"; + + PREPARE (pg, + "select_aml_attributes_inc", + "SELECT" + " ka.kyc_attributes_serial_id" + ",ka.collection_time" + ",ka.by_aml_officer" + ",astaff.decider_name" + ",ka.encrypted_attributes" + " FROM kyc_attributes ka" + " LEFT JOIN legitimization_processes lp" + " ON (ka.by_aml_officer AND" + " (ka.legitimization_serial = lp.legitimization_process_serial_id))" + " LEFT JOIN aml_staff astaff" + " ON (ka.by_aml_officer AND" + " (DECODE(lp.provider_user_id, 'base64') = astaff.decider_pub))" + " WHERE ka.h_payto=$1" + " AND ka.kyc_attributes_serial_id > $2" + " ORDER BY ka.kyc_attributes_serial_id ASC" + " LIMIT $3"); + PREPARE (pg, + "select_aml_attributes_dec", + "SELECT" + " ka.kyc_attributes_serial_id" + ",ka.collection_time" + ",ka.by_aml_officer" + ",astaff.decider_name" + ",ka.encrypted_attributes" + " FROM kyc_attributes ka" + " LEFT JOIN legitimization_processes lp" + " ON (ka.by_aml_officer AND" + " (ka.legitimization_serial = lp.legitimization_process_serial_id))" + " LEFT JOIN aml_staff astaff" + " ON (ka.by_aml_officer AND" + " (DECODE(lp.provider_user_id, 'base64') = astaff.decider_pub))" + " WHERE ka.h_payto=$1" + " AND ka.kyc_attributes_serial_id < $2" + " ORDER BY ka.kyc_attributes_serial_id DESC" + " LIMIT $3"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + stmt, + params, + &handle_aml_attributes, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_aml_decisions.c b/src/exchangedb/select_aml_decisions.c @@ -0,0 +1,248 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/select_aml_decisions.c + * @brief Implementation of the select_aml_decisions function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_aml_decisions.h" +#include "helper.h" + + +/** + * Closure for #handle_aml_result. + */ +struct AmlProcessResultContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_AmlDecisionCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on serious errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. Helper function + * for #TALER_EXCHANGEDB_select_aml_decisions(). + * + * @param cls closure of type `struct AmlProcessResultContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +handle_aml_result (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct AmlProcessResultContext *ctx = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_NormalizedPaytoHashP h_payto; + uint64_t rowid; + char *justification = NULL; + struct GNUNET_TIME_Timestamp decision_time; + struct GNUNET_TIME_Absolute expiration_time; + json_t *jproperties = NULL; + bool is_wallet; + bool to_investigate; + bool is_active; + json_t *account_rules; + struct TALER_FullPayto payto; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("outcome_serial_id", + &rowid), + GNUNET_PQ_result_spec_auto_from_type ("h_payto", + &h_payto), + GNUNET_PQ_result_spec_bool ("is_wallet", + &is_wallet), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("justification", + &justification), + NULL), + GNUNET_PQ_result_spec_timestamp ("decision_time", + &decision_time), + GNUNET_PQ_result_spec_absolute_time ("expiration_time", + &expiration_time), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("jproperties", + &jproperties), + NULL), + TALER_PQ_result_spec_json ("jnew_rules", + &account_rules), + GNUNET_PQ_result_spec_bool ("to_investigate", + &to_investigate), + GNUNET_PQ_result_spec_bool ("is_active", + &is_active), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto.full_payto), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + if (GNUNET_TIME_absolute_is_past (expiration_time)) + is_active = false; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Returning AML decisions for `%s' (%s)\n", + TALER_B2S (&h_payto), + is_wallet + ? "wallet" + : "account"); + ctx->cb (ctx->cb_cls, + rowid, + justification, + &h_payto, + decision_time, + expiration_time, + jproperties, + to_investigate, + is_active, + is_wallet, + payto, + account_rules); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_aml_decisions ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + enum TALER_EXCHANGE_YesNoAll investigation_only, + enum TALER_EXCHANGE_YesNoAll active_only, + uint64_t offset, + int64_t limit, + TALER_EXCHANGEDB_AmlDecisionCallback cb, + void *cb_cls) +{ + uint64_t ulimit = (limit > 0) ? limit : -limit; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_bool (NULL == h_payto), + NULL == h_payto + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == + investigation_only)), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == + investigation_only)), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == + active_only)), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == + active_only)), + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&ulimit), + GNUNET_PQ_query_param_end + }; + struct AmlProcessResultContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + const char *stmt = (limit > 0) + ? "select_aml_decisions_inc" + : "select_aml_decisions_dec"; + + PREPARE (pg, + "select_aml_decisions_inc", + "SELECT" + " lo.outcome_serial_id" + ",lo.h_payto" + ",ah.justification" + ",lo.decision_time" + ",lo.expiration_time" + ",lo.jproperties::TEXT" + ",lo.to_investigate" + ",lo.is_active" + ",lo.jnew_rules::TEXT" + ",kt.is_wallet" + ",wt.payto_uri" + " FROM legitimization_outcomes lo" + " JOIN kyc_targets kt" + " ON (lo.h_payto = kt.h_normalized_payto)" + " JOIN wire_targets wt" + " ON (lo.h_payto = wt.h_normalized_payto)" + " LEFT JOIN aml_history ah" + " USING (outcome_serial_id)" + " WHERE (outcome_serial_id > $7)" + " AND ($1 OR (lo.h_payto = $2))" + " AND ($3 OR (lo.to_investigate = $4))" + " AND ($5 OR (lo.is_active = $6))" + " ORDER BY lo.outcome_serial_id ASC" + " LIMIT $8"); + PREPARE (pg, + "select_aml_decisions_dec", + "SELECT" + " lo.outcome_serial_id" + ",lo.h_payto" + ",ah.justification" + ",lo.decision_time" + ",lo.expiration_time" + ",lo.jproperties::TEXT" + ",lo.to_investigate" + ",lo.is_active" + ",lo.jnew_rules::TEXT" + ",kt.is_wallet" + ",wt.payto_uri" + " FROM legitimization_outcomes lo" + " JOIN kyc_targets kt" + " ON (lo.h_payto = kt.h_normalized_payto)" + " JOIN wire_targets wt" + " ON (lo.h_payto = wt.h_normalized_payto)" + " LEFT JOIN aml_history ah" + " USING (outcome_serial_id)" + " WHERE lo.outcome_serial_id < $7" + " AND ($1 OR (lo.h_payto = $2))" + " AND ($3 OR (lo.to_investigate = $4))" + " AND ($5 OR (lo.is_active = $6))" + " ORDER BY lo.outcome_serial_id DESC" + " LIMIT $8"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + stmt, + params, + &handle_aml_result, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_aml_measures.c b/src/exchangedb/select_aml_measures.c @@ -0,0 +1,185 @@ +/* + This file is part of TALER + Copyright (C) 2024, 2025 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/> + */ +/** + * @file exchangedb/select_aml_measures.c + * @brief Implementation of the select_aml_measures function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_aml_measures.h" +#include "helper.h" + + +/** + * Closure for #handle_aml_result. + */ +struct LegiMeasureResultContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_LegitimizationMeasureCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on serious errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. Helper function + * for #TALER_EXCHANGEDB_select_aml_measures(). + * + * @param cls closure of type `struct LegiMeasureResultContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +handle_aml_result (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LegiMeasureResultContext *ctx = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_NormalizedPaytoHashP h_payto; + uint64_t rowid; + struct GNUNET_TIME_Absolute start_time; + json_t *jmeasures; + bool is_finished; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("legitimization_measure_serial_id", + &rowid), + GNUNET_PQ_result_spec_auto_from_type ("h_normalized_payto", + &h_payto), + GNUNET_PQ_result_spec_absolute_time ("start_time", + &start_time), + TALER_PQ_result_spec_json ("jmeasures", + &jmeasures), + GNUNET_PQ_result_spec_bool ("is_finished", + &is_finished), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ctx->cb (ctx->cb_cls, + &h_payto, + start_time, + jmeasures, + is_finished, + rowid); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_aml_measures ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + enum TALER_EXCHANGE_YesNoAll active_only, + uint64_t offset, + int64_t limit, + TALER_EXCHANGEDB_LegitimizationMeasureCallback cb, + void *cb_cls) +{ + uint64_t ulimit = (limit > 0) ? limit : -limit; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_bool (NULL == h_payto), + NULL == h_payto + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == + active_only)), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_NO == + active_only)), + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&ulimit), + GNUNET_PQ_query_param_end + }; + struct LegiMeasureResultContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + const char *stmt = (limit > 0) + ? "select_aml_measures_inc" + : "select_aml_measures_dec"; + + PREPARE (pg, + "select_aml_measures_inc", + "SELECT" + " lm.legitimization_measure_serial_id" + ",kt.h_normalized_payto" + ",lm.jmeasures::TEXT" + ",lm.start_time" + ",lm.is_finished" + " FROM kyc_targets kt" + " JOIN legitimization_measures lm" + " USING (access_token)" + " WHERE (legitimization_measure_serial_id > $5)" + " AND ($1 OR (kt.h_normalized_payto = $2))" + " AND ($3 OR (lm.is_finished = $4))" + " ORDER BY lm.legitimization_measure_serial_id ASC" + " LIMIT $6"); + PREPARE (pg, + "select_aml_measures_dec", + "SELECT" + " lm.legitimization_measure_serial_id" + ",kt.h_normalized_payto" + ",lm.jmeasures::TEXT" + ",lm.start_time" + ",lm.is_finished" + " FROM kyc_targets kt" + " JOIN legitimization_measures lm" + " USING (access_token)" + " WHERE (legitimization_measure_serial_id < $5)" + " AND ($1 OR (kt.h_normalized_payto = $2))" + " AND ($3 OR (lm.is_finished = $4))" + " ORDER BY lm.legitimization_measure_serial_id DESC" + " LIMIT $6"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + stmt, + params, + &handle_aml_result, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_aml_statistics.c b/src/exchangedb/select_aml_statistics.c @@ -0,0 +1,142 @@ +/* + This file is part of TALER + Copyright (C) 2024, 2025 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/> + */ +/** + * @file exchangedb/select_aml_statistics.c + * @brief Implementation of the select_aml_statistics function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_aml_statistics.h" +#include "helper.h" + + +/** + * Closure for #get_statistics_cb(). + */ +struct GetStatisticsContext +{ + /** + * Function to call per result. + */ + TALER_EXCHANGEDB_AmlStatisticsCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Flag set to #GNUNET_OK as long as everything is fine. + */ + enum GNUNET_GenericReturnValue status; + +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct GetStatisticsContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_statistics_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct GetStatisticsContext *ctx = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + uint64_t val; + char *name; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("name", + &name), + GNUNET_PQ_result_spec_uint64 ("value", + &val), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ctx->cb (ctx->cb_cls, + name, + val); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_aml_statistics ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + size_t num_names, + const char *names[static num_names], + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + TALER_EXCHANGEDB_AmlStatisticsCallback cb, + void *cb_cls) +{ + struct GetStatisticsContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_array_ptrs_string (num_names, + names, + pg->conn), + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_timestamp (&end_date), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_aml_statistics", + "SELECT " + " event_type AS name" + ",COUNT(*) AS value" + " FROM kyc_events" + " WHERE event_type = ANY ($1)" + " AND event_timestamp >= $2" + " AND event_timestamp < $3" + " GROUP BY event_type;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "select_aml_statistics", + params, + &get_statistics_cb, + &ctx); + GNUNET_PQ_cleanup_query_params_closures (params); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_auditor_denom_sig.c b/src/exchangedb/select_auditor_denom_sig.c @@ -0,0 +1,62 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_auditor_denom_sig.c + * @brief Implementation of the select_auditor_denom_sig function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_auditor_denom_sig.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_auditor_denom_sig ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct TALER_AuditorSignatureP *auditor_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (auditor_pub), + GNUNET_PQ_query_param_auto_from_type (h_denom_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("auditor_sig", + auditor_sig), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "select_auditor_denom_sig", + "SELECT" + " auditor_sig" + " FROM auditor_denom_sigs" + " WHERE auditor_uuid=" + " (SELECT auditor_uuid" + " FROM auditors" + " WHERE auditor_pub=$1)" + " AND denominations_serial=" + " (SELECT denominations_serial" + " FROM denominations" + " WHERE denom_pub_hash=$2);"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_auditor_denom_sig", + params, + rs); +} diff --git a/src/exchangedb/select_batch_deposits_missing_wire.c b/src/exchangedb/select_batch_deposits_missing_wire.c @@ -0,0 +1,140 @@ +/* + This file is part of TALER + Copyright (C) 2022-2023 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/> + */ +/** + * @file exchangedb/select_batch_deposits_missing_wire.c + * @brief Implementation of the select_batch_deposits_missing_wire function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_batch_deposits_missing_wire.h" +#include "helper.h" + +/** + * Closure for #missing_wire_cb(). + */ +struct MissingWireContext +{ + /** + * Function to call per result. + */ + TALER_EXCHANGEDB_WireMissingCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on error. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct MissingWireContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +missing_wire_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct MissingWireContext *mwc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = mwc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t batch_deposit_serial_id; + struct GNUNET_TIME_Timestamp deadline; + struct TALER_FullPaytoHashP wire_target_h_payto; + struct TALER_Amount total_amount; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id", + &batch_deposit_serial_id), + GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto", + &wire_target_h_payto), + GNUNET_PQ_result_spec_timestamp ("deadline", + &deadline), + TALER_PQ_RESULT_SPEC_AMOUNT ("total_amount", + &total_amount), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + mwc->status = GNUNET_SYSERR; + return; + } + mwc->cb (mwc->cb_cls, + batch_deposit_serial_id, + &total_amount, + &wire_target_h_payto, + deadline); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_batch_deposits_missing_wire ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t min_batch_deposit_serial_id, + TALER_EXCHANGEDB_WireMissingCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&min_batch_deposit_serial_id), + GNUNET_PQ_query_param_end + }; + struct MissingWireContext mwc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "deposits_get_deposits_missing_wire", + "SELECT" + " batch_deposit_serial_id" + ",wire_target_h_payto" + ",deadline" + ",total_amount" + " FROM exchange_do_select_deposits_missing_wire" + " ($1);"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "deposits_get_deposits_missing_wire", + params, + &missing_wire_cb, + &mwc); + if (GNUNET_OK != mwc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_coin_deposits_above_serial_id.c b/src/exchangedb/select_coin_deposits_above_serial_id.c @@ -0,0 +1,200 @@ +/* + This file is part of TALER + Copyright (C) 2022-2023 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/> + */ +/** + * @file exchangedb/select_coin_deposits_above_serial_id.c + * @brief Implementation of the select_coin_deposits_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_coin_deposits_above_serial_id.h" +#include "helper.h" + +/** + * Closure for #deposit_serial_helper_cb(). + */ +struct CoinDepositSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_DepositCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct CoinDepositSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +coin_deposit_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct CoinDepositSerialContext *dsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_Deposit deposit; + struct GNUNET_TIME_Timestamp exchange_timestamp; + struct TALER_DenominationPublicKey denom_pub; + bool done; + uint64_t rowid; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &deposit.amount_with_fee), + GNUNET_PQ_result_spec_timestamp ("wallet_timestamp", + &deposit.timestamp), + GNUNET_PQ_result_spec_timestamp ("exchange_timestamp", + &exchange_timestamp), + GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", + &deposit.merchant_pub), + TALER_PQ_result_spec_denom_pub ("denom_pub", + &denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &deposit.coin.coin_pub), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &deposit.coin.h_age_commitment), + &deposit.coin.no_age_commitment), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("wallet_data_hash", + &deposit.wallet_data_hash), + &deposit.no_wallet_data_hash), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &deposit.csig), + GNUNET_PQ_result_spec_timestamp ("refund_deadline", + &deposit.refund_deadline), + GNUNET_PQ_result_spec_timestamp ("wire_deadline", + &deposit.wire_deadline), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + &deposit.h_contract_terms), + GNUNET_PQ_result_spec_auto_from_type ("wire_salt", + &deposit.wire_salt), + GNUNET_PQ_result_spec_string ("receiver_wire_account", + &deposit.receiver_wire_account.full_payto), + GNUNET_PQ_result_spec_bool ("done", + &done), + GNUNET_PQ_result_spec_uint64 ("coin_deposit_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + memset (&deposit, + 0, + sizeof (deposit)); + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + dsc->status = GNUNET_SYSERR; + return; + } + ret = dsc->cb (dsc->cb_cls, + rowid, + exchange_timestamp, + &deposit, + &denom_pub, + done); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_coin_deposits_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_DepositCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct CoinDepositSerialContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Fetch deposits with rowid '\geq' the given parameter */ + PREPARE (pg, + "audit_get_coin_deposits_incr", + "SELECT" + " cdep.amount_with_fee" + ",bdep.wallet_timestamp" + ",bdep.exchange_timestamp" + ",bdep.merchant_pub" + ",bdep.wallet_data_hash" + ",denom.denom_pub" + ",kc.coin_pub" + ",kc.age_commitment_hash" + ",cdep.coin_sig" + ",bdep.refund_deadline" + ",bdep.wire_deadline" + ",bdep.h_contract_terms" + ",bdep.wire_salt" + ",wt.payto_uri AS receiver_wire_account" + ",bdep.done" + ",cdep.coin_deposit_serial_id" + " FROM coin_deposits cdep" + " JOIN batch_deposits bdep" + " USING (batch_deposit_serial_id)" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " JOIN known_coins kc" + " USING (coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " WHERE (coin_deposit_serial_id>=$1)" + " ORDER BY coin_deposit_serial_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_coin_deposits_incr", + params, + &coin_deposit_serial_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_contract.c b/src/exchangedb/select_contract.c @@ -0,0 +1,65 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_contract.c + * @brief Implementation of the select_contract function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_contract.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_contract (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ContractDiffiePublicP * + pub_ckey, + struct TALER_PurseContractPublicKeyP * + purse_pub, + struct TALER_PurseContractSignatureP * + econtract_sig, + size_t *econtract_size, + void **econtract) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (pub_ckey), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + purse_pub), + GNUNET_PQ_result_spec_auto_from_type ("contract_sig", + econtract_sig), + GNUNET_PQ_result_spec_variable_size ("e_contract", + econtract, + econtract_size), + GNUNET_PQ_result_spec_end + }; + + /* Used in #postgres_select_contract */ + PREPARE (pg, + "select_contract", + "SELECT " + " purse_pub" + ",e_contract" + ",contract_sig" + " FROM contracts" + " WHERE pub_ckey=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_contract", + params, + rs); + +} diff --git a/src/exchangedb/select_contract_by_purse.c b/src/exchangedb/select_contract_by_purse.c @@ -0,0 +1,59 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_contract_by_purse.c + * @brief Implementation of the select_contract_by_purse function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_contract_by_purse.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_select_contract_by_purse ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_EncryptedContract *econtract) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("pub_ckey", + &econtract->contract_pub), + GNUNET_PQ_result_spec_auto_from_type ("contract_sig", + &econtract->econtract_sig), + GNUNET_PQ_result_spec_variable_size ("e_contract", + &econtract->econtract, + &econtract->econtract_size), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "select_contract_by_purse", + "SELECT " + " pub_ckey" + ",e_contract" + ",contract_sig" + " FROM contracts" + " WHERE purse_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_contract_by_purse", + params, + rs); + +} diff --git a/src/exchangedb/select_deposit_amounts_for_kyc_check.c b/src/exchangedb/select_deposit_amounts_for_kyc_check.c @@ -0,0 +1,153 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/select_deposit_amounts_for_kyc_check.c + * @brief Implementation of the select_deposit_amounts_for_kyc_check function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_deposit_amounts_for_kyc_check.h" +#include "helper.h" + +/** + * Closure for #get_kyc_amounts_cb(). + */ +struct KycAmountCheckContext +{ + /** + * Function to call per result. + */ + TALER_KYCLOGIC_KycAmountCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Flag set to #GNUNET_OK as long as everything is fine. + */ + enum GNUNET_GenericReturnValue status; + +}; + +/** + * Invoke the callback for each result. + * + * @param cls a `struct KycAmountCheckContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_kyc_amounts_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct KycAmountCheckContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + + for (unsigned int i = 0; i < num_results; i++) + { + struct GNUNET_TIME_Absolute date; + struct TALER_Amount amount; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_absolute_time ("date", + &date), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ret = ctx->cb (ctx->cb_cls, + &amount, + date); + GNUNET_PQ_cleanup_result (rs); + switch (ret) + { + case GNUNET_OK: + continue; + case GNUNET_NO: + break; + case GNUNET_SYSERR: + ctx->status = GNUNET_SYSERR; + break; + } + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_deposit_amounts_for_kyc_check ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_KYCLOGIC_KycAmountCallback kac, + void *kac_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_absolute_time (&time_limit), + GNUNET_PQ_query_param_end + }; + struct KycAmountCheckContext ctx = { + .cb = kac, + .cb_cls = kac_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_kyc_relevant_deposit_events", + "SELECT" + " cd.amount_with_fee AS amount" + ",bd.exchange_timestamp AS date" + " FROM batch_deposits bd" + " JOIN coin_deposits cd" + " USING (batch_deposit_serial_id)" + " WHERE wire_target_h_payto IN (" + " SELECT wire_target_h_payto" + " FROM wire_targets" + " WHERE h_normalized_payto=$1" + " )" + " AND bd.exchange_timestamp >= $2" + " ORDER BY bd.exchange_timestamp DESC"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_kyc_relevant_deposit_events", + params, + &get_kyc_amounts_cb, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_exchange_credit_transfers.c b/src/exchangedb/select_exchange_credit_transfers.c @@ -0,0 +1,180 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/select_exchange_credit_transfers.c + * @brief Implementation of the select_exchange_credit_transfers function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_exchange_credit_transfers.h" +#include "helper.h" + +/** + * Closure for #handle_aml_result. + */ +struct SelectTransferContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_AmlTransferCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on serious errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. Helper function + * for #TALER_EXCHANGEDB_select_exchange_debit_transfers(). + * + * @param cls closure of type `struct SelectTransferContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +handle_transfer_result (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct SelectTransferContext *stc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + char *payto_uri; + uint64_t rowid; + struct GNUNET_TIME_Absolute execution_time; + struct TALER_Amount amount; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial_id", + &rowid), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri), + GNUNET_PQ_result_spec_absolute_time ("execution_time", + &execution_time), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + stc->status = GNUNET_SYSERR; + return; + } + stc->cb (stc->cb_cls, + rowid, + payto_uri, + execution_time, + &amount); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_exchange_credit_transfers ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_Amount *threshold, + uint64_t offset, + int64_t limit, + const struct TALER_NormalizedPaytoHashP *h_payto, + TALER_EXCHANGEDB_AmlTransferCallback cb, + void *cb_cls) +{ + struct SelectTransferContext stc = { + .pg = pg, + .cb = cb, + .cb_cls = cb_cls, + .status = GNUNET_OK + }; + uint64_t ulimit = (limit > 0) ? limit : -limit; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&ulimit), + TALER_PQ_query_param_amount (pg->conn, + threshold), + NULL != h_payto + ? GNUNET_PQ_query_param_auto_from_type (h_payto) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_exchange_credit_transfers_inc", + "SELECT" + " ri.reserve_in_serial_id AS serial_id" + ",wt.payto_uri" + ",ri.execution_date AS execution_time" + ",ri.credit AS amount" + " FROM reserves_in ri" + " LEFT JOIN wire_targets wt" + " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)" + " WHERE (ri.reserve_in_serial_id > $1)" + " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" + " AND ( ( (ri.credit).val > ($3::taler_amount).val)" + " OR ( ( (ri.credit).val >= ($3::taler_amount).val)" + " AND ( (ri.credit).frac >= ($3::taler_amount).frac) ) )" + " ORDER BY ri.reserve_in_serial_id ASC" + " LIMIT $2"); + PREPARE (pg, + "select_exchange_credit_transfers_dec", + "SELECT" + " ri.reserve_in_serial_id AS serial_id" + ",wt.payto_uri" + ",ri.execution_date AS execution_time" + ",ri.credit AS amount" + " FROM reserves_in ri" + " LEFT JOIN wire_targets wt" + " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)" + " WHERE (ri.reserve_in_serial_id < $1)" + " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" + " AND ( ( (ri.credit).val > ($3::taler_amount).val)" + " OR ( ( (ri.credit).val >= ($3::taler_amount).val)" + " AND ( (ri.credit).frac >= ($3::taler_amount).frac) ) )" + " ORDER BY ri.reserve_in_serial_id DESC" + " LIMIT $2"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + (limit > 0) + ? "select_exchange_credit_transfers_inc" + : "select_exchange_credit_transfers_dec", + params, + &handle_transfer_result, + &stc); + if (GNUNET_OK != stc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_exchange_debit_transfers.c b/src/exchangedb/select_exchange_debit_transfers.c @@ -0,0 +1,181 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/select_exchange_debit_transfers.c + * @brief Implementation of the select_exchange_debit_transfers function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_exchange_debit_transfers.h" +#include "helper.h" + + +/** + * Closure for #handle_aml_result. + */ +struct SelectTransferContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_AmlTransferCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on serious errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. Helper function + * for #TALER_EXCHANGEDB_select_exchange_debit_transfers(). + * + * @param cls closure of type `struct SelectTransferContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +handle_transfer_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct SelectTransferContext *stc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + char *payto_uri; + uint64_t rowid; + struct GNUNET_TIME_Absolute execution_time; + struct TALER_Amount amount; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial_id", + &rowid), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri), + GNUNET_PQ_result_spec_absolute_time ("execution_time", + &execution_time), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + stc->status = GNUNET_SYSERR; + return; + } + stc->cb (stc->cb_cls, + rowid, + payto_uri, + execution_time, + &amount); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_exchange_debit_transfers ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_Amount *threshold, + uint64_t offset, + int64_t limit, + const struct TALER_NormalizedPaytoHashP *h_payto, + TALER_EXCHANGEDB_AmlTransferCallback cb, + void *cb_cls) +{ + struct SelectTransferContext stc = { + .pg = pg, + .cb = cb, + .cb_cls = cb_cls, + .status = GNUNET_OK + }; + uint64_t ulimit = (limit > 0) ? limit : -limit; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&ulimit), + TALER_PQ_query_param_amount (pg->conn, + threshold), + NULL != h_payto + ? GNUNET_PQ_query_param_auto_from_type (h_payto) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_exchange_debit_transfers_inc", + "SELECT" + " wo.wireout_uuid AS serial_id" + ",wt.payto_uri" + ",wo.execution_date AS execution_time" + ",wo.amount" + " FROM wire_out wo" + " LEFT JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " WHERE (wo.wireout_uuid > $1)" + " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" + " AND ( ( (wo.amount).val > ($3::taler_amount).val)" + " OR ( ( (wo.amount).val >= ($3::taler_amount).val)" + " AND ( (wo.amount).frac >= ($3::taler_amount).frac) ) )" + " ORDER BY wo.wireout_uuid ASC" + " LIMIT $2"); + PREPARE (pg, + "select_exchange_debit_transfers_dec", + "SELECT" + " wo.wireout_uuid AS serial_id" + ",wt.payto_uri" + ",wo.execution_date AS execution_time" + ",wo.amount" + " FROM wire_out wo" + " LEFT JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " WHERE (wo.wireout_uuid < $1)" + " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" + " AND ( ( (wo.amount).val > ($3::taler_amount).val)" + " OR ( ( (wo.amount).val >= ($3::taler_amount).val)" + " AND ( (wo.amount).frac >= ($3::taler_amount).frac) ) )" + " ORDER BY wo.wireout_uuid DESC" + " LIMIT $2"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + (limit > 0) + ? "select_exchange_debit_transfers_inc" + : "select_exchange_debit_transfers_dec", + params, + &handle_transfer_cb, + &stc); + if (GNUNET_OK != stc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_exchange_kycauth_transfers.c b/src/exchangedb/select_exchange_kycauth_transfers.c @@ -0,0 +1,180 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/select_exchange_kycauth_transfers.c + * @brief Implementation of the select_exchange_kycauth_transfers function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_exchange_kycauth_transfers.h" +#include "helper.h" + +/** + * Closure for #handle_aml_result. + */ +struct SelectTransferContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_AmlTransferCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on serious errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. Helper function + * for #TALER_EXCHANGEDB_select_exchange_debit_transfers(). + * + * @param cls closure of type `struct SelectTransferContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +handle_transfer_result (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct SelectTransferContext *stc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + char *payto_uri; + uint64_t rowid; + struct GNUNET_TIME_Absolute execution_time; + struct TALER_Amount amount; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("serial_id", + &rowid), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri), + GNUNET_PQ_result_spec_absolute_time ("execution_time", + &execution_time), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + stc->status = GNUNET_SYSERR; + return; + } + stc->cb (stc->cb_cls, + rowid, + payto_uri, + execution_time, + &amount); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_exchange_kycauth_transfers ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_Amount *threshold, + uint64_t offset, + int64_t limit, + const struct TALER_NormalizedPaytoHashP *h_payto, + TALER_EXCHANGEDB_AmlTransferCallback cb, + void *cb_cls) +{ + struct SelectTransferContext stc = { + .pg = pg, + .cb = cb, + .cb_cls = cb_cls, + .status = GNUNET_OK + }; + uint64_t ulimit = (limit > 0) ? limit : -limit; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&ulimit), + TALER_PQ_query_param_amount (pg->conn, + threshold), + NULL != h_payto + ? GNUNET_PQ_query_param_auto_from_type (h_payto) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_exchange_kycauth_transfers_inc", + "SELECT" + " ki.kycauth_in_serial_id AS serial_id" + ",wt.payto_uri" + ",ki.execution_date AS execution_time" + ",ki.credit AS amount" + " FROM kycauths_in ki" + " LEFT JOIN wire_targets wt" + " ON (ki.wire_source_h_payto = wt.wire_target_h_payto)" + " WHERE (ki.kycauth_in_serial_id > $1)" + " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" + " AND ( ( (ki.credit).val > ($3::taler_amount).val)" + " OR ( ( (ki.credit).val >= ($3::taler_amount).val)" + " AND ( (ki.credit).frac >= ($3::taler_amount).frac) ) )" + " ORDER BY ki.kycauth_in_serial_id ASC" + " LIMIT $2"); + PREPARE (pg, + "select_exchange_kycauth_transfers_dec", + "SELECT" + " ki.kycauth_in_serial_id AS serial_id" + ",wt.payto_uri" + ",ki.execution_date AS execution_time" + ",ki.credit AS amount" + " FROM kycauths_in ki" + " LEFT JOIN wire_targets wt" + " ON (ki.wire_source_h_payto = wt.wire_target_h_payto)" + " WHERE (ki.kycauth_in_serial_id < $1)" + " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )" + " AND ( ( (ki.credit).val > ($3::taler_amount).val)" + " OR ( ( (ki.credit).val >= ($3::taler_amount).val)" + " AND ( (ki.credit).frac >= ($3::taler_amount).frac) ) )" + " ORDER BY ki.kycauth_in_serial_id DESC" + " LIMIT $2"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + (limit > 0) + ? "select_exchange_kycauth_transfers_inc" + : "select_exchange_kycauth_transfers_dec", + params, + &handle_transfer_result, + &stc); + if (GNUNET_OK != stc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_kyc_accounts.c b/src/exchangedb/select_kyc_accounts.c @@ -0,0 +1,235 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/select_kyc_accounts.c + * @brief Implementation of the select_kyc_accounts function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_kyc_accounts.h" +#include "helper.h" + + +/** + * Closure for #handle_aml_result. + */ +struct KycAccountResultContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_AmlAccountListCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on serious errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. Helper function + * for #TALER_EXCHANGEDB_select_kyc_accounts(). + * + * @param cls closure of type `struct KycAccountResultContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +handle_kyc_account_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct KycAccountResultContext *ctx = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + struct TALER_NormalizedPaytoHashP h_payto; + char *comments = NULL; + struct GNUNET_TIME_Timestamp open_time + = GNUNET_TIME_UNIT_FOREVER_TS; + struct GNUNET_TIME_Timestamp close_time + = GNUNET_TIME_UNIT_FOREVER_TS; + bool to_investigate; + bool high_risk; + struct TALER_FullPayto payto; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("kyc_target_serial_id", + &rowid), + GNUNET_PQ_result_spec_auto_from_type ("h_payto", + &h_payto), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("comments", + &comments), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_timestamp ("open_time", + &open_time), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_timestamp ("close_time", + &close_time), + NULL), + GNUNET_PQ_result_spec_bool ("to_investigate", + &to_investigate), + GNUNET_PQ_result_spec_bool ("high_risk", + &high_risk), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto.full_payto), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ctx->cb (ctx->cb_cls, + rowid, + &h_payto, + open_time, + close_time, + comments, + high_risk, + to_investigate, + payto); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_kyc_accounts ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + enum TALER_EXCHANGE_YesNoAll investigation_only, + enum TALER_EXCHANGE_YesNoAll open_only, + enum TALER_EXCHANGE_YesNoAll high_risk_only, + uint64_t offset, + int64_t limit, + TALER_EXCHANGEDB_AmlAccountListCallback cb, + void *cb_cls) +{ + uint64_t ulimit = (limit > 0) ? limit : -limit; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&ulimit), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == + investigation_only)), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == + investigation_only)), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == + open_only)), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == + open_only)), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL == + high_risk_only)), + GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES == + high_risk_only)), + GNUNET_PQ_query_param_end + }; + struct KycAccountResultContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + const char *stmt = (limit > 0) + ? "select_kyc_accounts_inc" + : "select_kyc_accounts_dec"; + + PREPARE (pg, + "select_kyc_accounts_inc", + "SELECT" + " kt.kyc_target_serial_id" + ",kt.h_normalized_payto AS h_payto" + ",kt.open_time" + ",kt.close_time" + ",lo.jproperties ->> 'FILE_NOTE' AS comments" + ",lo.jproperties ->> 'open_date' AS open_time" + ",COALESCE(lo.to_investigate,FALSE) AS to_investigate" + ",COALESCE((lo.jproperties ->> 'HIGH_RISK_CUSTOMER')::bool,FALSE) AS high_risk" + ",wt.payto_uri" + " FROM kyc_targets kt" + " JOIN wire_targets wt" + " ON (wt.h_normalized_payto = kt.h_normalized_payto)" + " LEFT JOIN legitimization_outcomes lo" + " ON (lo.h_payto = kt.h_normalized_payto)" + " WHERE (kyc_target_serial_id > $1)" + // select most recent outcomes only + " AND COALESCE (lo.is_active, TRUE)" + " AND ($3 OR (COALESCE(lo.to_investigate,FALSE) = $4))" + // Account is open if we had an AML outcome + " AND ($5 OR ((lo.outcome_serial_id IS NULL) = $6))" + " AND ($7 OR ((COALESCE((lo.jproperties ->>'high_risk')::bool,FALSE) = $8)))" + " ORDER BY kt.kyc_target_serial_id ASC" + " LIMIT $2"); + PREPARE (pg, + "select_kyc_accounts_dec", + "SELECT" + " kt.kyc_target_serial_id" + ",kt.h_normalized_payto AS h_payto" + ",kt.open_time" + ",kt.close_time" + ",lo.jproperties ->> 'FILE_NOTE' AS comments" + ",lo.jproperties ->> 'open_date' AS open_time" + ",COALESCE(lo.to_investigate,FALSE) AS to_investigate" + ",COALESCE((lo.jproperties ->> 'HIGH_RISK_CUSTOMER')::bool,FALSE) AS high_risk" + ",wt.payto_uri" + " FROM kyc_targets kt" + " LEFT JOIN legitimization_outcomes lo" + " ON (lo.h_payto = kt.h_normalized_payto)" + " LEFT JOIN LATERAL (" + " SELECT payto_uri" + " FROM wire_targets" + " WHERE h_normalized_payto = kt.h_normalized_payto" + " ORDER BY wire_target_serial_id DESC" + " LIMIT 1" + " ) wt ON true" + " WHERE (kyc_target_serial_id < $1)" + // select most recent outcomes only + " AND COALESCE (lo.is_active, TRUE)" + " AND ($3 OR (COALESCE(lo.to_investigate,FALSE) = $4))" + // Account is open if we had an AML outcome + " AND ($5 OR ((lo.outcome_serial_id IS NULL) = $6))" + " AND ($7 OR ((COALESCE((lo.jproperties ->>'high_risk')::bool,FALSE) = $8)))" + " ORDER BY kt.kyc_target_serial_id DESC" + " LIMIT $2"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + stmt, + params, + &handle_kyc_account_cb, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_kyc_attributes.c b/src/exchangedb/select_kyc_attributes.c @@ -0,0 +1,154 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/select_kyc_attributes.c + * @brief Implementation of the select_kyc_attributes function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_kyc_attributes.h" +#include "helper.h" + + +/** + * Closure for #get_attributes_cb(). + */ +struct GetAttributesContext +{ + /** + * Function to call per result. + */ + TALER_EXCHANGEDB_AttributeCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Key of our query. + */ + const struct TALER_NormalizedPaytoHashP *h_payto; + + /** + * Flag set to #GNUNET_OK as long as everything is fine. + */ + enum GNUNET_GenericReturnValue status; + +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct GetAttributesContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_attributes_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct GetAttributesContext *ctx = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + struct GNUNET_TIME_Timestamp collection_time; + struct GNUNET_TIME_Timestamp expiration_time; + size_t enc_attributes_size; + void *enc_attributes; + char *provider; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("provider_name", + &provider), + GNUNET_PQ_result_spec_timestamp ("collection_time", + &collection_time), + GNUNET_PQ_result_spec_timestamp ("expiration_time", + &expiration_time), + GNUNET_PQ_result_spec_variable_size ("encrypted_attributes", + &enc_attributes, + &enc_attributes_size), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ctx->cb (ctx->cb_cls, + ctx->h_payto, + provider, + collection_time, + expiration_time, + enc_attributes_size, + enc_attributes); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_kyc_attributes ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + TALER_EXCHANGEDB_AttributeCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_end + }; + struct GetAttributesContext ctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .h_payto = h_payto, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_kyc_attributes", + "SELECT " + " lp.provider_name" + ",ka.collection_time" + ",ka.expiration_time" + ",ka.encrypted_attributes" + " FROM kyc_attributes ka" + " JOIN legitimization_processes lp" + " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)" + " WHERE ka.h_payto=$1"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_kyc_attributes", + params, + &get_attributes_cb, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_merge_amounts_for_kyc_check.c b/src/exchangedb/select_merge_amounts_for_kyc_check.c @@ -0,0 +1,152 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/select_merge_amounts_for_kyc_check.c + * @brief Implementation of the select_merge_amounts_for_kyc_check function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_merge_amounts_for_kyc_check.h" +#include "helper.h" + + +/** + * Closure for #get_kyc_amounts_cb(). + */ +struct KycAmountCheckContext +{ + /** + * Function to call per result. + */ + TALER_KYCLOGIC_KycAmountCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Flag set to #GNUNET_OK as long as everything is fine. + */ + enum GNUNET_GenericReturnValue status; + +}; + +/** + * Invoke the callback for each result. + * + * @param cls a `struct KycAmountCheckContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_kyc_amounts_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct KycAmountCheckContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + + for (unsigned int i = 0; i < num_results; i++) + { + struct GNUNET_TIME_Absolute date; + struct TALER_Amount amount; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_absolute_time ("date", + &date), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ret = ctx->cb (ctx->cb_cls, + &amount, + date); + GNUNET_PQ_cleanup_result (rs); + switch (ret) + { + case GNUNET_OK: + continue; + case GNUNET_NO: + break; + case GNUNET_SYSERR: + ctx->status = GNUNET_SYSERR; + break; + } + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_merge_amounts_for_kyc_check ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_KYCLOGIC_KycAmountCallback kac, + void *kac_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_absolute_time (&time_limit), + GNUNET_PQ_query_param_end + }; + struct KycAmountCheckContext ctx = { + .cb = kac, + .cb_cls = kac_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_kyc_relevant_merge_events", + "SELECT" + " amount_with_fee AS amount" + ",merge_timestamp AS date" + " FROM account_merges" + " JOIN purse_merges USING (purse_pub)" + " JOIN purse_requests USING (purse_pub)" + " JOIN purse_decision USING (purse_pub)" + " WHERE wallet_h_payto=$1" + " AND merge_timestamp >= $2" + " AND NOT refunded" + " ORDER BY merge_timestamp DESC"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_kyc_relevant_merge_events", + params, + &get_kyc_amounts_cb, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_purse.c b/src/exchangedb/select_purse.c @@ -0,0 +1,90 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file select_purse.c + * @brief Implementation of the select_purse function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_purse.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_purse ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp *purse_creation, + struct GNUNET_TIME_Timestamp *purse_expiration, + struct TALER_Amount *amount, + struct TALER_Amount *deposited, + struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp *merge_timestamp, + bool *purse_deleted, + bool *purse_refunded) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("purse_expiration", + purse_expiration), + GNUNET_PQ_result_spec_timestamp ("purse_creation", + purse_creation), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + amount), + TALER_PQ_RESULT_SPEC_AMOUNT ("balance", + deposited), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + h_contract_terms), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_timestamp ("merge_timestamp", + merge_timestamp), + NULL), + GNUNET_PQ_result_spec_bool ("purse_deleted", + purse_deleted), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_bool ("purse_refunded", + purse_refunded), + NULL), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "select_purse", + "SELECT " + " pr.merge_pub" + ",pr.purse_creation" + ",pr.purse_expiration" + ",pr.h_contract_terms" + ",pr.amount_with_fee" + ",pr.balance" + ",pm.merge_timestamp" + ",pd.purse_sig IS NOT NULL AS purse_deleted" + ",pc.refunded AS purse_refunded" + " FROM purse_requests pr" + " LEFT JOIN purse_merges pm ON (pm.purse_pub = pr.purse_pub)" + " LEFT JOIN purse_decision pc ON (pc.purse_pub = pr.purse_pub)" + " LEFT JOIN purse_deletion pd ON (pd.purse_pub = pr.purse_pub)" + " WHERE pr.purse_pub=$1;"); + *merge_timestamp = GNUNET_TIME_UNIT_FOREVER_TS; + *purse_refunded = false; + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_purse", + params, + rs); +} diff --git a/src/exchangedb/select_purse_by_merge_pub.c b/src/exchangedb/select_purse_by_merge_pub.c @@ -0,0 +1,75 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_purse_by_merge_pub.c + * @brief Implementation of the select_purse_by_merge_pub function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_purse_by_merge_pub.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_select_purse_by_merge_pub ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseMergePublicKeyP *merge_pub, + struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp *purse_expiration, + struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t *age_limit, + struct TALER_Amount *target_amount, + struct TALER_Amount *balance, + struct TALER_PurseContractSignatureP *purse_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (merge_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + purse_pub), + GNUNET_PQ_result_spec_timestamp ("purse_expiration", + purse_expiration), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + h_contract_terms), + GNUNET_PQ_result_spec_uint32 ("age_limit", + age_limit), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + target_amount), + TALER_PQ_RESULT_SPEC_AMOUNT ("balance", + balance), + GNUNET_PQ_result_spec_auto_from_type ("purse_sig", + purse_sig), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "select_purse_by_merge_pub", + "SELECT " + " purse_pub" + ",purse_expiration" + ",h_contract_terms" + ",age_limit" + ",amount_with_fee" + ",balance" + ",purse_sig" + " FROM purse_requests" + " WHERE merge_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_purse_by_merge_pub", + params, + rs); +} diff --git a/src/exchangedb/select_purse_decisions_above_serial_id.c b/src/exchangedb/select_purse_decisions_above_serial_id.c @@ -0,0 +1,158 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_purse_decisions_above_serial_id.c + * @brief Implementation of the select_purse_decisions_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_purse_decisions_above_serial_id.h" +#include "helper.h" + +/** + * Closure for #purse_decision_serial_helper_cb(). + */ +struct PurseDecisionSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_PurseDecisionCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct PurseRefundSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +purse_decision_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct PurseDecisionSerialContext *dsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_ReservePublicKeyP reserve_pub; + bool no_reserve = true; + uint64_t rowid; + struct TALER_Amount val; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + &purse_pub), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + &no_reserve), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &val), + GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + dsc->status = GNUNET_SYSERR; + return; + } + ret = dsc->cb (dsc->cb_cls, + rowid, + &purse_pub, + no_reserve ? NULL : &reserve_pub, + &val); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_select_purse_decisions_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + bool refunded, + TALER_EXCHANGEDB_PurseDecisionCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_bool (refunded), + GNUNET_PQ_query_param_end + }; + struct PurseDecisionSerialContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "audit_get_purse_decisions_incr", + "SELECT" + " pd.purse_pub" + ",pm.reserve_pub" + ",pd.purse_decision_serial_id" + ",pr.amount_with_fee" + " FROM purse_decision pd" + " JOIN purse_requests pr ON (pd.purse_pub = pr.purse_pub)" + " LEFT JOIN purse_merges pm ON (pm.purse_pub = pd.purse_pub)" + " WHERE (" + " (purse_decision_serial_id>=$1) AND " + " (refunded=$2)" + " )" + " ORDER BY purse_decision_serial_id ASC;"); + + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_purse_decisions_incr", + params, + &purse_decision_serial_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_purse_deposits_above_serial_id.c b/src/exchangedb/select_purse_deposits_above_serial_id.c @@ -0,0 +1,198 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file select_purse_deposits_above_serial_id.c + * @brief Implementation of the select_purse_deposits_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_purse_deposits_above_serial_id.h" +#include "helper.h" + +/** + * Closure for #purse_deposit_serial_helper_cb(). + */ +struct PurseDepositSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_PurseDepositCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct DepositSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +purse_deposit_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct PurseDepositSerialContext *dsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_PurseDeposit deposit = { + .exchange_base_url = NULL + }; + struct TALER_DenominationPublicKey denom_pub; + uint64_t rowid; + uint32_t flags32; + struct TALER_ReservePublicKeyP reserve_pub; + bool not_merged = false; + struct TALER_Amount purse_balance; + struct TALER_Amount purse_total; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &deposit.amount), + TALER_PQ_RESULT_SPEC_AMOUNT ("balance", + &purse_balance), + TALER_PQ_RESULT_SPEC_AMOUNT ("total", + &purse_total), + TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", + &deposit.deposit_fee), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("partner_base_url", + &deposit.exchange_base_url), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + &not_merged), + TALER_PQ_result_spec_denom_pub ("denom_pub", + &denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + &deposit.purse_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &deposit.coin_sig), + GNUNET_PQ_result_spec_uint32 ("flags", + &flags32), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &deposit.coin_pub), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &deposit.h_age_commitment), + &deposit.no_age_commitment), + GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + memset (&deposit, + 0, + sizeof (deposit)); + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + dsc->status = GNUNET_SYSERR; + return; + } + ret = dsc->cb (dsc->cb_cls, + rowid, + &deposit, + not_merged ? NULL : &reserve_pub, + (enum TALER_WalletAccountMergeFlags) flags32, + &purse_balance, + &purse_total, + &denom_pub); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_select_purse_deposits_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseDepositCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct PurseDepositSerialContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "audit_get_purse_deposits_incr", + "SELECT" + " pd.amount_with_fee" + ",pr.amount_with_fee AS total" + ",pr.balance" + ",pr.flags" + ",pd.purse_pub" + ",pd.coin_sig" + ",partner_base_url" + ",denom.denom_pub" + ",denom.fee_deposit" + ",pm.reserve_pub" + ",kc.coin_pub" + ",kc.age_commitment_hash" + ",pd.purse_deposit_serial_id" + " FROM purse_deposits pd" + " LEFT JOIN partners USING (partner_serial_id)" + " LEFT JOIN purse_merges pm USING (purse_pub)" + " JOIN purse_requests pr USING (purse_pub)" + " JOIN known_coins kc USING (coin_pub)" + " JOIN denominations denom USING (denominations_serial)" + " WHERE (" + " (purse_deposit_serial_id>=$1)" + " )" + " ORDER BY purse_deposit_serial_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_purse_deposits_incr", + params, + &purse_deposit_serial_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_purse_deposits_by_purse.c b/src/exchangedb/select_purse_deposits_by_purse.c @@ -0,0 +1,149 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_purse_deposits_by_purse.c + * @brief Implementation of the select_purse_deposits_by_purse function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_purse_deposits_by_purse.h" +#include "helper.h" + +/** + * Closure for #purse_refund_coin_helper_cb(). + */ +struct PurseRefundCoinContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_PurseRefundCoinCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct PurseRefundCoinContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +purse_refund_coin_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct PurseRefundCoinContext *dsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_Amount amount_with_fee; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_DenominationPublicKey denom_pub; + uint64_t rowid; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_denom_pub ("denom_pub", + &denom_pub), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &amount_with_fee), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &coin_pub), + GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + dsc->status = GNUNET_SYSERR; + return; + } + ret = dsc->cb (dsc->cb_cls, + rowid, + &amount_with_fee, + &coin_pub, + &denom_pub); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_select_purse_deposits_by_purse ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + TALER_EXCHANGEDB_PurseRefundCoinCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_end + }; + struct PurseRefundCoinContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "audit_get_purse_deposits_by_purse", + "SELECT" + " pd.purse_deposit_serial_id" + ",pd.amount_with_fee" + ",pd.coin_pub" + ",denom.denom_pub" + " FROM purse_deposits pd" + " JOIN known_coins kc" + " USING (coin_pub)" + " JOIN denominations denom" + " USING (denominations_serial)" + " WHERE purse_pub=$1;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_purse_deposits_by_purse", + params, + &purse_refund_coin_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_purse_merge.c b/src/exchangedb/select_purse_merge.c @@ -0,0 +1,76 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_purse_merge.c + * @brief Implementation of the select_purse_merge function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_purse_merge.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_select_purse_merge ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_PurseMergeSignatureP *merge_sig, + struct GNUNET_TIME_Timestamp *merge_timestamp, + char **partner_url, + struct TALER_ReservePublicKeyP *reserve_pub, + bool *refunded) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("merge_sig", + merge_sig), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + reserve_pub), + GNUNET_PQ_result_spec_timestamp ("merge_timestamp", + merge_timestamp), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("partner_base_url", + partner_url), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_bool ("refunded", + refunded), + NULL), + GNUNET_PQ_result_spec_end + }; + + *partner_url = NULL; + *refunded = false; + PREPARE (pg, + "select_purse_merge", + "SELECT " + " pm.reserve_pub" + ",pm.merge_sig" + ",pm.merge_timestamp" + ",pr.partner_base_url" + ",pd.refunded" + " FROM purse_merges pm" + " LEFT JOIN purse_decision pd USING (purse_pub)" + " LEFT JOIN partners pr USING (partner_serial_id)" + " WHERE pm.purse_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_purse_merge", + params, + rs); +} diff --git a/src/exchangedb/select_purse_merges_above_serial_id.c b/src/exchangedb/select_purse_merges_above_serial_id.c @@ -0,0 +1,186 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file select_purse_merges_above_serial_id.c + * @brief Implementation of the select_purse_merges_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_purse_merges_above_serial_id.h" +#include "helper.h" + + +/** + * Closure for #purse_deposit_serial_helper_cb(). + */ +struct PurseMergeSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_PurseMergeCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct PurseMergeSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +purse_merges_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct PurseMergeSerialContext *dsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + char *partner_base_url = NULL; + struct TALER_Amount amount; + struct TALER_Amount balance; + uint32_t flags32; + enum TALER_WalletAccountMergeFlags flags; + struct TALER_PurseMergePublicKeyP merge_pub; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_PurseMergeSignatureP merge_sig; + struct TALER_PurseContractPublicKeyP purse_pub; + struct GNUNET_TIME_Timestamp merge_timestamp; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &amount), + TALER_PQ_RESULT_SPEC_AMOUNT ("balance", + &balance), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("partner_base_url", + &partner_base_url), + NULL), + GNUNET_PQ_result_spec_uint32 ("flags", + &flags32), + GNUNET_PQ_result_spec_timestamp ("merge_timestamp", + &merge_timestamp), + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + &purse_pub), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ("merge_sig", + &merge_sig), + GNUNET_PQ_result_spec_auto_from_type ("merge_pub", + &merge_pub), + GNUNET_PQ_result_spec_uint64 ("purse_merge_request_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + dsc->status = GNUNET_SYSERR; + return; + } + flags = (enum TALER_WalletAccountMergeFlags) flags32; + ret = dsc->cb (dsc->cb_cls, + rowid, + partner_base_url, + &amount, + &balance, + flags, + &merge_pub, + &reserve_pub, + &merge_sig, + &purse_pub, + merge_timestamp); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_TALER_TALER_EXCHANGEDB_select_purse_merges_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseMergeCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct PurseMergeSerialContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "audit_get_purse_merge_incr", + "SELECT" + " pm.purse_merge_request_serial_id" + ",partner_base_url" + ",pr.amount_with_fee" + ",pr.balance" + ",pr.flags" + ",pr.merge_pub" + ",pm.reserve_pub" + ",pm.merge_sig" + ",pm.purse_pub" + ",pm.merge_timestamp" + " FROM purse_merges pm" + " JOIN purse_requests pr USING (purse_pub)" + " LEFT JOIN partners USING (partner_serial_id)" + " WHERE (" + " (purse_merge_request_serial_id>=$1)" + " )" + " ORDER BY purse_merge_request_serial_id ASC;"); + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_purse_merge_incr", + params, + &purse_merges_serial_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_purse_requests_above_serial_id.c b/src/exchangedb/select_purse_requests_above_serial_id.c @@ -0,0 +1,174 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file select_purse_requests_above_serial_id.c + * @brief Implementation of the select_purse_requests_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_purse_requests_above_serial_id.h" +#include "helper.h" + + +/** + * Closure for #purse_deposit_serial_helper_cb(). + */ +struct PurseRequestsSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_PurseRequestCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct PurseRequestsSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +purse_requests_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct PurseRequestsSerialContext *dsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + struct TALER_Amount target_amount; + uint32_t age_limit; + struct TALER_PurseMergePublicKeyP merge_pub; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PrivateContractHashP h_contract_terms; + struct TALER_PurseContractSignatureP purse_sig; + struct GNUNET_TIME_Timestamp purse_creation; + struct GNUNET_TIME_Timestamp purse_expiration; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &target_amount), + GNUNET_PQ_result_spec_uint32 ("age_limit", + &age_limit), + GNUNET_PQ_result_spec_timestamp ("purse_creation", + &purse_creation), + GNUNET_PQ_result_spec_timestamp ("purse_expiration", + &purse_expiration), + GNUNET_PQ_result_spec_auto_from_type ("purse_pub", + &purse_pub), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + &h_contract_terms), + GNUNET_PQ_result_spec_auto_from_type ("purse_sig", + &purse_sig), + GNUNET_PQ_result_spec_auto_from_type ("merge_pub", + &merge_pub), + GNUNET_PQ_result_spec_uint64 ("purse_requests_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + dsc->status = GNUNET_SYSERR; + return; + } + ret = dsc->cb (dsc->cb_cls, + rowid, + &purse_pub, + &merge_pub, + purse_creation, + purse_expiration, + &h_contract_terms, + age_limit, + &target_amount, + &purse_sig); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_select_purse_requests_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseRequestCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct PurseRequestsSerialContext dsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "audit_get_purse_requests_incr", + "SELECT" + " purse_requests_serial_id" + ",purse_pub" + ",amount_with_fee" + ",age_limit" + ",h_contract_terms" + ",purse_creation" + ",purse_expiration" + ",merge_pub" + ",purse_sig" + " FROM purse_requests" + " WHERE (" + " (purse_requests_serial_id>=$1)" + " )" + " ORDER BY purse_requests_serial_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_purse_requests_incr", + params, + &purse_requests_serial_helper_cb, + &dsc); + if (GNUNET_OK != dsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_recoup_above_serial_id.c b/src/exchangedb/select_recoup_above_serial_id.c @@ -0,0 +1,184 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_recoup_above_serial_id.c + * @brief Implementation of the select_recoup_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_recoup_above_serial_id.h" +#include "helper.h" + + +/** + * Closure for #recoup_serial_helper_cb(). + */ +struct RecoupSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_RecoupCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct RecoupSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +recoup_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct RecoupSerialContext *psc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = psc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_CoinPublicInfo coin; + struct TALER_CoinSpendSignatureP coin_sig; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; + struct TALER_Amount amount; + struct TALER_DenominationPublicKey denom_pub; + struct GNUNET_TIME_Timestamp timestamp; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("recoup_uuid", + &rowid), + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + &timestamp), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &coin.coin_pub), + TALER_PQ_result_spec_denom_pub ("denom_pub", + &denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &coin_sig), + GNUNET_PQ_result_spec_auto_from_type ("coin_blind", + &coin_blind), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &coin.denom_pub_hash), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &coin.h_age_commitment), + &coin.no_age_commitment), + TALER_PQ_result_spec_denom_sig ("denom_sig", + &coin.denom_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_end + }; + int ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + psc->status = GNUNET_SYSERR; + return; + } + ret = psc->cb (psc->cb_cls, + rowid, + timestamp, + &amount, + &reserve_pub, + &coin, + &denom_pub, + &coin_sig, + &coin_blind); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_recoup_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_RecoupCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct RecoupSerialContext psc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "recoup_get_incr", + "SELECT" + " recoup_uuid" + ",recoup_timestamp" + ",withdraw.reserve_pub" + ",coins.coin_pub" + ",coin_sig" + ",coin_blind" + ",denoms.denom_pub_hash" + ",coins.denom_sig" + ",coins.age_commitment_hash" + ",denoms.denom_pub" + ",amount" + " FROM recoup" + " JOIN known_coins coins" + " USING (coin_pub)" + " JOIN withdraw" + " USING (withdraw_id)" + " JOIN denominations denoms" + " ON (coins.denominations_serial = denoms.denominations_serial)" + " WHERE recoup_uuid>=$1" + " ORDER BY recoup_uuid ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "recoup_get_incr", + params, + &recoup_serial_helper_cb, + &psc); + if (GNUNET_OK != psc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_recoup_refresh_above_serial_id.c b/src/exchangedb/select_recoup_refresh_above_serial_id.c @@ -0,0 +1,204 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_recoup_refresh_above_serial_id.c + * @brief Implementation of the select_recoup_refresh_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_recoup_refresh_above_serial_id.h" +#include "helper.h" + + +/** + * Closure for #recoup_refresh_serial_helper_cb(). + */ +struct RecoupRefreshSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_RecoupRefreshCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct RecoupRefreshSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +recoup_refresh_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct RecoupRefreshSerialContext *psc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = psc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + struct TALER_CoinSpendPublicKeyP old_coin_pub; + struct TALER_CoinPublicInfo coin; + struct TALER_CoinSpendSignatureP coin_sig; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; + struct TALER_DenominationPublicKey denom_pub; + struct TALER_DenominationHashP old_denom_pub_hash; + struct TALER_Amount amount; + struct TALER_BlindedCoinHashP h_blind_ev; + struct GNUNET_TIME_Timestamp timestamp; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid", + &rowid), + GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", + &timestamp), + GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", + &old_coin_pub), + GNUNET_PQ_result_spec_auto_from_type ("old_denom_pub_hash", + &old_denom_pub_hash), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &coin.coin_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_sig", + &coin_sig), + GNUNET_PQ_result_spec_auto_from_type ("coin_blind", + &coin_blind), + TALER_PQ_result_spec_denom_pub ("denom_pub", + &denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", + &h_blind_ev), + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + &coin.denom_pub_hash), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &coin.h_age_commitment), + &coin.no_age_commitment), + TALER_PQ_result_spec_denom_sig ("denom_sig", + &coin.denom_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + psc->status = GNUNET_SYSERR; + return; + } + ret = psc->cb (psc->cb_cls, + rowid, + timestamp, + &amount, + &old_coin_pub, + &old_denom_pub_hash, + &coin, + &denom_pub, + &coin_sig, + &coin_blind); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_recoup_refresh_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_RecoupRefreshCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct RecoupRefreshSerialContext psc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_recoup_refresh_above_serial_id", + "SELECT" + " rr.recoup_refresh_uuid" + ",rr.recoup_timestamp" + ",rr.coin_sig" + ",rr.coin_blind" + ",rr.amount" + ",rrc.h_coin_ev AS h_blind_ev" // FIXME:-#9828 r.rc? r.selected_h? Old logic wanted a TALER_BlindedCoinHash, which we now need to derive (from rr.coin_blind) + ",new_coins.age_commitment_hash" + ",new_coins.coin_pub AS coin_pub" + ",new_denoms.denom_pub AS denom_pub" + ",new_denoms.denom_pub_hash" + ",new_coins.denom_sig AS denom_sig" + ",old_coins.coin_pub AS old_coin_pub" + ",old_denoms.denom_pub_hash AS old_denom_pub_hash" + " FROM recoup_refresh rr" + " INNER JOIN refresh_revealed_coins rrc" // FIXME-#9828: no such table anymore! + // but we have 'refresh_id" which is an FK into 'refresh'! + " USING (rrc_serial)" + " INNER JOIN refresh r" + // but we have 'refresh_id" which is an FK into 'refresh'! + " USING (refresh_id)" + " INNER JOIN known_coins old_coins" + " ON (r.old_coin_pub = old_coins.coin_pub)" + " INNER JOIN known_coins new_coins" + " ON (rr.coin_pub == new_coins.coin_pub)" + " INNER JOIN refresh_commitments rfc" + " ON (rrc.melt_serial_id = rfc.melt_serial_id)" + " INNER JOIN denominations new_denoms" + " ON (new_coins.denominations_serial = new_denoms.denominations_serial)" + " INNER JOIN denominations old_denoms" + " ON (old_coins.denominations_serial = old_denoms.denominations_serial)" + " WHERE recoup_refresh_uuid>=$1" + " ORDER BY recoup_refresh_uuid ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_recoup_refresh_above_serial_id", + params, + &recoup_refresh_serial_helper_cb, + &psc); + if (GNUNET_OK != psc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_refreshes_above_serial_id.c b/src/exchangedb/select_refreshes_above_serial_id.c @@ -0,0 +1,180 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2025 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/> + */ +/** + * @file exchangedb/select_refreshes_above_serial_id.c + * @brief Implementation of the select_refreshes_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_refreshes_above_serial_id.h" +#include "helper.h" + + +/** + * Closure for #refreshs_serial_helper_cb(). + */ +struct RefreshsSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_RefreshesCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct RefreshsSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +refreshs_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct RefreshsSerialContext *rsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = rsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_DenominationPublicKey old_denom_pub; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_AgeCommitmentHashP h_age_commitment; + bool ac_isnull; + struct TALER_Amount amount_with_fee; + uint64_t rowid; + struct TALER_RefreshCommitmentP rc; + size_t num_nds; + uint64_t *nds; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_denom_pub ("old_denom_pub", + &old_denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", + &coin_pub), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &h_age_commitment), + &ac_isnull), + GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", + &coin_sig), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &amount_with_fee), + GNUNET_PQ_result_spec_uint64 ("refresh_id", + &rowid), + GNUNET_PQ_result_spec_auto_from_type ("rc", + &rc), + GNUNET_PQ_result_spec_array_uint64 (pg->conn, + "new_denominations_serials", + &num_nds, + &nds), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + rsc->status = GNUNET_SYSERR; + return; + } + + ret = rsc->cb (rsc->cb_cls, + rowid, + &old_denom_pub, + &coin_pub, + &coin_sig, + ac_isnull ? NULL : &h_age_commitment, + &amount_with_fee, + num_nds, + nds, + &rc); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_refreshes_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_RefreshesCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct RefreshsSerialContext rsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_refreshes_above_serial_id", + "SELECT" + " denom.denom_pub AS old_denom_pub" + ",r.old_coin_pub" + ",kc.age_commitment_hash" + ",r.old_coin_sig" + ",r.amount_with_fee" + ",r.refresh_id" + ",r.rc" + ",r.denom_serials AS new_denominations_serials" + " FROM refresh r" + " JOIN known_coins kc" + " ON (r.old_coin_pub = kc.coin_pub)" + " JOIN denominations denom" + " ON (kc.denominations_serial = denom.denominations_serial)" + " WHERE refresh_id>=$1" + " ORDER BY refresh_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_refreshes_above_serial_id", + params, + &refreshs_serial_helper_cb, + &rsc); + if (GNUNET_OK != rsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_refunds_above_serial_id.c b/src/exchangedb/select_refunds_above_serial_id.c @@ -0,0 +1,220 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_refunds_above_serial_id.c + * @brief Implementation of the select_refunds_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_refunds_above_serial_id.h" +#include "helper.h" + +/** + * Closure for #refunds_serial_helper_cb(). + */ +struct RefundsSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_RefundCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct RefundsSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +refunds_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct RefundsSerialContext *rsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = rsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_EXCHANGEDB_Refund refund; + struct TALER_DenominationPublicKey denom_pub; + uint64_t rowid; + bool full_refund; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", + &refund.details.merchant_pub), + GNUNET_PQ_result_spec_auto_from_type ("merchant_sig", + &refund.details.merchant_sig), + GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", + &refund.details.h_contract_terms), + GNUNET_PQ_result_spec_uint64 ("rtransaction_id", + &refund.details.rtransaction_id), + TALER_PQ_result_spec_denom_pub ("denom_pub", + &denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &refund.coin.coin_pub), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &refund.details.refund_amount), + GNUNET_PQ_result_spec_uint64 ("refund_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + rsc->status = GNUNET_SYSERR; + return; + } + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&rowid), + GNUNET_PQ_query_param_end + }; + struct TALER_Amount amount_with_fee; + uint64_t s_f; + uint64_t s_v; + struct GNUNET_PQ_ResultSpec rs2[] = { + GNUNET_PQ_result_spec_uint64 ("s_v", + &s_v), + GNUNET_PQ_result_spec_uint64 ("s_f", + &s_f), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &amount_with_fee), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + qs = GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "test_refund_full", + params, + rs2); + if (qs <= 0) + { + GNUNET_break (0); + rsc->status = GNUNET_SYSERR; + return; + } + /* normalize */ + s_v += s_f / TALER_AMOUNT_FRAC_BASE; + s_f %= TALER_AMOUNT_FRAC_BASE; + full_refund = (s_v >= amount_with_fee.value) && + (s_f >= amount_with_fee.fraction); + } + ret = rsc->cb (rsc->cb_cls, + rowid, + &denom_pub, + &refund.coin.coin_pub, + &refund.details.merchant_pub, + &refund.details.merchant_sig, + &refund.details.h_contract_terms, + refund.details.rtransaction_id, + full_refund, + &refund.details.refund_amount); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_refunds_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_RefundCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct RefundsSerialContext rsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Fetch refunds with rowid '\geq' the given parameter */ + PREPARE (pg, + "audit_get_refunds_incr", + "SELECT" + " bdep.merchant_pub" + ",ref.merchant_sig" + ",bdep.h_contract_terms" + ",ref.rtransaction_id" + ",denom.denom_pub" + ",kc.coin_pub" + ",ref.amount_with_fee" + ",ref.refund_serial_id" + " FROM refunds ref" + " JOIN batch_deposits bdep" + " ON (ref.batch_deposit_serial_id=bdep.batch_deposit_serial_id)" + " JOIN coin_deposits cdep" + " ON (ref.coin_pub=cdep.coin_pub AND ref.batch_deposit_serial_id=cdep.batch_deposit_serial_id)" + " JOIN known_coins kc" + " ON (cdep.coin_pub=kc.coin_pub)" + " JOIN denominations denom" + " ON (kc.denominations_serial=denom.denominations_serial)" + " WHERE ref.refund_serial_id>=$1" + " ORDER BY ref.refund_serial_id ASC;"); + PREPARE (pg, + "test_refund_full", + "SELECT" + " CAST(SUM(CAST((ref.amount_with_fee).frac AS INT8)) AS INT8) AS s_f" + ",CAST(SUM((ref.amount_with_fee).val) AS INT8) AS s_v" + ",cdep.amount_with_fee" + " FROM refunds ref" + " JOIN coin_deposits cdep" + " ON (ref.coin_pub=cdep.coin_pub AND ref.batch_deposit_serial_id=cdep.batch_deposit_serial_id)" + " WHERE ref.refund_serial_id=$1" + " GROUP BY (cdep.amount_with_fee);"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_refunds_incr", + params, + &refunds_serial_helper_cb, + &rsc); + if (GNUNET_OK != rsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_refunds_by_coin.c b/src/exchangedb/select_refunds_by_coin.c @@ -0,0 +1,139 @@ +/* + This file is part of TALER + Copyright (C) 2022-2023 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/> + */ +/** + * @file exchangedb/select_refunds_by_coin.c + * @brief Implementation of the select_refunds_by_coin function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_refunds_by_coin.h" +#include "helper.h" + + +/** + * Closure for #get_refunds_cb(). + */ +struct SelectRefundContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_RefundCoinCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Set to #GNUNET_SYSERR on error. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct SelectRefundContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +get_refunds_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct SelectRefundContext *srctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = srctx->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_Amount amount_with_fee; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &amount_with_fee), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + srctx->status = GNUNET_SYSERR; + return; + } + if (GNUNET_OK != + srctx->cb (srctx->cb_cls, + &amount_with_fee)) + return; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_refunds_by_coin ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_PrivateContractHashP *h_contract, + TALER_EXCHANGEDB_RefundCoinCallback cb, + void *cb_cls) +{ + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_auto_from_type (h_contract), + GNUNET_PQ_query_param_end + }; + struct SelectRefundContext srctx = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + const char *query = "get_refunds_by_coin_and_contract"; + + PREPARE (pg, + query, + "SELECT" + " ref.amount_with_fee" + " FROM refunds ref" + " JOIN coin_deposits cdep" + " USING (coin_pub,batch_deposit_serial_id)" + " JOIN batch_deposits bdep" + " ON (ref.batch_deposit_serial_id = bdep.batch_deposit_serial_id)" + " WHERE ref.coin_pub=$1" + " AND bdep.merchant_pub=$2" + " AND bdep.h_contract_terms=$3;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + query, + params, + &get_refunds_cb, + &srctx); + if (GNUNET_SYSERR == srctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_reserve_close_info.c b/src/exchangedb/select_reserve_close_info.c @@ -0,0 +1,62 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file select_reserve_close_info.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_reserve_close_info.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_reserve_close_info ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_Amount *balance, + struct TALER_FullPayto *payto_uri) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_amount ("current_balance", + pg->currency, + balance), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri->full_payto), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "select_reserve_close_info", + "SELECT " + " r.current_balance" + ",wt.payto_uri" + " FROM reserves r" + " LEFT JOIN reserves_in ri" + " USING (reserve_pub)" + " LEFT JOIN wire_targets wt" + " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)" + " WHERE r.reserve_pub=$1;"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "select_reserve_close_info", + params, + rs); +} diff --git a/src/exchangedb/select_reserve_close_request_info.c b/src/exchangedb/select_reserve_close_request_info.c @@ -0,0 +1,73 @@ +/* + This file is part of TALER + 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 + 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/> + */ +/** + * @file select_reserve_close_request_info.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_reserve_close_request_info.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_reserve_close_request_info ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t rowid, + struct TALER_ReserveSignatureP *reserve_sig, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *close_balance, + struct TALER_Amount *close_fee, + struct TALER_FullPayto *payto_uri) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_uint64 (&rowid), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", + reserve_sig), + GNUNET_PQ_result_spec_timestamp ("request_timestamp", + request_timestamp), + TALER_PQ_result_spec_amount ("close_balance", + pg->currency, + close_balance), + TALER_PQ_result_spec_amount ("close_fee", + pg->currency, + close_fee), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri->full_payto), + GNUNET_PQ_result_spec_end + }; + + // FIXME: this SQL query is still complete nonsense! + PREPARE (pg, + "select_reserve_close_request_info", + "SELECT " + " r.current_balance" + ",wt.payto_uri" + " FROM reserves r" + " LEFT JOIN reserves_in ri" + " USING (reserve_pub)" + " WHERE r.reserve_pub=$1" + " AND r.row_id=$2;"); + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "select_reserve_close_request_info", + params, + rs); +} diff --git a/src/exchangedb/select_reserve_closed_above_serial_id.c b/src/exchangedb/select_reserve_closed_above_serial_id.c @@ -0,0 +1,172 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file select_reserve_closed_above_serial_id.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_reserve_closed_above_serial_id.h" +#include "helper.h" + +/** + * Closure for #reserve_closed_serial_helper_cb(). + */ +struct ReserveClosedSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_ReserveClosedCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin's context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct ReserveClosedSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +reserve_closed_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReserveClosedSerialContext *rcsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = rcsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_FullPayto receiver_account; + struct TALER_WireTransferIdentifierRawP wtid; + struct TALER_Amount amount_with_fee; + struct TALER_Amount closing_fee; + struct GNUNET_TIME_Timestamp execution_date; + uint64_t close_request_row; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("close_uuid", + &rowid), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + GNUNET_PQ_result_spec_timestamp ("execution_date", + &execution_date), + GNUNET_PQ_result_spec_auto_from_type ("wtid", + &wtid), + GNUNET_PQ_result_spec_string ("receiver_account", + &receiver_account.full_payto), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount_with_fee), + TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", + &closing_fee), + GNUNET_PQ_result_spec_uint64 ("close_request_row", + &close_request_row), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + rcsc->status = GNUNET_SYSERR; + return; + } + ret = rcsc->cb (rcsc->cb_cls, + rowid, + execution_date, + &amount_with_fee, + &closing_fee, + &reserve_pub, + receiver_account, + &wtid, + close_request_row); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_reserve_closed_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_ReserveClosedCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct ReserveClosedSerialContext rcsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE ( + pg, + "reserves_close_get_incr", + "SELECT" + " close_uuid" + ",reserves.reserve_pub" + ",execution_date" + ",wtid" + ",wt.payto_uri AS receiver_account" + ",amount" + ",closing_fee" + ",close_request_row" + " FROM reserves_close" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " JOIN reserves" + " USING (reserve_pub)" + " WHERE close_uuid>=$1" + " ORDER BY close_uuid ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "reserves_close_get_incr", + params, + &reserve_closed_serial_helper_cb, + &rcsc); + if (GNUNET_OK != rcsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_reserve_open_above_serial_id.c b/src/exchangedb/select_reserve_open_above_serial_id.c @@ -0,0 +1,163 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file select_reserve_open_above_serial_id.c + * @brief Low-level (statement-level) Postgres database access for the exchange + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_reserve_open_above_serial_id.h" +#include "helper.h" + + +/** + * Closure for #reserve_open_serial_helper_cb(). + */ +struct ReserveOpenSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_ReserveOpenCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin's context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct ReserveOpenSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +reserve_open_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReserveOpenSerialContext *rcsc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = rcsc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + uint32_t requested_purse_limit; + struct GNUNET_TIME_Timestamp request_timestamp; + struct GNUNET_TIME_Timestamp reserve_expiration; + struct TALER_Amount reserve_payment; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("open_request_uuid", + &rowid), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", + &reserve_sig), + GNUNET_PQ_result_spec_timestamp ("request_timestamp", + &request_timestamp), + GNUNET_PQ_result_spec_timestamp ("expiration_date", + &reserve_expiration), + GNUNET_PQ_result_spec_uint32 ("requested_purse_limit", + &requested_purse_limit), + TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_payment", + &reserve_payment), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + rcsc->status = GNUNET_SYSERR; + return; + } + ret = rcsc->cb (rcsc->cb_cls, + rowid, + &reserve_payment, + request_timestamp, + reserve_expiration, + requested_purse_limit, + &reserve_pub, + &reserve_sig); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_reserve_open_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_ReserveOpenCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct ReserveOpenSerialContext rcsc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE ( + pg, + "reserves_open_get_incr", + "SELECT" + " open_request_uuid" + ",reserve_pub" + ",request_timestamp" + ",expiration_date" + ",reserve_sig" + ",reserve_payment" + ",requested_purse_limit" + " FROM reserves_open_requests" + " WHERE open_request_uuid>=$1" + " ORDER BY open_request_uuid ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "reserves_open_get_incr", + params, + &reserve_open_serial_helper_cb, + &rcsc); + if (GNUNET_OK != rcsc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_reserves_in_above_serial_id.c b/src/exchangedb/select_reserves_in_above_serial_id.c @@ -0,0 +1,163 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_reserves_in_above_serial_id.c + * @brief Implementation of the select_reserves_in_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_reserves_in_above_serial_id.h" +#include "helper.h" + +/** + * Closure for #reserves_in_serial_helper_cb(). + */ +struct ReservesInSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_ReserveInCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct ReservesInSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +reserves_in_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReservesInSerialContext *risc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = risc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_Amount credit; + struct TALER_FullPayto sender_account_details; + struct GNUNET_TIME_Timestamp execution_date; + uint64_t rowid; + uint64_t wire_reference; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + GNUNET_PQ_result_spec_uint64 ("wire_reference", + &wire_reference), + TALER_PQ_RESULT_SPEC_AMOUNT ("credit", + &credit), + GNUNET_PQ_result_spec_timestamp ("execution_date", + &execution_date), + GNUNET_PQ_result_spec_string ("sender_account_details", + &sender_account_details.full_payto), + GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + risc->status = GNUNET_SYSERR; + return; + } + ret = risc->cb (risc->cb_cls, + rowid, + &reserve_pub, + &credit, + sender_account_details, + wire_reference, + execution_date); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_reserves_in_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_ReserveInCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct ReservesInSerialContext risc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_reserves_in_above_serial_id", + "SELECT" + " reserves.reserve_pub" + ",wire_reference" + ",credit" + ",execution_date" + ",wt.payto_uri AS sender_account_details" + ",reserve_in_serial_id" + " FROM reserves_in" + " JOIN reserves" + " USING (reserve_pub)" + " JOIN wire_targets wt" + " ON (wire_source_h_payto = wire_target_h_payto)" + " WHERE reserve_in_serial_id>=$1" + " ORDER BY reserve_in_serial_id;"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_reserves_in_above_serial_id", + params, + &reserves_in_serial_helper_cb, + &risc); + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + return qs; + if (GNUNET_OK != risc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_reserves_in_above_serial_id_by_account.c b/src/exchangedb/select_reserves_in_above_serial_id_by_account.c @@ -0,0 +1,166 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/select_reserves_in_above_serial_id_by_account.c + * @brief Implementation of the select_reserves_in_above_serial_id_by_account function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include \ + "taler/exchange-database/select_reserves_in_above_serial_id_by_account.h" +#include "helper.h" + + +/** + * Closure for #reserves_in_serial_helper_cb(). + */ +struct ReservesInSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_ReserveInCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct ReservesInSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +reserves_in_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReservesInSerialContext *risc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = risc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_Amount credit; + struct TALER_FullPayto sender_account_details; + struct GNUNET_TIME_Timestamp execution_date; + uint64_t rowid; + uint64_t wire_reference; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + GNUNET_PQ_result_spec_uint64 ("wire_reference", + &wire_reference), + TALER_PQ_RESULT_SPEC_AMOUNT ("credit", + &credit), + GNUNET_PQ_result_spec_timestamp ("execution_date", + &execution_date), + GNUNET_PQ_result_spec_string ("sender_account_details", + &sender_account_details.full_payto), + GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id", + &rowid), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + risc->status = GNUNET_SYSERR; + return; + } + ret = risc->cb (risc->cb_cls, + rowid, + &reserve_pub, + &credit, + sender_account_details, + wire_reference, + execution_date); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_select_reserves_in_above_serial_id_by_account ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *account_name, + uint64_t serial_id, + TALER_EXCHANGEDB_ReserveInCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_string (account_name), + GNUNET_PQ_query_param_end + }; + struct ReservesInSerialContext risc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_reserves_in_above_serial_id_by_account", + "SELECT" + " reserves.reserve_pub" + ",wire_reference" + ",credit" + ",execution_date" + ",wt.payto_uri AS sender_account_details" + ",reserve_in_serial_id" + " FROM reserves_in" + " JOIN reserves " + " USING (reserve_pub)" + " JOIN wire_targets wt" + " ON (wire_source_h_payto = wire_target_h_payto)" + " WHERE reserve_in_serial_id>=$1" + " AND exchange_account_section=$2" + " ORDER BY reserve_in_serial_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_reserves_in_above_serial_id_by_account", + params, + &reserves_in_serial_helper_cb, + &risc); + if (GNUNET_OK != risc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_wire_out_above_serial_id.c b/src/exchangedb/select_wire_out_above_serial_id.c @@ -0,0 +1,154 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/select_wire_out_above_serial_id.c + * @brief Implementation of the select_wire_out_above_serial_id function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_wire_out_above_serial_id.h" +#include "helper.h" + +/** + * Closure for #wire_out_serial_helper_cb(). + */ +struct WireOutSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_WireTransferOutCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + int status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct WireOutSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +wire_out_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct WireOutSerialContext *wosc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = wosc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + struct GNUNET_TIME_Timestamp date; + struct TALER_WireTransferIdentifierRawP wtid; + struct TALER_FullPayto payto_uri; + struct TALER_Amount amount; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("wireout_uuid", + &rowid), + GNUNET_PQ_result_spec_timestamp ("execution_date", + &date), + GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", + &wtid), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri.full_payto), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_end + }; + int ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + wosc->status = GNUNET_SYSERR; + return; + } + ret = wosc->cb (wosc->cb_cls, + rowid, + date, + &wtid, + payto_uri, + &amount); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_wire_out_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_WireTransferOutCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct WireOutSerialContext wosc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_wire_out_above_serial_id", + "SELECT" + " wo.wireout_uuid" + ",wo.execution_date" + ",wo.wtid_raw" + ",wt.payto_uri" + ",wo.amount" + " FROM wire_out wo" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " WHERE wireout_uuid>=$1" + " ORDER BY wireout_uuid ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_wire_out_above_serial_id", + params, + &wire_out_serial_helper_cb, + &wosc); + if (GNUNET_OK != wosc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_wire_out_above_serial_id_by_account.c b/src/exchangedb/select_wire_out_above_serial_id_by_account.c @@ -0,0 +1,157 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/select_wire_out_above_serial_id_by_account.c + * @brief Implementation of the select_wire_out_above_serial_id_by_account function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_wire_out_above_serial_id_by_account.h" +#include "helper.h" + +/** + * Closure for #wire_out_serial_helper_cb(). + */ +struct WireOutSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_WireTransferOutCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + int status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct WireOutSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +wire_out_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct WireOutSerialContext *wosc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = wosc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + struct GNUNET_TIME_Timestamp date; + struct TALER_WireTransferIdentifierRawP wtid; + struct TALER_FullPayto payto_uri; + struct TALER_Amount amount; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("wireout_uuid", + &rowid), + GNUNET_PQ_result_spec_timestamp ("execution_date", + &date), + GNUNET_PQ_result_spec_auto_from_type ("wtid_raw", + &wtid), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri.full_payto), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_end + }; + int ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + wosc->status = GNUNET_SYSERR; + return; + } + ret = wosc->cb (wosc->cb_cls, + rowid, + date, + &wtid, + payto_uri, + &amount); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_TALER_EXCHANGEDB_select_wire_out_above_serial_id_by_account ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *account_name, + uint64_t serial_id, + TALER_EXCHANGEDB_WireTransferOutCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_string (account_name), + GNUNET_PQ_query_param_end + }; + struct WireOutSerialContext wosc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_wire_out_above_serial_id_by_account", + "SELECT" + " wo.wireout_uuid" + ",wo.execution_date" + ",wo.wtid_raw" + ",wt.payto_uri" + ",wo.amount" + " FROM wire_out wo" + " JOIN wire_targets wt" + " USING (wire_target_h_payto)" + " WHERE wo.wireout_uuid>=$1 " + " AND wo.exchange_account_section=$2" + " ORDER BY wo.wireout_uuid ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_wire_out_above_serial_id_by_account", + params, + &wire_out_serial_helper_cb, + &wosc); + if (GNUNET_OK != wosc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_withdraw_amounts_for_kyc_check.c b/src/exchangedb/select_withdraw_amounts_for_kyc_check.c @@ -0,0 +1,158 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/select_withdraw_amounts_for_kyc_check.c + * @brief Implementation of the select_withdraw_amounts_for_kyc_check function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_withdraw_amounts_for_kyc_check.h" +#include "taler/exchange-database/select_aggregation_amounts_for_kyc_check.h" +#include "helper.h" + + +/** + * Closure for #get_kyc_amounts_cb(). + */ +struct KycAmountCheckContext +{ + /** + * Function to call per result. + */ + TALER_KYCLOGIC_KycAmountCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Flag set to #GNUNET_OK as long as everything is fine. + */ + enum GNUNET_GenericReturnValue status; + +}; + +/** + * Invoke the callback for each result. + * + * @param cls a `struct KycAmountCheckContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_kyc_amounts_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct KycAmountCheckContext *ctx = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg; + + for (unsigned int i = 0; i < num_results; i++) + { + struct GNUNET_TIME_Absolute date; + struct TALER_Amount amount; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("amount", + &amount), + GNUNET_PQ_result_spec_absolute_time ("date", + &date), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->status = GNUNET_SYSERR; + return; + } + ret = ctx->cb (ctx->cb_cls, + &amount, + date); + GNUNET_PQ_cleanup_result (rs); + switch (ret) + { + case GNUNET_OK: + continue; + case GNUNET_NO: + break; + case GNUNET_SYSERR: + ctx->status = GNUNET_SYSERR; + break; + } + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_withdraw_amounts_for_kyc_check ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_KYCLOGIC_KycAmountCallback kac, + void *kac_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_absolute_time (&time_limit), + GNUNET_PQ_query_param_end + }; + struct KycAmountCheckContext ctx = { + .cb = kac, + .cb_cls = kac_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "select_withdraw_amounts_for_kyc_check", + "SELECT" + " wd.amount_with_fee AS amount" + ",wd.execution_date AS date" + " FROM reserves_in ri" + " JOIN reserve_history rh" + " ON (rh.reserve_pub = ri.reserve_pub)" + " JOIN withdraw wd" + " ON (wd.withdraw_id = rh.serial_id)" + " WHERE ri.wire_source_h_payto IN (" + " SELECT wire_target_h_payto" + " FROM wire_targets" + " WHERE h_normalized_payto=$1" + " )" + " AND rh.table_name='withdraw'" + " AND wd.execution_date >= $2" + " ORDER BY rh.reserve_history_serial_id DESC"); + qs = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "select_withdraw_amounts_for_kyc_check", + params, + &get_kyc_amounts_cb, + &ctx); + if (GNUNET_OK != ctx.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/select_withdrawals_above_serial_id.c b/src/exchangedb/select_withdrawals_above_serial_id.c @@ -0,0 +1,212 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/select_withdrawals_above_serial_id.c + * @brief Implementation of the select_withdrawals_above_serial_id function for Postgres + * @author Christian Grothoff + * @author Özgür Kesim + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/select_withdrawals_above_serial_id.h" +#include "helper.h" + +/** + * Closure for #withdraw_serial_helper_cb(). + */ +struct WithdrawSerialContext +{ + + /** + * Callback to call. + */ + TALER_EXCHANGEDB_WithdrawCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Plugin context. + */ + struct TALER_EXCHANGEDB_PostgresContext *pg; + + /** + * Status code, set to #GNUNET_SYSERR on hard errors. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Helper function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct WithdrawSerialContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +withdraw_serial_helper_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct WithdrawSerialContext *rosc = cls; + struct TALER_EXCHANGEDB_PostgresContext *pg = rosc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t rowid; + struct TALER_HashBlindedPlanchetsP h_planchets; + struct GNUNET_TIME_Timestamp execution_date; + struct TALER_Amount amount_with_fee; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + uint16_t max_age; + bool no_max_age; + uint16_t noreveal_index; + bool no_noreveal_index; + struct TALER_HashBlindedPlanchetsP selected_h; + bool no_selected_h; + struct TALER_BlindingMasterSeedP blinding_seed; + bool no_blinding_seed; + size_t num_denom_serials; + uint64_t *denom_serials = NULL; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("withdraw_id", + &rowid), + GNUNET_PQ_result_spec_auto_from_type ("planchets_h", + &h_planchets), + GNUNET_PQ_result_spec_timestamp ("execution_date", + &execution_date), + TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", + &amount_with_fee), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", + &reserve_sig), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint16 ("max_age", + &max_age), + &no_max_age), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint16 ("noreveal_index", + &noreveal_index), + &no_noreveal_index), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ( + "selected_h", + &selected_h), + &no_selected_h), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_auto_from_type ( + "blinding_seed", + &blinding_seed), + &no_blinding_seed), + GNUNET_PQ_result_spec_array_uint64 ( + pg->conn, + "denom_serials", + &num_denom_serials, + &denom_serials), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + rosc->status = GNUNET_SYSERR; + GNUNET_PQ_cleanup_result (rs); + return; + } + if ((! no_max_age) && + ((255 <= noreveal_index) || (255 <= max_age))) + { + GNUNET_break (0); + rosc->status = GNUNET_SYSERR; + GNUNET_PQ_cleanup_result (rs); + return; + } + ret = rosc->cb (rosc->cb_cls, + rowid, + num_denom_serials, + denom_serials, + no_selected_h ? NULL : &selected_h, + &h_planchets, + no_blinding_seed ? NULL : &blinding_seed, + ! no_max_age, + (uint8_t) max_age, + (uint8_t) noreveal_index, + &reserve_pub, + &reserve_sig, + execution_date, + &amount_with_fee); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_select_withdrawals_above_serial_id ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t serial_id, + TALER_EXCHANGEDB_WithdrawCallback cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&serial_id), + GNUNET_PQ_query_param_end + }; + struct WithdrawSerialContext rosc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + /* Fetch deposits with rowid '\geq' the given parameter */ + PREPARE (pg, + "audit_get_withdraw_incr", + "SELECT" + " withdraw_id" + ",planchets_h" + ",execution_date" + ",amount_with_fee" + ",reserve_pub" + ",reserve_sig" + ",max_age" + ",noreveal_index" + ",selected_h" + ",blinding_seed" + ",denom_serials" + " FROM withdraw" + " WHERE withdraw_id>=$1" + " ORDER BY withdraw_id ASC;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "audit_get_withdraw_incr", + params, + &withdraw_serial_helper_cb, + &rosc); + if (GNUNET_OK != rosc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/set_aml_lock.c b/src/exchangedb/set_aml_lock.c @@ -0,0 +1,70 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/set_aml_lock.c + * @brief Implementation of the set_aml_lock function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/set_aml_lock.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_set_aml_lock ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_NormalizedPaytoHashP *h_payto, + struct GNUNET_TIME_Relative lock_duration, + struct GNUNET_TIME_Absolute *existing_lock) +{ + + struct GNUNET_TIME_Absolute expires + = GNUNET_TIME_relative_to_absolute (lock_duration); + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_absolute_time (&expires), + GNUNET_PQ_query_param_end + }; + bool nx; /* true if the *account* is not known */ + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_absolute_time ("out_aml_program_lock_timeout", + existing_lock), + &nx), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "set_aml_lock", + "SELECT out_aml_program_lock_timeout" + " FROM exchange_do_set_aml_lock($1,$2,$3);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "set_aml_lock", + params, + rs); + if (qs <= 0) + return qs; + if (nx) + { + *existing_lock = GNUNET_TIME_UNIT_ZERO_ABS; + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + return qs; +} diff --git a/src/exchangedb/set_extension_manifest.c b/src/exchangedb/set_extension_manifest.c @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/set_extension_manifest.c + * @brief Implementation of the set_extension_manifest function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/set_extension_manifest.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_set_extension_manifest (struct + TALER_EXCHANGEDB_PostgresContext *pg, + const char *extension_name, + const char *manifest) +{ + struct GNUNET_PQ_QueryParam pcfg = + (NULL == manifest || 0 == *manifest) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (manifest); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (extension_name), + pcfg, + GNUNET_PQ_query_param_end + }; + + + PREPARE (pg, + "set_extension_manifest", + "INSERT INTO extensions (name, manifest) VALUES ($1, $2) " + "ON CONFLICT (name) " + "DO UPDATE SET manifest=$2"); + + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "set_extension_manifest", + params); +} diff --git a/src/exchangedb/set_purse_balance.c b/src/exchangedb/set_purse_balance.c @@ -0,0 +1,48 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/set_purse_balance.c + * @brief Implementation of the set_purse_balance function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/set_purse_balance.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_set_purse_balance ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (purse_pub), + TALER_PQ_query_param_amount (pg->conn, + balance), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "set_purse_balance", + "UPDATE purse_requests" + " SET balance=$2" + " WHERE purse_pub=$1;"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "set_purse_balance", + params); +} diff --git a/src/exchangedb/start.c b/src/exchangedb/start.c @@ -0,0 +1,51 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/start.c + * @brief Implementation of the start function for Postgres + * @author Christian Grothoff + */ +#include "taler/exchange-database/preflight.h" +#include "taler/exchange-database/start.h" +#include "helper.h" + +enum GNUNET_GenericReturnValue +TALER_EXCHANGEDB_start (struct TALER_EXCHANGEDB_PostgresContext *pg, + const char *name) +{ + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL SERIALIZABLE"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + GNUNET_assert (NULL != name); + if (GNUNET_SYSERR == + TALER_EXCHANGEDB_preflight (pg)) + return GNUNET_SYSERR; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Starting transaction `%s'\n", + name); + if (GNUNET_OK != + GNUNET_PQ_exec_statements (pg->conn, + es)) + { + TALER_LOG_ERROR ("Failed to start transaction\n"); + GNUNET_break (0); + return GNUNET_SYSERR; + } + pg->transaction_name = name; + return GNUNET_OK; +} diff --git a/src/exchangedb/start_deferred_wire_out.c b/src/exchangedb/start_deferred_wire_out.c @@ -0,0 +1,56 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/start_deferred_wire_out.c + * @brief Implementation of the start_deferred_wire_out function for Postgres + * @author Christian Grothoff + */ +#include "taler/exchange-database/start_deferred_wire_out.h" +#include "helper.h" +#include "taler/exchange-database/preflight.h" +#include "taler/exchange-database/rollback.h" + +enum GNUNET_GenericReturnValue +TALER_TALER_EXCHANGEDB_start_deferred_wire_out (struct + TALER_EXCHANGEDB_PostgresContext + *pg) +{ + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_execute ( + "START TRANSACTION ISOLATION LEVEL READ COMMITTED;"), + GNUNET_PQ_make_execute ("SET CONSTRAINTS ALL DEFERRED;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + if (GNUNET_SYSERR == + TALER_EXCHANGEDB_preflight (pg)) + return GNUNET_SYSERR; + if (GNUNET_OK != + GNUNET_PQ_exec_statements (pg->conn, + es)) + { + TALER_LOG_ERROR ( + "Failed to defer wire_out_ref constraint on transaction\n"); + GNUNET_break (0); + TALER_EXCHANGEDB_rollback (pg); + return GNUNET_SYSERR; + } + pg->transaction_name = "deferred wire out"; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Starting READ COMMITTED DEFERRED transaction `%s'\n", + pg->transaction_name); + return GNUNET_OK; +} diff --git a/src/exchangedb/start_read_committed.c b/src/exchangedb/start_read_committed.c @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/start_read_committed.c + * @brief Implementation of the start_read_committed function for Postgres + * @author Christian Grothoff + */ +#include "taler/exchange-database/start_read_committed.h" +#include "taler/exchange-database/preflight.h" +#include "helper.h" + +enum GNUNET_GenericReturnValue +TALER_TALER_EXCHANGEDB_start_read_committed (struct + TALER_EXCHANGEDB_PostgresContext * + pg, + const char *name) +{ + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL READ COMMITTED"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + GNUNET_assert (NULL != name); + if (GNUNET_SYSERR == + TALER_EXCHANGEDB_preflight (pg)) + return GNUNET_SYSERR; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Starting READ COMMITTED transaction `%s`\n", + name); + if (GNUNET_OK != + GNUNET_PQ_exec_statements (pg->conn, + es)) + { + TALER_LOG_ERROR ("Failed to start transaction\n"); + GNUNET_break (0); + return GNUNET_SYSERR; + } + pg->transaction_name = name; + return GNUNET_OK; +} diff --git a/src/exchangedb/start_read_only.c b/src/exchangedb/start_read_only.c @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/start_read_only.c + * @brief Implementation of the start_read_only function for Postgres + * @author Christian Grothoff + */ +#include "taler/exchange-database/start_read_only.h" +#include "taler/exchange-database/preflight.h" +#include "helper.h" + +enum GNUNET_GenericReturnValue +TALER_TALER_EXCHANGEDB_start_read_only (struct + TALER_EXCHANGEDB_PostgresContext *pg, + const char *name) +{ + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_execute ( + "START TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + GNUNET_assert (NULL != name); + if (GNUNET_SYSERR == + TALER_EXCHANGEDB_preflight (pg)) + return GNUNET_SYSERR; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Starting READ ONLY transaction `%s`\n", + name); + if (GNUNET_OK != + GNUNET_PQ_exec_statements (pg->conn, + es)) + { + TALER_LOG_ERROR ("Failed to start transaction\n"); + GNUNET_break (0); + return GNUNET_SYSERR; + } + pg->transaction_name = name; + return GNUNET_OK; +} diff --git a/src/exchangedb/store_wire_transfer_out.c b/src/exchangedb/store_wire_transfer_out.c @@ -0,0 +1,63 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/store_wire_transfer_out.c + * @brief Implementation of the store_wire_transfer_out function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/store_wire_transfer_out.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_store_wire_transfer_out ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + struct GNUNET_TIME_Timestamp date, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_FullPaytoHashP *h_payto, + const char *exchange_account_section, + const struct TALER_Amount *amount, + const char *extra_wire_subject_metadata) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_timestamp (&date), + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_string (exchange_account_section), + TALER_PQ_query_param_amount (pg->conn, + amount), + NULL == extra_wire_subject_metadata + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (extra_wire_subject_metadata), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_wire_out", + "INSERT INTO wire_out " + "(execution_date" + ",wtid_raw" + ",wire_target_h_payto" + ",exchange_account_section" + ",amount" + ",extra_wire_subject_metadata" + ") VALUES " + "($1, $2, $3, $4, $5, $6);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_wire_out", + params); +} diff --git a/src/exchangedb/template.c b/src/exchangedb/template.c @@ -0,0 +1,20 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/> + */ +/** + * @file exchangedb/template.c + * @brief Implementation of the template function for Postgres + * @author Christian Grothoff + */ diff --git a/src/exchangedb/pg_template.sh b/src/exchangedb/template.sh diff --git a/src/exchangedb/test_aml_officer.c b/src/exchangedb/test_aml_officer.c @@ -0,0 +1,52 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/test_aml_officer.c + * @brief Implementation of the test_aml_officer function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/test_aml_officer.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_test_aml_officer ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + bool *read_only) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (decider_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("read_only", + read_only), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "test_aml_staff", + "SELECT read_only" + " FROM aml_staff" + " WHERE decider_pub=$1" + " AND is_active;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "test_aml_staff", + params, + rs); +} diff --git a/src/exchangedb/trigger_kyc_rule_for_account.c b/src/exchangedb/trigger_kyc_rule_for_account.c @@ -0,0 +1,98 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/trigger_kyc_rule_for_account.c + * @brief Implementation of the trigger_kyc_rule_for_account function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/trigger_kyc_rule_for_account.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_trigger_kyc_rule_for_account ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_FullPayto payto_uri, + const struct TALER_NormalizedPaytoHashP *h_payto, + const union TALER_AccountPublicKeyP *set_account_pub, + const struct TALER_MerchantPublicKeyP *check_merchant_pub, + const json_t *jmeasures, + uint32_t display_priority, + uint64_t *requirement_row, + bool *bad_kyc_auth) +{ + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + struct TALER_EXCHANGEDB_KycCompletedEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), + .h_payto = *h_payto + }; + char *notify_str + = GNUNET_PQ_get_event_notify_channel (&rep.header); + struct TALER_FullPaytoHashP h_full_payto; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + NULL == set_account_pub + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (set_account_pub), + NULL == check_merchant_pub + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (check_merchant_pub), + NULL == payto_uri.full_payto + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (payto_uri.full_payto), + NULL == payto_uri.full_payto + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (&h_full_payto), + GNUNET_PQ_query_param_absolute_time (&now), + TALER_PQ_query_param_json (jmeasures), + GNUNET_PQ_query_param_uint32 (&display_priority), + GNUNET_PQ_query_param_string (notify_str), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ( + "legitimization_measure_serial_id", + requirement_row), + GNUNET_PQ_result_spec_bool ( + "bad_kyc_auth", + bad_kyc_auth), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "trigger_kyc_rule_for_account", + "SELECT" + " out_legitimization_measure_serial_id" + " AS legitimization_measure_serial_id" + " ,out_bad_kyc_auth" + " AS bad_kyc_auth" + " FROM exchange_do_trigger_kyc_rule_for_account" + "($1, $2, $3, $4, $5, $6, $7::TEXT::JSONB, $8, $9);"); + if (NULL != payto_uri.full_payto) + TALER_full_payto_hash (payto_uri, + &h_full_payto); + qs = GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "trigger_kyc_rule_for_account", + params, + rs); + GNUNET_free (notify_str); + return qs; +} diff --git a/src/exchangedb/update_aggregation_transient.c b/src/exchangedb/update_aggregation_transient.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/update_aggregation_transient.c + * @brief Implementation of the update_aggregation_transient function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/update_aggregation_transient.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_update_aggregation_transient ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_FullPaytoHashP *h_payto, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, + const struct TALER_Amount *total) +{ + struct GNUNET_PQ_QueryParam params[] = { + TALER_PQ_query_param_amount (pg->conn, + total), + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_uint64 (&kyc_requirement_row), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "update_aggregation_transient", + "UPDATE aggregation_transient" + " SET amount=$1" + " ,legitimization_requirement_serial_id=$4" + " WHERE wire_target_h_payto=$2" + " AND wtid_raw=$3"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_aggregation_transient", + params); +} diff --git a/src/exchangedb/update_auditor.c b/src/exchangedb/update_auditor.c @@ -0,0 +1,56 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/update_auditor.c + * @brief Implementation of the update_auditor function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/update_auditor.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_update_auditor (struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_AuditorPublicKeyP * + auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp change_date, + bool enabled) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (auditor_pub), + GNUNET_PQ_query_param_string (auditor_url), + GNUNET_PQ_query_param_string (auditor_name), + GNUNET_PQ_query_param_bool (enabled), + GNUNET_PQ_query_param_timestamp (&change_date), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "update_auditor", + "UPDATE auditors" + " SET" + " auditor_url=$2" + " ,auditor_name=$3" + " ,is_active=$4" + " ,last_change=$5" + " WHERE auditor_pub=$1"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_auditor", + params); +} diff --git a/src/exchangedb/update_kyc_process_by_row.c b/src/exchangedb/update_kyc_process_by_row.c @@ -0,0 +1,131 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2024 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/> + */ +/** + * @file exchangedb/update_kyc_process_by_row.c + * @brief Implementation of the update_kyc_process_by_row function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_error_codes.h" +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/update_kyc_process_by_row.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_update_kyc_process_by_row ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t process_row, + const char *provider_name, + const struct TALER_NormalizedPaytoHashP *h_payto, + const char *provider_account_id, + const char *provider_legitimization_id, + const char *redirect_url, + struct GNUNET_TIME_Absolute expiration, + enum TALER_ErrorCode ec, + const char *error_message_hint, + bool finished) +{ + uint32_t ec32 = (uint32_t) ec; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&process_row), + GNUNET_PQ_query_param_string (provider_name), + GNUNET_PQ_query_param_auto_from_type (h_payto), /*3*/ + (NULL != provider_account_id) + ? GNUNET_PQ_query_param_string (provider_account_id) + : GNUNET_PQ_query_param_null (), /*4*/ + (NULL != provider_legitimization_id) + ? GNUNET_PQ_query_param_string (provider_legitimization_id) + : GNUNET_PQ_query_param_null (), /*5*/ + (NULL != redirect_url) + ? GNUNET_PQ_query_param_string (redirect_url) + : GNUNET_PQ_query_param_null (), /*6*/ + GNUNET_PQ_query_param_absolute_time (&expiration), + GNUNET_PQ_query_param_uint32 (&ec32), /* 8 */ + (NULL != error_message_hint) + ? GNUNET_PQ_query_param_string (error_message_hint) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_bool (finished), /* 10 */ + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Updating KYC data for %llu (%s)\n", + (unsigned long long) process_row, + provider_name); + PREPARE (pg, + "update_legitimization_process", + "UPDATE legitimization_processes" + " SET provider_user_id=$4" + " ,provider_legitimization_id=$5" + " ,redirect_url=$6" + " ,expiration_time=GREATEST(expiration_time,$7)" + " ,error_code=$8" + " ,error_message=$9" + " ,finished=$10" + " WHERE" + " h_payto=$3" + " AND legitimization_process_serial_id=$1" + " AND provider_name=$2;"); + qs = GNUNET_PQ_eval_prepared_non_select ( + pg->conn, + "update_legitimization_process", + params); + if (qs <= 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to update legitimization process %llu: %d\n", + (unsigned long long) process_row, + qs); + return qs; + } + if (GNUNET_TIME_absolute_is_future (expiration)) + { + enum GNUNET_DB_QueryStatus qs2; + struct TALER_EXCHANGEDB_KycCompletedEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED), + .h_payto = *h_payto + }; + uint32_t trigger_type = 1; + struct GNUNET_PQ_QueryParam params2[] = { + GNUNET_PQ_query_param_auto_from_type (h_payto), + GNUNET_PQ_query_param_uint32 (&trigger_type), + GNUNET_PQ_query_param_end + }; + + GNUNET_PQ_event_notify (pg->conn, + &rep.header, + NULL, + 0); + PREPARE (pg, + "alert_kyc_status_change", + "INSERT INTO kyc_alerts" + " (h_payto" + " ,trigger_type)" + " VALUES" + " ($1,$2);"); + qs2 = GNUNET_PQ_eval_prepared_non_select ( + pg->conn, + "alert_kyc_status_change", + params2); + if (qs2 < 0) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to store KYC alert: %d\n", + qs2); + } + return qs; +} diff --git a/src/exchangedb/update_wire.c b/src/exchangedb/update_wire.c @@ -0,0 +1,88 @@ +/* + This file is part of TALER + Copyright (C) 2022, 2023, 2024 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/> + */ +/** + * @file exchangedb/update_wire.c + * @brief Implementation of the update_wire function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/update_wire.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_update_wire ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_FullPayto payto_uri, + const char *conversion_url, + const char *open_banking_gateway, + const char *wire_transfer_gateway, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + struct GNUNET_TIME_Timestamp change_date, + const struct TALER_MasterSignatureP *master_sig, + const char *bank_label, + int64_t priority, + bool enabled) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (payto_uri.full_payto), + GNUNET_PQ_query_param_bool (enabled), + NULL == conversion_url + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (conversion_url), + enabled + ? TALER_PQ_query_param_json (debit_restrictions) + : GNUNET_PQ_query_param_null (), + enabled + ? TALER_PQ_query_param_json (credit_restrictions) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_timestamp (&change_date), + NULL == master_sig + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_auto_from_type (master_sig), + NULL == bank_label + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (bank_label), + GNUNET_PQ_query_param_int64 (&priority), + NULL == open_banking_gateway + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (open_banking_gateway), + NULL == wire_transfer_gateway + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (wire_transfer_gateway), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "update_wire", + "UPDATE wire_accounts" + " SET" + " is_active=$2" + " ,conversion_url=$3" + " ,debit_restrictions=$4::TEXT::JSONB" + " ,credit_restrictions=$5::TEXT::JSONB" + " ,last_change=$6" + " ,master_sig=$7" + " ,bank_label=$8" + " ,priority=$9" + " ,open_banking_gateway=$10" + " ,wire_transfer_gateway=$11" + " WHERE payto_uri=$1"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_wire", + params); +} diff --git a/src/exchangedb/wad_in_insert.c b/src/exchangedb/wad_in_insert.c @@ -0,0 +1,58 @@ +/* + This file is part of TALER + Copyright (C) 2024 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/> + */ +/** + * @file exchangedb/wad_in_insert.c + * @brief Implementation of the wad_in_insert function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/wad_in_insert.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_wad_in_insert ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + const struct TALER_WadIdentifierP *wad_id, + const char *origin_exchange_url, + const struct TALER_Amount *amount, + struct GNUNET_TIME_Timestamp execution_date, + const struct TALER_FullPayto debit_account_uri, + const char *section_name, + uint64_t serial_id) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (wad_id), + GNUNET_PQ_query_param_string (origin_exchange_url), + TALER_PQ_query_param_amount (pg->conn, + amount), + GNUNET_PQ_query_param_timestamp (&execution_date), + GNUNET_PQ_query_param_end + }; + + // FIXME-#7271: should we keep the account data + serial_id? + PREPARE (pg, + "wad_in_insert", + "INSERT INTO wads_in " + "(wad_id" + ",origin_exchange_url" + ",amount" + ",arrival_time" + ") VALUES " + "($1, $2, $3, $4);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "wad_in_insert", + params); +} diff --git a/src/exchangedb/wire_prepare_data_get.c b/src/exchangedb/wire_prepare_data_get.c @@ -0,0 +1,138 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/wire_prepare_data_get.c + * @brief Implementation of the wire_prepare_data_get function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/wire_prepare_data_get.h" +#include "helper.h" + +/** + * Closure for #prewire_cb(). + */ +struct PrewireContext +{ + /** + * Function to call on each result. + */ + TALER_EXCHANGEDB_WirePreparationIterator cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * #GNUNET_OK if everything went fine. + */ + enum GNUNET_GenericReturnValue status; +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct MissingWireContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +prewire_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct PrewireContext *pc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + uint64_t prewire_uuid; + char *wire_method; + void *buf = NULL; + size_t buf_size; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("prewire_uuid", + &prewire_uuid), + GNUNET_PQ_result_spec_string ("wire_method", + &wire_method), + GNUNET_PQ_result_spec_variable_size ("buf", + &buf, + &buf_size), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + pc->status = GNUNET_SYSERR; + return; + } + pc->cb (pc->cb_cls, + prewire_uuid, + wire_method, + buf, + buf_size); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_wire_prepare_data_get (struct + TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t start_row, + uint64_t limit, + TALER_EXCHANGEDB_WirePreparationIterator + cb, + void *cb_cls) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&start_row), + GNUNET_PQ_query_param_uint64 (&limit), + GNUNET_PQ_query_param_end + }; + struct PrewireContext pc = { + .cb = cb, + .cb_cls = cb_cls, + .status = GNUNET_OK + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "wire_prepare_data_get", + "SELECT" + " prewire_uuid" + ",wire_method" + ",buf" + " FROM prewire" + " WHERE prewire_uuid >= $1" + " AND finished=FALSE" + " AND failed=FALSE" + " ORDER BY prewire_uuid ASC" + " LIMIT $2;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "wire_prepare_data_get", + params, + &prewire_cb, + &pc); + if (GNUNET_OK != pc.status) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/exchangedb/wire_prepare_data_insert.c b/src/exchangedb/wire_prepare_data_insert.c @@ -0,0 +1,51 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/wire_prepare_data_insert.c + * @brief Implementation of the wire_prepare_data_insert function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/wire_prepare_data_insert.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_wire_prepare_data_insert (struct + TALER_EXCHANGEDB_PostgresContext *pg, + const char *type, + const char *buf, + size_t buf_size) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (type), + GNUNET_PQ_query_param_fixed_size (buf, buf_size), + GNUNET_PQ_query_param_end + }; + + + /* Used in #postgres_wire_prepare_data_insert() to store + wire transfer information before actually committing it with the bank */ + PREPARE (pg, + "wire_prepare_data_insert", + "INSERT INTO prewire " + "(wire_method" + ",buf" + ") VALUES " + "($1, $2);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "wire_prepare_data_insert", + params); +} diff --git a/src/exchangedb/wire_prepare_data_mark_failed.c b/src/exchangedb/wire_prepare_data_mark_failed.c @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/wire_prepare_data_mark_failed.c + * @brief Implementation of the wire_prepare_data_mark_failed function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/wire_prepare_data_mark_failed.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_wire_prepare_data_mark_failed ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t rowid) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&rowid), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "wire_prepare_data_mark_failed", + "UPDATE prewire" + " SET failed=TRUE" + " WHERE prewire_uuid=$1;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "wire_prepare_data_mark_failed", + params); +} diff --git a/src/exchangedb/wire_prepare_data_mark_finished.c b/src/exchangedb/wire_prepare_data_mark_finished.c @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 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/> + */ +/** + * @file exchangedb/wire_prepare_data_mark_finished.c + * @brief Implementation of the wire_prepare_data_mark_finished function for Postgres + * @author Christian Grothoff + */ +#include "taler/taler_pq_lib.h" +#include "taler/exchange-database/wire_prepare_data_mark_finished.h" +#include "helper.h" + +enum GNUNET_DB_QueryStatus +TALER_EXCHANGEDB_wire_prepare_data_mark_finished ( + struct TALER_EXCHANGEDB_PostgresContext *pg, + uint64_t rowid) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&rowid), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "wire_prepare_data_mark_done", + "UPDATE prewire" + " SET finished=TRUE" + " WHERE prewire_uuid=$1;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "wire_prepare_data_mark_done", + params); +}