update exchange API to return struct instead of lots of individual args for TALER_EXCHANGE_transfers_get() -- simplifies merchant later

This commit is contained in:
Christian Grothoff 2020-05-03 19:54:36 +02:00
parent 19f51f558b
commit 77ab94eb68
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
3 changed files with 140 additions and 129 deletions

View File

@ -1580,32 +1580,68 @@ TALER_EXCHANGE_link_cancel (struct TALER_EXCHANGE_LinkHandle *lh);
struct TALER_EXCHANGE_TransfersGetHandle; struct TALER_EXCHANGE_TransfersGetHandle;
/**
* Information the exchange returns per wire transfer.
*/
struct TALER_EXCHANGE_TransferData
{
/**
* exchange key used to sign
*/
struct TALER_ExchangePublicKeyP exchange_pub;
/**
* exchange signature over the transfer data
*/
struct TALER_ExchangeSignatureP exchange_sig;
/**
* hash of the wire transfer address the transfer went to
*/
struct GNUNET_HashCode h_wire;
/**
* time when the exchange claims to have performed the wire transfer
*/
struct GNUNET_TIME_Absolute execution_time;
/**
* amount of the wire transfer
*/
struct TALER_Amount total_amount;
/**
* wire fee that was charged by the exchange
*/
struct TALER_Amount wire_fee;
/**
* length of the @e details array
*/
unsigned int details_length;
/**
* array with details about the combined transactions
*/
const struct TALER_TrackTransferDetails *details;
};
/** /**
* Function called with detailed wire transfer data, including all * Function called with detailed wire transfer data, including all
* of the coin transactions that were combined into the wire transfer. * of the coin transactions that were combined into the wire transfer.
* *
* @param cls closure * @param cls closure
* @param hr HTTP response data * @param hr HTTP response data
* @param sign_key exchange key used to sign @a json, or NULL * @param ta transfer data, (set only if @a http_status is #MHD_HTTP_OK, otherwise NULL)
* @param h_wire hash of the wire transfer address the transfer went to, or NULL on error
* @param execution_time time when the exchange claims to have performed the wire transfer
* @param total_amount total amount of the wire transfer, or NULL if the exchange could
* not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK)
* @param wire_fee wire fee that was charged by the exchange
* @param details_length length of the @a details array
* @param details array with details about the combined transactions
*/ */
typedef void typedef void
(*TALER_EXCHANGE_TransfersGetCallback)( (*TALER_EXCHANGE_TransfersGetCallback)(
void *cls, void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr, const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_ExchangePublicKeyP *sign_key, const struct TALER_EXCHANGE_TransferData *ta);
const struct GNUNET_HashCode *h_wire,
struct GNUNET_TIME_Absolute execution_time,
const struct TALER_Amount *total_amount,
const struct TALER_Amount *wire_fee,
unsigned int details_length,
const struct TALER_TrackTransferDetails *details);
/** /**
@ -1651,17 +1687,19 @@ struct TALER_EXCHANGE_DepositGetHandle;
* *
* @param cls closure * @param cls closure
* @param hr HTTP response data * @param hr HTTP response data
* @param sign_key exchange key used to sign @a json, or NULL * @param exchange_pub exchange key used to sign @a json, or NULL
* @param wtid wire transfer identifier used by the exchange, NULL if exchange did not * @param wtid wire transfer identifier used by the exchange, NULL if exchange did not
* yet execute the transaction * yet execute the transaction
* @param execution_time actual or planned execution time for the wire transfer * @param execution_time actual or planned execution time for the wire transfer
* @param coin_contribution contribution to the total amount by this coin (can be NULL) * @param coin_contribution contribution to the total amount by this coin (can be NULL)
* // FIXME: also return the exchange signature
* // FIXME: combine all of the above (except cls,hr) into a 'struct'! => DepositData
*/ */
typedef void typedef void
(*TALER_EXCHANGE_DepositGetCallback)( (*TALER_EXCHANGE_DepositGetCallback)(
void *cls, void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr, const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_ExchangePublicKeyP *sign_key, const struct TALER_ExchangePublicKeyP *exchange_pub,
const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_WireTransferIdentifierRawP *wtid,
struct GNUNET_TIME_Absolute execution_time, struct GNUNET_TIME_Absolute execution_time,
const struct TALER_Amount *coin_contribution); const struct TALER_Amount *coin_contribution);

