diff --git a/src/exchangedb/exchange-0001-part.sql b/src/exchangedb/exchange-0001-part.sql index a47a2aede..21810034e 100644 --- a/src/exchangedb/exchange-0001-part.sql +++ b/src/exchangedb/exchange-0001-part.sql @@ -3452,11 +3452,11 @@ BEGIN IF NOT FOUND THEN out_balance_ok=TRUE; - out_conflict=TRUE; + out_idempotent=TRUE; RETURN; END IF; - out_conflict=FALSE; + out_idempotent=FALSE; -- Update reserve balance. UPDATE reserves diff --git a/src/exchangedb/plugin_exchangedb_common.c b/src/exchangedb/plugin_exchangedb_common.c index a07ae78c1..c9ffa5b87 100644 --- a/src/exchangedb/plugin_exchangedb_common.c +++ b/src/exchangedb/plugin_exchangedb_common.c @@ -71,6 +71,20 @@ common_free_reserve_history (void *cls, GNUNET_free (closing); break; } + case TALER_EXCHANGEDB_RO_PURSE_MERGE: + { + struct TALER_EXCHANGEDB_PurseMerge *merge; + + merge = rh->details.merge; + GNUNET_free (merge); + } + case TALER_EXCHANGEDB_RO_HISTORY_REQUEST: + { + struct TALER_EXCHANGEDB_HistoryRequest *history; + + history = rh->details.history; + GNUNET_free (history); + } } { struct TALER_EXCHANGEDB_ReserveHistory *next; diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 5d84a2af4..8f1828008 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -2126,6 +2126,43 @@ prepare_statements (struct PostgresClosure *pg) " USING (wire_target_h_payto)" " WHERE reserve_pub=$1;", 1), + /* Used in #postgres_get_reserve_history() */ + GNUNET_PQ_make_prepare ( + "merge_by_reserve", + "SELECT" + " pr.amount_with_fee_val" + ",pr.amount_with_fee_frac" + ",pr.purse_fee_val" + ",pr.purse_fee_frac" + ",pr.h_contract_terms" + ",pr.merge_pub" + ",pr.purse_sig" + ",am.reserve_sig" + ",pm.purse_pub" + ",pm.merge_sig" + ",pm.merge_timestamp" + " FROM purse_merges pm" + " JOIN purse_requests pr" + " USING (purse_pub)" + " JOIN account_merges am" + " ON (am.purse_pub = pm.purse_pub AND" + " am.reserve_pub = pm.reserve_pub)" + " WHERE pm.reserve_pub=$1" + " AND pm.partner_serial_id=0" /* must be local! */ + " AND pr.finished" + " AND NOT pr.refunded;", + 1), + /* Used in #postgres_get_reserve_history() */ + GNUNET_PQ_make_prepare ( + "history_by_reserve", + "SELECT" + " history_fee_val" + ",history_fee_frac" + ",request_timestamp" + ",reserve_sig" + " FROM history_requests" + " WHERE reserve_pub=$1;", + 1), /* Used in #postgres_get_expired_reserves() */ GNUNET_PQ_make_prepare ( "get_expired_reserves", @@ -6131,6 +6168,54 @@ add_exchange_to_bank (void *cls, } +/** + * Add purse merge transfers to result set for + * #postgres_get_reserve_history. + * + * @param cls a `struct ReserveHistoryContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +add_p2p_merge (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReserveHistoryContext *rhc = cls; + struct PostgresClosure *pg = rhc->pg; + + while (0 < num_results) + { + // FIXME! + GNUNET_break (0); + } +} + + +/** + * Add paid for history requests to result set for + * #postgres_get_reserve_history. + * + * @param cls a `struct ReserveHistoryContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +add_history_requests (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct ReserveHistoryContext *rhc = cls; + struct PostgresClosure *pg = rhc->pg; + + while (0 < num_results) + { + // FIXME! + GNUNET_break (0); + } +} + + /** * Get all of the transaction history associated with the specified * reserve. @@ -6163,7 +6248,6 @@ postgres_get_reserve_history (void *cls, /** #TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE */ { "reserves_in_get_transactions", add_bank_to_exchange }, -#ifndef GRID5K_MARCO_OPT /** #TALER_EXCHANGEDB_RO_WITHDRAW_COIN */ { "get_reserves_out", &add_withdraw_coin }, @@ -6173,7 +6257,12 @@ postgres_get_reserve_history (void *cls, /** #TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK */ { "close_by_reserve", &add_exchange_to_bank }, -#endif + /** #TALER_EXCHANGEDB_RO_PURSE_MERGE */ + { "merge_by_reserve", + &add_p2p_merge }, + /** #TALER_EXCHANGEDB_RO_HISTORY_REQUEST */ + { "history_by_reserve", + &add_history_requests }, /* List terminator */ { NULL, NULL } diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index 4112b3d15..127895d65 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -1906,6 +1906,16 @@ run (void *cls) &fee_closing)); } break; + case TALER_EXCHANGEDB_RO_PURSE_MERGE: + { + /* FIXME: not yet tested */ + break; + } + case TALER_EXCHANGEDB_RO_HISTORY_REQUEST: + { + /* FIXME: not yet tested */ + break; + } } } FAILIF (4 != cnt); diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 2ef291235..68faf34f9 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -978,6 +978,81 @@ struct TALER_EXCHANGEDB_RecoupRefreshListEntry }; +/** + * Details about a purse merge operation. + */ +struct TALER_EXCHANGEDB_PurseMerge +{ + /** + * Amount in the purse, with fees. + */ + struct TALER_Amount amount_with_fee; + + /** + * Fee paid for the purse. + */ + struct TALER_Amount purse_fee; + + /** + * Hash over the contract. + */ + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * Merge capability key. + */ + struct TALER_PurseMergePublicKeyP merge_pub; + + /** + * Purse signature. + */ + struct TALER_PurseContractSignatureP purse_sig; + + /** + * Purse public key. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Merge signature. + */ + struct TALER_PurseMergePublicKeyP merge_sig; + + /** + * Signature by the reserve approving the merge. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * When was the merge made. + */ + struct GNUNET_TIME_Timestamp merge_timestamp; + +}; + + +/** + * Details about a (paid for) reserve history request. + */ +struct TALER_EXCHANGEDB_HistoryRequest +{ + /** + * Fee paid for the request. + */ + struct TALER_Amount history_fee; + + /** + * When was the request made. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * Signature by the reserve approving the history request. + */ + struct TALER_ReserveSignatureP reserve_sig; +}; + + /** * @brief Types of operations on a reserve. */ @@ -1004,7 +1079,17 @@ enum TALER_EXCHANGEDB_ReserveOperation * customer's bank account. This happens when the exchange * closes a reserve with a non-zero amount left in it. */ - TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK = 3 + TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK = 3, + + /** + * Event where a purse was merged into a reserve. + */ + TALER_EXCHANGEDB_RO_PURSE_MERGE = 4, + + /** + * Event where a wallet paid for a full reserve history. + */ + TALER_EXCHANGEDB_RO_HISTORY_REQUEST = 5 }; @@ -1055,6 +1140,16 @@ struct TALER_EXCHANGEDB_ReserveHistory */ struct TALER_EXCHANGEDB_ClosingTransfer *closing; + /** + * Details about a purse merge operation. + */ + struct TALER_EXCHANGEDB_PurseMerge *merge; + + /** + * Details about a (paid for) reserve history request. + */ + struct TALER_EXCHANGEDB_HistoryRequest *history; + } details; };