commit dc223fd8aa6b1c27be78484ceb7a8efbb1c42cef
parent 3322693545f8648b7e8dd9b881d0827b737680a5
Author: Antoine A <>
Date: Thu, 26 Mar 2026 17:36:39 +0100
common: improve prepared transfer tests, fix bugs and bump API version
Diffstat:
7 files changed, 325 insertions(+), 183 deletions(-)
diff --git a/common/taler-api/db/taler-api-procedures.sql b/common/taler-api/db/taler-api-procedures.sql
@@ -174,19 +174,21 @@ IF local_pending THEN
INSERT INTO pending_recurrent_in (tx_in_id, authorization_pub)
VALUES (out_tx_row_id, local_authorization_pub);
ELSE
- IF local_authorization_pub IS NOT NULL THEN
- UPDATE prepared_in
- SET tx_in_id = out_tx_row_id
- WHERE authorization_pub = local_authorization_pub;
- END IF;
+ UPDATE prepared_in
+ SET tx_in_id = out_tx_row_id
+ WHERE (tx_in_id IS NULL AND account_pub = in_account_pub) OR authorization_pub = local_authorization_pub;
INSERT INTO taler_in (
tx_in_id,
type,
- account_pub
+ account_pub,
+ authorization_pub,
+ authorization_sig
) VALUES (
out_tx_row_id,
in_type,
- in_account_pub
+ in_account_pub,
+ local_authorization_pub,
+ local_authorization_sig
);
-- Notify new incoming transaction
PERFORM pg_notify('incoming_tx', out_tx_row_id || '');
diff --git a/common/taler-api/src/constants.rs b/common/taler-api/src/constants.rs
@@ -14,7 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-pub const WIRE_GATEWAY_API_VERSION: &str = "4:0:0";
+pub const WIRE_GATEWAY_API_VERSION: &str = "5:0:0";
pub const WIRE_GATEWAY_TRANSFER_API_VERSION: &str = "1:0:0";
pub const REVENUE_API_VERSION: &str = "1:0:0";
pub const MAX_PAGE_SIZE: i64 = 1024;
diff --git a/common/taler-test-utils/src/routine.rs b/common/taler-test-utils/src/routine.rs
@@ -24,7 +24,10 @@ use aws_lc_rs::signature::{Ed25519KeyPair, KeyPair as _};
use axum::Router;
use jiff::{SignedDuration, Timestamp};
use serde::{Deserialize, de::DeserializeOwned};
-use taler_api::{crypto::eddsa_sign, subject::fmt_in_subject};
+use taler_api::{
+ crypto::{check_eddsa_signature, eddsa_sign},
+ subject::fmt_in_subject,
+};
use taler_common::{
api_common::{EddsaPublicKey, HashCode, ShortHashCode},
api_params::PageParams,
@@ -683,28 +686,28 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O
let currency = &get_transfer_currency(server).await;
let amount = amount(format!("{currency}:42"));
- let key_pair = Ed25519KeyPair::generate().unwrap();
- let auth_pub = EddsaPublicKey::try_from(key_pair.public_key().as_ref()).unwrap();
+ let key_pair1 = Ed25519KeyPair::generate().unwrap();
+ let auth_pub1 = EddsaPublicKey::try_from(key_pair1.public_key().as_ref()).unwrap();
let req = json!({
"credit_amount": amount,
"type": "reserve",
"alg": "EdDSA",
- "account_pub": auth_pub,
- "authorization_pub": auth_pub,
- "authorization_sig": eddsa_sign(&key_pair, auth_pub.as_ref()),
+ "account_pub": auth_pub1,
+ "authorization_pub": auth_pub1,
+ "authorization_sig": eddsa_sign(&key_pair1, auth_pub1.as_ref()),
"recurrent": false
});
+ /* ----- Registration ----- */
let routine = async |ty: TransferType,
account_pub: &EddsaPublicKey,
- auth_pub: &EddsaPublicKey,
recurrent: bool,
- expected: &str| {
+ fmt: IncomingType| {
let req = json!(req + {
"type": ty,
"account_pub": account_pub,
- "authorization_pub": auth_pub,
- "authorization_sig": eddsa_sign(&key_pair, account_pub.as_ref()),
+ "authorization_pub": auth_pub1,
+ "authorization_sig": eddsa_sign(&key_pair1, account_pub.as_ref()),
"recurrent": recurrent
});
// Valid
@@ -728,54 +731,26 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O
for sub in res.subjects {
if let TransferSubject::Simple { subject, .. } = sub {
- assert_eq!(subject, expected);
+ assert_eq!(subject, fmt_in_subject(fmt, &auth_pub1));
};
}
};
for ty in [TransferType::reserve, TransferType::kyc] {
- routine(
- ty,
- &auth_pub,
- &auth_pub,
- false,
- &fmt_in_subject(ty.into(), &auth_pub),
- )
- .await;
- routine(
- ty,
- &auth_pub,
- &auth_pub,
- true,
- &fmt_in_subject(IncomingType::map, &auth_pub),
- )
- .await;
+ routine(ty, &auth_pub1, false, ty.into()).await;
+ routine(ty, &auth_pub1, true, IncomingType::map).await;
}
- let account_pub = EddsaPublicKey::rand();
+ let acc_pub1 = EddsaPublicKey::rand();
for ty in [TransferType::reserve, TransferType::kyc] {
- routine(
- ty,
- &account_pub,
- &auth_pub,
- false,
- &fmt_in_subject(IncomingType::map, &auth_pub),
- )
- .await;
- routine(
- ty,
- &account_pub,
- &auth_pub,
- true,
- &fmt_in_subject(IncomingType::map, &auth_pub),
- )
- .await;
+ routine(ty, &acc_pub1, false, IncomingType::map).await;
+ routine(ty, &acc_pub1, true, IncomingType::map).await;
}
// Bad signature
server
.post("/taler-wire-transfer-gateway/registration")
.json(&json!(req + {
- "authorization_sig": eddsa_sign(&key_pair, "lol".as_bytes()),
+ "authorization_sig": eddsa_sign(&key_pair1, "lol".as_bytes()),
}))
.await
.assert_error(ErrorCode::BANK_BAD_SIGNATURE);
@@ -784,8 +759,8 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O
server
.post("/taler-wire-transfer-gateway/registration")
.json(&json!(req + {
- "account_pub": account_pub,
- "authorization_sig": eddsa_sign(&key_pair, account_pub.as_ref()),
+ "account_pub": acc_pub1,
+ "authorization_sig": eddsa_sign(&key_pair1, acc_pub1.as_ref()),
}))
.await
.assert_ok_json::<RegistrationResponse>();
@@ -795,9 +770,9 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O
server
.post("/taler-wire-transfer-gateway/registration")
.json(&json!(req + {
- "account_pub": account_pub,
+ "account_pub": acc_pub1,
"authorization_pub": auth_pub,
- "authorization_sig": eddsa_sign(&key_pair, account_pub.as_ref()),
+ "authorization_sig": eddsa_sign(&key_pair, acc_pub1.as_ref()),
}))
.await
.assert_error(ErrorCode::BANK_DUPLICATE_RESERVE_PUB_SUBJECT);
@@ -807,34 +782,64 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O
server
.post("/taler-wire-transfer-gateway/registration")
.json(&json!(req + {
- "account_pub": account_pub,
- "authorization_sig": eddsa_sign(&key_pair, account_pub.as_ref()),
+ "account_pub": acc_pub1,
+ "authorization_sig": eddsa_sign(&key_pair1, acc_pub1.as_ref()),
}))
.await
.assert_ok_json::<RegistrationResponse>();
- register(&auth_pub).await;
- check_in(&[Reserve(account_pub.clone())]).await;
- register(&auth_pub).await;
- check_in(&[Reserve(account_pub.clone()), Bounced]).await;
+ register(&auth_pub1).await;
+ check_in(&[Reserve(acc_pub1.clone())]).await;
+ register(&auth_pub1).await;
+ check_in(&[Reserve(acc_pub1.clone()), Bounced]).await;
+
+ // Again without using mapping
+ let acc_pub2 = EddsaPublicKey::rand();
+ server
+ .post("/taler-wire-transfer-gateway/registration")
+ .json(&json!(req + {
+ "account_pub": acc_pub2,
+ "authorization_sig": eddsa_sign(&key_pair1, acc_pub2.as_ref()),
+ }))
+ .await
+ .assert_ok_json::<RegistrationResponse>();
+ server
+ .post("/taler-wire-gateway/admin/add-incoming")
+ .json(&json!({
+ "amount": amount,
+ "reserve_pub": acc_pub2,
+ "debit_account": account,
+ }))
+ .await
+ .assert_ok();
+ register(&auth_pub1).await;
+ check_in(&[
+ Reserve(acc_pub1.clone()),
+ Bounced,
+ Reserve(acc_pub2.clone()),
+ Bounced,
+ ])
+ .await;
// Recurrent accept one and delay others
- let new_key = EddsaPublicKey::rand();
+ let acc_pub3 = EddsaPublicKey::rand();
server
.post("/taler-wire-transfer-gateway/registration")
.json(&json!(req + {
- "account_pub": new_key,
- "authorization_sig": eddsa_sign(&key_pair, new_key.as_ref()),
+ "account_pub": acc_pub3,
+ "authorization_sig": eddsa_sign(&key_pair1, acc_pub3.as_ref()),
"recurrent": true
}))
.await
.assert_ok_json::<RegistrationResponse>();
for _ in 0..5 {
- register(&auth_pub).await;
+ register(&auth_pub1).await;
}
check_in(&[
- Reserve(account_pub.clone()),
+ Reserve(acc_pub1.clone()),
+ Bounced,
+ Reserve(acc_pub2.clone()),
Bounced,
- Reserve(new_key.clone()),
+ Reserve(acc_pub3.clone()),
Pending,
Pending,
Pending,
@@ -843,13 +848,13 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O
.await;
// Complete pending on recurrent update
- let kyc_key = EddsaPublicKey::rand();
+ let acc_pub4 = EddsaPublicKey::rand();
server
.post("/taler-wire-transfer-gateway/registration")
.json(&json!(req + {
"type": "kyc",
- "account_pub": kyc_key,
- "authorization_sig": eddsa_sign(&key_pair, kyc_key.as_ref()),
+ "account_pub": acc_pub4,
+ "authorization_sig": eddsa_sign(&key_pair1, acc_pub4.as_ref()),
"recurrent": true
}))
.await
@@ -857,18 +862,20 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O
server
.post("/taler-wire-transfer-gateway/registration")
.json(&json!(req + {
- "account_pub": kyc_key,
- "authorization_sig": eddsa_sign(&key_pair, kyc_key.as_ref()),
+ "account_pub": acc_pub4,
+ "authorization_sig": eddsa_sign(&key_pair1, acc_pub4.as_ref()),
"recurrent": true
}))
.await
.assert_ok_json::<RegistrationResponse>();
check_in(&[
- Reserve(account_pub.clone()),
+ Reserve(acc_pub1.clone()),
+ Bounced,
+ Reserve(acc_pub2.clone()),
Bounced,
- Reserve(new_key.clone()),
- Kyc(kyc_key.clone()),
- Reserve(kyc_key.clone()),
+ Reserve(acc_pub3.clone()),
+ Kyc(acc_pub4.clone()),
+ Reserve(acc_pub4.clone()),
Pending,
Pending,
])
@@ -879,49 +886,53 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O
.post("/taler-wire-gateway/admin/add-kycauth")
.json(&json!({
"amount": amount,
- "account_pub": kyc_key,
+ "account_pub": acc_pub4,
"debit_account": account,
}))
.await
.assert_ok_json::<TransferResponse>();
check_in(&[
- Reserve(account_pub.clone()),
+ Reserve(acc_pub1.clone()),
Bounced,
- Reserve(new_key.clone()),
- Kyc(kyc_key.clone()),
- Reserve(kyc_key.clone()),
+ Reserve(acc_pub2.clone()),
+ Bounced,
+ Reserve(acc_pub3.clone()),
+ Kyc(acc_pub4.clone()),
+ Reserve(acc_pub4.clone()),
Pending,
Pending,
- Kyc(kyc_key.clone()),
+ Kyc(acc_pub4.clone()),
])
.await;
// Switching to non recurrent cancel pending
let auth_pair = Ed25519KeyPair::generate().unwrap();
- let last_pub = EddsaPublicKey::try_from(auth_pair.public_key().as_ref()).unwrap();
+ let auth_pub2 = EddsaPublicKey::try_from(auth_pair.public_key().as_ref()).unwrap();
server
.post("/taler-wire-transfer-gateway/registration")
.json(&json!(req + {
- "account_pub": last_pub,
- "authorization_pub": last_pub,
- "authorization_sig": eddsa_sign(&auth_pair, last_pub.as_ref()),
+ "account_pub": auth_pub2,
+ "authorization_pub": auth_pub2,
+ "authorization_sig": eddsa_sign(&auth_pair, auth_pub2.as_ref()),
"recurrent": true
}))
.await
.assert_ok_json::<RegistrationResponse>();
for _ in 0..3 {
- register(&last_pub).await;
+ register(&auth_pub2).await;
}
check_in(&[
- Reserve(account_pub.clone()),
+ Reserve(acc_pub1.clone()),
+ Bounced,
+ Reserve(acc_pub2.clone()),
Bounced,
- Reserve(new_key.clone()),
- Kyc(kyc_key.clone()),
- Reserve(kyc_key.clone()),
+ Reserve(acc_pub3.clone()),
+ Kyc(acc_pub4.clone()),
+ Reserve(acc_pub4.clone()),
Pending,
Pending,
- Kyc(kyc_key.clone()),
- Reserve(last_pub.clone()),
+ Kyc(acc_pub4.clone()),
+ Reserve(auth_pub2.clone()),
Pending,
Pending,
])
@@ -930,123 +941,244 @@ pub async fn registration_routine<F1: Future<Output = Vec<Status>>, F2: Future<O
.post("/taler-wire-transfer-gateway/registration")
.json(&json!(req + {
"type": "kyc",
- "account_pub": last_pub,
- "authorization_pub": last_pub,
- "authorization_sig": eddsa_sign(&auth_pair, last_pub.as_ref()),
+ "account_pub": auth_pub2,
+ "authorization_pub": auth_pub2,
+ "authorization_sig": eddsa_sign(&auth_pair, auth_pub2.as_ref()),
"recurrent": false
}))
.await
.assert_ok_json::<RegistrationResponse>();
check_in(&[
- Reserve(account_pub.clone()),
+ Reserve(acc_pub1.clone()),
Bounced,
- Reserve(new_key.clone()),
- Kyc(kyc_key.clone()),
- Reserve(kyc_key.clone()),
+ Reserve(acc_pub2.clone()),
+ Bounced,
+ Reserve(acc_pub3.clone()),
+ Kyc(acc_pub4.clone()),
+ Reserve(acc_pub4.clone()),
Pending,
Pending,
- Kyc(kyc_key.clone()),
- Reserve(last_pub.clone()),
+ Kyc(acc_pub4.clone()),
+ Reserve(auth_pub2.clone()),
Bounced,
Bounced,
])
.await;
- // Unregistration
- let now = Timestamp::now().to_string();
- let un_req = json!({
- "timestamp": now,
- "authorization_pub": last_pub,
- "authorization_sig": eddsa_sign(&auth_pair, now.as_bytes()),
- });
-
- // Known
- server
- .delete("/taler-wire-transfer-gateway/registration")
- .json(&un_req)
- .await
- .assert_no_content();
-
- // Idempotent
+ // Recurrent reserve simple subject
+ let acc_pub5 = EddsaPublicKey::rand();
server
- .delete("/taler-wire-transfer-gateway/registration")
- .json(&un_req)
+ .post("/taler-wire-transfer-gateway/registration")
+ .json(&json!(req + {
+ "type": "reserve",
+ "account_pub": acc_pub5,
+ "authorization_pub": auth_pub2,
+ "authorization_sig": eddsa_sign(&auth_pair, acc_pub5.as_ref()),
+ "recurrent": true
+ }))
.await
- .assert_error(ErrorCode::BANK_TRANSACTION_NOT_FOUND);
-
- // Bad signature
+ .assert_ok_json::<RegistrationResponse>();
server
- .delete("/taler-wire-transfer-gateway/registration")
- .json(&json!(un_req + {
- "authorization_sig": eddsa_sign(&auth_pair, "lol".as_bytes()),
+ .post("/taler-wire-gateway/admin/add-incoming")
+ .json(&json!({
+ "amount": amount,
+ "reserve_pub": acc_pub5,
+ "debit_account": account,
}))
.await
- .assert_error(ErrorCode::BANK_BAD_SIGNATURE);
+ .assert_ok();
+ register(&auth_pub2).await;
+ check_in(&[
+ Reserve(acc_pub1.clone()),
+ Bounced,
+ Reserve(acc_pub2.clone()),
+ Bounced,
+ Reserve(acc_pub3.clone()),
+ Kyc(acc_pub4.clone()),
+ Reserve(acc_pub4.clone()),
+ Pending,
+ Pending,
+ Kyc(acc_pub4.clone()),
+ Reserve(auth_pub2.clone()),
+ Bounced,
+ Bounced,
+ Reserve(acc_pub5.clone()),
+ Pending,
+ ])
+ .await;
- // Old timestamp
- let now = (Timestamp::now() - SignedDuration::from_mins(10)).to_string();
+ // Recurrent kyc simple subject
server
- .delete("/taler-wire-transfer-gateway/registration")
- .json(&json!({
- "timestamp": now,
- "authorization_pub": last_pub,
- "authorization_sig": eddsa_sign(&auth_pair, now.as_bytes()),
+ .post("/taler-wire-transfer-gateway/registration")
+ .json(&json!(req + {
+ "type": "kyc",
+ "account_pub": acc_pub5,
+ "authorization_pub": auth_pub2,
+ "authorization_sig": eddsa_sign(&auth_pair, acc_pub5.as_ref()),
+ "recurrent": false
}))
.await
- .assert_error(ErrorCode::BANK_OLD_TIMESTAMP);
-
- // Check bounce pending on deletion
+ .assert_ok_json::<RegistrationResponse>();
server
.post("/taler-wire-transfer-gateway/registration")
.json(&json!(req + {
"type": "kyc",
- "account_pub": last_pub,
- "authorization_pub": last_pub,
- "authorization_sig": eddsa_sign(&auth_pair, last_pub.as_ref()),
+ "account_pub": acc_pub5,
+ "authorization_pub": auth_pub2,
+ "authorization_sig": eddsa_sign(&auth_pair, acc_pub5.as_ref()),
"recurrent": true
}))
.await
.assert_ok_json::<RegistrationResponse>();
- for _ in 0..3 {
- register(&last_pub).await;
- }
+ server
+ .post("/taler-wire-gateway/admin/add-kycauth")
+ .json(&json!({
+ "amount": amount,
+ "account_pub": acc_pub5,
+ "debit_account": account,
+ }))
+ .await
+ .assert_ok();
+ register(&auth_pub2).await;
+ register(&auth_pub2).await;
check_in(&[
- Reserve(account_pub.clone()),
+ Reserve(acc_pub1.clone()),
+ Bounced,
+ Reserve(acc_pub2.clone()),
Bounced,
- Reserve(new_key.clone()),
- Kyc(kyc_key.clone()),
- Reserve(kyc_key.clone()),
+ Reserve(acc_pub3.clone()),
+ Kyc(acc_pub4.clone()),
+ Reserve(acc_pub4.clone()),
Pending,
Pending,
- Kyc(kyc_key.clone()),
- Reserve(last_pub.clone()),
+ Kyc(acc_pub4.clone()),
+ Reserve(auth_pub2.clone()),
Bounced,
Bounced,
- Kyc(last_pub.clone()),
+ Reserve(acc_pub5.clone()),
+ Bounced,
+ Kyc(acc_pub5.clone()),
Pending,
Pending,
])
.await;
+
+ /* ----- Unregistration ----- */
+ let now = Timestamp::now().to_string();
+ let un_req = json!({
+ "timestamp": now,
+ "authorization_pub": auth_pub2,
+ "authorization_sig": eddsa_sign(&auth_pair, now.as_bytes()),
+ });
+
+ // Delete
server
.delete("/taler-wire-transfer-gateway/registration")
.json(&un_req)
.await
.assert_no_content();
+
+ // Check bounce pending on deletion
+
check_in(&[
- Reserve(account_pub.clone()),
+ Reserve(acc_pub1.clone()),
Bounced,
- Reserve(new_key.clone()),
- Kyc(kyc_key.clone()),
- Reserve(kyc_key.clone()),
+ Reserve(acc_pub2.clone()),
+ Bounced,
+ Reserve(acc_pub3.clone()),
+ Kyc(acc_pub4.clone()),
+ Reserve(acc_pub4.clone()),
Pending,
Pending,
- Kyc(kyc_key.clone()),
- Reserve(last_pub.clone()),
+ Kyc(acc_pub4.clone()),
+ Reserve(auth_pub2.clone()),
+ Bounced,
Bounced,
+ Reserve(acc_pub5.clone()),
Bounced,
- Kyc(last_pub.clone()),
+ Kyc(acc_pub5.clone()),
Bounced,
Bounced,
])
.await;
+
+ // Idempotent
+ server
+ .delete("/taler-wire-transfer-gateway/registration")
+ .json(&un_req)
+ .await
+ .assert_error(ErrorCode::BANK_TRANSACTION_NOT_FOUND);
+
+ // Bad signature
+ server
+ .delete("/taler-wire-transfer-gateway/registration")
+ .json(&json!(un_req + {
+ "authorization_sig": eddsa_sign(&auth_pair, "lol".as_bytes()),
+ }))
+ .await
+ .assert_error(ErrorCode::BANK_BAD_SIGNATURE);
+
+ // Old timestamp
+ let now = (Timestamp::now() - SignedDuration::from_mins(10)).to_string();
+ server
+ .delete("/taler-wire-transfer-gateway/registration")
+ .json(&json!({
+ "timestamp": now,
+ "authorization_pub": auth_pub2,
+ "authorization_sig": eddsa_sign(&auth_pair, now.as_bytes()),
+ }))
+ .await
+ .assert_error(ErrorCode::BANK_OLD_TIMESTAMP);
+
+ /* ----- API ----- */
+
+ let history: Vec<_> = server
+ .get("/taler-wire-gateway/history/incoming?limit=20")
+ .await
+ .assert_ok_json::<IncomingHistory>()
+ .incoming_transactions
+ .into_iter()
+ .map(|tx| {
+ let (acc_pub, auth_pub, auth_sig) = match tx {
+ IncomingBankTransaction::Reserve {
+ reserve_pub,
+ authorization_pub,
+ authorization_sig,
+ ..
+ } => (reserve_pub, authorization_pub, authorization_sig),
+ IncomingBankTransaction::Wad { .. } => unreachable!(),
+ IncomingBankTransaction::Kyc {
+ account_pub,
+ authorization_pub,
+ authorization_sig,
+ ..
+ } => (account_pub, authorization_pub, authorization_sig),
+ };
+ if let Some(auth_pub) = &auth_pub {
+ assert!(check_eddsa_signature(
+ auth_pub,
+ acc_pub.as_ref(),
+ &auth_sig.unwrap()
+ ));
+ } else {
+ assert!(auth_sig.is_none())
+ }
+ (acc_pub, auth_pub)
+ })
+ .collect();
+ dbg!(&history);
+ assert_eq!(
+ history,
+ [
+ (acc_pub1.clone(), Some(auth_pub1.clone())),
+ (acc_pub2.clone(), None),
+ (acc_pub3.clone(), Some(auth_pub1.clone())),
+ (acc_pub4.clone(), Some(auth_pub1.clone())),
+ (acc_pub4.clone(), Some(auth_pub1.clone())),
+ (acc_pub4.clone(), None),
+ (auth_pub2.clone(), Some(auth_pub2.clone())),
+ (acc_pub5.clone(), None),
+ (acc_pub5.clone(), None),
+ ]
+ )
}
diff --git a/taler-cyclos/db/cyclos-procedures.sql b/taler-cyclos/db/cyclos-procedures.sql
@@ -127,20 +127,22 @@ IF out_pending THEN
INSERT INTO pending_recurrent_in (tx_in_id, authorization_pub)
VALUES (out_tx_row_id, local_authorization_pub);
ELSIF in_type IS NOT NULL THEN
- IF local_authorization_pub IS NOT NULL THEN
- UPDATE prepared_in
- SET tx_in_id = out_tx_row_id
- WHERE authorization_pub = local_authorization_pub;
- END IF;
+ UPDATE prepared_in
+ SET tx_in_id = out_tx_row_id
+ WHERE (tx_in_id IS NULL AND account_pub = in_metadata) OR authorization_pub = local_authorization_pub;
-- Insert new incoming talerable transaction
INSERT INTO taler_in (
tx_in_id,
type,
- metadata
+ metadata,
+ authorization_pub,
+ authorization_sig
) VALUES (
out_tx_row_id,
in_type,
- in_metadata
+ in_metadata,
+ local_authorization_pub,
+ local_authorization_sig
);
-- Notify new incoming talerable transaction registration
PERFORM pg_notify('taler_in', out_tx_row_id || '');
diff --git a/taler-cyclos/src/db.rs b/taler-cyclos/src/db.rs
@@ -573,7 +573,9 @@ pub async fn incoming_history(
debit_account,
debit_name,
valued_at,
- metadata
+ metadata,
+ authorization_pub,
+ authorization_sig
FROM taler_in
JOIN tx_in USING (tx_in_id)
WHERE
@@ -589,8 +591,8 @@ pub async fn incoming_history(
debit_account: r.try_get_cyclos_fullpaytouri(3, 4, root)?,
date: r.try_get_timestamp(5)?.into(),
reserve_pub: r.try_get(6)?,
- authorization_pub: None,
- authorization_sig: None,
+ authorization_pub: r.try_get(7)?,
+ authorization_sig: r.try_get(8)?,
},
IncomingType::kyc => IncomingBankTransaction::Kyc {
row_id: r.try_get_safeu64(1)?,
@@ -599,8 +601,8 @@ pub async fn incoming_history(
debit_account: r.try_get_cyclos_fullpaytouri(3, 4, root)?,
date: r.try_get_timestamp(5)?.into(),
account_pub: r.try_get(6)?,
- authorization_pub: None,
- authorization_sig: None,
+ authorization_pub: r.try_get(7)?,
+ authorization_sig: r.try_get(8)?,
},
IncomingType::map => unimplemented!("MAP are never listed in the history"),
})
diff --git a/taler-magnet-bank/db/magnet-bank-procedures.sql b/taler-magnet-bank/db/magnet-bank-procedures.sql
@@ -123,20 +123,22 @@ IF out_pending THEN
INSERT INTO pending_recurrent_in (tx_in_id, authorization_pub)
VALUES (out_tx_row_id, local_authorization_pub);
ELSIF in_type IS NOT NULL THEN
- IF local_authorization_pub IS NOT NULL THEN
- UPDATE prepared_in
- SET tx_in_id = out_tx_row_id
- WHERE authorization_pub = local_authorization_pub;
- END IF;
+ UPDATE prepared_in
+ SET tx_in_id = out_tx_row_id
+ WHERE (tx_in_id IS NULL AND account_pub = in_metadata) OR authorization_pub = local_authorization_pub;
-- Insert new incoming talerable transaction
INSERT INTO taler_in (
tx_in_id,
type,
- metadata
+ metadata,
+ authorization_pub,
+ authorization_sig
) VALUES (
out_tx_row_id,
in_type,
- in_metadata
+ in_metadata,
+ local_authorization_pub,
+ local_authorization_sig
);
-- Notify new incoming talerable transaction registration
PERFORM pg_notify('taler_in', out_tx_row_id || '');
diff --git a/taler-magnet-bank/src/db.rs b/taler-magnet-bank/src/db.rs
@@ -585,7 +585,9 @@ pub async fn incoming_history(
debit_account,
debit_name,
valued_at,
- metadata
+ metadata,
+ authorization_pub,
+ authorization_sig
FROM taler_in
JOIN tx_in USING (tx_in_id)
WHERE
@@ -601,8 +603,8 @@ pub async fn incoming_history(
debit_account: r.try_get_iban(3)?.as_full_payto(r.try_get(4)?),
date: r.try_get_timestamp(5)?.into(),
reserve_pub: r.try_get(6)?,
- authorization_pub: None,
- authorization_sig: None,
+ authorization_pub: r.try_get(7)?,
+ authorization_sig: r.try_get(8)?,
},
IncomingType::kyc => IncomingBankTransaction::Kyc {
row_id: r.try_get_safeu64(1)?,
@@ -611,8 +613,8 @@ pub async fn incoming_history(
debit_account: r.try_get_iban(3)?.as_full_payto(r.try_get(4)?),
date: r.try_get_timestamp(5)?.into(),
account_pub: r.try_get(6)?,
- authorization_pub: None,
- authorization_sig: None,
+ authorization_pub: r.try_get(7)?,
+ authorization_sig: r.try_get(8)?,
},
IncomingType::map => unimplemented!("MAP are never listed in the history"),
})