From b5cba3251053c22bf1df46282f1dd0a4c46f6a38 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 1 Mar 2016 15:35:04 +0100 Subject: renaming mint->exchange --- src/exchangedb/test_exchangedb.c | 907 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 907 insertions(+) create mode 100644 src/exchangedb/test_exchangedb.c (limited to 'src/exchangedb/test_exchangedb.c') diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c new file mode 100644 index 000000000..df1adf561 --- /dev/null +++ b/src/exchangedb/test_exchangedb.c @@ -0,0 +1,907 @@ +/* + 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 +*/ +/** + * @file exchangedb/test_exchangedb.c + * @brief test cases for DB interaction functions + * @author Sree Harsha Totakura + */ +#include "platform.h" +#include "taler_exchangedb_lib.h" +#include "taler_exchangedb_plugin.h" + +static int result; + +#define FAILIF(cond) \ + do { \ + if (!(cond)){ break;} \ + GNUNET_break (0); \ + goto drop; \ + } while (0) + + +#define RND_BLK(ptr) \ + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr)) + +#define ZR_BLK(ptr) \ + memset (ptr, 0, sizeof (*ptr)) + + +#define CURRENCY "EUR" + +static struct TALER_EXCHANGEDB_Plugin *plugin; + +/** + * Checks if the given reserve has the given amount of balance and expiry + * + * @param session the database connection + * @param pub the public key of the reserve + * @param value balance value + * @param fraction balance fraction + * @param currency currency of the reserve + * @return #GNUNET_OK if the given reserve has the same balance and expiration + * as the given parameters; #GNUNET_SYSERR if not + */ +static int +check_reserve (struct TALER_EXCHANGEDB_Session *session, + const struct TALER_ReservePublicKeyP *pub, + uint64_t value, + uint32_t fraction, + const char *currency) +{ + struct TALER_EXCHANGEDB_Reserve reserve; + + reserve.pub = *pub; + + FAILIF (GNUNET_OK != + plugin->reserve_get (plugin->cls, + session, + &reserve)); + FAILIF (value != reserve.balance.value); + FAILIF (fraction != reserve.balance.fraction); + FAILIF (0 != strcmp (currency, reserve.balance.currency)); + + return GNUNET_OK; + drop: + return GNUNET_SYSERR; +} + + +struct DenomKeyPair +{ + struct TALER_DenominationPrivateKey priv; + struct TALER_DenominationPublicKey pub; +}; + + +/** + * Destroy a denomination key pair. The key is not necessarily removed from the DB. + * + * @param dkp the keypair to destroy + */ +static void +destroy_denom_key_pair (struct DenomKeyPair *dkp) +{ + GNUNET_CRYPTO_rsa_public_key_free (dkp->pub.rsa_public_key); + GNUNET_CRYPTO_rsa_private_key_free (dkp->priv.rsa_private_key); + GNUNET_free (dkp); +} + + +/** + * Create a denominaiton key pair by registering the denomination in the DB. + * + * @param size the size of the denomination key + * @param session the DB session + * @return the denominaiton key pair; NULL upon error + */ +static struct DenomKeyPair * +create_denom_key_pair (unsigned int size, + struct TALER_EXCHANGEDB_Session *session, + const struct TALER_Amount *value, + const struct TALER_Amount *fee_withdraw, + const struct TALER_Amount *fee_deposit, + const struct TALER_Amount *fee_refresh) +{ + struct DenomKeyPair *dkp; + struct TALER_EXCHANGEDB_DenominationKeyIssueInformation dki; + + dkp = GNUNET_new (struct DenomKeyPair); + dkp->priv.rsa_private_key = GNUNET_CRYPTO_rsa_private_key_create (size); + GNUNET_assert (NULL != dkp->priv.rsa_private_key); + dkp->pub.rsa_public_key + = GNUNET_CRYPTO_rsa_private_key_get_public (dkp->priv.rsa_private_key); + + /* Using memset() as fields like master key and signature + are not properly initialized for this test. */ + memset (&dki, + 0, + sizeof (struct TALER_EXCHANGEDB_DenominationKeyIssueInformation)); + dki.denom_pub = dkp->pub; + dki.issue.properties.start = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); + dki.issue.properties.expire_withdraw = GNUNET_TIME_absolute_hton + (GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), + GNUNET_TIME_UNIT_HOURS)); + dki.issue.properties.expire_spend = GNUNET_TIME_absolute_hton + (GNUNET_TIME_absolute_add + (GNUNET_TIME_absolute_get (), + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 2))); + dki.issue.properties.expire_legal = GNUNET_TIME_absolute_hton + (GNUNET_TIME_absolute_add + (GNUNET_TIME_absolute_get (), + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 3))); + TALER_amount_hton (&dki.issue.properties.value, value); + TALER_amount_hton (&dki.issue.properties.fee_withdraw, fee_withdraw); + TALER_amount_hton (&dki.issue.properties.fee_deposit, fee_deposit); + TALER_amount_hton (&dki.issue.properties.fee_refresh, fee_refresh); + GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key, + &dki.issue.properties.denom_hash); + if (GNUNET_OK != + plugin->insert_denomination_info (plugin->cls, + session, + &dki.denom_pub, + &dki.issue)) + { + GNUNET_break(0); + destroy_denom_key_pair (dkp); + return NULL; + } + return dkp; +} + +static struct TALER_Amount value; +static struct TALER_Amount fee_withdraw; +static struct TALER_Amount fee_deposit; +static struct TALER_Amount fee_refresh; +static struct TALER_Amount amount_with_fee; + +static void +free_refresh_commit_coins_array(struct TALER_EXCHANGEDB_RefreshCommitCoin + *commit_coins, + unsigned int size) +{ + unsigned int cnt; + struct TALER_EXCHANGEDB_RefreshCommitCoin *ccoin; + struct TALER_RefreshLinkEncrypted *rlink; + + for (cnt = 0; cnt < size; cnt++) + { + ccoin = &commit_coins[cnt]; + GNUNET_free_non_null (ccoin->coin_ev); + rlink = (struct TALER_RefreshLinkEncrypted *) ccoin->refresh_link; + GNUNET_free_non_null (rlink); + } + GNUNET_free (commit_coins); +} + +#define MELT_NEW_COINS 5 + +static int +test_refresh_commit_coins (struct TALER_EXCHANGEDB_Session *session, + struct TALER_EXCHANGEDB_RefreshSession *refresh_session, + const struct GNUNET_HashCode *session_hash) +{ + struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins; + struct TALER_EXCHANGEDB_RefreshCommitCoin *ret_commit_coins; + struct TALER_EXCHANGEDB_RefreshCommitCoin *a_ccoin; + struct TALER_RefreshLinkEncrypted *a_rlink; + struct TALER_EXCHANGEDB_RefreshCommitCoin *b_ccoin; + struct TALER_RefreshLinkEncrypted *b_rlink; + size_t size; + unsigned int cnt; + uint16_t cnc_index; + int ret; + + #define COIN_ENC_MAX_SIZE 512 + ret = GNUNET_SYSERR; + ret_commit_coins = NULL; + commit_coins = GNUNET_new_array (MELT_NEW_COINS, + struct TALER_EXCHANGEDB_RefreshCommitCoin); + cnc_index = (uint16_t) GNUNET_CRYPTO_random_u32 + (GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_MIN (MELT_NEW_COINS, UINT16_MAX)); + for (cnt=0; cnt < MELT_NEW_COINS; cnt++) + { + struct TALER_EXCHANGEDB_RefreshCommitCoin *ccoin; + struct TALER_RefreshLinkEncrypted *rlink; + ccoin = &commit_coins[cnt]; + size = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, + COIN_ENC_MAX_SIZE); + rlink = GNUNET_malloc (sizeof (struct TALER_RefreshLinkEncrypted) + size); + ccoin->refresh_link = rlink; + ccoin->coin_ev_size = GNUNET_CRYPTO_random_u64 + (GNUNET_CRYPTO_QUALITY_WEAK, COIN_ENC_MAX_SIZE); + ccoin->coin_ev = GNUNET_malloc (ccoin->coin_ev_size); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, + ccoin->coin_ev, + ccoin->coin_ev_size); + rlink->blinding_key_enc_size = size; + RND_BLK (&rlink->coin_priv_enc); + rlink->blinding_key_enc = (const char *) &rlink[1]; + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, + (void *)rlink->blinding_key_enc, + rlink->blinding_key_enc_size); + } + FAILIF (GNUNET_OK != + plugin->insert_refresh_commit_coins (plugin->cls, + session, + session_hash, + cnc_index, + MELT_NEW_COINS, + commit_coins)); + ret_commit_coins = GNUNET_new_array (MELT_NEW_COINS, + struct TALER_EXCHANGEDB_RefreshCommitCoin); + FAILIF (GNUNET_OK != + plugin->get_refresh_commit_coins (plugin->cls, + session, + session_hash, + cnc_index, + MELT_NEW_COINS, + ret_commit_coins)); + /* compare the refresh commit coin arrays */ + for (cnt = 0; cnt < MELT_NEW_COINS; cnt++) + { + a_ccoin = &commit_coins[cnt]; + b_ccoin = &ret_commit_coins[cnt]; + FAILIF (a_ccoin->coin_ev_size != b_ccoin->coin_ev_size); + FAILIF (0 != memcmp (a_ccoin->coin_ev, + a_ccoin->coin_ev, + a_ccoin->coin_ev_size)); + a_rlink = a_ccoin->refresh_link; + b_rlink = b_ccoin->refresh_link; + FAILIF (a_rlink->blinding_key_enc_size != b_rlink->blinding_key_enc_size); + FAILIF (0 != memcmp (a_rlink->blinding_key_enc, + b_rlink->blinding_key_enc, + a_rlink->blinding_key_enc_size)); + FAILIF (0 != memcmp (a_rlink->coin_priv_enc, + b_rlink->coin_priv_enc, + sizeof (a_rlink->coin_priv_enc))); + } + ret = GNUNET_OK; + + drop: + if (NULL != ret_commit_coins) + free_refresh_commit_coins_array (ret_commit_coins, MELT_NEW_COINS); + if (NULL != commit_coins) + free_refresh_commit_coins_array (commit_coins, MELT_NEW_COINS); + return ret; +} + +/** + * Function to test melting of coins as part of a refresh session + * + * @param session the database session + * @param refresh_session the refresh session + * @return #GNUNET_OK if everything went well; #GNUNET_SYSERR if not + */ +static int +test_melting (struct TALER_EXCHANGEDB_Session *session) +{ +#define MELT_OLD_COINS 10 + struct TALER_EXCHANGEDB_RefreshSession refresh_session; + struct TALER_EXCHANGEDB_RefreshSession ret_refresh_session; + struct GNUNET_HashCode session_hash; + struct DenomKeyPair *dkp; + struct DenomKeyPair **new_dkp; + /* struct TALER_CoinPublicInfo *coins; */ + struct TALER_EXCHANGEDB_RefreshMelt *melts; + struct TALER_DenominationPublicKey *new_denom_pubs; + struct TALER_DenominationPublicKey *ret_denom_pubs; + unsigned int cnt; + int ret; + + ret = GNUNET_SYSERR; + RND_BLK (&refresh_session); + RND_BLK (&session_hash); + melts = NULL; + dkp = NULL; + new_dkp = NULL; + new_denom_pubs = NULL; + ret_denom_pubs = NULL; + /* create and test a refresh session */ + refresh_session.num_oldcoins = MELT_OLD_COINS; + refresh_session.num_newcoins = 1; + refresh_session.noreveal_index = 1; + FAILIF (GNUNET_OK != plugin->create_refresh_session (plugin->cls, + session, + &session_hash, + &refresh_session)); + FAILIF (GNUNET_OK != plugin->get_refresh_session (plugin->cls, + session, + &session_hash, + &ret_refresh_session)); + FAILIF (0 != memcmp (&ret_refresh_session, + &refresh_session, + sizeof (refresh_session))); + + /* create a denomination (value: 1; fraction: 100) */ + dkp = create_denom_key_pair (512, session, + &value, + &fee_withdraw, + &fee_deposit, + &fee_refresh); + /* create MELT_OLD_COINS number of refresh melts */ + melts = GNUNET_new_array (MELT_OLD_COINS, struct TALER_EXCHANGEDB_RefreshMelt); + for (cnt=0; cnt < MELT_OLD_COINS; cnt++) + { + RND_BLK (&melts[cnt].coin.coin_pub); + melts[cnt].coin.denom_sig.rsa_signature = + GNUNET_CRYPTO_rsa_sign (dkp->priv.rsa_private_key, + &melts[cnt].coin.coin_pub, + sizeof (melts[cnt].coin.coin_pub)); + melts[cnt].coin.denom_pub = dkp->pub; + RND_BLK (&melts[cnt].coin_sig); + melts[cnt].session_hash = session_hash; + melts[cnt].amount_with_fee = amount_with_fee; + melts[cnt].melt_fee = fee_refresh; + FAILIF (GNUNET_OK != plugin->insert_refresh_melt (plugin->cls, + session, + cnt, + &melts[cnt])); + } + for (cnt = 0; cnt < MELT_OLD_COINS; cnt++) + { + struct TALER_EXCHANGEDB_RefreshMelt ret_melt; + FAILIF (GNUNET_OK != plugin->get_refresh_melt (plugin->cls, + session, + &session_hash, + cnt, + &ret_melt)); + FAILIF (0 != GNUNET_CRYPTO_rsa_signature_cmp + (ret_melt.coin.denom_sig.rsa_signature, + melts[cnt].coin.denom_sig.rsa_signature)); + FAILIF (0 != memcmp (&ret_melt.coin.coin_pub, + &melts[cnt].coin.coin_pub, + sizeof (ret_melt.coin.coin_pub))); + FAILIF (0 != GNUNET_CRYPTO_rsa_public_key_cmp + (ret_melt.coin.denom_pub.rsa_public_key, + melts[cnt].coin.denom_pub.rsa_public_key)); + FAILIF (0 != memcmp (&ret_melt.coin_sig, + &melts[cnt].coin_sig, + sizeof (ret_melt.coin_sig))); + FAILIF (0 != memcmp (&ret_melt.session_hash, + &melts[cnt].session_hash, + sizeof (ret_melt.session_hash))); + FAILIF (0 != TALER_amount_cmp (&ret_melt.amount_with_fee, + &melts[cnt].amount_with_fee)); + FAILIF (0 != TALER_amount_cmp (&ret_melt.melt_fee, + &melts[cnt].melt_fee)); + GNUNET_CRYPTO_rsa_signature_free (ret_melt.coin.denom_sig.rsa_signature); + GNUNET_CRYPTO_rsa_public_key_free (ret_melt.coin.denom_pub.rsa_public_key); + } + new_dkp = GNUNET_new_array (MELT_NEW_COINS, struct DenomKeyPair *); + new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS, + struct TALER_DenominationPublicKey); + for (cnt=0; cnt < MELT_NEW_COINS; cnt++) + { + new_dkp[cnt] = create_denom_key_pair (128, session, + &value, + &fee_withdraw, + &fee_deposit, + &fee_refresh); + new_denom_pubs[cnt]=new_dkp[cnt]->pub; + } + FAILIF (GNUNET_OK != plugin->insert_refresh_order (plugin->cls, + session, + &session_hash, + MELT_NEW_COINS, + new_denom_pubs)); + ret_denom_pubs = GNUNET_new_array (MELT_NEW_COINS, + struct TALER_DenominationPublicKey); + FAILIF (GNUNET_OK != plugin->get_refresh_order (plugin->cls, + session, + &session_hash, + MELT_NEW_COINS, + ret_denom_pubs)); + for (cnt=0; cnt < MELT_NEW_COINS; cnt++) + { + FAILIF (0 != GNUNET_CRYPTO_rsa_public_key_cmp + (ret_denom_pubs[cnt].rsa_public_key, + new_denom_pubs[cnt].rsa_public_key)); + } + FAILIF (GNUNET_OK != + test_refresh_commit_coins (session, + &refresh_session, + &session_hash)); + + ret = GNUNET_OK; + + drop: + if (NULL != dkp) + destroy_denom_key_pair (dkp); + if (NULL != melts) + { + for (cnt = 0; cnt < MELT_OLD_COINS; cnt++) + GNUNET_CRYPTO_rsa_signature_free (melts[cnt].coin.denom_sig.rsa_signature); + GNUNET_free (melts); + } + for (cnt = 0; + (NULL != ret_denom_pubs) && (cnt < MELT_NEW_COINS) + && (NULL != ret_denom_pubs[cnt].rsa_public_key); + cnt++) + GNUNET_CRYPTO_rsa_public_key_free (ret_denom_pubs[cnt].rsa_public_key); + GNUNET_free_non_null (ret_denom_pubs); + GNUNET_free_non_null (new_denom_pubs); + for (cnt = 0; + (NULL != new_dkp) && (cnt < MELT_NEW_COINS) && (NULL != new_dkp[cnt]); + cnt++) + destroy_denom_key_pair (new_dkp[cnt]); + GNUNET_free_non_null (new_dkp); + return ret; +} + + +/** + * 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) +{ + 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, + 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) +{ + 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)); +} + + +/** + * 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, + 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)); +} + + +/** + * Main function that will be run by the scheduler. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct TALER_EXCHANGEDB_Session *session; + struct TALER_ReservePublicKeyP reserve_pub; + struct DenomKeyPair *dkp; + struct TALER_EXCHANGEDB_CollectableBlindcoin cbc; + struct TALER_EXCHANGEDB_CollectableBlindcoin cbc2; + struct TALER_EXCHANGEDB_ReserveHistory *rh; + struct TALER_EXCHANGEDB_ReserveHistory *rh_head; + struct TALER_EXCHANGEDB_BankTransfer *bt; + struct TALER_EXCHANGEDB_CollectableBlindcoin *withdraw; + struct TALER_EXCHANGEDB_Deposit deposit; + struct TALER_EXCHANGEDB_Deposit deposit2; + struct TALER_WireTransferIdentifierRawP wtid; + json_t *wire; + json_t *just; + const char * const json_wire_str = + "{ \"type\":\"SEPA\", \ +\"IBAN\":\"DE67830654080004822650\", \ +\"name\":\"GNUnet e.V.\", \ +\"bic\":\"GENODEF1SLR\", \ +\"edate\":\"1449930207000\", \ +\"r\":123456789, \ +\"address\": \"foobar\"}"; + unsigned int cnt; + + dkp = NULL; + rh = NULL; + wire = NULL; + session = NULL; + ZR_BLK (&cbc); + ZR_BLK (&cbc2); + if (NULL == + (plugin = TALER_EXCHANGEDB_plugin_load (cfg))) + { + result = 1; + return; + } + if (GNUNET_OK != + plugin->create_tables (plugin->cls, + GNUNET_YES)) + { + result = 2; + goto drop; + } + if (NULL == + (session = plugin->get_session (plugin->cls, + GNUNET_YES))) + { + result = 3; + goto drop; + } + RND_BLK (&reserve_pub); + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (CURRENCY ":1.000010", + &value)); + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (CURRENCY ":0.000010", + &fee_withdraw)); + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (CURRENCY ":0.000010", + &fee_deposit)); + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (CURRENCY ":0.000010", + &fee_refresh)); + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (CURRENCY ":1.000010", + &amount_with_fee)); + + result = 4; + just = json_loads ("{ \"justification\":\"1\" }", 0, NULL); + FAILIF (GNUNET_OK != + plugin->reserves_in_insert (plugin->cls, + session, + &reserve_pub, + &value, + GNUNET_TIME_absolute_get (), + just)); + json_decref (just); + FAILIF (GNUNET_OK != + check_reserve (session, + &reserve_pub, + value.value, + value.fraction, + value.currency)); + just = json_loads ("{ \"justification\":\"2\" }", 0, NULL); + FAILIF (GNUNET_OK != + plugin->reserves_in_insert (plugin->cls, + session, + &reserve_pub, + &value, + GNUNET_TIME_absolute_get (), + just)); + json_decref (just); + FAILIF (GNUNET_OK != + check_reserve (session, + &reserve_pub, + value.value * 2, + value.fraction * 2, + value.currency)); + dkp = create_denom_key_pair (1024, session, + &value, + &fee_withdraw, + &fee_deposit, + &fee_refresh); + RND_BLK(&cbc.h_coin_envelope); + RND_BLK(&cbc.reserve_sig); + cbc.denom_pub = dkp->pub; + cbc.sig.rsa_signature + = GNUNET_CRYPTO_rsa_sign (dkp->priv.rsa_private_key, + &cbc.h_coin_envelope, + sizeof (cbc.h_coin_envelope)); + cbc.reserve_pub = reserve_pub; + cbc.amount_with_fee = value; + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero (CURRENCY, &cbc.withdraw_fee)); + FAILIF (GNUNET_OK != + plugin->insert_withdraw_info (plugin->cls, + session, + &cbc)); + FAILIF (GNUNET_OK != + check_reserve (session, + &reserve_pub, + value.value, + value.fraction, + value.currency)); + FAILIF (GNUNET_YES != + plugin->get_withdraw_info (plugin->cls, + session, + &cbc.h_coin_envelope, + &cbc2)); + FAILIF (NULL == cbc2.denom_pub.rsa_public_key); + FAILIF (0 != memcmp (&cbc2.reserve_sig, + &cbc.reserve_sig, + sizeof (cbc2.reserve_sig))); + FAILIF (0 != memcmp (&cbc2.reserve_pub, + &cbc.reserve_pub, + sizeof (cbc2.reserve_pub))); + FAILIF (GNUNET_OK != + GNUNET_CRYPTO_rsa_verify (&cbc.h_coin_envelope, + cbc2.sig.rsa_signature, + dkp->pub.rsa_public_key)); + rh = plugin->get_reserve_history (plugin->cls, + session, + &reserve_pub); + FAILIF (NULL == rh); + rh_head = rh; + for (cnt=0; NULL != rh_head; rh_head=rh_head->next, cnt++) + { + switch (rh_head->type) + { + case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE: + bt = rh_head->details.bank; + FAILIF (0 != memcmp (&bt->reserve_pub, + &reserve_pub, + sizeof (reserve_pub))); + /* this is the amount we trasferred twice*/ + FAILIF (1 != bt->amount.value); + FAILIF (10 != bt->amount.fraction); + FAILIF (0 != strcmp (CURRENCY, bt->amount.currency)); + FAILIF (NULL == bt->wire); + break; + case TALER_EXCHANGEDB_RO_WITHDRAW_COIN: + withdraw = rh_head->details.withdraw; + FAILIF (0 != memcmp (&withdraw->reserve_pub, + &reserve_pub, + sizeof (reserve_pub))); + FAILIF (0 != memcmp (&withdraw->h_coin_envelope, + &cbc.h_coin_envelope, + sizeof (cbc.h_coin_envelope))); + break; + } + } + FAILIF (3 != cnt); + /* Tests for deposits */ + memset (&deposit, 0, sizeof (deposit)); + RND_BLK (&deposit.coin.coin_pub); + deposit.coin.denom_pub = dkp->pub; + deposit.coin.denom_sig = cbc.sig; + RND_BLK (&deposit.csig); + RND_BLK (&deposit.merchant_pub); + RND_BLK (&deposit.h_contract); + RND_BLK (&deposit.h_wire); + wire = json_loads (json_wire_str, 0, NULL); + deposit.wire = wire; + deposit.transaction_id = + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); + deposit.amount_with_fee = value; + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero (CURRENCY, &deposit.deposit_fee)); + FAILIF (GNUNET_OK != + plugin->insert_deposit (plugin->cls, + session, &deposit)); + FAILIF (GNUNET_YES != + plugin->have_deposit (plugin->cls, + session, + &deposit)); + deposit2 = deposit; + deposit2.transaction_id++; /* should fail if transaction id is different */ + FAILIF (GNUNET_NO != + plugin->have_deposit (plugin->cls, + session, + &deposit2)); + deposit2.transaction_id = deposit.transaction_id; + RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */ + FAILIF (GNUNET_NO != + plugin->have_deposit (plugin->cls, + session, + &deposit2)); + deposit2.merchant_pub = deposit.merchant_pub; + RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */ + FAILIF (GNUNET_NO != + plugin->have_deposit (plugin->cls, + session, + &deposit2)); + 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)); + 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; + + drop: + if (NULL != wire) + json_decref (wire); + if (NULL != rh) + plugin->free_reserve_history (plugin->cls, + rh); + rh = NULL; + if (NULL != session) + GNUNET_break (GNUNET_OK == + plugin->drop_temporary (plugin->cls, + session)); + if (NULL != dkp) + destroy_denom_key_pair (dkp); + if (NULL != cbc.sig.rsa_signature) + GNUNET_CRYPTO_rsa_signature_free (cbc.sig.rsa_signature); + if (NULL != cbc2.denom_pub.rsa_public_key) + GNUNET_CRYPTO_rsa_public_key_free (cbc2.denom_pub.rsa_public_key); + if (NULL != cbc2.sig.rsa_signature) + GNUNET_CRYPTO_rsa_signature_free (cbc2.sig.rsa_signature); + dkp = NULL; + TALER_EXCHANGEDB_plugin_unload (plugin); + plugin = NULL; +} + + +int +main (int argc, + char *const argv[]) +{ + static const struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + char *argv2[] = { + "test-exchange-db-", /* will be replaced later */ + "-c", "test-exchange-db-.conf", /* will be replaced later */ + NULL, + }; + const char *plugin_name; + char *config_filename; + char *testname; + + result = -1; + if (NULL == (plugin_name = strrchr (argv[0], (int) '-'))) + { + GNUNET_break (0); + return -1; + } + plugin_name++; + (void) GNUNET_asprintf (&testname, + "test-exchange-db-%s", plugin_name); + (void) GNUNET_asprintf (&config_filename, + "%s.conf", testname); + argv2[0] = argv[0]; + argv2[2] = config_filename; + if (GNUNET_OK != + GNUNET_PROGRAM_run ((sizeof (argv2)/sizeof (char *)) - 1, argv2, + testname, + "Test cases for exchange database helper functions.", + options, &run, NULL)) + { + GNUNET_free (config_filename); + GNUNET_free (testname); + return 3; + } + GNUNET_free (config_filename); + GNUNET_free (testname); + return result; +} -- cgit v1.2.3