[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-anastasis] branch master updated: -API break: allow clients to sp
From: |
gnunet |
Subject: |
[taler-anastasis] branch master updated: -API break: allow clients to specify number of years of service to pay for, including reducer update. Will break stuff, partial patch for #6841 |
Date: |
Sun, 11 Jul 2021 12:16:06 +0200 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository anastasis.
The following commit(s) were added to refs/heads/master by this push:
new 6ae716e -API break: allow clients to specify number of years of
service to pay for, including reducer update. Will break stuff, partial patch
for #6841
6ae716e is described below
commit 6ae716e2661284378af8708c364ff8b957f7d975
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Jul 11 12:16:03 2021 +0200
-API break: allow clients to specify number of years of service to pay for,
including reducer update. Will break stuff, partial patch for #6841
---
src/backend/anastasis-httpd_policy.c | 2 +
src/backend/anastasis-httpd_policy_upload.c | 105 ++++-
src/backend/anastasis-httpd_truth_upload.c | 170 +++++--
src/include/anastasis.h | 38 +-
src/include/anastasis_database_plugin.h | 2 +
src/include/anastasis_service.h | 13 +-
src/lib/anastasis_backup.c | 49 +-
src/reducer/anastasis_api_backup_redux.c | 692 +++++++++++++++++++++++-----
src/restclient/anastasis_api_policy_store.c | 18 +-
src/restclient/anastasis_api_truth_store.c | 11 +-
src/stasis/plugin_anastasis_postgres.c | 14 +
11 files changed, 860 insertions(+), 254 deletions(-)
diff --git a/src/backend/anastasis-httpd_policy.c
b/src/backend/anastasis-httpd_policy.c
index 588ce6a..2417e15 100644
--- a/src/backend/anastasis-httpd_policy.c
+++ b/src/backend/anastasis-httpd_policy.c
@@ -170,9 +170,11 @@ AH_policy_get (struct MHD_Connection *connection,
enum ANASTASIS_DB_AccountStatus as;
MHD_RESULT ret;
uint32_t version;
+ struct GNUNET_TIME_Absolute expiration;
as = db->lookup_account (db->cls,
account_pub,
+ &expiration,
&recovery_data_hash,
&version);
switch (as)
diff --git a/src/backend/anastasis-httpd_policy_upload.c
b/src/backend/anastasis-httpd_policy_upload.c
index b15edab..9104b3b 100644
--- a/src/backend/anastasis-httpd_policy_upload.c
+++ b/src/backend/anastasis-httpd_policy_upload.c
@@ -121,6 +121,18 @@ struct PolicyUploadContext
*/
struct GNUNET_TIME_Absolute timeout;
+ /**
+ * How long must the account be valid? Determines whether we should
+ * trigger payment, and if so how much.
+ */
+ struct GNUNET_TIME_Absolute end_date;
+
+ /**
+ * How long is the account already valid?
+ * Determines how much the user needs to pay.
+ */
+ struct GNUNET_TIME_Absolute paid_until;
+
/**
* Expected total upload size.
*/
@@ -404,11 +416,27 @@ check_payment_cb (void *cls,
case TALER_MERCHANT_OSC_PAID:
{
enum GNUNET_DB_QueryStatus qs;
+ unsigned int years;
+ struct GNUNET_TIME_Relative paid_until;
+
+ years = TALER_amount_divide2 (&osr->details.paid.deposit_total,
+ &AH_annual_fee);
+ paid_until = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
+ years);
+ /* add 1 week grace period, otherwise if a user
+ wants to pay for 1 year, the first seconds
+ would have passed between making the payment
+ and our subsequent check if +1 year was
+ paid... So we actually say 1 year = 52 weeks
+ on the server, while the client calculates
+ with 365 days. */
+ paid_until = GNUNET_TIME_relative_add (paid_until,
+ GNUNET_TIME_UNIT_WEEKS);
qs = db->increment_lifetime (db->cls,
&puc->account,
&puc->payment_identifier,
- GNUNET_TIME_UNIT_YEARS);
+ paid_until);
if (0 <= qs)
return; /* continue as planned */
GNUNET_break (0);
@@ -503,20 +531,44 @@ begin_payment (struct PolicyUploadContext *puc)
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Suspending connection while creating order at `%s'\n",
AH_backend_url);
- MHD_suspend_connection (puc->con);
-
{
char *order_id;
+ struct GNUNET_TIME_Absolute now;
+ unsigned int years_to_pay;
+ struct TALER_Amount upload_fee;
+
+ now = GNUNET_TIME_absolute_get ();
+ if (puc->paid_until.abs_value_us < now.abs_value_us)
+ puc->paid_until = now;
+ years_to_pay = (puc->end_date.abs_value_us
+ - puc->paid_until.abs_value_us)
+ / GNUNET_TIME_UNIT_YEARS.rel_value_us;
+ if (0 >
+ TALER_amount_multiply (&upload_fee,
+ &AH_annual_fee,
+ years_to_pay))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (puc->con,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "storage_duration_years");
+ }
order_id = GNUNET_STRINGS_data_to_string_alloc (
&puc->payment_identifier,
sizeof(struct ANASTASIS_PaymentSecretP));
- order = json_pack ("{s:o, s:s, s:s }",
- "amount", TALER_JSON_from_amount (&AH_annual_fee),
- "summary", "annual fee for anastasis service",
+ order = json_pack ("{s:o, s:s, s:[{s:s,s:I,s:s}], s:s }",
+ "amount", TALER_JSON_from_amount (&upload_fee),
+ "summary", "Anastasis policy storage fee",
+ "products",
+ "description", "policy storage fee",
+ "quantity", (json_int_t) years_to_pay,
+ "unit", "years",
"order_id", order_id);
GNUNET_free (order_id);
}
+ MHD_suspend_connection (puc->con);
puc->po = TALER_MERCHANT_orders_post2 (AH_ctx,
AH_backend_url,
order,
@@ -817,13 +869,35 @@ AH_handler_policy_post (
/* check if the client insists on paying */
{
- const char *order_req;
+ const char *req;
+ unsigned int years;
- order_req = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "pay");
- if (NULL != order_req)
- return begin_payment (puc);
+ req = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "storage_duration");
+ if (NULL != req)
+ {
+ char dummy;
+
+ if (1 != sscanf (req,
+ "%u%c",
+ &years,
+ &dummy))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+
TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "storage_duration (must be
non-negative number)");
+ }
+ }
+ else
+ {
+ years = 0;
+ }
+ puc->end_date = GNUNET_TIME_relative_to_absolute (
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
+ years));
}
/* Check if existing policy matches upload (and if, skip it) */
@@ -834,8 +908,15 @@ AH_handler_policy_post (
as = db->lookup_account (db->cls,
account_pub,
+ &puc->paid_until,
&hc,
&version);
+ if ( (ANASTASIS_DB_ACCOUNT_STATUS_VALID_HASH_RETURNED == as) &&
+ (puc->paid_until.abs_value_us < puc->end_date.abs_value_us) )
+ {
+ /* user requested extension, force payment */
+ as = ANASTASIS_DB_ACCOUNT_STATUS_PAYMENT_REQUIRED;
+ }
switch (as)
{
case ANASTASIS_DB_ACCOUNT_STATUS_PAYMENT_REQUIRED:
diff --git a/src/backend/anastasis-httpd_truth_upload.c
b/src/backend/anastasis-httpd_truth_upload.c
index 852ddc9..6038bd5 100644
--- a/src/backend/anastasis-httpd_truth_upload.c
+++ b/src/backend/anastasis-httpd_truth_upload.c
@@ -31,6 +31,10 @@
#include <taler/taler_signatures.h>
#include "anastasis_authorization_lib.h"
+/**
+ * For how many years do we allow users to store truth at most?
+ */
+#define MAX_YEARS_STORAGE 5
/**
* Information we track per truth upload.
@@ -83,11 +87,21 @@ struct TruthUploadContext
*/
struct GNUNET_TIME_Absolute timeout;
+ /**
+ * Fee that is to be paid for this upload.
+ */
+ struct TALER_Amount upload_fee;
+
/**
* HTTP response code to use on resume, if resp is set.
*/
unsigned int response_code;
+ /**
+ * For how many years must the customer still pay?
+ */
+ unsigned int years_to_pay;
+
};
@@ -300,16 +314,33 @@ check_payment_cb (void *cls,
case TALER_MERCHANT_OSC_PAID:
{
enum GNUNET_DB_QueryStatus qs;
-
- qs = db->record_truth_upload_payment (db->cls,
- &tuc->truth_uuid,
- &AH_truth_upload_fee,
- GNUNET_TIME_UNIT_YEARS);
+ unsigned int years;
+ struct GNUNET_TIME_Relative paid_until;
+
+ years = TALER_amount_divide2 (&osr->details.paid.deposit_total,
+ &AH_truth_upload_fee);
+ paid_until = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
+ years);
+ /* add 1 week grace period, otherwise if a user
+ wants to pay for 1 year, the first seconds
+ would have passed between making the payment
+ and our subsequent check if +1 year was
+ paid... So we actually say 1 year = 52 weeks
+ on the server, while the client calculates
+ with 365 days. */
+ paid_until = GNUNET_TIME_relative_add (paid_until,
+ GNUNET_TIME_UNIT_WEEKS);
+ qs = db->record_truth_upload_payment (
+ db->cls,
+ &tuc->truth_uuid,
+ &osr->details.paid.deposit_total,
+ paid_until);
if (qs <= 0)
{
tuc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
- tuc->resp = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED,
- "record_truth_upload_payment");
+ tuc->resp = TALER_MHD_make_error (
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "record_truth_upload_payment");
break;
}
}
@@ -353,11 +384,16 @@ check_payment_cb (void *cls,
"%u, setting up fresh order %s\n",
MHD_HTTP_NOT_FOUND,
order_id);
- order = json_pack ("{s:o, s:s, s:s}",
+ order = json_pack ("{s:o, s:s, s:[{s:s,s:I,s:s}], s:s}",
"amount",
- TALER_JSON_from_amount (&AH_truth_upload_fee),
+ TALER_JSON_from_amount (&tuc->upload_fee),
"summary",
"Anastasis challenge storage fee",
+ "products",
+ "description", "challenge storage fee",
+ "quantity", (json_int_t) tuc->years_to_pay,
+ "unit", "years",
+
"order_id",
order_id);
GNUNET_free (order_id);
@@ -465,6 +501,7 @@ AH_handler_truth_post (
const char *truth_mime;
const char *type;
enum GNUNET_DB_QueryStatus qs;
+ uint32_t storage_years;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("keyshare_data",
&keyshare_data),
@@ -475,6 +512,8 @@ AH_handler_truth_post (
&encrypted_truth_size),
GNUNET_JSON_spec_string ("truth_mime",
&truth_mime),
+ GNUNET_JSON_spec_uint32 ("storage_duration_years",
+ &storage_years),
GNUNET_JSON_spec_end ()
};
@@ -553,44 +592,6 @@ AH_handler_truth_post (
}
}
- {
- struct TALER_Amount zero_amount;
-
- TALER_amount_get_zero (AH_currency,
- &zero_amount);
- if (0 != TALER_amount_cmp (&AH_truth_upload_fee,
- &zero_amount))
- {
- struct GNUNET_TIME_Absolute paid_until;
- enum GNUNET_DB_QueryStatus qs;
-
- qs = db->check_truth_upload_paid (db->cls,
- truth_uuid,
- &paid_until);
- if (qs < 0)
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL);
- if ( (0 == qs) ||
- (0 ==
- GNUNET_TIME_absolute_get_remaining (paid_until).rel_value_us) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Truth upload payment required (%d)!\n",
- qs);
- return begin_payment (tuc);
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "TRUTH paid until %s (%d)!\n",
- GNUNET_STRINGS_relative_time_to_string (
- GNUNET_TIME_absolute_get_remaining (
- paid_until),
- GNUNET_YES),
- qs);
- }
- }
-
} /* end 'if (NULL == tuc)' */
if (NULL != tuc->resp)
@@ -651,6 +652,81 @@ AH_handler_truth_post (
}
}
+ if (storage_years > MAX_YEARS_STORAGE)
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "storage_duration_years");
+ }
+
+ {
+ struct TALER_Amount zero_amount;
+
+ TALER_amount_get_zero (AH_currency,
+ &zero_amount);
+ if (0 != TALER_amount_cmp (&AH_truth_upload_fee,
+ &zero_amount))
+ {
+ struct GNUNET_TIME_Absolute paid_until;
+ struct GNUNET_TIME_Absolute desired_until;
+ enum GNUNET_DB_QueryStatus qs;
+
+ desired_until
+ = GNUNET_TIME_relative_to_absolute (
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
+ storage_years));
+ qs = db->check_truth_upload_paid (db->cls,
+ truth_uuid,
+ &paid_until);
+ if (qs < 0)
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
+ if ( (0 == qs) ||
+ (paid_until.abs_value_us < desired_until.abs_value_us) )
+ {
+ struct GNUNET_TIME_Absolute now;
+
+ now = GNUNET_TIME_absolute_get ();
+ if (paid_until.abs_value_us < now.abs_value_us)
+ paid_until = now;
+ tuc->years_to_pay = (desired_until.abs_value_us
+ - paid_until.abs_value_us)
+ / GNUNET_TIME_UNIT_YEARS.rel_value_us;
+ if (0 >
+ TALER_amount_multiply (&tuc->upload_fee,
+ &AH_truth_upload_fee,
+ tuc->years_to_pay))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+
TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "storage_duration_years");
+ }
+ if ( (0 != tuc->upload_fee.fraction) ||
+ (0 != tuc->upload_fee.value) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Truth upload payment required (%d)!\n",
+ qs);
+ return begin_payment (tuc);
+ }
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "TRUTH paid until %s (%d)!\n",
+ GNUNET_STRINGS_relative_time_to_string (
+ GNUNET_TIME_absolute_get_remaining (
+ paid_until),
+ GNUNET_YES),
+ qs);
+ }
+ }
+
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Storing truth!\n");
qs = db->store_truth (db->cls,
diff --git a/src/include/anastasis.h b/src/include/anastasis.h
index 1e8c1af..705dd07 100644
--- a/src/include/anastasis.h
+++ b/src/include/anastasis.h
@@ -613,11 +613,11 @@ typedef void
* @param mime_type format of the challenge
* @param provider_salt the providers salt
* @param truth_data contains the truth for this challenge i.e. phone number,
email address
- * @param truth_data_size size of the data
- * @param payment_requested true if the client wants to pay more for the
account now
+ * @param truth_data_size size of the @a truth_data
+ * @param payment_years_requested for how many years would the client like the
service to store the truth?
* @param pay_timeout how long to wait for payment
* @param tc opens the truth callback which contains the status of the upload
- * @param tc_cls closure for the callback
+ * @param tc_cls closure for the @a tc callback
*/
struct ANASTASIS_TruthUpload *
ANASTASIS_truth_upload (
@@ -630,7 +630,7 @@ ANASTASIS_truth_upload (
const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt,
const void *truth_data,
size_t truth_data_size,
- bool payment_requested,
+ uint32_t payment_years_requested,
struct GNUNET_TIME_Relative pay_timeout,
ANASTASIS_TruthCallback tc,
void *tc_cls);
@@ -648,8 +648,8 @@ ANASTASIS_truth_upload (
* @param mime_type format of the challenge
* @param provider_salt the providers salt
* @param truth_data contains the truth for this challenge i.e. phone number,
email address
- * @param truth_data_size size of the data
- * @param payment_requested true if the client wants to pay more for the
account now
+ * @param truth_data_size size of the @a truth_data
+ * @param payment_years_requested for how many years would the client like the
service to store the truth?
* @param pay_timeout how long to wait for payment
* @param nonce nonce to use for symmetric encryption
* @param uuid truth UUID to use
@@ -657,7 +657,7 @@ ANASTASIS_truth_upload (
* @param truth_key symmetric encryption key to use to encrypt @a truth_data
* @param key_share share of the overall key to store in this truth object
* @param tc opens the truth callback which contains the status of the upload
- * @param tc_cls closure for the callback
+ * @param tc_cls closure for the @a tc callback
*/
struct ANASTASIS_TruthUpload *
ANASTASIS_truth_upload2 (
@@ -670,7 +670,7 @@ ANASTASIS_truth_upload2 (
const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt,
const void *truth_data,
size_t truth_data_size,
- bool payment_requested,
+ uint32_t payment_years_requested,
struct GNUNET_TIME_Relative pay_timeout,
const struct ANASTASIS_CRYPTO_NonceP *nonce,
const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid,
@@ -690,11 +690,11 @@ ANASTASIS_truth_upload2 (
* @param user_id user identifier derived from user data and backend salt
* @param[in] t truth details, reference is consumed
* @param truth_data contains the truth for this challenge i.e. phone number,
email address
- * @param truth_data_size size of the data
- * @param payment_requested true if the client wants to pay more for the
account now
+ * @param truth_data_size size of the @a truth_data
+ * @param payment_years_requested for how many years would the client like the
service to store the truth?
* @param pay_timeout how long to wait for payment
* @param tc opens the truth callback which contains the status of the upload
- * @param tc_cls closure for the callback
+ * @param tc_cls closure for the @a tc callback
*/
struct ANASTASIS_TruthUpload *
ANASTASIS_truth_upload3 (struct GNUNET_CURL_Context *ctx,
@@ -702,7 +702,7 @@ ANASTASIS_truth_upload3 (struct GNUNET_CURL_Context *ctx,
struct ANASTASIS_Truth *t,
const void *truth_data,
size_t truth_data_size,
- bool payment_requested,
+ uint32_t payment_years_requested,
struct GNUNET_TIME_Relative pay_timeout,
ANASTASIS_TruthCallback tc,
void *tc_cls);
@@ -923,16 +923,16 @@ struct ANASTASIS_ProviderDetails
* @param providers array of providers with URLs to upload the policies to
* @param pss_length length of the @a providers array
* @param policies list of policies which are included in this recovery
document
- * @param policies_length amount of policies in the document
- * @param payment_requested the client insists on paying for the policy store,
even if not
- * yet needed
+ * @param policies_length length of the @a policies array
+ * @param payment_years_requested for how many years would the client like the
service to store the truth?
* @param pay_timeout how long to wait for payment
* @param spc payment callback is opened to pay the upload
- * @param spc_cls closure for the payment callback
+ * @param spc_cls closure for the @a spc payment callback
* @param src callback for the upload process
- * @param src_cls closure for the upload callback
+ * @param src_cls closure for the @a src upload callback
* @param core_secret input of the user which is secured by anastasis e.g.
(wallet private key)
- * @param core_secret_size size of the core secret
+ * @param core_secret_size size of the @a core_secret
+ * @return NULL on error
*/
struct ANASTASIS_SecretShare *
ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
@@ -941,7 +941,7 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
unsigned int pss_length,
const struct ANASTASIS_Policy *policies[],
unsigned int policies_len,
- bool payment_requested,
+ uint32_t payment_years_requested,
struct GNUNET_TIME_Relative pay_timeout,
ANASTASIS_ShareResultCallback src,
void *src_cls,
diff --git a/src/include/anastasis_database_plugin.h
b/src/include/anastasis_database_plugin.h
index 8bd702e..b7ae2dc 100644
--- a/src/include/anastasis_database_plugin.h
+++ b/src/include/anastasis_database_plugin.h
@@ -380,6 +380,7 @@ struct ANASTASIS_DatabasePlugin
*
* @param cls closure
* @param anastasis_pub account identifier
+ * @param[out] paid_until until when is the account paid up?
* @param[out] recovery_data_hash set to hash of @a recovery document
* @param[out] version set to the recovery policy version
* @return transaction status
@@ -388,6 +389,7 @@ struct ANASTASIS_DatabasePlugin
(*lookup_account)(
void *cls,
const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
+ struct GNUNET_TIME_Absolute *paid_until,
struct GNUNET_HashCode *recovery_data_hash,
uint32_t *version);
diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h
index 0af787f..1a61e54 100644
--- a/src/include/anastasis_service.h
+++ b/src/include/anastasis_service.h
@@ -387,7 +387,7 @@ typedef void
* @param anastasis_priv private key of the user's account
* @param recovery_data policy data to be stored
* @param recovery_data_size number of bytes in @a recovery_data
- * @param payment_requested true if the client wants to pay more for the
account now
+ * @param payment_years_requested for how many years would the client like the
service to store the truth?
* @param paid_order_id payment identifier of last payment
* @param payment_timeout how long to wait for the payment, use
* #GNUNET_TIME_UNIT_ZERO to let the server pick
@@ -402,7 +402,7 @@ ANASTASIS_policy_store (
const struct ANASTASIS_CRYPTO_AccountPrivateKeyP *anastasis_priv,
const void *recovery_data,
size_t recovery_data_size,
- bool payment_requested,
+ uint32_t payment_years_requested,
const struct ANASTASIS_PaymentSecretP *payment_secret,
struct GNUNET_TIME_Relative payment_timeout,
ANASTASIS_PolicyStoreCallback cb,
@@ -667,7 +667,7 @@ typedef void
* @param truth_mime mime type of @e encrypted_truth (after decryption)
* @param encrypted_truth_size number of bytes in @e encrypted_truth
* @param encrypted_truth contains the @a type-specific authorization data
- * @param payment_requested true if we want to pay, even if not yet required
+ * @param payment_years_requested for how many years would the client like the
service to store the truth?
* @param payment_timeout how long to wait for the payment, use
* #GNUNET_TIME_UNIT_ZERO to let the server pick
* @param cb callback processing the response from /truth
@@ -684,7 +684,7 @@ ANASTASIS_truth_store (
const char *truth_mime,
size_t encrypted_truth_size,
const void *encrypted_truth,
- bool payment_requested,
+ uint32_t payment_years_requested,
struct GNUNET_TIME_Relative payment_timeout,
ANASTASIS_TruthStoreCallback cb,
void *cb_cls);
@@ -704,8 +704,9 @@ ANASTASIS_truth_store_cancel (
// FIXME: BAD API & MISSING IMPLEMENTATION:
/**
- * Defines a Callback for a Escrow Provider Inspection, simply passes back the
terms
- * of the provider (price, supported methods .... )
+ * Defines a Callback for a Escrow Provider Inspection, simply passes
+ * back the configuration of the provider (price, supported methods
+ * .... )
*
* @param cls closure for the callback
* @param policy 0 terminated string which contains the terms of service
diff --git a/src/lib/anastasis_backup.c b/src/lib/anastasis_backup.c
index 2e00a2b..c3eaed9 100644
--- a/src/lib/anastasis_backup.c
+++ b/src/lib/anastasis_backup.c
@@ -80,14 +80,6 @@ struct ANASTASIS_Truth
};
-/**
- * Extracts truth data from JSON.
- *
- * @param json JSON encoding to decode; truth returned ONLY valid as long
- * as the JSON remains valid (do not decref until the truth
- * is truly finished)
- * @return decoded truth object, NULL on error
- */
struct ANASTASIS_Truth *
ANASTASIS_truth_from_json (const json_t *json)
{
@@ -139,15 +131,6 @@ ANASTASIS_truth_from_json (const json_t *json)
}
-/**
- * Returns JSON-encoded truth data.
- * Creates a policy with a set of truth's. Creates the policy key
- * with the different key shares from the @a truths. The policy key
- * will then be used to encrypt/decrypt the escrow master key.
- *
- * @param t object to return JSON encoding for
- * @return JSON encoding of @a t
- */
json_t *
ANASTASIS_truth_to_json (const struct ANASTASIS_Truth *t)
{
@@ -234,29 +217,13 @@ truth_store_callback (void *cls,
}
-/**
- * Retries upload of truth data to an escrow provider using an
- * existing truth object. If payment is required, it is requested via
- * the @a tc callback.
- *
- * @param ctx the CURL context used to connect to the backend
- * @param user_id user identifier derived from user data and backend salt
- * @param[in] t truth details, reference is consumed
- * @param truth_data contains the truth for this challenge i.e. phone number,
email address
- * @param truth_data_size size of the data
- * @param payment_requested true if the client wants to pay more for the
account now
- * @param paid_order_id payment identifier of last payment
- * @param pay_timeout how long to wait for payment
- * @param tc opens the truth callback which contains the status of the upload
- * @param tc_cls closure for the callback
- */
struct ANASTASIS_TruthUpload *
ANASTASIS_truth_upload3 (struct GNUNET_CURL_Context *ctx,
const struct ANASTASIS_CRYPTO_UserIdentifierP
*user_id,
struct ANASTASIS_Truth *t,
const void *truth_data,
size_t truth_data_size,
- bool payment_requested,
+ uint32_t payment_years_requested,
struct GNUNET_TIME_Relative pay_timeout,
ANASTASIS_TruthCallback tc,
void *tc_cls)
@@ -316,7 +283,7 @@ ANASTASIS_truth_upload3 (struct GNUNET_CURL_Context *ctx,
t->mime_type,
encrypted_truth_size,
encrypted_truth,
- payment_requested,
+ payment_years_requested,
pay_timeout,
&truth_store_callback,
tu);
@@ -343,7 +310,7 @@ ANASTASIS_truth_upload2 (
const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt,
const void *truth_data,
size_t truth_data_size,
- bool payment_requested,
+ uint32_t payment_years_requested,
struct GNUNET_TIME_Relative pay_timeout,
const struct ANASTASIS_CRYPTO_NonceP *nonce,
const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid,
@@ -375,7 +342,7 @@ ANASTASIS_truth_upload2 (
t,
truth_data,
truth_data_size,
- payment_requested,
+ payment_years_requested,
pay_timeout,
tc,
tc_cls);
@@ -393,7 +360,7 @@ ANASTASIS_truth_upload (
const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt,
const void *truth_data,
size_t truth_data_size,
- bool payment_requested,
+ uint32_t payment_years_requested,
struct GNUNET_TIME_Relative pay_timeout,
ANASTASIS_TruthCallback tc,
void *tc_cls)
@@ -426,7 +393,7 @@ ANASTASIS_truth_upload (
provider_salt,
truth_data,
truth_data_size,
- payment_requested,
+ payment_years_requested,
pay_timeout,
&nonce,
&uuid,
@@ -750,7 +717,7 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
unsigned int pss_length,
const struct ANASTASIS_Policy *policies[],
unsigned int policies_len,
- bool payment_requested,
+ uint32_t payment_years_requested,
struct GNUNET_TIME_Relative pay_timeout,
ANASTASIS_ShareResultCallback src,
void *src_cls,
@@ -964,7 +931,7 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
&anastasis_priv,
recovery_data,
recovery_data_size,
- payment_requested,
+ payment_years_requested,
(! GNUNET_is_zero (&pss->payment_secret))
? &pss->payment_secret
: NULL,
diff --git a/src/reducer/anastasis_api_backup_redux.c
b/src/reducer/anastasis_api_backup_redux.c
index 60430d7..b6f5176 100644
--- a/src/reducer/anastasis_api_backup_redux.c
+++ b/src/reducer/anastasis_api_backup_redux.c
@@ -41,6 +41,59 @@ static const char *backup_strings[] = {
#undef GENERATE_STRING
+/**
+ * Linked list of costs.
+ */
+struct Costs
+{
+
+ /**
+ * Kept in a LL.
+ */
+ struct Costs *next;
+
+ /**
+ * Cost in one of the currencies.
+ */
+ struct TALER_Amount cost;
+};
+
+
+/**
+ * Add amount from @a cost to @a my_cost list.
+ *
+ * @param[in,out] my_cost pointer to list to modify
+ * @param cost amount to add
+ */
+static void
+add_cost (struct Costs **my_cost,
+ const struct TALER_Amount *cost)
+{
+ for (struct Costs *pos = *my_cost;
+ NULL != pos;
+ pos = pos->next)
+ {
+ if (GNUNET_OK !=
+ TALER_amount_cmp_currency (&pos->cost,
+ cost))
+ continue;
+ GNUNET_assert (0 <=
+ TALER_amount_add (&pos->cost,
+ &pos->cost,
+ cost));
+ return;
+ }
+ {
+ struct Costs *nc;
+
+ nc = GNUNET_new (struct Costs);
+ nc->cost = *cost;
+ nc->next = *my_cost;
+ *my_cost = nc;
+ }
+}
+
+
enum ANASTASIS_BackupState
ANASTASIS_backup_state_from_string_ (const char *state_string)
{
@@ -380,24 +433,6 @@ del_authentication (json_t *state,
/* ********************** done_authentication ******************** */
-/**
- * Linked list of costs to associate with a policy.
- */
-struct Costs
-{
-
- /**
- * Kept in a LL.
- */
- struct Costs *next;
-
- /**
- * Cost in one of the currencies.
- */
- struct TALER_Amount cost;
-};
-
-
/**
* Which provider would be used for the given challenge,
* and at what cost?
@@ -1113,41 +1148,6 @@ lookup_salt (const json_t *state,
}
-/**
- * Add costs from @a pe to @a my_cost list.
- *
- * @param[in,out] my_cost pointer to list to modify
- * @param pe cost entry to add
- */
-static void
-add_cost (struct Costs **my_cost,
- const struct PolicyEntry *pe)
-{
- for (struct Costs *pos = *my_cost;
- NULL != pos;
- pos = pos->next)
- {
- if (GNUNET_OK !=
- TALER_amount_cmp_currency (&pos->cost,
- &pe->usage_fee))
- continue;
- GNUNET_assert (0 <=
- TALER_amount_add (&pos->cost,
- &pos->cost,
- &pe->usage_fee));
- return;
- }
- {
- struct Costs *nc;
-
- nc = GNUNET_new (struct Costs);
- nc->cost = pe->usage_fee;
- nc->next = *my_cost;
- *my_cost = nc;
- }
-}
-
-
/**
* Compare two cost lists.
*
@@ -1296,7 +1296,7 @@ evaluate_map (struct PolicyBuilder *pb,
if (found)
continue; /* cost already included, do not add */
add_cost (&my_cost,
- pe);
+ &pe->usage_fee);
}
}
@@ -2234,6 +2234,233 @@ del_challenge (json_t *state,
/* ********************** done_policy_review ***************** */
+/**
+ * Calculate how many years of service we need
+ * from the desired @a expiration time,
+ * rounding up.
+ *
+ * @param expiration desired expiration time
+ * @return number of years of service to pay for
+*/
+static unsigned int
+expiration_to_years (struct GNUNET_TIME_Absolute expiration)
+{
+ struct GNUNET_TIME_Relative rem;
+ unsigned int years;
+
+ rem = GNUNET_TIME_absolute_get_remaining (expiration);
+ years = rem.rel_value_us / GNUNET_TIME_UNIT_YEARS.rel_value_us;
+ if (0 != rem.rel_value_us / GNUNET_TIME_UNIT_YEARS.rel_value_us)
+ years++;
+ return years;
+}
+
+
+/**
+ * Update @a state such that the earliest expiration for
+ * any truth or policy is @a expiration. Recalculate
+ * the ``upload_fees`` array with the associated costs.
+ *
+ * @param[in,out] state our state to update
+ * @param expiration new expiration to enforce
+ * @return #GNUNET_OK on success,
+ * #GNUNET_SYSERR if the state is invalid
+ */
+static enum GNUNET_GenericReturnValue
+update_expiration_cost (json_t *state,
+ struct GNUNET_TIME_Absolute expiration)
+{
+ struct Costs *costs = NULL;
+ unsigned int years;
+ json_t *providers;
+
+ providers = json_object_get (state,
+ "policy_providers");
+ if (0 == json_array_size (providers))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ years = expiration_to_years (expiration);
+
+ /* go over all providers and add up cost */
+ {
+ const char *url;
+ json_t *provider;
+
+ json_object_foreach (providers, url, provider)
+ {
+ struct TALER_Amount annual_fee;
+ struct GNUNET_JSON_Specification pspec[] = {
+ TALER_JSON_spec_amount ("annual_fee",
+ &annual_fee),
+ GNUNET_JSON_spec_end ()
+ };
+ struct TALER_Amount fee;
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (provider,
+ pspec,
+ NULL, NULL))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (0 >
+ TALER_amount_multiply (&fee,
+ &annual_fee,
+ years))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ add_cost (&costs,
+ &fee);
+ }
+ }
+
+ /* go over all truths and add up cost */
+ {
+ unsigned int off = 0;
+ unsigned int len = 0;
+ struct AlreadySeen
+ {
+ uint32_t method;
+ const char *provider_url;
+ } *seen;
+ json_t *policies;
+ size_t pidx;
+ json_t *policy;
+
+ policies = json_object_get (state,
+ "policies");
+ json_array_foreach (policies, pidx, policy)
+ {
+ json_t *methods;
+ json_t *method;
+ size_t midx;
+
+ methods = json_object_get (policy,
+ "methods");
+ json_array_foreach (methods, midx, method)
+ {
+ const char *provider_url;
+ uint32_t method_idx;
+
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("provider",
+ &provider_url),
+ GNUNET_JSON_spec_uint32 ("authentication_method",
+ &method_idx),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (method,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ /* check if we have seen this one before */
+ {
+ bool found = false;
+
+ for (unsigned int i = 0; i<off; i++)
+ if ( (seen[i].method == method_idx) &&
+ (0 == strcmp (seen[i].provider_url,
+ provider_url)) )
+ found = true;
+ if (found)
+ continue; /* skip */
+ }
+ if (off == len)
+ {
+ GNUNET_array_grow (seen,
+ len,
+ 4 + len * 2);
+ }
+ seen[off].method = method_idx;
+ seen[off].provider_url = provider_url;
+ off++;
+ {
+ struct TALER_Amount upload_cost;
+ struct GNUNET_JSON_Specification pspec[] = {
+ TALER_JSON_spec_amount ("truth_upload_fee",
+ &upload_cost),
+ GNUNET_JSON_spec_end ()
+ };
+ struct TALER_Amount fee;
+ const json_t *provider_cfg
+ = json_object_get (providers,
+ provider_url);
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (provider_cfg,
+ pspec,
+ NULL, NULL))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (0 >
+ TALER_amount_multiply (&fee,
+ &upload_cost,
+ years))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ add_cost (&costs,
+ &fee);
+ }
+ }
+ }
+ GNUNET_array_grow (seen,
+ len,
+ 0);
+ }
+
+ /* update 'expiration' in state */
+ {
+ json_t *eo;
+
+ eo = GNUNET_JSON_from_time_abs (expiration);
+ GNUNET_assert (0 ==
+ json_object_set_new (state,
+ "expiration",
+ eo));
+ }
+
+ /* convert 'costs' into state */
+ {
+ json_t *arr;
+
+ arr = json_array ();
+ GNUNET_assert (NULL != arr);
+ while (NULL != costs)
+ {
+ struct Costs *nxt = costs->next;
+ json_t *ao;
+
+ ao = TALER_JSON_from_amount (&costs->cost);
+ GNUNET_assert (0 ==
+ json_array_append_new (arr,
+ ao));
+ GNUNET_free (costs);
+ costs = nxt;
+ }
+ GNUNET_assert (0 ==
+ json_object_set_new (state,
+ "upload_fees",
+ arr));
+ }
+ return GNUNET_OK;
+}
+
+
/**
* DispatchHandler/Callback function which is called for a
* "done_policy_review" action.
@@ -2262,6 +2489,40 @@ done_policy_review (json_t *state,
"no policies specified");
return NULL;
}
+ {
+ struct GNUNET_TIME_Absolute exp = {0};
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_absolute_time ("expiration",
+ &exp)),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (state,
+ spec,
+ NULL, NULL))
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+
TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE,
+ "invalid expiration specified");
+ return NULL;
+ }
+ if (0 == exp.abs_value_us)
+ exp = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS);
+
+ if (GNUNET_OK !=
+ update_expiration_cost (state,
+ exp))
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+
TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE,
+ "could not calculate expiration cost");
+ return NULL;
+ }
+ }
set_state (state,
ANASTASIS_BACKUP_STATE_SECRET_EDITING);
cb (cb_cls,
@@ -2412,6 +2673,11 @@ struct UploadContext
*/
struct GNUNET_TIME_Relative timeout;
+ /**
+ * For how many years should we pay?
+ */
+ unsigned int years;
+
};
@@ -2666,16 +2932,12 @@ share_secret (struct UploadContext *uc)
void *core_secret;
json_t *jpolicies;
json_t *providers = NULL;
- bool force_payment = false;
- unsigned int policies_len;
+ size_t policies_len;
unsigned int pds_len;
struct GNUNET_TIME_Relative timeout = GNUNET_TIME_UNIT_ZERO;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_json ("identity_attributes",
&user_id),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_bool ("force_pay",
- &force_payment)),
GNUNET_JSON_spec_json ("policies",
&jpolicies),
GNUNET_JSON_spec_json ("policy_providers",
@@ -2768,7 +3030,7 @@ share_secret (struct UploadContext *uc)
memset (pds,
0,
sizeof (pds));
- for (unsigned int i = 0; i<policies_len; i++)
+ for (size_t i = 0; i<policies_len; i++)
{
const json_t *policy = json_array_get (jpolicies,
i);
@@ -2941,7 +3203,7 @@ share_secret (struct UploadContext *uc)
pds_len,
policies,
policies_len,
- force_payment,
+ uc->years,
timeout,
&secret_share_result_cb,
uc,
@@ -3120,7 +3382,6 @@ add_truth_object (struct UploadContext *uc,
}
}
-
if (NULL == tue)
{
/* Create new entry */
@@ -3181,13 +3442,9 @@ add_truth_object (struct UploadContext *uc,
{
struct ANASTASIS_CRYPTO_ProviderSaltP salt;
struct ANASTASIS_CRYPTO_UserIdentifierP id;
- bool force_payment = false;
void *truth_data;
size_t truth_data_size;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_bool ("force_pay",
- &force_payment)),
GNUNET_JSON_spec_varsize ("challenge",
&truth_data,
&truth_data_size),
@@ -3232,7 +3489,7 @@ add_truth_object (struct UploadContext *uc,
tue->t,
truth_data,
truth_data_size,
- force_payment,
+ uc->years,
uc->timeout,
&truth_upload_cb,
tue);
@@ -3323,15 +3580,11 @@ check_truth_upload (struct UploadContext *uc,
const char *type;
const char *mime_type = NULL;
const char *instructions = NULL;
- bool force_payment = false;
void *truth_data;
size_t truth_data_size;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("type",
&type),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_bool ("force_pay",
- &force_payment)),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("mime_type",
&mime_type)),
@@ -3415,7 +3668,7 @@ check_truth_upload (struct UploadContext *uc,
&provider_salt,
truth_data,
truth_data_size,
- force_payment,
+ uc->years,
uc->timeout,
&truth_upload_cb,
tue);
@@ -3431,7 +3684,7 @@ check_truth_upload (struct UploadContext *uc,
&provider_salt,
truth_data,
truth_data_size,
- force_payment,
+ uc->years,
uc->timeout,
&nonce,
&uuid,
@@ -3473,7 +3726,24 @@ upload (json_t *state,
struct UploadContext *uc;
json_t *auth_methods;
json_t *policies;
+ struct GNUNET_TIME_Absolute expiration;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_absolute_time ("expiration",
+ &expiration),
+ GNUNET_JSON_spec_end ()
+ };
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (state,
+ spec,
+ NULL, NULL))
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
+ "'expiration' missing");
+ return NULL;
+ }
auth_methods = json_object_get (state,
"authentication_methods");
if ( (! json_is_array (auth_methods)) ||
@@ -3503,6 +3773,7 @@ upload (json_t *state,
uc->cb = cb;
uc->cb_cls = cb_cls;
uc->state = json_incref (state);
+ uc->years = expiration_to_years (expiration);
{
json_t *args;
@@ -3689,15 +3960,68 @@ core_secret_fits (const json_t *state,
}
+/**
+ * Check if the upload size limit is satisfied.
+ *
+ * @param state our state
+ * @param secret_size size of the uploaded secret
+ * @return #GNUNET_OK if @a secret_size works for all providers,
+ * #GNUNET_NO if the @a secret_size is too big,
+ * #GNUNET_SYSERR if a provider has a limit of 0
+ */
+static enum GNUNET_GenericReturnValue
+check_upload_size_limit (json_t *state,
+ size_t secret_size)
+{
+ uint32_t min_limit = UINT32_MAX;
+ json_t *aps = json_object_get (state,
+ "authentication_providers");
+ const char *url;
+ json_t *ap;
+
+ /* We calculate the minimum upload limit of all possible providers;
+ this is under the (simplified) assumption that we store the
+ recovery document at all providers; this may be changed later,
+ see #6760. */
+ json_object_foreach (aps, url, ap)
+ {
+ uint32_t limit;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_uint32 ("storage_limit_in_megabytes",
+ &limit),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (ap,
+ spec,
+ NULL, NULL))
+ {
+ /* skip malformed provider, likely /config failed */
+ continue;
+ }
+ if (0 == limit)
+ return GNUNET_SYSERR;
+ min_limit = GNUNET_MIN (min_limit,
+ limit);
+ }
+ if (! core_secret_fits (state,
+ secret_size,
+ min_limit))
+ return GNUNET_NO;
+ return GNUNET_OK;
+}
+
+
/**
* DispatchHandler/Callback function which is called for a
* "enter_secret" action.
- * Returns an #ANASTASIS_ReduxAction as operation is async.
*
* @param state state to operate on
* @param arguments arguments to use for operation on state
* @param cb callback to call during/after operation
* @param cb_cls callback closure
+ * @return NULL
*/
static struct ANASTASIS_ReduxAction *
enter_secret (json_t *state,
@@ -3708,9 +4032,17 @@ enter_secret (json_t *state,
json_t *jsecret;
void *secret;
size_t secret_size;
+ const char *secret_name = NULL;
+ struct GNUNET_TIME_Absolute expiration = {0};
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_json ("secret",
&jsecret),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("name",
+ &secret_name)),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_absolute_time ("expiration",
+ &expiration)),
GNUNET_JSON_spec_end ()
};
@@ -3740,65 +4072,179 @@ enter_secret (json_t *state,
/* check upload size limit */
{
- uint32_t min_limit = UINT32_MAX;
- json_t *aps = json_object_get (state,
- "authentication_providers");
- const char *url;
- json_t *ap;
-
- /* We calculate the minimum upload limit of all possible providers;
- this is under the (simplified) assumption that we store the
- recovery document at all providers; this may be changed later,
- see #6760. */
- json_object_foreach (aps, url, ap)
- {
- uint32_t limit;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_uint32 ("storage_limit_in_megabytes",
- &limit),
- GNUNET_JSON_spec_end ()
- };
+ enum GNUNET_GenericReturnValue ret;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (ap,
- spec,
- NULL, NULL))
- {
- /* skip malformed provider, likely /config failed */
- continue;
- }
- if (0 == limit)
- {
- ANASTASIS_redux_fail_ (cb,
- cb_cls,
- TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
- "provider has an upload limit of 0");
- GNUNET_free (secret);
- return NULL;
- }
- min_limit = GNUNET_MIN (min_limit,
- limit);
- }
- if (! core_secret_fits (state,
- secret_size,
- min_limit))
+ ret = check_upload_size_limit (state,
+ secret_size);
+ switch (ret)
{
+ case GNUNET_SYSERR:
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
+ "provider has an upload limit of 0");
+ GNUNET_free (secret);
+ return NULL;
+ case GNUNET_NO:
ANASTASIS_redux_fail_ (cb,
cb_cls,
TALER_EC_ANASTASIS_REDUCER_SECRET_TOO_BIG,
NULL);
GNUNET_free (secret);
return NULL;
+ default:
+ break;
}
}
-
-
+ if (0 != expiration.abs_value_us)
+ {
+ if (GNUNET_OK !=
+ update_expiration_cost (state,
+ expiration))
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+
TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE,
+ "could not calculate expiration cost");
+ return NULL;
+ }
+ }
+ if (NULL != secret_name)
+ GNUNET_assert (0 ==
+ json_object_set_new (state,
+ "secret_name",
+ json_string (secret_name)));
GNUNET_assert (0 ==
json_object_set_new (state,
"core_secret",
GNUNET_JSON_from_data (secret,
secret_size)));
- GNUNET_free (secret);
+ GNUNET_JSON_parse_free (spec);
+ return NULL;
+}
+
+
+/**
+ * DispatchHandler/Callback function which is called for the
+ * "update_expiration" action in the "secret editing" state.
+ * Updates how long we are to store the truth and policies
+ * and computes the new cost.
+ *
+ * @param state state to operate on
+ * @param arguments arguments to use for operation on state
+ * @param cb callback to call during/after operation
+ * @param cb_cls callback closure
+ * @return NULL (synchronous operation)
+ */
+static struct ANASTASIS_ReduxAction *
+update_expiration (json_t *state,
+ const json_t *arguments,
+ ANASTASIS_ActionCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_TIME_Absolute expiration;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_absolute_time ("expiration",
+ &expiration),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (NULL == arguments)
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
+ "arguments missing");
+ return NULL;
+ }
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (arguments,
+ spec,
+ NULL, NULL))
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
+ "'expiration' argument required");
+ return NULL;
+ }
+ if (GNUNET_OK !=
+ update_expiration_cost (state,
+ expiration))
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE,
+ "could not calculate expiration cost");
+ return NULL;
+ }
+ return NULL;
+}
+
+
+/**
+ * DispatchHandler/Callback function which is called for the
+ * "next" action in the "secret editing" state.
+ * Returns an #ANASTASIS_ReduxAction as operation is async.
+ *
+ * @param state state to operate on
+ * @param arguments arguments to use for operation on state
+ * @param cb callback to call during/after operation
+ * @param cb_cls callback closure
+ */
+static struct ANASTASIS_ReduxAction *
+finish_secret (json_t *state,
+ const json_t *arguments,
+ ANASTASIS_ActionCallback cb,
+ void *cb_cls)
+{
+ void *core_secret;
+ size_t core_secret_size;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_varsize ("core_secret",
+ &core_secret,
+ &core_secret_size),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (state,
+ spec,
+ NULL, NULL))
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
+ "State parsing failed: 'core_secret' is missing");
+ return NULL;
+ }
+
+ /* check upload size limit */
+ {
+ enum GNUNET_GenericReturnValue ret;
+
+ ret = check_upload_size_limit (state,
+ core_secret_size);
+ switch (ret)
+ {
+ case GNUNET_SYSERR:
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
+ "provider has an upload limit of 0");
+ GNUNET_JSON_parse_free (spec);
+ return NULL;
+ case GNUNET_NO:
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_SECRET_TOO_BIG,
+ NULL);
+ GNUNET_JSON_parse_free (spec);
+ return NULL;
+ default:
+ break;
+ }
+ }
GNUNET_JSON_parse_free (spec);
return upload (state,
@@ -3997,6 +4443,16 @@ ANASTASIS_backup_action_ (json_t *state,
"back",
&ANASTASIS_back_generic_decrement_
},
+ {
+ ANASTASIS_BACKUP_STATE_SECRET_EDITING,
+ "update_expiration",
+ &update_expiration
+ },
+ {
+ ANASTASIS_BACKUP_STATE_SECRET_EDITING,
+ "next",
+ &finish_secret
+ },
{
ANASTASIS_BACKUP_STATE_TRUTHS_PAYING,
"pay",
diff --git a/src/restclient/anastasis_api_policy_store.c
b/src/restclient/anastasis_api_policy_store.c
index babf06e..9b8c370 100644
--- a/src/restclient/anastasis_api_policy_store.c
+++ b/src/restclient/anastasis_api_policy_store.c
@@ -308,7 +308,7 @@ ANASTASIS_policy_store (
const struct ANASTASIS_CRYPTO_AccountPrivateKeyP *anastasis_priv,
const void *recovery_data,
size_t recovery_data_size,
- bool payment_requested,
+ uint32_t payment_years_requested,
const struct ANASTASIS_PaymentSecretP *payment_secret,
struct GNUNET_TIME_Relative payment_timeout,
ANASTASIS_PolicyStoreCallback cb,
@@ -418,24 +418,30 @@ ANASTASIS_policy_store (
char *path;
struct ANASTASIS_CRYPTO_AccountPublicKeyP pub;
char timeout_ms[32];
+ char pyrs[32];
GNUNET_snprintf (timeout_ms,
sizeof (timeout_ms),
"%llu",
tms);
+ GNUNET_snprintf (pyrs,
+ sizeof (pyrs),
+ "%u",
+ (unsigned int) payment_years_requested);
GNUNET_CRYPTO_eddsa_key_get_public (&anastasis_priv->priv,
&pub.pub);
- acc_pub_str = GNUNET_STRINGS_data_to_string_alloc (&pub,
- sizeof (pub));
+ acc_pub_str
+ = GNUNET_STRINGS_data_to_string_alloc (&pub,
+ sizeof (pub));
GNUNET_asprintf (&path,
"policy/%s",
acc_pub_str);
GNUNET_free (acc_pub_str);
pso->url = TALER_url_join (backend_url,
path,
- "pay",
- (payment_requested)
- ? "y"
+ "storage_duration",
+ (0 != payment_years_requested)
+ ? pyrs
: NULL,
"timeout_ms",
(0 != payment_timeout.rel_value_us)
diff --git a/src/restclient/anastasis_api_truth_store.c
b/src/restclient/anastasis_api_truth_store.c
index 5a75878..20bcde4 100644
--- a/src/restclient/anastasis_api_truth_store.c
+++ b/src/restclient/anastasis_api_truth_store.c
@@ -248,7 +248,7 @@ ANASTASIS_truth_store (
const char *truth_mime,
size_t encrypted_truth_size,
const void *encrypted_truth,
- bool payment_requested,
+ uint32_t payment_years_requested,
struct GNUNET_TIME_Relative payment_timeout,
ANASTASIS_TruthStoreCallback cb,
void *cb_cls)
@@ -277,8 +277,6 @@ ANASTASIS_truth_store (
uuid_str);
tso->url = TALER_url_join (backend_url,
path,
- "pay",
- (payment_requested) ? "y" : NULL,
"timeout_ms",
(0 != payment_timeout.rel_value_us)
? timeout_ms
@@ -293,7 +291,8 @@ ANASTASIS_truth_store (
truth_data = json_pack ("{s:o," /* encrypted KeyShare */
" s:s," /* type */
" s:o," /* nonce */
- " s:s}", /* truth_mime */
+ " s:s," /* truth_mime */
+ " s:I}", /* payment years */
"keyshare_data",
GNUNET_JSON_from_data_auto (encrypted_keyshare),
"type",
@@ -304,7 +303,9 @@ ANASTASIS_truth_store (
"truth_mime",
(NULL != truth_mime)
? truth_mime
- : "");
+ : "",
+ "storage_duration_years",
+ (json_int_t) payment_years_requested);
GNUNET_assert (NULL != truth_data);
json_str = json_dumps (truth_data,
JSON_COMPACT);
diff --git a/src/stasis/plugin_anastasis_postgres.c
b/src/stasis/plugin_anastasis_postgres.c
index e183211..ded8d0c 100644
--- a/src/stasis/plugin_anastasis_postgres.c
+++ b/src/stasis/plugin_anastasis_postgres.c
@@ -1071,9 +1071,12 @@ postgres_get_key_share (
/**
+ * Check if an account exists, and if so, return the
+ * current @a recovery_document_hash.
*
* @param cls closure
* @param anastasis_pub account identifier
+ * @param[out] paid_until until when is the account paid up?
* @param[out] recovery_data_hash set to hash of @a recovery document
* @param[out] version set to the recovery policy version
* @return transaction status
@@ -1082,6 +1085,7 @@ enum ANASTASIS_DB_AccountStatus
postgres_lookup_account (
void *cls,
const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
+ struct GNUNET_TIME_Absolute *paid_until,
struct GNUNET_HashCode *recovery_data_hash,
uint32_t *version)
{
@@ -1096,6 +1100,8 @@ postgres_lookup_account (
postgres_preflight (pg);
{
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("expiration_date",
+ &paid_until),
GNUNET_PQ_result_spec_auto_from_type ("recovery_data_hash",
recovery_data_hash),
GNUNET_PQ_result_spec_uint32 ("version",
@@ -1124,6 +1130,8 @@ postgres_lookup_account (
/* check if account exists */
{
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("expiration_date",
+ &paid_until),
GNUNET_PQ_result_spec_end
};
@@ -1144,6 +1152,10 @@ postgres_lookup_account (
return ANASTASIS_DB_ACCOUNT_STATUS_PAYMENT_REQUIRED;
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
/* indicates: no backup */
+ *version = UINT32_MAX;
+ memset (recovery_data_hash,
+ 0,
+ sizeof (*recovery_data_hash));
return ANASTASIS_DB_ACCOUNT_STATUS_NO_RESULTS;
default:
GNUNET_break (0);
@@ -1898,7 +1910,9 @@ libanastasis_plugin_db_postgres_init (void *cls)
"SELECT"
" version"
",recovery_data_hash"
+ ",expiration_date"
" FROM anastasis_recoverydocument"
+ " JOIN anastasis_user USING (user_id)"
" WHERE user_id=$1"
" ORDER BY version DESC"
" LIMIT 1;",
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-anastasis] branch master updated: -API break: allow clients to specify number of years of service to pay for, including reducer update. Will break stuff, partial patch for #6841,
gnunet <=