diff options
author | Christian Grothoff <christian@grothoff.org> | 2023-08-24 22:09:13 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2023-08-24 22:09:13 +0200 |
commit | b4dbf7bcf38e183c0ddd39b48e911221bdd9d36c (patch) | |
tree | 5c3db74a94f0c8fb1eacbbce13b032645c34d187 /src/backend | |
parent | d4cbd450a5eb55a33e753ff28e85debe8016577a (diff) |
add merchant backend support for STEFAN curves
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/taler-merchant-httpd_exchanges.h | 2 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-orders.c | 211 |
2 files changed, 152 insertions, 61 deletions
diff --git a/src/backend/taler-merchant-httpd_exchanges.h b/src/backend/taler-merchant-httpd_exchanges.h index b0f2d879..d8202922 100644 --- a/src/backend/taler-merchant-httpd_exchanges.h +++ b/src/backend/taler-merchant-httpd_exchanges.h @@ -125,6 +125,7 @@ void TMH_exchange_get_trusted (TMH_ExchangeCallback cb, void *cb_cls); + /** * Return the master public key of the given @a exchange. * Will be returned from configuration for trusted @@ -137,6 +138,7 @@ const struct TALER_MasterPublicKeyP * TMH_EXCHANGES_get_master_pub ( const struct TMH_Exchange *exchange); + /** * Lookup current wire fee by @a exchange_url and * @a wire_method. diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c index 370050d4..409c3eec 100644 --- a/src/backend/taler-merchant-httpd_private-post-orders.c +++ b/src/backend/taler-merchant-httpd_private-post-orders.c @@ -176,6 +176,24 @@ struct OrderContext json_t *order; /** + * Maximum fee for @e order based on STEFAN curves. + * Used to set @e max_fee if not provided as part of + * @e order. + */ + struct TALER_Amount max_stefan_fee; + + /** + * Maximum fee as given by the client request. + */ + struct TALER_Amount max_fee; + + /** + * Gross amount value of the contract. Used to + * compute @e max_stefan_fee. + */ + struct TALER_Amount brutto; + + /** * Array of exchanges we find acceptable for this * order. */ @@ -265,6 +283,7 @@ struct OrderContext ORDER_PHASE_ADD_PAYMENT_DETAILS, ORDER_PHASE_PATCH_ORDER, ORDER_PHASE_SET_EXCHANGES, + ORDER_PHASE_SET_MAX_FEE, ORDER_PHASE_CHECK_CONTRACT, ORDER_PHASE_EXECUTE_ORDER, @@ -532,7 +551,6 @@ execute_order (struct OrderContext *oc) { const struct TALER_MERCHANTDB_InstanceSettings *settings = &oc->hc->instance->settings; - struct TALER_Amount total; const char *summary; const char *fulfillment_msg = NULL; const json_t *products; @@ -541,9 +559,6 @@ execute_order (struct OrderContext *oc) struct GNUNET_TIME_Timestamp refund_deadline = { 0 }; struct GNUNET_TIME_Timestamp wire_transfer_deadline; struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount ("amount", - TMH_currency, - &total), GNUNET_JSON_spec_string ("order_id", &oc->order_id), TALER_JSON_spec_i18n_str ("summary", @@ -857,6 +872,47 @@ check_contract (struct OrderContext *oc) /** + * Update MAX STEFAN fees based on @a keys. + * + * @param[in,out] oc order context to update + * @param keys keys to derive STEFAN fees from + */ +static void +update_stefan (struct OrderContext *oc, + const struct TALER_EXCHANGE_Keys *keys) +{ + struct TALER_Amount net; + + if (0 == keys->num_denom_keys) + sleep (600); + if (GNUNET_SYSERR != + TALER_EXCHANGE_keys_stefan_b2n (keys, + &oc->brutto, + &net)) + { + struct TALER_Amount fee; + + TALER_EXCHANGE_keys_stefan_round (keys, + &net); + GNUNET_assert (0 <= + TALER_amount_subtract (&fee, + &oc->brutto, + &net)); + if ( (GNUNET_OK != + TALER_amount_is_valid (&oc->max_stefan_fee)) || + (-1 == TALER_amount_cmp (&oc->max_stefan_fee, + &fee)) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Updated STEFAN-based fee to %s\n", + TALER_amount2s (&fee)); + oc->max_stefan_fee = fee; + } + } +} + + +/** * Compute the set of exchanges that would be acceptable * for this order. * @@ -918,13 +974,15 @@ get_acceptable (void *cls, * @param exchange representation of the exchange */ static void -keys_forced ( +keys_cb ( void *cls, struct TALER_EXCHANGE_Keys *keys, struct TMH_Exchange *exchange) { struct RekeyExchange *rx = cls; struct OrderContext *oc = rx->oc; + const struct TALER_MERCHANTDB_InstanceSettings *settings = + &oc->hc->instance->settings; rx->fo = NULL; GNUNET_CONTAINER_DLL_remove (oc->pending_reload_head, @@ -936,6 +994,14 @@ keys_forced ( "Failed to download %s/keys\n", rx->url); } + else + { + if ( (settings->use_stefan) && + (GNUNET_OK != + TALER_amount_is_valid (&oc->max_fee)) ) + update_stefan (oc, + keys); + } get_acceptable (oc, rx->url, exchange); @@ -966,9 +1032,9 @@ keys_forced ( * @param exchange internal handle for the exchange */ static void -rekey_exchanges (void *cls, - const char *url, - const struct TMH_Exchange *exchange) +get_exchange_keys (void *cls, + const char *url, + const struct TMH_Exchange *exchange) { struct OrderContext *oc = cls; struct RekeyExchange *rx; @@ -983,13 +1049,49 @@ rekey_exchanges (void *cls, "Forcing download of %s/keys\n", url); rx->fo = TMH_EXCHANGES_keys4exchange (url, - true, - &keys_forced, + oc->forced_reload, + &keys_cb, rx); } /** + * Set max_fee in @a oc based on STEFAN value if + * not yet present. + * + * @param[in,out] oc order context + */ +static void +set_max_fee (struct OrderContext *oc) +{ + const struct TALER_MERCHANTDB_InstanceSettings *settings = + &oc->hc->instance->settings; + + if (GNUNET_OK != + TALER_amount_is_valid (&oc->max_fee)) + { + struct TALER_Amount stefan; + + if ( (settings->use_stefan) && + (GNUNET_OK == + TALER_amount_is_valid (&oc->max_stefan_fee)) ) + stefan = oc->max_stefan_fee; + else + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (TMH_currency, + &stefan)); + GNUNET_assert (0 == + json_object_set_new ( + oc->order, + "max_fee", + TALER_JSON_from_amount (&stefan))); + } + + oc->phase++; +} + + +/** * Set list of acceptable exchanges in @a oc. * * @param[in,out] oc order context @@ -1002,41 +1104,46 @@ set_exchanges (struct OrderContext *oc) expensive; could likely consider caching the result if it starts to matter. */ if (NULL == oc->exchanges) + { oc->exchanges = json_array (); - TMH_exchange_get_trusted (&get_acceptable, - oc); - if (! oc->exchange_good) + TMH_exchange_get_trusted (&get_exchange_keys, + oc); + } + else if (! oc->exchange_good) { if (! oc->forced_reload) { oc->forced_reload = true; GNUNET_assert (0 == json_array_clear (oc->exchanges)); - TMH_exchange_get_trusted (&rekey_exchanges, + TMH_exchange_get_trusted (&get_exchange_keys, oc); } - if (NULL != oc->pending_reload_head) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Still trying to re-load /keys\n"); - MHD_suspend_connection (oc->connection); - oc->suspended = GNUNET_YES; - GNUNET_CONTAINER_DLL_insert (oc_head, - oc_tail, - oc); - return true; /* reloads pending */ - } - if (0 == json_array_size (oc->exchanges)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Cannot create order: lacking trusted exchanges\n"); - reply_with_error ( - oc, - MHD_HTTP_CONFLICT, - TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGES_FOR_WIRE_METHOD, - oc->wm->wire_method); - return false; - } + } + if (NULL != oc->pending_reload_head) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Still trying to re-load /keys\n"); + MHD_suspend_connection (oc->connection); + oc->suspended = GNUNET_YES; + GNUNET_CONTAINER_DLL_insert (oc_head, + oc_tail, + oc); + return true; /* reloads pending */ + } + if (0 == json_array_size (oc->exchanges)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Cannot create order: lacking trusted exchanges\n"); + reply_with_error ( + oc, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGES_FOR_WIRE_METHOD, + oc->wm->wire_method); + return false; + } + if (! oc->exchange_good) + { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Creating order, but possibly without usable trusted exchanges\n"); } @@ -1066,7 +1173,6 @@ patch_order (struct OrderContext *oc) const char *merchant_base_url = NULL; const json_t *jmerchant = NULL; const json_t *delivery_location = NULL; - struct TALER_Amount max_fee = { 0 }; struct GNUNET_TIME_Timestamp timestamp = GNUNET_TIME_UNIT_ZERO_TS; struct GNUNET_TIME_Timestamp delivery_date @@ -1092,6 +1198,9 @@ patch_order (struct OrderContext *oc) GNUNET_JSON_spec_string ("order_id", &order_id), NULL), + TALER_JSON_spec_amount ("amount", + TMH_currency, + &oc->brutto), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("fulfillment_url", &fulfillment_url), @@ -1115,7 +1224,7 @@ patch_order (struct OrderContext *oc) GNUNET_JSON_spec_mark_optional ( TALER_JSON_spec_amount ("max_fee", TMH_currency, - &max_fee), + &oc->max_fee), NULL), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_timestamp ("delivery_date", @@ -1352,29 +1461,6 @@ patch_order (struct OrderContext *oc) return; } - /* Note: total amount currency match checked - later in execute_order() */ - if (GNUNET_OK != - TALER_amount_is_valid (&max_fee)) - { - struct TALER_Amount stefan; - - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (TMH_currency, - &stefan)); - if (settings->use_stefan) - { - /* FIXME: update amount from stefan curve! */ - stefan.value = 5; // FIXME! - } - - GNUNET_assert (0 == - json_object_set_new ( - oc->order, - "max_fee", - TALER_JSON_from_amount (&stefan))); - } - if (NULL == merchant_base_url) { char *url; @@ -1868,6 +1954,9 @@ TMH_private_post_orders_with_pos_secrets ( if (set_exchanges (oc)) return MHD_YES; break; + case ORDER_PHASE_SET_MAX_FEE: + set_max_fee (oc); + break; case ORDER_PHASE_CHECK_CONTRACT: check_contract (oc); break; |