From 8da74a6ca7f0fa30a4f23be2adccbdf33799cbb9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 18 Jun 2022 20:36:44 +0200 Subject: -more work on taler-helper-auditor-reserve p2p audits --- src/auditor/taler-helper-auditor-reserves.c | 391 +++++++++++++++++----------- src/include/taler_util.h | 13 + src/util/payto.c | 44 ++++ 3 files changed, 303 insertions(+), 145 deletions(-) diff --git a/src/auditor/taler-helper-auditor-reserves.c b/src/auditor/taler-helper-auditor-reserves.c index 814ba11d0..49176dcfa 100644 --- a/src/auditor/taler-helper-auditor-reserves.c +++ b/src/auditor/taler-helper-auditor-reserves.c @@ -399,6 +399,54 @@ struct ReserveContext }; +/** + * Create a new reserve for @a reserve_pub in @a rc. + * + * @param[in,out] rc context to update + * @param reserve_pub key for which to create a reserve + * @return NULL on error + */ +static struct ReserveSummary * +setup_reserve (struct ReserveContext *rc, + const struct TALER_ReservePublicKeyP *reserve_pub) +{ + struct ReserveSummary *rs; + struct GNUNET_HashCode key; + enum GNUNET_DB_QueryStatus qs; + + GNUNET_CRYPTO_hash (reserve_pub, + sizeof (*reserve_pub), + &key); + rs = GNUNET_CONTAINER_multihashmap_get (rc->reserves, + &key); + if (NULL != rs) + return rs; + rs = GNUNET_new (struct ReserveSummary); + rs->reserve_pub = *reserve_pub; + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (TALER_ARL_currency, + &rs->total_in)); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (TALER_ARL_currency, + &rs->total_out)); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (TALER_ARL_currency, + &rs->total_fee)); + if (0 > (qs = load_auditor_reserve_summary (rs))) + { + GNUNET_free (rs); + rc->qs = qs; + return NULL; + } + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multihashmap_put (rc->reserves, + &key, + rs, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + return rs; +} + + /** * Function called with details about incoming wire transfers. * @@ -421,54 +469,26 @@ handle_reserve_in (void *cls, struct GNUNET_TIME_Timestamp execution_date) { struct ReserveContext *rc = cls; - struct GNUNET_HashCode key; struct ReserveSummary *rs; struct GNUNET_TIME_Timestamp expiry; - enum GNUNET_DB_QueryStatus qs; (void) wire_reference; /* should be monotonically increasing */ GNUNET_assert (rowid >= ppr.last_reserve_in_serial_id); ppr.last_reserve_in_serial_id = rowid + 1; - GNUNET_CRYPTO_hash (reserve_pub, - sizeof (*reserve_pub), - &key); - rs = GNUNET_CONTAINER_multihashmap_get (rc->reserves, - &key); + rs = setup_reserve (rc, + reserve_pub); if (NULL == rs) { - rs = GNUNET_new (struct ReserveSummary); - rs->sender_account = GNUNET_strdup (sender_account_details); - rs->reserve_pub = *reserve_pub; - rs->total_in = *credit; - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (credit->currency, - &rs->total_out)); - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (credit->currency, - &rs->total_fee)); - if (0 > (qs = load_auditor_reserve_summary (rs))) - { - GNUNET_break (0); - GNUNET_free (rs); - rc->qs = qs; - return GNUNET_SYSERR; - } - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (rc->reserves, - &key, - rs, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - } - else - { - TALER_ARL_amount_add (&rs->total_in, - &rs->total_in, - credit); - if (NULL == rs->sender_account) - rs->sender_account = GNUNET_strdup (sender_account_details); + GNUNET_break (0); + return GNUNET_SYSERR; } + TALER_ARL_amount_add (&rs->total_in, + &rs->total_in, + credit); + if (NULL == rs->sender_account) + rs->sender_account = GNUNET_strdup (sender_account_details); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Additional incoming wire transfer for reserve `%s' of %s\n", TALER_B2S (reserve_pub), @@ -509,7 +529,6 @@ handle_reserve_out (void *cls, const struct TALER_Amount *amount_with_fee) { struct ReserveContext *rc = cls; - struct GNUNET_HashCode key; struct ReserveSummary *rs; const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue; struct TALER_Amount auditor_amount_with_fee; @@ -608,44 +627,16 @@ handle_reserve_out (void *cls, rowid, "amount with fee from exchange does not match denomination value plus fee"); } - - - GNUNET_CRYPTO_hash (reserve_pub, - sizeof (*reserve_pub), - &key); - rs = GNUNET_CONTAINER_multihashmap_get (rc->reserves, - &key); + rs = setup_reserve (rc, + reserve_pub); if (NULL == rs) { - rs = GNUNET_new (struct ReserveSummary); - rs->reserve_pub = *reserve_pub; - rs->total_out = auditor_amount_with_fee; - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (amount_with_fee->currency, - &rs->total_in)); - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (amount_with_fee->currency, - &rs->total_fee)); - qs = load_auditor_reserve_summary (rs); - if (0 > qs) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - GNUNET_free (rs); - rc->qs = qs; - return GNUNET_SYSERR; - } - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (rc->reserves, - &key, - rs, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - } - else - { - TALER_ARL_amount_add (&rs->total_out, - &rs->total_out, - &auditor_amount_with_fee); + GNUNET_break (0); + return GNUNET_SYSERR; } + TALER_ARL_amount_add (&rs->total_out, + &rs->total_out, + &auditor_amount_with_fee); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reserve `%s' reduced by %s from withdraw\n", TALER_B2S (reserve_pub), @@ -691,7 +682,6 @@ handle_recoup_by_reserve ( const union TALER_DenominationBlindingKeyP *coin_blind) { struct ReserveContext *rc = cls; - struct GNUNET_HashCode key; struct ReserveSummary *rs; struct GNUNET_TIME_Timestamp expiry; struct TALER_MasterSignatureP msig; @@ -794,42 +784,16 @@ handle_recoup_by_reserve ( amount); } - GNUNET_CRYPTO_hash (reserve_pub, - sizeof (*reserve_pub), - &key); - rs = GNUNET_CONTAINER_multihashmap_get (rc->reserves, - &key); + rs = setup_reserve (rc, + reserve_pub); if (NULL == rs) { - rs = GNUNET_new (struct ReserveSummary); - rs->reserve_pub = *reserve_pub; - rs->total_in = *amount; - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (amount->currency, - &rs->total_out)); - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (amount->currency, - &rs->total_fee)); - qs = load_auditor_reserve_summary (rs); - if (0 > qs) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - GNUNET_free (rs); - rc->qs = qs; - return GNUNET_SYSERR; - } - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (rc->reserves, - &key, - rs, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - } - else - { - TALER_ARL_amount_add (&rs->total_in, - &rs->total_in, - amount); + GNUNET_break (0); + return GNUNET_SYSERR; } + TALER_ARL_amount_add (&rs->total_in, + &rs->total_in, + amount); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Additional /recoup value to for reserve `%s' of %s\n", TALER_B2S (reserve_pub), @@ -923,44 +887,20 @@ handle_reserve_closed ( const struct TALER_WireTransferIdentifierRawP *transfer_details) { struct ReserveContext *rc = cls; - struct GNUNET_HashCode key; struct ReserveSummary *rs; - enum GNUNET_DB_QueryStatus qs; (void) transfer_details; /* should be monotonically increasing */ GNUNET_assert (rowid >= ppr.last_reserve_close_serial_id); ppr.last_reserve_close_serial_id = rowid + 1; - GNUNET_CRYPTO_hash (reserve_pub, - sizeof (*reserve_pub), - &key); - rs = GNUNET_CONTAINER_multihashmap_get (rc->reserves, - &key); + rs = setup_reserve (rc, + reserve_pub); if (NULL == rs) { - rs = GNUNET_new (struct ReserveSummary); - rs->reserve_pub = *reserve_pub; - rs->total_out = *amount_with_fee; - rs->total_fee = *closing_fee; - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (amount_with_fee->currency, - &rs->total_in)); - qs = load_auditor_reserve_summary (rs); - if (0 > qs) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - GNUNET_free (rs); - rc->qs = qs; - return GNUNET_SYSERR; - } - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (rc->reserves, - &key, - rs, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + GNUNET_break (0); + return GNUNET_SYSERR; } - else { struct TALER_Amount expected_fee; @@ -1088,7 +1028,7 @@ verify_reserve_balance (void *cls, making an illegitimate gain over the amount it dropped. We don't add the amount to some total simply because it is not an actualized gain and could be trivially corrected by - restoring the summary. */// + restoring the summary. */ TALER_ARL_report (report_reserve_balance_insufficient_inconsistencies, GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("reserve_pub", @@ -1325,7 +1265,36 @@ handle_purse_deposits ( const struct TALER_EXCHANGEDB_PurseDeposit *deposit, const struct TALER_DenominationPublicKey *denom_pub) { + const char *base_url + = (NULL == deposit->exchange_base_url) + ? TALER_ARL_exchange_url + : deposit->exchange_base_url; + + if (GNUNET_OK != + TALER_wallet_purse_deposit_verify (base_url, + &deposit->purse_pub, + &deposit->amount, + &deposit->coin_pub, + &deposit->coin_sig)) + { + TALER_ARL_report (report_bad_sig_losses, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("operation", + "purse-deposit"), + GNUNET_JSON_pack_uint64 ("row", + rowid), + TALER_JSON_pack_amount ("loss", + &deposit->amount), + GNUNET_JSON_pack_data_auto ("key_pub", + &deposit->coin_pub))); + TALER_ARL_amount_add (&total_bad_sig_loss, + &total_bad_sig_loss, + &deposit->amount); + return GNUNET_OK; + } + GNUNET_break (0); // FIXME + // FIXME: need flags + total deposited! /* Credit purse value (if last op)! */ return GNUNET_SYSERR; } @@ -1353,9 +1322,65 @@ handle_purse_merged ( const struct TALER_PurseContractPublicKeyP *purse_pub, struct GNUNET_TIME_Timestamp merge_timestamp) { - GNUNET_break (0); // FIXME - /* Credit purse value (if last op)! */ - return GNUNET_SYSERR; + struct ReserveContext *rc = cls; + struct ReserveSummary *rs; + char *reserve_url; + + reserve_url + = TALER_reserve_make_payto (NULL == partner_base_url + ? TALER_ARL_exchange_url + : partner_base_url, + reserve_pub); + if (GNUNET_OK != + TALER_wallet_purse_merge_verify (reserve_url, + merge_timestamp, + purse_pub, + merge_pub, + merge_sig)) + { + GNUNET_free (reserve_url); + TALER_ARL_report (report_bad_sig_losses, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("operation", + "merge-purse"), + GNUNET_JSON_pack_uint64 ("row", + rowid), + TALER_JSON_pack_amount ("loss", + amount), + GNUNET_JSON_pack_data_auto ("key_pub", + merge_pub))); + TALER_ARL_amount_add (&total_bad_sig_loss, + &total_bad_sig_loss, + amount); + return GNUNET_OK; + } + GNUNET_free (reserve_url); + if (TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE == + (flags & TALER_WAMF_MERGE_MODE_MASK)) + { + /* This just created the purse, actual credit to + the reserve will be done in handle_purse_deposits() */ + return GNUNET_OK; + } + if ( (NULL != partner_base_url) && + (0 != strcmp (partner_base_url, + TALER_ARL_exchange_url)) ) + { + /* credited reserve is at another exchange, do NOT credit here! */ + return GNUNET_OK; + } + rs = setup_reserve (rc, + reserve_pub); + if (NULL == rs) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + TALER_ARL_amount_add (&rs->total_in, + &rs->total_in, + amount); + // rs->a_expiration_date = FIXME: set to what?; + return GNUNET_OK; } @@ -1383,9 +1408,50 @@ handle_account_merged ( struct GNUNET_TIME_Timestamp merge_timestamp, const struct TALER_ReserveSignatureP *reserve_sig) { - GNUNET_break (0); // FIXME - /* Debit purse fee */ - return GNUNET_SYSERR; + struct ReserveContext *rc = cls; + struct ReserveSummary *rs; + + if (GNUNET_OK != + TALER_wallet_account_merge_verify (merge_timestamp, + purse_pub, + purse_expiration, + h_contract_terms, + amount, + purse_fee, + min_age, + flags, + reserve_pub, + reserve_sig)) + { + TALER_ARL_report (report_bad_sig_losses, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("operation", + "account-merge"), + GNUNET_JSON_pack_uint64 ("row", + rowid), + TALER_JSON_pack_amount ("loss", + purse_fee), + GNUNET_JSON_pack_data_auto ("key_pub", + reserve_pub))); + TALER_ARL_amount_add (&total_bad_sig_loss, + &total_bad_sig_loss, + purse_fee); + return GNUNET_OK; + } + rs = setup_reserve (rc, + reserve_pub); + if (NULL == rs) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + TALER_ARL_amount_add (&total_purse_fee_income, + &total_purse_fee_income, + purse_fee); + TALER_ARL_amount_add (&rs->total_out, + &rs->total_out, + purse_fee); + return GNUNET_OK; } @@ -1407,9 +1473,44 @@ handle_history_request ( const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReserveSignatureP *reserve_sig) { - GNUNET_break (0); // FIXME - /* Debit purse fee */ - return GNUNET_SYSERR; + struct ReserveContext *rc = cls; + struct ReserveSummary *rs; + + if (GNUNET_OK != + TALER_wallet_reserve_history_verify (ts, + history_fee, + reserve_pub, + reserve_sig)) + { + TALER_ARL_report (report_bad_sig_losses, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("operation", + "account-history"), + GNUNET_JSON_pack_uint64 ("row", + rowid), + TALER_JSON_pack_amount ("loss", + history_fee), + GNUNET_JSON_pack_data_auto ("key_pub", + reserve_pub))); + TALER_ARL_amount_add (&total_bad_sig_loss, + &total_bad_sig_loss, + history_fee); + return GNUNET_OK; + } + rs = setup_reserve (rc, + reserve_pub); + if (NULL == rs) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + TALER_ARL_amount_add (&total_history_fee_income, + &total_history_fee_income, + history_fee); + TALER_ARL_amount_add (&rs->total_out, + &rs->total_out, + history_fee); + return GNUNET_OK; } diff --git a/src/include/taler_util.h b/src/include/taler_util.h index 607d76724..e5c7b97b5 100644 --- a/src/include/taler_util.h +++ b/src/include/taler_util.h @@ -417,6 +417,19 @@ char * TALER_payto_validate (const char *payto_uri); +/** + * Create payto://-URI for a given exchange base URL + * and a @a reserve_pub. + * + * @param exchange_url the base URL of the exchange + * @param reserve_pub the public key of the reserve + * @return payto://-URI for the reserve (without receiver-name!) + */ +char * +TALER_reserve_make_payto (const char *exchange_url, + const struct TALER_ReservePublicKeyP *reserve_pub); + + /** * Check that an IBAN number is well-formed. * diff --git a/src/util/payto.c b/src/util/payto.c index d0f3a994b..83a1a7e1d 100644 --- a/src/util/payto.c +++ b/src/util/payto.c @@ -312,4 +312,48 @@ TALER_payto_from_reserve (const char *exchange_base_url, } +char * +TALER_reserve_make_payto (const char *exchange_url, + const struct TALER_ReservePublicKeyP *reserve_pub) +{ + char pub_str[sizeof (*reserve_pub) * 2]; + char *end; + bool is_http; + char *reserve_url; + + end = GNUNET_STRINGS_data_to_string ( + reserve_pub, + sizeof (*reserve_pub), + pub_str, + sizeof (pub_str)); + *end = '\0'; + if (0 == strncmp (exchange_url, + "http://", + strlen ("http://"))) + { + is_http = true; + exchange_url = &exchange_url[strlen ("http://")]; + } + else if (0 == strncmp (exchange_url, + "https://", + strlen ("https://"))) + { + is_http = false; + exchange_url = &exchange_url[strlen ("https://")]; + } + else + { + GNUNET_break (0); + return NULL; + } + /* exchange_url includes trailing '/' */ + GNUNET_asprintf (&reserve_url, + "payto://%s/%s%s", + is_http ? "taler+http" : "taler", + exchange_url, + pub_str); + return reserve_url; +} + + /* end of payto.c */ -- cgit v1.2.3