summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-07-02 17:28:35 +0200
committerChristian Grothoff <christian@grothoff.org>2022-07-02 17:28:35 +0200
commit4e73e59e1cc8d0934c651bba7c2b99f8ac5dc92b (patch)
tree11de318985c82f4e3b1fc69153613666557156d6 /src
parent3408486b5ba1752e589bec2ba592dcdb638c8be9 (diff)
downloadmerchant-4e73e59e1cc8d0934c651bba7c2b99f8ac5dc92b.tar.gz
merchant-4e73e59e1cc8d0934c651bba7c2b99f8ac5dc92b.tar.bz2
merchant-4e73e59e1cc8d0934c651bba7c2b99f8ac5dc92b.zip
-refactoring towards batch deposits
Diffstat (limited to 'src')
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-pay.c179
1 files changed, 94 insertions, 85 deletions
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
index 690a1921..82419668 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -58,6 +58,7 @@
*/
struct PayContext;
+
/**
* Information kept during a pay request for each coin.
*/
@@ -81,15 +82,9 @@ struct DepositConfirmation
char *exchange_url;
/**
- * Hash of the denomination of this coin.
+ * Details about the coin being deposited.
*/
- struct TALER_DenominationHashP h_denom;
-
- /**
- * Amount this coin contributes to the total purchase price.
- * This amount includes the deposit fee.
- */
- struct TALER_Amount amount_with_fee;
+ struct TALER_EXCHANGE_CoinDepositDetail cdd;
/**
* Fee charged by the exchange for the deposit operation of this coin.
@@ -107,21 +102,6 @@ struct DepositConfirmation
struct TALER_Amount wire_fee;
/**
- * Public key of the coin.
- */
- struct TALER_CoinSpendPublicKeyP coin_pub;
-
- /**
- * Signature using the @e denom key over the @e coin_pub.
- */
- struct TALER_DenominationSignature ub_sig;
-
- /**
- * Signature of the coin's private key over the contract.
- */
- struct TALER_CoinSpendSignatureP coin_sig;
-
- /**
* If a minimum age was required (i. e. pc->minimum_age is large enough),
* this is the signature of the minimum age (as a single uint8_t), using the
* private key to the corresponding age group. Might be all zeroes for no
@@ -129,9 +109,6 @@ struct DepositConfirmation
*/
struct TALER_AgeAttestation minimum_age_sig;
- /* true, if no field "minimum_age_sig" was found in the JSON blob */
- bool no_minimum_age_sig;
-
/**
* If a minimum age was required (i. e. pc->minimum_age is large enough),
* this is the age commitment (i. e. age mask and vector of EdDSA public
@@ -141,20 +118,6 @@ struct DepositConfirmation
*/
struct TALER_AgeCommitment age_commitment;
- /* true, if no field "age_commitment" was found in the JSON blob */
- bool no_age_commitment;
-
- /**
- * In the case that somebody pays with a coin that is age restricted, but the
- * the contract did not ask for a minimum age, the merchant still needs the
- * hash of the age commitment in order to a) verify the coin and b) deposit
- * it.
- */
- struct TALER_AgeCommitmentHash h_age_commitment;
-
- /* true, if no field "h_age_commitment" was found in the JSON blob */
- bool no_h_age_commitment;
-
/**
* Age mask in the denomination that defines the age groups. Only
* applicable, if minimum age was required.
@@ -168,6 +131,21 @@ struct DepositConfirmation
unsigned int index;
/**
+ * true, if no field "age_commitment" was found in the JSON blob
+ */
+ bool no_age_commitment;
+
+ /**
+ * True, if no field "minimum_age_sig" was found in the JSON blob
+ */
+ bool no_minimum_age_sig;
+
+ /**
+ * true, if no field "h_age_commitment" was found in the JSON blob
+ */
+ bool no_h_age_commitment;
+
+ /**
* true if we found this coin in the database.
*/
bool found_in_db;
@@ -181,6 +159,33 @@ struct DepositConfirmation
/**
+ * Information kept during a pay request for each exchange.
+ */
+struct ExchangeGroup
+{
+
+ /**
+ * Handle to the batch deposit operation we are performing for this
+ * exchange, NULL after the operation is done.
+ */
+ struct TALER_EXCHANGE_BatchDepositHandle *bdh;
+
+ /**
+ * Handle for operation to lookup /keys (and auditors) from
+ * the exchange used for this transaction; NULL if no operation is
+ * pending.
+ */
+ struct TMH_EXCHANGES_FindOperation *fo;
+
+ /**
+ * URL of the exchange that issued this coin.
+ */
+ char *exchange_url;
+
+};
+
+
+/**
* Information we keep for an individual call to the /pay handler.
*/
struct PayContext
@@ -197,6 +202,12 @@ struct PayContext
struct PayContext *prev;
/**
+ * Array with @e num_exchange exchanges we are depositing
+ * coins into.
+ */
+ struct ExchangeGroup *eg;
+
+ /**
* Array with @e coins_cnt coins we are despositing.
*/
struct DepositConfirmation *dc;
@@ -307,11 +318,6 @@ struct PayContext
struct TALER_Amount max_wire_fee;
/**
- * Minimum age required for this purchase.
- */
- unsigned int minimum_age;
-
- /**
* Amount from @e root. This is the amount the merchant expects
* to make, minus @e max_fee.
*/
@@ -368,12 +374,23 @@ struct PayContext
uint32_t wire_fee_amortization;
/**
+ * Minimum age required for this purchase.
+ */
+ unsigned int minimum_age;
+
+ /**
* Number of coins this payment is made of. Length
* of the @e dc array.
*/
unsigned int coins_cnt;
/**
+ * Number of exchanges involved in the payment. Length
+ * of the @e eg array.
+ */
+ unsigned int num_exchanges;
+
+ /**
* How often have we retried the 'main' transaction?
*/
unsigned int retry_counter;
@@ -678,7 +695,7 @@ pay_context_cleanup (void *cls)
{
struct DepositConfirmation *dc = &pc->dc[i];
- TALER_denom_sig_free (&dc->ub_sig);
+ TALER_denom_sig_free (&dc->cdd.denom_sig);
GNUNET_free (dc->exchange_url);
}
GNUNET_free (pc->dc);
@@ -904,7 +921,7 @@ check_kyc (struct PayContext *pc,
kc->wm = pc->wm;
kc->exchange_url = GNUNET_strdup (dc->exchange_url);
kc->h_contract_terms = pc->h_contract_terms;
- kc->coin_pub = dc->coin_pub;
+ kc->coin_pub = dc->cdd.coin_pub;
GNUNET_CONTAINER_DLL_insert (kc_head,
kc_tail,
kc);
@@ -965,9 +982,9 @@ deposit_cb (void *cls,
pc->hc->instance->settings.id,
dr->details.success.deposit_timestamp,
&pc->h_contract_terms,
- &dc->coin_pub,
+ &dc->cdd.coin_pub,
dc->exchange_url,
- &dc->amount_with_fee,
+ &dc->cdd.amount,
&dc->deposit_fee,
&dc->refund_fee,
&dc->wire_fee,
@@ -1045,7 +1062,7 @@ deposit_cb (void *cls,
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS),
TMH_pack_exchange_reply (&dr->hr),
GNUNET_JSON_pack_data_auto ("coin_pub",
- &dc->coin_pub)));
+ &dc->cdd.coin_pub)));
return;
}
resume_pay_with_response (
@@ -1056,7 +1073,7 @@ deposit_cb (void *cls,
TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS),
TMH_pack_exchange_reply (&dr->hr),
GNUNET_JSON_pack_data_auto ("coin_pub",
- &dc->coin_pub)));
+ &dc->cdd.coin_pub)));
return;
} /* end switch */
}
@@ -1143,7 +1160,7 @@ process_pay_with_exchange (
continue;
denom_details
= TALER_EXCHANGE_get_denomination_key_by_hash (keys,
- &dc->h_denom);
+ &dc->cdd.h_denom_pub);
if (NULL == denom_details)
{
if (! pc->tried_force_keys)
@@ -1167,7 +1184,7 @@ process_pay_with_exchange (
TALER_JSON_pack_ec (
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND),
GNUNET_JSON_pack_data_auto ("h_denom_pub",
- &dc->h_denom),
+ &dc->cdd.h_denom_pub),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_object_incref (
"exchange_keys",
@@ -1259,7 +1276,7 @@ AGE_FAIL:
/* Age restriction successfully verified!
* Calculate the hash of the age commitment. */
TALER_age_commitment_hash (&dc->age_commitment,
- &dc->h_age_commitment);
+ &dc->cdd.h_age_commitment);
GNUNET_free (dc->age_commitment.keys);
}
else if (is_age_restricted_denom)
@@ -1289,14 +1306,6 @@ AGE_FAIL:
GNUNET_assert (NULL != pc->wm);
TMH_db->preflight (TMH_db->cls);
{
- struct TALER_EXCHANGE_CoinDepositDetail cdd = {
- .amount = dc->amount_with_fee,
- .coin_pub = dc->coin_pub,
- .coin_sig = dc->coin_sig,
- .denom_sig = dc->ub_sig,
- .h_denom_pub = denom_details->h_key,
- .h_age_commitment = dc->h_age_commitment
- };
struct TALER_EXCHANGE_DepositContractDetail dcd = {
.wire_deadline = pc->wire_transfer_deadline,
.merchant_payto_uri = pc->wm->payto_uri,
@@ -1310,7 +1319,7 @@ AGE_FAIL:
dc->dh = TALER_EXCHANGE_deposit (exchange_handle,
&dcd,
- &cdd,
+ &dc->cdd,
&deposit_cb,
dc,
&ec);
@@ -1409,12 +1418,12 @@ check_coin_paid (void *cls,
continue; /* processed earlier, skip "expensive" memcmp() */
/* Get matching coin from results*/
if ( (0 != GNUNET_memcmp (coin_pub,
- &dc->coin_pub)) ||
+ &dc->cdd.coin_pub)) ||
(0 !=
strcmp (exchange_url,
dc->exchange_url)) ||
(0 != TALER_amount_cmp (amount_with_fee,
- &dc->amount_with_fee)) )
+ &dc->cdd.amount)) )
continue; /* does not match, skip */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Deposit of coin `%s' already in our DB.\n",
@@ -1431,7 +1440,7 @@ check_coin_paid (void *cls,
dc->deposit_fee = *deposit_fee;
dc->refund_fee = *refund_fee;
dc->wire_fee = *wire_fee;
- dc->amount_with_fee = *amount_with_fee;
+ dc->cdd.amount = *amount_with_fee;
dc->found_in_db = true;
pc->pending--;
}
@@ -1469,7 +1478,7 @@ check_coin_refunded (void *cls,
/* Get matching coins from results. */
if (0 != GNUNET_memcmp (coin_pub,
- &dc->coin_pub))
+ &dc->cdd.coin_pub))
continue;
GNUNET_assert (0 <=
TALER_amount_add (&pc->total_refunded,
@@ -1506,7 +1515,7 @@ check_payment_sufficient (struct PayContext *pc)
acc_fee = pc->dc[0].deposit_fee;
total_wire_fee = pc->dc[0].wire_fee;
- acc_amount = pc->dc[0].amount_with_fee;
+ acc_amount = pc->dc[0].cdd.amount;
/**
* This loops calculates what are the deposit fee / total
@@ -1523,7 +1532,7 @@ check_payment_sufficient (struct PayContext *pc)
&acc_fee)) ||
(0 >
TALER_amount_add (&acc_amount,
- &dc->amount_with_fee,
+ &dc->cdd.amount,
&acc_amount)) )
{
GNUNET_break (0);
@@ -1536,7 +1545,7 @@ check_payment_sufficient (struct PayContext *pc)
}
if (1 ==
TALER_amount_cmp (&dc->deposit_fee,
- &dc->amount_with_fee))
+ &dc->cdd.amount))
{
GNUNET_break_op (0);
resume_pay_with_error (pc,
@@ -2100,16 +2109,16 @@ parse_pay (struct PayContext *pc)
const char *exchange_url;
struct GNUNET_JSON_Specification ispec[] = {
GNUNET_JSON_spec_fixed_auto ("coin_sig",
- &dc->coin_sig),
+ &dc->cdd.coin_sig),
GNUNET_JSON_spec_fixed_auto ("coin_pub",
- &dc->coin_pub),
+ &dc->cdd.coin_pub),
TALER_JSON_spec_denom_sig ("ub_sig",
- &dc->ub_sig),
+ &dc->cdd.denom_sig),
GNUNET_JSON_spec_fixed_auto ("h_denom",
- &dc->h_denom),
+ &dc->cdd.h_denom_pub),
TALER_JSON_spec_amount ("contribution",
TMH_currency,
- &dc->amount_with_fee),
+ &dc->cdd.amount),
GNUNET_JSON_spec_string ("exchange_url",
&exchange_url),
/* if a minimum age was required, the minimum_age_sig and
@@ -2126,7 +2135,7 @@ parse_pay (struct PayContext *pc)
* was used, h_age_commitment must be provided. */
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
- &dc->h_age_commitment),
+ &dc->cdd.h_age_commitment),
&dc->no_h_age_commitment),
GNUNET_JSON_spec_end ()
};
@@ -2145,8 +2154,8 @@ parse_pay (struct PayContext *pc)
for (unsigned int j = 0; j<coins_index; j++)
{
if (0 ==
- GNUNET_memcmp (&dc->coin_pub,
- &pc->dc[j].coin_pub))
+ GNUNET_memcmp (&dc->cdd.coin_pub,
+ &pc->dc[j].cdd.coin_pub))
{
GNUNET_break_op (0);
return (MHD_YES ==
@@ -2164,7 +2173,7 @@ parse_pay (struct PayContext *pc)
dc->pc = pc;
if (0 !=
- strcasecmp (dc->amount_with_fee.currency,
+ strcasecmp (dc->cdd.amount.currency,
TMH_currency))
{
GNUNET_break_op (0);
@@ -2231,13 +2240,13 @@ deposit_paid_check (
struct DepositConfirmation *dci = &pc->dc[i];
if ( (0 ==
- GNUNET_memcmp (&dci->coin_pub,
+ GNUNET_memcmp (&dci->cdd.coin_pub,
coin_pub)) &&
(0 ==
strcmp (dci->exchange_url,
exchange_url)) &&
(0 ==
- TALER_amount_cmp (&dci->amount_with_fee,
+ TALER_amount_cmp (&dci->cdd.amount,
amount_with_fee)) )
{
dci->matched_in_db = true;
@@ -2317,10 +2326,10 @@ handle_contract_paid (struct PayContext *pc)
if (dci->matched_in_db)
continue;
- TALER_merchant_refund_sign (&dci->coin_pub,
+ TALER_merchant_refund_sign (&dci->cdd.coin_pub,
&pc->h_contract_terms,
0, /* rtransaction id */
- &dci->amount_with_fee,
+ &dci->cdd.amount,
&pc->hc->instance->merchant_priv,
&merchant_sig);
GNUNET_assert (
@@ -2330,12 +2339,12 @@ handle_contract_paid (struct PayContext *pc)
GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto (
"coin_pub",
- &dci->coin_pub),
+ &dci->cdd.coin_pub),
GNUNET_JSON_pack_data_auto (
"merchant_sig",
&merchant_sig),
TALER_JSON_pack_amount ("amount",
- &dci->amount_with_fee),
+ &dci->cdd.amount),
GNUNET_JSON_pack_uint64 ("rtransaction_id",
0))));
}