View File

@ -85,24 +85,18 @@ check_transfers_get_response_ok (
const json_t *json) const json_t *json)
{ {
json_t *details_j; json_t *details_j;
struct GNUNET_HashCode h_wire; struct TALER_EXCHANGE_TransferData td;
struct GNUNET_TIME_Absolute exec_time;
struct TALER_Amount total_amount;
struct TALER_Amount total_expected; struct TALER_Amount total_expected;
struct TALER_Amount wire_fee;
struct TALER_MerchantPublicKeyP merchant_pub; struct TALER_MerchantPublicKeyP merchant_pub;
unsigned int num_details;
struct TALER_ExchangePublicKeyP exchange_pub;
struct TALER_ExchangeSignatureP exchange_sig;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount ("total", &total_amount), TALER_JSON_spec_amount ("total", &td.total_amount),
TALER_JSON_spec_amount ("wire_fee", &wire_fee), TALER_JSON_spec_amount ("wire_fee", &td.wire_fee),
GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub), GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub),
GNUNET_JSON_spec_fixed_auto ("h_wire", &h_wire), GNUNET_JSON_spec_fixed_auto ("h_wire", &td.h_wire),
GNUNET_JSON_spec_absolute_time ("execution_time", &exec_time), GNUNET_JSON_spec_absolute_time ("execution_time", &td.execution_time),
GNUNET_JSON_spec_json ("deposits", &details_j), GNUNET_JSON_spec_json ("deposits", &details_j),
GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig), GNUNET_JSON_spec_fixed_auto ("exchange_sig", &td.exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub), GNUNET_JSON_spec_fixed_auto ("exchange_pub", &td.exchange_pub),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
struct TALER_EXCHANGE_HttpResponse hr = { struct TALER_EXCHANGE_HttpResponse hr = {
@ -119,22 +113,32 @@ check_transfers_get_response_ok (
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_amount_get_zero (total_amount.currency, TALER_amount_get_zero (td.total_amount.currency,
&total_expected)) &total_expected))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
num_details = json_array_size (details_j); if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (
TALER_EXCHANGE_get_keys (wdh->exchange),
&td.exchange_pub))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
td.details_length = json_array_size (details_j);
{ {
struct TALER_TrackTransferDetails details[num_details];
unsigned int i;
struct GNUNET_HashContext *hash_context; struct GNUNET_HashContext *hash_context;
struct TALER_WireDepositDetailP dd; struct TALER_TrackTransferDetails *details;
struct TALER_WireDepositDataPS wdp;
details = GNUNET_new_array (td.details_length,
struct TALER_TrackTransferDetails);
td.details = details;
hash_context = GNUNET_CRYPTO_hash_context_start (); hash_context = GNUNET_CRYPTO_hash_context_start ();
for (i = 0; i<num_details; i++) for (unsigned int i = 0; i<td.details_length; i++)
{ {
struct TALER_TrackTransferDetails *detail = &details[i]; struct TALER_TrackTransferDetails *detail = &details[i];
struct json_t *detail_j = json_array_get (details_j, i); struct json_t *detail_j = json_array_get (details_j, i);
@ -147,25 +151,11 @@ check_transfers_get_response_ok (
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
if (GNUNET_OK != if ( (GNUNET_OK !=
GNUNET_JSON_parse (detail_j, GNUNET_JSON_parse (detail_j,
spec_detail, spec_detail,
NULL, NULL)) NULL, NULL)) ||
{ (0 >
GNUNET_break_op (0);
GNUNET_CRYPTO_hash_context_abort (hash_context);
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
/* build up big hash for signature checking later */
dd.h_contract_terms = detail->h_contract_terms;
dd.execution_time = GNUNET_TIME_absolute_hton (exec_time);
dd.coin_pub = detail->coin_pub;
TALER_amount_hton (&dd.deposit_value,
&detail->coin_value);
TALER_amount_hton (&dd.deposit_fee,
&detail->coin_fee);
if ( (0 >
TALER_amount_add (&total_expected, TALER_amount_add (&total_expected,
&total_expected, &total_expected,
&detail->coin_value)) || &detail->coin_value)) ||
@ -177,71 +167,78 @@ check_transfers_get_response_ok (
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_CRYPTO_hash_context_abort (hash_context); GNUNET_CRYPTO_hash_context_abort (hash_context);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
GNUNET_free (details);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
GNUNET_CRYPTO_hash_context_read ( /* build up big hash for signature checking later */
hash_context, {
&dd, struct TALER_WireDepositDetailP dd;
sizeof (struct TALER_WireDepositDetailP));
dd.h_contract_terms = detail->h_contract_terms;
dd.execution_time = GNUNET_TIME_absolute_hton (td.execution_time);
dd.coin_pub = detail->coin_pub;
TALER_amount_hton (&dd.deposit_value,
&detail->coin_value);
TALER_amount_hton (&dd.deposit_fee,
&detail->coin_fee);
GNUNET_CRYPTO_hash_context_read (hash_context,
&dd,
sizeof (dd));
}
} }
/* Check signature */ /* Check signature */
wdp.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT);
wdp.purpose.size = htonl (sizeof (struct TALER_WireDepositDataPS));
TALER_amount_hton (&wdp.total,
&total_amount);
TALER_amount_hton (&wdp.wire_fee,
&wire_fee);
wdp.merchant_pub = merchant_pub;
wdp.h_wire = h_wire;
GNUNET_CRYPTO_hash_context_finish (hash_context,
&wdp.h_details);
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (TALER_EXCHANGE_get_keys (
wdh->exchange),
&exchange_pub))
{ {
GNUNET_break_op (0); struct TALER_WireDepositDataPS wdp = {
GNUNET_JSON_parse_free (spec); .purpose.purpose = htonl (
return GNUNET_SYSERR; TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT),
} .purpose.size = htonl (sizeof (wdp)),
if (GNUNET_OK != .merchant_pub = merchant_pub,
GNUNET_CRYPTO_eddsa_verify ( .h_wire = td.h_wire
TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT, };
&wdp,
&exchange_sig.eddsa_signature, TALER_amount_hton (&wdp.total,
&exchange_pub.eddsa_pub)) &td.total_amount);
{ TALER_amount_hton (&wdp.wire_fee,
GNUNET_break_op (0); &td.wire_fee);
GNUNET_JSON_parse_free (spec); GNUNET_CRYPTO_hash_context_finish (hash_context,
return GNUNET_SYSERR; &wdp.h_details);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT,
&wdp,
&td.exchange_sig.eddsa_signature,
&td.exchange_pub.eddsa_pub))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
GNUNET_free (details);
return GNUNET_SYSERR;
}
} }
if (0 > if (0 >
TALER_amount_subtract (&total_expected, TALER_amount_subtract (&total_expected,
&total_expected, &total_expected,
&wire_fee)) &td.wire_fee))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
GNUNET_free (details);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (0 != if (0 !=
TALER_amount_cmp (&total_expected, TALER_amount_cmp (&total_expected,
&total_amount)) &td.total_amount))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
GNUNET_free (details);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
wdh->cb (wdh->cb_cls, wdh->cb (wdh->cb_cls,
&hr, &hr,
&exchange_pub, &td);
&h_wire, GNUNET_free (details);
exec_time,
&total_amount,
&wire_fee,
num_details,
details);
} }
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
TALER_EXCHANGE_transfers_get_cancel (wdh); TALER_EXCHANGE_transfers_get_cancel (wdh);
@ -322,12 +319,7 @@ handle_transfers_get_finished (void *cls,
} }
wdh->cb (wdh->cb_cls, wdh->cb (wdh->cb_cls,
&hr, &hr,
NULL, NULL);
NULL,
GNUNET_TIME_UNIT_ZERO_ABS,
NULL,
NULL,
0, NULL);
TALER_EXCHANGE_transfers_get_cancel (wdh); TALER_EXCHANGE_transfers_get_cancel (wdh);
} }

