From a83aa1f70ec66b468c3498251ea55f3ab89f6b0e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 22 Jul 2019 13:28:48 +0200 Subject: include new payback-refresh possibilities in coin history generation --- src/exchange/taler-exchange-httpd_db.c | 26 +++++++- src/exchange/taler-exchange-httpd_payback.c | 20 ------ src/exchange/taler-exchange-httpd_refund.c | 6 ++ src/exchange/taler-exchange-httpd_responses.c | 88 +++++++++++++++++++++++++++ src/exchangedb/plugin_exchangedb_common.c | 4 ++ src/include/taler_signatures.h | 45 +++++++++++++- 6 files changed, 166 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c index 1f47f8e1a..3b9dc36b5 100644 --- a/src/exchange/taler-exchange-httpd_db.c +++ b/src/exchange/taler-exchange-httpd_db.c @@ -168,8 +168,8 @@ TEH_DB_run_transaction (struct MHD_Connection *connection, // FIXME: maybe move to another module, i.e. exchangedb??? int TEH_DB_calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionList *tl, - const struct TALER_Amount *off, - struct TALER_Amount *ret) + const struct TALER_Amount *off, + struct TALER_Amount *ret) { struct TALER_Amount spent = *off; struct TALER_Amount refunded; @@ -222,6 +222,17 @@ TEH_DB_calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionLis return GNUNET_SYSERR; } break; + case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK: + /* refunded += pos->value */ + if (GNUNET_OK != + TALER_amount_add (&refunded, + &refunded, + &pos->details.old_coin_payback->value)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + break; case TALER_EXCHANGEDB_TT_PAYBACK: /* spent += pos->value */ if (GNUNET_OK != @@ -233,6 +244,17 @@ TEH_DB_calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionLis return GNUNET_SYSERR; } break; + case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH: + /* spent += pos->value */ + if (GNUNET_OK != + TALER_amount_add (&spent, + &spent, + &pos->details.payback_refresh->value)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + break; } } /* spent = spent - refunded */ diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c index 232c639e4..2f1a2dde7 100644 --- a/src/exchange/taler-exchange-httpd_payback.c +++ b/src/exchange/taler-exchange-httpd_payback.c @@ -285,26 +285,6 @@ payback_transaction (void *cls, } return qs; } - /* increment reserve balance */ - qs = TEH_plugin->increment_reserve_balance (TEH_plugin->cls, - session, - &pc->reserve_pub, - pc->coin, - pc->coin_sig, - pc->coin_bks, - &pc->amount, - &pc->h_blind, - pc->now); - if (0 > qs) - { - if (GNUNET_DB_STATUS_HARD_ERROR == qs) - { - TALER_LOG_WARNING ("Failed to store /payback information in database\n"); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_DB_PUT_FAILED); - } - return qs; - } return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; } diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c index ee6aac1bd..69b5cae96 100644 --- a/src/exchange/taler-exchange-httpd_refund.c +++ b/src/exchange/taler-exchange-httpd_refund.c @@ -236,9 +236,15 @@ refund_transaction (void *cls, } } break; + case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK: + /* Paybacks cannot be refunded, ignore here */ + break; case TALER_EXCHANGEDB_TT_PAYBACK: /* Paybacks cannot be refunded, ignore here */ break; + case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH: + /* Paybacks cannot be refunded, ignore here */ + break; } } /* handle if deposit was NOT found */ diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index 5881cbe5b..3cf3e781b 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -632,6 +632,50 @@ TEH_RESPONSE_compile_transaction_history (const struct TALER_EXCHANGEDB_Transact } } break; + case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK: + { + struct TALER_EXCHANGEDB_PaybackRefresh *pr = pos->details.old_coin_payback; + struct TALER_PaybackRefreshConfirmationPS pc; + struct TALER_ExchangePublicKeyP epub; + struct TALER_ExchangeSignatureP esig; + + pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH); + pc.purpose.size = htonl (sizeof (pc)); + pc.timestamp = GNUNET_TIME_absolute_hton (pr->timestamp); + TALER_amount_hton (&pc.payback_amount, + &pr->value); + pc.coin_pub = pr->coin.coin_pub; + pc.old_coin_pub = pr->old_coin_pub; + if (GNUNET_OK != + TEH_KS_sign (&pc.purpose, + &epub, + &esig)) + { + GNUNET_break (0); + json_decref (history); + return NULL; + } + /* NOTE: we could also provide coin_pub's coin_sig, denomination key hash and + the denomination key's RSA signature over coin_pub, but as the + wallet should really already have this information (and cannot + check or do anything with it anyway if it doesn't), it seems + strictly unnecessary. */ + if (0 != + json_array_append_new (history, + json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}", + "type", "OLD-COIN-PAYBACK", + "amount", TALER_JSON_from_amount (&pr->value), + "exchange_sig", GNUNET_JSON_from_data_auto (&esig), + "exchange_pub", GNUNET_JSON_from_data_auto (&epub), + "coin_pub", GNUNET_JSON_from_data_auto (&pr->coin.coin_pub), + "timestamp", GNUNET_JSON_from_time_abs (pr->timestamp)))) + { + GNUNET_break (0); + json_decref (history); + return NULL; + } + break; + } case TALER_EXCHANGEDB_TT_PAYBACK: { const struct TALER_EXCHANGEDB_Payback *payback = pos->details.payback; @@ -671,6 +715,50 @@ TEH_RESPONSE_compile_transaction_history (const struct TALER_EXCHANGEDB_Transact } } break; + case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH: + { + struct TALER_EXCHANGEDB_PaybackRefresh *pr = pos->details.payback_refresh; + struct TALER_PaybackRefreshConfirmationPS pc; + struct TALER_ExchangePublicKeyP epub; + struct TALER_ExchangeSignatureP esig; + + pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH); + pc.purpose.size = htonl (sizeof (pc)); + pc.timestamp = GNUNET_TIME_absolute_hton (pr->timestamp); + TALER_amount_hton (&pc.payback_amount, + &pr->value); + pc.coin_pub = pr->coin.coin_pub; + pc.old_coin_pub = pr->old_coin_pub; + if (GNUNET_OK != + TEH_KS_sign (&pc.purpose, + &epub, + &esig)) + { + GNUNET_break (0); + json_decref (history); + return NULL; + } + /* NOTE: we could also provide coin_pub's coin_sig, denomination key + hash and the denomination key's RSA signature over coin_pub, but as + the wallet should really already have this information (and cannot + check or do anything with it anyway if it doesn't), it seems + strictly unnecessary. */ + if (0 != + json_array_append_new (history, + json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}", + "type", "PAYBACK-REFRESH", + "amount", TALER_JSON_from_amount (&pr->value), + "exchange_sig", GNUNET_JSON_from_data_auto (&esig), + "exchange_pub", GNUNET_JSON_from_data_auto (&epub), + "old_coin_pub", GNUNET_JSON_from_data_auto (&pr->old_coin_pub), + "timestamp", GNUNET_JSON_from_time_abs (pr->timestamp)))) + { + GNUNET_break (0); + json_decref (history); + return NULL; + } + break; + } default: GNUNET_assert (0); } diff --git a/src/exchangedb/plugin_exchangedb_common.c b/src/exchangedb/plugin_exchangedb_common.c index 4a72f5460..4c381586b 100644 --- a/src/exchangedb/plugin_exchangedb_common.c +++ b/src/exchangedb/plugin_exchangedb_common.c @@ -100,6 +100,8 @@ common_free_coin_transaction_list (void *cls, GNUNET_free (list->details.melt); break; case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK: + if (NULL != list->details.payback_refresh->coin.denom_sig.rsa_signature) + GNUNET_CRYPTO_rsa_signature_free (list->details.payback_refresh->coin.denom_sig.rsa_signature); GNUNET_free (list->details.old_coin_payback); break; case TALER_EXCHANGEDB_TT_REFUND: @@ -113,6 +115,8 @@ common_free_coin_transaction_list (void *cls, GNUNET_free (list->details.payback); break; case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH: + if (NULL != list->details.payback_refresh->coin.denom_sig.rsa_signature) + GNUNET_CRYPTO_rsa_signature_free (list->details.payback_refresh->coin.denom_sig.rsa_signature); GNUNET_free (list->details.payback_refresh); break; } diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index b738e3156..aedf93e36 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -129,6 +129,11 @@ */ #define TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED 1040 +/** + * Signature where the Exchange confirms a payback-refresh operation. + */ +#define TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH 1041 + /**********************/ /* Auditor signatures */ @@ -1229,7 +1234,7 @@ struct TALER_PaybackRequestPS /** * Response by which the exchange affirms that it will * refund a coin as part of the emergency /payback - * protocol. The refund will go back to the bank + * protocol. The payback will go back to the bank * account that created the reserve. */ struct TALER_PaybackConfirmationPS @@ -1265,6 +1270,44 @@ struct TALER_PaybackConfirmationPS }; +/** + * Response by which the exchange affirms that it will refund a refreshed coin + * as part of the emergency /payback protocol. The payback will go back to the + * old coin's balance. + */ +struct TALER_PaybackRefreshConfirmationPS +{ + + /** + * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * When did the exchange receive the payback request? + * Indirectly determines when the wire transfer is (likely) + * to happen. + */ + struct GNUNET_TIME_AbsoluteNBO timestamp; + + /** + * How much of the coin's value will the exchange transfer? + * (Needed in case the coin was partially spent.) + */ + struct TALER_AmountNBO payback_amount; + + /** + * Public key of the refreshed coin. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + /** + * Public key of the old coin that will receive the payback. + */ + struct TALER_CoinSpendPublicKeyP old_coin_pub; +}; + + /** * Response by which the exchange affirms that it has * closed a reserve and send back the funds. -- cgit v1.2.3