diff options
author | Christian Grothoff <christian@grothoff.org> | 2023-02-21 14:21:01 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2023-02-21 14:21:01 +0100 |
commit | 243045a63fac366ca9c3cb8f97220b76249a8f51 (patch) | |
tree | dc25c6b8534653c60861ec7a5a6fd4760df96495 | |
parent | e5a9bd4c35135cd58a106355d1651c8dfc7b9da5 (diff) |
POS secret support
-rw-r--r-- | src/backend/taler-merchant-httpd_get-orders-ID.c | 1 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_post-orders-ID-pay.c | 16 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_post-using-templates.c | 11 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-orders.c | 36 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-orders.h | 20 | ||||
-rw-r--r-- | src/backenddb/merchant-0004.sql | 12 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 172 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 69 |
8 files changed, 221 insertions, 116 deletions
diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c b/src/backend/taler-merchant-httpd_get-orders-ID.c index f97d9d40..ab4de015 100644 --- a/src/backend/taler-merchant-httpd_get-orders-ID.c +++ b/src/backend/taler-merchant-httpd_get-orders-ID.c @@ -1059,7 +1059,6 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh, TALER_EC_GENERIC_DB_FETCH_FAILED, "lookup_contract_terms"); } - /* Note: when "!ord.requireClaimToken" and the client does not provide a claim token (all zeros!), then token_match==TRUE below: */ token_match = (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) 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 9b9b1a00..278bd473 100644 --- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c +++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c @@ -2579,13 +2579,15 @@ check_contract (struct PayContext *pc) json_decref (pc->contract_terms); pc->contract_terms = NULL; } - qs = TMH_db->lookup_contract_terms (TMH_db->cls, - pc->hc->instance->settings.id, - pc->order_id, - &pc->contract_terms, - &pc->order_serial, - &paid, - NULL); // FIXME: add &pc->pos_key + &pc->pos_alg! + qs = TMH_db->lookup_contract_terms2 (TMH_db->cls, + pc->hc->instance->settings.id, + pc->order_id, + &pc->contract_terms, + &pc->order_serial, + &paid, + NULL, + &pc->pos_key, + &pc->pos_alg); if (0 > qs) { /* single, read-only SQL statements should never cause diff --git a/src/backend/taler-merchant-httpd_post-using-templates.c b/src/backend/taler-merchant-httpd_post-using-templates.c index 0f875853..aeb50cee 100644 --- a/src/backend/taler-merchant-httpd_post-using-templates.c +++ b/src/backend/taler-merchant-httpd_post-using-templates.c @@ -45,7 +45,8 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh, json_t *fake_body; bool no_summary; struct TALER_MERCHANTDB_TemplateDetails etp; - + char *pos_key = NULL; // FIXME: fetch from DB! + enum TALER_MerchantConfirmationAlgorithm pos_algorithm = TALER_MCA_NONE; // FIXME fetch from DB! struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("summary", @@ -234,9 +235,11 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh, .instance = hc->instance }; - mret = TMH_private_post_orders (NULL, /* not even used */ - connection, - &fake_hc); + mret = TMH_private_post_orders_with_pos_secrets (NULL, /* not even used */ + connection, + &fake_hc, + pos_key, + pos_algorithm); } TALER_MERCHANTDB_template_details_free (&etp); json_decref (fake_body); diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c index 62ac3b15..66c698e8 100644 --- a/src/backend/taler-merchant-httpd_private-post-orders.c +++ b/src/backend/taler-merchant-httpd_private-post-orders.c @@ -277,7 +277,9 @@ execute_transaction (struct TMH_HandlerContext *hc, h_post_data, pay_deadline, claim_token, - order); // called 'contract terms' at database. + order, /* called 'contract terms' at database. */ + NULL, // FIXME! + TALER_MCA_NONE); // FIXME: use from TMH_private_post_orders_with_pos_secrets if (qs <= 0) { /* qs == 0: probably instance does not exist (anymore) */ @@ -1439,20 +1441,13 @@ merge_inventory (struct MHD_Connection *connection, } -/** - * Generate an order. We add the fields 'exchanges', 'merchant_pub', and - * 'H_wire' to the order gotten from the frontend, as well as possibly other - * fields if the frontend did not provide them. Returns the order_id. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ MHD_RESULT -TMH_private_post_orders (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) +TMH_private_post_orders_with_pos_secrets ( + const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc, + const char *pos_key, + enum TALER_MerchantConfirmationAlgorithm pos_algorithm) { json_t *order; struct GNUNET_TIME_Relative refund_delay = GNUNET_TIME_UNIT_ZERO; @@ -1668,4 +1663,17 @@ TMH_private_post_orders (const struct TMH_RequestHandler *rh, } +MHD_RESULT +TMH_private_post_orders (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + return TMH_private_post_orders_with_pos_secrets (rh, + connection, + hc, + NULL, + TALER_MCA_NONE); +} + + /* end of taler-merchant-httpd_private-post-orders.c */ diff --git a/src/backend/taler-merchant-httpd_private-post-orders.h b/src/backend/taler-merchant-httpd_private-post-orders.h index 9bffb6aa..9d7b1841 100644 --- a/src/backend/taler-merchant-httpd_private-post-orders.h +++ b/src/backend/taler-merchant-httpd_private-post-orders.h @@ -38,5 +38,25 @@ TMH_private_post_orders (const struct TMH_RequestHandler *rh, struct MHD_Connection *connection, struct TMH_HandlerContext *hc); +/** + * Generate an order. We add the fields 'exchanges', 'merchant_pub', and + * 'H_wire' to the order gotten from the frontend, as well as possibly other + * fields if the frontend did not provide them. Returns the order_id. + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param[in,out] hc context with further information about the request + * @param pos_key key identifying the POS, can be NULL + * @param pos_algorithm algorithm for computing the POS confirmation + * @return MHD result code + */ +MHD_RESULT +TMH_private_post_orders_with_pos_secrets ( + const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc, + const char *pos_key, + enum TALER_MerchantConfirmationAlgorithm pos_algorithm); + #endif diff --git a/src/backenddb/merchant-0004.sql b/src/backenddb/merchant-0004.sql index 695166ff..41d1008b 100644 --- a/src/backenddb/merchant-0004.sql +++ b/src/backenddb/merchant-0004.sql @@ -112,23 +112,23 @@ COMMENT ON COLUMN merchant_kyc.aml_decision ALTER TABLE merchant_orders ADD COLUMN pos_key VARCHAR DEFAULT NULL; - ADD COLUMN pricing_algorithm INT8; + ADD COLUMN pos_algorithm INT4 NOT NULL DEFAULT (0); COMMENT ON COLUMN merchant_orders.pos_key IS 'encoded based key which is used for the verification of payment'; -COMMENT ON COLUMN merchant_orders.pricing_algorithm - IS 'algorithm to put the price of the order. It is link with the pos_key'; +COMMENT ON COLUMN merchant_orders.pos_algorithm + IS 'algorithm to used to generate the confirmation code. It is link with the pos_key'; ALTER TABLE merchant_contract_terms ADD COLUMN pos_key VARCHAR DEFAULT NULL; - ADD COLUMN pricing_algorithm INT8; + ADD COLUMN pos_algorithm INT4 NOT NULL DEFAULT (0); COMMENT ON COLUMN merchant_contract_terms.pos_key IS 'enconded based key which is used for the verification of payment'; -COMMENT ON COLUMN merchant_orders.pricing_algorithm - IS 'algorithm to put the price of the order. It is link with the pos_key'; +COMMENT ON COLUMN merchant_orders.pos_algorithm + IS 'algorithm to used to generate the confirmation code. It is link with the pos_key'; COMMIT; diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 48e0d63c..f8ef6efb 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -1694,8 +1694,6 @@ postgres_delete_order (void *cls, * @param[out] h_post_data set to the hash of the POST data that created the order * @param[out] contract_terms where to store the retrieved contract terms, * NULL to only test if the order exists - * @param pos_key encoded key for payment verification - * @param pricing_algorithm to show the price in the payment verification * @return transaction status */ static enum GNUNET_DB_QueryStatus @@ -1704,9 +1702,7 @@ postgres_lookup_order (void *cls, const char *order_id, struct TALER_ClaimTokenP *claim_token, struct TALER_MerchantPostDataHashP *h_post_data, - json_t **contract_terms, - char *pos_key, - uint64_t pricing_algorithm) + json_t **contract_terms) { struct PostgresClosure *pg = cls; json_t *j; @@ -1724,14 +1720,6 @@ postgres_lookup_order (void *cls, &ct), GNUNET_PQ_result_spec_auto_from_type ("h_post_data", h_post_data), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("pos_key", - &pos_key), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ("pricing_algorithm", - &pricing_algorithm), - NULL), GNUNET_PQ_result_spec_end }; @@ -1950,7 +1938,7 @@ postgres_lookup_orders (void *cls, * @param claim_token token to use for access control * @param contract_terms proposal data to store * @param pos_key encoded key for payment verification - * @param pricing_algorithm to show the price in the payment verification + * @param pos_algorithm algorithm to compute the payment verification * @return transaction status */ static enum GNUNET_DB_QueryStatus @@ -1962,10 +1950,11 @@ postgres_insert_order (void *cls, const struct TALER_ClaimTokenP *claim_token, const json_t *contract_terms, const char *pos_key, - uint64_t pricing_algorithm) + enum TALER_MerchantConfirmationAlgorithm pos_algorithm) { struct PostgresClosure *pg = cls; struct GNUNET_TIME_Timestamp now; + uint32_t pos32 = (uint32_t) pos_algorithm; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_string (instance_id), GNUNET_PQ_query_param_string (order_id), @@ -1977,9 +1966,7 @@ postgres_insert_order (void *cls, (NULL == pos_key) ? GNUNET_PQ_query_param_null () : GNUNET_PQ_query_param_string (pos_key), - (NULL == pos_key) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 (&pricing_algorithm), + GNUNET_PQ_query_param_uint32 (&pos32), GNUNET_PQ_query_param_end }; @@ -2071,15 +2058,16 @@ postgres_insert_order_lock (void *cls, * @return transaction status */ static enum GNUNET_DB_QueryStatus -postgres_lookup_contract_terms (void *cls, - const char *instance_id, - const char *order_id, - json_t **contract_terms, - uint64_t *order_serial, - bool *paid, - struct TALER_ClaimTokenP *claim_token, - char *pos_key, - uint64_t pricing_algorithm) +postgres_lookup_contract_terms2 ( + void *cls, + const char *instance_id, + const char *order_id, + json_t **contract_terms, + uint64_t *order_serial, + bool *paid, + struct TALER_ClaimTokenP *claim_token, + char **pos_key, + enum TALER_MerchantConfirmationAlgorithm *pos_algorithm) { struct PostgresClosure *pg = cls; enum GNUNET_DB_QueryStatus qs; @@ -2089,6 +2077,7 @@ postgres_lookup_contract_terms (void *cls, GNUNET_PQ_query_param_string (order_id), GNUNET_PQ_query_param_end }; + uint32_t pos32; struct GNUNET_PQ_ResultSpec rs[] = { /* contract_terms must be first! */ TALER_PQ_result_spec_json ("contract_terms", @@ -2101,12 +2090,68 @@ postgres_lookup_contract_terms (void *cls, &ct), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_string ("pos_key", - &pos_key), - NULL), + pos_key), + NULL), GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ("pricing_algorithm", - &pricing_algorithm), - NULL), + GNUNET_PQ_result_spec_uint32 ("pos_algorithm", + &pos32), + NULL), + GNUNET_PQ_result_spec_end + }; + + check_connection (pg); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_contract_terms2", + params, + (NULL != contract_terms) + ? rs + : &rs[1]); + *pos_algorithm = (enum TALER_MerchantConfirmationAlgorithm) pos32; + if (NULL != claim_token) + *claim_token = ct; + return qs; +} + + +/** + * Retrieve contract terms given its @a order_id + * + * @param cls closure + * @param instance_id instance's identifier + * @param order_id order_id used to lookup. + * @param[out] contract_terms where to store the result, NULL to only check for existence + * @param[out] order_serial set to the order's serial number + * @param[out] paid set to true if the order is fully paid + * @return transaction status + */ +static enum GNUNET_DB_QueryStatus +postgres_lookup_contract_terms ( + void *cls, + const char *instance_id, + const char *order_id, + json_t **contract_terms, + uint64_t *order_serial, + bool *paid, + struct TALER_ClaimTokenP *claim_token) +{ + struct PostgresClosure *pg = cls; + enum GNUNET_DB_QueryStatus qs; + struct TALER_ClaimTokenP ct; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (order_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + /* contract_terms must be first! */ + TALER_PQ_result_spec_json ("contract_terms", + contract_terms), + GNUNET_PQ_result_spec_uint64 ("order_serial", + order_serial), + GNUNET_PQ_result_spec_bool ("paid", + paid), + GNUNET_PQ_result_spec_auto_from_type ("claim_token", + &ct), GNUNET_PQ_result_spec_end }; @@ -2137,18 +2182,17 @@ postgres_lookup_contract_terms (void *cls, * @param contract_terms contract terms to store * @param[out] order_serial set to the serial of the order * @param pos_key encoded key for payment verification - * @param pricing_algorithm to show the price in the payment verification + * @param pos_algorithm algorithm to compute the payment verification * @return transaction status, #GNUNET_DB_STATUS_HARD_ERROR if @a contract_terms * is malformed */ static enum GNUNET_DB_QueryStatus -postgres_insert_contract_terms (void *cls, - const char *instance_id, - const char *order_id, - json_t *contract_terms, - uint64_t *order_serial, - const char *pos_key, - uint64_t pricing_algorithm) +postgres_insert_contract_terms ( + void *cls, + const char *instance_id, + const char *order_id, + json_t *contract_terms, + uint64_t *order_serial) { struct PostgresClosure *pg = cls; struct GNUNET_TIME_Timestamp pay_deadline; @@ -2199,12 +2243,6 @@ postgres_insert_contract_terms (void *cls, (NULL == fulfillment_url) ? GNUNET_PQ_query_param_null () : GNUNET_PQ_query_param_string (fulfillment_url), - (NULL == pos_key) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (pos_key), - (NULL == pos_key) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 (&pricing_algorithm), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { @@ -2810,12 +2848,12 @@ postgres_refund_coin (void *cls, * @return transaction status */ static enum GNUNET_DB_QueryStatus -postgres_lookup_order_status (void *cls, - const char *instance_id, - const char *order_id, - struct TALER_PrivateContractHashP * - h_contract_terms, - bool *paid) +postgres_lookup_order_status ( + void *cls, + const char *instance_id, + const char *order_id, + struct TALER_PrivateContractHashP *h_contract_terms, + bool *paid) { struct PostgresClosure *pg = cls; uint8_t paid8; @@ -3655,7 +3693,7 @@ process_deposits_for_refund_cb (void *cls, * Although this should be checked as the business should never * issue a refund bigger than the contract's actual price, we cannot * rely upon the frontend being correct. - */// + */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "The refund of %s is bigger than the order's value\n", TALER_amount2s (ctx->refund)); @@ -9028,9 +9066,10 @@ postgres_connect (void *cls) ",h_post_data" ",creation_time" ",contract_terms" - ",pos_key)" + ",pos_key" + ",pos_algorithm)" " SELECT merchant_serial," - " $2, $3, $4, $5, $6, $7, $8" + " $2, $3, $4, $5, $6, $7, $8, $9" " FROM merchant_instances" " WHERE merchant_id=$1"), /* for postgres_unlock_inventory() */ @@ -9075,7 +9114,21 @@ postgres_connect (void *cls) ",order_serial" ",claim_token" ",paid" + " FROM merchant_contract_terms" + " WHERE order_id=$2" + " AND merchant_serial=" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)"), + /* for postgres_lookup_contract_terms() */ + GNUNET_PQ_make_prepare ("lookup_contract_terms2", + "SELECT" + " contract_terms" + ",order_serial" + ",claim_token" + ",paid" ",pos_key" + ",pos_algorithm" " FROM merchant_contract_terms" " WHERE order_id=$2" " AND merchant_serial=" @@ -9095,7 +9148,8 @@ postgres_connect (void *cls) ",refund_deadline" ",fulfillment_url" ",claim_token" - ",pos_key)" + ",pos_key" + ",pos_algorithm)" "SELECT" " mo.order_serial" ",mo.merchant_serial" @@ -9106,8 +9160,9 @@ postgres_connect (void *cls) ",$5" /* pay_deadline */ ",$6" /* refund_deadline */ ",$7" /* fulfillment_url */ - ",$8" /* pos_key */ - ",mo.claim_token " + ",mo.claim_token" + ",mo.pos_key" + ",mo.pos_algorithm" "FROM merchant_orders mo" " WHERE order_id=$2" " AND merchant_serial=" @@ -10600,6 +10655,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) plugin->unlock_inventory = &postgres_unlock_inventory; plugin->insert_order_lock = &postgres_insert_order_lock; plugin->lookup_contract_terms = &postgres_lookup_contract_terms; + plugin->lookup_contract_terms2 = &postgres_lookup_contract_terms2; plugin->insert_contract_terms = &postgres_insert_contract_terms; plugin->update_contract_terms = &postgres_update_contract_terms; plugin->delete_contract_terms = &postgres_delete_contract_terms; diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index 496bc77c..0cedf3ee 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -1416,8 +1416,6 @@ struct TALER_MERCHANTDB_Plugin * @param[out] h_post_data set to the hash of the POST data that created the order * @param[out] contract_terms where to store the retrieved contract terms, * NULL to only test if the order exists - * @param pos_key [out] encoded key for payment verification - * @param pricing_algorithm [out] to show the price in the payment verification * @return transaction status */ enum GNUNET_DB_QueryStatus @@ -1426,9 +1424,7 @@ struct TALER_MERCHANTDB_Plugin const char *order_id, struct TALER_ClaimTokenP *claim_token, struct TALER_MerchantPostDataHashP *h_post_data, - json_t **contract_terms, - char *pos_key, - uint64_t pricing_algorithm); + json_t **contract_terms); /** @@ -1478,7 +1474,7 @@ struct TALER_MERCHANTDB_Plugin * @param claim_token token to use for access control * @param contract_terms proposal data to store * @param pos_key encoded key for payment verification - * @param pricing_algorithm to show the price in the payment verification + * @param pos_algorithm algorithm to compute the payment verification * @return transaction status */ enum GNUNET_DB_QueryStatus @@ -1490,7 +1486,7 @@ struct TALER_MERCHANTDB_Plugin const struct TALER_ClaimTokenP *claim_token, const json_t *contract_terms, const char *pos_key, - uint64_t pricing_algorithm); + enum TALER_MerchantConfirmationAlgorithm pos_algorithm); /** @@ -1539,19 +1535,43 @@ struct TALER_MERCHANTDB_Plugin * @param[out] paid set to true if the order is fully paid * @param[out] claim_token set to the claim token, NULL to only check for existence * @param[out] pos_key encoded key for payment verification - * @param pricing_algorithm [out] to show the price in the payment verification + * @param[out] pos_algorithm set to algorithm to compute the payment verification * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_contract_terms)(void *cls, - const char *instance_id, - const char *order_id, - json_t **contract_terms, - uint64_t *order_serial, - bool *paid, - struct TALER_ClaimTokenP *claim_token, - char *pos_key, - uint64_t pricing_algorithm); + (*lookup_contract_terms2)( + void *cls, + const char *instance_id, + const char *order_id, + json_t **contract_terms, + uint64_t *order_serial, + bool *paid, + struct TALER_ClaimTokenP *claim_token, + char **pos_key, + enum TALER_MerchantConfirmationAlgorithm *pricing_algorithm); + + + /** + * Retrieve contract terms given its @a order_id + * + * @param cls closure + * @param instance_id instance's identifier + * @param order_id order_id used to lookup. + * @param[out] contract_terms where to store the result, NULL to only check for existence + * @param[out] order_serial set to the order's serial number + * @param[out] paid set to true if the order is fully paid + * @param[out] claim_token set to the claim token, NULL to only check for existence + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_contract_terms)( + void *cls, + const char *instance_id, + const char *order_id, + json_t **contract_terms, + uint64_t *order_serial, + bool *paid, + struct TALER_ClaimTokenP *claim_token); /** @@ -1567,19 +1587,16 @@ struct TALER_MERCHANTDB_Plugin * @param order_id order_id used to store * @param claim_token the token belonging to the order * @param[out] order_serial set to the serial of the order - * @param pos_key encoded key for payment verification - * @param pricing_algorithm to show the price in the payment verification * @return transaction status, #GNUNET_DB_STATUS_HARD_ERROR if @a contract_terms * is malformed */ enum GNUNET_DB_QueryStatus - (*insert_contract_terms)(void *cls, - const char *instance_id, - const char *order_id, - json_t *contract_terms, - uint64_t *order_serial, - const char *pos_key, - uint64_t pricing_algorithm); + (*insert_contract_terms)( + void *cls, + const char *instance_id, + const char *order_id, + json_t *contract_terms, + uint64_t *order_serial); /** |