-add test for batch deposits

This commit is contained in:
Christian Grothoff 2022-07-01 15:42:48 +02:00
parent 182c618579
commit cebf4f11b9
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
6 changed files with 80 additions and 64 deletions

View File

@ -30,6 +30,7 @@
#include <limits.h> #include <limits.h>
#include "taler_mhd_lib.h" #include "taler_mhd_lib.h"
#include "taler-exchange-httpd_auditors.h" #include "taler-exchange-httpd_auditors.h"
#include "taler-exchange-httpd_batch-deposit.h"
#include "taler-exchange-httpd_batch-withdraw.h" #include "taler-exchange-httpd_batch-withdraw.h"
#include "taler-exchange-httpd_contract.h" #include "taler-exchange-httpd_contract.h"
#include "taler-exchange-httpd_csr.h" #include "taler-exchange-httpd_csr.h"
@ -66,18 +67,6 @@
#include "taler_extensions.h" #include "taler_extensions.h"
#include <gnunet/gnunet_mhd_compat.h> #include <gnunet/gnunet_mhd_compat.h>
/**
* Macro to enable P2P handlers. ON for debugging,
* FIXME: set to OFF for 0.9.0 release as the feature is not stable!
*/
#define WITH_P2P 1
/**
* Should the experimental batch withdraw be supported?
* ON for testing disable for 0.9.0 release!
*/
#define WITH_EXPERIMENTAL 1
/** /**
* Backlog for listen operation on unix domain sockets. * Backlog for listen operation on unix domain sockets.
*/ */
@ -374,12 +363,10 @@ handle_post_reserves (struct TEH_RequestContext *rc,
.op = "withdraw", .op = "withdraw",
.handler = &TEH_handler_withdraw .handler = &TEH_handler_withdraw
}, },
#if WITH_EXPERIMENTAL
{ {
.op = "batch-withdraw", .op = "batch-withdraw",
.handler = &TEH_handler_batch_withdraw .handler = &TEH_handler_batch_withdraw
}, },
#endif
{ {
.op = "status", .op = "status",
.handler = &TEH_handler_reserves_status .handler = &TEH_handler_reserves_status
@ -388,12 +375,10 @@ handle_post_reserves (struct TEH_RequestContext *rc,
.op = "history", .op = "history",
.handler = &TEH_handler_reserves_history .handler = &TEH_handler_reserves_history
}, },
#if WITH_P2P
{ {
.op = "purse", .op = "purse",
.handler = &TEH_handler_reserves_purse .handler = &TEH_handler_reserves_purse
}, },
#endif
{ {
.op = NULL, .op = NULL,
.handler = NULL .handler = NULL
@ -465,7 +450,6 @@ handle_post_purses (struct TEH_RequestContext *rc,
PurseOpHandler handler; PurseOpHandler handler;
} h[] = { } h[] = {
#if WITH_P2P
{ {
.op = "create", .op = "create",
.handler = &TEH_handler_purses_create .handler = &TEH_handler_purses_create
@ -478,7 +462,6 @@ handle_post_purses (struct TEH_RequestContext *rc,
.op = "merge", .op = "merge",
.handler = &TEH_handler_purses_merge .handler = &TEH_handler_purses_merge
}, },
#endif
{ {
.op = NULL, .op = NULL,
.handler = NULL .handler = NULL
@ -1123,6 +1106,12 @@ handle_mhd_request (void *cls,
.method = MHD_HTTP_METHOD_GET, .method = MHD_HTTP_METHOD_GET,
.handler.get = &TEH_handler_wire .handler.get = &TEH_handler_wire
}, },
{
.url = "batch-deposit",
.method = MHD_HTTP_METHOD_POST,
.handler.post = &TEH_handler_batch_deposit,
.nargs = 0
},
/* request R, used in clause schnorr withdraw and refresh */ /* request R, used in clause schnorr withdraw and refresh */
{ {
.url = "csr-melt", .url = "csr-melt",
@ -1190,7 +1179,6 @@ handle_mhd_request (void *cls,
.handler.post = &handle_post_purses, .handler.post = &handle_post_purses,
.nargs = 2 // ?? .nargs = 2 // ??
}, },
#if WITH_P2P
/* Getting purse status */ /* Getting purse status */
{ {
.url = "purses", .url = "purses",
@ -1205,7 +1193,6 @@ handle_mhd_request (void *cls,
.handler.get = &TEH_handler_contracts_get, .handler.get = &TEH_handler_contracts_get,
.nargs = 1 .nargs = 1
}, },
#endif
/* KYC endpoints */ /* KYC endpoints */
{ {
.url = "kyc-check", .url = "kyc-check",

View File

@ -151,13 +151,15 @@ reply_batch_deposit_success (
const struct BatchDepositContext *bdc) const struct BatchDepositContext *bdc)
{ {
json_t *arr; json_t *arr;
struct TALER_ExchangePublicKeyP pub;
again:
arr = json_array (); arr = json_array ();
GNUNET_assert (NULL != arr); GNUNET_assert (NULL != arr);
for (unsigned int i = 0; i<bdc->num_coins; i++) for (unsigned int i = 0; i<bdc->num_coins; i++)
{ {
const struct TALER_EXCHANGEDB_Deposit *deposit = &bdc->deposits[i]; const struct TALER_EXCHANGEDB_Deposit *deposit = &bdc->deposits[i];
struct TALER_ExchangePublicKeyP pub; struct TALER_ExchangePublicKeyP pubi;
struct TALER_ExchangeSignatureP sig; struct TALER_ExchangeSignatureP sig;
enum TALER_ErrorCode ec; enum TALER_ErrorCode ec;
struct TALER_Amount amount_without_fee; struct TALER_Amount amount_without_fee;
@ -178,30 +180,45 @@ reply_batch_deposit_success (
&amount_without_fee, &amount_without_fee,
&deposit->coin.coin_pub, &deposit->coin.coin_pub,
&bdc->merchant_pub, &bdc->merchant_pub,
&pub, &pubi,
&sig))) &sig)))
{ {
GNUNET_break (0);
return TALER_MHD_reply_with_ec (connection, return TALER_MHD_reply_with_ec (connection,
ec, ec,
NULL); NULL);
} }
if (0 == i)
pub = pubi;
if (0 !=
GNUNET_memcmp (&pub,
&pubi))
{
/* note: in the future, maybe have batch
sign API to avoid having to handle
key rollover... */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Exchange public key changed during batch deposit, trying again\n");
json_decref (arr);
goto again;
}
GNUNET_assert ( GNUNET_assert (
0 == 0 ==
json_array_append_new (arr, json_array_append_new (arr,
GNUNET_JSON_PACK ( GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ( GNUNET_JSON_pack_data_auto (
"exchange_sig", "exchange_sig",
&sig), &sig))));
GNUNET_JSON_pack_data_auto (
"exchange_pub",
&pub))));
} }
return TALER_MHD_REPLY_JSON_PACK ( return TALER_MHD_REPLY_JSON_PACK (
connection, connection,
MHD_HTTP_OK, MHD_HTTP_OK,
GNUNET_JSON_pack_timestamp ("exchange_timestamp", GNUNET_JSON_pack_timestamp ("exchange_timestamp",
bdc->exchange_timestamp), bdc->exchange_timestamp),
GNUNET_JSON_pack_array_steal ("confirmations", GNUNET_JSON_pack_data_auto (
"exchange_pub",
&pub),
GNUNET_JSON_pack_array_steal ("exchange_sigs",
arr)); arr));
} }
@ -476,12 +493,15 @@ parse_coin (struct MHD_Connection *connection,
MHD_RESULT MHD_RESULT
TEH_handler_batch_deposit (struct MHD_Connection *connection, TEH_handler_batch_deposit (struct TEH_RequestContext *rc,
const json_t *root) const json_t *root,
const char *const args[])
{ {
struct MHD_Connection *connection = rc->connection;
struct BatchDepositContext dc; struct BatchDepositContext dc;
json_t *coins; json_t *coins;
bool no_refund_deadline = true; bool no_refund_deadline = true;
bool no_extensions = true;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("merchant_payto_uri", GNUNET_JSON_spec_string ("merchant_payto_uri",
&dc.payto_uri), &dc.payto_uri),
@ -493,8 +513,10 @@ TEH_handler_batch_deposit (struct MHD_Connection *connection,
&dc.h_contract_terms), &dc.h_contract_terms),
GNUNET_JSON_spec_json ("coins", GNUNET_JSON_spec_json ("coins",
&coins), &coins),
GNUNET_JSON_spec_json ("extension_details", GNUNET_JSON_spec_mark_optional (
&dc.extension_details), GNUNET_JSON_spec_json ("extension_details",
&dc.extension_details),
&no_extensions),
GNUNET_JSON_spec_timestamp ("timestamp", GNUNET_JSON_spec_timestamp ("timestamp",
&dc.timestamp), &dc.timestamp),
GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_mark_optional (
@ -505,7 +527,6 @@ TEH_handler_batch_deposit (struct MHD_Connection *connection,
&dc.wire_deadline), &dc.wire_deadline),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
enum GNUNET_GenericReturnValue res; enum GNUNET_GenericReturnValue res;
res = TALER_MHD_parse_json_data (connection, res = TALER_MHD_parse_json_data (connection,
@ -567,6 +588,7 @@ TEH_handler_batch_deposit (struct MHD_Connection *connection,
&dc.wire_salt, &dc.wire_salt,
&dc.h_wire); &dc.h_wire);
/* FIXME-OEC: hash actual extension JSON object here */ /* FIXME-OEC: hash actual extension JSON object here */
// if (! no_extensions)
memset (&dc.h_extensions, memset (&dc.h_extensions,
0, 0,
sizeof (dc.h_extensions)); sizeof (dc.h_extensions));

View File

@ -35,13 +35,15 @@
* out, this will ultimately lead to the "/batch-deposit" being executed, or * out, this will ultimately lead to the "/batch-deposit" being executed, or
* rejected. * rejected.
* *
* @param connection the MHD connection to handle * @param rc request context
* @param root uploaded JSON data * @param root uploaded JSON data
* @param args arguments, empty in this case
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_batch_deposit (struct MHD_Connection *connection, TEH_handler_batch_deposit (struct TEH_RequestContext *rc,
const json_t *root); const json_t *root,
const char *const args[]);
#endif #endif

View File

@ -520,6 +520,12 @@ TALER_EXCHANGE_batch_deposit (
{ {
*ec = TALER_EC_EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT; *ec = TALER_EC_EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT;
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Amount: %s\n",
TALER_amount2s (&cdd->amount));
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Fee: %s\n",
TALER_amount2s (&dki->fees.deposit));
GNUNET_free (dh->cdds); GNUNET_free (dh->cdds);
GNUNET_free (dh); GNUNET_free (dh);
return NULL; return NULL;
@ -545,13 +551,15 @@ TALER_EXCHANGE_batch_deposit (
GNUNET_JSON_PACK ( GNUNET_JSON_PACK (
TALER_JSON_pack_amount ("contribution", TALER_JSON_pack_amount ("contribution",
&cdd->amount), &cdd->amount),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_data_auto ("h_age_commitment",
&cdd->h_age_commitment)),
GNUNET_JSON_pack_data_auto ("denom_pub_hash", GNUNET_JSON_pack_data_auto ("denom_pub_hash",
&cdd->h_denom_pub), &cdd->h_denom_pub),
TALER_JSON_pack_denom_sig ("ub_sig", TALER_JSON_pack_denom_sig ("ub_sig",
&cdd->denom_sig), &cdd->denom_sig),
GNUNET_JSON_pack_data_auto ("coin_pub",
&cdd->coin_pub),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_data_auto ("h_age_commitment",
&cdd->h_age_commitment)),
GNUNET_JSON_pack_data_auto ("coin_sig", GNUNET_JSON_pack_data_auto ("coin_sig",
&cdd->coin_sig) &cdd->coin_sig)
))); )));
@ -569,14 +577,17 @@ TALER_EXCHANGE_batch_deposit (
} }
deposit_obj = GNUNET_JSON_PACK ( deposit_obj = GNUNET_JSON_PACK (
GNUNET_JSON_pack_array_steal ("coins",
deposits),
GNUNET_JSON_pack_string ("merchant_payto_uri", GNUNET_JSON_pack_string ("merchant_payto_uri",
dcd->merchant_payto_uri), dcd->merchant_payto_uri),
GNUNET_JSON_pack_data_auto ("wire_salt", GNUNET_JSON_pack_data_auto ("wire_salt",
&dcd->wire_salt), &dcd->wire_salt),
GNUNET_JSON_pack_data_auto ("h_contract_terms", GNUNET_JSON_pack_data_auto ("h_contract_terms",
&dcd->h_contract_terms), &dcd->h_contract_terms),
GNUNET_JSON_pack_array_steal ("coins",
deposits),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_object_steal ("extension_details",
NULL)), /* FIXME-Oec */
GNUNET_JSON_pack_timestamp ("timestamp", GNUNET_JSON_pack_timestamp ("timestamp",
dcd->timestamp), dcd->timestamp),
GNUNET_JSON_pack_data_auto ("merchant_pub", GNUNET_JSON_pack_data_auto ("merchant_pub",
@ -619,17 +630,16 @@ TALER_EXCHANGE_batch_deposit (
void void
TALER_EXCHANGE_batch_deposit_force_dc (struct TALER_EXCHANGE_batch_deposit_force_dc (
TALER_EXCHANGE_BatchDepositHandle * struct TALER_EXCHANGE_BatchDepositHandle *deposit)
deposit)
{ {
deposit->auditor_chance = 1; deposit->auditor_chance = 1;
} }
void void
TALER_EXCHANGE_batch_deposit_cancel (struct TALER_EXCHANGE_batch_deposit_cancel (
TALER_EXCHANGE_BatchDepositHandle *deposit) struct TALER_EXCHANGE_BatchDepositHandle *deposit)
{ {
if (NULL != deposit->job) if (NULL != deposit->job)
{ {

View File

@ -1183,22 +1183,16 @@ run (void *cls,
/** /**
* Spend the coins. * Spend the coins.
*/ */
TALER_TESTING_cmd_deposit ("deposit-batch-simple-1", TALER_TESTING_cmd_batch_deposit ("batch-deposit-1",
"batch-withdraw-coin-1", bc.user42_payto,
0, "{\"items\":[{\"name\":\"ice cream\",\"value\":5}]}",
bc.user42_payto, GNUNET_TIME_UNIT_ZERO,
"{\"items\":[{\"name\":\"ice cream\",\"value\":5}]}", MHD_HTTP_OK,
GNUNET_TIME_UNIT_ZERO, "batch-withdraw-coin-1#0",
"EUR:5", "EUR:5",
MHD_HTTP_OK), "batch-withdraw-coin-1#1",
TALER_TESTING_cmd_deposit ("deposit-batch-simple-2", "EUR:1",
"batch-withdraw-coin-1", NULL),
1,
bc.user42_payto,
"{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
MHD_HTTP_OK),
TALER_TESTING_cmd_end () TALER_TESTING_cmd_end ()
}; };

View File

@ -317,9 +317,10 @@ batch_deposit_run (void *cls,
const struct TALER_AgeCommitmentProof *age_commitment_proof = NULL; const struct TALER_AgeCommitmentProof *age_commitment_proof = NULL;
GNUNET_assert (NULL != coin->coin_reference); GNUNET_assert (NULL != coin->coin_reference);
coin->coin_cmd = TALER_TESTING_interpreter_lookup_command (is, cdd->amount = coin->amount;
coin-> coin->coin_cmd = TALER_TESTING_interpreter_lookup_command (
coin_reference); is,
coin->coin_reference);
if (NULL == coin->coin_cmd) if (NULL == coin->coin_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);