libeufin

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

commit aa49980281add0cef16b2c1efda3eef2b9e5ae9c
parent 6d6b7543b7e7b5e159ccd5c96064a96b354e483d
Author: Antoine A <>
Date:   Tue, 28 Jul 2026 14:20:10 +0200

common: bug fixes

Diffstat:
MCargo.lock | 113++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mlibeufin-bank/src/db/gc.rs | 4++--
Mlibeufin-bank/src/lib.rs | 2+-
Mlibeufin-ebics/src/bin/iso20022-codegen.rs | 4++--
Mlibeufin-ebics/src/db.rs | 2+-
Mlibeufin-ebics/src/iso20022/bank_tx_code.rs | 4++--
Mlibeufin-ebics/src/iso20022/camt.rs | 9++++++++-
Mlibeufin-nexus/src/lib.rs | 18+++++++++---------
8 files changed, 80 insertions(+), 76 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -206,7 +206,7 @@ checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ "axum-core", "axum-macros", - "base64", + "base64 0.22.1", "bytes", "form_urlencoded", "futures-util", @@ -273,6 +273,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] +name = "base64" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b25655df2c3cdd83c5e5b293b88acd880332b2ddadd7c30ac43144fdc0033da9" + +[[package]] name = "base64ct" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -280,11 +286,11 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bcrypt" -version = "0.19.2" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f3c067aa24dd4ed5c79cf222a38f260c8f23d3b82a062fba3f28c6fe563b753" +checksum = "a0cd0bd35a28836d528d2b58ad499bc3c5641d59379421b1be9eeb0c2f2b912a" dependencies = [ - "base64", + "base64 0.23.0", "blowfish", "getrandom 0.4.3", "subtle", @@ -364,9 +370,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "calamine" -version = "0.36.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6975084f43060e56343ffba7f9731fa52a7dcf2e1cd8e2459fd4c6bf4a1bff59" +checksum = "5fa68281b1a76b54a62156474adb06bb380a67e07dd60656e3217152b42183f3" dependencies = [ "atoi_simd", "byteorder", @@ -390,9 +396,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" dependencies = [ "find-msvc-tools", "jobserver", @@ -447,9 +453,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.3" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fb99565819980999fb7b4a1796046a5c949e6d4ff132cf5fadf5a641e20d776" +checksum = "d91e0c145792ef73a6ad36d27c75ac09f1832222a3c209689d90f534685ee5b7" dependencies = [ "clap_builder", "clap_derive", @@ -469,14 +475,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.3" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f2392eae7f16557a3d727ef3a12e57b2b2ca6f98566a5f4fb41ffe305df077" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -536,15 +542,6 @@ dependencies = [ ] [[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] name = "console" version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -930,9 +927,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "either" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" dependencies = [ "serde", ] @@ -981,11 +978,10 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.4.1" +version = "5.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" dependencies = [ - "concurrent-queue", "parking", "pin-project-lite", ] @@ -1217,9 +1213,9 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" [[package]] name = "globset" @@ -1360,7 +1356,7 @@ dependencies = [ [[package]] name = "http-client" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#0a8cd6865484b261e7f86d4d0bc680fa12330b14" +source = "git+git://git.taler.net/taler-rust.git/#0b262a884fa9afaf4b718cf7b841f0fa0a9dc62f" dependencies = [ "compact_str", "futures-util", @@ -1453,7 +1449,7 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-util", @@ -1653,9 +1649,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e184d09547b80eb7e20d141ba2fb1fbac843ca53f4cf1b31210adc4c1adc6e16" +checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" dependencies = [ "defmt", "jiff-core", @@ -1677,9 +1673,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "323da076b7a6faf914dc677cb05a4b907742ff7375c8322c9e7f5061e5e0e9de" +checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" dependencies = [ "jiff-core", "proc-macro2", @@ -1783,9 +1779,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.188" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22053b6a34f84abc97f9129e61334f40174659a1b9bd18c970b83db6a9a6348b" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libeufin-bank" @@ -2261,7 +2257,7 @@ version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ - "base64", + "base64 0.22.1", "serde_core", ] @@ -2637,7 +2633,7 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", @@ -2796,9 +2792,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ "web-time", "zeroize", @@ -2935,7 +2931,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.2", + "syn 3.0.3", ] [[package]] @@ -3165,7 +3161,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "crc", "crossbeam-queue", @@ -3241,7 +3237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", - "base64", + "base64 0.22.1", "bitflags 2.13.1", "byteorder", "bytes", @@ -3284,7 +3280,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", - "base64", + "base64 0.22.1", "bitflags 2.13.1", "byteorder", "crc", @@ -3418,9 +3414,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a207d6d6a2b7fc470b80443726053f18a2481b7e1eee970597051596567987a3" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" dependencies = [ "proc-macro2", "quote", @@ -3471,7 +3467,7 @@ dependencies = [ [[package]] name = "taler-api" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#0a8cd6865484b261e7f86d4d0bc680fa12330b14" +source = "git+git://git.taler.net/taler-rust.git/#0b262a884fa9afaf4b718cf7b841f0fa0a9dc62f" dependencies = [ "aws-lc-rs", "axum", @@ -3499,12 +3495,12 @@ dependencies = [ [[package]] name = "taler-build" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#0a8cd6865484b261e7f86d4d0bc680fa12330b14" +source = "git+git://git.taler.net/taler-rust.git/#0b262a884fa9afaf4b718cf7b841f0fa0a9dc62f" [[package]] name = "taler-common" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#0a8cd6865484b261e7f86d4d0bc680fa12330b14" +source = "git+git://git.taler.net/taler-rust.git/#0b262a884fa9afaf4b718cf7b841f0fa0a9dc62f" dependencies = [ "anyhow", "aws-lc-rs", @@ -3534,17 +3530,17 @@ dependencies = [ [[package]] name = "taler-macros" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#0a8cd6865484b261e7f86d4d0bc680fa12330b14" +source = "git+git://git.taler.net/taler-rust.git/#0b262a884fa9afaf4b718cf7b841f0fa0a9dc62f" dependencies = [ "proc-macro2", "quote", - "syn 3.0.2", + "syn 3.0.3", ] [[package]] name = "taler-test-utils" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#0a8cd6865484b261e7f86d4d0bc680fa12330b14" +source = "git+git://git.taler.net/taler-rust.git/#0b262a884fa9afaf4b718cf7b841f0fa0a9dc62f" dependencies = [ "aws-lc-rs", "axum", @@ -3626,7 +3622,7 @@ checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" dependencies = [ "proc-macro2", "quote", - "syn 3.0.2", + "syn 3.0.3", ] [[package]] @@ -3732,9 +3728,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" dependencies = [ "futures-core", "pin-project-lite", @@ -3755,14 +3751,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" dependencies = [ "bytes", "futures-core", "futures-io", "futures-sink", + "libc", "pin-project-lite", "tokio", ] diff --git a/libeufin-bank/src/db/gc.rs b/libeufin-bank/src/db/gc.rs @@ -34,7 +34,7 @@ pub async fn collect( sqlx::query( " UPDATE taler_withdrawal_operations SET aborted = true WHERE creation_date < $1 AND NOT EXISTS( - SELECT FROM prepared_transfers JOIN taler_withdrawal_operations USING (withdrawal_id) + SELECT FROM prepared_transfers WHERE prepared_transfers.withdrawal_id=taler_withdrawal_operations.withdrawal_id ) " ).bind_timestamp(abort_after).execute(db).await?; @@ -42,7 +42,7 @@ pub async fn collect( // Clean aborted operations, expired challenges and expired tokens for stm in [ "DELETE FROM taler_withdrawal_operations WHERE aborted = true AND creation_date < $1 AND NOT EXISTS( - SELECT FROM prepared_transfers JOIN taler_withdrawal_operations USING (withdrawal_id) + SELECT FROM prepared_transfers WHERE prepared_transfers.withdrawal_id=taler_withdrawal_operations.withdrawal_id )", "DELETE FROM tan_challenges WHERE expiration_date < $1", "DELETE FROM bearer_tokens WHERE expiration_time < $1" diff --git a/libeufin-bank/src/lib.rs b/libeufin-bank/src/lib.rs @@ -305,7 +305,7 @@ pub async fn run(cfg: &Config, cmd: Cmd) -> anyhow::Result<()> { let now = Timestamp::now(); let new = if let Some(current) = current_token && let Some(token) = access(&db, current.as_ref(), &now).await? - && token.expiration < TalerTimestamp::Timestamp(now) + && token.expiration > TalerTimestamp::Timestamp(now) && scope.logical().is_valid_scope(token.scope, refreshable) { current diff --git a/libeufin-ebics/src/bin/iso20022-codegen.rs b/libeufin-ebics/src/bin/iso20022-codegen.rs @@ -116,7 +116,7 @@ use taler_macros::EnumMeta; } writeln!(&mut out, "}}").unwrap(); } - std::fs::write("src/iso20022/status_code.rs", out).unwrap(); + std::fs::write("libeufin-ebics/src/iso20022/status_code.rs", out).unwrap(); } pub async fn iso20022codegen_bank_transaction_code() { @@ -194,7 +194,7 @@ use taler_macros::EnumMeta; } writeln!(&mut out, "}}").unwrap(); } - std::fs::write("src/iso20022/bank_tx_code.rs", out).unwrap(); + std::fs::write("libeufin-ebics/src/iso20022/bank_tx_code.rs", out).unwrap(); } #[tokio::main] diff --git a/libeufin-ebics/src/db.rs b/libeufin-ebics/src/db.rs @@ -73,7 +73,7 @@ pub async fn update_task_status( sqlx::query(if success { "INSERT INTO kv (key, value) VALUES ($1, jsonb_build_object('last_successfull', $2, 'last_trial', $3)) ON CONFLICT (key) DO UPDATE SET value=EXCLUDED.value" } else { - "INSERT INTO kv (key, value) VALUES ($1, jsonb_build_object('last_trial', $2)) ON CONFLICT (key) DO UPDATE SET value=jsonb_set(EXCLUDED.value, '{last_trial}'::text[], to_jsonb($3))" + "INSERT INTO kv (key, value) VALUES ($1, jsonb_build_object('last_trial', $2)) ON CONFLICT (key) DO UPDATE SET value=jsonb_set(kv.value, '{last_trial}'::text[], to_jsonb($3))" }).bind(key).bind_timestamp(timestamp).bind_timestamp(timestamp).execute(db))?; Ok(()) } diff --git a/libeufin-ebics/src/iso20022/bank_tx_code.rs b/libeufin-ebics/src/iso20022/bank_tx_code.rs @@ -514,7 +514,7 @@ pub enum BankTxSubFamilyCode { PPAY, /// Priority Credit Transfer PRCT, - /// Reversal Due To Payment Reversal + /// Reversal Due To Payment Reversal PRDD, /// Partial Redemption Without Reduction of Nominal Value PRED, @@ -550,7 +550,7 @@ pub enum BankTxSubFamilyCode { RPBC, /// Repo client owned collateral RPCC, - /// Reversal Due To Payment Cancellation Request + /// Reversal Due To Payment Cancellation Request RPCR, /// Repayment RPMT, diff --git a/libeufin-ebics/src/iso20022/camt.rs b/libeufin-ebics/src/iso20022/camt.rs @@ -87,7 +87,14 @@ impl BankTxCode { fn is_reversal(&self) -> bool { matches!( self.subfamily, - BankTxSubFamilyCode::RPCR | BankTxSubFamilyCode::RRTN | BankTxSubFamilyCode::PSTE + BankTxSubFamilyCode::RRTN + | BankTxSubFamilyCode::RPCR + | BankTxSubFamilyCode::PSTE + | BankTxSubFamilyCode::XRTN + | BankTxSubFamilyCode::RCDD + | BankTxSubFamilyCode::UPDD + | BankTxSubFamilyCode::PRDD + | BankTxSubFamilyCode::RCOV ) } } diff --git a/libeufin-nexus/src/lib.rs b/libeufin-nexus/src/lib.rs @@ -241,14 +241,14 @@ pub async fn ebics_submit( // Send submittable batches for batch in initiated_submittable(db, &cfg.currency).await? { - debug!(target: "ebics-submit", "Submitting batch {}", batch.msg_id); + debug!(target: "submit", "Submitting batch {}", batch.msg_id); let res = async { if let Some(instant) = standard.instant_direct_debit() { match submit_batch(&instant, &batch, true).await { Ok(id) => return Ok(id), Err(e) => if let EbicsErrKind::Code { .. } = e.kind { // No longer try to submit using the instant method for now - debug!(target: "ebics-submit", "Failed to submit using instant credit order {e}"); + debug!(target: "submit", "Failed to submit using instant credit order {e}"); instant_order = None; } else { return Err(e) @@ -267,14 +267,14 @@ pub async fn ebics_submit( .collect::<Vec<_>>() .join_compact(","); if instant_order.is_some() { - info!(target: "ebics-submit", "Instant batch {} submitted as order {order_id}: {txs}", batch.msg_id); + info!(target: "submit", "Instant batch {} submitted as order {order_id}: {txs}", batch.msg_id); } else { - info!(target: "ebics-submit", "Batch {} submitted as order {order_id}: {txs}", batch.msg_id); + info!(target: "submit", "Batch {} submitted as order {order_id}: {txs}", batch.msg_id); } } Err(e) => { batch_sub_failure(db, batch.id, &Timestamp::now(), &e.to_string()).await?; - error!(target: "ebics-submit", "Batch {} submission failure: {e}", batch.msg_id); + error!(target: "submit", "Batch {} submission failure: {e}", batch.msg_id); return Err(e.into()); } } @@ -283,21 +283,21 @@ pub async fn ebics_submit( Ok(()) }; if transient { - debug!(target: "ebics-submit", "Transient mode: submitting what found and returning"); + debug!(target: "submit", "Transient mode: submitting what found and returning"); submit_all().await } else { - debug!(target: "ebics-submit", "Running with a frequency of {}", submit_cfg.frequency_raw); + debug!(target: "submit", "Running with a frequency of {}", submit_cfg.frequency_raw); loop { let now = Timestamp::now(); let success = match submit_all().await { Ok(_) => true, Err(e) => { - error!(target: "ebics-submit", "{e}"); + error!(target: "submit", "{e}"); false } }; if let Err(e) = update_task_status(db, SUBMIT_TASK_KEY, &now, success).await { - warn!(target: "ebics-submit", "{e}"); + warn!(target: "submit", "{e}"); } tokio::time::sleep(Duration::from_millis( Timestamp::now()