libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit d986d1c90011d18b35f5d6d3538cd19f49de4cbd
parent 267f85053f44a89d1481df27891e23e05d95d60e
Author: Antoine A <>
Date:   Thu,  9 Jul 2026 08:51:00 +0200

common: fix prepared transfer db procedure

Diffstat:
MCargo.lock | 42+++++++++++++++++++++---------------------
Mdatabase-versioning/libeufin-bank-procedures.sql | 2+-
Mdatabase-versioning/libeufin-nexus-procedures.sql | 44++++++++++++++++++++++----------------------
3 files changed, 44 insertions(+), 44 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -358,9 +358,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "calamine" @@ -1360,7 +1360,7 @@ dependencies = [ [[package]] name = "http-client" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#425313290a4ed284a97b430a9ada4f0ac5990264" +source = "git+git://git.taler.net/taler-rust.git/#4019ab323771ee02486072b50adb13b5836c8f6b" dependencies = [ "compact_str", "futures-util", @@ -1653,9 +1653,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccfe6121cbe750cf81efa362d85c0bde7ea298ec43092d3a193baca59cdbd634" +checksum = "961d16382652bfdd8c6f68b223b26a8c93e0d475c672f414411db31c6c5c900e" dependencies = [ "defmt", "jiff-static", @@ -1667,9 +1667,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e165e897f662d428f3cd3828a919dbe067c2d42bb1031eede74ef9d27ecdedd2" +checksum = "d0879bd39df99c4c5e2c6615ccc026391a423dde10532c573e6086eb94a802cc" dependencies = [ "proc-macro2", "quote", @@ -2006,9 +2006,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "mimalloc" @@ -2154,11 +2154,10 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -3452,7 +3451,7 @@ dependencies = [ [[package]] name = "taler-api" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#425313290a4ed284a97b430a9ada4f0ac5990264" +source = "git+git://git.taler.net/taler-rust.git/#4019ab323771ee02486072b50adb13b5836c8f6b" dependencies = [ "aws-lc-rs", "axum", @@ -3479,12 +3478,12 @@ dependencies = [ [[package]] name = "taler-build" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#425313290a4ed284a97b430a9ada4f0ac5990264" +source = "git+git://git.taler.net/taler-rust.git/#4019ab323771ee02486072b50adb13b5836c8f6b" [[package]] name = "taler-common" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#425313290a4ed284a97b430a9ada4f0ac5990264" +source = "git+git://git.taler.net/taler-rust.git/#4019ab323771ee02486072b50adb13b5836c8f6b" dependencies = [ "anyhow", "aws-lc-rs", @@ -3514,7 +3513,7 @@ dependencies = [ [[package]] name = "taler-macros" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#425313290a4ed284a97b430a9ada4f0ac5990264" +source = "git+git://git.taler.net/taler-rust.git/#4019ab323771ee02486072b50adb13b5836c8f6b" dependencies = [ "proc-macro2", "quote", @@ -3524,7 +3523,7 @@ dependencies = [ [[package]] name = "taler-test-utils" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#425313290a4ed284a97b430a9ada4f0ac5990264" +source = "git+git://git.taler.net/taler-rust.git/#4019ab323771ee02486072b50adb13b5836c8f6b" dependencies = [ "aws-lc-rs", "axum", @@ -3533,6 +3532,7 @@ dependencies = [ "http-body-util", "jiff", "nu-ansi-term", + "pretty_assertions", "reedline", "serde", "serde_json", @@ -4541,18 +4541,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.53" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75726053136156d419e285b9b7eddaaea9e3fea6ce32eed44a89901f0bd98de1" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.53" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4714fd92cf900833d49538023a9b3915155210801d1c1169eba513b2addefd71" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" dependencies = [ "proc-macro2", "quote", diff --git a/database-versioning/libeufin-bank-procedures.sql b/database-versioning/libeufin-bank-procedures.sql @@ -1,6 +1,6 @@ -- -- This file is part of TALER --- Copyright (C) 2023, 2024, 2025, 2026 Taler Systems SA +-- Copyright (C) 2023-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 diff --git a/database-versioning/libeufin-nexus-procedures.sql b/database-versioning/libeufin-nexus-procedures.sql @@ -1,6 +1,6 @@ -- -- This file is part of TALER --- Copyright (C) 2023, 2024, 2025, 2026 Taler Systems SA +-- Copyright (C) 2023-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 @@ -113,7 +113,7 @@ BEGIN -- Check if already registered SELECT outgoing_transaction_id, subject, credit_payto, (amount).val, (amount).frac, wtid, exchange_base_url, metadata - INTO out_tx_id, local_subject, local_credit_payto, local_amount.val, local_amount.frac, + INTO out_tx_id, local_subject, local_credit_payto, local_amount.val, local_amount.frac, local_wtid, local_exchange_base_url, local_metadata FROM outgoing_transactions LEFT JOIN talerable_outgoing_transactions USING (outgoing_transaction_id) WHERE end_to_end_id = in_end_to_end_id OR acct_svcr_ref = in_acct_svcr_ref; @@ -144,7 +144,7 @@ END IF; -- Check if initiated SELECT initiated_outgoing_transaction_id, subject, credit_payto, (amount).val, (amount).frac, wtid, exchange_base_url, metadata - INTO init_id, local_subject, local_credit_payto, local_amount.val, local_amount.frac, + INTO init_id, local_subject, local_credit_payto, local_amount.val, local_amount.frac, local_wtid, local_exchange_base_url, local_metadata FROM initiated_outgoing_transactions LEFT JOIN transfer_operations USING (initiated_outgoing_transaction_id) WHERE end_to_end_id = in_end_to_end_id; @@ -223,13 +223,13 @@ IF NOT out_found THEN IF out_initiated THEN -- Reconciles the related initiated transaction UPDATE initiated_outgoing_transactions - SET + SET outgoing_transaction_id = out_tx_id ,status = 'success' ,status_msg = null - WHERE initiated_outgoing_transaction_id = init_id + WHERE initiated_outgoing_transaction_id = init_id AND status != 'late_failure'; - + -- Reconciles the related initiated batch UPDATE initiated_outgoing_batches SET status = 'success', status_msg = null @@ -282,7 +282,7 @@ out_pending=FALSE; SELECT incoming_transaction_id, tx.subject, debit_payto, (tx.amount).val, (tx.amount).frac, metadata IS NOT NULL, end_to_end_id INTO out_tx_id, local_subject, local_debit_payto, local_amount.val, local_amount.frac, out_talerable, out_bounce_id FROM incoming_transactions AS tx - LEFT JOIN talerable_incoming_transactions USING (incoming_transaction_id) + LEFT JOIN talerable_incoming_transactions USING (incoming_transaction_id) LEFT JOIN bounced_transactions USING (incoming_transaction_id) LEFT JOIN initiated_outgoing_transactions USING (initiated_outgoing_transaction_id) WHERE uetr = in_uetr OR tx_id = in_tx_id OR acct_svcr_ref = in_acct_svcr_ref; @@ -307,7 +307,7 @@ IF NOT out_found OR NOT out_talerable THEN out_reserve_pub_reuse=NOT out_pending AND in_type = 'reserve' AND EXISTS(SELECT FROM talerable_incoming_transactions WHERE metadata = in_metadata AND type = 'reserve'); IF out_reserve_pub_reuse THEN RETURN; - END IF; + END IF; END IF; IF out_found THEN @@ -322,7 +322,7 @@ IF out_found THEN IF local_amount != in_amount THEN RAISE NOTICE 'incoming tx %: stored amount is % got %', local_ref, local_amount, in_amount; END IF; - UPDATE incoming_transactions + UPDATE incoming_transactions SET subject=COALESCE(subject, in_subject), debit_payto=COALESCE(debit_payto, in_debit_payto), uetr=COALESCE(uetr, in_uetr), @@ -370,7 +370,7 @@ IF in_type IS NOT NULL AND NOT out_talerable AND out_bounce_id IS NULL THEN UPDATE prepared_transfers SET incoming_transaction_id = out_tx_id WHERE ( - incoming_transaction_id IS NULL AND account_pub = in_metadata AND type='reserve' + incoming_transaction_id IS NULL AND account_pub = in_metadata AND type='reserve' ) OR authorization_pub = local_authorization_pub; -- We cannot use ON CONFLICT here because conversion use a trigger before insertion that isn't idempotent INSERT INTO talerable_incoming_transactions ( @@ -454,7 +454,7 @@ SELECT end_to_end_id INTO out_bounce_id IF NOT FOUND THEN out_bounce_id = in_bounce_id; -- Get incoming transaction bank ID and creditor - SELECT COALESCE(uetr::text, tx_id, acct_svcr_ref), debit_payto + SELECT COALESCE(uetr::text, tx_id, acct_svcr_ref), debit_payto INTO local_bank_id, payto_uri FROM libeufin_nexus.incoming_transactions WHERE incoming_transaction_id = in_tx_id; @@ -502,7 +502,7 @@ CREATE FUNCTION taler_transfer( LANGUAGE plpgsql AS $$ BEGIN -- Check for idempotence and conflict -SELECT (amount != in_amount +SELECT (amount != in_amount OR credit_payto != in_credit_account_payto OR exchange_base_url != in_exchange_base_url OR metadata != in_metadata @@ -511,7 +511,7 @@ SELECT (amount != in_amount INTO out_request_uid_reuse, out_tx_row_id, out_timestamp FROM transfer_operations JOIN initiated_outgoing_transactions - ON transfer_operations.initiated_outgoing_transaction_id=initiated_outgoing_transactions.initiated_outgoing_transaction_id + ON transfer_operations.initiated_outgoing_transaction_id=initiated_outgoing_transactions.initiated_outgoing_transaction_id WHERE transfer_operations.request_uid = in_request_uid; IF FOUND THEN RETURN; @@ -572,13 +572,13 @@ IF EXISTS(SELECT FROM initiated_outgoing_transactions WHERE initiated_outgoing_b VALUES (in_timestamp, batch_ebics_id) RETURNING initiated_outgoing_batch_id INTO batch_id; -- Link batched payment while computing the sum of amounts - FOR tx IN UPDATE initiated_outgoing_transactions + FOR tx IN UPDATE initiated_outgoing_transactions SET initiated_outgoing_batch_id=batch_id WHERE initiated_outgoing_batch_id IS NULL AND (NOT require_ack OR NOT awaiting_ack) RETURNING amount LOOP - SELECT sum.val, sum.frac + SELECT sum.val, sum.frac INTO local_sum.val, local_sum.frac FROM amount_add(local_sum, tx.amount) AS sum; END LOOP; @@ -603,10 +603,10 @@ BEGIN WHERE message_id = in_message_id; out_ok=FOUND; IF FOUND THEN - -- Update unsettled batch status - UPDATE initiated_outgoing_batches + -- Update unsettled batch status + UPDATE initiated_outgoing_batches SET status = in_status, status_msg = in_status_msg - WHERE initiated_outgoing_batch_id = local_batch_id + WHERE initiated_outgoing_batch_id = local_batch_id AND status NOT IN ('success', 'permanent_failure', 'late_failure'); -- When a batch succeed it doesn't mean that individual transaction also succeed @@ -615,7 +615,7 @@ BEGIN END IF; -- Update unsettled batch's transaction status - UPDATE initiated_outgoing_transactions + UPDATE initiated_outgoing_transactions SET status = in_status, status_msg = in_status_msg WHERE initiated_outgoing_batch_id = local_batch_id AND status NOT IN ('success', 'permanent_failure', 'late_failure'); @@ -645,7 +645,7 @@ BEGIN IF in_status = 'permanent_failure' AND local_status = 'success' THEN in_status = 'late_failure'; END IF; - UPDATE initiated_outgoing_transactions + UPDATE initiated_outgoing_transactions SET status = in_status, status_msg = in_status_msg WHERE initiated_outgoing_transaction_id = local_tx_id; END IF; @@ -676,8 +676,8 @@ DECLARE idempotent BOOLEAN; BEGIN --- Check idempotency -SELECT type = in_type +-- Check idempotency +SELECT type = in_type AND account_pub = in_account_pub AND recurrent = in_recurrent AND reference_number = in_reference_number