WIP: policy handling advancements
- introduction of policy states. - introduction of default state on timeout. - introduction of TALER_PolicyFulfilmentOutcome - parsing for policy_details now also provides default state on timeout. - introduction of check_serial as preflight func before heavy operations in policy post handler - brandt auction now returns outcomes.
This commit is contained in:
parent
18d8dcd1f9
commit
956e3c3065
@ -1070,18 +1070,32 @@ handle_get_extensions (struct TEH_RequestContext *rc,
|
||||
"/extensions/$EXTENSION unknown");
|
||||
}
|
||||
|
||||
if (NULL == ext->http_get_handler)
|
||||
if (NULL == ext->policy_get_handler)
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_NOT_IMPLEMENTED,
|
||||
TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN,
|
||||
"GET /extensions/$EXTENSION not supported");
|
||||
|
||||
return ext->http_get_handler (
|
||||
return ext->policy_get_handler (
|
||||
rc->connection,
|
||||
&args[1]);
|
||||
}
|
||||
|
||||
|
||||
/* @brief function pointer for TALER_extension.check */
|
||||
static enum GNUNET_GenericReturnValue
|
||||
check_serial_ids (
|
||||
struct GNUNET_HashCode serial_ids[],
|
||||
size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; i++)
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Got to check serial_id: %s\n",
|
||||
GNUNET_h2s (&serial_ids[i]));
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle POST "/extensions/..." requests.
|
||||
*
|
||||
@ -1096,6 +1110,7 @@ handle_post_extensions (struct TEH_RequestContext *rc,
|
||||
const char *const args[])
|
||||
{
|
||||
const struct TALER_Extension *ext = NULL;
|
||||
json_t *output;
|
||||
|
||||
if (NULL == args[0])
|
||||
{
|
||||
@ -1112,16 +1127,49 @@ handle_post_extensions (struct TEH_RequestContext *rc,
|
||||
"/extensions/$EXTENSION unknown");
|
||||
}
|
||||
|
||||
if (NULL == ext->http_post_handler)
|
||||
if (NULL == ext->policy_post_handler)
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_NOT_IMPLEMENTED,
|
||||
TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN,
|
||||
"POST /extensions/$EXTENSION not supported");
|
||||
|
||||
return ext->http_post_handler (
|
||||
rc->connection,
|
||||
root,
|
||||
&args[1]);
|
||||
{
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
struct TALER_PolicyFulfilmentOutcome *outcome;
|
||||
|
||||
ret = ext->policy_post_handler (root,
|
||||
&args[1],
|
||||
&check_serial_ids,
|
||||
&outcome,
|
||||
&output);
|
||||
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
TALER_policy_fulfilment_outcome_free (outcome);
|
||||
TALER_MHD_reply_json_steal (
|
||||
rc->connection,
|
||||
output,
|
||||
MHD_HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
/* TODO: deal with outcome */
|
||||
{
|
||||
for (size_t i = 0; i < outcome->len; i++)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Got outcome for serial_id: %s, state: %s, amount: %s\n",
|
||||
GNUNET_h2s (&outcome->positions[i].serial_id),
|
||||
TALER_policy_fulfilment_state_str (
|
||||
outcome->positions[i].state),
|
||||
TALER_amount_to_string (&outcome->positions[i].new_amount));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return TALER_MHD_reply_json_steal (rc->connection,
|
||||
output,
|
||||
MHD_HTTP_OK);
|
||||
}
|
||||
|
||||
|
||||
|
@ -337,15 +337,22 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
if (deposit.has_policy_details)
|
||||
{
|
||||
const char *error_hint = NULL;
|
||||
enum TALER_PolicyFulfilmentState state_on_timeout;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_extensions_serial_from_policy_details (deposit.policy_details,
|
||||
&deposit.policy_serial_id,
|
||||
&deposit.policy_deadline,
|
||||
&error_hint))
|
||||
TALER_extensions_extract_meta_data_from_policy_details (
|
||||
deposit.policy_details,
|
||||
&deposit.policy_serial_id,
|
||||
&deposit.policy_deadline,
|
||||
&state_on_timeout,
|
||||
&error_hint))
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_DEPOSITS_POLICY_NOT_ACCEPTED,
|
||||
error_hint);
|
||||
|
||||
GNUNET_assert (TALER_PolicyFulfilmentStateMax >= state_on_timeout);
|
||||
deposit.policy_state_on_timeout = state_on_timeout;
|
||||
}
|
||||
|
||||
/* new deposit */
|
||||
|
@ -561,7 +561,8 @@ CREATE TABLE IF NOT EXISTS policy_details
|
||||
,serial_id BYTEA PRIMARY KEY CHECK(LENGTH(serial_id)=64)
|
||||
,policy_options VARCHAR
|
||||
,deadline INT8 NOT NULL
|
||||
,fulfilment_state INT4 NOT NULL CHECK(fulfilment_state between 0 and 3))
|
||||
,timeout_fulfilment_state smallint NOT NULL CHECK(timeout_fulfilment_state in (5, 6))
|
||||
,fulfilment_state smallint NOT NULL CHECK(fulfilment_state between 0 and 6))
|
||||
PARTITION BY HASH (serial_id);
|
||||
COMMENT ON TABLE policy_details
|
||||
IS 'Policies that were provided with deposits via policy extensions.';
|
||||
@ -571,8 +572,17 @@ COMMENT ON COLUMN policy_details.policy_options
|
||||
IS 'JSON object with options set that the exchange needs to consider when executing a deposit. Supported details depend on the policy extensions supported by the exchange.';
|
||||
COMMENT ON COLUMN policy_details.deadline
|
||||
IS 'Deadline until the policy must be marked as fulfilled or unfulfilled (maybe "forever")';
|
||||
COMMENT ON COLUMN policy_details.timeout_fulfilment_state
|
||||
IS 'State that a pending policy should be put into, once the deadline is reached. Allowed values are 5 (TIMEOUT, transfer coins) or 6 (TIMEOUT, coins refreshable)';
|
||||
COMMENT ON COLUMN policy_details.fulfilment_state
|
||||
IS 'State of the fulfilment: 0 (PENDING), 1 (FULFILLED), 2 (NOT FULFILLED), 3 (TIMED OUT)';
|
||||
IS 'State of the fulfilment:
|
||||
- 0 (PENDING)
|
||||
- 1 (SUCCESS, transfer coins)
|
||||
- 2 (SUCCESS, coins refreshable)
|
||||
- 3 (FAILURE, transfer coins)
|
||||
- 4 (FAILURE, coins refreshable)
|
||||
- 5 (TIMEOUT, tranfer coins)
|
||||
- 6 (TIMEOUT, coins refrehsable)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS policy_details_default
|
||||
PARTITION OF policy_details
|
||||
|
@ -929,11 +929,16 @@ irbt_cb_table_policy_details (struct PostgresClosure *pg,
|
||||
{
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_uint64 (&td->serial),
|
||||
NULL ==
|
||||
td->details.policy_details.policy_options ?
|
||||
NULL == td->details.policy_details.policy_options ?
|
||||
GNUNET_PQ_query_param_null () :
|
||||
GNUNET_PQ_query_param_string (
|
||||
td->details.policy_details.policy_options),
|
||||
GNUNET_PQ_query_param_timestamp (
|
||||
&td->details.policy_details.deadline),
|
||||
GNUNET_PQ_query_param_uint16 (
|
||||
&td->details.policy_details.timeout_fulfilment_state),
|
||||
GNUNET_PQ_query_param_uint16 (
|
||||
&td->details.policy_details.fulfilment_state),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
|
||||
|
@ -1456,7 +1456,10 @@ lrbt_cb_table_policy_details (void *cls,
|
||||
GNUNET_PQ_result_spec_timestamp ("deadline",
|
||||
&td.details.policy_details.
|
||||
deadline),
|
||||
GNUNET_PQ_result_spec_uint64 ("fulfilment_state",
|
||||
GNUNET_PQ_result_spec_uint16 ("timeout_fulfilment_state",
|
||||
&td.details.policy_details.
|
||||
timeout_fulfilment_state),
|
||||
GNUNET_PQ_result_spec_uint16 ("fulfilment_state",
|
||||
&td.details.policy_details.
|
||||
fulfilment_state),
|
||||
GNUNET_PQ_result_spec_end
|
||||
@ -1502,16 +1505,16 @@ lrbt_cb_table_policy_fulfilments (void *cls,
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_uint64 ("fulfilment_id",
|
||||
&td.serial),
|
||||
GNUNET_PQ_result_spec_allow_null (
|
||||
GNUNET_PQ_result_spec_string ("fulfilment_proof",
|
||||
&td.details.policy_fulfilments.
|
||||
fulfilment_proof),
|
||||
&no_config),
|
||||
GNUNET_PQ_result_spec_allow_null (
|
||||
GNUNET_PQ_result_spec_timestamp ("fulfilment_timestamp",
|
||||
&td.details.policy_fulfilments.
|
||||
fulfilment_timestamp),
|
||||
&no_timestamp),
|
||||
GNUNET_PQ_result_spec_allow_null (
|
||||
GNUNET_PQ_result_spec_string ("fulfilment_proof",
|
||||
&td.details.policy_fulfilments.
|
||||
fulfilment_proof),
|
||||
&no_config),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
|
@ -822,8 +822,8 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
",out_balance_ok AS balance_ok"
|
||||
",out_conflict AS conflicted"
|
||||
" FROM exchange_do_deposit"
|
||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19);",
|
||||
19),
|
||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20);",
|
||||
20),
|
||||
/* used in postgres_do_purse_deposit() */
|
||||
GNUNET_PQ_make_prepare (
|
||||
"call_purse_deposit",
|
||||
@ -3933,10 +3933,11 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
",serial_id"
|
||||
",policy_options"
|
||||
",deadline"
|
||||
",timeout_fulfilment_state"
|
||||
",fulfilment_state"
|
||||
") VALUES "
|
||||
"($1, $2, $3, $4, $5);",
|
||||
5),
|
||||
"($1, $2, $3, $4, $5, $6);",
|
||||
6),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"insert_into_table_policy_fulfilments",
|
||||
"INSERT INTO policy_fulfilments"
|
||||
@ -6292,6 +6293,9 @@ postgres_do_deposit (
|
||||
(deposit->has_policy_details)
|
||||
? GNUNET_PQ_query_param_timestamp (&deposit->policy_deadline)
|
||||
: GNUNET_PQ_query_param_null (),
|
||||
(deposit->has_policy_details)
|
||||
? GNUNET_PQ_query_param_uint16 (&deposit->policy_state_on_timeout)
|
||||
: GNUNET_PQ_query_param_null (),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
@ -14651,6 +14655,7 @@ postgres_insert_records_by_table (void *cls,
|
||||
case TALER_EXCHANGEDB_RT_POLICY_DETAILS:
|
||||
rh = &irbt_cb_table_policy_details;
|
||||
break;
|
||||
/* TODO: policy_details_fulfilments and policy_fulfilments */
|
||||
case TALER_EXCHANGEDB_RT_PURSE_REQUESTS:
|
||||
rh = &irbt_cb_table_purse_requests;
|
||||
break;
|
||||
|
@ -513,7 +513,8 @@ CREATE OR REPLACE FUNCTION exchange_do_deposit(
|
||||
IN in_policy_blocked BOOLEAN,
|
||||
IN in_policy_details VARCHAR,
|
||||
IN in_policy_serial_id BYTEA,
|
||||
IN in_policy_deadline INT8,
|
||||
IN in_policy_deadline SMALLINT,
|
||||
IN in_policy_timeout_fulfilment_state SMALLINT,
|
||||
OUT out_exchange_timestamp INT8,
|
||||
OUT out_balance_ok BOOLEAN,
|
||||
OUT out_conflict BOOLEAN)
|
||||
@ -535,11 +536,13 @@ THEN
|
||||
(serial_id
|
||||
,policy_options
|
||||
,deadline
|
||||
,timeout_fulfilment_state
|
||||
,fulfilment_state)
|
||||
VALUES
|
||||
(in_policy_serial_id
|
||||
,in_policy_details
|
||||
,in_policy_deadline
|
||||
,in_policy_timeout_fulfilment_state
|
||||
,0) -- 0 == pending
|
||||
RETURNING policy_details_serial_id INTO xdi;
|
||||
ELSE
|
||||
|
@ -154,8 +154,8 @@ struct TALER_Extension TE_age_restriction = {
|
||||
|
||||
/* This extension is not a policy extension */
|
||||
.parse_policy_details = NULL,
|
||||
.http_get_handler = NULL,
|
||||
.http_post_handler = NULL,
|
||||
.policy_get_handler = NULL,
|
||||
.policy_post_handler = NULL,
|
||||
};
|
||||
|
||||
|
||||
|
@ -353,13 +353,38 @@ TALER_extensions_load_manifests (
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Policy related
|
||||
*/
|
||||
|
||||
static char *fulfilment2str[] = {
|
||||
[TALER_PolicyFulfilmentPending] = "Pending",
|
||||
[TALER_PolicyFulfilmentSuccessTransfer] = "SuccessTransfer",
|
||||
[TALER_PolicyFulfilmentSuccessRefreshable] = "SuccessRefreshable",
|
||||
[TALER_PolicyFulfilmentFailureTransfer] = "FailureTransfer",
|
||||
[TALER_PolicyFulfilmentFailureRefreshable] = "FailureRefreshable",
|
||||
[TALER_PolicyFulfilmentTimeoutTransfer] = "TimeoutTransfer",
|
||||
[TALER_PolicyFulfilmentTimeoutRefreshable] = "TimeoutRefreshable",
|
||||
};
|
||||
|
||||
const char *
|
||||
TALER_policy_fulfilment_state_str (
|
||||
enum TALER_PolicyFulfilmentState state)
|
||||
{
|
||||
GNUNET_assert (TALER_PolicyFulfilmentStateMax >= state);
|
||||
return fulfilment2str[state];
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_extensions_serial_from_policy_details (
|
||||
TALER_extensions_extract_meta_data_from_policy_details (
|
||||
const json_t *policy_details,
|
||||
struct GNUNET_HashCode *serial,
|
||||
struct GNUNET_TIME_Timestamp *deadline,
|
||||
enum TALER_PolicyFulfilmentState *state_on_deadline,
|
||||
const char **error_hint)
|
||||
{
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
const struct TALER_Extension *extension;
|
||||
const json_t *jtype;
|
||||
const char *type;
|
||||
@ -399,12 +424,49 @@ TALER_extensions_serial_from_policy_details (
|
||||
}
|
||||
|
||||
*deadline = GNUNET_TIME_UNIT_FOREVER_TS;
|
||||
return extension->parse_policy_details (policy_details,
|
||||
serial,
|
||||
deadline,
|
||||
error_hint);
|
||||
ret = extension->parse_policy_details (policy_details,
|
||||
serial,
|
||||
deadline,
|
||||
state_on_deadline,
|
||||
error_hint);
|
||||
|
||||
GNUNET_assert ((TALER_PolicyFulfilmentTimeoutRefreshable ==
|
||||
*state_on_deadline) ||
|
||||
(TALER_PolicyFulfilmentTimeoutTransfer ==
|
||||
*state_on_deadline));
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct TALER_PolicyFulfilmentOutcome *
|
||||
TALER_policy_fulfilment_outcome_new (size_t len)
|
||||
{
|
||||
struct TALER_PolicyFulfilmentOutcome *out;
|
||||
|
||||
out = GNUNET_new (struct TALER_PolicyFulfilmentOutcome);
|
||||
out->len = len;
|
||||
out->positions = GNUNET_new_array (len,
|
||||
struct
|
||||
TALER_PolicyFulfilmentOutcomePosition);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_policy_fulfilment_outcome_free (
|
||||
struct TALER_PolicyFulfilmentOutcome *outcome)
|
||||
{
|
||||
if (NULL == outcome)
|
||||
return;
|
||||
|
||||
if (NULL != outcome->positions)
|
||||
GNUNET_free (outcome->positions);
|
||||
|
||||
GNUNET_free (outcome);
|
||||
}
|
||||
|
||||
|
||||
/* end of extensions.c */
|
||||
|
@ -14,7 +14,7 @@
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file policy_brandt_vickery_auction.c
|
||||
* @file policy_brandt_vickrey_auction.c
|
||||
* @brief Extension for replay of auctions of type Brandt
|
||||
* @author Özgür Kesim
|
||||
*/
|
||||
@ -26,8 +26,8 @@
|
||||
#include "stdint.h"
|
||||
#include <microhttpd.h>
|
||||
|
||||
#define POLICY_AUCTION "policy_brandt_vickery_auction"
|
||||
#define LOG_PREFIX "[policy_brandt_vickery_auction] "
|
||||
#define POLICY_AUCTION "policy_brandt_vickrey_auction"
|
||||
#define LOG_PREFIX "[policy_brandt_vickrey_auction] "
|
||||
#define MAX_RESULT_SIZE 10 * 1024
|
||||
|
||||
/* (public) configuration of this extension */
|
||||
@ -54,7 +54,7 @@ struct result
|
||||
{
|
||||
uint16_t bidder;
|
||||
uint16_t price_idx;
|
||||
const char *price;
|
||||
const char *price;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -73,12 +73,19 @@ struct transcript
|
||||
/* Payto URL */
|
||||
const char *payto;
|
||||
|
||||
/* Number of bidders + 1 (for seller) */
|
||||
/* Number of bidders */
|
||||
uint16_t n;
|
||||
|
||||
/* (n-1) public keys of bidders */
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey *bidder_pub;
|
||||
|
||||
/* Hash of the auction */
|
||||
struct GNUNET_HashCode h_auction;
|
||||
|
||||
/* (n-1) calculated serial_ids */
|
||||
struct GNUNET_HashCode *serial_ids;
|
||||
|
||||
|
||||
/* Type of auction, see libbrandt */
|
||||
uint16_t m;
|
||||
|
||||
@ -137,6 +144,25 @@ json_error (json_t **output,
|
||||
};
|
||||
|
||||
|
||||
/* Create serial as H(bidder_pub, h_auction) */
|
||||
static void
|
||||
calculate_serial (
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey *pub,
|
||||
struct GNUNET_HashCode *hc,
|
||||
struct GNUNET_HashCode *serial)
|
||||
{
|
||||
struct GNUNET_HashContext *ctx = GNUNET_CRYPTO_hash_context_start ();
|
||||
GNUNET_CRYPTO_hash_context_read (ctx,
|
||||
pub,
|
||||
sizeof(*pub));
|
||||
GNUNET_CRYPTO_hash_context_read (ctx,
|
||||
hc,
|
||||
sizeof(*hc));
|
||||
GNUNET_CRYPTO_hash_context_finish (ctx,
|
||||
serial);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @brief Parses a given json as transcript.
|
||||
*
|
||||
@ -165,8 +191,8 @@ parse_transcript (const json_t *jtr,
|
||||
char *perr;
|
||||
unsigned int eline;
|
||||
struct GNUNET_JSON_Specification au_spec[] = {
|
||||
GNUNET_JSON_spec_bool ("public", &tr->public),
|
||||
GNUNET_JSON_spec_uint16 ("type", &tr->m),
|
||||
GNUNET_JSON_spec_bool ("outcome_public", &tr->public),
|
||||
GNUNET_JSON_spec_uint16 ("auction_type", &tr->m),
|
||||
GNUNET_JSON_spec_fixed_auto ("pubkey", &tr->seller_pub),
|
||||
GNUNET_JSON_spec_timestamp ("time_start", &tr->time_start),
|
||||
GNUNET_JSON_spec_relative_time ("time_round", &tr->time_round),
|
||||
@ -187,6 +213,13 @@ parse_transcript (const json_t *jtr,
|
||||
return json_error (jerror,
|
||||
perr);
|
||||
|
||||
{
|
||||
const char *auc_js = json_dumps (auc, JSON_COMPACT);
|
||||
GNUNET_CRYPTO_hash (auc_js,
|
||||
strlen (auc_js),
|
||||
&tr->h_auction);
|
||||
}
|
||||
|
||||
// Prices...
|
||||
{
|
||||
size_t idx;
|
||||
@ -235,15 +268,23 @@ parse_transcript (const json_t *jtr,
|
||||
|
||||
tr->n = json_array_size (bidders);
|
||||
|
||||
tr->bidder_pub = GNUNET_new_array (tr->n, struct
|
||||
GNUNET_CRYPTO_EddsaPublicKey);
|
||||
tr->bidder_pub = GNUNET_new_array (
|
||||
tr->n,
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey);
|
||||
|
||||
tr->serial_ids = GNUNET_new_array (
|
||||
tr->n,
|
||||
struct GNUNET_HashCode);
|
||||
|
||||
json_array_foreach (bidders, idx, val)
|
||||
{
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto (NULL,
|
||||
&(tr->bidder_pub[idx])),
|
||||
&tr->bidder_pub[idx]),
|
||||
GNUNET_JSON_spec_end (),
|
||||
};
|
||||
|
||||
/* TODO: cleanup */
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (val,
|
||||
spec,
|
||||
@ -252,12 +293,13 @@ parse_transcript (const json_t *jtr,
|
||||
return json_error (jerror,
|
||||
"bidder no %ld public key couldn't be parsed",
|
||||
idx + 1);
|
||||
|
||||
calculate_serial (&tr->bidder_pub[idx],
|
||||
&tr->h_auction,
|
||||
&tr->serial_ids[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: parse and verify signatures from bidders of the auction
|
||||
|
||||
|
||||
// Messages
|
||||
{
|
||||
size_t nm;
|
||||
@ -322,7 +364,6 @@ parse_transcript (const json_t *jtr,
|
||||
|
||||
DONE:
|
||||
|
||||
*jerror = NULL;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
@ -331,7 +372,8 @@ DONE:
|
||||
* @brief replay an auction using the external program
|
||||
*
|
||||
* @param[in] root The original JSON transcript
|
||||
* @param[in] transcript The transcript object parsed so far
|
||||
* @param[in,out] transcript The transcript object parsed so far
|
||||
* @param[out] outcome Outcome object to fill
|
||||
* @param[out] result The JSON result from the program
|
||||
* @return GNUNET_OK on success
|
||||
*
|
||||
@ -340,8 +382,10 @@ DONE:
|
||||
static enum GNUNET_GenericReturnValue
|
||||
replay_transcript (const json_t*root,
|
||||
struct transcript *tr,
|
||||
struct TALER_PolicyFulfilmentOutcome **outcome,
|
||||
json_t **result)
|
||||
{
|
||||
enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR;
|
||||
struct GNUNET_DISK_PipeHandle *pi;
|
||||
struct GNUNET_DISK_PipeHandle *po;
|
||||
const struct GNUNET_DISK_FileHandle *fd;
|
||||
@ -444,32 +488,106 @@ replay_transcript (const json_t*root,
|
||||
return json_error (result, "internal error");
|
||||
}
|
||||
|
||||
// TODO: check each winner with tr->expected, if applicable
|
||||
|
||||
|
||||
// Create the outcome object
|
||||
{
|
||||
// TODO: check each winner with tr->expected, if applicable
|
||||
json_object_set (res, "exchange_sig", json_string (
|
||||
"sig(priv_E, winners)"));
|
||||
json_t *w;
|
||||
size_t idx;
|
||||
struct TALER_PolicyFulfilmentOutcomePosition *pos;
|
||||
|
||||
*outcome =
|
||||
TALER_policy_fulfilment_outcome_new (tr->n);
|
||||
|
||||
/* Set outcome for all bidders to a default value first */
|
||||
for (uint16_t i = 0; i<tr->n; i++)
|
||||
{
|
||||
pos = &((*outcome)->positions[i]);
|
||||
pos->serial_id = tr->serial_ids[i];
|
||||
pos->has_new_amount = false;
|
||||
pos->state = TALER_PolicyFulfilmentFailureRefreshable;
|
||||
}
|
||||
|
||||
/* Set the outcome of the winners */
|
||||
json_array_foreach (winners, idx, w)
|
||||
{
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
const char *jerror;
|
||||
uint16_t bidder;
|
||||
uint16_t price_idx;
|
||||
struct TALER_Amount price;
|
||||
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_uint16 ("bidder",
|
||||
&bidder),
|
||||
GNUNET_JSON_spec_uint16 ("price_idx",
|
||||
&price_idx),
|
||||
TALER_JSON_spec_amount ("price",
|
||||
BV_config.auction_fee.currency,
|
||||
&price),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
ret = GNUNET_JSON_parse (w,
|
||||
spec,
|
||||
&jerror,
|
||||
NULL);
|
||||
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
LOG_PREFIX
|
||||
"couldn't parse output of replay program: %s\n",
|
||||
jerror);
|
||||
ret = json_error (result, "internal error");
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
if (bidder > tr->n - 1)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
LOG_PREFIX
|
||||
"replay program sent a bidder out of range\n");
|
||||
ret = json_error (result, "internal error");
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
// Fill the outcome position for this winning bidder.
|
||||
pos = &((*outcome)->positions[idx]);
|
||||
pos->has_new_amount = true;
|
||||
pos->new_amount = price;
|
||||
pos->state = TALER_PolicyFulfilmentSuccessTransfer;
|
||||
}
|
||||
|
||||
// TODO: return own result object.
|
||||
// TODO: sign the result by the exchange
|
||||
*result = json_copy (res);
|
||||
json_decref (res);
|
||||
}
|
||||
|
||||
// TODO: return own result object.
|
||||
*result = json_copy (res);
|
||||
json_decref (res);
|
||||
}
|
||||
|
||||
ret = GNUNET_OK;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != GNUNET_OS_process_wait (proc))
|
||||
ret = GNUNET_OS_process_wait (proc);
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
LOG_PREFIX "error while launching auction replay program '%s'\n",
|
||||
LOG_PREFIX
|
||||
"error waiting for auction replay program '%s'\n",
|
||||
replay_program);
|
||||
|
||||
json_object_clear (*result);
|
||||
return json_error (result, "internal error");
|
||||
ret = json_error (result, "internal error");
|
||||
}
|
||||
|
||||
|
||||
return GNUNET_OK;
|
||||
DONE:
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
TALER_policy_fulfilment_outcome_free (*outcome);
|
||||
*outcome = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -531,60 +649,58 @@ auction_load_config (
|
||||
|
||||
|
||||
/**
|
||||
* @brief implements the TALER_Extension.http_get_handler
|
||||
* @brief implements the TALER_Extension.policy_get_handler
|
||||
*/
|
||||
static MHD_RESULT
|
||||
auction_http_get_handler (
|
||||
auction_policy_get_handler (
|
||||
struct MHD_Connection *connection,
|
||||
const char *const args[])
|
||||
{
|
||||
/* TODO: return some meta-data about supported version, limits, etc.*/
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
LOG_PREFIX "auction_http_get_handler not implemented yet\n");
|
||||
LOG_PREFIX "auction_policy_get_handler not implemented yet\n");
|
||||
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_NOT_IMPLEMENTED,
|
||||
TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN,
|
||||
"auction_http_get_handler not implemented yet\n");
|
||||
"auction_policy_get_handler not implemented yet\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief implements the TALER_Extension.http_post_handler
|
||||
* @brief implements the TALER_Extension.policy_post_handler
|
||||
*
|
||||
* TODO: make this non-blocking
|
||||
*/
|
||||
static MHD_RESULT
|
||||
auction_http_post_handler (
|
||||
struct MHD_Connection *connection,
|
||||
enum GNUNET_GenericReturnValue
|
||||
auction_policy_post_handler (
|
||||
const json_t *root,
|
||||
const char *const args[])
|
||||
const char *const args[],
|
||||
enum GNUNET_GenericReturnValue (*serial_id_check)(struct GNUNET_HashCode
|
||||
serial_ids[], size_t size),
|
||||
struct TALER_PolicyFulfilmentOutcome **outcome,
|
||||
json_t **output)
|
||||
{
|
||||
struct transcript tr = {};
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
json_t *result1;
|
||||
json_t *result2;
|
||||
|
||||
*outcome = NULL;
|
||||
ret = parse_transcript (root,
|
||||
&tr,
|
||||
&result1);
|
||||
output);
|
||||
|
||||
/* TODO: cleanups! */
|
||||
if (GNUNET_OK != ret)
|
||||
return TALER_MHD_reply_json_steal (connection,
|
||||
result1,
|
||||
MHD_HTTP_BAD_REQUEST);
|
||||
GNUNET_assert (NULL == result1);
|
||||
return ret;
|
||||
|
||||
ret = replay_transcript (root,
|
||||
&tr,
|
||||
&result2);
|
||||
serial_id_check (tr.serial_ids, tr.n);
|
||||
|
||||
return TALER_MHD_reply_json_steal (connection,
|
||||
result2,
|
||||
GNUNET_OK == ret?
|
||||
MHD_HTTP_OK :
|
||||
MHD_HTTP_BAD_REQUEST);
|
||||
return replay_transcript (root,
|
||||
&tr,
|
||||
outcome,
|
||||
output);
|
||||
}
|
||||
|
||||
|
||||
@ -594,6 +710,7 @@ auction_http_post_handler (
|
||||
* @param[in] input The policy_details for this handler during deposit
|
||||
* @param[out] serial On success will contain the serial-ID under which the
|
||||
* @param[out] deadline On success will contain a deadline, might be "forever"
|
||||
* @param[out] state_on_timeout On success, will be set to the default state that the policy shall be put in case of a timeout.
|
||||
* @param[out] error_hint On error, will contain a hint
|
||||
* exchange should store the policy_details in the policy_details table.
|
||||
* @return GNUNET_OK if the request was OK
|
||||
@ -603,6 +720,7 @@ auction_parse_policy_details (
|
||||
const json_t *input,
|
||||
struct GNUNET_HashCode *serial,
|
||||
struct GNUNET_TIME_Timestamp *deadline,
|
||||
enum TALER_PolicyFulfilmentState *state_on_timeout,
|
||||
const char **error_hint)
|
||||
{
|
||||
enum GNUNET_GenericReturnValue ret = GNUNET_NO;
|
||||
@ -636,22 +754,14 @@ auction_parse_policy_details (
|
||||
LOG_PREFIX "check of deadline %ld not implemented!\n",
|
||||
deadline->abs_time.abs_value_us);
|
||||
|
||||
/* Create serial as H(bidder_pub, h_auction) */
|
||||
{
|
||||
struct GNUNET_HashContext *hc = GNUNET_CRYPTO_hash_context_start ();
|
||||
GNUNET_CRYPTO_hash_context_read (hc,
|
||||
&pub,
|
||||
sizeof(pub));
|
||||
GNUNET_CRYPTO_hash_context_read (hc,
|
||||
&hc,
|
||||
sizeof(hc));
|
||||
GNUNET_CRYPTO_hash_context_finish (hc,
|
||||
serial);
|
||||
}
|
||||
calculate_serial (&pub, &hc, serial);
|
||||
|
||||
ret = GNUNET_OK;
|
||||
} while(0);
|
||||
|
||||
/* In case of timeout, the coin shall be refreshable by the owner */
|
||||
*state_on_timeout = TALER_PolicyFulfilmentTimeoutRefreshable;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -668,8 +778,8 @@ struct TALER_Extension TE_auction_brandt = {
|
||||
.load_config = &auction_load_config,
|
||||
.manifest = &auction_manifest,
|
||||
.parse_policy_details = &auction_parse_policy_details,
|
||||
.http_get_handler = &auction_http_get_handler,
|
||||
.http_post_handler = &auction_http_post_handler,
|
||||
.policy_get_handler = &auction_policy_get_handler,
|
||||
.policy_post_handler = &auction_policy_post_handler,
|
||||
};
|
||||
|
||||
|
||||
@ -687,7 +797,7 @@ struct TALER_Extension TE_auction_brandt = {
|
||||
* @return Pointer to TE_auction_brandt
|
||||
*/
|
||||
struct TALER_Extension *
|
||||
libtaler_extension_policy_brandt_vickery_auction_init (void *arg)
|
||||
libtaler_extension_policy_brandt_vickrey_auction_init (void *arg)
|
||||
{
|
||||
const struct GNUNET_CONFIGURATION_Handle *cfg = arg;
|
||||
|
||||
@ -751,7 +861,7 @@ libtaler_extension_policy_brandt_vickery_auction_init (void *arg)
|
||||
* @return null
|
||||
*/
|
||||
void *
|
||||
libtaler_extension_policy_brandt_vickery_auction_done (void *arg)
|
||||
libtaler_extension_policy_brandt_vickrey_auction_done (void *arg)
|
||||
{
|
||||
auction_disable (&TE_auction_brandt);
|
||||
GNUNET_free (replay_program);
|
||||
@ -761,4 +871,4 @@ libtaler_extension_policy_brandt_vickery_auction_done (void *arg)
|
||||
}
|
||||
|
||||
|
||||
/* end of policy_brandt_vickery_auction.c */
|
||||
/* end of policy_brandt_vickrey_auction.c */
|
||||
|
@ -531,7 +531,8 @@ struct TALER_EXCHANGEDB_TableData
|
||||
char *policy_options;
|
||||
struct GNUNET_HashCode serial_id;
|
||||
struct GNUNET_TIME_Timestamp deadline;
|
||||
uint64_t fulfilment_state;
|
||||
uint16_t timeout_fulfilment_state;
|
||||
uint16_t fulfilment_state;
|
||||
} policy_details;
|
||||
|
||||
struct
|
||||
@ -1464,6 +1465,11 @@ struct TALER_EXCHANGEDB_Deposit
|
||||
*/
|
||||
struct GNUNET_TIME_Timestamp policy_deadline;
|
||||
|
||||
/**
|
||||
* The state that a _pending_ policy should be put into once the timeout triggers
|
||||
*/
|
||||
uint16_t policy_state_on_timeout;
|
||||
|
||||
|
||||
/**
|
||||
* Hash over the @e policy_details. Only filled if has_policy_details is
|
||||
|
@ -53,6 +53,10 @@ struct TALER_Extensions
|
||||
const struct TALER_Extension *extension;
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
enum TALER_PolicyFulfilmentState;
|
||||
struct TALER_PolicyFulfilmentOutcome;
|
||||
|
||||
/*
|
||||
* @brief Represents the implementation of an extension.
|
||||
*
|
||||
@ -159,6 +163,7 @@ struct TALER_Extension
|
||||
* Policy related handlers
|
||||
* =========================
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Handler to check a policy. Can be NULL;
|
||||
*
|
||||
@ -166,44 +171,55 @@ struct TALER_Extension
|
||||
* (see https://docs.taler.net/core/api-exchange.html#deposit), this handler
|
||||
* will be called before the deposit transaction.
|
||||
*
|
||||
* @param[in] policy_details Details about the policy, provided by the client
|
||||
* during a deposit request.
|
||||
* @param[in] policy_details Details about the policy, provided by the client
|
||||
* during a deposit request.
|
||||
* @param[out] serial On success, will contain the serial-ID under which the
|
||||
* exchange should save the policy_details in the deposit table.
|
||||
* exchange should save the policy_details in the deposit table.
|
||||
* @param[out] deadline On success, set to the deadline until the policy must
|
||||
* be fulfilled. Might be "forever". This value is used by an external
|
||||
* be fulfilled. Might be "forever". This value is used by an
|
||||
* external mechanism to detect timeouts.
|
||||
* @param[out] state_on_timeout On GNUNET_OK, which state shall the
|
||||
* fulfilment of this policy be put in. MUST be either
|
||||
* TALER_PolicyFulfilmentTimeoutTransfer or
|
||||
* TALER_PolicyFulfilmentTimeoutRefreshable
|
||||
* @param[out] error_hint On error, will contain a hint
|
||||
* mechanism to detect timeouts.
|
||||
* @return GNUNET_OK if the data was accepted by the extension.
|
||||
* @return GNUNET_OK if the data was accepted by the extension.
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue (*parse_policy_details)(
|
||||
const json_t *policy_details,
|
||||
struct GNUNET_HashCode *serial,
|
||||
struct GNUNET_TIME_Timestamp *deadline,
|
||||
enum TALER_PolicyFulfilmentState *state_on_timeout,
|
||||
const char **error_hint);
|
||||
|
||||
/**
|
||||
* @brief Handler for POST-requests to the /policy/$name endpoint. Can be NULL.
|
||||
* @brief Handler for POST-requests to the /extensions/$name endpoint. Can be NULL.
|
||||
*
|
||||
* @param connection The current connection
|
||||
* @param root The JSON body from the request
|
||||
* @param args Additional query parameters of the request.
|
||||
* @return MDH result
|
||||
* @param[in] root The JSON body from the request
|
||||
* @param[in] args Additional query parameters of the request.
|
||||
* @param[in] serial_id_check Helper function to check the presence of serial_ids in policy_details. Can be used by the handler to ensure the presence of entries before starting calculations.
|
||||
* @param[out] outcome Result of the operation. Must be freed via TALER_policy_fulfilment_outcome_free after use.
|
||||
* @param[out] output JSON output to return to the client
|
||||
* @return GNUNET_OK on success.
|
||||
*/
|
||||
MHD_RESULT (*http_post_handler)(
|
||||
struct MHD_Connection *connection,
|
||||
enum GNUNET_GenericReturnValue (*policy_post_handler)(
|
||||
const json_t *root,
|
||||
const char *const args[]);
|
||||
const char *const args[],
|
||||
enum GNUNET_GenericReturnValue (*serial_id_check)(struct GNUNET_HashCode
|
||||
serial_ids[], size_t
|
||||
size),
|
||||
struct TALER_PolicyFulfilmentOutcome **outcome,
|
||||
json_t **output);
|
||||
|
||||
/**
|
||||
* @brief Handler for GET-requests to the /policy/$name endpoint. Can be NULL.
|
||||
* @brief Handler for GET-requests to the /extensions/$name endpoint. Can be NULL.
|
||||
*
|
||||
* @param connection The current connection
|
||||
* @param root The JSON body from the request
|
||||
* @param args Additional query parameters of the request.
|
||||
* @return MDH result
|
||||
*/
|
||||
MHD_RESULT (*http_get_handler)(
|
||||
MHD_RESULT (*policy_get_handler)(
|
||||
struct MHD_Connection *connection,
|
||||
const char *const args[]);
|
||||
};
|
||||
@ -382,28 +398,123 @@ TALER_extensions_get_age_restriction_mask ();
|
||||
|
||||
/*
|
||||
* ===================================
|
||||
* Policy extensions related functions
|
||||
* Policy extensions related API
|
||||
* ===================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @brief Finds the extension for a given policy
|
||||
* @brief Describes the states of fulfilment of a policy bound to a deposit
|
||||
*/
|
||||
enum TALER_PolicyFulfilmentState
|
||||
{
|
||||
/* Initial state of the policy */
|
||||
TALER_PolicyFulfilmentPending = 0,
|
||||
|
||||
/*
|
||||
* Policy provably fulfilled. The semantics of the policy require that
|
||||
* the exchange MUST transfer amount in the associated deposit to the
|
||||
* payto-URI */
|
||||
TALER_PolicyFulfilmentSuccessTransfer = 1,
|
||||
|
||||
/*
|
||||
* Policy provably fulfilled. The semantics of the policy require that
|
||||
* the coins' value in the associated deposit remains and the owner can
|
||||
* refresh them. */
|
||||
TALER_PolicyFulfilmentSuccessRefreshable = 2,
|
||||
|
||||
/*
|
||||
* Policy provably UNfulfilled. The semantics of the policy require
|
||||
* that the exchange MUST transfer amount in the associated deposit to
|
||||
* the payto-URI. */
|
||||
TALER_PolicyFulfilmentFailureTransfer = 3,
|
||||
|
||||
/*
|
||||
* Policy provably UNfulfilled. The semantics of the policy require that
|
||||
* the coins' value in the associated deposit remains and the owner can
|
||||
* refresh them. */
|
||||
TALER_PolicyFulfilmentFailureRefreshable = 4,
|
||||
|
||||
/*
|
||||
* Policy timed out. The semantics of the policy require that the
|
||||
* exchange MUST transfer amount in the associated deposit to the
|
||||
* payto-URI. */
|
||||
TALER_PolicyFulfilmentTimeoutTransfer = 5,
|
||||
|
||||
/*
|
||||
* Policy timed out. The semantics of the policy require that the
|
||||
* coins' value in the associated deposit remains and the owner can
|
||||
* refresh them. */
|
||||
TALER_PolicyFulfilmentTimeoutRefreshable = 6,
|
||||
|
||||
TALER_PolicyFulfilmentStateMax = TALER_PolicyFulfilmentTimeoutRefreshable
|
||||
};
|
||||
|
||||
|
||||
const char *
|
||||
TALER_policy_fulfilment_state_str (enum TALER_PolicyFulfilmentState state);
|
||||
|
||||
/*
|
||||
* @brief Respresents the outcome of a policy fulfilment evaluation
|
||||
* returned by a http_post_handler.
|
||||
*/
|
||||
struct TALER_PolicyFulfilmentOutcome
|
||||
{
|
||||
size_t len;
|
||||
struct TALER_PolicyFulfilmentOutcomePosition
|
||||
{
|
||||
/* Identifies the particular policy in the policy_details */
|
||||
struct GNUNET_HashCode serial_id;
|
||||
|
||||
/* The state that the policy should be be put into. */
|
||||
enum TALER_PolicyFulfilmentState state;
|
||||
|
||||
/* If @e has_new_amount is true, the actual amount to be transfered
|
||||
* according to the @e state is not taken from the associated deposit
|
||||
* entry, but provided with @new_amount
|
||||
*/
|
||||
bool has_new_amount;
|
||||
struct TALER_Amount new_amount;
|
||||
|
||||
} *positions;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* @brief allocate a TALER_PolicyFulfilmentOutcome
|
||||
*/
|
||||
struct TALER_PolicyFulfilmentOutcome *
|
||||
TALER_policy_fulfilment_outcome_new (size_t len);
|
||||
|
||||
/*
|
||||
* @brief free the content of a TALER_PolicyFulfilmentOutcome
|
||||
*/
|
||||
void
|
||||
TALER_policy_fulfilment_outcome_free (
|
||||
struct TALER_PolicyFulfilmentOutcome *outcome);
|
||||
|
||||
|
||||
/*
|
||||
* @brief Extracts meta information from policy_details
|
||||
*
|
||||
* @param[in] policy_details JSON of the policy detail from a deposit request
|
||||
* @param[out] serial On GNUNET_OK, the hash code that should be used to save the policy_details in the policy_details table
|
||||
* @param[out] deadline On GNUNET_OK, the deadline that should be saved in the policy_details table
|
||||
* @param[out] state_on_timeout On GNUNET_OK, which state shall the fulfilment of this policy be put in
|
||||
* @param[out] error_hint On GNUNET_SYSERR, will contain a hint for the reason why it failed
|
||||
* @return GNUNET_OK on success, with *extension set to the correct extension.
|
||||
* GNUNET_NO, when no extension was found. GNUNET_SYSERR when the JSON was
|
||||
* invalid, with *error_hint maybe non-NULL.
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_extensions_serial_from_policy_details (
|
||||
TALER_extensions_extract_meta_data_from_policy_details (
|
||||
const json_t *policy_details,
|
||||
struct GNUNET_HashCode *serial,
|
||||
struct GNUNET_TIME_Timestamp *deadline,
|
||||
enum TALER_PolicyFulfilmentState *state_on_timeout,
|
||||
const char **error_hint);
|
||||
|
||||
|
||||
/*
|
||||
* ================================
|
||||
* Merchant refund policy
|
||||
|
Loading…
Reference in New Issue
Block a user