summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-06-04 21:59:55 +0200
committerChristian Grothoff <christian@grothoff.org>2022-06-04 22:00:02 +0200
commita17781ba8d5f875b5150e524174c5f144aa6c0ba (patch)
treec01f11a3810428471e6399b4961942732a21a1f1
parent6512456dc2559577867fdce1f7fe7f1b5a12291f (diff)
downloadexchange-a17781ba8d5f875b5150e524174c5f144aa6c0ba.tar.gz
exchange-a17781ba8d5f875b5150e524174c5f144aa6c0ba.tar.bz2
exchange-a17781ba8d5f875b5150e524174c5f144aa6c0ba.zip
-more work on p2p payments and tests thereof
-rw-r--r--src/exchange/taler-exchange-httpd_purses_merge.c30
-rw-r--r--src/exchange/taler-exchange-httpd_reserves_purse.c7
-rw-r--r--src/exchangedb/exchange-0001-part.sql15
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c16
-rw-r--r--src/include/taler_crypto_lib.h17
-rw-r--r--src/include/taler_exchangedb_plugin.h4
-rw-r--r--src/lib/exchange_api_common.c11
-rw-r--r--src/lib/exchange_api_purse_create_with_merge.c236
-rw-r--r--src/testing/Makefile.am8
-rw-r--r--src/testing/test_exchange_p2p.c16
-rw-r--r--src/testing/testing_api_cmd_purse_deposit.c29
-rw-r--r--src/testing/testing_api_cmd_reserve_purse.c2
-rw-r--r--src/util/wallet_signatures.c41
13 files changed, 346 insertions, 86 deletions
diff --git a/src/exchange/taler-exchange-httpd_purses_merge.c b/src/exchange/taler-exchange-httpd_purses_merge.c
index 14dba5232..d87fb16de 100644
--- a/src/exchange/taler-exchange-httpd_purses_merge.c
+++ b/src/exchange/taler-exchange-httpd_purses_merge.c
@@ -226,19 +226,20 @@ merge_transaction (void *cls,
bool no_kyc = true;
bool no_reserve = true;
- // FIXME: add KYC-check logic!
- qs = TEH_plugin->do_purse_merge (TEH_plugin->cls,
- pcc->purse_pub,
- &pcc->merge_sig,
- pcc->merge_timestamp,
- &pcc->reserve_sig,
- pcc->provider_url,
- &pcc->reserve_pub,
- &no_partner,
- &no_balance,
- &no_reserve,
- &no_kyc,
- &in_conflict);
+ qs = TEH_plugin->do_purse_merge (
+ TEH_plugin->cls,
+ pcc->purse_pub,
+ &pcc->merge_sig,
+ pcc->merge_timestamp,
+ &pcc->reserve_sig,
+ pcc->provider_url,
+ &pcc->reserve_pub,
+ TEH_KYC_NONE != TEH_kyc_config.mode,
+ &no_partner,
+ &no_balance,
+ &no_reserve,
+ &no_kyc,
+ &in_conflict);
if (qs < 0)
{
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -270,7 +271,8 @@ merge_transaction (void *cls,
NULL);
return GNUNET_DB_STATUS_HARD_ERROR;
}
- if (no_kyc)
+ if ( (no_kyc) &&
+ (TEH_KYC_NONE != TEH_kyc_config.mode) )
{
*mhd_ret
= TALER_MHD_REPLY_JSON_PACK (
diff --git a/src/exchange/taler-exchange-httpd_reserves_purse.c b/src/exchange/taler-exchange-httpd_reserves_purse.c
index f56852d53..44f3e85c3 100644
--- a/src/exchange/taler-exchange-httpd_reserves_purse.c
+++ b/src/exchange/taler-exchange-httpd_reserves_purse.c
@@ -301,6 +301,9 @@ purse_transaction (void *cls,
bool no_reserve = true;
bool no_kyc = true;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Creating purse with flags %d\n",
+ rpc->flags);
qs = TEH_plugin->do_reserve_purse (
TEH_plugin->cls,
&rpc->purse_pub,
@@ -312,6 +315,7 @@ purse_transaction (void *cls,
? NULL
: &rpc->gf->fees.purse,
rpc->reserve_pub,
+ TEH_KYC_NONE != TEH_kyc_config.mode,
&in_conflict,
&no_reserve,
&no_kyc,
@@ -387,7 +391,8 @@ purse_transaction (void *cls,
TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN));
return GNUNET_DB_STATUS_HARD_ERROR;
}
- if (no_kyc)
+ if ( (no_kyc) &&
+ (TEH_KYC_NONE != TEH_kyc_config.mode) )
{
*mhd_ret
= TALER_MHD_REPLY_JSON_PACK (
diff --git a/src/exchangedb/exchange-0001-part.sql b/src/exchangedb/exchange-0001-part.sql
index 0b99e25f9..c79fdf840 100644
--- a/src/exchangedb/exchange-0001-part.sql
+++ b/src/exchangedb/exchange-0001-part.sql
@@ -3090,6 +3090,7 @@ CREATE OR REPLACE FUNCTION exchange_do_purse_merge(
IN in_reserve_sig BYTEA,
IN in_partner_url VARCHAR,
IN in_reserve_pub BYTEA,
+ IN in_require_kyc BOOLEAN,
OUT out_no_partner BOOLEAN,
OUT out_no_balance BOOLEAN,
OUT out_no_kyc BOOLEAN,
@@ -3197,7 +3198,8 @@ out_conflict=FALSE;
ASSERT NOT my_finished, 'internal invariant failed';
-IF in_partner_url IS NULL
+IF ( (in_partner_url IS NULL) AND
+ (in_require_kyc) )
THEN
-- Need to do KYC check.
SELECT NOT kyc_passed
@@ -3272,7 +3274,7 @@ RETURN;
END $$;
-COMMENT ON FUNCTION exchange_do_purse_merge(BYTEA, BYTEA, INT8, BYTEA, VARCHAR, BYTEA)
+COMMENT ON FUNCTION exchange_do_purse_merge(BYTEA, BYTEA, INT8, BYTEA, VARCHAR, BYTEA, BOOLEAN)
IS 'Checks that the partner exists, the purse has not been merged with a different reserve and that the purse is full. If so, persists the merge data and either merges the purse with the reserve or marks it as ready for the taler-exchange-router. Caller MUST abort the transaction on failures so as to not persist data by accident.';
@@ -3285,6 +3287,7 @@ CREATE OR REPLACE FUNCTION exchange_do_reserve_purse(
IN in_purse_fee_val INT8,
IN in_purse_fee_frac INT4,
IN in_reserve_pub BYTEA,
+ IN in_require_kyc BOOLEAN,
OUT out_no_funds BOOLEAN,
OUT out_no_kyc BOOLEAN,
OUT out_no_reserve BOOLEAN,
@@ -3350,7 +3353,7 @@ THEN
END IF;
out_no_reserve=FALSE;
-IF (out_no_kyc)
+IF (out_no_kyc AND in_require_kyc)
THEN
out_no_funds=FALSE;
RETURN;
@@ -3412,6 +3415,12 @@ INSERT INTO account_merges
END $$;
+COMMENT ON FUNCTION exchange_do_reserve_purse(BYTEA, BYTEA, INT8, BYTEA, BOOLEAN, INT8, INT4, BYTEA, BOOLEAN)
+ IS 'Create a purse for a reserve.';
+
+
+
+
CREATE OR REPLACE FUNCTION exchange_do_account_merge(
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index 01869d592..9fcd6203a 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -3977,8 +3977,8 @@ prepare_statements (struct PostgresClosure *pg)
",out_no_reserve AS no_reserve"
",out_conflict AS conflict"
" FROM exchange_do_purse_merge"
- " ($1, $2, $3, $4, $5, $6);",
- 6),
+ " ($1, $2, $3, $4, $5, $6, $7);",
+ 7),
/* Used in #postgres_do_reserve_purse() */
GNUNET_PQ_make_prepare (
"call_reserve_purse",
@@ -3988,8 +3988,8 @@ prepare_statements (struct PostgresClosure *pg)
",out_no_kyc AS no_kyc"
",out_conflict AS conflict"
" FROM exchange_do_reserve_purse"
- " ($1, $2, $3, $4, $5, $6, $7, $8);",
- 8),
+ " ($1, $2, $3, $4, $5, $6, $7, $8, $9);",
+ 9),
/* Used in #postgres_select_purse_merge */
GNUNET_PQ_make_prepare (
"select_purse_merge",
@@ -14492,6 +14492,7 @@ postgres_get_purse_deposit (
* @param reserve_sig signature of the reserve affirming the merge
* @param partner_url URL of the partner exchange, can be NULL if the reserves lives with us
* @param reserve_pub public key of the reserve to credit
+ * @param require_kyc true if we should check for KYC
* @param[out] no_partner set to true if @a partner_url is unknown
* @param[out] no_balance set to true if the @a purse_pub is not paid up yet
* @param[out] no_reserve set to true if the @a reserve_pub is not known
@@ -14508,6 +14509,7 @@ postgres_do_purse_merge (
const struct TALER_ReserveSignatureP *reserve_sig,
const char *partner_url,
const struct TALER_ReservePublicKeyP *reserve_pub,
+ bool require_kyc,
bool *no_partner,
bool *no_balance,
bool *no_reserve,
@@ -14524,6 +14526,7 @@ postgres_do_purse_merge (
? GNUNET_PQ_query_param_null ()
: GNUNET_PQ_query_param_string (partner_url),
GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_bool (require_kyc),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
@@ -14559,7 +14562,10 @@ postgres_do_purse_merge (
* @param reserve_sig signature of the reserve affirming the merge
* @param purse_fee amount to charge the reserve for the purse creation, NULL to use the quota
* @param reserve_pub public key of the reserve to credit
+ * @param require_kyc true if we should check for KYC
* @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already
+ * @param[out] no_reserve set to true if @a reserve_pub is not a known reserve
+ * @param[out] no_kyc set to true if @a reserve_pub has not passed KYC checks
* @param[out] insufficient_funds set to true if @a reserve_pub has insufficient capacity to create another purse
* @return transaction status code
*/
@@ -14572,6 +14578,7 @@ postgres_do_reserve_purse (
const struct TALER_ReserveSignatureP *reserve_sig,
const struct TALER_Amount *purse_fee,
const struct TALER_ReservePublicKeyP *reserve_pub,
+ bool require_kyc,
bool *in_conflict,
bool *no_reserve,
bool *no_kyc,
@@ -14589,6 +14596,7 @@ postgres_do_reserve_purse (
? &zero_fee
: purse_fee),
GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_bool (require_kyc),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index c4c439af1..63fb56cee 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -2840,6 +2840,23 @@ TALER_wallet_econtract_upload_verify (
/**
+ * Verify a signature over encrypted contract.
+ *
+ * @param h_econtract hashed encrypted contract
+ * @param contract_pub public key for the DH-encryption
+ * @param purse_pub purse’s public key
+ * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_CREATE
+ * @return #GNUNET_OK if the signature is valid
+ */
+enum GNUNET_GenericReturnValue
+TALER_wallet_econtract_upload_verify2 (
+ const struct GNUNET_HashCode *h_econtract,
+ const struct TALER_ContractDiffiePublicP *contract_pub,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PurseContractSignatureP *purse_sig);
+
+
+/**
* Sign a request to inquire about a purse's status.
*
* @param purse_priv key identifying the purse
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index a88f34b01..394177751 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -5037,6 +5037,7 @@ struct TALER_EXCHANGEDB_Plugin
* @param reserve_sig signature of the reserve affirming the merge
* @param partner_url URL of the partner exchange, can be NULL if the reserves lives with us
* @param reserve_pub public key of the reserve to credit
+ * @param require_kyc true if we should check for KYC
* @param[out] no_partner set to true if @a partner_url is unknown
* @param[out] no_balance set to true if the @a purse_pub is not paid up yet
* @param[out] no_reserve set to true if the @a reserve_pub is not known
@@ -5053,6 +5054,7 @@ struct TALER_EXCHANGEDB_Plugin
const struct TALER_ReserveSignatureP *reserve_sig,
const char *partner_url,
const struct TALER_ReservePublicKeyP *reserve_pub,
+ bool require_kyc,
bool *no_partner,
bool *no_balance,
bool *no_reserve,
@@ -5072,6 +5074,7 @@ struct TALER_EXCHANGEDB_Plugin
* @param reserve_sig signature of the reserve affirming the merge
* @param purse_fee amount to charge the reserve for the purse creation, NULL to use the quota
* @param reserve_pub public key of the reserve to credit
+ * @param require_kyc true if we should check for KYC
* @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already
* @param[out] no_reserve set to true if @a reserve_pub is not a known reserve
* @param[out] no_kyc set to true if @a reserve_pub has not passed KYC checks
@@ -5087,6 +5090,7 @@ struct TALER_EXCHANGEDB_Plugin
const struct TALER_ReserveSignatureP *reserve_sig,
const struct TALER_Amount *purse_fee,
const struct TALER_ReservePublicKeyP *reserve_pub,
+ bool require_kyc,
bool *in_conflict,
bool *no_reserve,
bool *no_kyc,
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c
index d60327831..9cbcdeb26 100644
--- a/src/lib/exchange_api_common.c
+++ b/src/lib/exchange_api_common.c
@@ -398,6 +398,7 @@ parse_merge (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
const json_t *transaction)
{
uint32_t flags32;
+ struct TALER_Amount total;
struct GNUNET_JSON_Specification merge_spec[] = {
GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
&rh->details.merge_details.h_contract_terms),
@@ -433,13 +434,21 @@ parse_merge (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
}
rh->details.merge_details.flags =
(enum TALER_WalletAccountMergeFlags) flags32;
+ if (0 >
+ TALER_amount_add (&total,
+ &rh->amount,
+ &rh->details.merge_details.purse_fee))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
if (GNUNET_OK !=
TALER_wallet_account_merge_verify (
rh->details.merge_details.merge_timestamp,
&rh->details.merge_details.purse_pub,
rh->details.merge_details.purse_expiration,
&rh->details.merge_details.h_contract_terms,
- &rh->amount,
+ &total,
&rh->details.merge_details.purse_fee,
rh->details.merge_details.min_age,
rh->details.merge_details.flags,
diff --git a/src/lib/exchange_api_purse_create_with_merge.c b/src/lib/exchange_api_purse_create_with_merge.c
index af5b554e4..fcc68e699 100644
--- a/src/lib/exchange_api_purse_create_with_merge.c
+++ b/src/lib/exchange_api_purse_create_with_merge.c
@@ -86,11 +86,31 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle
struct TALER_ReserveSignatureP reserve_sig;
/**
+ * Merge capability key.
+ */
+ struct TALER_PurseMergePublicKeyP merge_pub;
+
+ /**
+ * Our merge signature (if any).
+ */
+ struct TALER_PurseMergeSignatureP merge_sig;
+
+ /**
+ * Our contract signature (if any).
+ */
+ struct TALER_PurseContractSignatureP contract_sig;
+
+ /**
* Public key of the purse.
*/
struct TALER_PurseContractPublicKeyP purse_pub;
/**
+ * Request data we signed over.
+ */
+ struct TALER_PurseContractSignatureP purse_sig;
+
+ /**
* Hash over the purse's contrac terms.
*/
struct TALER_PrivateContractHashP h_contract_terms;
@@ -136,13 +156,14 @@ handle_purse_create_with_merge_finished (void *cls,
break;
case MHD_HTTP_OK:
{
-#if FIXME
const struct TALER_EXCHANGE_Keys *key_state;
struct GNUNET_TIME_Timestamp etime;
struct TALER_Amount total_deposited;
struct TALER_ExchangeSignatureP exchange_sig;
struct TALER_ExchangePublicKeyP exchange_pub;
struct GNUNET_JSON_Specification spec[] = {
+ TALER_JSON_spec_amount_any ("total_deposited",
+ &total_deposited),
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
&exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
@@ -169,29 +190,25 @@ handle_purse_create_with_merge_finished (void *cls,
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
- dr.hr.ec =
- TALER_EC_EXCHANGE_PURSE_CREATE_WITH_MERGE_EXCHANGE_SIGNATURE_INVALID;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
if (GNUNET_OK !=
- TALER_exchange_online_purse_create_with_merged_verify (
+ TALER_exchange_online_purse_created_verify (
etime,
pcm->purse_expiration,
&pcm->purse_value_after_fees,
+ &total_deposited,
&pcm->purse_pub,
&pcm->h_contract_terms,
- &pcm->reserve_pub,
- pcm->provider_url,
&exchange_pub,
&exchange_sig))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
- dr.hr.ec =
- TALER_EC_EXCHANGE_PURSE_CREATE_WITH_MERGE_EXCHANGE_SIGNATURE_INVALID;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
-#endif
}
break;
case MHD_HTTP_BAD_REQUEST:
@@ -214,7 +231,184 @@ handle_purse_create_with_merge_finished (void *cls,
happen, we should pass the JSON reply to the application */
break;
case MHD_HTTP_CONFLICT:
- // FIXME: check reply!
+ dr.hr.ec = TALER_JSON_get_error_code (j);
+ switch (dr.hr.ec)
+ {
+ case TALER_EC_EXCHANGE_RESERVES_PURSE_CREATE_CONFLICTING_META_DATA:
+ {
+ struct TALER_Amount amount;
+ uint32_t min_age;
+ struct GNUNET_TIME_Timestamp purse_expiration;
+ struct TALER_PurseContractSignatureP purse_sig;
+ struct TALER_PrivateContractHashP h_contract_terms;
+ struct TALER_PurseMergePublicKeyP merge_pub;
+ struct GNUNET_JSON_Specification spec[] = {
+ TALER_JSON_spec_amount_any ("amount",
+ &amount),
+ GNUNET_JSON_spec_uint32 ("min_age",
+ &min_age),
+ GNUNET_JSON_spec_timestamp ("purse_expiration",
+ &purse_expiration),
+ GNUNET_JSON_spec_fixed_auto ("purse_sig",
+ &purse_sig),
+ GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
+ &h_contract_terms),
+ GNUNET_JSON_spec_fixed_auto ("merge_pub",
+ &merge_pub),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (j,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ }
+ if (GNUNET_OK !=
+ TALER_wallet_purse_create_verify (purse_expiration,
+ &h_contract_terms,
+ &merge_pub,
+ min_age,
+ &amount,
+ &pcm->purse_pub,
+ &purse_sig))
+ {
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ }
+ if (0 ==
+ GNUNET_memcmp (&purse_sig,
+ &pcm->purse_sig))
+ {
+ /* Must be the SAME data, not a conflict! */
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ }
+ break;
+ }
+ case TALER_EC_EXCHANGE_RESERVES_PURSE_MERGE_CONFLICTING_META_DATA:
+ {
+ struct TALER_PurseMergeSignatureP merge_sig;
+ struct GNUNET_TIME_Timestamp merge_timestamp;
+ const char *partner_url = pcm->exchange->url;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("partner_url",
+ &partner_url),
+ NULL),
+ GNUNET_JSON_spec_timestamp ("merge_timestamp",
+ &merge_timestamp),
+ GNUNET_JSON_spec_fixed_auto ("merge_sig",
+ &merge_sig),
+ GNUNET_JSON_spec_fixed_auto ("reserve_pub",
+ &reserve_pub),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (j,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ }
+ if (GNUNET_OK !=
+ TALER_wallet_purse_merge_verify (
+ partner_url,
+ merge_timestamp,
+ &pcm->purse_pub,
+ &pcm->merge_pub,
+ &merge_sig))
+ {
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ }
+ if (0 ==
+ GNUNET_memcmp (&merge_sig,
+ &pcm->merge_sig))
+ {
+ /* Must be the SAME data, not a conflict! */
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ }
+ }
+ break;
+ case TALER_EC_EXCHANGE_RESERVES_PURSE_CREATE_INSUFFICIENT_FUNDS:
+ /* nothing to verify */
+ break;
+ case TALER_EC_EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA:
+ {
+ struct TALER_ContractDiffiePublicP pub_ckey;
+ struct TALER_PurseContractSignatureP contract_sig;
+ struct GNUNET_HashCode h_econtract;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto ("h_econtract",
+ &h_econtract),
+ GNUNET_JSON_spec_fixed_auto ("econtract_sig",
+ &contract_sig),
+ GNUNET_JSON_spec_fixed_auto ("pub_ckey",
+ &pub_ckey),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (j,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ }
+ if (GNUNET_OK !=
+ TALER_wallet_econtract_upload_verify2 (
+ &h_econtract,
+ &pub_ckey,
+ &pcm->purse_pub,
+ &contract_sig))
+ {
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ }
+ if (0 ==
+ GNUNET_memcmp (&contract_sig,
+ &pcm->contract_sig))
+ {
+ /* Must be the SAME data, not a conflict! */
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ }
+
+ break;
+ }
+ default:
+ /* unexpected EC! */
+ GNUNET_break_op (0);
+ dr.hr.http_status = 0;
+ dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ break;
+ } /* end inner (EC) switch */
break;
case MHD_HTTP_GONE:
/* could happen if denomination was revoked */
@@ -272,11 +466,7 @@ TALER_EXCHANGE_purse_create_with_merge (
CURL *eh;
char arg_str[sizeof (pcm->reserve_pub) * 2 + 32];
uint32_t min_age = 0;
- struct TALER_PurseMergePublicKeyP merge_pub;
- struct TALER_PurseMergeSignatureP merge_sig;
struct TALER_ContractDiffiePublicP contract_pub;
- struct TALER_PurseContractSignatureP contract_sig;
- struct TALER_PurseContractSignatureP purse_sig;
void *econtract = NULL;
size_t econtract_size = 0;
struct TALER_Amount purse_fee;
@@ -301,7 +491,7 @@ TALER_EXCHANGE_purse_create_with_merge (
GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
&pcm->reserve_pub.eddsa_pub);
GNUNET_CRYPTO_eddsa_key_get_public (&merge_priv->eddsa_priv,
- &merge_pub.eddsa_pub);
+ &pcm->merge_pub.eddsa_pub);
GNUNET_CRYPTO_ecdhe_key_get_public (&contract_priv->ecdhe_priv,
&contract_pub.ecdhe_pub);
@@ -372,16 +562,16 @@ TALER_EXCHANGE_purse_create_with_merge (
}
TALER_wallet_purse_create_sign (pcm->purse_expiration,
&pcm->h_contract_terms,
- &merge_pub,
+ &pcm->merge_pub,
min_age,
&pcm->purse_value_after_fees,
purse_priv,
- &purse_sig);
+ &pcm->purse_sig);
TALER_wallet_purse_merge_sign (exchange->url,
merge_timestamp,
&pcm->purse_pub,
merge_priv,
- &merge_sig);
+ &pcm->merge_sig);
TALER_wallet_account_merge_sign (merge_timestamp,
&pcm->purse_pub,
pcm->purse_expiration,
@@ -405,7 +595,7 @@ TALER_EXCHANGE_purse_create_with_merge (
econtract_size,
&contract_pub,
purse_priv,
- &contract_sig);
+ &pcm->contract_sig);
}
create_with_merge_obj = GNUNET_JSON_PACK (
TALER_JSON_pack_amount ("purse_value",
@@ -419,7 +609,7 @@ TALER_EXCHANGE_purse_create_with_merge (
GNUNET_JSON_pack_allow_null (
upload_contract
? GNUNET_JSON_pack_data_auto ("econtract_sig",
- &contract_sig)
+ &pcm->contract_sig)
: GNUNET_JSON_pack_string ("dummy",
NULL)),
GNUNET_JSON_pack_allow_null (
@@ -435,15 +625,15 @@ TALER_EXCHANGE_purse_create_with_merge (
: GNUNET_JSON_pack_string ("dummy2",
NULL)),
GNUNET_JSON_pack_data_auto ("merge_pub",
- &merge_pub),
+ &pcm->merge_pub),
GNUNET_JSON_pack_data_auto ("merge_sig",
- &merge_sig),
+ &pcm->merge_sig),
GNUNET_JSON_pack_data_auto ("reserve_sig",
&pcm->reserve_sig),
GNUNET_JSON_pack_data_auto ("purse_pub",
&pcm->purse_pub),
GNUNET_JSON_pack_data_auto ("purse_sig",
- &purse_sig),
+ &pcm->purse_sig),
GNUNET_JSON_pack_data_auto ("h_contract_terms",
&pcm->h_contract_terms),
GNUNET_JSON_pack_timestamp ("merge_timestamp",
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index fefb7c984..7da713beb 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -127,10 +127,6 @@ libtalertesting_la_LIBADD = \
AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
-noinst_PROGRAMS = \
- test_exchange_p2p_cs \
- test_exchange_p2p_rsa
-
.NOTPARALLEL:
check_PROGRAMS = \
@@ -152,7 +148,9 @@ check_PROGRAMS = \
test_exchange_management_api_rsa \
test_kyc_api \
test_taler_exchange_aggregator-postgres \
- test_taler_exchange_wirewatch-postgres
+ test_taler_exchange_wirewatch-postgres \
+ test_exchange_p2p_cs \
+ test_exchange_p2p_rsa
if HAVE_TWISTER
check_PROGRAMS += \
test_exchange_api_twisted_cs \
diff --git a/src/testing/test_exchange_p2p.c b/src/testing/test_exchange_p2p.c
index 647c56c8f..ba6d5bbf2 100644
--- a/src/testing/test_exchange_p2p.c
+++ b/src/testing/test_exchange_p2p.c
@@ -116,16 +116,16 @@ run (void *cls,
* Move money to the exchange's bank account.
*/
CMD_TRANSFER_TO_EXCHANGE ("create-reserve-1",
- "EUR:5.01"),
+ "EUR:5.04"),
CMD_TRANSFER_TO_EXCHANGE ("create-reserve-2",
"EUR:5.01"),
TALER_TESTING_cmd_reserve_poll ("poll-reserve-1",
"create-reserve-1",
- "EUR:5.01",
+ "EUR:5.04",
GNUNET_TIME_UNIT_MINUTES,
MHD_HTTP_OK),
TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-1",
- "EUR:5.01",
+ "EUR:5.04",
bc.user42_payto,
bc.exchange_payto,
"create-reserve-1"),
@@ -155,7 +155,7 @@ run (void *cls,
*/
TALER_TESTING_cmd_status ("status-1",
"create-reserve-1",
- "EUR:0",
+ "EUR:0.03",
MHD_HTTP_OK),
TALER_TESTING_cmd_end ()
};
@@ -195,13 +195,13 @@ run (void *cls,
TALER_TESTING_cmd_status (
"push-check-post-merge-reserve-balance-get",
"create-reserve-1",
- "EUR:1",
+ "EUR:1.03",
MHD_HTTP_OK),
/* POST history doesn't yet support P2P transfers */
TALER_TESTING_cmd_reserve_status (
"push-check-post-merge-reserve-balance-post",
"create-reserve-1",
- "EUR:1",
+ "EUR:1.03",
MHD_HTTP_OK),
/* Test conflicting merge */
TALER_TESTING_cmd_purse_merge (
@@ -249,13 +249,13 @@ run (void *cls,
TALER_TESTING_cmd_status (
"pull-check-post-merge-reserve-balance-get",
"create-reserve-1",
- "EUR:2",
+ "EUR:2.02",
MHD_HTTP_OK),
/* POST history doesn't yet support P2P transfers */
TALER_TESTING_cmd_reserve_status (
"push-check-post-merge-reserve-balance-post",
"create-reserve-1",
- "EUR:2",
+ "EUR:2.02",
MHD_HTTP_OK),
/* create 2nd purse for a deposit conflict */
TALER_TESTING_cmd_purse_create_with_reserve (
diff --git a/src/testing/testing_api_cmd_purse_deposit.c b/src/testing/testing_api_cmd_purse_deposit.c
index fa1b900da..0fa0998d2 100644
--- a/src/testing/testing_api_cmd_purse_deposit.c
+++ b/src/testing/testing_api_cmd_purse_deposit.c
@@ -201,9 +201,6 @@ deposit_cb (void *cls,
/* Deposits complete, create trait! */
ds->reserve_history.type = TALER_EXCHANGE_RTT_MERGE;
- ds->reserve_history.amount
- = dr->details.success.purse_value_after_fees;
-#if 0
{
const struct TALER_EXCHANGE_Keys *keys;
const struct TALER_EXCHANGE_GlobalFee *gf;
@@ -213,12 +210,26 @@ deposit_cb (void *cls,
gf = TALER_EXCHANGE_get_global_fee (keys,
*merge_timestamp);
GNUNET_assert (NULL != gf);
+
+ /* Note: change when flags below changes! */
+ if (true)
+ {
+ /* If we paid a purse fee, we need to subtract the
+ purse fee from the reserve history amount */
+ TALER_amount_subtract (&ds->reserve_history.amount,
+ &dr->details.success.purse_value_after_fees,
+ &gf->fees.purse);
+ ds->reserve_history.details.merge_details.purse_fee = gf->fees.purse;
+ }
+ else
+ {
+ ds->reserve_history.amount
+ = dr->details.success.purse_value_after_fees;
+ TALER_amount_set_zero (
+ ds->reserve_history.amount.currency,
+ &ds->reserve_history.details.merge_details.purse_fee);
+ }
}
-#endif
- /* Note: change when flags below changes! */
- TALER_amount_set_zero (
- ds->reserve_history.amount.currency,
- &ds->reserve_history.details.merge_details.purse_fee);
ds->reserve_history.details.merge_details.h_contract_terms
= dr->details.success.h_contract_terms;
ds->reserve_history.details.merge_details.merge_pub
@@ -234,7 +245,7 @@ deposit_cb (void *cls,
ds->reserve_history.details.merge_details.min_age
= ds->min_age;
ds->reserve_history.details.merge_details.flags
- = TALER_WAMF_MODE_CREATE_FROM_PURSE_QUOTA;
+ = TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE;
ds->purse_complete = true;
}
}
diff --git a/src/testing/testing_api_cmd_reserve_purse.c b/src/testing/testing_api_cmd_reserve_purse.c
index 42aff80e3..4106600cb 100644
--- a/src/testing/testing_api_cmd_reserve_purse.c
+++ b/src/testing/testing_api_cmd_reserve_purse.c
@@ -208,7 +208,7 @@ purse_run (void *cls,
&ds->contract_priv,
ds->contract_terms,
true /* upload contract */,
- false /* do not pay purse fee -- FIXME: make this a choice to test this case; then update testing_api_cmd_purse_deposit flags logic to match! */,
+ true /* do pay purse fee -- FIXME: make this a choice to test this case; then update testing_api_cmd_purse_deposit flags logic to match! */,
ds->merge_timestamp,
&purse_cb,
ds);
diff --git a/src/util/wallet_signatures.c b/src/util/wallet_signatures.c
index 9c5669650..41e272eb0 100644
--- a/src/util/wallet_signatures.c
+++ b/src/util/wallet_signatures.c
@@ -1248,20 +1248,9 @@ TALER_wallet_econtract_upload_sign (
}
-/**
- * Verify a signature over encrypted contract.
- *
- * @param econtract encrypted contract
- * @param econtract_size number of bytes in @a econtract
- * @param contract_pub public key for the DH-encryption
- * @param purse_pub purse’s public key
- * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_CREATE
- * @return #GNUNET_OK if the signature is valid
- */
enum GNUNET_GenericReturnValue
-TALER_wallet_econtract_upload_verify (
- const void *econtract,
- size_t econtract_size,
+TALER_wallet_econtract_upload_verify2 (
+ const struct GNUNET_HashCode *h_econtract,
const struct TALER_ContractDiffiePublicP *contract_pub,
const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PurseContractSignatureP *purse_sig)
@@ -1269,12 +1258,10 @@ TALER_wallet_econtract_upload_verify (
struct TALER_PurseContractPS pc = {
.purpose.size = htonl (sizeof (pc)),
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT),
- .contract_pub = *contract_pub
+ .contract_pub = *contract_pub,
+ .h_econtract = *h_econtract
};
- GNUNET_CRYPTO_hash (econtract,
- econtract_size,
- &pc.h_econtract);
return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT,
&pc.purpose,
&purse_sig->eddsa_signature,
@@ -1282,4 +1269,24 @@ TALER_wallet_econtract_upload_verify (
}
+enum GNUNET_GenericReturnValue
+TALER_wallet_econtract_upload_verify (
+ const void *econtract,
+ size_t econtract_size,
+ const struct TALER_ContractDiffiePublicP *contract_pub,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PurseContractSignatureP *purse_sig)
+{
+ struct GNUNET_HashCode h_econtract;
+
+ GNUNET_CRYPTO_hash (econtract,
+ econtract_size,
+ &h_econtract);
+ return TALER_wallet_econtract_upload_verify2 (&h_econtract,
+ contract_pub,
+ purse_pub,
+ purse_sig);
+}
+
+
/* end of wallet_signatures.c */