summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-03-04 18:45:25 +0100
committerChristian Grothoff <christian@grothoff.org>2017-03-04 18:45:25 +0100
commit0e15a995048f1653e92f762d983bf47b4fc6b39f (patch)
tree48e075ff6eb17d895f849d5cd5263a8e18da1d3a /src
parent1c84b3d4af1a2484e60a9071556d4690dd7aac33 (diff)
downloadexchange-0e15a995048f1653e92f762d983bf47b4fc6b39f.tar.gz
exchange-0e15a995048f1653e92f762d983bf47b4fc6b39f.tar.bz2
exchange-0e15a995048f1653e92f762d983bf47b4fc6b39f.zip
implement #4937: allow extraction of fees
Diffstat (limited to 'src')
-rw-r--r--src/exchange-lib/exchange_api_wire.c169
-rw-r--r--src/include/taler_exchange_service.h63
2 files changed, 225 insertions, 7 deletions
diff --git a/src/exchange-lib/exchange_api_wire.c b/src/exchange-lib/exchange_api_wire.c
index fe60d664c..ae37741ff 100644
--- a/src/exchange-lib/exchange_api_wire.c
+++ b/src/exchange-lib/exchange_api_wire.c
@@ -27,6 +27,7 @@
#include <gnunet/gnunet_curl_lib.h>
#include "taler_exchange_service.h"
#include "taler_json_lib.h"
+#include "taler_signatures.h"
#include "taler_wire_plugin.h"
#include "exchange_api_handle.h"
@@ -148,6 +149,8 @@ handle_wire_finished (void *cls,
break;
case MHD_HTTP_OK:
{
+ const struct TALER_EXCHANGE_Keys *keys;
+ const struct TALER_MasterPublicKeyP *master_pub;
const char *key;
json_t *method;
int ret;
@@ -175,18 +178,31 @@ handle_wire_finished (void *cls,
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)
{
/* all supported methods were valid, use 'keep' for 'json' */
break;
}
- else
- {
- /* some supported methods were invalid, release 'keep', preserve
- full 'json' for application-level error handling. */
- json_decref (keep);
- keep = NULL;
- }
+ /* some supported methods were invalid, release 'keep', preserve
+ full 'json' for application-level error handling. */
+ json_decref (keep);
+ keep = NULL;
}
break;
case MHD_HTTP_BAD_REQUEST:
@@ -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 */
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index 3ac4069f3..3b9058433 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -341,6 +341,69 @@ TALER_EXCHANGE_get_denomination_key_by_hash (const struct TALER_EXCHANGE_Keys *k
/**
+ * 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
*/
struct TALER_EXCHANGE_WireHandle;