refactoring /deposit towards new transaction style (#5010)
This commit is contained in:
parent
d2c7ef54a7
commit
2ec1b055a0
@ -112,6 +112,79 @@ transaction_start_label: /* we will use goto for retries */ \
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a database transaction for @a connection.
|
||||||
|
* Starts a transaction and calls @a cb. Upon success,
|
||||||
|
* attempts to commit the transaction. Upon soft failures,
|
||||||
|
* retries @a cb a few times. Upon hard or persistent soft
|
||||||
|
* errors, generates an error message for @a connection.
|
||||||
|
*
|
||||||
|
* @param connection MHD connection to run @a cb for
|
||||||
|
* @param[out] set to MHD response code, if transaction failed
|
||||||
|
* @param cb callback implementing transaction logic
|
||||||
|
* @param cb_cls closure for @a cb, must be read-only!
|
||||||
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
TEH_DB_run_transaction (struct MHD_Connection *connection,
|
||||||
|
int *mhd_ret,
|
||||||
|
TEH_DB_TransactionCallback cb,
|
||||||
|
void *cb_cls)
|
||||||
|
{
|
||||||
|
struct TALER_EXCHANGEDB_Session *session;
|
||||||
|
|
||||||
|
*mhd_ret = -1; /* invalid value */
|
||||||
|
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
*mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
|
||||||
|
TALER_EC_DB_SETUP_FAILED);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
for (unsigned int retries = 0;retries < MAX_TRANSACTION_COMMIT_RETRIES; retries++)
|
||||||
|
{
|
||||||
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
TEH_plugin->start (TEH_plugin->cls,
|
||||||
|
session))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
*mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
|
||||||
|
TALER_EC_DB_START_FAILED);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
qs = cb (cb_cls,
|
||||||
|
connection,
|
||||||
|
session,
|
||||||
|
mhd_ret);
|
||||||
|
if (0 > qs)
|
||||||
|
TEH_plugin->rollback (TEH_plugin->cls,
|
||||||
|
session);
|
||||||
|
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
if (0 <= qs)
|
||||||
|
qs = TEH_plugin->commit (TEH_plugin->cls,
|
||||||
|
session);
|
||||||
|
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||||
|
{
|
||||||
|
*mhd_ret = TEH_RESPONSE_reply_commit_error (connection,
|
||||||
|
TALER_EC_DB_COMMIT_FAILED_HARD);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
/* make sure callback did not violate invariants! */
|
||||||
|
GNUNET_assert (-1 == *mhd_ret);
|
||||||
|
if (0 <= qs)
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
TALER_LOG_WARNING ("Transaction commit failed %u times\n",
|
||||||
|
MAX_TRANSACTION_COMMIT_RETRIES);
|
||||||
|
*mhd_ret = TEH_RESPONSE_reply_commit_error (connection,
|
||||||
|
TALER_EC_DB_COMMIT_FAILED_ON_RETRY);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the total value of all transactions performed.
|
* Calculate the total value of all transactions performed.
|
||||||
* Stores @a off plus the cost of all transactions in @a tl
|
* Stores @a off plus the cost of all transactions in @a tl
|
||||||
@ -119,13 +192,13 @@ transaction_start_label: /* we will use goto for retries */ \
|
|||||||
*
|
*
|
||||||
* @param tl transaction list to process
|
* @param tl transaction list to process
|
||||||
* @param off offset to use as the starting value
|
* @param off offset to use as the starting value
|
||||||
* @param ret where the resulting total is to be stored
|
* @param[out] ret where the resulting total is to be stored
|
||||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionList *tl,
|
TEH_DB_calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionList *tl,
|
||||||
const struct TALER_Amount *off,
|
const struct TALER_Amount *off,
|
||||||
struct TALER_Amount *ret)
|
struct TALER_Amount *ret)
|
||||||
{
|
{
|
||||||
struct TALER_Amount spent = *off;
|
struct TALER_Amount spent = *off;
|
||||||
struct TALER_EXCHANGEDB_TransactionList *pos;
|
struct TALER_EXCHANGEDB_TransactionList *pos;
|
||||||
@ -206,146 +279,6 @@ calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionList *tl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a deposit. The validity of the coin and signature
|
|
||||||
* have already been checked. The database must now check that
|
|
||||||
* the coin is not (double or over) spent, and execute the
|
|
||||||
* transaction (record details, generate success or failure response).
|
|
||||||
*
|
|
||||||
* @param connection the MHD connection to handle
|
|
||||||
* @param deposit information about the deposit
|
|
||||||
* @return MHD result code
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
TEH_DB_execute_deposit (struct MHD_Connection *connection,
|
|
||||||
const struct TALER_EXCHANGEDB_Deposit *deposit)
|
|
||||||
{
|
|
||||||
struct TALER_EXCHANGEDB_Session *session;
|
|
||||||
struct TALER_EXCHANGEDB_TransactionList *tl;
|
|
||||||
struct TALER_Amount spent;
|
|
||||||
struct TALER_Amount value;
|
|
||||||
struct TALER_Amount amount_without_fee;
|
|
||||||
struct TEH_KS_StateHandle *mks;
|
|
||||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
|
|
||||||
int ret;
|
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
|
||||||
unsigned int retries = 0;
|
|
||||||
|
|
||||||
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
|
||||||
TALER_EC_DB_SETUP_FAILED);
|
|
||||||
}
|
|
||||||
again:
|
|
||||||
if (GNUNET_YES ==
|
|
||||||
TEH_plugin->have_deposit (TEH_plugin->cls,
|
|
||||||
session,
|
|
||||||
deposit))
|
|
||||||
{
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_subtract (&amount_without_fee,
|
|
||||||
&deposit->amount_with_fee,
|
|
||||||
&deposit->deposit_fee));
|
|
||||||
return TEH_RESPONSE_reply_deposit_success (connection,
|
|
||||||
&deposit->coin.coin_pub,
|
|
||||||
&deposit->h_wire,
|
|
||||||
&deposit->h_contract_terms,
|
|
||||||
deposit->timestamp,
|
|
||||||
deposit->refund_deadline,
|
|
||||||
&deposit->merchant_pub,
|
|
||||||
&amount_without_fee);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: move the 'mks'-logic outside of _db.c? */
|
|
||||||
mks = TEH_KS_acquire ();
|
|
||||||
dki = TEH_KS_denomination_key_lookup (mks,
|
|
||||||
&deposit->coin.denom_pub,
|
|
||||||
TEH_KS_DKU_DEPOSIT);
|
|
||||||
if (NULL == dki)
|
|
||||||
{
|
|
||||||
TEH_KS_release (mks);
|
|
||||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
|
||||||
TALER_EC_DEPOSIT_DB_DENOMINATION_KEY_UNKNOWN);
|
|
||||||
}
|
|
||||||
TALER_amount_ntoh (&value,
|
|
||||||
&dki->issue.properties.value);
|
|
||||||
TEH_KS_release (mks);
|
|
||||||
|
|
||||||
START_TRANSACTION (session, connection);
|
|
||||||
|
|
||||||
/* fee for THIS transaction */
|
|
||||||
spent = deposit->amount_with_fee;
|
|
||||||
/* add cost of all previous transactions */
|
|
||||||
tl = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
|
|
||||||
session,
|
|
||||||
&deposit->coin.coin_pub);
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
calculate_transaction_list_totals (tl,
|
|
||||||
&spent,
|
|
||||||
&spent))
|
|
||||||
{
|
|
||||||
TEH_plugin->rollback (TEH_plugin->cls,
|
|
||||||
session);
|
|
||||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
|
||||||
tl);
|
|
||||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
|
||||||
TALER_EC_DEPOSIT_HISTORY_DB_ERROR);
|
|
||||||
}
|
|
||||||
/* Check that cost of all transactions is smaller than
|
|
||||||
the value of the coin. */
|
|
||||||
if (0 < TALER_amount_cmp (&spent,
|
|
||||||
&value))
|
|
||||||
{
|
|
||||||
TEH_plugin->rollback (TEH_plugin->cls,
|
|
||||||
session);
|
|
||||||
ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection,
|
|
||||||
TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS,
|
|
||||||
tl);
|
|
||||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
|
||||||
tl);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
|
||||||
tl);
|
|
||||||
qs = TEH_plugin->insert_deposit (TEH_plugin->cls,
|
|
||||||
session,
|
|
||||||
deposit);
|
|
||||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
|
||||||
{
|
|
||||||
TALER_LOG_WARNING ("Failed to store /deposit information in database\n");
|
|
||||||
TEH_plugin->rollback (TEH_plugin->cls,
|
|
||||||
session);
|
|
||||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
|
||||||
TALER_EC_DEPOSIT_STORE_DB_ERROR);
|
|
||||||
}
|
|
||||||
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
|
||||||
{
|
|
||||||
retries++;
|
|
||||||
TEH_plugin->rollback (TEH_plugin->cls,
|
|
||||||
session);
|
|
||||||
if (retries > 5)
|
|
||||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
|
||||||
TALER_EC_DEPOSIT_STORE_DB_ERROR);
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
|
|
||||||
COMMIT_TRANSACTION(session, connection);
|
|
||||||
GNUNET_assert (GNUNET_SYSERR !=
|
|
||||||
TALER_amount_subtract (&amount_without_fee,
|
|
||||||
&deposit->amount_with_fee,
|
|
||||||
&deposit->deposit_fee));
|
|
||||||
return TEH_RESPONSE_reply_deposit_success (connection,
|
|
||||||
&deposit->coin.coin_pub,
|
|
||||||
&deposit->h_wire,
|
|
||||||
&deposit->h_contract_terms,
|
|
||||||
deposit->timestamp,
|
|
||||||
deposit->refund_deadline,
|
|
||||||
&deposit->merchant_pub,
|
|
||||||
&amount_without_fee);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a "/refund". Returns a confirmation that the refund
|
* Execute a "/refund". Returns a confirmation that the refund
|
||||||
* was successful, or a failure if we are not aware of a matching
|
* was successful, or a failure if we are not aware of a matching
|
||||||
@ -367,6 +300,7 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
|||||||
struct TEH_KS_StateHandle *mks;
|
struct TEH_KS_StateHandle *mks;
|
||||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
|
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
|
||||||
struct TALER_Amount expect_fee;
|
struct TALER_Amount expect_fee;
|
||||||
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
int ret;
|
int ret;
|
||||||
int deposit_found;
|
int deposit_found;
|
||||||
int refund_found;
|
int refund_found;
|
||||||
@ -595,10 +529,10 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
|||||||
tl);
|
tl);
|
||||||
|
|
||||||
/* Finally, store new refund data */
|
/* Finally, store new refund data */
|
||||||
if (GNUNET_OK !=
|
qs = TEH_plugin->insert_refund (TEH_plugin->cls,
|
||||||
TEH_plugin->insert_refund (TEH_plugin->cls,
|
session,
|
||||||
session,
|
refund);
|
||||||
refund))
|
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||||
{
|
{
|
||||||
TALER_LOG_WARNING ("Failed to store /refund information in database\n");
|
TALER_LOG_WARNING ("Failed to store /refund information in database\n");
|
||||||
TEH_plugin->rollback (TEH_plugin->cls,
|
TEH_plugin->rollback (TEH_plugin->cls,
|
||||||
@ -606,6 +540,11 @@ TEH_DB_execute_refund (struct MHD_Connection *connection,
|
|||||||
return TEH_RESPONSE_reply_internal_db_error (connection,
|
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||||
TALER_EC_REFUND_STORE_DB_ERROR);
|
TALER_EC_REFUND_STORE_DB_ERROR);
|
||||||
}
|
}
|
||||||
|
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
||||||
|
{
|
||||||
|
/* FIXME: #5010: retry! */
|
||||||
|
}
|
||||||
|
|
||||||
COMMIT_TRANSACTION (session, connection);
|
COMMIT_TRANSACTION (session, connection);
|
||||||
|
|
||||||
return TEH_RESPONSE_reply_refund_success (connection,
|
return TEH_RESPONSE_reply_refund_success (connection,
|
||||||
@ -1043,9 +982,9 @@ refresh_check_melt (struct MHD_Connection *connection,
|
|||||||
session,
|
session,
|
||||||
&coin_details->coin_info.coin_pub);
|
&coin_details->coin_info.coin_pub);
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
calculate_transaction_list_totals (tl,
|
TEH_DB_calculate_transaction_list_totals (tl,
|
||||||
&spent,
|
&spent,
|
||||||
&spent))
|
&spent))
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||||
@ -2403,9 +2342,9 @@ TEH_DB_execute_payback (struct MHD_Connection *connection,
|
|||||||
TALER_amount_get_zero (value->currency,
|
TALER_amount_get_zero (value->currency,
|
||||||
&spent);
|
&spent);
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
calculate_transaction_list_totals (tl,
|
TEH_DB_calculate_transaction_list_totals (tl,
|
||||||
&spent,
|
&spent,
|
||||||
&spent))
|
&spent))
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
TEH_plugin->rollback (TEH_plugin->cls,
|
TEH_plugin->rollback (TEH_plugin->cls,
|
||||||
|
@ -24,20 +24,63 @@
|
|||||||
#include <microhttpd.h>
|
#include <microhttpd.h>
|
||||||
#include "taler_exchangedb_plugin.h"
|
#include "taler_exchangedb_plugin.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function implementing a database transaction. Runs the transaction
|
||||||
|
* logic; IF it returns a non-error code, the transaction logic MUST
|
||||||
|
* NOT queue a MHD response. IF it returns an hard error, the
|
||||||
|
* transaction logic MUST queue a MHD response and set @a mhd_ret. IF
|
||||||
|
* it returns the soft error code, the function MAY be called again to
|
||||||
|
* retry and MUST not queue a MHD response.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param connection MHD request which triggered the transaction
|
||||||
|
* @param session database session to use
|
||||||
|
* @param[out] mhd_ret set to MHD response status for @a connection,
|
||||||
|
* if transaction failed (!)
|
||||||
|
* @return transaction status
|
||||||
|
*/
|
||||||
|
typedef enum GNUNET_DB_QueryStatus
|
||||||
|
(*TEH_DB_TransactionCallback)(void *cls,
|
||||||
|
struct MHD_Connection *connection,
|
||||||
|
struct TALER_EXCHANGEDB_Session *session,
|
||||||
|
int *mhd_ret);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a "/deposit". The validity of the coin and signature
|
* Run a database transaction for @a connection.
|
||||||
* have already been checked. The database must now check that
|
* Starts a transaction and calls @a cb. Upon success,
|
||||||
* the coin is not (double or over) spent, and execute the
|
* attempts to commit the transaction. Upon soft failures,
|
||||||
* transaction (record details, generate success or failure response).
|
* retries @a cb a few times. Upon hard or persistent soft
|
||||||
|
* errors, generates an error message for @a connection.
|
||||||
*
|
*
|
||||||
* @param connection the MHD connection to handle
|
* @param connection MHD connection to run @a cb for
|
||||||
* @param deposit information about the deposit
|
* @param[out] set to MHD response code, if transaction failed
|
||||||
* @return MHD result code
|
* @param cb callback implementing transaction logic
|
||||||
|
* @param cb_cls closure for @a cb, must be read-only!
|
||||||
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
TEH_DB_execute_deposit (struct MHD_Connection *connection,
|
TEH_DB_run_transaction (struct MHD_Connection *connection,
|
||||||
const struct TALER_EXCHANGEDB_Deposit *deposit);
|
int *mhd_ret,
|
||||||
|
TEH_DB_TransactionCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the total value of all transactions performed.
|
||||||
|
* Stores @a off plus the cost of all transactions in @a tl
|
||||||
|
* in @a ret.
|
||||||
|
*
|
||||||
|
* @param tl transaction list to process
|
||||||
|
* @param off offset to use as the starting value
|
||||||
|
* @param[out] ret where the resulting total is to be stored
|
||||||
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
|
||||||
|
*/
|
||||||
|
// FIXME: maybe move to another module?
|
||||||
|
int
|
||||||
|
TEH_DB_calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionList *tl,
|
||||||
|
const struct TALER_Amount *off,
|
||||||
|
struct TALER_Amount *ret);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2014, 2015, 2016 Inria and GNUnet e.V.
|
Copyright (C) 2014-2017 Inria and GNUnet e.V.
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
TALER is free software; you can redistribute it and/or modify it under the
|
||||||
terms of the GNU Affero General Public License as published by the Free Software
|
terms of the GNU Affero General Public License as published by the Free Software
|
||||||
@ -36,6 +36,174 @@
|
|||||||
#include "taler-exchange-httpd_validation.h"
|
#include "taler-exchange-httpd_validation.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send confirmation of deposit success to client. This function
|
||||||
|
* will create a signed message affirming the given information
|
||||||
|
* and return it to the client. By this, the exchange affirms that
|
||||||
|
* the coin had sufficient (residual) value for the specified
|
||||||
|
* transaction and that it will execute the requested deposit
|
||||||
|
* operation with the given wiring details.
|
||||||
|
*
|
||||||
|
* @param connection connection to the client
|
||||||
|
* @param coin_pub public key of the coin
|
||||||
|
* @param h_wire hash of wire details
|
||||||
|
* @param h_contract_terms hash of contract details
|
||||||
|
* @param timestamp client's timestamp
|
||||||
|
* @param refund_deadline until when this deposit be refunded
|
||||||
|
* @param merchant merchant public key
|
||||||
|
* @param amount_without_fee fraction of coin value to deposit, without the fee
|
||||||
|
* @return MHD result code
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
reply_deposit_success (struct MHD_Connection *connection,
|
||||||
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
|
const struct GNUNET_HashCode *h_wire,
|
||||||
|
const struct GNUNET_HashCode *h_contract_terms,
|
||||||
|
struct GNUNET_TIME_Absolute timestamp,
|
||||||
|
struct GNUNET_TIME_Absolute refund_deadline,
|
||||||
|
const struct TALER_MerchantPublicKeyP *merchant,
|
||||||
|
const struct TALER_Amount *amount_without_fee)
|
||||||
|
{
|
||||||
|
struct TALER_DepositConfirmationPS dc;
|
||||||
|
struct TALER_ExchangePublicKeyP pub;
|
||||||
|
struct TALER_ExchangeSignatureP sig;
|
||||||
|
|
||||||
|
dc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT);
|
||||||
|
dc.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS));
|
||||||
|
dc.h_contract_terms = *h_contract_terms;
|
||||||
|
dc.h_wire = *h_wire;
|
||||||
|
dc.timestamp = GNUNET_TIME_absolute_hton (timestamp);
|
||||||
|
dc.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
|
||||||
|
TALER_amount_hton (&dc.amount_without_fee,
|
||||||
|
amount_without_fee);
|
||||||
|
dc.coin_pub = *coin_pub;
|
||||||
|
dc.merchant = *merchant;
|
||||||
|
TEH_KS_sign (&dc.purpose,
|
||||||
|
&pub,
|
||||||
|
&sig);
|
||||||
|
return TEH_RESPONSE_reply_json_pack (connection,
|
||||||
|
MHD_HTTP_OK,
|
||||||
|
"{s:s, s:o, s:o}",
|
||||||
|
"status", "DEPOSIT_OK",
|
||||||
|
"sig", GNUNET_JSON_from_data_auto (&sig),
|
||||||
|
"pub", GNUNET_JSON_from_data_auto (&pub));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure for #deposit_transaction.
|
||||||
|
*/
|
||||||
|
struct DepositContext
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Information about the deposit request.
|
||||||
|
*/
|
||||||
|
const struct TALER_EXCHANGEDB_Deposit *deposit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of the coin.
|
||||||
|
*/
|
||||||
|
struct TALER_Amount value;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute database transaction for /deposit. Runs the transaction
|
||||||
|
* logic; IF it returns a non-error code, the transaction logic MUST
|
||||||
|
* NOT queue a MHD response. IF it returns an hard error, the
|
||||||
|
* transaction logic MUST queue a MHD response and set @a mhd_ret. IF
|
||||||
|
* it returns the soft error code, the function MAY be called again to
|
||||||
|
* retry and MUST not queue a MHD response.
|
||||||
|
*
|
||||||
|
* @param cls a `struct DepositContext`
|
||||||
|
* @param connection MHD request context
|
||||||
|
* @param session database session and transaction to use
|
||||||
|
* @param[out] mhd_ret set to MHD status on error
|
||||||
|
* @return transaction status
|
||||||
|
*/
|
||||||
|
static enum GNUNET_DB_QueryStatus
|
||||||
|
deposit_transaction (void *cls,
|
||||||
|
struct MHD_Connection *connection,
|
||||||
|
struct TALER_EXCHANGEDB_Session *session,
|
||||||
|
int *mhd_ret)
|
||||||
|
{
|
||||||
|
struct DepositContext *dc = cls;
|
||||||
|
const struct TALER_EXCHANGEDB_Deposit *deposit = dc->deposit;
|
||||||
|
struct TALER_EXCHANGEDB_TransactionList *tl;
|
||||||
|
struct TALER_Amount spent;
|
||||||
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
|
||||||
|
qs = TEH_plugin->have_deposit (TEH_plugin->cls,
|
||||||
|
session,
|
||||||
|
deposit);
|
||||||
|
if (qs < 0)
|
||||||
|
return qs;
|
||||||
|
if (1 == qs)
|
||||||
|
{
|
||||||
|
struct TALER_Amount amount_without_fee;
|
||||||
|
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_subtract (&amount_without_fee,
|
||||||
|
&deposit->amount_with_fee,
|
||||||
|
&deposit->deposit_fee));
|
||||||
|
*mhd_ret = reply_deposit_success (connection,
|
||||||
|
&deposit->coin.coin_pub,
|
||||||
|
&deposit->h_wire,
|
||||||
|
&deposit->h_contract_terms,
|
||||||
|
deposit->timestamp,
|
||||||
|
deposit->refund_deadline,
|
||||||
|
&deposit->merchant_pub,
|
||||||
|
&amount_without_fee);
|
||||||
|
/* Treat as 'hard' DB error as we want to rollback and
|
||||||
|
never try again. */
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start with fee for THIS transaction */
|
||||||
|
spent = deposit->amount_with_fee;
|
||||||
|
/* add cost of all previous transactions */
|
||||||
|
tl = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
|
||||||
|
session,
|
||||||
|
&deposit->coin.coin_pub);
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
TEH_DB_calculate_transaction_list_totals (tl,
|
||||||
|
&spent,
|
||||||
|
&spent))
|
||||||
|
{
|
||||||
|
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||||
|
tl);
|
||||||
|
*mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
|
||||||
|
TALER_EC_DEPOSIT_HISTORY_DB_ERROR);
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
}
|
||||||
|
/* Check that cost of all transactions is smaller than
|
||||||
|
the value of the coin. */
|
||||||
|
if (0 < TALER_amount_cmp (&spent,
|
||||||
|
&dc->value))
|
||||||
|
{
|
||||||
|
*mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection,
|
||||||
|
TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS,
|
||||||
|
tl);
|
||||||
|
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||||
|
tl);
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
}
|
||||||
|
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||||
|
tl);
|
||||||
|
qs = TEH_plugin->insert_deposit (TEH_plugin->cls,
|
||||||
|
session,
|
||||||
|
deposit);
|
||||||
|
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||||
|
{
|
||||||
|
TALER_LOG_WARNING ("Failed to store /deposit information in database\n");
|
||||||
|
*mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
|
||||||
|
TALER_EC_DEPOSIT_STORE_DB_ERROR);
|
||||||
|
}
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We have parsed the JSON information about the deposit, do some
|
* We have parsed the JSON information about the deposit, do some
|
||||||
* basic sanity checks (especially that the signature on the coin is
|
* basic sanity checks (especially that the signature on the coin is
|
||||||
@ -51,7 +219,13 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
|
|||||||
const struct TALER_EXCHANGEDB_Deposit *deposit)
|
const struct TALER_EXCHANGEDB_Deposit *deposit)
|
||||||
{
|
{
|
||||||
struct TALER_DepositRequestPS dr;
|
struct TALER_DepositRequestPS dr;
|
||||||
|
int mhd_ret;
|
||||||
|
struct TALER_Amount amount_without_fee;
|
||||||
|
struct DepositContext dc;
|
||||||
|
struct TEH_KS_StateHandle *mks;
|
||||||
|
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
|
||||||
|
|
||||||
|
/* check signature */
|
||||||
dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
|
dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
|
||||||
dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
|
dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
|
||||||
dr.h_contract_terms = deposit->h_contract_terms;
|
dr.h_contract_terms = deposit->h_contract_terms;
|
||||||
@ -76,8 +250,43 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
|
|||||||
"coin_sig");
|
"coin_sig");
|
||||||
}
|
}
|
||||||
|
|
||||||
return TEH_DB_execute_deposit (connection,
|
/* check denomination */
|
||||||
deposit);
|
mks = TEH_KS_acquire ();
|
||||||
|
dki = TEH_KS_denomination_key_lookup (mks,
|
||||||
|
&deposit->coin.denom_pub,
|
||||||
|
TEH_KS_DKU_DEPOSIT);
|
||||||
|
if (NULL == dki)
|
||||||
|
{
|
||||||
|
TEH_KS_release (mks);
|
||||||
|
return TEH_RESPONSE_reply_internal_db_error (connection,
|
||||||
|
TALER_EC_DEPOSIT_DB_DENOMINATION_KEY_UNKNOWN);
|
||||||
|
}
|
||||||
|
TALER_amount_ntoh (&dc.value,
|
||||||
|
&dki->issue.properties.value);
|
||||||
|
TEH_KS_release (mks);
|
||||||
|
|
||||||
|
/* execute transaction */
|
||||||
|
dc.deposit = deposit;
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
TEH_DB_run_transaction (connection,
|
||||||
|
&mhd_ret,
|
||||||
|
&deposit_transaction,
|
||||||
|
&dc))
|
||||||
|
return mhd_ret;
|
||||||
|
|
||||||
|
/* generate regular response */
|
||||||
|
GNUNET_assert (GNUNET_SYSERR !=
|
||||||
|
TALER_amount_subtract (&amount_without_fee,
|
||||||
|
&deposit->amount_with_fee,
|
||||||
|
&deposit->deposit_fee));
|
||||||
|
return reply_deposit_success (connection,
|
||||||
|
&deposit->coin.coin_pub,
|
||||||
|
&deposit->h_wire,
|
||||||
|
&deposit->h_contract_terms,
|
||||||
|
deposit->timestamp,
|
||||||
|
deposit->refund_deadline,
|
||||||
|
&deposit->merchant_pub,
|
||||||
|
&amount_without_fee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -461,60 +461,6 @@ TEH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send confirmation of deposit success to client. This function
|
|
||||||
* will create a signed message affirming the given information
|
|
||||||
* and return it to the client. By this, the exchange affirms that
|
|
||||||
* the coin had sufficient (residual) value for the specified
|
|
||||||
* transaction and that it will execute the requested deposit
|
|
||||||
* operation with the given wiring details.
|
|
||||||
*
|
|
||||||
* @param connection connection to the client
|
|
||||||
* @param coin_pub public key of the coin
|
|
||||||
* @param h_wire hash of wire details
|
|
||||||
* @param h_contract_terms hash of contract details
|
|
||||||
* @param timestamp client's timestamp
|
|
||||||
* @param refund_deadline until when this deposit be refunded
|
|
||||||
* @param merchant merchant public key
|
|
||||||
* @param amount_without_fee fraction of coin value to deposit, without the fee
|
|
||||||
* @return MHD result code
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
TEH_RESPONSE_reply_deposit_success (struct MHD_Connection *connection,
|
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|
||||||
const struct GNUNET_HashCode *h_wire,
|
|
||||||
const struct GNUNET_HashCode *h_contract_terms,
|
|
||||||
struct GNUNET_TIME_Absolute timestamp,
|
|
||||||
struct GNUNET_TIME_Absolute refund_deadline,
|
|
||||||
const struct TALER_MerchantPublicKeyP *merchant,
|
|
||||||
const struct TALER_Amount *amount_without_fee)
|
|
||||||
{
|
|
||||||
struct TALER_DepositConfirmationPS dc;
|
|
||||||
struct TALER_ExchangePublicKeyP pub;
|
|
||||||
struct TALER_ExchangeSignatureP sig;
|
|
||||||
|
|
||||||
dc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT);
|
|
||||||
dc.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS));
|
|
||||||
dc.h_contract_terms = *h_contract_terms;
|
|
||||||
dc.h_wire = *h_wire;
|
|
||||||
dc.timestamp = GNUNET_TIME_absolute_hton (timestamp);
|
|
||||||
dc.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
|
|
||||||
TALER_amount_hton (&dc.amount_without_fee,
|
|
||||||
amount_without_fee);
|
|
||||||
dc.coin_pub = *coin_pub;
|
|
||||||
dc.merchant = *merchant;
|
|
||||||
TEH_KS_sign (&dc.purpose,
|
|
||||||
&pub,
|
|
||||||
&sig);
|
|
||||||
return TEH_RESPONSE_reply_json_pack (connection,
|
|
||||||
MHD_HTTP_OK,
|
|
||||||
"{s:s, s:o, s:o}",
|
|
||||||
"status", "DEPOSIT_OK",
|
|
||||||
"sig", GNUNET_JSON_from_data_auto (&sig),
|
|
||||||
"pub", GNUNET_JSON_from_data_auto (&pub));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile the transaction history of a coin into a JSON object.
|
* Compile the transaction history of a coin into a JSON object.
|
||||||
*
|
*
|
||||||
|
@ -243,35 +243,6 @@ int
|
|||||||
TEH_RESPONSE_reply_invalid_json (struct MHD_Connection *connectionx);
|
TEH_RESPONSE_reply_invalid_json (struct MHD_Connection *connectionx);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send confirmation of deposit success to client. This function
|
|
||||||
* will create a signed message affirming the given information
|
|
||||||
* and return it to the client. By this, the exchange affirms that
|
|
||||||
* the coin had sufficient (residual) value for the specified
|
|
||||||
* transaction and that it will execute the requested deposit
|
|
||||||
* operation with the given wiring details.
|
|
||||||
*
|
|
||||||
* @param connection connection to the client
|
|
||||||
* @param coin_pub public key of the coin
|
|
||||||
* @param h_wire hash of wire details
|
|
||||||
* @param h_contract_terms hash of proposal data
|
|
||||||
* @param timestamp client's timestamp
|
|
||||||
* @param refund_deadline until when this deposit be refunded
|
|
||||||
* @param merchant merchant public key
|
|
||||||
* @param amount_without_fee fraction of coin value to deposit (without fee)
|
|
||||||
* @return MHD result code
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
TEH_RESPONSE_reply_deposit_success (struct MHD_Connection *connection,
|
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|
||||||
const struct GNUNET_HashCode *h_wire,
|
|
||||||
const struct GNUNET_HashCode *h_contract_terms,
|
|
||||||
struct GNUNET_TIME_Absolute timestamp,
|
|
||||||
struct GNUNET_TIME_Absolute refund_deadline,
|
|
||||||
const struct TALER_MerchantPublicKeyP *merchant,
|
|
||||||
const struct TALER_Amount *amount_without_fee);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send proof that a request is invalid to client because of
|
* Send proof that a request is invalid to client because of
|
||||||
* insufficient funds. This function will create a message with all
|
* insufficient funds. This function will create a message with all
|
||||||
|
@ -1350,7 +1350,7 @@ interpret (struct PERF_TALER_EXCHANGEDB_interpreter_state *state)
|
|||||||
case PERF_TALER_EXCHANGEDB_CMD_GET_DEPOSIT:
|
case PERF_TALER_EXCHANGEDB_CMD_GET_DEPOSIT:
|
||||||
{
|
{
|
||||||
unsigned int source_index;
|
unsigned int source_index;
|
||||||
int ret;
|
enum GNUNET_DB_QueryStatus ret;
|
||||||
struct PERF_TALER_EXCHANGEDB_Data *data;
|
struct PERF_TALER_EXCHANGEDB_Data *data;
|
||||||
|
|
||||||
source_index = state->cmd[state->i].details.get_deposit.index_deposit;
|
source_index = state->cmd[state->i].details.get_deposit.index_deposit;
|
||||||
@ -1358,7 +1358,7 @@ interpret (struct PERF_TALER_EXCHANGEDB_interpreter_state *state)
|
|||||||
ret = state->plugin->have_deposit (state->plugin->cls,
|
ret = state->plugin->have_deposit (state->plugin->cls,
|
||||||
state->session,
|
state->session,
|
||||||
data->data.deposit);
|
data->data.deposit);
|
||||||
GNUNET_assert (GNUNET_SYSERR != ret);
|
GNUNET_assert (0 >= ret);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2698,11 +2698,11 @@ postgres_get_reserve_history (void *cls,
|
|||||||
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
* @param cls the `struct PostgresClosure` with the plugin-specific state
|
||||||
* @param session database connection
|
* @param session database connection
|
||||||
* @param deposit deposit to search for
|
* @param deposit deposit to search for
|
||||||
* @return #GNUNET_YES if we know this operation,
|
* @return 1 if we know this operation,
|
||||||
* #GNUNET_NO if this exact deposit is unknown to us
|
* 0 if this exact deposit is unknown to us,
|
||||||
* #GNUNET_SYSERR on DB error
|
* otherwise transaction error status
|
||||||
*/
|
*/
|
||||||
static int
|
static enum GNUNET_DB_QueryStatus
|
||||||
postgres_have_deposit (void *cls,
|
postgres_have_deposit (void *cls,
|
||||||
struct TALER_EXCHANGEDB_Session *session,
|
struct TALER_EXCHANGEDB_Session *session,
|
||||||
const struct TALER_EXCHANGEDB_Deposit *deposit)
|
const struct TALER_EXCHANGEDB_Deposit *deposit)
|
||||||
@ -2713,75 +2713,52 @@ postgres_have_deposit (void *cls,
|
|||||||
GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
|
GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
|
||||||
GNUNET_PQ_query_param_end
|
GNUNET_PQ_query_param_end
|
||||||
};
|
};
|
||||||
PGresult *result;
|
struct TALER_EXCHANGEDB_Deposit deposit2;
|
||||||
|
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||||
result = GNUNET_PQ_exec_prepared (session->conn,
|
TALER_PQ_result_spec_amount ("amount_with_fee",
|
||||||
"get_deposit",
|
&deposit2.amount_with_fee),
|
||||||
params);
|
GNUNET_PQ_result_spec_absolute_time ("timestamp",
|
||||||
if (PGRES_TUPLES_OK !=
|
&deposit2.timestamp),
|
||||||
PQresultStatus (result))
|
GNUNET_PQ_result_spec_absolute_time ("refund_deadline",
|
||||||
{
|
&deposit2.refund_deadline),
|
||||||
BREAK_DB_ERR (result, session->conn);
|
GNUNET_PQ_result_spec_absolute_time ("wire_deadline",
|
||||||
PQclear (result);
|
&deposit2.wire_deadline),
|
||||||
return GNUNET_SYSERR;
|
GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
|
||||||
}
|
&deposit2.h_contract_terms),
|
||||||
if (0 == PQntuples (result))
|
GNUNET_PQ_result_spec_auto_from_type ("h_wire",
|
||||||
{
|
&deposit2.h_wire),
|
||||||
PQclear (result);
|
GNUNET_PQ_result_spec_end
|
||||||
return GNUNET_NO;
|
};
|
||||||
}
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
|
||||||
|
qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn,
|
||||||
|
"get_deposit",
|
||||||
|
params,
|
||||||
|
rs);
|
||||||
|
if (0 >= qs)
|
||||||
|
return qs;
|
||||||
/* Now we check that the other information in @a deposit
|
/* Now we check that the other information in @a deposit
|
||||||
also matches, and if not report inconsistencies. */
|
also matches, and if not report inconsistencies. */
|
||||||
|
if ( (0 != TALER_amount_cmp (&deposit->amount_with_fee,
|
||||||
|
&deposit2.amount_with_fee)) ||
|
||||||
|
(deposit->timestamp.abs_value_us !=
|
||||||
|
deposit2.timestamp.abs_value_us) ||
|
||||||
|
(deposit->refund_deadline.abs_value_us !=
|
||||||
|
deposit2.refund_deadline.abs_value_us) ||
|
||||||
|
(0 != memcmp (&deposit->h_contract_terms,
|
||||||
|
&deposit2.h_contract_terms,
|
||||||
|
sizeof (struct GNUNET_HashCode))) ||
|
||||||
|
(0 != memcmp (&deposit->h_wire,
|
||||||
|
&deposit2.h_wire,
|
||||||
|
sizeof (struct GNUNET_HashCode))) )
|
||||||
{
|
{
|
||||||
struct TALER_EXCHANGEDB_Deposit deposit2;
|
/* Inconsistencies detected! Does not match! (We might want to
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
expand the API with a 'get_deposit' function to return the
|
||||||
TALER_PQ_result_spec_amount ("amount_with_fee",
|
original transaction details to be used for an error message
|
||||||
&deposit2.amount_with_fee),
|
in the future!) #3838 */
|
||||||
GNUNET_PQ_result_spec_absolute_time ("timestamp",
|
return 0; /* Counts as if the transaction was not there */
|
||||||
&deposit2.timestamp),
|
|
||||||
GNUNET_PQ_result_spec_absolute_time ("refund_deadline",
|
|
||||||
&deposit2.refund_deadline),
|
|
||||||
GNUNET_PQ_result_spec_absolute_time ("wire_deadline",
|
|
||||||
&deposit2.wire_deadline),
|
|
||||||
GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
|
|
||||||
&deposit2.h_contract_terms),
|
|
||||||
GNUNET_PQ_result_spec_auto_from_type ("h_wire",
|
|
||||||
&deposit2.h_wire),
|
|
||||||
GNUNET_PQ_result_spec_end
|
|
||||||
};
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
GNUNET_PQ_extract_result (result,
|
|
||||||
rs,
|
|
||||||
0))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
PQclear (result);
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
|
||||||
if ( (0 != TALER_amount_cmp (&deposit->amount_with_fee,
|
|
||||||
&deposit2.amount_with_fee)) ||
|
|
||||||
(deposit->timestamp.abs_value_us !=
|
|
||||||
deposit2.timestamp.abs_value_us) ||
|
|
||||||
(deposit->refund_deadline.abs_value_us !=
|
|
||||||
deposit2.refund_deadline.abs_value_us) ||
|
|
||||||
(0 != memcmp (&deposit->h_contract_terms,
|
|
||||||
&deposit2.h_contract_terms,
|
|
||||||
sizeof (struct GNUNET_HashCode))) ||
|
|
||||||
(0 != memcmp (&deposit->h_wire,
|
|
||||||
&deposit2.h_wire,
|
|
||||||
sizeof (struct GNUNET_HashCode))) )
|
|
||||||
{
|
|
||||||
/* Inconsistencies detected! Does not match! (We might want to
|
|
||||||
expand the API with a 'get_deposit' function to return the
|
|
||||||
original transaction details to be used for an error message
|
|
||||||
in the future!) #3838 */
|
|
||||||
PQclear (result);
|
|
||||||
return GNUNET_NO;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PQclear (result);
|
return 1;
|
||||||
return GNUNET_YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3267,11 +3244,9 @@ postgres_insert_deposit (void *cls,
|
|||||||
* @param cls the @e cls of this struct with the plugin-specific state
|
* @param cls the @e cls of this struct with the plugin-specific state
|
||||||
* @param session connection to the database
|
* @param session connection to the database
|
||||||
* @param refund refund information to store
|
* @param refund refund information to store
|
||||||
* @return #GNUNET_OK on success
|
* @return query result status
|
||||||
* #GNUNET_NO on transient error
|
|
||||||
* #GNUNET_SYSERR on error
|
|
||||||
*/
|
*/
|
||||||
static int
|
static enum GNUNET_DB_QueryStatus
|
||||||
postgres_insert_refund (void *cls,
|
postgres_insert_refund (void *cls,
|
||||||
struct TALER_EXCHANGEDB_Session *session,
|
struct TALER_EXCHANGEDB_Session *session,
|
||||||
const struct TALER_EXCHANGEDB_Refund *refund)
|
const struct TALER_EXCHANGEDB_Refund *refund)
|
||||||
@ -3289,9 +3264,9 @@ postgres_insert_refund (void *cls,
|
|||||||
GNUNET_assert (GNUNET_YES ==
|
GNUNET_assert (GNUNET_YES ==
|
||||||
TALER_amount_cmp_currency (&refund->refund_amount,
|
TALER_amount_cmp_currency (&refund->refund_amount,
|
||||||
&refund->refund_fee));
|
&refund->refund_fee));
|
||||||
return execute_prepared_non_select (session,
|
return GNUNET_PQ_eval_prepared_non_select (session->conn,
|
||||||
"insert_refund",
|
"insert_refund",
|
||||||
params);
|
params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1772,7 +1772,7 @@ run (void *cls)
|
|||||||
plugin->insert_deposit (plugin->cls,
|
plugin->insert_deposit (plugin->cls,
|
||||||
session,
|
session,
|
||||||
&deposit));
|
&deposit));
|
||||||
FAILIF (GNUNET_YES !=
|
FAILIF (1 !=
|
||||||
plugin->have_deposit (plugin->cls,
|
plugin->have_deposit (plugin->cls,
|
||||||
session,
|
session,
|
||||||
&deposit));
|
&deposit));
|
||||||
@ -1839,13 +1839,13 @@ run (void *cls)
|
|||||||
result = 10;
|
result = 10;
|
||||||
deposit2 = deposit;
|
deposit2 = deposit;
|
||||||
RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */
|
RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */
|
||||||
FAILIF (GNUNET_NO !=
|
FAILIF (0 !=
|
||||||
plugin->have_deposit (plugin->cls,
|
plugin->have_deposit (plugin->cls,
|
||||||
session,
|
session,
|
||||||
&deposit2));
|
&deposit2));
|
||||||
deposit2.merchant_pub = deposit.merchant_pub;
|
deposit2.merchant_pub = deposit.merchant_pub;
|
||||||
RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */
|
RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */
|
||||||
FAILIF (GNUNET_NO !=
|
FAILIF (0 !=
|
||||||
plugin->have_deposit (plugin->cls,
|
plugin->have_deposit (plugin->cls,
|
||||||
session,
|
session,
|
||||||
&deposit2));
|
&deposit2));
|
||||||
@ -1860,7 +1860,7 @@ run (void *cls)
|
|||||||
refund.rtransaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
|
refund.rtransaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
|
||||||
refund.refund_amount = deposit.amount_with_fee;
|
refund.refund_amount = deposit.amount_with_fee;
|
||||||
refund.refund_fee = fee_refund;
|
refund.refund_fee = fee_refund;
|
||||||
FAILIF (GNUNET_OK !=
|
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||||
plugin->insert_refund (plugin->cls,
|
plugin->insert_refund (plugin->cls,
|
||||||
session,
|
session,
|
||||||
&refund));
|
&refund));
|
||||||
|
@ -1293,11 +1293,11 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
* @param cls the @e cls of this struct with the plugin-specific state
|
* @param cls the @e cls of this struct with the plugin-specific state
|
||||||
* @param session database connection
|
* @param session database connection
|
||||||
* @param deposit deposit to search for
|
* @param deposit deposit to search for
|
||||||
* @return #GNUNET_YES if we know this operation,
|
* @return 1 if we know this operation,
|
||||||
* #GNUNET_NO if this exact deposit is unknown to us,
|
* 0 if this exact deposit is unknown to us,
|
||||||
* #GNUNET_SYSERR on DB error
|
* otherwise transaction error status
|
||||||
*/
|
*/
|
||||||
int
|
enum GNUNET_DB_QueryStatus
|
||||||
(*have_deposit) (void *cls,
|
(*have_deposit) (void *cls,
|
||||||
struct TALER_EXCHANGEDB_Session *session,
|
struct TALER_EXCHANGEDB_Session *session,
|
||||||
const struct TALER_EXCHANGEDB_Deposit *deposit);
|
const struct TALER_EXCHANGEDB_Deposit *deposit);
|
||||||
@ -1323,11 +1323,9 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
* @param cls the @e cls of this struct with the plugin-specific state
|
* @param cls the @e cls of this struct with the plugin-specific state
|
||||||
* @param session connection to the database
|
* @param session connection to the database
|
||||||
* @param refund refund information to store
|
* @param refund refund information to store
|
||||||
* @return #GNUNET_OK on success,
|
* @return query result status
|
||||||
* #GNUNET_NO on transient error
|
|
||||||
* #GNUNET_SYSERR on error
|
|
||||||
*/
|
*/
|
||||||
int
|
enum GNUNET_DB_QueryStatus
|
||||||
(*insert_refund) (void *cls,
|
(*insert_refund) (void *cls,
|
||||||
struct TALER_EXCHANGEDB_Session *session,
|
struct TALER_EXCHANGEDB_Session *session,
|
||||||
const struct TALER_EXCHANGEDB_Refund *refund);
|
const struct TALER_EXCHANGEDB_Refund *refund);
|
||||||
|
Loading…
Reference in New Issue
Block a user