implement #4937: allow extraction of fees
This commit is contained in:
parent
1c84b3d4af
commit
0e15a99504
@ -27,6 +27,7 @@
|
|||||||
#include <gnunet/gnunet_curl_lib.h>
|
#include <gnunet/gnunet_curl_lib.h>
|
||||||
#include "taler_exchange_service.h"
|
#include "taler_exchange_service.h"
|
||||||
#include "taler_json_lib.h"
|
#include "taler_json_lib.h"
|
||||||
|
#include "taler_signatures.h"
|
||||||
#include "taler_wire_plugin.h"
|
#include "taler_wire_plugin.h"
|
||||||
#include "exchange_api_handle.h"
|
#include "exchange_api_handle.h"
|
||||||
|
|
||||||
@ -148,6 +149,8 @@ handle_wire_finished (void *cls,
|
|||||||
break;
|
break;
|
||||||
case MHD_HTTP_OK:
|
case MHD_HTTP_OK:
|
||||||
{
|
{
|
||||||
|
const struct TALER_EXCHANGE_Keys *keys;
|
||||||
|
const struct TALER_MasterPublicKeyP *master_pub;
|
||||||
const char *key;
|
const char *key;
|
||||||
json_t *method;
|
json_t *method;
|
||||||
int ret;
|
int ret;
|
||||||
@ -175,19 +178,32 @@ handle_wire_finished (void *cls,
|
|||||||
method);
|
method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* check fees */
|
||||||
|
keys = TALER_EXCHANGE_get_keys (wh->exchange);
|
||||||
|
if (NULL == keys)
|
||||||
|
master_pub = NULL;
|
||||||
|
else
|
||||||
|
master_pub = &keys->master_pub;
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
TALER_EXCHANGE_wire_get_fees (master_pub,
|
||||||
|
keep,
|
||||||
|
NULL,
|
||||||
|
NULL))
|
||||||
|
{
|
||||||
|
/* bogus reply */
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
response_code = 0;
|
||||||
|
}
|
||||||
if (0 != response_code)
|
if (0 != response_code)
|
||||||
{
|
{
|
||||||
/* all supported methods were valid, use 'keep' for 'json' */
|
/* all supported methods were valid, use 'keep' for 'json' */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* some supported methods were invalid, release 'keep', preserve
|
/* some supported methods were invalid, release 'keep', preserve
|
||||||
full 'json' for application-level error handling. */
|
full 'json' for application-level error handling. */
|
||||||
json_decref (keep);
|
json_decref (keep);
|
||||||
keep = NULL;
|
keep = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case MHD_HTTP_BAD_REQUEST:
|
case MHD_HTTP_BAD_REQUEST:
|
||||||
/* This should never happen, either us or the exchange is buggy
|
/* This should never happen, either us or the exchange is buggy
|
||||||
@ -300,4 +316,143 @@ TALER_EXCHANGE_wire_cancel (struct TALER_EXCHANGE_WireHandle *wh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse wire @a fee and store the result in @a af.
|
||||||
|
*
|
||||||
|
* @param[out] af where to write the result
|
||||||
|
* @param fee json AggregateTransferFee to parse
|
||||||
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parse_json_fees (struct TALER_EXCHANGE_WireAggregateFees *af,
|
||||||
|
json_t *fee)
|
||||||
|
{
|
||||||
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("sig",
|
||||||
|
&af->master_sig),
|
||||||
|
TALER_JSON_spec_amount ("wire_fee",
|
||||||
|
&af->wire_fee),
|
||||||
|
GNUNET_JSON_spec_absolute_time ("start_date",
|
||||||
|
&af->start_date),
|
||||||
|
GNUNET_JSON_spec_absolute_time ("end_date",
|
||||||
|
&af->end_date),
|
||||||
|
GNUNET_JSON_spec_end()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_JSON_parse (fee,
|
||||||
|
spec,
|
||||||
|
NULL,
|
||||||
|
NULL))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the #TALER_SIGNATURE_MASTER_WIRE_FEES signature.
|
||||||
|
*
|
||||||
|
* @param af record to check
|
||||||
|
* @param wire_method wire method to check against
|
||||||
|
* @param master_pub expected signing key
|
||||||
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
check_sig (const struct TALER_EXCHANGE_WireAggregateFees *af,
|
||||||
|
const char *wire_method,
|
||||||
|
const struct TALER_MasterPublicKeyP *master_pub)
|
||||||
|
{
|
||||||
|
struct TALER_MasterWireFeePS wp;
|
||||||
|
|
||||||
|
wp.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_FEES);
|
||||||
|
wp.purpose.size = htonl (sizeof (wp));
|
||||||
|
GNUNET_CRYPTO_hash (wire_method,
|
||||||
|
strlen (wire_method) + 1,
|
||||||
|
&wp.h_wire_method);
|
||||||
|
wp.start_date = GNUNET_TIME_absolute_hton (af->start_date);
|
||||||
|
wp.end_date = GNUNET_TIME_absolute_hton (af->end_date);
|
||||||
|
TALER_amount_hton (&wp.wire_fee,
|
||||||
|
&af->wire_fee);
|
||||||
|
return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_FEES,
|
||||||
|
&wp.purpose,
|
||||||
|
&af->master_sig.eddsa_signature,
|
||||||
|
&master_pub->eddsa_pub);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain information about wire fees encoded in @a obj
|
||||||
|
* by wire method.
|
||||||
|
*
|
||||||
|
* @param master_pub public key to use to verify signatures, NULL to not verify
|
||||||
|
* @param obj wire information as encoded in the #TALER_EXCHANGE_WireResultCallback
|
||||||
|
* @param cb callback to invoke for the fees
|
||||||
|
* @param cb_cls closure for @a cb
|
||||||
|
* @return #GNUNET_OK in success, #GNUNET_SYSERR if @a obj is ill-formed
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
TALER_EXCHANGE_wire_get_fees (const struct TALER_MasterPublicKeyP *master_pub,
|
||||||
|
const json_t *obj,
|
||||||
|
TALER_EXCHANGE_WireFeeCallback cb,
|
||||||
|
void *cb_cls)
|
||||||
|
{
|
||||||
|
const char *wire_method;
|
||||||
|
json_t *value;
|
||||||
|
|
||||||
|
json_object_foreach (((json_t *) obj), wire_method, value)
|
||||||
|
{
|
||||||
|
json_t *fees;
|
||||||
|
size_t num_fees;
|
||||||
|
|
||||||
|
fees = json_object_get (value, "fees");
|
||||||
|
if ( (NULL == fees) ||
|
||||||
|
(! json_is_array (fees)) )
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
num_fees = json_array_size (fees);
|
||||||
|
if (num_fees > 1024)
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
struct TALER_EXCHANGE_WireAggregateFees af[num_fees + 1];
|
||||||
|
|
||||||
|
for (size_t i=0;i<num_fees;i++)
|
||||||
|
{
|
||||||
|
af[i].next = &af[i+1];
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
parse_json_fees (&af[i],
|
||||||
|
json_array_get (fees,
|
||||||
|
i)))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
if ( (NULL != master_pub) &&
|
||||||
|
(GNUNET_OK !=
|
||||||
|
check_sig (&af[i],
|
||||||
|
wire_method,
|
||||||
|
master_pub)) )
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
af[num_fees].next = NULL;
|
||||||
|
if (NULL != cb)
|
||||||
|
cb (cb_cls,
|
||||||
|
wire_method,
|
||||||
|
&af[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end of exchange_api_wire.c */
|
/* end of exchange_api_wire.c */
|
||||||
|
@ -340,6 +340,69 @@ TALER_EXCHANGE_get_denomination_key_by_hash (const struct TALER_EXCHANGE_Keys *k
|
|||||||
/* ********************* /wire *********************** */
|
/* ********************* /wire *********************** */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorted list of fees to be paid for aggregate wire transfers.
|
||||||
|
*/
|
||||||
|
struct TALER_EXCHANGE_WireAggregateFees
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This is a linked list.
|
||||||
|
*/
|
||||||
|
struct TALER_EXCHANGE_WireAggregateFees *next;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fee to be paid.
|
||||||
|
*/
|
||||||
|
struct TALER_Amount wire_fee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time when this fee goes into effect (inclusive)
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Absolute start_date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time when this fee stops being in effect (exclusive).
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Absolute end_date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signature affirming the above fee structure.
|
||||||
|
*/
|
||||||
|
struct TALER_MasterSignatureP master_sig;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called with information about the wire fees
|
||||||
|
* for each wire method.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param wire_method name of the wire method (i.e. "sepa")
|
||||||
|
* @param fees fee structure for this method
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*TALER_EXCHANGE_WireFeeCallback)(void *cls,
|
||||||
|
const char *wire_method,
|
||||||
|
const struct TALER_EXCHANGE_WireAggregateFees *fees);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain information about wire fees encoded in @a obj
|
||||||
|
* by wire method.
|
||||||
|
*
|
||||||
|
* @param master_pub public key to use to verify signatures, NULL to not verify
|
||||||
|
* @param obj wire information as encoded in the #TALER_EXCHANGE_WireResultCallback
|
||||||
|
* @param cb callback to invoke for the fees
|
||||||
|
* @param cb_cls closure for @a cb
|
||||||
|
* @return #GNUNET_OK in success, #GNUNET_SYSERR if @a obj is ill-formed
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
TALER_EXCHANGE_wire_get_fees (const struct TALER_MasterPublicKeyP *master_pub,
|
||||||
|
const json_t *obj,
|
||||||
|
TALER_EXCHANGE_WireFeeCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A Wire format inquiry handle
|
* @brief A Wire format inquiry handle
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user