summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcello Stanisci <marcello.stanisci@inria.fr>2017-02-03 18:41:45 +0100
committerMarcello Stanisci <marcello.stanisci@inria.fr>2017-02-03 18:41:45 +0100
commitd9a1d781e072847e51b7fb731c544eeb8bfe5cee (patch)
tree302a082c8119def67bc2e3349b48df732228469c /src
parent36d68f9f47240cfb691644ab003122e5e0fa3915 (diff)
downloadmerchant-d9a1d781e072847e51b7fb731c544eeb8bfe5cee.tar.gz
merchant-d9a1d781e072847e51b7fb731c544eeb8bfe5cee.tar.bz2
merchant-d9a1d781e072847e51b7fb731c544eeb8bfe5cee.zip
renaming: proposal logic ported
Diffstat (limited to 'src')
-rw-r--r--src/backend/Makefile.am3
-rw-r--r--src/backend/taler-merchant-httpd.c18
-rw-r--r--src/backend/taler-merchant-httpd_pay.c10
-rw-r--r--src/backend/taler-merchant-httpd_proposal.c148
-rw-r--r--src/backend/taler-merchant-httpd_proposal.h (renamed from src/backend/taler-merchant-httpd_propose.h)35
-rw-r--r--src/lib/test_merchant_api.c77
6 files changed, 186 insertions, 105 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index db782fe7..c635ef03 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -23,8 +23,7 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_pay.c taler-merchant-httpd_pay.h \
taler-merchant-httpd_history.c taler-merchant-httpd_history.h \
taler-merchant-httpd_track-transaction.c taler-merchant-httpd_track-transaction.h \
- taler-merchant-httpd_track-transfer.c taler-merchant-httpd_track-transfer.h \
- taler-merchant-httpd_map.c taler-merchant-httpd_map.h
+ taler-merchant-httpd_track-transfer.c taler-merchant-httpd_track-transfer.h
taler_merchant_httpd_LDADD = \
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index e571ee62..35894fde 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -35,7 +35,7 @@
#include "taler-merchant-httpd_mhd.h"
#include "taler-merchant-httpd_auditors.h"
#include "taler-merchant-httpd_exchanges.h"
-#include "taler-merchant-httpd_propose.h"
+#include "taler-merchant-httpd_proposal.h"
#include "taler-merchant-httpd_pay.h"
#include "taler-merchant-httpd_track-transaction.h"
#include "taler-merchant-httpd_track-transfer.h"
@@ -164,13 +164,9 @@ url_handler (void *cls,
{ "/", MHD_HTTP_METHOD_GET, "text/plain",
"Hello, I'm a merchant's Taler backend. This HTTP server is not for humans.\n", 0,
&TMH_MHD_handler_static_response, MHD_HTTP_OK },
- { "/contract", MHD_HTTP_METHOD_POST, "application/json",
+ { "/proposal", MHD_HTTP_METHOD_PUT, "application/json",
NULL, 0,
- &MH_handler_propose, MHD_HTTP_OK },
- { "/contract/propose", NULL, "text/plain",
- "Only POST is allowed", 0,
- &TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
+ &MH_handler_proposal_put, MHD_HTTP_OK },
{ "/pay", MHD_HTTP_METHOD_POST, "application/json",
NULL, 0,
&MH_handler_pay, MHD_HTTP_OK },
@@ -192,9 +188,13 @@ url_handler (void *cls,
{ "/history", MHD_HTTP_METHOD_GET, "text/plain",
"Only GET is allowed", 0,
&MH_handler_history, MHD_HTTP_OK},
- { "/contract/lookup", MHD_HTTP_METHOD_GET, "text/plain",
+ { "/proposal", MHD_HTTP_METHOD_GET, "text/plain",
"Only GET is allowed", 0,
- &MH_handler_map_out, MHD_HTTP_OK},
+ &MH_handler_proposal_lookup, MHD_HTTP_OK},
+ { "/proposal", NULL, "text/plain",
+ "Only GET/PUT are allowed", 0,
+ &TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
+
{NULL, NULL, NULL, NULL, 0, 0 }
};
static struct TMH_RequestHandler h404 =
diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c
index f9810746..17c31c7b 100644
--- a/src/backend/taler-merchant-httpd_pay.c
+++ b/src/backend/taler-merchant-httpd_pay.c
@@ -941,7 +941,7 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
json_t *coin;
unsigned int coins_index;
struct TALER_MerchantSignatureP merchant_sig;
- struct TALER_ContractPS cp;
+ struct TALER_ProposalDataPS pdps;
const char *chosen_exchange;
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount ("amount", &pc->amount),
@@ -988,12 +988,12 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
pc->chosen_exchange = GNUNET_strdup (chosen_exchange);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Parsed JSON for /pay.\n");
- cp.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
- cp.purpose.size = htonl (sizeof (struct TALER_ContractPS));
- cp.h_contract = pc->h_contract;
+ pdps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
+ pdps.purpose.size = htonl (sizeof (pdps));
+ pdps.h_proposal_data = pc->h_contract;
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_CONTRACT,
- &cp.purpose,
+ &pdps.purpose,
&merchant_sig.eddsa_sig,
&pc->mi->pubkey.eddsa_pub))
{
diff --git a/src/backend/taler-merchant-httpd_proposal.c b/src/backend/taler-merchant-httpd_proposal.c
index ed222c97..2a59ae5e 100644
--- a/src/backend/taler-merchant-httpd_proposal.c
+++ b/src/backend/taler-merchant-httpd_proposal.c
@@ -120,15 +120,11 @@ get_instance (struct json_t *json);
/**
- * Manage a contract request. In practical terms, it adds the fields
- * 'exchanges', 'merchant_pub', and 'H_wire' to the contract 'proposition'
- * gotten from the frontend. Finally, it adds (outside of the
- * contract) a signature of the (hashed stringification) of the
- * contract (and the hashed stringification of this contract as well
- * to aid diagnostics) to the final bundle, which is then send back to
- * the frontend.
+ * Generate a proposal, given its order. In practical terms, it adds the
+ * fields 'exchanges', 'merchant_pub', and 'H_wire' to the order gotten
+ * from the frontend. Finally, it signs this data, and returns it to the
+ * frontend.
*
- * @param rh context of the handler
* @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated)
* @param upload_data upload data
@@ -136,23 +132,24 @@ get_instance (struct json_t *json);
* @return MHD result code
*/
int
-MH_handler_propose (struct TMH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+MH_handler_proposal_put (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size)
{
json_t *root;
- json_t *jcontract;
+ json_t *order;
int res;
struct MerchantInstance *mi;
struct TMH_JsonParseContext *ctx;
- struct TALER_ContractPS contract;
- struct GNUNET_CRYPTO_EddsaSignature contract_sig;
+ struct TALER_ProposalDataPS pdps;
+ struct GNUNET_CRYPTO_EddsaSignature merchant_sig;
struct TALER_Amount total;
struct TALER_Amount max_fee;
- uint64_t transaction_id;
+ const char *transaction_id;
+ struct GNUNET_HashCode h_tid;
json_t *products;
json_t *merchant;
struct GNUNET_TIME_Absolute timestamp;
@@ -161,9 +158,9 @@ MH_handler_propose (struct TMH_RequestHandler *rh,
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount ("amount", &total),
TALER_JSON_spec_amount ("max_fee", &max_fee),
- GNUNET_JSON_spec_uint64 ("transaction_id", &transaction_id),
+ GNUNET_JSON_spec_string ("transaction_id", &transaction_id),
/* The following entries we don't actually need, except to check that
- the contract is well-formed */
+ the order is well-formed */
GNUNET_JSON_spec_json ("products", &products),
GNUNET_JSON_spec_json ("merchant", &merchant),
GNUNET_JSON_spec_absolute_time ("timestamp", &timestamp),
@@ -194,18 +191,18 @@ MH_handler_propose (struct TMH_RequestHandler *rh,
if ((GNUNET_NO == res) || (NULL == root))
return MHD_YES;
- jcontract = json_object_get (root,
- "contract");
- if (NULL == jcontract)
+ order = json_object_get (root,
+ "order");
+ if (NULL == order)
{
json_decref (root);
return TMH_RESPONSE_reply_arg_missing (connection,
TALER_EC_PARAMETER_MISSING,
- "contract");
+ "order");
}
/* extract fields we need to sign separately */
res = TMH_PARSE_json_data (connection,
- jcontract,
+ order,
spec);
if (GNUNET_NO == res)
{
@@ -217,7 +214,7 @@ MH_handler_propose (struct TMH_RequestHandler *rh,
json_decref (root);
return TMH_RESPONSE_reply_internal_error (connection,
TALER_EC_NONE,
- "Impossible to parse contract");
+ "Impossible to parse the order");
}
/* check contract is well-formed */
if (GNUNET_OK != check_products (products))
@@ -226,7 +223,7 @@ MH_handler_propose (struct TMH_RequestHandler *rh,
json_decref (root);
return TMH_RESPONSE_reply_arg_invalid (connection,
TALER_EC_PARAMETER_MALFORMED,
- "contract:products");
+ "order:products");
}
mi = get_instance (merchant);
@@ -243,39 +240,108 @@ MH_handler_propose (struct TMH_RequestHandler *rh,
"Signing contract on behalf of instance '%s'\n",
mi->id);
/* add fields to the contract that the backend should provide */
- json_object_set (jcontract,
+ json_object_set (order,
"exchanges",
trusted_exchanges);
- json_object_set (jcontract,
+ json_object_set (order,
"auditors",
j_auditors);
- json_object_set_new (jcontract,
+ json_object_set_new (order,
"H_wire",
GNUNET_JSON_from_data_auto (&mi->h_wire));
- json_object_set_new (jcontract,
+ json_object_set_new (order,
"merchant_pub",
GNUNET_JSON_from_data_auto (&mi->pubkey));
- /* create contract signature */
- contract.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
- contract.purpose.size = htonl (sizeof (contract));
+ /* create proposal signature */
+ pdps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
+ pdps.purpose.size = htonl (sizeof (pdps));
GNUNET_assert (GNUNET_OK ==
- TALER_JSON_hash (jcontract,
- &contract.h_contract));
+ TALER_JSON_hash (order,
+ &pdps.h_proposal_data));
GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv,
- &contract.purpose,
- &contract_sig);
+ &pdps.purpose,
+ &merchant_sig);
+
+
+ GNUNET_CRYPTO_hash (transaction_id,
+ strlen (transaction_id),
+ &h_tid);
+ if (GNUNET_OK !=
+ db->insert_proposal_data (db->cls,
+ &h_tid,
+ order))
+ return TMH_RESPONSE_reply_internal_error (connection,
+ TALER_EC_PROPOSAL_STORE_DB_ERROR,
+ "db error: could not store this proposal's data into db");
+
- /* return final response */
res = TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_OK,
"{s:O, s:o s:o}",
- "contract", jcontract,
- "merchant_sig", GNUNET_JSON_from_data_auto (&contract_sig),
- "H_contract", GNUNET_JSON_from_data_auto (&contract.h_contract));
+ "data", order,
+ "merchant_sig", GNUNET_JSON_from_data_auto (&merchant_sig),
+ "hash", GNUNET_JSON_from_data_auto (&pdps.h_proposal_data));
GNUNET_JSON_parse_free (spec);
json_decref (root);
return res;
}
+/**
+ * Manage a GET /proposal request. Query the db and returns the
+ * proposal's data related to the transaction id given as the URL's
+ * parameter.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ const char *transaction_id;
+ struct GNUNET_HashCode h_tid;
+ int res;
+ json_t *proposal_data;
+
+ transaction_id = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "transaction_id");
+ if (NULL == transaction_id)
+ return TMH_RESPONSE_reply_arg_missing (connection,
+ TALER_EC_PARAMETER_MISSING,
+ "transaction_id");
+ GNUNET_CRYPTO_hash (transaction_id,
+ strlen (transaction_id),
+ &h_tid);
+
+ res = db->find_proposal_data (db->cls,
+ &proposal_data,
+ &h_tid);
+ if (GNUNET_NO == res)
+ return TMH_RESPONSE_reply_not_found (connection,
+ TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND,
+ "unknown transaction id");
+
+ if (GNUNET_SYSERR == res)
+ return TMH_RESPONSE_reply_internal_error (connection,
+ TALER_EC_PROPOSAL_LOOKUP_DB_ERROR,
+ "An error occurred while retrieving proposal data from db");
+
+
+ return TMH_RESPONSE_reply_json (connection,
+ proposal_data,
+ MHD_HTTP_OK);
+
+
+}
+
+
/* end of taler-merchant-httpd_contract.c */
diff --git a/src/backend/taler-merchant-httpd_propose.h b/src/backend/taler-merchant-httpd_proposal.h
index ad3e1dcd..fe5b319a 100644
--- a/src/backend/taler-merchant-httpd_propose.h
+++ b/src/backend/taler-merchant-httpd_proposal.h
@@ -24,9 +24,11 @@
#include "taler-merchant-httpd.h"
/**
- * Manage a contract request
+ * Generate a proposal, given its order. In practical terms, it adds the
+ * fields 'exchanges', 'merchant_pub', and 'H_wire' to the order gotten
+ * from the frontend. Finally, it signs this data, and returns it to the
+ * frontend.
*
- * @param rh context of the handler
* @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated)
* @param upload_data upload data
@@ -34,10 +36,29 @@
* @return MHD result code
*/
int
-MH_handler_propose (struct TMH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+MH_handler_proposal_put (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size);
+
+/**
+ * Manage a GET /proposal request. Query the db and returns the
+ * proposal's data related to the transaction id given as the URL's
+ * parameter.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size);
#endif
diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c
index 0d9d3b66..0e2ea5c7 100644
--- a/src/lib/test_merchant_api.c
+++ b/src/lib/test_merchant_api.c
@@ -409,7 +409,7 @@ struct Command
* It's dynamically generated because we need different transaction_id
* for different merchant instances.
*/
- char order[OFFER_MAX_SIZE];
+ char order[ORDER_MAX_SIZE];
/**
* Handle to the active PUT /proposal operation, or NULL.
@@ -1497,14 +1497,13 @@ interpreter_run (void *cls)
case OC_PROPOSAL_LOOKUP:
{
- char *transaction_id;
- json_error_t error;
+ const char *transaction_id;
GNUNET_assert (NULL != cmd->details.proposal_lookup.proposal_reference);
ref = find_command (is, cmd->details.proposal_lookup.proposal_reference);
GNUNET_assert (NULL != ref);
- transaction_id = json_object_get (ref->details.proposal.proposal, "transaction_id");
+ transaction_id = json_string_value (json_object_get (ref->details.proposal.proposal_data, "transaction_id"));
GNUNET_assert (NULL !=
(cmd->details.proposal_lookup.plo
= TALER_MERCHANT_proposal_lookup (ctx,
@@ -1677,7 +1676,7 @@ interpreter_run (void *cls)
json_t *order;
json_error_t error;
- order = json_loads (cmd->details.contract.order,
+ order = json_loads (cmd->details.proposal.order,
JSON_REJECT_DUPLICATES,
&error);
if (NULL != instance)
@@ -1695,21 +1694,21 @@ interpreter_run (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to parse the order `%s' at command #%u: %s at %u\n",
- cmd->details.contract.order,
+ cmd->details.proposal.order,
is->ip,
error.text,
(unsigned int) error.column);
fail (is);
return;
}
- cmd->details.contract.po
- = TALER_MERCHANT_proposal (ctx,
- MERCHANT_URI,
- order,
- &proposal_cb,
- is);
+ cmd->details.proposal.po
+ = TALER_MERCHANT_order_put (ctx,
+ MERCHANT_URI,
+ order,
+ &proposal_cb,
+ is);
json_decref (order);
- if (NULL == cmd->details.contract.po)
+ if (NULL == cmd->details.proposal.po)
{
GNUNET_break (0);
fail (is);
@@ -1727,7 +1726,6 @@ interpreter_run (void *cls)
struct GNUNET_HashCode h_wire;
struct TALER_MerchantPublicKeyP merchant_pub;
struct TALER_MerchantSignatureP merchant_sig;
- struct GNUNET_HashCode h_contract;
struct TALER_Amount total_amount;
struct TALER_Amount max_fee;
const char *error_name;
@@ -1737,8 +1735,8 @@ interpreter_run (void *cls)
ref = find_command (is,
cmd->details.pay.contract_ref);
GNUNET_assert (NULL != ref);
- merchant_sig = ref->details.contract.merchant_sig;
- GNUNET_assert (NULL != ref->details.contract.contract);
+ merchant_sig = ref->details.proposal.merchant_sig;
+ GNUNET_assert (NULL != ref->details.proposal.proposal_data);
{
/* Get information that need to be replied in the deposit permission */
struct GNUNET_JSON_Specification spec[] = {
@@ -1754,7 +1752,7 @@ interpreter_run (void *cls)
};
if (GNUNET_OK !=
- GNUNET_JSON_parse (ref->details.contract.contract,
+ GNUNET_JSON_parse (ref->details.proposal.proposal_data,
spec,
&error_name,
&error_line))
@@ -1771,9 +1769,6 @@ interpreter_run (void *cls)
cmd->details.pay.merchant_pub = merchant_pub;
}
- TALER_JSON_hash (ref->details.contract.contract,
- &h_contract);
-
/* initialize 'pc' (FIXME: to do in a loop later...) */
{
memset (&pc, 0, sizeof (pc));
@@ -1820,7 +1815,7 @@ interpreter_run (void *cls)
= TALER_MERCHANT_pay_wallet (ctx,
MERCHANT_URI,
instance,
- &h_contract,
+ &ref->details.proposal.h_proposal_data,
transaction_id,
&total_amount,
&max_fee,
@@ -2007,7 +2002,7 @@ do_shutdown (void *cls)
"Command %u (%s) did not complete\n",
i,
cmd->label);
- TALER_MERCHANT_map_cancel (cmd->details.proposal_lookup.plo);
+ TALER_MERCHANT_proposal_lookup_cancel (cmd->details.proposal_lookup.plo);
}
break;
@@ -2059,10 +2054,10 @@ do_shutdown (void *cls)
TALER_MERCHANT_proposal_cancel (cmd->details.proposal.po);
cmd->details.proposal.po = NULL;
}
- if (NULL != cmd->details.proposal.proposal)
+ if (NULL != cmd->details.proposal.proposal_data)
{
- json_decref (cmd->details.proposal.proposal);
- cmd->details.proposal.proposal = NULL;
+ json_decref (cmd->details.proposal.proposal_data);
+ cmd->details.proposal.proposal_data = NULL;
}
break;
case OC_PAY:
@@ -2244,11 +2239,11 @@ run (void *cls)
.expected_response_code = MHD_HTTP_OK,
.details.reserve_status.reserve_reference = "create-reserve-1",
.details.reserve_status.expected_balance = "EUR:0" },
- /* Create contract */
- { .oc = OC_CONTRACT,
- .label = "create-contract-1",
+ /* Create proposal */
+ { .oc = OC_PROPOSAL,
+ .label = "create-proposal-1",
.expected_response_code = MHD_HTTP_OK,
- .details.contract.order = "{\
+ .details.proposal.order = "{\
\"max_fee\":\
{\"currency\":\"EUR\", \"value\":0, \"fraction\":50000000},\
\"transaction_id\":1,\
@@ -2269,10 +2264,10 @@ run (void *cls)
/* Create another contract */
- { .oc = OC_CONTRACT,
- .label = "create-contract-2",
+ { .oc = OC_PROPOSAL,
+ .label = "create-proposal-2",
.expected_response_code = MHD_HTTP_OK,
- .details.contract.order = "{\
+ .details.proposal.order = "{\
\"max_fee\":\
{\"currency\":\"EUR\", \"value\":0, \"fraction\":50000000},\
\"transaction_id\":2,\
@@ -2319,10 +2314,10 @@ run (void *cls)
/* Fetch contract-1 */
{
- .oc = OC_MAP_OUT,
- .label = "fetch-contract-2",
+ .oc = OC_PROPOSAL_LOOKUP,
+ .label = "fetch-proposal-2",
.expected_response_code = MHD_HTTP_OK,
- .details.map.contract_reference = "create-contract-2" },
+ .details.proposal_lookup.proposal_reference = "create-proposal-2" },
/* Check nothing happened on the bank side so far */
{ .oc = OC_CHECK_BANK_TRANSFERS_EMPTY,
@@ -2455,16 +2450,16 @@ run (void *cls)
},
/* Retrieve via /map/out a contract NOT stored previously. */
{
- .oc = OC_MAP_OUT,
- .label = "fetch-contract-not-found",
+ .oc = OC_PROPOSAL_LOOKUP,
+ .label = "fetch-proposal-not-found",
.expected_response_code = MHD_HTTP_NOT_FOUND,
- .details.map.contract_reference = "create-contract-3" },
+ .details.proposal_lookup.proposal_reference = "create-proposal-3" },
/* Create another contract, NOT to be stored. */
- { .oc = OC_CONTRACT,
- .label = "create-contract-3",
+ { .oc = OC_PROPOSAL,
+ .label = "create-proposal-3",
.expected_response_code = MHD_HTTP_OK,
- .details.contract.order = "{\
+ .details.proposal.order = "{\
\"max_fee\":\
{\"currency\":\"EUR\", \"value\":0, \"fraction\":10000},\
\"transaction_id\":3,\