Merge branch 'master' of git+ssh://taler.net/var/git/mint
This commit is contained in:
commit
d89c91e64a
@ -1059,5 +1059,165 @@ void
|
|||||||
TALER_MINT_admin_add_incoming_cancel (struct TALER_MINT_AdminAddIncomingHandle *aai);
|
TALER_MINT_admin_add_incoming_cancel (struct TALER_MINT_AdminAddIncomingHandle *aai);
|
||||||
|
|
||||||
|
|
||||||
|
/* ********************* /wire/deposits *********************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A /wire/deposits Handle
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_WireDepositsHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Details for one of the /deposit operations that the
|
||||||
|
* mint combined into a single wire transfer.
|
||||||
|
*/
|
||||||
|
struct TALER_WireDepositDetails
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Hash of the contract.
|
||||||
|
*/
|
||||||
|
struct GNUNET_HashCode h_contract;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which coin was deposited?
|
||||||
|
*/
|
||||||
|
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of the deposit (including fee).
|
||||||
|
*/
|
||||||
|
struct TALER_Amount coin_value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fee charged by the mint for the deposit.
|
||||||
|
*/
|
||||||
|
struct TALER_Amount coin_fee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merchant's transaction identifier.
|
||||||
|
*/
|
||||||
|
uint64_t transaction_id;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called with detailed wire transfer data, including all
|
||||||
|
* of the coin transactions that were combined into the wire transfer.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param http_status HTTP status code we got, 0 on mint protocol violation
|
||||||
|
* @param json original json reply (may include signatures, those have then been
|
||||||
|
* validated already)
|
||||||
|
* @param wtid extracted wire transfer identifier, or NULL if the mint could
|
||||||
|
* not provide any (set only if @a http_status is #MHD_HTTP_OK)
|
||||||
|
* @param total_amount total amount of the wire transfer, or NULL if the mint could
|
||||||
|
* not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK)
|
||||||
|
* @param details_length length of the @a details array
|
||||||
|
* @param details array with details about the combined transactions
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*TALER_MINT_WireDepositsCallback)(void *cls,
|
||||||
|
unsigned int http_status,
|
||||||
|
json_t *json,
|
||||||
|
const struct GNUNET_HashCode *h_wire,
|
||||||
|
const struct TALER_Amount *total_amount,
|
||||||
|
unsigned int details_length,
|
||||||
|
const struct TALER_WireDepositDetails *details);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the mint about which transactions were combined
|
||||||
|
* to create a wire transfer.
|
||||||
|
*
|
||||||
|
* @param mint mint to query
|
||||||
|
* @param wtid raw wire transfer identifier to get information about
|
||||||
|
* @param cb callback to call
|
||||||
|
* @param cb_cls closure for @a cb
|
||||||
|
* @return handle to cancel operation
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_WireDepositsHandle *
|
||||||
|
TALER_MINT_wire_deposits (struct TALER_MINT_Handle *mint,
|
||||||
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
|
TALER_MINT_WireDepositsCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel wire deposits request. This function cannot be used on a request
|
||||||
|
* handle if a response is already served for it.
|
||||||
|
*
|
||||||
|
* @param wdh the wire deposits request handle
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TALER_MINT_wire_deposits_cancel (struct TALER_MINT_WireDepositsHandle *wdh);
|
||||||
|
|
||||||
|
|
||||||
|
/* ********************* /deposit/wtid *********************** */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A /deposit/wtid Handle
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_DepositWtidHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called with detailed wire transfer data.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param http_status HTTP status code we got, 0 on mint protocol violation
|
||||||
|
* @param json original json reply (may include signatures, those have then been
|
||||||
|
* validated already)
|
||||||
|
* @param wtid wire transfer identifier used by the mint, NULL if mint did not
|
||||||
|
* yet execute the transaction
|
||||||
|
* @param execution_time actual or planned execution time for the wire transfer
|
||||||
|
* @param coin_contribution contribution to the @a total_amount of the deposited coin (may be NULL)
|
||||||
|
* @param total_amount total amount of the wire transfer, or NULL if the mint could
|
||||||
|
* not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK)
|
||||||
|
*/
|
||||||
|
typedef void
|
||||||
|
(*TALER_MINT_DepositWtidCallback)(void *cls,
|
||||||
|
unsigned int http_status,
|
||||||
|
json_t *json,
|
||||||
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
|
struct GNUNET_TIME_Absolute execution_time,
|
||||||
|
const struct TALER_Amount *coin_contribution,
|
||||||
|
const struct TALER_Amount *total_amount);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain the wire transfer details for a given deposit.
|
||||||
|
*
|
||||||
|
* @param mint the mint to query
|
||||||
|
* @param merchant_priv the merchant's private key
|
||||||
|
* @param h_wire hash of merchant's wire transfer details
|
||||||
|
* @param h_contract hash of the contract
|
||||||
|
* @param coin_pub public key of the coin
|
||||||
|
* @param transaction_id transaction identifier
|
||||||
|
* @param cb function to call with the result
|
||||||
|
* @param cb_cls closure for @a cb
|
||||||
|
* @return handle to abort request
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_DepositWtidHandle *
|
||||||
|
TALER_MINT_deposit_wtid (struct TALER_MINT_Handle *mint,
|
||||||
|
const struct TALER_MerchantPrivateKeyP *merchant_priv,
|
||||||
|
const struct GNUNET_HashCode *h_wire,
|
||||||
|
const struct GNUNET_HashCode *h_contract,
|
||||||
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
|
uint64_t transaction_id,
|
||||||
|
TALER_MINT_DepositWtidCallback cb,
|
||||||
|
void *cb_cls);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel deposit wtid request. This function cannot be used on a request
|
||||||
|
* handle if a response is already served for it.
|
||||||
|
*
|
||||||
|
* @param dwh the wire deposits request handle
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TALER_MINT_deposit_wtid_cancel (struct TALER_MINT_DepositWtidHandle *dwh);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _TALER_MINT_SERVICE_H */
|
#endif /* _TALER_MINT_SERVICE_H */
|
||||||
|
@ -570,23 +570,24 @@ typedef void
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called with the results of the lookup of the
|
* Function called with the results of the lookup of the
|
||||||
* wire transfer identifier information.
|
* wire transfer identifier information. Only called if
|
||||||
|
* we are at least aware of the transaction existing.
|
||||||
*
|
*
|
||||||
* @param cls closure
|
* @param cls closure
|
||||||
* @param wtid wire transfer identifier, NULL
|
* @param wtid wire transfer identifier, NULL
|
||||||
* if the transaction was not yet done
|
* if the transaction was not yet done
|
||||||
* @param coin_contribution how much did the coin we asked about
|
* @param coin_contribution how much did the coin we asked about
|
||||||
* contribute to the total transfer value? (deposit value minus fee)
|
* contribute to the total transfer value? (deposit value including fee)
|
||||||
|
* @param coin_fee how much did the mint charge for the deposit fee
|
||||||
* @param total_amount how much was the total wire transfer?
|
* @param total_amount how much was the total wire transfer?
|
||||||
* @param execution_time when was the transaction done, or
|
* @param execution_time when was the transaction done, or
|
||||||
* when we expect it to be done (if @a wtid was NULL);
|
* when we expect it to be done (if @a wtid was NULL)
|
||||||
* #GNUNET_TIME_UNIT_FOREVER_ABS if the /deposit is unknown
|
|
||||||
* to the mint
|
|
||||||
*/
|
*/
|
||||||
typedef void
|
typedef void
|
||||||
(*TALER_MINTDB_DepositWtidCallback)(void *cls,
|
(*TALER_MINTDB_DepositWtidCallback)(void *cls,
|
||||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
const struct TALER_Amount *coin_contribution,
|
const struct TALER_Amount *coin_contribution,
|
||||||
|
const struct TALER_Amount *coin_fee,
|
||||||
const struct TALER_Amount *total_amount,
|
const struct TALER_Amount *total_amount,
|
||||||
struct GNUNET_TIME_Absolute execution_time);
|
struct GNUNET_TIME_Absolute execution_time);
|
||||||
|
|
||||||
@ -601,18 +602,20 @@ typedef void
|
|||||||
* @param h_contract which contract was this payment about
|
* @param h_contract which contract was this payment about
|
||||||
* @param transaction_id merchant's transaction ID for the payment
|
* @param transaction_id merchant's transaction ID for the payment
|
||||||
* @param coin_pub which public key was this payment about
|
* @param coin_pub which public key was this payment about
|
||||||
* @param deposit_value amount contributed by this coin in total
|
* @param coin_value amount contributed by this coin in total (with fee)
|
||||||
* @param deposit_fee deposit fee charged by mint for this coin
|
* @param coin_fee applicable fee for this coin
|
||||||
|
* @param transfer_value total amount of the wire transfer
|
||||||
*/
|
*/
|
||||||
typedef void
|
typedef void
|
||||||
(*TALER_MINTDB_TransactionDataCallback)(void *cls,
|
(*TALER_MINTDB_WireTransferDataCallback)(void *cls,
|
||||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
const struct GNUNET_HashCode *h_wire,
|
const struct GNUNET_HashCode *h_wire,
|
||||||
const struct GNUNET_HashCode *h_contract,
|
const struct GNUNET_HashCode *h_contract,
|
||||||
uint64_t transaction_id,
|
uint64_t transaction_id,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
const struct TALER_Amount *deposit_value,
|
const struct TALER_Amount *coin_value,
|
||||||
const struct TALER_Amount *deposit_fee);
|
const struct TALER_Amount *coin_fee,
|
||||||
|
const struct TALER_Amount *transfer_value);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1229,15 +1232,18 @@ struct TALER_MINTDB_Plugin
|
|||||||
* into a wire transfer by the respective @a raw_wtid.
|
* into a wire transfer by the respective @a raw_wtid.
|
||||||
*
|
*
|
||||||
* @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 wtid the raw wire transfer identifier we used
|
* @param wtid the raw wire transfer identifier we used
|
||||||
* @param cb function to call on each transaction found
|
* @param cb function to call on each transaction found
|
||||||
* @param cb_cls closure for @a cb
|
* @param cb_cls closure for @a cb
|
||||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors,
|
||||||
|
* #GNUNET_NO if we found no results
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
(*lookup_wire_transactions) (void *cls,
|
(*lookup_wire_transfer) (void *cls,
|
||||||
|
struct TALER_MINTDB_Session *session,
|
||||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
TALER_MINTDB_TransactionDataCallback cb,
|
TALER_MINTDB_WireTransferDataCallback cb,
|
||||||
void *cb_cls);
|
void *cb_cls);
|
||||||
|
|
||||||
|
|
||||||
@ -1247,6 +1253,7 @@ struct TALER_MINTDB_Plugin
|
|||||||
* to be executed.
|
* to be executed.
|
||||||
*
|
*
|
||||||
* @param cls closure
|
* @param cls closure
|
||||||
|
* @param session database connection
|
||||||
* @param h_contract hash of the contract
|
* @param h_contract hash of the contract
|
||||||
* @param h_wire hash of merchant wire details
|
* @param h_wire hash of merchant wire details
|
||||||
* @param coin_pub public key of deposited coin
|
* @param coin_pub public key of deposited coin
|
||||||
@ -1254,10 +1261,12 @@ struct TALER_MINTDB_Plugin
|
|||||||
* @param transaction_id transaction identifier
|
* @param transaction_id transaction identifier
|
||||||
* @param cb function to call with the result
|
* @param cb function to call with the result
|
||||||
* @param cb_cls closure to pass to @a cb
|
* @param cb_cls closure to pass to @a cb
|
||||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors,
|
||||||
|
* #GNUNET_NO if nothing was found
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
(*wire_lookup_deposit_wtid)(void *cls,
|
(*wire_lookup_deposit_wtid)(void *cls,
|
||||||
|
struct TALER_MINTDB_Session *session,
|
||||||
const struct GNUNET_HashCode *h_contract,
|
const struct GNUNET_HashCode *h_contract,
|
||||||
const struct GNUNET_HashCode *h_wire,
|
const struct GNUNET_HashCode *h_wire,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
@ -1271,26 +1280,32 @@ struct TALER_MINTDB_Plugin
|
|||||||
* Function called to insert aggregation information into the DB.
|
* Function called to insert aggregation information into the DB.
|
||||||
*
|
*
|
||||||
* @param cls closure
|
* @param cls closure
|
||||||
|
* @param session database connection
|
||||||
* @param wtid the raw wire transfer identifier we used
|
* @param wtid the raw wire transfer identifier we used
|
||||||
* @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls)
|
* @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls)
|
||||||
* @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls)
|
* @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls)
|
||||||
* @param h_contract which contract was this payment about
|
* @param h_contract which contract was this payment about
|
||||||
* @param transaction_id merchant's transaction ID for the payment
|
* @param transaction_id merchant's transaction ID for the payment
|
||||||
|
* @param execution_time when did we execute the transaction
|
||||||
* @param coin_pub which public key was this payment about
|
* @param coin_pub which public key was this payment about
|
||||||
* @param deposit_value amount contributed by this coin in total
|
* @param coin_value amount contributed by this coin in total
|
||||||
* @param deposit_fee deposit fee charged by mint for this coin
|
* @param coin_fee deposit fee charged by mint for this coin
|
||||||
|
* @param transfer_value total amount of the wire transfer
|
||||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
(*insert_aggregation_tracking)(void *cls,
|
(*insert_aggregation_tracking)(void *cls,
|
||||||
|
struct TALER_MINTDB_Session *session,
|
||||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
const struct GNUNET_HashCode *h_wire,
|
const struct GNUNET_HashCode *h_wire,
|
||||||
const struct GNUNET_HashCode *h_contract,
|
const struct GNUNET_HashCode *h_contract,
|
||||||
uint64_t transaction_id,
|
uint64_t transaction_id,
|
||||||
|
struct GNUNET_TIME_Absolute execution_time,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
const struct TALER_Amount *deposit_value,
|
const struct TALER_Amount *coin_value,
|
||||||
const struct TALER_Amount *deposit_fee);
|
const struct TALER_Amount *coin_fee,
|
||||||
|
const struct TALER_Amount *transfer_value);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -20,10 +20,12 @@ libtalermint_la_SOURCES = \
|
|||||||
mint_api_handle.c mint_api_handle.h \
|
mint_api_handle.c mint_api_handle.h \
|
||||||
mint_api_admin.c \
|
mint_api_admin.c \
|
||||||
mint_api_deposit.c \
|
mint_api_deposit.c \
|
||||||
|
mint_api_deposit_wtid.c \
|
||||||
mint_api_refresh.c \
|
mint_api_refresh.c \
|
||||||
mint_api_refresh_link.c \
|
mint_api_refresh_link.c \
|
||||||
mint_api_reserve.c \
|
mint_api_reserve.c \
|
||||||
mint_api_wire.c
|
mint_api_wire.c \
|
||||||
|
mint_api_wire_deposits.c
|
||||||
|
|
||||||
libtalermint_la_LIBADD = \
|
libtalermint_la_LIBADD = \
|
||||||
-lgnunetutil \
|
-lgnunetutil \
|
||||||
|
@ -288,7 +288,7 @@ TALER_MINT_perform (struct TALER_MINT_Context *ctx)
|
|||||||
GNUNET_assert (CURLE_OK ==
|
GNUNET_assert (CURLE_OK ==
|
||||||
curl_easy_getinfo (cmsg->easy_handle,
|
curl_easy_getinfo (cmsg->easy_handle,
|
||||||
CURLINFO_PRIVATE,
|
CURLINFO_PRIVATE,
|
||||||
(char *) &job));
|
(char **) &job));
|
||||||
GNUNET_assert (job->ctx == ctx);
|
GNUNET_assert (job->ctx == ctx);
|
||||||
job->jcc (job->jcc_cls,
|
job->jcc (job->jcc_cls,
|
||||||
cmsg->easy_handle);
|
cmsg->easy_handle);
|
||||||
|
386
src/mint-lib/mint_api_deposit_wtid.c
Normal file
386
src/mint-lib/mint_api_deposit_wtid.c
Normal file
@ -0,0 +1,386 @@
|
|||||||
|
/*
|
||||||
|
This file is part of TALER
|
||||||
|
Copyright (C) 2014, 2015, 2016 GNUnet e.V.
|
||||||
|
|
||||||
|
TALER is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
TALER; see the file COPYING. If not, If not, see
|
||||||
|
<http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file mint-lib/mint_api_deposit_wtid.c
|
||||||
|
* @brief Implementation of the /deposit/wtid request of the mint's HTTP API
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*/
|
||||||
|
#include "platform.h"
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <jansson.h>
|
||||||
|
#include <microhttpd.h> /* just for HTTP status codes */
|
||||||
|
#include <gnunet/gnunet_util_lib.h>
|
||||||
|
#include "taler_mint_service.h"
|
||||||
|
#include "mint_api_common.h"
|
||||||
|
#include "mint_api_json.h"
|
||||||
|
#include "mint_api_context.h"
|
||||||
|
#include "mint_api_handle.h"
|
||||||
|
#include "taler_signatures.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A Deposit Wtid Handle
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_DepositWtidHandle
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connection to mint this request handle will use
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_Handle *mint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The url for this request.
|
||||||
|
*/
|
||||||
|
char *url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON encoding of the request to POST.
|
||||||
|
*/
|
||||||
|
char *json_enc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for the request.
|
||||||
|
*/
|
||||||
|
struct MAC_Job *job;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to call with the result.
|
||||||
|
*/
|
||||||
|
TALER_MINT_DepositWtidCallback cb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure for @a cb.
|
||||||
|
*/
|
||||||
|
void *cb_cls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download buffer
|
||||||
|
*/
|
||||||
|
struct MAC_DownloadBuffer db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information the mint should sign in response.
|
||||||
|
* (with pre-filled fields from the request).
|
||||||
|
*/
|
||||||
|
struct TALER_ConfirmWirePS depconf;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that the signature on the "200 OK" response
|
||||||
|
* from the mint is valid.
|
||||||
|
*
|
||||||
|
* @param dwh deposit wtid handle
|
||||||
|
* @param json json reply with the signature
|
||||||
|
* @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
verify_deposit_wtid_signature_ok (const struct TALER_MINT_DepositWtidHandle *dwh,
|
||||||
|
json_t *json)
|
||||||
|
{
|
||||||
|
struct TALER_MintSignatureP mint_sig;
|
||||||
|
struct TALER_MintPublicKeyP mint_pub;
|
||||||
|
const struct TALER_MINT_Keys *key_state;
|
||||||
|
struct MAJ_Specification spec[] = {
|
||||||
|
MAJ_spec_fixed_auto ("mint_sig", &mint_sig),
|
||||||
|
MAJ_spec_fixed_auto ("mint_pub", &mint_pub),
|
||||||
|
MAJ_spec_end
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
MAJ_parse_json (json,
|
||||||
|
spec))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
key_state = TALER_MINT_get_keys (dwh->mint);
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
TALER_MINT_test_signing_key (key_state,
|
||||||
|
&mint_pub))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_CONFIRM_WIRE,
|
||||||
|
&dwh->depconf.purpose,
|
||||||
|
&mint_sig.eddsa_signature,
|
||||||
|
&mint_pub.eddsa_pub))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called when we're done processing the
|
||||||
|
* HTTP /deposit/wtid request.
|
||||||
|
*
|
||||||
|
* @param cls the `struct TALER_MINT_DepositWtidHandle`
|
||||||
|
* @param eh the curl request handle
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
handle_deposit_wtid_finished (void *cls,
|
||||||
|
CURL *eh)
|
||||||
|
{
|
||||||
|
struct TALER_MINT_DepositWtidHandle *dwh = cls;
|
||||||
|
long response_code;
|
||||||
|
json_t *json;
|
||||||
|
const struct TALER_WireTransferIdentifierRawP *wtid = NULL;
|
||||||
|
struct GNUNET_TIME_Absolute execution_time = GNUNET_TIME_UNIT_FOREVER_ABS;
|
||||||
|
const struct TALER_Amount *coin_contribution = NULL;
|
||||||
|
const struct TALER_Amount *total_amount = NULL;
|
||||||
|
struct TALER_Amount coin_contribution_s;
|
||||||
|
struct TALER_Amount total_amount_s;
|
||||||
|
|
||||||
|
dwh->job = NULL;
|
||||||
|
json = MAC_download_get_result (&dwh->db,
|
||||||
|
eh,
|
||||||
|
&response_code);
|
||||||
|
switch (response_code)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_OK:
|
||||||
|
{
|
||||||
|
struct MAJ_Specification spec[] = {
|
||||||
|
MAJ_spec_fixed_auto ("wtid", &dwh->depconf.wtid),
|
||||||
|
MAJ_spec_absolute_time ("execution_time", &execution_time),
|
||||||
|
MAJ_spec_amount ("coin_contribution", &coin_contribution_s),
|
||||||
|
MAJ_spec_amount ("total_amount", &total_amount_s),
|
||||||
|
MAJ_spec_end
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
MAJ_parse_json (json,
|
||||||
|
spec))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
response_code = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wtid = &dwh->depconf.wtid;
|
||||||
|
dwh->depconf.execution_time = GNUNET_TIME_absolute_hton (execution_time);
|
||||||
|
TALER_amount_hton (&dwh->depconf.coin_contribution,
|
||||||
|
&coin_contribution_s);
|
||||||
|
coin_contribution = &coin_contribution_s;
|
||||||
|
TALER_amount_hton (&dwh->depconf.total_amount,
|
||||||
|
&total_amount_s);
|
||||||
|
total_amount = &total_amount_s;
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
verify_deposit_wtid_signature_ok (dwh,
|
||||||
|
json))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
response_code = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_ACCEPTED:
|
||||||
|
{
|
||||||
|
/* Transaction known, but not executed yet */
|
||||||
|
struct MAJ_Specification spec[] = {
|
||||||
|
MAJ_spec_absolute_time ("execution_time", &execution_time),
|
||||||
|
MAJ_spec_end
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
MAJ_parse_json (json,
|
||||||
|
spec))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
response_code = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_BAD_REQUEST:
|
||||||
|
/* This should never happen, either us or the mint is buggy
|
||||||
|
(or API version conflict); just pass JSON reply to the application */
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_UNAUTHORIZED:
|
||||||
|
/* Nothing really to verify, mint says one of the signatures is
|
||||||
|
invalid; as we checked them, this should never happen, we
|
||||||
|
should pass the JSON reply to the application */
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_NOT_FOUND:
|
||||||
|
/* Mint does not know about transaction;
|
||||||
|
we should pass the reply to the application */
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_INTERNAL_SERVER_ERROR:
|
||||||
|
/* Server had an internal issue; we should retry, but this API
|
||||||
|
leaves this to the application */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* unexpected response code */
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Unexpected response code %u\n",
|
||||||
|
response_code);
|
||||||
|
GNUNET_break (0);
|
||||||
|
response_code = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dwh->cb (dwh->cb_cls,
|
||||||
|
response_code,
|
||||||
|
json,
|
||||||
|
wtid,
|
||||||
|
execution_time,
|
||||||
|
coin_contribution,
|
||||||
|
total_amount);
|
||||||
|
json_decref (json);
|
||||||
|
TALER_MINT_deposit_wtid_cancel (dwh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain wire transfer details about an existing deposit operation.
|
||||||
|
*
|
||||||
|
* @param mint the mint to query
|
||||||
|
* @param merchant_priv the merchant's private key
|
||||||
|
* @param h_wire hash of merchant's wire transfer details
|
||||||
|
* @param h_contract hash of the contract
|
||||||
|
* @param coin_pub public key of the coin
|
||||||
|
* @param transaction_id transaction identifier
|
||||||
|
* @param cb function to call with the result
|
||||||
|
* @param cb_cls closure for @a cb
|
||||||
|
* @return handle to abort request
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_DepositWtidHandle *
|
||||||
|
TALER_MINT_deposit_wtid (struct TALER_MINT_Handle *mint,
|
||||||
|
const struct TALER_MerchantPrivateKeyP *merchant_priv,
|
||||||
|
const struct GNUNET_HashCode *h_wire,
|
||||||
|
const struct GNUNET_HashCode *h_contract,
|
||||||
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
|
uint64_t transaction_id,
|
||||||
|
TALER_MINT_DepositWtidCallback cb,
|
||||||
|
void *cb_cls)
|
||||||
|
{
|
||||||
|
struct TALER_DepositTrackPS dtp;
|
||||||
|
struct TALER_MerchantSignatureP merchant_sig;
|
||||||
|
struct TALER_MINT_DepositWtidHandle *dwh;
|
||||||
|
struct TALER_MINT_Context *ctx;
|
||||||
|
json_t *deposit_wtid_obj;
|
||||||
|
CURL *eh;
|
||||||
|
|
||||||
|
if (GNUNET_YES !=
|
||||||
|
MAH_handle_is_ready (mint))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dtp.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_DEPOSIT_WTID);
|
||||||
|
dtp.purpose.size = htonl (sizeof (dtp));
|
||||||
|
dtp.h_contract = *h_contract;
|
||||||
|
dtp.h_wire = *h_wire;
|
||||||
|
dtp.transaction_id = GNUNET_htonll (transaction_id);
|
||||||
|
GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv,
|
||||||
|
&dtp.merchant.eddsa_pub);
|
||||||
|
|
||||||
|
dtp.coin_pub = *coin_pub;
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv,
|
||||||
|
&dtp.purpose,
|
||||||
|
&merchant_sig.eddsa_sig));
|
||||||
|
deposit_wtid_obj = json_pack ("{s:o, s:o," /* H_wire, H_contract */
|
||||||
|
" s:o, s:I," /* coin_pub, transaction_id */
|
||||||
|
" s:o, s:o}", /* merchant_pub, merchant_sig */
|
||||||
|
"H_wire", TALER_json_from_data (h_wire,
|
||||||
|
sizeof (struct GNUNET_HashCode)),
|
||||||
|
"H_contract", TALER_json_from_data (h_contract,
|
||||||
|
sizeof (struct GNUNET_HashCode)),
|
||||||
|
"coin_pub", TALER_json_from_data (coin_pub,
|
||||||
|
sizeof (*coin_pub)),
|
||||||
|
"transaction_id", (json_int_t) transaction_id,
|
||||||
|
"merchant_pub", TALER_json_from_data (&dtp.merchant,
|
||||||
|
sizeof (struct TALER_MerchantPublicKeyP)),
|
||||||
|
"merchant_sig", TALER_json_from_data (&merchant_sig,
|
||||||
|
sizeof (merchant_sig)));
|
||||||
|
|
||||||
|
dwh = GNUNET_new (struct TALER_MINT_DepositWtidHandle);
|
||||||
|
dwh->mint = mint;
|
||||||
|
dwh->cb = cb;
|
||||||
|
dwh->cb_cls = cb_cls;
|
||||||
|
dwh->url = MAH_path_to_url (mint, "/deposit/wtid");
|
||||||
|
dwh->depconf.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS));
|
||||||
|
dwh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_WIRE);
|
||||||
|
dwh->depconf.h_wire = *h_wire;
|
||||||
|
dwh->depconf.h_contract = *h_contract;
|
||||||
|
dwh->depconf.coin_pub = *coin_pub;
|
||||||
|
dwh->depconf.transaction_id = GNUNET_htonll (transaction_id);
|
||||||
|
|
||||||
|
eh = curl_easy_init ();
|
||||||
|
GNUNET_assert (NULL != (dwh->json_enc =
|
||||||
|
json_dumps (deposit_wtid_obj,
|
||||||
|
JSON_COMPACT)));
|
||||||
|
json_decref (deposit_wtid_obj);
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_URL,
|
||||||
|
dwh->url));
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_POSTFIELDS,
|
||||||
|
dwh->json_enc));
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_POSTFIELDSIZE,
|
||||||
|
strlen (dwh->json_enc)));
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_WRITEFUNCTION,
|
||||||
|
&MAC_download_cb));
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_WRITEDATA,
|
||||||
|
&dwh->db));
|
||||||
|
ctx = MAH_handle_to_context (mint);
|
||||||
|
dwh->job = MAC_job_add (ctx,
|
||||||
|
eh,
|
||||||
|
GNUNET_YES,
|
||||||
|
&handle_deposit_wtid_finished,
|
||||||
|
dwh);
|
||||||
|
return dwh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel deposit wtid request. This function cannot be used on a request
|
||||||
|
* handle if a response is already served for it.
|
||||||
|
*
|
||||||
|
* @param dwh the wire deposits request handle
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TALER_MINT_deposit_wtid_cancel (struct TALER_MINT_DepositWtidHandle *dwh)
|
||||||
|
{
|
||||||
|
if (NULL != dwh->job)
|
||||||
|
{
|
||||||
|
MAC_job_cancel (dwh->job);
|
||||||
|
dwh->job = NULL;
|
||||||
|
}
|
||||||
|
GNUNET_free_non_null (dwh->db.buf);
|
||||||
|
GNUNET_free (dwh->url);
|
||||||
|
GNUNET_free (dwh->json_enc);
|
||||||
|
GNUNET_free (dwh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* end of mint_api_deposit_wtid.c */
|
@ -757,7 +757,7 @@ TALER_MINT_connect (struct TALER_MINT_Context *ctx,
|
|||||||
GNUNET_assert (CURLE_OK ==
|
GNUNET_assert (CURLE_OK ==
|
||||||
curl_easy_setopt (c,
|
curl_easy_setopt (c,
|
||||||
CURLOPT_VERBOSE,
|
CURLOPT_VERBOSE,
|
||||||
1));
|
0));
|
||||||
GNUNET_assert (CURLE_OK ==
|
GNUNET_assert (CURLE_OK ==
|
||||||
curl_easy_setopt (c,
|
curl_easy_setopt (c,
|
||||||
CURLOPT_STDERR,
|
CURLOPT_STDERR,
|
||||||
|
@ -232,6 +232,20 @@ parse_json (json_t *root,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MAJ_CMD_UINT64:
|
||||||
|
{
|
||||||
|
json_int_t val;
|
||||||
|
|
||||||
|
if (! json_is_integer (pos))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
val = json_integer_value (pos);
|
||||||
|
*spec[i].details.u64 = (uint64_t) val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case MAJ_CMD_JSON_OBJECT:
|
case MAJ_CMD_JSON_OBJECT:
|
||||||
{
|
{
|
||||||
if (! (json_is_object (pos) || json_is_array (pos)) )
|
if (! (json_is_object (pos) || json_is_array (pos)) )
|
||||||
@ -428,6 +442,26 @@ MAJ_spec_uint16 (const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 64-bit integer.
|
||||||
|
*
|
||||||
|
* @param name name of the JSON field
|
||||||
|
* @param[out] u64 where to store the integer found under @a name
|
||||||
|
*/
|
||||||
|
struct MAJ_Specification
|
||||||
|
MAJ_spec_uint64 (const char *name,
|
||||||
|
uint64_t *u64)
|
||||||
|
{
|
||||||
|
struct MAJ_Specification ret =
|
||||||
|
{
|
||||||
|
.cmd = MAJ_CMD_UINT64,
|
||||||
|
.field = name,
|
||||||
|
.details.u64 = u64
|
||||||
|
};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON object.
|
* JSON object.
|
||||||
*
|
*
|
||||||
|
@ -78,6 +78,11 @@ enum MAJ_Command
|
|||||||
*/
|
*/
|
||||||
MAJ_CMD_UINT16,
|
MAJ_CMD_UINT16,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse `uint64_t` integer at the current position.
|
||||||
|
*/
|
||||||
|
MAJ_CMD_UINT64,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse JSON object at the current position.
|
* Parse JSON object at the current position.
|
||||||
*/
|
*/
|
||||||
@ -191,6 +196,11 @@ struct MAJ_Specification
|
|||||||
*/
|
*/
|
||||||
uint16_t *u16;
|
uint16_t *u16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where to store 64-bit integer.
|
||||||
|
*/
|
||||||
|
uint64_t *u64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Where to store a JSON object.
|
* Where to store a JSON object.
|
||||||
*/
|
*/
|
||||||
@ -282,6 +292,17 @@ MAJ_spec_uint16 (const char *name,
|
|||||||
uint16_t *u16);
|
uint16_t *u16);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 64-bit integer.
|
||||||
|
*
|
||||||
|
* @param name name of the JSON field
|
||||||
|
* @param[out] u64 where to store the integer found under @a name
|
||||||
|
*/
|
||||||
|
struct MAJ_Specification
|
||||||
|
MAJ_spec_uint64 (const char *name,
|
||||||
|
uint64_t *u64);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON object.
|
* JSON object.
|
||||||
*
|
*
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2015 GNUnet e.V.
|
Copyright (C) 2015, 2016 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 General Public License as published by the Free Software
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -185,6 +185,17 @@ parse_refresh_link_ok (struct TALER_MINT_RefreshLinkHandle *rlh,
|
|||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
num_coins = 0;
|
num_coins = 0;
|
||||||
|
/* Theoretically, a coin may have been melted repeatedly
|
||||||
|
into different sessions; so the response is an array
|
||||||
|
which contains information by melting session. That
|
||||||
|
array contains another array. However, our API returns
|
||||||
|
a single 1d array, so we flatten the 2d array that is
|
||||||
|
returned into a single array. Note that usually a coin
|
||||||
|
is melted at most once, and so we'll only run this
|
||||||
|
loop once for 'session=0' in most cases.
|
||||||
|
|
||||||
|
num_coins tracks the size of the 1d array we return,
|
||||||
|
whilst 'i' and 'session' track the 2d array. */
|
||||||
for (session=0;session<json_array_size (json); session++)
|
for (session=0;session<json_array_size (json); session++)
|
||||||
{
|
{
|
||||||
json_t *jsona;
|
json_t *jsona;
|
||||||
@ -212,13 +223,17 @@ parse_refresh_link_ok (struct TALER_MINT_RefreshLinkHandle *rlh,
|
|||||||
num_coins += json_array_size (jsona);
|
num_coins += json_array_size (jsona);
|
||||||
MAJ_parse_free (spec);
|
MAJ_parse_free (spec);
|
||||||
}
|
}
|
||||||
|
/* Now that we know how big the 1d array is, allocate
|
||||||
|
and fill it. */
|
||||||
{
|
{
|
||||||
unsigned int off_coin;
|
unsigned int off_coin; /* index into 1d array */
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct TALER_CoinSpendPrivateKeyP coin_privs[num_coins];
|
struct TALER_CoinSpendPrivateKeyP coin_privs[num_coins];
|
||||||
struct TALER_DenominationSignature sigs[num_coins];
|
struct TALER_DenominationSignature sigs[num_coins];
|
||||||
struct TALER_DenominationPublicKey pubs[num_coins];
|
struct TALER_DenominationPublicKey pubs[num_coins];
|
||||||
|
|
||||||
|
memset (sigs, 0, sizeof (sigs));
|
||||||
|
memset (pubs, 0, sizeof (pubs));
|
||||||
off_coin = 0;
|
off_coin = 0;
|
||||||
for (session=0;session<json_array_size (json); session++)
|
for (session=0;session<json_array_size (json); session++)
|
||||||
{
|
{
|
||||||
@ -265,6 +280,7 @@ parse_refresh_link_ok (struct TALER_MINT_RefreshLinkHandle *rlh,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* check if we really got all, then invoke callback */
|
/* check if we really got all, then invoke callback */
|
||||||
|
off_coin += i;
|
||||||
if (i != json_array_size (jsona))
|
if (i != json_array_size (jsona))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
@ -272,7 +288,6 @@ parse_refresh_link_ok (struct TALER_MINT_RefreshLinkHandle *rlh,
|
|||||||
MAJ_parse_free (spec);
|
MAJ_parse_free (spec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
off_coin += json_array_size (jsona);
|
|
||||||
MAJ_parse_free (spec);
|
MAJ_parse_free (spec);
|
||||||
} /* end of for (session) */
|
} /* end of for (session) */
|
||||||
|
|
||||||
@ -295,9 +310,13 @@ parse_refresh_link_ok (struct TALER_MINT_RefreshLinkHandle *rlh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* clean up */
|
/* clean up */
|
||||||
for (i=0;i<num_coins;i++)
|
for (i=0;i<off_coin;i++)
|
||||||
|
{
|
||||||
if (NULL != sigs[i].rsa_signature)
|
if (NULL != sigs[i].rsa_signature)
|
||||||
GNUNET_CRYPTO_rsa_signature_free (sigs[i].rsa_signature);
|
GNUNET_CRYPTO_rsa_signature_free (sigs[i].rsa_signature);
|
||||||
|
if (NULL != pubs[i].rsa_public_key)
|
||||||
|
GNUNET_CRYPTO_rsa_public_key_free (pubs[i].rsa_public_key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
284
src/mint-lib/mint_api_wire_deposits.c
Normal file
284
src/mint-lib/mint_api_wire_deposits.c
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
/*
|
||||||
|
This file is part of TALER
|
||||||
|
Copyright (C) 2014, 2015, 2016 GNUnet e.V.
|
||||||
|
|
||||||
|
TALER is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
TALER; see the file COPYING. If not, If not, see
|
||||||
|
<http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file mint-lib/mint_api_wire_deposits.c
|
||||||
|
* @brief Implementation of the /wire/deposits request of the mint's HTTP API
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*/
|
||||||
|
#include "platform.h"
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <jansson.h>
|
||||||
|
#include <microhttpd.h> /* just for HTTP status codes */
|
||||||
|
#include <gnunet/gnunet_util_lib.h>
|
||||||
|
#include "taler_mint_service.h"
|
||||||
|
#include "mint_api_common.h"
|
||||||
|
#include "mint_api_json.h"
|
||||||
|
#include "mint_api_context.h"
|
||||||
|
#include "mint_api_handle.h"
|
||||||
|
#include "taler_signatures.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A /wire/deposits Handle
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_WireDepositsHandle
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connection to mint this request handle will use
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_Handle *mint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The url for this request.
|
||||||
|
*/
|
||||||
|
char *url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for the request.
|
||||||
|
*/
|
||||||
|
struct MAC_Job *job;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to call with the result.
|
||||||
|
*/
|
||||||
|
TALER_MINT_WireDepositsCallback cb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure for @a cb.
|
||||||
|
*/
|
||||||
|
void *cb_cls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download buffer
|
||||||
|
*/
|
||||||
|
struct MAC_DownloadBuffer db;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called when we're done processing the
|
||||||
|
* HTTP /wire/deposits request.
|
||||||
|
*
|
||||||
|
* @param cls the `struct TALER_MINT_WireDepositsHandle`
|
||||||
|
* @param eh the curl request handle
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
handle_wire_deposits_finished (void *cls,
|
||||||
|
CURL *eh)
|
||||||
|
{
|
||||||
|
struct TALER_MINT_WireDepositsHandle *wdh = cls;
|
||||||
|
long response_code;
|
||||||
|
json_t *json;
|
||||||
|
|
||||||
|
wdh->job = NULL;
|
||||||
|
json = MAC_download_get_result (&wdh->db,
|
||||||
|
eh,
|
||||||
|
&response_code);
|
||||||
|
switch (response_code)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_OK:
|
||||||
|
{
|
||||||
|
json_t *details_j;
|
||||||
|
struct GNUNET_HashCode h_wire;
|
||||||
|
struct TALER_Amount total_amount;
|
||||||
|
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||||
|
unsigned int num_details;
|
||||||
|
struct MAJ_Specification spec[] = {
|
||||||
|
MAJ_spec_fixed_auto ("H_wire", &h_wire),
|
||||||
|
MAJ_spec_fixed_auto ("merchant_pub", &merchant_pub),
|
||||||
|
MAJ_spec_amount ("total_amount", &total_amount),
|
||||||
|
MAJ_spec_json ("details", &details_j),
|
||||||
|
MAJ_spec_end
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
MAJ_parse_json (json,
|
||||||
|
spec))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
response_code = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
num_details = json_array_size (details_j);
|
||||||
|
{
|
||||||
|
struct TALER_WireDepositDetails details[num_details];
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i=0;i<num_details;i++)
|
||||||
|
{
|
||||||
|
struct TALER_WireDepositDetails *detail = &details[i];
|
||||||
|
struct json_t *detail_j = json_array_get (details_j, i);
|
||||||
|
struct MAJ_Specification spec_detail[] = {
|
||||||
|
MAJ_spec_fixed_auto ("H_contract", &detail->h_contract),
|
||||||
|
MAJ_spec_amount ("deposit_value", &detail->coin_value),
|
||||||
|
MAJ_spec_amount ("deposit_fee", &detail->coin_fee),
|
||||||
|
MAJ_spec_uint64 ("transaction_id", &detail->transaction_id),
|
||||||
|
MAJ_spec_fixed_auto ("coin_pub", &detail->coin_pub),
|
||||||
|
MAJ_spec_end
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
MAJ_parse_json (detail_j,
|
||||||
|
spec_detail))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
response_code = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 == response_code)
|
||||||
|
break;
|
||||||
|
wdh->cb (wdh->cb_cls,
|
||||||
|
response_code,
|
||||||
|
json,
|
||||||
|
&h_wire,
|
||||||
|
&total_amount,
|
||||||
|
num_details,
|
||||||
|
details);
|
||||||
|
json_decref (json);
|
||||||
|
TALER_MINT_wire_deposits_cancel (wdh);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_BAD_REQUEST:
|
||||||
|
/* This should never happen, either us or the mint is buggy
|
||||||
|
(or API version conflict); just pass JSON reply to the application */
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_UNAUTHORIZED:
|
||||||
|
/* Nothing really to verify, mint says one of the signatures is
|
||||||
|
invalid; as we checked them, this should never happen, we
|
||||||
|
should pass the JSON reply to the application */
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_NOT_FOUND:
|
||||||
|
/* Mint does not know about transaction;
|
||||||
|
we should pass the reply to the application */
|
||||||
|
break;
|
||||||
|
case MHD_HTTP_INTERNAL_SERVER_ERROR:
|
||||||
|
/* Server had an internal issue; we should retry, but this API
|
||||||
|
leaves this to the application */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* unexpected response code */
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Unexpected response code %u\n",
|
||||||
|
response_code);
|
||||||
|
GNUNET_break (0);
|
||||||
|
response_code = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wdh->cb (wdh->cb_cls,
|
||||||
|
response_code,
|
||||||
|
json,
|
||||||
|
NULL, NULL, 0, NULL);
|
||||||
|
json_decref (json);
|
||||||
|
TALER_MINT_wire_deposits_cancel (wdh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the mint about which transactions were combined
|
||||||
|
* to create a wire transfer.
|
||||||
|
*
|
||||||
|
* @param mint mint to query
|
||||||
|
* @param wtid raw wire transfer identifier to get information about
|
||||||
|
* @param cb callback to call
|
||||||
|
* @param cb_cls closure for @a cb
|
||||||
|
* @return handle to cancel operation
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_WireDepositsHandle *
|
||||||
|
TALER_MINT_wire_deposits (struct TALER_MINT_Handle *mint,
|
||||||
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
|
TALER_MINT_WireDepositsCallback cb,
|
||||||
|
void *cb_cls)
|
||||||
|
{
|
||||||
|
struct TALER_MINT_WireDepositsHandle *wdh;
|
||||||
|
struct TALER_MINT_Context *ctx;
|
||||||
|
char *buf;
|
||||||
|
char *path;
|
||||||
|
CURL *eh;
|
||||||
|
|
||||||
|
if (GNUNET_YES !=
|
||||||
|
MAH_handle_is_ready (mint))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wdh = GNUNET_new (struct TALER_MINT_WireDepositsHandle);
|
||||||
|
wdh->mint = mint;
|
||||||
|
wdh->cb = cb;
|
||||||
|
wdh->cb_cls = cb_cls;
|
||||||
|
|
||||||
|
buf = GNUNET_STRINGS_data_to_string_alloc (wtid,
|
||||||
|
sizeof (struct TALER_WireTransferIdentifierRawP));
|
||||||
|
GNUNET_asprintf (&path,
|
||||||
|
"/wire/deposits?wtid=%s",
|
||||||
|
buf);
|
||||||
|
wdh->url = MAH_path_to_url (wdh->mint,
|
||||||
|
path);
|
||||||
|
GNUNET_free (buf);
|
||||||
|
GNUNET_free (path);
|
||||||
|
|
||||||
|
eh = curl_easy_init ();
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_URL,
|
||||||
|
wdh->url));
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_WRITEFUNCTION,
|
||||||
|
&MAC_download_cb));
|
||||||
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_WRITEDATA,
|
||||||
|
&wdh->db));
|
||||||
|
ctx = MAH_handle_to_context (mint);
|
||||||
|
wdh->job = MAC_job_add (ctx,
|
||||||
|
eh,
|
||||||
|
GNUNET_YES,
|
||||||
|
&handle_wire_deposits_finished,
|
||||||
|
wdh);
|
||||||
|
return wdh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel wire deposits request. This function cannot be used on a request
|
||||||
|
* handle if a response is already served for it.
|
||||||
|
*
|
||||||
|
* @param wdh the wire deposits request handle
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TALER_MINT_wire_deposits_cancel (struct TALER_MINT_WireDepositsHandle *wdh)
|
||||||
|
{
|
||||||
|
if (NULL != wdh->job)
|
||||||
|
{
|
||||||
|
MAC_job_cancel (wdh->job);
|
||||||
|
wdh->job = NULL;
|
||||||
|
}
|
||||||
|
GNUNET_free_non_null (wdh->db.buf);
|
||||||
|
GNUNET_free (wdh->url);
|
||||||
|
GNUNET_free (wdh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* end of mint_api_wire_deposits.c */
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2014, 2015 GNUnet e.V.
|
Copyright (C) 2014, 2015, 2016 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 General Public License as published by the Free Software
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -111,7 +111,17 @@ enum OpCode
|
|||||||
/**
|
/**
|
||||||
* Verify the mint's /wire-method.
|
* Verify the mint's /wire-method.
|
||||||
*/
|
*/
|
||||||
OC_WIRE
|
OC_WIRE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify mint's /wire/deposits method.
|
||||||
|
*/
|
||||||
|
OC_WIRE_DEPOSITS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify mint's /deposit/wtid method.
|
||||||
|
*/
|
||||||
|
OC_DEPOSIT_WTID
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -470,6 +480,60 @@ struct Command
|
|||||||
|
|
||||||
} wire;
|
} wire;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information for the /wire/deposits's command.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle to the wire deposits request.
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_WireDepositsHandle *wdh;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to a /deposit/wtid command. If set, we use the
|
||||||
|
* WTID from that command.
|
||||||
|
*/
|
||||||
|
const char *wtid_ref;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WTID to use (used if @e wtid_ref is NULL).
|
||||||
|
*/
|
||||||
|
struct TALER_WireTransferIdentifierRawP wtid;
|
||||||
|
|
||||||
|
/* TODO: may want to add list of deposits we expected
|
||||||
|
to see aggregated here in the future. */
|
||||||
|
|
||||||
|
} wire_deposits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information for the /deposit/wtid command.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle to the deposit wtid request.
|
||||||
|
*/
|
||||||
|
struct TALER_MINT_DepositWtidHandle *dwh;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which /deposit operation should we obtain WTID data for?
|
||||||
|
*/
|
||||||
|
const char *deposit_ref;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What is the expected total amount? Only used if
|
||||||
|
* @e expected_response_code was #MHD_HTTP_OK.
|
||||||
|
*/
|
||||||
|
struct TALER_Amount total_amount_expected;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wire transfer identifier, set if #MHD_HTTP_OK was the response code.
|
||||||
|
*/
|
||||||
|
struct TALER_WireTransferIdentifierRawP wtid;
|
||||||
|
|
||||||
|
} deposit_wtid;
|
||||||
|
|
||||||
} details;
|
} details;
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -1219,6 +1283,158 @@ wire_cb (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called with detailed wire transfer data, including all
|
||||||
|
* of the coin transactions that were combined into the wire transfer.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param http_status HTTP status code we got, 0 on mint protocol violation
|
||||||
|
* @param json original json reply (may include signatures, those have then been
|
||||||
|
* validated already)
|
||||||
|
* @param wtid extracted wire transfer identifier, or NULL if the mint could
|
||||||
|
* not provide any (set only if @a http_status is #MHD_HTTP_OK)
|
||||||
|
* @param total_amount total amount of the wire transfer, or NULL if the mint could
|
||||||
|
* not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK)
|
||||||
|
* @param details_length length of the @a details array
|
||||||
|
* @param details array with details about the combined transactions
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
wire_deposits_cb (void *cls,
|
||||||
|
unsigned int http_status,
|
||||||
|
json_t *json,
|
||||||
|
const struct GNUNET_HashCode *h_wire,
|
||||||
|
const struct TALER_Amount *total_amount,
|
||||||
|
unsigned int details_length,
|
||||||
|
const struct TALER_WireDepositDetails *details)
|
||||||
|
{
|
||||||
|
struct InterpreterState *is = cls;
|
||||||
|
struct Command *cmd = &is->commands[is->ip];
|
||||||
|
const struct Command *ref;
|
||||||
|
|
||||||
|
cmd->details.wire_deposits.wdh = NULL;
|
||||||
|
ref = find_command (is,
|
||||||
|
cmd->details.wire_deposits.wtid_ref);
|
||||||
|
if (cmd->expected_response_code != http_status)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Unexpected response code %u to command %s\n",
|
||||||
|
http_status,
|
||||||
|
cmd->label);
|
||||||
|
json_dumpf (json, stderr, 0);
|
||||||
|
fail (is);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (http_status)
|
||||||
|
{
|
||||||
|
case MHD_HTTP_OK:
|
||||||
|
if (0 != TALER_amount_cmp (total_amount,
|
||||||
|
&ref->details.deposit_wtid.total_amount_expected))
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Total amount missmatch to command %s\n",
|
||||||
|
http_status,
|
||||||
|
cmd->label);
|
||||||
|
json_dumpf (json, stderr, 0);
|
||||||
|
fail (is);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (NULL != ref->details.deposit_wtid.deposit_ref)
|
||||||
|
{
|
||||||
|
const struct Command *dep;
|
||||||
|
struct GNUNET_HashCode hw;
|
||||||
|
|
||||||
|
dep = find_command (is,
|
||||||
|
ref->details.deposit_wtid.deposit_ref);
|
||||||
|
GNUNET_CRYPTO_hash (dep->details.deposit.wire_details,
|
||||||
|
strlen (dep->details.deposit.wire_details),
|
||||||
|
&hw);
|
||||||
|
if (0 != memcmp (&hw,
|
||||||
|
h_wire,
|
||||||
|
sizeof (struct GNUNET_HashCode)))
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Wire hash missmatch to command %s\n",
|
||||||
|
cmd->label);
|
||||||
|
json_dumpf (json, stderr, 0);
|
||||||
|
fail (is);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move to next command */
|
||||||
|
is->ip++;
|
||||||
|
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
|
||||||
|
is);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called with detailed wire transfer data.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param http_status HTTP status code we got, 0 on mint protocol violation
|
||||||
|
* @param json original json reply (may include signatures, those have then been
|
||||||
|
* validated already)
|
||||||
|
* @param wtid wire transfer identifier used by the mint, NULL if mint did not
|
||||||
|
* yet execute the transaction
|
||||||
|
* @param execution_time actual or planned execution time for the wire transfer
|
||||||
|
* @param coin_contribution contribution to the @a total_amount of the deposited coin (may be NULL)
|
||||||
|
* @param total_amount total amount of the wire transfer, or NULL if the mint could
|
||||||
|
* not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
deposit_wtid_cb (void *cls,
|
||||||
|
unsigned int http_status,
|
||||||
|
json_t *json,
|
||||||
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
|
struct GNUNET_TIME_Absolute execution_time,
|
||||||
|
const struct TALER_Amount *coin_contribution,
|
||||||
|
const struct TALER_Amount *total_amount)
|
||||||
|
{
|
||||||
|
struct InterpreterState *is = cls;
|
||||||
|
struct Command *cmd = &is->commands[is->ip];
|
||||||
|
|
||||||
|
cmd->details.deposit_wtid.dwh = NULL;
|
||||||
|
if (cmd->expected_response_code != http_status)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Unexpected response code %u to command %s\n",
|
||||||
|
http_status,
|
||||||
|
cmd->label);
|
||||||
|
json_dumpf (json, stderr, 0);
|
||||||
|
fail (is);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (http_status)
|
||||||
|
{
|
||||||
|
case MHD_HTTP_OK:
|
||||||
|
cmd->details.deposit_wtid.wtid = *wtid;
|
||||||
|
if (0 != TALER_amount_cmp (total_amount,
|
||||||
|
&cmd->details.deposit_wtid.total_amount_expected))
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Total amount missmatch to command %s\n",
|
||||||
|
cmd->label);
|
||||||
|
json_dumpf (json, stderr, 0);
|
||||||
|
fail (is);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move to next command */
|
||||||
|
is->ip++;
|
||||||
|
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
|
||||||
|
is);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the main interpreter loop that performs mint operations.
|
* Run the main interpreter loop that performs mint operations.
|
||||||
*
|
*
|
||||||
@ -1401,7 +1617,9 @@ interpreter_run (void *cls,
|
|||||||
struct GNUNET_TIME_Absolute refund_deadline;
|
struct GNUNET_TIME_Absolute refund_deadline;
|
||||||
struct GNUNET_TIME_Absolute wire_deadline;
|
struct GNUNET_TIME_Absolute wire_deadline;
|
||||||
struct GNUNET_TIME_Absolute timestamp;
|
struct GNUNET_TIME_Absolute timestamp;
|
||||||
|
struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
|
||||||
struct TALER_MerchantPublicKeyP merchant_pub;
|
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||||
|
json_t *contract;
|
||||||
json_t *wire;
|
json_t *wire;
|
||||||
|
|
||||||
GNUNET_assert (NULL !=
|
GNUNET_assert (NULL !=
|
||||||
@ -1444,8 +1662,20 @@ interpreter_run (void *cls,
|
|||||||
fail (is);
|
fail (is);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GNUNET_CRYPTO_hash (cmd->details.deposit.contract,
|
contract = json_loads (cmd->details.deposit.contract,
|
||||||
strlen (cmd->details.deposit.contract),
|
JSON_REJECT_DUPLICATES,
|
||||||
|
NULL);
|
||||||
|
if (NULL == contract)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Failed to parse contract details `%s' at %u/%s\n",
|
||||||
|
cmd->details.deposit.contract,
|
||||||
|
is->ip,
|
||||||
|
cmd->label);
|
||||||
|
fail (is);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TALER_hash_json (contract,
|
||||||
&h_contract);
|
&h_contract);
|
||||||
wire = json_loads (cmd->details.deposit.wire_details,
|
wire = json_loads (cmd->details.deposit.wire_details,
|
||||||
JSON_REJECT_DUPLICATES,
|
JSON_REJECT_DUPLICATES,
|
||||||
@ -1453,28 +1683,30 @@ interpreter_run (void *cls,
|
|||||||
if (NULL == wire)
|
if (NULL == wire)
|
||||||
{
|
{
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Failed to parse wire details `%s' at %u\n",
|
"Failed to parse wire details `%s' at %u/%s\n",
|
||||||
cmd->details.deposit.wire_details,
|
cmd->details.deposit.wire_details,
|
||||||
is->ip);
|
is->ip,
|
||||||
|
cmd->label);
|
||||||
fail (is);
|
fail (is);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
|
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
|
||||||
&coin_pub.eddsa_pub);
|
&coin_pub.eddsa_pub);
|
||||||
|
|
||||||
if (0 != cmd->details.deposit.refund_deadline.rel_value_us)
|
|
||||||
{
|
|
||||||
struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
|
|
||||||
|
|
||||||
priv = GNUNET_CRYPTO_eddsa_key_create ();
|
priv = GNUNET_CRYPTO_eddsa_key_create ();
|
||||||
cmd->details.deposit.merchant_priv.eddsa_priv = *priv;
|
cmd->details.deposit.merchant_priv.eddsa_priv = *priv;
|
||||||
GNUNET_free (priv);
|
GNUNET_free (priv);
|
||||||
|
if (0 != cmd->details.deposit.refund_deadline.rel_value_us)
|
||||||
|
{
|
||||||
refund_deadline = GNUNET_TIME_relative_to_absolute (cmd->details.deposit.refund_deadline);
|
refund_deadline = GNUNET_TIME_relative_to_absolute (cmd->details.deposit.refund_deadline);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
refund_deadline = GNUNET_TIME_UNIT_ZERO_ABS;
|
refund_deadline = GNUNET_TIME_UNIT_ZERO_ABS;
|
||||||
}
|
}
|
||||||
|
GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.deposit.merchant_priv.eddsa_priv,
|
||||||
|
&merchant_pub.eddsa_pub);
|
||||||
|
|
||||||
wire_deadline = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS);
|
wire_deadline = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS);
|
||||||
timestamp = GNUNET_TIME_absolute_get ();
|
timestamp = GNUNET_TIME_absolute_get ();
|
||||||
TALER_round_abs_time (×tamp);
|
TALER_round_abs_time (×tamp);
|
||||||
@ -1686,6 +1918,85 @@ interpreter_run (void *cls,
|
|||||||
is);
|
is);
|
||||||
trigger_context_task ();
|
trigger_context_task ();
|
||||||
return;
|
return;
|
||||||
|
case OC_WIRE_DEPOSITS:
|
||||||
|
if (NULL != cmd->details.wire_deposits.wtid_ref)
|
||||||
|
{
|
||||||
|
ref = find_command (is,
|
||||||
|
cmd->details.wire_deposits.wtid_ref);
|
||||||
|
GNUNET_assert (NULL != ref);
|
||||||
|
cmd->details.wire_deposits.wtid = ref->details.deposit_wtid.wtid;
|
||||||
|
}
|
||||||
|
cmd->details.wire_deposits.wdh
|
||||||
|
= TALER_MINT_wire_deposits (mint,
|
||||||
|
&cmd->details.wire_deposits.wtid,
|
||||||
|
&wire_deposits_cb,
|
||||||
|
is);
|
||||||
|
trigger_context_task ();
|
||||||
|
return;
|
||||||
|
case OC_DEPOSIT_WTID:
|
||||||
|
{
|
||||||
|
struct GNUNET_HashCode h_wire;
|
||||||
|
struct GNUNET_HashCode h_contract;
|
||||||
|
json_t *wire;
|
||||||
|
json_t *contract;
|
||||||
|
const struct Command *coin;
|
||||||
|
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||||
|
|
||||||
|
ref = find_command (is,
|
||||||
|
cmd->details.deposit_wtid.deposit_ref);
|
||||||
|
GNUNET_assert (NULL != ref);
|
||||||
|
coin = find_command (is,
|
||||||
|
ref->details.deposit.coin_ref);
|
||||||
|
GNUNET_assert (NULL != coin);
|
||||||
|
switch (coin->oc)
|
||||||
|
{
|
||||||
|
case OC_WITHDRAW_SIGN:
|
||||||
|
GNUNET_CRYPTO_eddsa_key_get_public (&coin->details.reserve_withdraw.coin_priv.eddsa_priv,
|
||||||
|
&coin_pub.eddsa_pub);
|
||||||
|
break;
|
||||||
|
case OC_REFRESH_REVEAL:
|
||||||
|
{
|
||||||
|
const struct FreshCoin *fc;
|
||||||
|
unsigned int idx;
|
||||||
|
|
||||||
|
idx = ref->details.deposit.coin_idx;
|
||||||
|
GNUNET_assert (idx < coin->details.refresh_reveal.num_fresh_coins);
|
||||||
|
fc = &coin->details.refresh_reveal.fresh_coins[idx];
|
||||||
|
|
||||||
|
GNUNET_CRYPTO_eddsa_key_get_public (&fc->coin_priv.eddsa_priv,
|
||||||
|
&coin_pub.eddsa_pub);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GNUNET_assert (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
wire = json_loads (ref->details.deposit.wire_details,
|
||||||
|
JSON_REJECT_DUPLICATES,
|
||||||
|
NULL);
|
||||||
|
GNUNET_assert (NULL != wire);
|
||||||
|
TALER_hash_json (wire,
|
||||||
|
&h_wire);
|
||||||
|
json_decref (wire);
|
||||||
|
contract = json_loads (ref->details.deposit.contract,
|
||||||
|
JSON_REJECT_DUPLICATES,
|
||||||
|
NULL);
|
||||||
|
GNUNET_assert (NULL != contract);
|
||||||
|
TALER_hash_json (contract,
|
||||||
|
&h_contract);
|
||||||
|
json_decref (contract);
|
||||||
|
cmd->details.deposit_wtid.dwh
|
||||||
|
= TALER_MINT_deposit_wtid (mint,
|
||||||
|
&ref->details.deposit.merchant_priv,
|
||||||
|
&h_wire,
|
||||||
|
&h_contract,
|
||||||
|
&coin_pub,
|
||||||
|
ref->details.deposit.transaction_id,
|
||||||
|
&deposit_wtid_cb,
|
||||||
|
is);
|
||||||
|
trigger_context_task ();
|
||||||
|
}
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Unknown instruction %d at %u (%s)\n",
|
"Unknown instruction %d at %u (%s)\n",
|
||||||
@ -1695,8 +2006,6 @@ interpreter_run (void *cls,
|
|||||||
fail (is);
|
fail (is);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
|
|
||||||
is);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1829,10 +2138,36 @@ do_shutdown (void *cls,
|
|||||||
case OC_WIRE:
|
case OC_WIRE:
|
||||||
if (NULL != cmd->details.wire.wh)
|
if (NULL != cmd->details.wire.wh)
|
||||||
{
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"Command %u (%s) did not complete\n",
|
||||||
|
i,
|
||||||
|
cmd->label);
|
||||||
TALER_MINT_wire_cancel (cmd->details.wire.wh);
|
TALER_MINT_wire_cancel (cmd->details.wire.wh);
|
||||||
cmd->details.wire.wh = NULL;
|
cmd->details.wire.wh = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case OC_WIRE_DEPOSITS:
|
||||||
|
if (NULL != cmd->details.wire_deposits.wdh)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"Command %u (%s) did not complete\n",
|
||||||
|
i,
|
||||||
|
cmd->label);
|
||||||
|
TALER_MINT_wire_deposits_cancel (cmd->details.wire_deposits.wdh);
|
||||||
|
cmd->details.wire_deposits.wdh = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OC_DEPOSIT_WTID:
|
||||||
|
if (NULL != cmd->details.deposit_wtid.dwh)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"Command %u (%s) did not complete\n",
|
||||||
|
i,
|
||||||
|
cmd->label);
|
||||||
|
TALER_MINT_deposit_wtid_cancel (cmd->details.deposit_wtid.dwh);
|
||||||
|
cmd->details.deposit_wtid.dwh = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Unknown instruction %d at %u (%s)\n",
|
"Unknown instruction %d at %u (%s)\n",
|
||||||
@ -2047,7 +2382,7 @@ run (void *cls,
|
|||||||
.details.deposit.amount = "EUR:5",
|
.details.deposit.amount = "EUR:5",
|
||||||
.details.deposit.coin_ref = "withdraw-coin-1",
|
.details.deposit.coin_ref = "withdraw-coin-1",
|
||||||
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
||||||
.details.deposit.contract = "{ \"items\"={ \"name\":\"ice cream\", \"value\":1 } }",
|
.details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }",
|
||||||
.details.deposit.transaction_id = 1 },
|
.details.deposit.transaction_id = 1 },
|
||||||
|
|
||||||
/* Try to overdraw funds ... */
|
/* Try to overdraw funds ... */
|
||||||
@ -2064,7 +2399,7 @@ run (void *cls,
|
|||||||
.details.deposit.amount = "EUR:5",
|
.details.deposit.amount = "EUR:5",
|
||||||
.details.deposit.coin_ref = "withdraw-coin-1",
|
.details.deposit.coin_ref = "withdraw-coin-1",
|
||||||
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":43 }",
|
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":43 }",
|
||||||
.details.deposit.contract = "{ \"items\"={ \"name\":\"ice cream\", \"value\":1 } }",
|
.details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }",
|
||||||
.details.deposit.transaction_id = 1 },
|
.details.deposit.transaction_id = 1 },
|
||||||
/* Try to double-spend the 5 EUR coin at the same merchant (but different
|
/* Try to double-spend the 5 EUR coin at the same merchant (but different
|
||||||
transaction ID) */
|
transaction ID) */
|
||||||
@ -2074,7 +2409,7 @@ run (void *cls,
|
|||||||
.details.deposit.amount = "EUR:5",
|
.details.deposit.amount = "EUR:5",
|
||||||
.details.deposit.coin_ref = "withdraw-coin-1",
|
.details.deposit.coin_ref = "withdraw-coin-1",
|
||||||
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
||||||
.details.deposit.contract = "{ \"items\"={ \"name\":\"ice cream\", \"value\":1 } }",
|
.details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }",
|
||||||
.details.deposit.transaction_id = 2 },
|
.details.deposit.transaction_id = 2 },
|
||||||
/* Try to double-spend the 5 EUR coin at the same merchant (but different
|
/* Try to double-spend the 5 EUR coin at the same merchant (but different
|
||||||
contract) */
|
contract) */
|
||||||
@ -2084,7 +2419,7 @@ run (void *cls,
|
|||||||
.details.deposit.amount = "EUR:5",
|
.details.deposit.amount = "EUR:5",
|
||||||
.details.deposit.coin_ref = "withdraw-coin-1",
|
.details.deposit.coin_ref = "withdraw-coin-1",
|
||||||
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
||||||
.details.deposit.contract = "{ \"items\"={ \"name\":\"ice cream\", \"value\":2 } }",
|
.details.deposit.contract = "{ \"items\":[{ \"name\":\"ice cream\", \"value\":2 } ] }",
|
||||||
.details.deposit.transaction_id = 1 },
|
.details.deposit.transaction_id = 1 },
|
||||||
|
|
||||||
/* ***************** /refresh testing ******************** */
|
/* ***************** /refresh testing ******************** */
|
||||||
@ -2109,7 +2444,7 @@ run (void *cls,
|
|||||||
.details.deposit.amount = "EUR:1",
|
.details.deposit.amount = "EUR:1",
|
||||||
.details.deposit.coin_ref = "refresh-withdraw-coin-1",
|
.details.deposit.coin_ref = "refresh-withdraw-coin-1",
|
||||||
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
||||||
.details.deposit.contract = "{ \"items\"={ \"name\":\"ice cream\", \"value\"EUR:1 } }",
|
.details.deposit.contract = "{ \"items\" : [ { \"name\":\"ice cream\", \"value\":\"EUR:1\" } ] }",
|
||||||
.details.deposit.transaction_id = 42421 },
|
.details.deposit.transaction_id = 42421 },
|
||||||
|
|
||||||
/* Melt the rest of the coin's value (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
|
/* Melt the rest of the coin's value (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
|
||||||
@ -2143,7 +2478,7 @@ run (void *cls,
|
|||||||
.details.deposit.coin_ref = "refresh-reveal-1",
|
.details.deposit.coin_ref = "refresh-reveal-1",
|
||||||
.details.deposit.coin_idx = 0,
|
.details.deposit.coin_idx = 0,
|
||||||
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
||||||
.details.deposit.contract = "{ \"items\"={ \"name\":\"ice cream\", \"value\":3 } }",
|
.details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":3 } ] }",
|
||||||
.details.deposit.transaction_id = 2 },
|
.details.deposit.transaction_id = 2 },
|
||||||
|
|
||||||
/* Test successfully spending coins from the refresh operation:
|
/* Test successfully spending coins from the refresh operation:
|
||||||
@ -2155,7 +2490,7 @@ run (void *cls,
|
|||||||
.details.deposit.coin_ref = "refresh-reveal-1",
|
.details.deposit.coin_ref = "refresh-reveal-1",
|
||||||
.details.deposit.coin_idx = 4,
|
.details.deposit.coin_idx = 4,
|
||||||
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
|
||||||
.details.deposit.contract = "{ \"items\"={ \"name\":\"ice cream\", \"value\":3 } }",
|
.details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":3 } ] }",
|
||||||
.details.deposit.transaction_id = 2 },
|
.details.deposit.transaction_id = 2 },
|
||||||
|
|
||||||
/* Test running a failing melt operation (same operation again must fail) */
|
/* Test running a failing melt operation (same operation again must fail) */
|
||||||
@ -2168,6 +2503,35 @@ run (void *cls,
|
|||||||
// FIXME: also test with coin that was already melted
|
// FIXME: also test with coin that was already melted
|
||||||
// (signature differs from coin that was deposited...)
|
// (signature differs from coin that was deposited...)
|
||||||
/* *************** end of /refresh testing ************** */
|
/* *************** end of /refresh testing ************** */
|
||||||
|
|
||||||
|
/* ************** Test tracking API ******************** */
|
||||||
|
/* Try resolving a deposit's WTID, as we never triggered
|
||||||
|
execution of transactions, the answer should be that
|
||||||
|
the mint knows about the deposit, but has no WTID yet. */
|
||||||
|
{ .oc = OC_DEPOSIT_WTID,
|
||||||
|
.label = "deposit-wtid-found",
|
||||||
|
.expected_response_code = MHD_HTTP_ACCEPTED,
|
||||||
|
.details.deposit_wtid.deposit_ref = "deposit-simple" },
|
||||||
|
/* Try resolving a deposit's WTID for a failed deposit.
|
||||||
|
As the deposit failed, the answer should be that
|
||||||
|
the mint does NOT know about the deposit. */
|
||||||
|
{ .oc = OC_DEPOSIT_WTID,
|
||||||
|
.label = "deposit-wtid-failing",
|
||||||
|
.expected_response_code = MHD_HTTP_NOT_FOUND,
|
||||||
|
.details.deposit_wtid.deposit_ref = "deposit-double-2" },
|
||||||
|
/* Try resolving an undefined (all zeros) WTID; this
|
||||||
|
should fail as obviously the mint didn't use that
|
||||||
|
WTID value for any transaction. */
|
||||||
|
{ .oc = OC_WIRE_DEPOSITS,
|
||||||
|
.label = "wire-deposit-failing",
|
||||||
|
.expected_response_code = MHD_HTTP_NOT_FOUND },
|
||||||
|
|
||||||
|
/* TODO: trigger aggregation logic and then check the
|
||||||
|
cases where tracking succeeds! */
|
||||||
|
|
||||||
|
/* ************** End of tracking API testing************* */
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ .oc = OC_END }
|
{ .oc = OC_END }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2014, 2015 GNUnet e.V.
|
Copyright (C) 2014, 2015, 2016 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 General Public License as published by the Free Software
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -1565,6 +1565,12 @@ struct WtidTransactionContext
|
|||||||
*/
|
*/
|
||||||
struct TALER_Amount total;
|
struct TALER_Amount total;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value we find in the DB for the @e total; only valid if @e is_valid
|
||||||
|
* is #GNUNET_YES.
|
||||||
|
*/
|
||||||
|
struct TALER_Amount db_transaction_value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public key of the merchant, only valid if @e is_valid
|
* Public key of the merchant, only valid if @e is_valid
|
||||||
* is #GNUNET_YES.
|
* is #GNUNET_YES.
|
||||||
@ -1606,6 +1612,7 @@ struct WtidTransactionContext
|
|||||||
* @param coin_pub which public key was this payment about
|
* @param coin_pub which public key was this payment about
|
||||||
* @param deposit_value amount contributed by this coin in total
|
* @param deposit_value amount contributed by this coin in total
|
||||||
* @param deposit_fee deposit fee charged by mint for this coin
|
* @param deposit_fee deposit fee charged by mint for this coin
|
||||||
|
* @param transaction_value total value of the wire transaction
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
handle_transaction_data (void *cls,
|
handle_transaction_data (void *cls,
|
||||||
@ -1615,7 +1622,8 @@ handle_transaction_data (void *cls,
|
|||||||
uint64_t transaction_id,
|
uint64_t transaction_id,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
const struct TALER_Amount *deposit_value,
|
const struct TALER_Amount *deposit_value,
|
||||||
const struct TALER_Amount *deposit_fee)
|
const struct TALER_Amount *deposit_fee,
|
||||||
|
const struct TALER_Amount *transaction_value)
|
||||||
{
|
{
|
||||||
struct WtidTransactionContext *ctx = cls;
|
struct WtidTransactionContext *ctx = cls;
|
||||||
struct TALER_Amount delta;
|
struct TALER_Amount delta;
|
||||||
@ -1626,6 +1634,7 @@ handle_transaction_data (void *cls,
|
|||||||
{
|
{
|
||||||
ctx->merchant_pub = *merchant_pub;
|
ctx->merchant_pub = *merchant_pub;
|
||||||
ctx->h_wire = *h_wire;
|
ctx->h_wire = *h_wire;
|
||||||
|
ctx->db_transaction_value = *transaction_value;
|
||||||
ctx->is_valid = GNUNET_YES;
|
ctx->is_valid = GNUNET_YES;
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
TALER_amount_subtract (&ctx->total,
|
TALER_amount_subtract (&ctx->total,
|
||||||
@ -1644,7 +1653,9 @@ handle_transaction_data (void *cls,
|
|||||||
sizeof (struct TALER_MerchantPublicKeyP))) ||
|
sizeof (struct TALER_MerchantPublicKeyP))) ||
|
||||||
(0 != memcmp (&ctx->h_wire,
|
(0 != memcmp (&ctx->h_wire,
|
||||||
h_wire,
|
h_wire,
|
||||||
sizeof (struct GNUNET_HashCode))) )
|
sizeof (struct GNUNET_HashCode))) ||
|
||||||
|
(0 != TALER_amount_cmp (transaction_value,
|
||||||
|
&ctx->db_transaction_value)) )
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
ctx->is_valid = GNUNET_SYSERR;
|
ctx->is_valid = GNUNET_SYSERR;
|
||||||
@ -1693,15 +1704,23 @@ handle_transaction_data (void *cls,
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
TMH_DB_execute_wire_deposits (struct MHD_Connection *connection,
|
TMH_DB_execute_wire_deposits (struct MHD_Connection *connection,
|
||||||
const struct TALER_WireTransferIdentifierP *wtid)
|
const struct TALER_WireTransferIdentifierRawP *wtid)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct WtidTransactionContext ctx;
|
struct WtidTransactionContext ctx;
|
||||||
|
struct TALER_MINTDB_Session *session;
|
||||||
|
|
||||||
|
if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls,
|
||||||
|
TMH_test_mode)))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return TMH_RESPONSE_reply_internal_db_error (connection);
|
||||||
|
}
|
||||||
ctx.is_valid = GNUNET_NO;
|
ctx.is_valid = GNUNET_NO;
|
||||||
ctx.deposits = json_array ();
|
ctx.deposits = json_array ();
|
||||||
ret = TMH_plugin->lookup_wire_transactions (TMH_plugin->cls,
|
ret = TMH_plugin->lookup_wire_transfer (TMH_plugin->cls,
|
||||||
&wtid->raw,
|
session,
|
||||||
|
wtid,
|
||||||
&handle_transaction_data,
|
&handle_transaction_data,
|
||||||
&ctx);
|
&ctx);
|
||||||
if (GNUNET_SYSERR == ret)
|
if (GNUNET_SYSERR == ret)
|
||||||
@ -1722,8 +1741,15 @@ TMH_DB_execute_wire_deposits (struct MHD_Connection *connection,
|
|||||||
return TMH_RESPONSE_reply_arg_unknown (connection,
|
return TMH_RESPONSE_reply_arg_unknown (connection,
|
||||||
"wtid");
|
"wtid");
|
||||||
}
|
}
|
||||||
|
if (0 != TALER_amount_cmp (&ctx.total,
|
||||||
|
&ctx.db_transaction_value))
|
||||||
|
{
|
||||||
|
/* FIXME: this CAN actually differ, due to rounding
|
||||||
|
down. But we should still check that the values
|
||||||
|
do match after rounding 'total' down! */
|
||||||
|
}
|
||||||
return TMH_RESPONSE_reply_wire_deposit_details (connection,
|
return TMH_RESPONSE_reply_wire_deposit_details (connection,
|
||||||
&ctx.total,
|
&ctx.db_transaction_value,
|
||||||
&ctx.merchant_pub,
|
&ctx.merchant_pub,
|
||||||
&ctx.h_wire,
|
&ctx.h_wire,
|
||||||
ctx.deposits);
|
ctx.deposits);
|
||||||
@ -1776,7 +1802,8 @@ struct DepositWtidContext
|
|||||||
* @param wtid raw wire transfer identifier, NULL
|
* @param wtid raw wire transfer identifier, NULL
|
||||||
* if the transaction was not yet done
|
* if the transaction was not yet done
|
||||||
* @param coin_contribution how much did the coin we asked about
|
* @param coin_contribution how much did the coin we asked about
|
||||||
* contribute to the total transfer value? (deposit value minus fee)
|
* contribute to the total transfer value? (deposit value including fee)
|
||||||
|
* @param coin_fee how much did the mint charge for the deposit fee
|
||||||
* @param total_amount how much was the total wire transfer?
|
* @param total_amount how much was the total wire transfer?
|
||||||
* @param execution_time when was the transaction done, or
|
* @param execution_time when was the transaction done, or
|
||||||
* when we expect it to be done (if @a wtid was NULL);
|
* when we expect it to be done (if @a wtid was NULL);
|
||||||
@ -1787,32 +1814,41 @@ static void
|
|||||||
handle_wtid_data (void *cls,
|
handle_wtid_data (void *cls,
|
||||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
const struct TALER_Amount *coin_contribution,
|
const struct TALER_Amount *coin_contribution,
|
||||||
|
const struct TALER_Amount *coin_fee,
|
||||||
const struct TALER_Amount *total_amount,
|
const struct TALER_Amount *total_amount,
|
||||||
struct GNUNET_TIME_Absolute execution_time)
|
struct GNUNET_TIME_Absolute execution_time)
|
||||||
{
|
{
|
||||||
struct DepositWtidContext *ctx = cls;
|
struct DepositWtidContext *ctx = cls;
|
||||||
|
struct TALER_Amount coin_delta;
|
||||||
|
|
||||||
if (NULL == wtid)
|
if (NULL == wtid)
|
||||||
{
|
{
|
||||||
if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us ==
|
|
||||||
execution_time.abs_value_us)
|
|
||||||
ctx->res = TMH_RESPONSE_reply_deposit_unknown (ctx->connection);
|
|
||||||
else
|
|
||||||
ctx->res = TMH_RESPONSE_reply_deposit_pending (ctx->connection,
|
ctx->res = TMH_RESPONSE_reply_deposit_pending (ctx->connection,
|
||||||
execution_time);
|
execution_time);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (GNUNET_SYSERR ==
|
||||||
|
TALER_amount_subtract (&coin_delta,
|
||||||
|
coin_contribution,
|
||||||
|
coin_fee))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
ctx->res = TMH_RESPONSE_reply_internal_db_error (ctx->connection);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ctx->res = TMH_RESPONSE_reply_deposit_wtid (ctx->connection,
|
ctx->res = TMH_RESPONSE_reply_deposit_wtid (ctx->connection,
|
||||||
&ctx->h_contract,
|
&ctx->h_contract,
|
||||||
&ctx->h_wire,
|
&ctx->h_wire,
|
||||||
&ctx->coin_pub,
|
&ctx->coin_pub,
|
||||||
coin_contribution,
|
&coin_delta,
|
||||||
total_amount,
|
total_amount,
|
||||||
ctx->transaction_id,
|
ctx->transaction_id,
|
||||||
wtid,
|
wtid,
|
||||||
execution_time);
|
execution_time);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1838,14 +1874,22 @@ TMH_DB_execute_deposit_wtid (struct MHD_Connection *connection,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct DepositWtidContext ctx;
|
struct DepositWtidContext ctx;
|
||||||
|
struct TALER_MINTDB_Session *session;
|
||||||
|
|
||||||
|
if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls,
|
||||||
|
TMH_test_mode)))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return TMH_RESPONSE_reply_internal_db_error (connection);
|
||||||
|
}
|
||||||
ctx.connection = connection;
|
ctx.connection = connection;
|
||||||
ctx.h_contract = *h_contract;
|
ctx.h_contract = *h_contract;
|
||||||
ctx.h_wire = *h_wire;
|
ctx.h_wire = *h_wire;
|
||||||
ctx.coin_pub = *coin_pub;
|
ctx.coin_pub = *coin_pub;
|
||||||
ctx.transaction_id = transaction_id;
|
ctx.transaction_id = transaction_id;
|
||||||
ctx.res = MHD_NO; /* this value should never be read... */
|
ctx.res = GNUNET_SYSERR;
|
||||||
ret = TMH_plugin->wire_lookup_deposit_wtid (TMH_plugin->cls,
|
ret = TMH_plugin->wire_lookup_deposit_wtid (TMH_plugin->cls,
|
||||||
|
session,
|
||||||
h_contract,
|
h_contract,
|
||||||
h_wire,
|
h_wire,
|
||||||
coin_pub,
|
coin_pub,
|
||||||
@ -1856,8 +1900,20 @@ TMH_DB_execute_deposit_wtid (struct MHD_Connection *connection,
|
|||||||
if (GNUNET_SYSERR == ret)
|
if (GNUNET_SYSERR == ret)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
|
GNUNET_break (GNUNET_SYSERR == ctx.res);
|
||||||
return TMH_RESPONSE_reply_internal_db_error (connection);
|
return TMH_RESPONSE_reply_internal_db_error (connection);
|
||||||
}
|
}
|
||||||
|
if (GNUNET_NO == ret)
|
||||||
|
{
|
||||||
|
GNUNET_break (GNUNET_SYSERR == ctx.res);
|
||||||
|
return TMH_RESPONSE_reply_deposit_unknown (connection);
|
||||||
|
}
|
||||||
|
if (GNUNET_SYSERR == ctx.res)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return TMH_RESPONSE_reply_internal_error (connection,
|
||||||
|
"bug resolving deposit wtid");
|
||||||
|
}
|
||||||
return ctx.res;
|
return ctx.res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ TMH_DB_execute_admin_add_incoming (struct MHD_Connection *connection,
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
TMH_DB_execute_wire_deposits (struct MHD_Connection *connection,
|
TMH_DB_execute_wire_deposits (struct MHD_Connection *connection,
|
||||||
const struct TALER_WireTransferIdentifierP *wtid);
|
const struct TALER_WireTransferIdentifierRawP *wtid);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1081,7 +1081,7 @@ TMH_RESPONSE_reply_deposit_pending (struct MHD_Connection *connection,
|
|||||||
struct GNUNET_TIME_Absolute planned_exec_time)
|
struct GNUNET_TIME_Absolute planned_exec_time)
|
||||||
{
|
{
|
||||||
return TMH_RESPONSE_reply_json_pack (connection,
|
return TMH_RESPONSE_reply_json_pack (connection,
|
||||||
MHD_HTTP_FOUND,
|
MHD_HTTP_ACCEPTED,
|
||||||
"{s:o}",
|
"{s:o}",
|
||||||
"execution_time", TALER_json_from_abs (planned_exec_time));
|
"execution_time", TALER_json_from_abs (planned_exec_time));
|
||||||
}
|
}
|
||||||
@ -1117,11 +1117,7 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection,
|
|||||||
struct TALER_ConfirmWirePS cw;
|
struct TALER_ConfirmWirePS cw;
|
||||||
struct TALER_MintPublicKeyP pub;
|
struct TALER_MintPublicKeyP pub;
|
||||||
struct TALER_MintSignatureP sig;
|
struct TALER_MintSignatureP sig;
|
||||||
struct TALER_WireTransferIdentifierP wtid_crc;
|
|
||||||
char *wtid_s;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Create signature for the reply */
|
|
||||||
cw.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_WIRE);
|
cw.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_WIRE);
|
||||||
cw.purpose.size = htonl (sizeof (struct TALER_ConfirmWirePS));
|
cw.purpose.size = htonl (sizeof (struct TALER_ConfirmWirePS));
|
||||||
cw.h_wire = *h_wire;
|
cw.h_wire = *h_wire;
|
||||||
@ -1137,24 +1133,18 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection,
|
|||||||
TMH_KS_sign (&cw.purpose,
|
TMH_KS_sign (&cw.purpose,
|
||||||
&pub,
|
&pub,
|
||||||
&sig);
|
&sig);
|
||||||
/* Compute checksum and crockford encoding if wire transfer subject */
|
return TMH_RESPONSE_reply_json_pack (connection,
|
||||||
wtid_crc.raw = *wtid;
|
|
||||||
wtid_crc.crc8 = GNUNET_CRYPTO_crc8_n (wtid,
|
|
||||||
sizeof (struct TALER_WireTransferIdentifierRawP));
|
|
||||||
|
|
||||||
wtid_s = GNUNET_STRINGS_data_to_string_alloc (&wtid_crc,
|
|
||||||
sizeof (wtid_crc));
|
|
||||||
ret = TMH_RESPONSE_reply_json_pack (connection,
|
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"{s:s, s:o, s:o, s:o}",
|
"{s:o, s:o, s:o, s:o, s:o, s:o}",
|
||||||
"wtid", wtid_s,
|
"wtid", TALER_json_from_data (wtid,
|
||||||
|
sizeof (*wtid)),
|
||||||
"execution_time", TALER_json_from_abs (exec_time),
|
"execution_time", TALER_json_from_abs (exec_time),
|
||||||
|
"coin_contribution", TALER_json_from_amount (coin_contribution),
|
||||||
|
"total_amount", TALER_json_from_amount (total_amount),
|
||||||
"mint_sig", TALER_json_from_data (&sig,
|
"mint_sig", TALER_json_from_data (&sig,
|
||||||
sizeof (sig)),
|
sizeof (sig)),
|
||||||
"mint_pub", TALER_json_from_data (&pub,
|
"mint_pub", TALER_json_from_data (&pub,
|
||||||
sizeof (pub)));
|
sizeof (pub)));
|
||||||
GNUNET_free (wtid_s);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,22 +46,17 @@ TMH_TRACKING_handler_wire_deposits (struct TMH_RequestHandler *rh,
|
|||||||
const char *upload_data,
|
const char *upload_data,
|
||||||
size_t *upload_data_size)
|
size_t *upload_data_size)
|
||||||
{
|
{
|
||||||
struct TALER_WireTransferIdentifierP wtid;
|
struct TALER_WireTransferIdentifierRawP wtid;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
res = TMH_PARSE_mhd_request_arg_data (connection,
|
res = TMH_PARSE_mhd_request_arg_data (connection,
|
||||||
"wtid",
|
"wtid",
|
||||||
&wtid,
|
&wtid,
|
||||||
sizeof (struct TALER_WireTransferIdentifierP));
|
sizeof (struct TALER_WireTransferIdentifierRawP));
|
||||||
if (GNUNET_SYSERR == res)
|
if (GNUNET_SYSERR == res)
|
||||||
return MHD_NO; /* internal error */
|
return MHD_NO; /* internal error */
|
||||||
if (GNUNET_NO == res)
|
if (GNUNET_NO == res)
|
||||||
return MHD_YES; /* parse error */
|
return MHD_YES; /* parse error */
|
||||||
if (wtid.crc8 !=
|
|
||||||
GNUNET_CRYPTO_crc8_n (&wtid.raw,
|
|
||||||
sizeof (wtid.raw)))
|
|
||||||
return TMH_RESPONSE_reply_arg_invalid (connection,
|
|
||||||
"wtid");
|
|
||||||
return TMH_DB_execute_wire_deposits (connection,
|
return TMH_DB_execute_wire_deposits (connection,
|
||||||
&wtid);
|
&wtid);
|
||||||
}
|
}
|
||||||
@ -126,13 +121,12 @@ TMH_TRACKING_handler_deposit_wtid (struct TMH_RequestHandler *rh,
|
|||||||
struct TALER_DepositTrackPS tps;
|
struct TALER_DepositTrackPS tps;
|
||||||
uint64_t transaction_id;
|
uint64_t transaction_id;
|
||||||
struct TALER_MerchantSignatureP merchant_sig;
|
struct TALER_MerchantSignatureP merchant_sig;
|
||||||
struct TALER_MerchantPublicKeyP merchant_pub;
|
|
||||||
struct TMH_PARSE_FieldSpecification spec[] = {
|
struct TMH_PARSE_FieldSpecification spec[] = {
|
||||||
TMH_PARSE_member_fixed ("H_wire", &tps.h_wire),
|
TMH_PARSE_member_fixed ("H_wire", &tps.h_wire),
|
||||||
TMH_PARSE_member_fixed ("H_contract", &tps.h_contract),
|
TMH_PARSE_member_fixed ("H_contract", &tps.h_contract),
|
||||||
TMH_PARSE_member_fixed ("coin_pub", &tps.coin_pub),
|
TMH_PARSE_member_fixed ("coin_pub", &tps.coin_pub),
|
||||||
TMH_PARSE_member_uint64 ("transaction_id", &transaction_id),
|
TMH_PARSE_member_uint64 ("transaction_id", &transaction_id),
|
||||||
TMH_PARSE_member_fixed ("merchant_pub", &merchant_pub),
|
TMH_PARSE_member_fixed ("merchant_pub", &tps.merchant),
|
||||||
TMH_PARSE_member_fixed ("merchant_sig", &merchant_sig),
|
TMH_PARSE_member_fixed ("merchant_sig", &merchant_sig),
|
||||||
TMH_PARSE_MEMBER_END
|
TMH_PARSE_MEMBER_END
|
||||||
};
|
};
|
||||||
@ -159,7 +153,7 @@ TMH_TRACKING_handler_deposit_wtid (struct TMH_RequestHandler *rh,
|
|||||||
tps.transaction_id = GNUNET_htonll (transaction_id);
|
tps.transaction_id = GNUNET_htonll (transaction_id);
|
||||||
res = check_and_handle_deposit_wtid_request (connection,
|
res = check_and_handle_deposit_wtid_request (connection,
|
||||||
&tps,
|
&tps,
|
||||||
&merchant_pub,
|
&tps.merchant,
|
||||||
&merchant_sig,
|
&merchant_sig,
|
||||||
transaction_id);
|
transaction_id);
|
||||||
TMH_PARSE_release_data (spec);
|
TMH_PARSE_release_data (spec);
|
||||||
|
@ -67,9 +67,11 @@ PERF_TALER_MINTDB_denomination_init ()
|
|||||||
properties.expire_withdraw = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_forever_());
|
properties.expire_withdraw = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_forever_());
|
||||||
properties.expire_spend = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_forever_());
|
properties.expire_spend = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_forever_());
|
||||||
properties.expire_legal = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_forever_());
|
properties.expire_legal = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_forever_());
|
||||||
TALER_string_to_amount (CURRENCY ":1.1", &amount);
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_string_to_amount (CURRENCY ":1.1", &amount));
|
||||||
TALER_amount_hton (&properties.value, &amount);
|
TALER_amount_hton (&properties.value, &amount);
|
||||||
TALER_string_to_amount (CURRENCY ":0.1", &amount);
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_string_to_amount (CURRENCY ":0.1", &amount));
|
||||||
TALER_amount_hton (&properties.fee_withdraw, &amount);
|
TALER_amount_hton (&properties.fee_withdraw, &amount);
|
||||||
TALER_amount_hton (&properties.fee_deposit, &amount);
|
TALER_amount_hton (&properties.fee_deposit, &amount);
|
||||||
TALER_amount_hton (&properties.fee_refresh, &amount);
|
TALER_amount_hton (&properties.fee_refresh, &amount);
|
||||||
@ -467,8 +469,8 @@ PERF_TALER_MINTDB_refresh_session_free (struct TALER_MINTDB_RefreshSession *refr
|
|||||||
{
|
{
|
||||||
if (NULL == refresh_session)
|
if (NULL == refresh_session)
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
return GNUNET_OK;
|
|
||||||
GNUNET_free (refresh_session);
|
GNUNET_free (refresh_session);
|
||||||
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -502,9 +504,11 @@ PERF_TALER_MINTDB_refresh_melt_init (struct GNUNET_HashCode *session,
|
|||||||
&to_sign.purpose,
|
&to_sign.purpose,
|
||||||
&coin_sig.eddsa_signature);
|
&coin_sig.eddsa_signature);
|
||||||
}
|
}
|
||||||
GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":1.1",
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_string_to_amount (CURRENCY ":1.1",
|
||||||
&amount));
|
&amount));
|
||||||
GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":0.1",
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_string_to_amount (CURRENCY ":0.1",
|
||||||
&amount_with_fee));
|
&amount_with_fee));
|
||||||
melt = GNUNET_new (struct TALER_MINTDB_RefreshMelt);
|
melt = GNUNET_new (struct TALER_MINTDB_RefreshMelt);
|
||||||
melt->coin.coin_pub = coin->public_info.coin_pub;
|
melt->coin.coin_pub = coin->public_info.coin_pub;
|
||||||
|
@ -451,8 +451,8 @@ postgres_create_tables (void *cls,
|
|||||||
/* Table for the tracking API, mapping from wire transfer identifiers
|
/* Table for the tracking API, mapping from wire transfer identifiers
|
||||||
to transactions and back */
|
to transactions and back */
|
||||||
SQLEXEC("CREATE TABLE IF NOT EXISTS aggregation_tracking "
|
SQLEXEC("CREATE TABLE IF NOT EXISTS aggregation_tracking "
|
||||||
"(h_contract BYTEA PRIMARY KEY CHECK (LENGTH(h_contract)=64)"
|
"(h_contract BYTEA CHECK (LENGTH(h_contract)=64)"
|
||||||
",h_wire BYTEA PRIMARY KEY CHECK (LENGTH(h_wire)=64)"
|
",h_wire BYTEA CHECK (LENGTH(h_wire)=64)"
|
||||||
",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)"
|
",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)"
|
||||||
",merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)"
|
",merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)"
|
||||||
",transaction_id INT8 NOT NULL"
|
",transaction_id INT8 NOT NULL"
|
||||||
@ -461,9 +461,12 @@ postgres_create_tables (void *cls,
|
|||||||
",coin_amount_val INT8 NOT NULL"
|
",coin_amount_val INT8 NOT NULL"
|
||||||
",coin_amount_frac INT4 NOT NULL"
|
",coin_amount_frac INT4 NOT NULL"
|
||||||
",coin_amount_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
|
",coin_amount_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
|
||||||
",transaction_total_val INT8 NOT NULL"
|
",coin_fee_val INT8 NOT NULL"
|
||||||
",transaction_total_frac INT4 NOT NULL"
|
",coin_fee_frac INT4 NOT NULL"
|
||||||
",transaction_total_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
|
",coin_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
|
||||||
|
",transfer_total_val INT8 NOT NULL"
|
||||||
|
",transfer_total_frac INT4 NOT NULL"
|
||||||
|
",transfer_total_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
|
||||||
")");
|
")");
|
||||||
/* Index for lookup_transactions statement on wtid */
|
/* Index for lookup_transactions statement on wtid */
|
||||||
SQLEXEC_INDEX("CREATE INDEX aggregation_tracking_wtid_index "
|
SQLEXEC_INDEX("CREATE INDEX aggregation_tracking_wtid_index "
|
||||||
@ -708,7 +711,7 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
"SELECT"
|
"SELECT"
|
||||||
" denom_pub"
|
" denom_pub"
|
||||||
",denom_sig"
|
",denom_sig"
|
||||||
" FROM known_coins "
|
" FROM known_coins"
|
||||||
" WHERE coin_pub=$1",
|
" WHERE coin_pub=$1",
|
||||||
1, NULL);
|
1, NULL);
|
||||||
/* Used in #postgres_insert_known_coin() to store
|
/* Used in #postgres_insert_known_coin() to store
|
||||||
@ -875,6 +878,26 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
" (merchant_pub=$3)"
|
" (merchant_pub=$3)"
|
||||||
" )",
|
" )",
|
||||||
3, NULL);
|
3, NULL);
|
||||||
|
/* Fetch an existing deposit request.
|
||||||
|
Used in #postgres_wire_lookup_deposit_wtid(). */
|
||||||
|
PREPARE ("get_deposit_for_wtid",
|
||||||
|
"SELECT"
|
||||||
|
" amount_with_fee_val"
|
||||||
|
",amount_with_fee_frac"
|
||||||
|
",amount_with_fee_curr"
|
||||||
|
",deposit_fee_val"
|
||||||
|
",deposit_fee_frac"
|
||||||
|
",deposit_fee_curr"
|
||||||
|
",wire_deadline"
|
||||||
|
" FROM deposits"
|
||||||
|
" WHERE ("
|
||||||
|
" (coin_pub=$1) AND"
|
||||||
|
" (transaction_id=$2) AND"
|
||||||
|
" (merchant_pub=$3) AND"
|
||||||
|
" (h_contract=$4) AND"
|
||||||
|
" (h_wire=$5)"
|
||||||
|
" )",
|
||||||
|
5, NULL);
|
||||||
|
|
||||||
/* Used in #postgres_iterate_deposits() */
|
/* Used in #postgres_iterate_deposits() */
|
||||||
PREPARE ("deposits_iterate",
|
PREPARE ("deposits_iterate",
|
||||||
@ -972,7 +995,7 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
" AND rm.oldcoin_index = rcl.oldcoin_index"
|
" AND rm.oldcoin_index = rcl.oldcoin_index"
|
||||||
" AND rcl.cnc_index=rs.noreveal_index",
|
" AND rcl.cnc_index=rs.noreveal_index",
|
||||||
1, NULL);
|
1, NULL);
|
||||||
/* Used in #postgres_lookup_wire_transactions */
|
/* Used in #postgres_lookup_wire_transfer */
|
||||||
PREPARE ("lookup_transactions",
|
PREPARE ("lookup_transactions",
|
||||||
"SELECT"
|
"SELECT"
|
||||||
" h_contract"
|
" h_contract"
|
||||||
@ -984,9 +1007,12 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
",coin_amount_val"
|
",coin_amount_val"
|
||||||
",coin_amount_frac"
|
",coin_amount_frac"
|
||||||
",coin_amount_curr"
|
",coin_amount_curr"
|
||||||
",transaction_total_val"
|
",coin_fee_val"
|
||||||
",transaction_total_frac"
|
",coin_fee_frac"
|
||||||
",transaction_total_curr"
|
",coin_fee_curr"
|
||||||
|
",transfer_total_val"
|
||||||
|
",transfer_total_frac"
|
||||||
|
",transfer_total_curr"
|
||||||
" FROM aggregation_tracking"
|
" FROM aggregation_tracking"
|
||||||
" WHERE wtid_raw=$1",
|
" WHERE wtid_raw=$1",
|
||||||
1, NULL);
|
1, NULL);
|
||||||
@ -998,9 +1024,12 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
",coin_amount_val"
|
",coin_amount_val"
|
||||||
",coin_amount_frac"
|
",coin_amount_frac"
|
||||||
",coin_amount_curr"
|
",coin_amount_curr"
|
||||||
",transaction_total_val"
|
",coin_fee_val"
|
||||||
",transaction_total_frac"
|
",coin_fee_frac"
|
||||||
",transaction_total_curr"
|
",coin_fee_curr"
|
||||||
|
",transfer_total_val"
|
||||||
|
",transfer_total_frac"
|
||||||
|
",transfer_total_curr"
|
||||||
" FROM aggregation_tracking"
|
" FROM aggregation_tracking"
|
||||||
" WHERE"
|
" WHERE"
|
||||||
" coin_pub=$1 AND"
|
" coin_pub=$1 AND"
|
||||||
@ -1022,12 +1051,15 @@ postgres_prepare (PGconn *db_conn)
|
|||||||
",coin_amount_val"
|
",coin_amount_val"
|
||||||
",coin_amount_frac"
|
",coin_amount_frac"
|
||||||
",coin_amount_curr"
|
",coin_amount_curr"
|
||||||
",transaction_total_val"
|
",coin_fee_val"
|
||||||
",transaction_total_frac"
|
",coin_fee_frac"
|
||||||
",transaction_total_curr"
|
",coin_fee_curr"
|
||||||
|
",transfer_total_val"
|
||||||
|
",transfer_total_frac"
|
||||||
|
",transfer_total_curr"
|
||||||
") VALUES "
|
") VALUES "
|
||||||
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)",
|
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)",
|
||||||
13, NULL);
|
16, NULL);
|
||||||
|
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
#undef PREPARE
|
#undef PREPARE
|
||||||
@ -3451,19 +3483,87 @@ postgres_get_coin_transactions (void *cls,
|
|||||||
* into a wire transfer by the respective @a wtid.
|
* into a wire transfer by the respective @a wtid.
|
||||||
*
|
*
|
||||||
* @param cls closure
|
* @param cls closure
|
||||||
|
* @param session database connection
|
||||||
* @param wtid the raw wire transfer identifier we used
|
* @param wtid the raw wire transfer identifier we used
|
||||||
* @param cb function to call on each transaction found
|
* @param cb function to call on each transaction found
|
||||||
* @param cb_cls closure for @a cb
|
* @param cb_cls closure for @a cb
|
||||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors,
|
||||||
|
* #GNUNET_NO if we found no results
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
postgres_lookup_wire_transactions (void *cls,
|
postgres_lookup_wire_transfer (void *cls,
|
||||||
|
struct TALER_MINTDB_Session *session,
|
||||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
TALER_MINTDB_TransactionDataCallback cb,
|
TALER_MINTDB_WireTransferDataCallback cb,
|
||||||
void *cb_cls)
|
void *cb_cls)
|
||||||
{
|
{
|
||||||
GNUNET_break (0); // not implemented!
|
PGresult *result;
|
||||||
|
struct TALER_PQ_QueryParam params[] = {
|
||||||
|
TALER_PQ_query_param_auto_from_type (wtid),
|
||||||
|
TALER_PQ_query_param_end
|
||||||
|
};
|
||||||
|
int nrows;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* check if the melt record exists and get it */
|
||||||
|
result = TALER_PQ_exec_prepared (session->conn,
|
||||||
|
"lookup_transactions",
|
||||||
|
params);
|
||||||
|
if (PGRES_TUPLES_OK != PQresultStatus (result))
|
||||||
|
{
|
||||||
|
BREAK_DB_ERR (result);
|
||||||
|
PQclear (result);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
nrows = PQntuples (result);
|
||||||
|
if (0 == nrows)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"lookup_wire_transfer() returned 0 matching rows\n");
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_NO;
|
||||||
|
}
|
||||||
|
for (i=0;i<nrows;i++)
|
||||||
|
{
|
||||||
|
struct GNUNET_HashCode h_contract;
|
||||||
|
struct GNUNET_HashCode h_wire;
|
||||||
|
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||||
|
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||||
|
uint64_t transaction_id;
|
||||||
|
struct GNUNET_TIME_Absolute exec_time;
|
||||||
|
struct TALER_Amount coin_amount;
|
||||||
|
struct TALER_Amount coin_fee;
|
||||||
|
struct TALER_Amount transfer_amount;
|
||||||
|
struct TALER_PQ_ResultSpec rs[] = {
|
||||||
|
TALER_PQ_result_spec_auto_from_type ("h_contract", &h_contract),
|
||||||
|
TALER_PQ_result_spec_auto_from_type ("h_wire", &h_wire),
|
||||||
|
TALER_PQ_result_spec_auto_from_type ("coin_pub", &coin_pub),
|
||||||
|
TALER_PQ_result_spec_auto_from_type ("merchant_pub", &merchant_pub),
|
||||||
|
TALER_PQ_result_spec_uint64 ("transaction_id", &transaction_id),
|
||||||
|
TALER_PQ_result_spec_absolute_time ("execution_time", &exec_time),
|
||||||
|
TALER_PQ_result_spec_amount ("coin_amount", &coin_amount),
|
||||||
|
TALER_PQ_result_spec_amount ("coin_fee", &coin_fee),
|
||||||
|
TALER_PQ_result_spec_amount ("transfer_total", &transfer_amount),
|
||||||
|
TALER_PQ_result_spec_end
|
||||||
|
};
|
||||||
|
if (GNUNET_OK != TALER_PQ_extract_result (result, rs, i))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
cb (cb_cls,
|
||||||
|
&merchant_pub,
|
||||||
|
&h_wire,
|
||||||
|
&h_contract,
|
||||||
|
transaction_id,
|
||||||
|
&coin_pub,
|
||||||
|
&coin_amount,
|
||||||
|
&coin_fee,
|
||||||
|
&transfer_amount);
|
||||||
|
}
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3473,6 +3573,7 @@ postgres_lookup_wire_transactions (void *cls,
|
|||||||
* to be executed.
|
* to be executed.
|
||||||
*
|
*
|
||||||
* @param cls closure
|
* @param cls closure
|
||||||
|
* @param session database connection
|
||||||
* @param h_contract hash of the contract
|
* @param h_contract hash of the contract
|
||||||
* @param h_wire hash of merchant wire details
|
* @param h_wire hash of merchant wire details
|
||||||
* @param coin_pub public key of deposited coin
|
* @param coin_pub public key of deposited coin
|
||||||
@ -3480,10 +3581,12 @@ postgres_lookup_wire_transactions (void *cls,
|
|||||||
* @param transaction_id transaction identifier
|
* @param transaction_id transaction identifier
|
||||||
* @param cb function to call with the result
|
* @param cb function to call with the result
|
||||||
* @param cb_cls closure to pass to @a cb
|
* @param cb_cls closure to pass to @a cb
|
||||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors,
|
||||||
|
* #GNUNET_NO if nothing was found
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
postgres_wire_lookup_deposit_wtid (void *cls,
|
postgres_wire_lookup_deposit_wtid (void *cls,
|
||||||
|
struct TALER_MINTDB_Session *session,
|
||||||
const struct GNUNET_HashCode *h_contract,
|
const struct GNUNET_HashCode *h_contract,
|
||||||
const struct GNUNET_HashCode *h_wire,
|
const struct GNUNET_HashCode *h_wire,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
@ -3492,8 +3595,130 @@ postgres_wire_lookup_deposit_wtid (void *cls,
|
|||||||
TALER_MINTDB_DepositWtidCallback cb,
|
TALER_MINTDB_DepositWtidCallback cb,
|
||||||
void *cb_cls)
|
void *cb_cls)
|
||||||
{
|
{
|
||||||
GNUNET_break (0); // not implemented
|
PGresult *result;
|
||||||
|
struct TALER_PQ_QueryParam params[] = {
|
||||||
|
TALER_PQ_query_param_auto_from_type (coin_pub),
|
||||||
|
TALER_PQ_query_param_auto_from_type (h_contract),
|
||||||
|
TALER_PQ_query_param_auto_from_type (h_wire),
|
||||||
|
TALER_PQ_query_param_uint64 (&transaction_id),
|
||||||
|
TALER_PQ_query_param_auto_from_type (merchant_pub),
|
||||||
|
TALER_PQ_query_param_end
|
||||||
|
};
|
||||||
|
int nrows;
|
||||||
|
|
||||||
|
/* check if the melt record exists and get it */
|
||||||
|
result = TALER_PQ_exec_prepared (session->conn,
|
||||||
|
"lookup_deposit_wtid",
|
||||||
|
params);
|
||||||
|
if (PGRES_TUPLES_OK != PQresultStatus (result))
|
||||||
|
{
|
||||||
|
BREAK_DB_ERR (result);
|
||||||
|
PQclear (result);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
nrows = PQntuples (result);
|
||||||
|
if (0 == nrows)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"lookup_deposit_wtid returned 0 matching rows\n");
|
||||||
|
PQclear (result);
|
||||||
|
|
||||||
|
/* Check if transaction exists in deposits, so that we just
|
||||||
|
do not have a WTID yet, if so, do call the CB with a NULL wtid
|
||||||
|
and return GNUNET_YES! */
|
||||||
|
{
|
||||||
|
struct TALER_PQ_QueryParam params2[] = {
|
||||||
|
TALER_PQ_query_param_auto_from_type (coin_pub),
|
||||||
|
TALER_PQ_query_param_uint64 (&transaction_id),
|
||||||
|
TALER_PQ_query_param_auto_from_type (merchant_pub),
|
||||||
|
TALER_PQ_query_param_auto_from_type (h_contract),
|
||||||
|
TALER_PQ_query_param_auto_from_type (h_wire),
|
||||||
|
TALER_PQ_query_param_end
|
||||||
|
};
|
||||||
|
|
||||||
|
result = TALER_PQ_exec_prepared (session->conn,
|
||||||
|
"get_deposit_for_wtid",
|
||||||
|
params2);
|
||||||
|
if (PGRES_TUPLES_OK != PQresultStatus (result))
|
||||||
|
{
|
||||||
|
BREAK_DB_ERR (result);
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nrows = PQntuples (result);
|
||||||
|
if (0 == nrows)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"get_deposit_for_wtid returned 0 matching rows\n");
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ok, we're aware of the transaction, but it has not yet been
|
||||||
|
executed */
|
||||||
|
{
|
||||||
|
struct GNUNET_TIME_Absolute exec_time;
|
||||||
|
struct TALER_Amount coin_amount;
|
||||||
|
struct TALER_Amount coin_fee;
|
||||||
|
struct TALER_PQ_ResultSpec rs[] = {
|
||||||
|
TALER_PQ_result_spec_amount ("amount_with_fee", &coin_amount),
|
||||||
|
TALER_PQ_result_spec_amount ("deposit_fee", &coin_fee),
|
||||||
|
TALER_PQ_result_spec_absolute_time ("wire_deadline", &exec_time),
|
||||||
|
TALER_PQ_result_spec_end
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK != TALER_PQ_extract_result (result, rs, 0))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
cb (cb_cls,
|
||||||
|
NULL,
|
||||||
|
&coin_amount,
|
||||||
|
&coin_fee,
|
||||||
|
NULL,
|
||||||
|
exec_time);
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (1 != nrows)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
struct TALER_WireTransferIdentifierRawP wtid;
|
||||||
|
struct GNUNET_TIME_Absolute exec_time;
|
||||||
|
struct TALER_Amount coin_amount;
|
||||||
|
struct TALER_Amount coin_fee;
|
||||||
|
struct TALER_Amount transaction_amount;
|
||||||
|
struct TALER_PQ_ResultSpec rs[] = {
|
||||||
|
TALER_PQ_result_spec_auto_from_type ("wtid_raw", &wtid),
|
||||||
|
TALER_PQ_result_spec_absolute_time ("execution_time", &exec_time),
|
||||||
|
TALER_PQ_result_spec_amount ("coin_amount", &coin_amount),
|
||||||
|
TALER_PQ_result_spec_amount ("coin_fee", &coin_fee),
|
||||||
|
TALER_PQ_result_spec_amount ("transfer_total", &transaction_amount),
|
||||||
|
TALER_PQ_result_spec_end
|
||||||
|
};
|
||||||
|
if (GNUNET_OK != TALER_PQ_extract_result (result, rs, 0))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
cb (cb_cls,
|
||||||
|
&wtid,
|
||||||
|
&coin_amount,
|
||||||
|
&coin_fee,
|
||||||
|
&transaction_amount,
|
||||||
|
exec_time);
|
||||||
|
}
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3501,29 +3726,64 @@ postgres_wire_lookup_deposit_wtid (void *cls,
|
|||||||
* Function called to insert aggregation information into the DB.
|
* Function called to insert aggregation information into the DB.
|
||||||
*
|
*
|
||||||
* @param cls closure
|
* @param cls closure
|
||||||
|
* @param session database connection
|
||||||
* @param wtid the raw wire transfer identifier we used
|
* @param wtid the raw wire transfer identifier we used
|
||||||
* @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls)
|
* @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls)
|
||||||
* @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls)
|
* @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls)
|
||||||
* @param h_contract which contract was this payment about
|
* @param h_contract which contract was this payment about
|
||||||
* @param transaction_id merchant's transaction ID for the payment
|
* @param transaction_id merchant's transaction ID for the payment
|
||||||
* @param coin_pub which public key was this payment about
|
* @param coin_pub which public key was this payment about
|
||||||
* @param deposit_value amount contributed by this coin in total
|
* @param coin_value amount contributed by this coin in total
|
||||||
* @param deposit_fee deposit fee charged by mint for this coin
|
* @param coin_fee deposit fee charged by mint for this coin
|
||||||
|
* @param transfer_value total amount of the wire transfer
|
||||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
postgres_insert_aggregation_tracking (void *cls,
|
postgres_insert_aggregation_tracking (void *cls,
|
||||||
|
struct TALER_MINTDB_Session *session,
|
||||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
const struct GNUNET_HashCode *h_wire,
|
const struct GNUNET_HashCode *h_wire,
|
||||||
const struct GNUNET_HashCode *h_contract,
|
const struct GNUNET_HashCode *h_contract,
|
||||||
uint64_t transaction_id,
|
uint64_t transaction_id,
|
||||||
|
struct GNUNET_TIME_Absolute execution_time,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
const struct TALER_Amount *deposit_value,
|
const struct TALER_Amount *coin_value,
|
||||||
const struct TALER_Amount *deposit_fee)
|
const struct TALER_Amount *coin_fee,
|
||||||
|
const struct TALER_Amount *transfer_value)
|
||||||
{
|
{
|
||||||
GNUNET_break (0); // not implemented
|
struct TALER_PQ_QueryParam params[] = {
|
||||||
|
TALER_PQ_query_param_auto_from_type (h_contract),
|
||||||
|
TALER_PQ_query_param_auto_from_type (h_wire),
|
||||||
|
TALER_PQ_query_param_auto_from_type (coin_pub),
|
||||||
|
TALER_PQ_query_param_auto_from_type (merchant_pub),
|
||||||
|
TALER_PQ_query_param_uint64 (&transaction_id),
|
||||||
|
TALER_PQ_query_param_auto_from_type (wtid),
|
||||||
|
TALER_PQ_query_param_absolute_time (&execution_time),
|
||||||
|
TALER_PQ_query_param_amount (coin_value),
|
||||||
|
TALER_PQ_query_param_amount (coin_fee),
|
||||||
|
TALER_PQ_query_param_amount (transfer_value),
|
||||||
|
TALER_PQ_query_param_end
|
||||||
|
};
|
||||||
|
PGresult *result;
|
||||||
|
|
||||||
|
result = TALER_PQ_exec_prepared (session->conn,
|
||||||
|
"insert_aggregation_tracking",
|
||||||
|
params);
|
||||||
|
if (PGRES_COMMAND_OK != PQresultStatus (result))
|
||||||
|
{
|
||||||
|
BREAK_DB_ERR (result);
|
||||||
|
PQclear (result);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
if (0 != strcmp ("1", PQcmdTuples (result)))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
PQclear (result);
|
||||||
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3596,7 +3856,7 @@ libtaler_plugin_mintdb_postgres_init (void *cls)
|
|||||||
plugin->get_transfer = &postgres_get_transfer;
|
plugin->get_transfer = &postgres_get_transfer;
|
||||||
plugin->get_coin_transactions = &postgres_get_coin_transactions;
|
plugin->get_coin_transactions = &postgres_get_coin_transactions;
|
||||||
plugin->free_coin_transaction_list = &common_free_coin_transaction_list;
|
plugin->free_coin_transaction_list = &common_free_coin_transaction_list;
|
||||||
plugin->lookup_wire_transactions = &postgres_lookup_wire_transactions;
|
plugin->lookup_wire_transfer = &postgres_lookup_wire_transfer;
|
||||||
plugin->wire_lookup_deposit_wtid = &postgres_wire_lookup_deposit_wtid;
|
plugin->wire_lookup_deposit_wtid = &postgres_wire_lookup_deposit_wtid;
|
||||||
plugin->insert_aggregation_tracking = &postgres_insert_aggregation_tracking;
|
plugin->insert_aggregation_tracking = &postgres_insert_aggregation_tracking;
|
||||||
return plugin;
|
return plugin;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2014, 2015 GNUnet e.V.
|
Copyright (C) 2014, 2015, 2016 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 General Public License as published by the Free Software
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -14,7 +14,7 @@
|
|||||||
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @file mint/test_mintdb.c
|
* @file mintdb/test_mintdb.c
|
||||||
* @brief test cases for DB interaction functions
|
* @brief test cases for DB interaction functions
|
||||||
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
|
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
|
||||||
*/
|
*/
|
||||||
@ -305,8 +305,10 @@ test_melting (struct TALER_MINTDB_Session *session)
|
|||||||
RND_BLK (&refresh_session);
|
RND_BLK (&refresh_session);
|
||||||
RND_BLK (&session_hash);
|
RND_BLK (&session_hash);
|
||||||
melts = NULL;
|
melts = NULL;
|
||||||
|
dkp = NULL;
|
||||||
new_dkp = NULL;
|
new_dkp = NULL;
|
||||||
new_denom_pubs = NULL;
|
new_denom_pubs = NULL;
|
||||||
|
ret_denom_pubs = NULL;
|
||||||
/* create and test a refresh session */
|
/* create and test a refresh session */
|
||||||
refresh_session.num_oldcoins = MELT_OLD_COINS;
|
refresh_session.num_oldcoins = MELT_OLD_COINS;
|
||||||
refresh_session.num_newcoins = 1;
|
refresh_session.num_newcoins = 1;
|
||||||
@ -324,7 +326,7 @@ test_melting (struct TALER_MINTDB_Session *session)
|
|||||||
sizeof (refresh_session)));
|
sizeof (refresh_session)));
|
||||||
|
|
||||||
/* create a denomination (value: 1; fraction: 100) */
|
/* create a denomination (value: 1; fraction: 100) */
|
||||||
dkp = create_denom_key_pair(512, session,
|
dkp = create_denom_key_pair (512, session,
|
||||||
&value,
|
&value,
|
||||||
&fee_withdraw,
|
&fee_withdraw,
|
||||||
&fee_deposit,
|
&fee_deposit,
|
||||||
@ -416,6 +418,7 @@ test_melting (struct TALER_MINTDB_Session *session)
|
|||||||
ret = GNUNET_OK;
|
ret = GNUNET_OK;
|
||||||
|
|
||||||
drop:
|
drop:
|
||||||
|
if (NULL != dkp)
|
||||||
destroy_denom_key_pair (dkp);
|
destroy_denom_key_pair (dkp);
|
||||||
if (NULL != melts)
|
if (NULL != melts)
|
||||||
{
|
{
|
||||||
@ -439,6 +442,114 @@ test_melting (struct TALER_MINTDB_Session *session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback that should never be called.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
cb_wt_never (void *cls,
|
||||||
|
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
|
const struct GNUNET_HashCode *h_wire,
|
||||||
|
const struct GNUNET_HashCode *h_contract,
|
||||||
|
uint64_t transaction_id,
|
||||||
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
|
const struct TALER_Amount *coin_value,
|
||||||
|
const struct TALER_Amount *coin_fee,
|
||||||
|
const struct TALER_Amount *transfer_value)
|
||||||
|
{
|
||||||
|
GNUNET_assert (0); /* this statement should be unreachable */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback that should never be called.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
cb_wtid_never (void *cls,
|
||||||
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
|
const struct TALER_Amount *coin_contribution,
|
||||||
|
const struct TALER_Amount *coin_fee,
|
||||||
|
const struct TALER_Amount *total_amount,
|
||||||
|
struct GNUNET_TIME_Absolute execution_time)
|
||||||
|
{
|
||||||
|
GNUNET_assert (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct TALER_MerchantPublicKeyP merchant_pub_wt;
|
||||||
|
static struct GNUNET_HashCode h_wire_wt;
|
||||||
|
static struct GNUNET_HashCode h_contract_wt;
|
||||||
|
static uint64_t transaction_id_wt;
|
||||||
|
static struct TALER_CoinSpendPublicKeyP coin_pub_wt;
|
||||||
|
static struct TALER_Amount coin_value_wt;
|
||||||
|
static struct TALER_Amount coin_fee_wt;
|
||||||
|
static struct TALER_Amount transfer_value_wt;
|
||||||
|
static struct GNUNET_TIME_Absolute execution_time_wt;
|
||||||
|
static struct TALER_WireTransferIdentifierRawP wtid_wt;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback that should be called with the WT data.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
cb_wt_check (void *cls,
|
||||||
|
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||||
|
const struct GNUNET_HashCode *h_wire,
|
||||||
|
const struct GNUNET_HashCode *h_contract,
|
||||||
|
uint64_t transaction_id,
|
||||||
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
|
const struct TALER_Amount *coin_value,
|
||||||
|
const struct TALER_Amount *coin_fee,
|
||||||
|
const struct TALER_Amount *transfer_value)
|
||||||
|
{
|
||||||
|
GNUNET_assert (cls == &cb_wt_never);
|
||||||
|
GNUNET_assert (0 == memcmp (merchant_pub,
|
||||||
|
&merchant_pub_wt,
|
||||||
|
sizeof (struct TALER_MerchantPublicKeyP)));
|
||||||
|
GNUNET_assert (0 == memcmp (h_wire,
|
||||||
|
&h_wire_wt,
|
||||||
|
sizeof (struct GNUNET_HashCode)));
|
||||||
|
GNUNET_assert (0 == memcmp (h_contract,
|
||||||
|
&h_contract_wt,
|
||||||
|
sizeof (struct GNUNET_HashCode)));
|
||||||
|
GNUNET_assert (transaction_id == transaction_id_wt);
|
||||||
|
GNUNET_assert (0 == memcmp (coin_pub,
|
||||||
|
&coin_pub_wt,
|
||||||
|
sizeof (struct TALER_CoinSpendPublicKeyP)));
|
||||||
|
GNUNET_assert (0 == TALER_amount_cmp (coin_value,
|
||||||
|
&coin_value_wt));
|
||||||
|
GNUNET_assert (0 == TALER_amount_cmp (coin_fee,
|
||||||
|
&coin_fee_wt));
|
||||||
|
GNUNET_assert (0 == TALER_amount_cmp (transfer_value,
|
||||||
|
&transfer_value_wt));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback that should be called with the WT data.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
cb_wtid_check (void *cls,
|
||||||
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
|
const struct TALER_Amount *coin_contribution,
|
||||||
|
const struct TALER_Amount *coin_fee,
|
||||||
|
const struct TALER_Amount *total_amount,
|
||||||
|
struct GNUNET_TIME_Absolute execution_time)
|
||||||
|
{
|
||||||
|
GNUNET_assert (cls == &cb_wtid_never);
|
||||||
|
GNUNET_assert (0 == memcmp (wtid,
|
||||||
|
&wtid_wt,
|
||||||
|
sizeof (struct TALER_WireTransferIdentifierRawP)));
|
||||||
|
GNUNET_assert (execution_time.abs_value_us ==
|
||||||
|
execution_time_wt.abs_value_us);
|
||||||
|
GNUNET_assert (0 == TALER_amount_cmp (coin_contribution,
|
||||||
|
&coin_value_wt));
|
||||||
|
GNUNET_assert (0 == TALER_amount_cmp (coin_fee,
|
||||||
|
&coin_fee_wt));
|
||||||
|
GNUNET_assert (0 == TALER_amount_cmp (total_amount,
|
||||||
|
&transfer_value_wt));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main function that will be run by the scheduler.
|
* Main function that will be run by the scheduler.
|
||||||
*
|
*
|
||||||
@ -455,7 +566,6 @@ run (void *cls,
|
|||||||
{
|
{
|
||||||
struct TALER_MINTDB_Session *session;
|
struct TALER_MINTDB_Session *session;
|
||||||
struct TALER_ReservePublicKeyP reserve_pub;
|
struct TALER_ReservePublicKeyP reserve_pub;
|
||||||
struct TALER_Amount amount;
|
|
||||||
struct DenomKeyPair *dkp;
|
struct DenomKeyPair *dkp;
|
||||||
struct TALER_MINTDB_CollectableBlindcoin cbc;
|
struct TALER_MINTDB_CollectableBlindcoin cbc;
|
||||||
struct TALER_MINTDB_CollectableBlindcoin cbc2;
|
struct TALER_MINTDB_CollectableBlindcoin cbc2;
|
||||||
@ -465,6 +575,7 @@ run (void *cls,
|
|||||||
struct TALER_MINTDB_CollectableBlindcoin *withdraw;
|
struct TALER_MINTDB_CollectableBlindcoin *withdraw;
|
||||||
struct TALER_MINTDB_Deposit deposit;
|
struct TALER_MINTDB_Deposit deposit;
|
||||||
struct TALER_MINTDB_Deposit deposit2;
|
struct TALER_MINTDB_Deposit deposit2;
|
||||||
|
struct TALER_WireTransferIdentifierRawP wtid;
|
||||||
json_t *wire;
|
json_t *wire;
|
||||||
json_t *just;
|
json_t *just;
|
||||||
const char * const json_wire_str =
|
const char * const json_wire_str =
|
||||||
@ -563,11 +674,7 @@ run (void *cls,
|
|||||||
= GNUNET_CRYPTO_rsa_sign (dkp->priv.rsa_private_key,
|
= GNUNET_CRYPTO_rsa_sign (dkp->priv.rsa_private_key,
|
||||||
&cbc.h_coin_envelope,
|
&cbc.h_coin_envelope,
|
||||||
sizeof (cbc.h_coin_envelope));
|
sizeof (cbc.h_coin_envelope));
|
||||||
(void) memcpy (&cbc.reserve_pub,
|
cbc.reserve_pub = reserve_pub;
|
||||||
&reserve_pub,
|
|
||||||
sizeof (reserve_pub));
|
|
||||||
amount.value--;
|
|
||||||
amount.fraction--;
|
|
||||||
cbc.amount_with_fee = value;
|
cbc.amount_with_fee = value;
|
||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_amount_get_zero (CURRENCY, &cbc.withdraw_fee));
|
TALER_amount_get_zero (CURRENCY, &cbc.withdraw_fee));
|
||||||
@ -652,9 +759,7 @@ run (void *cls,
|
|||||||
plugin->have_deposit (plugin->cls,
|
plugin->have_deposit (plugin->cls,
|
||||||
session,
|
session,
|
||||||
&deposit));
|
&deposit));
|
||||||
(void) memcpy (&deposit2,
|
deposit2 = deposit;
|
||||||
&deposit,
|
|
||||||
sizeof (deposit));
|
|
||||||
deposit2.transaction_id++; /* should fail if transaction id is different */
|
deposit2.transaction_id++; /* should fail if transaction id is different */
|
||||||
FAILIF (GNUNET_NO !=
|
FAILIF (GNUNET_NO !=
|
||||||
plugin->have_deposit (plugin->cls,
|
plugin->have_deposit (plugin->cls,
|
||||||
@ -666,15 +771,79 @@ run (void *cls,
|
|||||||
plugin->have_deposit (plugin->cls,
|
plugin->have_deposit (plugin->cls,
|
||||||
session,
|
session,
|
||||||
&deposit2));
|
&deposit2));
|
||||||
(void) memcpy (&deposit2.merchant_pub,
|
deposit2.merchant_pub = deposit.merchant_pub;
|
||||||
&deposit.merchant_pub,
|
|
||||||
sizeof (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 (GNUNET_NO !=
|
||||||
plugin->have_deposit (plugin->cls,
|
plugin->have_deposit (plugin->cls,
|
||||||
session,
|
session,
|
||||||
&deposit2));
|
&deposit2));
|
||||||
FAILIF (GNUNET_OK != test_melting (session));
|
FAILIF (GNUNET_OK != test_melting (session));
|
||||||
|
|
||||||
|
/* setup values for wire transfer aggregation data */
|
||||||
|
memset (&wtid, 42, sizeof (wtid));
|
||||||
|
memset (&merchant_pub_wt, 43, sizeof (merchant_pub_wt));
|
||||||
|
memset (&h_wire_wt, 44, sizeof (h_wire_wt));
|
||||||
|
memset (&h_contract_wt, 45, sizeof (h_contract_wt));
|
||||||
|
memset (&coin_pub_wt, 46, sizeof (coin_pub_wt));
|
||||||
|
transaction_id_wt = 47;
|
||||||
|
execution_time_wt = GNUNET_TIME_absolute_get ();
|
||||||
|
memset (&merchant_pub_wt, 48, sizeof (merchant_pub_wt));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_string_to_amount (CURRENCY "KUDOS:1.000010",
|
||||||
|
&coin_value_wt));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_string_to_amount (CURRENCY "KUDOS:0.000010",
|
||||||
|
&coin_fee_wt));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_string_to_amount (CURRENCY "KUDOS:1.000000",
|
||||||
|
&transfer_value_wt));
|
||||||
|
|
||||||
|
FAILIF (GNUNET_NO !=
|
||||||
|
plugin->lookup_wire_transfer (plugin->cls,
|
||||||
|
session,
|
||||||
|
&wtid_wt,
|
||||||
|
&cb_wt_never,
|
||||||
|
NULL));
|
||||||
|
FAILIF (GNUNET_NO !=
|
||||||
|
plugin->wire_lookup_deposit_wtid (plugin->cls,
|
||||||
|
session,
|
||||||
|
&h_contract_wt,
|
||||||
|
&h_wire_wt,
|
||||||
|
&coin_pub_wt,
|
||||||
|
&merchant_pub_wt,
|
||||||
|
transaction_id_wt,
|
||||||
|
&cb_wtid_never,
|
||||||
|
NULL));
|
||||||
|
/* insert WT data */
|
||||||
|
FAILIF (GNUNET_OK !=
|
||||||
|
plugin->insert_aggregation_tracking (plugin->cls,
|
||||||
|
session,
|
||||||
|
&wtid_wt,
|
||||||
|
&merchant_pub_wt,
|
||||||
|
&h_wire_wt,
|
||||||
|
&h_contract_wt,
|
||||||
|
transaction_id_wt,
|
||||||
|
execution_time_wt,
|
||||||
|
&coin_pub_wt,
|
||||||
|
&coin_value_wt,
|
||||||
|
&coin_fee_wt,
|
||||||
|
&transfer_value_wt));
|
||||||
|
FAILIF (GNUNET_OK !=
|
||||||
|
plugin->lookup_wire_transfer (plugin->cls,
|
||||||
|
session,
|
||||||
|
&wtid_wt,
|
||||||
|
&cb_wt_check,
|
||||||
|
&cb_wt_never));
|
||||||
|
FAILIF (GNUNET_OK !=
|
||||||
|
plugin->wire_lookup_deposit_wtid (plugin->cls,
|
||||||
|
session,
|
||||||
|
&h_contract_wt,
|
||||||
|
&h_wire_wt,
|
||||||
|
&coin_pub_wt,
|
||||||
|
&merchant_pub_wt,
|
||||||
|
transaction_id_wt,
|
||||||
|
&cb_wtid_check,
|
||||||
|
&cb_wtid_never));
|
||||||
result = 0;
|
result = 0;
|
||||||
|
|
||||||
drop:
|
drop:
|
||||||
|
Loading…
Reference in New Issue
Block a user