View File

@ -121,37 +121,18 @@ track_transfer_cleanup (void *cls,
* *
* @param cls closure. * @param cls closure.
* @param hr HTTP response details * @param hr HTTP response details
* @param exchange_pub public key the exchange used for signing * @param ta transfer data returned by the exchange
* the response.
* @param h_wire hash of the wire transfer address the transfer
* went to, or NULL on error.
* @param execution_time time when the exchange claims to have
* performed the wire transfer.
* @param total_amount total amount of the wire transfer, or NULL
* if the exchange could not provide any @a wtid (set only
* if @a http_status is "200 OK").
* @param wire_fee wire fee that was charged by the exchange.
* @param details_length length of the @a details array.
* @param details array with details about the combined
* transactions.
*/ */
static void static void
track_transfer_cb (void *cls, track_transfer_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr, const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_ExchangePublicKeyP *exchange_pub, const struct TALER_EXCHANGE_TransferData *ta)
const struct GNUNET_HashCode *h_wire,
struct GNUNET_TIME_Absolute execution_time,
const struct TALER_Amount *total_amount,
const struct TALER_Amount *wire_fee,
unsigned int details_length,
const struct TALER_TrackTransferDetails *details)
{ {
struct TrackTransferState *tts = cls; struct TrackTransferState *tts = cls;
struct TALER_TESTING_Interpreter *is = tts->is; struct TALER_TESTING_Interpreter *is = tts->is;
struct TALER_TESTING_Command *cmd = &is->commands[is->ip]; struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
struct TALER_Amount expected_amount; struct TALER_Amount expected_amount;
(void) exchange_pub;
tts->tth = NULL; tts->tth = NULL;
if (tts->expected_response_code != hr->http_status) if (tts->expected_response_code != hr->http_status)
{ {
@ -193,14 +174,14 @@ track_transfer_cb (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
if (0 != TALER_amount_cmp (total_amount, if (0 != TALER_amount_cmp (&ta->total_amount,
&expected_amount)) &expected_amount))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Total amount mismatch to command %s - " "Total amount mismatch to command %s - "
"%s vs %s\n", "%s vs %s\n",
cmd->label, cmd->label,
TALER_amount_to_string (total_amount), TALER_amount_to_string (&ta->total_amount),
TALER_amount_to_string (&expected_amount)); TALER_amount_to_string (&expected_amount));
json_dumpf (hr->reply, json_dumpf (hr->reply,
stderr, stderr,
@ -219,7 +200,7 @@ track_transfer_cb (void *cls,
return; return;
} }
if (0 != TALER_amount_cmp (wire_fee, if (0 != TALER_amount_cmp (&ta->wire_fee,
&expected_amount)) &expected_amount))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@ -266,7 +247,7 @@ track_transfer_cb (void *cls,
TALER_JSON_merchant_wire_signature_hash (wire_details, TALER_JSON_merchant_wire_signature_hash (wire_details,
&h_wire_details)); &h_wire_details));
if (0 != GNUNET_memcmp (&h_wire_details, if (0 != GNUNET_memcmp (&h_wire_details,
h_wire)) &ta->h_wire))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Wire hash missmath to command %s\n", "Wire hash missmath to command %s\n",
@ -301,7 +282,7 @@ track_transfer_cb (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
if (0 != TALER_amount_cmp (total_amount, if (0 != TALER_amount_cmp (&ta->total_amount,
total_amount_from_reference)) total_amount_from_reference))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,