diff options
Diffstat (limited to 'src/exchangedb/test_exchangedb.c')
-rw-r--r-- | src/exchangedb/test_exchangedb.c | 2397 |
1 files changed, 1335 insertions, 1062 deletions
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index b332cd6d2..22788a562 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA 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 @@ -33,9 +33,9 @@ static int result; /** * Report line of error if @a cond is true, and jump to label "drop". */ -#define FAILIF(cond) \ +#define FAILIF(cond) \ do { \ - if (! (cond)) { break;} \ + if (! (cond)) { break;} \ GNUNET_break (0); \ goto drop; \ } while (0) @@ -45,7 +45,8 @@ static int result; * Initializes @a ptr with random data. */ #define RND_BLK(ptr) \ - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr)) + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, \ + sizeof (*ptr)) /** * Initializes @a ptr with zeros. @@ -95,6 +96,7 @@ mark_prepare_cb (void *cls, const char *buf, size_t buf_size) { + (void) cls; GNUNET_assert (11 == buf_size); GNUNET_assert (0 == strcasecmp (wire_method, "testcase")); @@ -108,11 +110,69 @@ mark_prepare_cb (void *cls, /** + * Simple check that config retrieval and setting for extensions work + */ +static enum GNUNET_GenericReturnValue +test_extension_manifest (void) +{ + char *manifest; + + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->get_extension_manifest (plugin->cls, + "fnord", + &manifest)); + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->set_extension_manifest (plugin->cls, + "fnord", + "bar")); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->get_extension_manifest (plugin->cls, + "fnord", + &manifest)); + + FAILIF (0 != strcmp ("bar", manifest)); + GNUNET_free (manifest); + + /* let's do this again! */ + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->set_extension_manifest (plugin->cls, + "fnord", + "buzz")); + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->get_extension_manifest (plugin->cls, + "fnord", + &manifest)); + + FAILIF (0 != strcmp ("buzz", manifest)); + GNUNET_free (manifest); + + /* let's do this again, with NULL */ + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->set_extension_manifest (plugin->cls, + "fnord", + NULL)); + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->get_extension_manifest (plugin->cls, + "fnord", + &manifest)); + + FAILIF (NULL != manifest); + + return GNUNET_OK; +drop: + return GNUNET_SYSERR; +} + + +/** * Test API relating to persisting the wire plugins preparation data. * * @return #GNUNET_OK on success */ -static int +static enum GNUNET_GenericReturnValue test_wire_prepare (void) { FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != @@ -154,7 +214,7 @@ drop: * @return #GNUNET_OK if the given reserve has the same balance and expiration * as the given parameters; #GNUNET_SYSERR if not */ -static int +static enum GNUNET_GenericReturnValue check_reserve (const struct TALER_ReservePublicKeyP *pub, uint64_t value, uint32_t fraction, @@ -168,8 +228,8 @@ check_reserve (const struct TALER_ReservePublicKeyP *pub, &reserve)); FAILIF (value != reserve.balance.value); FAILIF (fraction != reserve.balance.fraction); - FAILIF (0 != strcmp (currency, reserve.balance.currency)); - + FAILIF (0 != strcmp (currency, + reserve.balance.currency)); return GNUNET_OK; drop: return GNUNET_SYSERR; @@ -191,75 +251,64 @@ struct DenomKeyPair 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); + TALER_denom_pub_free (&dkp->pub); + TALER_denom_priv_free (&dkp->priv); GNUNET_free (dkp); } /** - * Create a denominaiton key pair by registering the denomination in the DB. + * Create a denomination key pair by registering the denomination in the DB. * * @param size the size of the denomination key * @param now time to use for key generation, legal expiration will be 3h later. - * @param fee_withdraw withdraw fee to use - * @param fee_deposit deposit fee to use - * @param fee_refresh refresh fee to use - * @param fee_refund refund fee to use + * @param fees fees to use * @return the denominaiton key pair; NULL upon error */ static struct DenomKeyPair * create_denom_key_pair (unsigned int size, - struct GNUNET_TIME_Absolute now, + struct GNUNET_TIME_Timestamp now, const struct TALER_Amount *value, - const struct TALER_Amount *fee_withdraw, - const struct TALER_Amount *fee_deposit, - const struct TALER_Amount *fee_refresh, - const struct TALER_Amount *fee_refund) + const struct TALER_DenomFeeSet *fees) { struct DenomKeyPair *dkp; struct TALER_EXCHANGEDB_DenominationKey dki; - struct TALER_EXCHANGEDB_DenominationKeyInformationP issue2; + struct TALER_EXCHANGEDB_DenominationKeyInformation issue2; 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); - + GNUNET_assert (GNUNET_OK == + TALER_denom_priv_create (&dkp->priv, + &dkp->pub, + GNUNET_CRYPTO_BSA_RSA, + size)); /* Using memset() as fields like master key and signature are not properly initialized for this test. */ memset (&dki, 0, sizeof (struct TALER_EXCHANGEDB_DenominationKey)); dki.denom_pub = dkp->pub; - GNUNET_TIME_round_abs (&now); - dki.issue.properties.start = GNUNET_TIME_absolute_hton (now); - dki.issue.properties.expire_withdraw = GNUNET_TIME_absolute_hton - (GNUNET_TIME_absolute_add (now, - GNUNET_TIME_UNIT_HOURS)); - dki.issue.properties.expire_deposit = GNUNET_TIME_absolute_hton - (GNUNET_TIME_absolute_add - (now, - GNUNET_TIME_relative_multiply ( - GNUNET_TIME_UNIT_HOURS, 2))); - dki.issue.properties.expire_legal = GNUNET_TIME_absolute_hton - (GNUNET_TIME_absolute_add - (now, - 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); - TALER_amount_hton (&dki.issue.properties.fee_refund, fee_refund); - GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key, - &dki.issue.properties.denom_hash); - - dki.issue.properties.purpose.size = htonl (sizeof (struct - TALER_DenominationKeyValidityPS)); - dki.issue.properties.purpose.purpose = htonl ( - TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY); + dki.issue.start = now; + dki.issue.expire_withdraw + = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add ( + now.abs_time, + GNUNET_TIME_UNIT_HOURS)); + dki.issue.expire_deposit + = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add ( + now.abs_time, + GNUNET_TIME_relative_multiply ( + GNUNET_TIME_UNIT_HOURS, 2))); + dki.issue.expire_legal + = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add ( + now.abs_time, + GNUNET_TIME_relative_multiply ( + GNUNET_TIME_UNIT_HOURS, 3))); + dki.issue.value = *value; + dki.issue.fees = *fees; + TALER_denom_pub_hash (&dkp->pub, + &dki.issue.denom_hash); if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->insert_denomination_info (plugin->cls, &dki.denom_pub, @@ -269,9 +318,10 @@ create_denom_key_pair (unsigned int size, destroy_denom_key_pair (dkp); return NULL; } + memset (&issue2, 0, sizeof (issue2)); if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_denomination_info (plugin->cls, - &dki.issue.properties.denom_hash, + &dki.issue.denom_hash, &issue2)) { GNUNET_break (0); @@ -290,10 +340,7 @@ create_denom_key_pair (unsigned int size, 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 fee_refund; +static struct TALER_DenomFeeSet fees; static struct TALER_Amount fee_closing; static struct TALER_Amount amount_with_fee; @@ -309,9 +356,9 @@ static struct TALER_Amount amount_with_fee; #define MELT_NOREVEAL_INDEX 1 /** - * How big do we make the coin envelopes? + * How big do we make the RSA keys? */ -#define COIN_ENC_MAX_SIZE 512 +#define RSA_KEY_SIZE 1024 static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins; @@ -328,24 +375,15 @@ static struct TALER_TransferPublicKeyP tpub; * @param rowid unique serial ID for the row in our database * @param num_freshcoins size of the @a rrcs array * @param rrcs array of @a num_freshcoins information about coins to be created - * @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1 - * @param tprivs array of @e num_tprivs transfer private keys - * @param tp transfer public key information */ static void never_called_cb (void *cls, uint32_t num_freshcoins, - const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs, - unsigned int num_tprivs, - const struct TALER_TransferPrivateKeyP *tprivs, - const struct TALER_TransferPublicKeyP *tp) + const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs) { (void) cls; (void) num_freshcoins; (void) rrcs; - (void) num_tprivs; - (void) tprivs; - (void) tp; GNUNET_assert (0); /* should never be called! */ } @@ -358,18 +396,12 @@ never_called_cb (void *cls, * @param rowid unique serial ID for the row in our database * @param num_freshcoins size of the @a rrcs array * @param rrcs array of @a num_freshcoins information about coins to be created - * @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1 - * @param tprivsr array of @e num_tprivs transfer private keys - * @param tpr transfer public key information */ static void check_refresh_reveal_cb ( void *cls, uint32_t num_freshcoins, - const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs, - unsigned int num_tprivs, - const struct TALER_TransferPrivateKeyP *tprivsr, - const struct TALER_TransferPublicKeyP *tpr) + const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs) { (void) cls; /* compare the refresh commit coin arrays */ @@ -379,20 +411,13 @@ check_refresh_reveal_cb ( &revealed_coins[cnt]; const struct TALER_EXCHANGEDB_RefreshRevealedCoin *bcoin = &rrcs[cnt]; - GNUNET_assert (acoin->coin_ev_size == bcoin->coin_ev_size); GNUNET_assert (0 == - GNUNET_memcmp (acoin->coin_ev, - bcoin->coin_ev)); + TALER_blinded_planchet_cmp (&acoin->blinded_planchet, + &bcoin->blinded_planchet)); GNUNET_assert (0 == - GNUNET_CRYPTO_rsa_public_key_cmp ( - acoin->denom_pub.rsa_public_key, - bcoin->denom_pub. - rsa_public_key)); + GNUNET_memcmp (&acoin->h_denom_pub, + &bcoin->h_denom_pub)); } - GNUNET_assert (0 == GNUNET_memcmp (&tpub, tpr)); - GNUNET_assert (0 == memcmp (tprivs, tprivsr, - sizeof(struct TALER_TransferPrivateKeyP) - * (TALER_CNC_KAPPA - 1))); } @@ -411,6 +436,7 @@ static unsigned int auditor_row_cnt; * @param cls closure * @param rowid unique serial ID for the refresh session in our DB * @param denom_pub denomination of the @a coin_pub + * @param h_age_commitment hash of age commitment that went into the minting, may be NULL * @param coin_pub public key of the coin * @param coin_sig signature from the coin * @param amount_with_fee amount that was deposited including fee @@ -419,23 +445,27 @@ static unsigned int auditor_row_cnt; * @param rc what is the session hash * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -static int -audit_refresh_session_cb (void *cls, - uint64_t rowid, - const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_CoinSpendSignatureP *coin_sig, - const struct TALER_Amount *amount_with_fee, - uint32_t noreveal_index, - const struct TALER_RefreshCommitmentP *rc) +static enum GNUNET_GenericReturnValue +audit_refresh_session_cb ( + void *cls, + uint64_t rowid, + const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig, + const struct TALER_Amount *amount_with_fee, + uint32_t noreveal_index, + const struct TALER_RefreshCommitmentP *rc) { (void) cls; (void) rowid; (void) denom_pub; + (void) coin_pub; (void) coin_sig; (void) amount_with_fee; (void) noreveal_index; (void) rc; + (void) h_age_commitment; auditor_row_cnt++; return GNUNET_OK; } @@ -466,22 +496,19 @@ handle_link_data_cb (void *cls, NULL != ldlp; ldlp = ldlp->next) { - int found; + bool found; - found = GNUNET_NO; + found = false; for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) { - GNUNET_assert (NULL != ldlp->ev_sig.rsa_signature); if ( (0 == - GNUNET_CRYPTO_rsa_public_key_cmp (ldlp->denom_pub.rsa_public_key, - new_dkp[cnt]->pub.rsa_public_key)) - && + TALER_denom_pub_cmp (&ldlp->denom_pub, + &new_dkp[cnt]->pub)) && (0 == - GNUNET_CRYPTO_rsa_signature_cmp (ldlp->ev_sig.rsa_signature, - revealed_coins[cnt].coin_sig. - rsa_signature)) ) + TALER_blinded_denom_sig_cmp (&ldlp->ev_sig, + &revealed_coins[cnt].coin_sig)) ) { - found = GNUNET_YES; + found = true; break; } } @@ -491,250 +518,44 @@ handle_link_data_cb (void *cls, /** - * Function to test melting of coins as part of a refresh session - * - * @return #GNUNET_OK if everything went well; #GNUNET_SYSERR if not - */ -static int -test_melting (void) -{ - struct TALER_EXCHANGEDB_Refresh refresh_session; - struct TALER_EXCHANGEDB_Melt ret_refresh_session; - struct DenomKeyPair *dkp; - struct TALER_DenominationPublicKey *new_denom_pubs; - int ret; - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Absolute now; - - ret = GNUNET_SYSERR; - RND_BLK (&refresh_session); - dkp = NULL; - new_dkp = NULL; - new_denom_pubs = NULL; - /* create and test a refresh session */ - refresh_session.noreveal_index = MELT_NOREVEAL_INDEX; - /* create a denomination (value: 1; fraction: 100) */ - now = GNUNET_TIME_absolute_get (); - GNUNET_TIME_round_abs (&now); - dkp = create_denom_key_pair (512, - now, - &value, - &fee_withdraw, - &fee_deposit, - &fee_refresh, - &fee_refund); - GNUNET_assert (NULL != dkp); - /* initialize refresh session melt data */ - { - struct GNUNET_HashCode hc; - - RND_BLK (&refresh_session.coin.coin_pub); - GNUNET_CRYPTO_hash (&refresh_session.coin.coin_pub, - sizeof (refresh_session.coin.coin_pub), - &hc); - refresh_session.coin.denom_sig.rsa_signature = - GNUNET_CRYPTO_rsa_sign_fdh (dkp->priv.rsa_private_key, - &hc); - GNUNET_assert (NULL != refresh_session.coin.denom_sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key, - &refresh_session.coin.denom_pub_hash); - refresh_session.amount_with_fee = amount_with_fee; - } - - /* test insert_melt & get_melt */ - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->get_melt (plugin->cls, - &refresh_session.rc, - &ret_refresh_session)); - FAILIF (TALER_EXCHANGEDB_CKS_ADDED != - plugin->ensure_coin_known (plugin->cls, - &refresh_session.coin)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->insert_melt (plugin->cls, - &refresh_session)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->get_melt (plugin->cls, - &refresh_session.rc, - &ret_refresh_session)); - FAILIF (refresh_session.noreveal_index != - ret_refresh_session.session.noreveal_index); - FAILIF (0 != - TALER_amount_cmp (&refresh_session.amount_with_fee, - &ret_refresh_session.session.amount_with_fee)); - FAILIF (0 != - TALER_amount_cmp (&fee_refresh, - &ret_refresh_session.melt_fee)); - FAILIF (0 != - GNUNET_memcmp (&refresh_session.rc, &ret_refresh_session.session.rc)); - FAILIF (0 != GNUNET_memcmp (&refresh_session.coin_sig, - &ret_refresh_session.session.coin_sig)); - FAILIF (NULL != - ret_refresh_session.session.coin.denom_sig.rsa_signature); - FAILIF (0 != memcmp (&refresh_session.coin.coin_pub, - &ret_refresh_session.session.coin.coin_pub, - sizeof (refresh_session.coin.coin_pub))); - FAILIF (0 != - GNUNET_memcmp (&refresh_session.coin.denom_pub_hash, - &ret_refresh_session.session.coin.denom_pub_hash)); - - /* test 'select_refreshes_above_serial_id' */ - auditor_row_cnt = 0; - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->select_refreshes_above_serial_id (plugin->cls, - 0, - &audit_refresh_session_cb, - NULL)); - FAILIF (1 != auditor_row_cnt); - - new_dkp = GNUNET_new_array (MELT_NEW_COINS, - struct DenomKeyPair *); - new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS, - struct TALER_DenominationPublicKey); - revealed_coins - = GNUNET_new_array (MELT_NEW_COINS, - struct TALER_EXCHANGEDB_RefreshRevealedCoin); - for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) - { - struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin; - struct GNUNET_HashCode hc; - struct GNUNET_TIME_Absolute now; - - now = GNUNET_TIME_absolute_get (); - GNUNET_TIME_round_abs (&now); - new_dkp[cnt] = create_denom_key_pair (1024, - now, - &value, - &fee_withdraw, - &fee_deposit, - &fee_refresh, - &fee_refund); - GNUNET_assert (NULL != new_dkp[cnt]); - new_denom_pubs[cnt] = new_dkp[cnt]->pub; - ccoin = &revealed_coins[cnt]; - ccoin->coin_ev_size = (size_t) 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); - RND_BLK (&hc); - ccoin->denom_pub = new_dkp[cnt]->pub; - ccoin->coin_sig.rsa_signature - = GNUNET_CRYPTO_rsa_sign_fdh (new_dkp[cnt]->priv.rsa_private_key, - &hc); - } - RND_BLK (&tprivs); - RND_BLK (&tpub); - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->get_refresh_reveal (plugin->cls, - &refresh_session.rc, - &never_called_cb, - NULL)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->insert_refresh_reveal (plugin->cls, - &refresh_session.rc, - MELT_NEW_COINS, - revealed_coins, - TALER_CNC_KAPPA - 1, - tprivs, - &tpub)); - FAILIF (0 >= - plugin->get_refresh_reveal (plugin->cls, - &refresh_session.rc, - &check_refresh_reveal_cb, - NULL)); - - - qs = plugin->get_link_data (plugin->cls, - &refresh_session.coin.coin_pub, - &handle_link_data_cb, - NULL); - FAILIF (0 >= qs); - { - /* Just to test fetching a coin with melt history */ - struct TALER_EXCHANGEDB_TransactionList *tl; - enum GNUNET_DB_QueryStatus qs; - - qs = plugin->get_coin_transactions (plugin->cls, - &refresh_session.coin.coin_pub, - GNUNET_YES, - &tl); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs); - plugin->free_coin_transaction_list (plugin->cls, - tl); - } - - - ret = GNUNET_OK; -drop: - if (NULL != revealed_coins) - { - for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) - { - if (NULL != revealed_coins[cnt].coin_sig.rsa_signature) - GNUNET_CRYPTO_rsa_signature_free ( - revealed_coins[cnt].coin_sig.rsa_signature); - GNUNET_free (revealed_coins[cnt].coin_ev); - } - GNUNET_free (revealed_coins); - revealed_coins = NULL; - } - destroy_denom_key_pair (dkp); - GNUNET_CRYPTO_rsa_signature_free ( - refresh_session.coin.denom_sig.rsa_signature); - GNUNET_free (new_denom_pubs); - for (unsigned int cnt = 0; - (NULL != new_dkp) && (cnt < MELT_NEW_COINS) && (NULL != new_dkp[cnt]); - cnt++) - destroy_denom_key_pair (new_dkp[cnt]); - GNUNET_free (new_dkp); - return ret; -} - - -/** * Callback that should never be called. */ static void cb_wt_never (void *cls, uint64_t serial_id, const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_wire, - const json_t *wire, - struct GNUNET_TIME_Absolute exec_time, - const struct GNUNET_HashCode *h_contract_terms, + const char *account_payto_uri, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Timestamp exec_time, + const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, const struct TALER_Amount *coin_fee) { + (void) cls; + (void) serial_id; + (void) merchant_pub; + (void) account_payto_uri; + (void) h_payto; + (void) exec_time; + (void) h_contract_terms; + (void) denom_pub; + (void) coin_pub; + (void) coin_value; + (void) 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_terms_wt; +static struct TALER_MerchantWireHashP h_wire_wt; +static struct TALER_PrivateContractHashP h_contract_terms_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 wire_out_date; +static struct GNUNET_TIME_Timestamp wire_out_date; static struct TALER_WireTransferIdentifierRawP wire_out_wtid; @@ -745,24 +566,26 @@ static void cb_wt_check (void *cls, uint64_t rowid, const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_wire, - const json_t *wire, - struct GNUNET_TIME_Absolute exec_time, - const struct GNUNET_HashCode *h_contract_terms, + const char *account_payto_uri, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Timestamp exec_time, + const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, const struct TALER_Amount *coin_fee) { + (void) rowid; + (void) denom_pub; + (void) h_payto; GNUNET_assert (cls == &cb_wt_never); GNUNET_assert (0 == GNUNET_memcmp (merchant_pub, &merchant_pub_wt)); - GNUNET_assert (0 == strcmp (json_string_value (json_object_get (wire, - "payto_uri")), + GNUNET_assert (0 == strcmp (account_payto_uri, "payto://iban/DE67830654080004822650?receiver-name=Test")); - GNUNET_assert (0 == GNUNET_memcmp (h_wire, - &h_wire_wt)); - GNUNET_assert (exec_time.abs_value_us == wire_out_date.abs_value_us); + GNUNET_assert (GNUNET_TIME_timestamp_cmp (exec_time, + ==, + wire_out_date)); GNUNET_assert (0 == GNUNET_memcmp (h_contract_terms, &h_contract_terms_wt)); GNUNET_assert (0 == GNUNET_memcmp (coin_pub, @@ -775,168 +598,36 @@ cb_wt_check (void *cls, /** - * 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 == GNUNET_memcmp (wtid, - &wire_out_wtid)); - GNUNET_assert (execution_time.abs_value_us == - wire_out_date.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)); -} - - -/** - * Here #deposit_cb() will store the row ID of the deposit. + * Here we store the hash of the payto URI. */ -static uint64_t deposit_rowid; +static struct TALER_PaytoHashP wire_target_h_payto; /** - * Function called with details about deposits that - * have been made. Called in the test on the - * deposit given in @a cls. - * - * @param cls closure a `struct TALER_EXCHANGEDB_Deposit *` - * @param rowid unique ID for the deposit in our DB, used for marking - * it as 'tiny' or 'done' - * @param merchant_pub public key of the merchant - * @param coin_pub public key of the coin - * @param amount_with_fee amount that was deposited including fee - * @param deposit_fee amount the exchange gets to keep as transaction fees - * @param h_contract_terms hash of the proposal data known to merchant and customer - * @param wire wire details for the merchant - * @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to continue to iterate - */ -static enum GNUNET_DB_QueryStatus -deposit_cb (void *cls, - uint64_t rowid, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount_with_fee, - const struct TALER_Amount *deposit_fee, - const struct GNUNET_HashCode *h_contract_terms, - const json_t *wire) -{ - struct TALER_EXCHANGEDB_Deposit *deposit = cls; - struct GNUNET_HashCode h_wire; - - deposit_rowid = rowid; - GNUNET_assert (GNUNET_OK == - TALER_JSON_merchant_wire_signature_hash (wire, - &h_wire)); - if ( (0 != GNUNET_memcmp (merchant_pub, - &deposit->merchant_pub)) || - (0 != TALER_amount_cmp (amount_with_fee, - &deposit->amount_with_fee)) || - (0 != TALER_amount_cmp (deposit_fee, - &deposit->deposit_fee)) || - (0 != GNUNET_memcmp (h_contract_terms, - &deposit->h_contract_terms)) || - (0 != memcmp (coin_pub, - &deposit->coin.coin_pub, - sizeof (struct TALER_CoinSpendPublicKeyP))) || - (0 != GNUNET_memcmp (&h_wire, - &deposit->h_wire)) ) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; -} - - -/** - * Function called with details about deposits that - * have been made. Called in the test on the - * deposit given in @a cls. - * - * @param cls closure a `struct TALER_EXCHANGEDB_Deposit *` - * @param rowid unique ID for the deposit in our DB, used for marking - * it as 'tiny' or 'done' - * @param coin_pub public key of the coin - * @param amount_with_fee amount that was deposited including fee - * @param deposit_fee amount the exchange gets to keep as transaction fees - * @param h_contract_terms hash of the proposal data known to merchant and customer - * @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to continue to iterate - */ -static enum GNUNET_DB_QueryStatus -matching_deposit_cb (void *cls, - uint64_t rowid, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount_with_fee, - const struct TALER_Amount *deposit_fee, - const struct GNUNET_HashCode *h_contract_terms) -{ - struct TALER_EXCHANGEDB_Deposit *deposit = cls; - - deposit_rowid = rowid; - if ( (0 != TALER_amount_cmp (amount_with_fee, - &deposit->amount_with_fee)) || - (0 != TALER_amount_cmp (deposit_fee, - &deposit->deposit_fee)) || - (0 != GNUNET_memcmp (h_contract_terms, - &deposit->h_contract_terms)) || - (0 != memcmp (coin_pub, - &deposit->coin.coin_pub, - sizeof (struct TALER_CoinSpendPublicKeyP))) ) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; -} - - -/** - * Callback for #select_deposits_above_serial_id () + * Callback for #select_coin_deposits_above_serial_id () * * @param cls closure * @param rowid unique serial ID for the deposit in our DB * @param exchange_timestamp when did the deposit happen - * @param wallet_timestamp when did the wallet sign the contract - * @param merchant_pub public key of the merchant + * @param deposit deposit details * @param denom_pub denomination of the @a coin_pub - * @param coin_pub public key of the coin - * @param coin_sig signature from the coin - * @param amount_with_fee amount that was deposited including fee - * @param h_contract_terms hash of the proposal data known to merchant and customer - * @param refund_deadline by which the merchant advised that he might want - * to get a refund - * @param wire_deadline by which the merchant advised that he would like the - * wire transfer to be executed - * @param receiver_wire_account wire details for the merchant, NULL from iterate_matching_deposits() * @param done flag set if the deposit was already executed (or not) * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -static int +static enum GNUNET_GenericReturnValue audit_deposit_cb (void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute exchange_timestamp, - struct GNUNET_TIME_Absolute wallet_timestamp, - const struct TALER_MerchantPublicKeyP *merchant_pub, + struct GNUNET_TIME_Timestamp exchange_timestamp, + const struct TALER_EXCHANGEDB_Deposit *deposit, const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_CoinSpendSignatureP *coin_sig, - const struct TALER_Amount *amount_with_fee, - const struct GNUNET_HashCode *h_contract_terms, - struct GNUNET_TIME_Absolute refund_deadline, - struct GNUNET_TIME_Absolute wire_deadline, - const json_t *receiver_wire_account, - int done) + bool done) { + (void) cls; + (void) rowid; + (void) exchange_timestamp; + (void) deposit; + (void) denom_pub; + (void) done; auditor_row_cnt++; return GNUNET_OK; } @@ -955,18 +646,20 @@ audit_deposit_cb (void *cls, * @param h_contract_terms hash of the proposal data in * the contract between merchant and customer * @param rtransaction_id refund transaction ID chosen by the merchant + * @param full_refund the deposit * @param amount_with_fee amount that was deposited including fee * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -static int +static enum GNUNET_GenericReturnValue audit_refund_cb (void *cls, uint64_t rowid, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_MerchantSignatureP *merchant_sig, - const struct GNUNET_HashCode *h_contract_terms, + const struct TALER_PrivateContractHashP *h_contract_terms, uint64_t rtransaction_id, + bool full_refund, const struct TALER_Amount *amount_with_fee) { (void) cls; @@ -978,6 +671,7 @@ audit_refund_cb (void *cls, (void) h_contract_terms; (void) rtransaction_id; (void) amount_with_fee; + (void) full_refund; auditor_row_cnt++; return GNUNET_OK; } @@ -995,14 +689,14 @@ audit_refund_cb (void *cls, * @param execution_date when did we receive the funds * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -static int +static enum GNUNET_GenericReturnValue audit_reserve_in_cb (void *cls, uint64_t rowid, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_Amount *credit, const char *sender_account_details, uint64_t wire_reference, - struct GNUNET_TIME_Absolute execution_date) + struct GNUNET_TIME_Timestamp execution_date) { (void) cls; (void) rowid; @@ -1029,14 +723,14 @@ audit_reserve_in_cb (void *cls, * @param amount_with_fee amount that was withdrawn * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -static int +static enum GNUNET_GenericReturnValue audit_reserve_out_cb (void *cls, uint64_t rowid, - const struct GNUNET_HashCode *h_blind_ev, + const struct TALER_BlindedCoinHashP *h_blind_ev, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReserveSignatureP *reserve_sig, - struct GNUNET_TIME_Absolute execution_date, + struct GNUNET_TIME_Timestamp execution_date, const struct TALER_Amount *amount_with_fee) { (void) cls; @@ -1057,28 +751,25 @@ audit_reserve_out_cb (void *cls, * * @return #GNUNET_OK on success */ -static int +static enum GNUNET_GenericReturnValue test_gc (void) { struct DenomKeyPair *dkp; - struct GNUNET_TIME_Absolute now; - struct GNUNET_TIME_Absolute past; - struct TALER_EXCHANGEDB_DenominationKeyInformationP issue2; - struct GNUNET_HashCode denom_hash; - - now = GNUNET_TIME_absolute_get (); - GNUNET_TIME_round_abs (&now); - past = GNUNET_TIME_absolute_subtract (now, - GNUNET_TIME_relative_multiply ( - GNUNET_TIME_UNIT_HOURS, - 4)); - dkp = create_denom_key_pair (1024, + struct GNUNET_TIME_Timestamp now; + struct GNUNET_TIME_Timestamp past; + struct TALER_EXCHANGEDB_DenominationKeyInformation issue2; + struct TALER_DenominationHashP denom_hash; + + now = GNUNET_TIME_timestamp_get (); + past = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_subtract (now.abs_time, + GNUNET_TIME_relative_multiply ( + GNUNET_TIME_UNIT_HOURS, + 4))); + dkp = create_denom_key_pair (RSA_KEY_SIZE, past, &value, - &fee_withdraw, - &fee_deposit, - &fee_refresh, - &fee_refund); + &fees); GNUNET_assert (NULL != dkp); if (GNUNET_OK != plugin->gc (plugin->cls)) @@ -1087,8 +778,8 @@ test_gc (void) destroy_denom_key_pair (dkp); return GNUNET_SYSERR; } - GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key, - &denom_hash); + TALER_denom_pub_hash (&dkp->pub, + &denom_hash); if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != plugin->get_denomination_info (plugin->cls, @@ -1109,30 +800,26 @@ test_gc (void) * * @return #GNUNET_OK on success */ -static int +static enum GNUNET_GenericReturnValue test_wire_fees (void) { - struct GNUNET_TIME_Absolute start_date; - struct GNUNET_TIME_Absolute end_date; - struct TALER_Amount wire_fee; - struct TALER_Amount closing_fee; + struct GNUNET_TIME_Timestamp start_date; + struct GNUNET_TIME_Timestamp end_date; + struct TALER_WireFeeSet fees; struct TALER_MasterSignatureP master_sig; - struct GNUNET_TIME_Absolute sd; - struct GNUNET_TIME_Absolute ed; - struct TALER_Amount fee; - struct TALER_Amount fee2; + struct GNUNET_TIME_Timestamp sd; + struct GNUNET_TIME_Timestamp ed; + struct TALER_WireFeeSet fees2; struct TALER_MasterSignatureP ms; - start_date = GNUNET_TIME_absolute_get (); - GNUNET_TIME_round_abs (&start_date); - end_date = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); - GNUNET_TIME_round_abs (&end_date); + start_date = GNUNET_TIME_timestamp_get (); + end_date = GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_MINUTES); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":1.424242", - &wire_fee)); + &fees.wire)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":2.424242", - &closing_fee)); + &fees.closing)); GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &master_sig, sizeof (master_sig)); @@ -1141,8 +828,7 @@ test_wire_fees (void) "wire-method", start_date, end_date, - &wire_fee, - &closing_fee, + &fees, &master_sig)) { GNUNET_break (0); @@ -1153,8 +839,7 @@ test_wire_fees (void) "wire-method", start_date, end_date, - &wire_fee, - &closing_fee, + &fees, &master_sig)) { GNUNET_break (0); @@ -1168,8 +853,7 @@ test_wire_fees (void) end_date, &sd, &ed, - &fee, - &fee2, + &fees2, &ms)) { GNUNET_break (0); @@ -1181,19 +865,20 @@ test_wire_fees (void) start_date, &sd, &ed, - &fee, - &fee2, + &fees2, &ms)) { GNUNET_break (0); return GNUNET_SYSERR; } - if ( (sd.abs_value_us != start_date.abs_value_us) || - (ed.abs_value_us != end_date.abs_value_us) || - (0 != TALER_amount_cmp (&fee, - &wire_fee)) || - (0 != TALER_amount_cmp (&fee2, - &closing_fee)) || + if ( (GNUNET_TIME_timestamp_cmp (sd, + !=, + start_date)) || + (GNUNET_TIME_timestamp_cmp (ed, + !=, + end_date)) || + (0 != TALER_wire_fee_set_cmp (&fees, + &fees2)) || (0 != GNUNET_memcmp (&ms, &master_sig)) ) { @@ -1218,14 +903,17 @@ static struct TALER_Amount wire_out_amount; * @param amount amount that was wired * @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration */ -static int +static enum GNUNET_GenericReturnValue audit_wire_cb (void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute date, + struct GNUNET_TIME_Timestamp date, const struct TALER_WireTransferIdentifierRawP *wtid, - const json_t *wire, + const char *payto_uri, const struct TALER_Amount *amount) { + (void) cls; + (void) rowid; + (void) payto_uri; auditor_row_cnt++; GNUNET_assert (0 == TALER_amount_cmp (amount, @@ -1233,7 +921,9 @@ audit_wire_cb (void *cls, GNUNET_assert (0 == GNUNET_memcmp (wtid, &wire_out_wtid)); - GNUNET_assert (date.abs_value_us == wire_out_date.abs_value_us); + GNUNET_assert (GNUNET_TIME_timestamp_cmp (date, + ==, + wire_out_date)); return GNUNET_OK; } @@ -1241,17 +931,23 @@ audit_wire_cb (void *cls, /** * Test API relating to wire_out handling. * + * @param bd batch deposit to test * @return #GNUNET_OK on success */ -static int -test_wire_out (const struct TALER_EXCHANGEDB_Deposit *deposit) +static enum GNUNET_GenericReturnValue +test_wire_out (const struct TALER_EXCHANGEDB_BatchDeposit *bd) { + const struct TALER_EXCHANGEDB_CoinDepositInformation *deposit = &bd->cdis[0]; + struct TALER_PaytoHashP h_payto; + + GNUNET_assert (0 < bd->num_cdis); + TALER_payto_hash (bd->receiver_wire_account, + &h_payto); auditor_row_cnt = 0; memset (&wire_out_wtid, - 42, + 41, sizeof (wire_out_wtid)); - wire_out_date = GNUNET_TIME_absolute_get (); - (void) GNUNET_TIME_round_abs (&wire_out_date); + wire_out_date = GNUNET_TIME_timestamp_get (); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":1", &wire_out_amount)); @@ -1263,13 +959,12 @@ test_wire_out (const struct TALER_EXCHANGEDB_Deposit *deposit) plugin->start_deferred_wire_out (plugin->cls)); /* setup values for wire transfer aggregation data */ - merchant_pub_wt = deposit->merchant_pub; - h_wire_wt = deposit->h_wire; - h_contract_terms_wt = deposit->h_contract_terms; + merchant_pub_wt = bd->merchant_pub; + h_contract_terms_wt = bd->h_contract_terms; coin_pub_wt = deposit->coin.coin_pub; coin_value_wt = deposit->amount_with_fee; - coin_fee_wt = fee_deposit; + coin_fee_wt = fees.deposit; GNUNET_assert (0 < TALER_amount_subtract (&transfer_value_wt, &coin_value_wt, @@ -1281,46 +976,44 @@ test_wire_out (const struct TALER_EXCHANGEDB_Deposit *deposit) NULL)); { - struct GNUNET_HashCode h_contract_terms_wt2 = h_contract_terms_wt; - - h_contract_terms_wt2.bits[0]++; + struct TALER_PrivateContractHashP h_contract_terms_wt2 = + h_contract_terms_wt; + bool pending; + struct TALER_WireTransferIdentifierRawP wtid2; + struct TALER_Amount coin_contribution2; + struct TALER_Amount coin_fee2; + struct GNUNET_TIME_Timestamp execution_time2; + struct TALER_EXCHANGEDB_KycStatus kyc; + enum TALER_AmlDecisionState aml; + + h_contract_terms_wt2.hash.bits[0]++; FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != plugin->lookup_transfer_by_deposit (plugin->cls, &h_contract_terms_wt2, &h_wire_wt, &coin_pub_wt, &merchant_pub_wt, - &cb_wtid_never, - NULL)); + &pending, + &wtid2, + &execution_time2, + &coin_contribution2, + &coin_fee2, + &kyc, + &aml)); } - /* insert WT data */ - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->insert_aggregation_tracking (plugin->cls, - &wire_out_wtid, - deposit_rowid)); - - /* Now let's fix the transient constraint violation by - putting in the WTID into the wire_out table */ { - json_t *wire_out_account; - - wire_out_account = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("payto_uri", - "payto://x-taler-bank/localhost:8080/1"), - GNUNET_JSON_pack_string ("salt", - "this-is-my-salt")); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->store_wire_transfer_out (plugin->cls, - wire_out_date, - &wire_out_wtid, - wire_out_account, - "my-config-section", - &wire_out_amount)) - { - json_decref (wire_out_account); - FAILIF (1); - } - json_decref (wire_out_account); + struct TALER_ReservePublicKeyP rpub; + + memset (&rpub, + 44, + sizeof (rpub)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->store_wire_transfer_out (plugin->cls, + wire_out_date, + &wire_out_wtid, + &h_payto, + "my-config-section", + &wire_out_amount)); } /* And now the commit should still succeed! */ FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != @@ -1331,14 +1024,39 @@ test_wire_out (const struct TALER_EXCHANGEDB_Deposit *deposit) &wire_out_wtid, &cb_wt_check, &cb_wt_never)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->lookup_transfer_by_deposit (plugin->cls, - &h_contract_terms_wt, - &h_wire_wt, - &coin_pub_wt, - &merchant_pub_wt, - &cb_wtid_check, - &cb_wtid_never)); + { + bool pending; + struct TALER_WireTransferIdentifierRawP wtid2; + struct TALER_Amount coin_contribution2; + struct TALER_Amount coin_fee2; + struct GNUNET_TIME_Timestamp execution_time2; + struct TALER_EXCHANGEDB_KycStatus kyc; + enum TALER_AmlDecisionState aml = TALER_AML_FROZEN; + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->lookup_transfer_by_deposit (plugin->cls, + &h_contract_terms_wt, + &h_wire_wt, + &coin_pub_wt, + &merchant_pub_wt, + &pending, + &wtid2, + &execution_time2, + &coin_contribution2, + &coin_fee2, + &kyc, + &aml)); + FAILIF (TALER_AML_NORMAL != aml); + GNUNET_assert (0 == GNUNET_memcmp (&wtid2, + &wire_out_wtid)); + GNUNET_assert (GNUNET_TIME_timestamp_cmp (execution_time2, + ==, + wire_out_date)); + GNUNET_assert (0 == TALER_amount_cmp (&coin_contribution2, + &coin_value_wt)); + GNUNET_assert (0 == TALER_amount_cmp (&coin_fee2, + &coin_fee_wt)); + } FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->select_wire_out_above_serial_id (plugin->cls, 0, @@ -1366,19 +1084,26 @@ drop: * @param coin_blind blinding factor used to blind the coin * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -static int +static enum GNUNET_GenericReturnValue recoup_cb (void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute timestamp, + struct GNUNET_TIME_Timestamp timestamp, const struct TALER_Amount *amount, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_CoinPublicInfo *coin, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, - const struct TALER_DenominationBlindingKeyP *coin_blind) + const union GNUNET_CRYPTO_BlindingSecretP *coin_blind) { - const struct TALER_DenominationBlindingKeyP *cb = cls; + const union GNUNET_CRYPTO_BlindingSecretP *cb = cls; + (void) rowid; + (void) timestamp; + (void) amount; + (void) reserve_pub; + (void) coin_sig; + (void) coin; + (void) denom_pub; FAILIF (NULL == cb); FAILIF (0 != GNUNET_memcmp (cb, coin_blind)); @@ -1389,68 +1114,32 @@ drop: /** - * Function called on deposits that are past their due date - * and have not yet seen a wire transfer. + * Function called on batch deposits that may require a + * wire transfer. * * @param cls closure a `struct TALER_EXCHANGEDB_Deposit *` - * @param rowid deposit table row of the coin's deposit - * @param coin_pub public key of the coin - * @param amount value of the deposit, including fee - * @param wire where should the funds be wired - * @param deadline what was the requested wire transfer deadline - * @param tiny did the exchange defer this transfer because it is too small? - * @param done did the exchange claim that it made a transfer? + * @param batch_deposit_serial_id where in the table are we + * @param total_amount value of all missing deposits, including fees + * @param wire_target_h_payto hash of the recipient account's payto URI + * @param deadline what was the earliest requested wire transfer deadline */ static void -wire_missing_cb (void *cls, - uint64_t rowid, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount, - const json_t *wire, - struct GNUNET_TIME_Absolute deadline, - /* bool? */ int tiny, - /* bool? */ int done) +wire_missing_cb ( + void *cls, + uint64_t batch_deposit_serial_id, + const struct TALER_Amount *total_amount, + const struct TALER_PaytoHashP *wire_target_h_payto, + struct GNUNET_TIME_Timestamp deadline) { - const struct TALER_EXCHANGEDB_Deposit *deposit = cls; - struct GNUNET_HashCode h_wire; - - (void) done; - if (NULL != wire) - GNUNET_assert (GNUNET_OK == - TALER_JSON_merchant_wire_signature_hash (wire, - &h_wire)); - else - memset (&h_wire, - 0, - sizeof (h_wire)); - if (GNUNET_NO != tiny) - { - GNUNET_break (0); - result = 66; - } - if (GNUNET_NO != done) - { - GNUNET_break (0); - result = 66; - } - if (0 != TALER_amount_cmp (amount, - &deposit->amount_with_fee)) - { - GNUNET_break (0); - result = 66; - } - if (0 != GNUNET_memcmp (coin_pub, - &deposit->coin.coin_pub)) - { - GNUNET_break (0); - result = 66; - } - if (0 != GNUNET_memcmp (&h_wire, - &deposit->h_wire)) - { - GNUNET_break (0); - result = 66; - } + const struct TALER_EXCHANGEDB_CoinDepositInformation *deposit = cls; + + (void) batch_deposit_serial_id; + (void) deadline; + (void) wire_target_h_payto; + if (0 == + TALER_amount_cmp (total_amount, + &deposit->amount_with_fee)) + result = 8; } @@ -1462,7 +1151,7 @@ wire_missing_cb (void *cls, * @param amount_with_fee amount being refunded * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -static int +static enum GNUNET_GenericReturnValue check_refund_cb (void *cls, const struct TALER_Amount *amount_with_fee) { @@ -1488,40 +1177,61 @@ run (void *cls) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct TALER_CoinSpendSignatureP coin_sig; - struct GNUNET_TIME_Absolute deadline; - struct TALER_DenominationBlindingKeyP coin_blind; + struct GNUNET_TIME_Timestamp deadline; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; struct TALER_ReservePublicKeyP reserve_pub; struct TALER_ReservePublicKeyP reserve_pub2; - struct DenomKeyPair *dkp; - struct GNUNET_HashCode dkp_pub_hash; + struct TALER_ReservePublicKeyP reserve_pub3; + struct DenomKeyPair *dkp = NULL; struct TALER_MasterSignatureP master_sig; struct TALER_EXCHANGEDB_CollectableBlindcoin cbc; struct TALER_EXCHANGEDB_CollectableBlindcoin cbc2; - struct TALER_EXCHANGEDB_ReserveHistory *rh; + struct TALER_EXCHANGEDB_ReserveHistory *rh = NULL; 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_EXCHANGEDB_CoinDepositInformation deposit; + struct TALER_EXCHANGEDB_BatchDeposit bd; + struct TALER_CoinSpendPublicKeyP cpub2; + struct TALER_MerchantPublicKeyP mpub2; struct TALER_EXCHANGEDB_Refund refund; struct TALER_EXCHANGEDB_TransactionList *tl; struct TALER_EXCHANGEDB_TransactionList *tlp; - json_t *wire; const char *sndr = "payto://x-taler-bank/localhost:8080/1"; + const char *rcvr = "payto://x-taler-bank/localhost:8080/2"; + const uint32_t num_partitions = 10; unsigned int matched; unsigned int cnt; - uint64_t rr; enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Absolute now; + struct GNUNET_TIME_Timestamp now; + struct TALER_WireSaltP salt; + struct TALER_CoinPubHashP c_hash; + uint64_t known_coin_id; + uint64_t rrc_serial; + struct TALER_EXCHANGEDB_Refresh refresh; + struct TALER_DenominationPublicKey *new_denom_pubs = NULL; + uint64_t reserve_out_serial_id; + uint64_t melt_serial_id; + struct TALER_PlanchetMasterSecretP ps; + union GNUNET_CRYPTO_BlindingSecretP bks; + const struct TALER_ExchangeWithdrawValues *alg_values + = TALER_denom_ewv_rsa_singleton (); - dkp = NULL; - rh = NULL; - deposit.coin.denom_sig.rsa_signature = NULL; - wire = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("payto_uri", - "payto://iban/DE67830654080004822650?receiver-name=Test"), - GNUNET_JSON_pack_string ("salt", - "this-is-a-salt-value")); + memset (&deposit, + 0, + sizeof (deposit)); + memset (&bd, + 0, + sizeof (bd)); + bd.receiver_wire_account = (char *) rcvr; + bd.cdis = &deposit; + bd.num_cdis = 1; + memset (&salt, + 45, + sizeof (salt)); + memset (&refresh, + 0, + sizeof (refresh)); ZR_BLK (&cbc); ZR_BLK (&cbc2); if (NULL == @@ -1532,10 +1242,12 @@ run (void *cls) } (void) plugin->drop_tables (plugin->cls); if (GNUNET_OK != - plugin->create_tables (plugin->cls)) + plugin->create_tables (plugin->cls, + true, + num_partitions)) { result = 77; - goto drop; + goto cleanup; } plugin->preflight (plugin->cls); FAILIF (GNUNET_OK != @@ -1548,156 +1260,568 @@ run (void *cls) 0, &recoup_cb, NULL)); + /* simple extension check */ + FAILIF (GNUNET_OK != + test_extension_manifest ()); + 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)); + &fees.withdraw)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":0.000010", - &fee_deposit)); + &fees.deposit)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":0.000010", - &fee_refresh)); + &fees.refresh)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":0.000010", - &fee_refund)); + &fees.refund)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":1.000010", &amount_with_fee)); - result = 4; FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->get_latest_reserve_in_reference (plugin->cls, - "exchange-account-1", - &rr)); - now = GNUNET_TIME_absolute_get (); - (void) GNUNET_TIME_round_abs (&now); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->reserves_in_insert (plugin->cls, - &reserve_pub, - &value, - now, - sndr, - "exchange-account-1", - 4)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->get_latest_reserve_in_reference (plugin->cls, - "exchange-account-1", - &rr)); - FAILIF (4 != rr); + plugin->commit (plugin->cls)); + now = GNUNET_TIME_timestamp_get (); + { + struct TALER_EXCHANGEDB_ReserveInInfo reserve = { + .reserve_pub = &reserve_pub, + .balance = &value, + .execution_time = now, + .sender_account_details = sndr, + .exchange_account_name = "exchange-account-1", + .wire_reference = 4 + }; + enum GNUNET_DB_QueryStatus qsr; + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->reserves_in_insert (plugin->cls, + &reserve, + 1, + &qsr)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + qsr); + } FAILIF (GNUNET_OK != check_reserve (&reserve_pub, value.value, value.fraction, value.currency)); - now = GNUNET_TIME_absolute_get (); - (void) GNUNET_TIME_round_abs (&now); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->reserves_in_insert (plugin->cls, - &reserve_pub, - &value, - now, - sndr, - "exchange-account-1", - 5)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->get_latest_reserve_in_reference (plugin->cls, - "exchange-account-1", - &rr)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->get_latest_reserve_in_reference (plugin->cls, - "exchange-account-1", - &rr)); - FAILIF (5 != rr); + now = GNUNET_TIME_timestamp_get (); + RND_BLK (&reserve_pub2); + { + struct TALER_EXCHANGEDB_ReserveInInfo reserve = { + .reserve_pub = &reserve_pub2, + .balance = &value, + .execution_time = now, + .sender_account_details = sndr, + .exchange_account_name = "exchange-account-1", + .wire_reference = 5 + }; + enum GNUNET_DB_QueryStatus qsr; + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->reserves_in_insert (plugin->cls, + &reserve, + 1, + &qsr)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + qsr); + } + FAILIF (GNUNET_OK != + plugin->start (plugin->cls, + "test-2")); FAILIF (GNUNET_OK != check_reserve (&reserve_pub, - value.value * 2, - value.fraction * 2, + value.value, + value.fraction, + value.currency)); + FAILIF (GNUNET_OK != + check_reserve (&reserve_pub2, + value.value, + value.fraction, value.currency)); result = 5; - now = GNUNET_TIME_absolute_get (); - (void) GNUNET_TIME_round_abs (&now); - dkp = create_denom_key_pair (1024, + now = GNUNET_TIME_timestamp_get (); + dkp = create_denom_key_pair (RSA_KEY_SIZE, now, &value, - &fee_withdraw, - &fee_deposit, - &fee_refresh, - &fee_refund); + &fees); GNUNET_assert (NULL != dkp); - GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key, - &dkp_pub_hash); - RND_BLK (&cbc.h_coin_envelope); + TALER_denom_pub_hash (&dkp->pub, + &cbc.denom_pub_hash); RND_BLK (&cbc.reserve_sig); - cbc.denom_pub_hash = dkp_pub_hash; - cbc.sig.rsa_signature - = GNUNET_CRYPTO_rsa_sign_fdh (dkp->priv.rsa_private_key, - &cbc.h_coin_envelope); + RND_BLK (&ps); + TALER_planchet_blinding_secret_create (&ps, + alg_values, + &bks); + { + struct TALER_PlanchetDetail pd; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_AgeCommitmentHash age_hash; + struct TALER_AgeCommitmentHash *p_ah[2] = { + NULL, + &age_hash + }; + + /* Call TALER_denom_blind()/TALER_denom_sign_blinded() twice, once without + * age_hash, once with age_hash */ + RND_BLK (&age_hash); + for (size_t i = 0; i < sizeof(p_ah) / sizeof(p_ah[0]); i++) + { + + RND_BLK (&coin_pub); + GNUNET_assert (GNUNET_OK == + TALER_denom_blind (&dkp->pub, + &bks, + NULL, + p_ah[i], + &coin_pub, + alg_values, + &c_hash, + &pd.blinded_planchet)); + TALER_coin_ev_hash (&pd.blinded_planchet, + &cbc.denom_pub_hash, + &cbc.h_coin_envelope); + if (i != 0) + TALER_blinded_denom_sig_free (&cbc.sig); + GNUNET_assert ( + GNUNET_OK == + TALER_denom_sign_blinded ( + &cbc.sig, + &dkp->priv, + false, + &pd.blinded_planchet)); + TALER_blinded_planchet_free (&pd.blinded_planchet); + } + } + cbc.reserve_pub = reserve_pub; cbc.amount_with_fee = value; GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (CURRENCY, &cbc.withdraw_fee)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->insert_withdraw_info (plugin->cls, - &cbc)); + TALER_amount_set_zero (CURRENCY, + &cbc.withdraw_fee)); + + { + bool found; + bool nonce_reuse; + bool balance_ok; + bool age_ok; + bool conflict; + bool denom_unknown; + uint16_t maximum_age; + uint64_t ruuid; + struct TALER_Amount reserve_balance; + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->do_batch_withdraw (plugin->cls, + now, + &reserve_pub, + &value, + true, + &found, + &balance_ok, + &reserve_balance, + &age_ok, + &maximum_age, + &ruuid)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->do_batch_withdraw_insert (plugin->cls, + NULL, + &cbc, + now, + ruuid, + &denom_unknown, + &conflict, + &nonce_reuse)); + GNUNET_assert (found); + GNUNET_assert (! nonce_reuse); + GNUNET_assert (! denom_unknown); + GNUNET_assert (balance_ok); + } + + FAILIF (GNUNET_OK != check_reserve (&reserve_pub, + 0, + 0, + value.currency)); + FAILIF (GNUNET_OK != + check_reserve (&reserve_pub2, value.value, value.fraction, value.currency)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_reserve_by_h_blind (plugin->cls, &cbc.h_coin_envelope, - &reserve_pub2)); + &reserve_pub3, + &reserve_out_serial_id)); FAILIF (0 != GNUNET_memcmp (&reserve_pub, - &reserve_pub2)); + &reserve_pub3)); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->get_withdraw_info (plugin->cls, &cbc.h_coin_envelope, &cbc2)); - FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_sig, &cbc.reserve_sig)); - FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_pub, &cbc.reserve_pub)); + FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_sig, + &cbc.reserve_sig)); + FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_pub, + &cbc.reserve_pub)); result = 6; - FAILIF (GNUNET_OK != - GNUNET_CRYPTO_rsa_verify (&cbc.h_coin_envelope, - cbc2.sig.rsa_signature, - dkp->pub.rsa_public_key)); + { + struct TALER_DenominationSignature ds; + + GNUNET_assert (GNUNET_OK == + TALER_denom_sig_unblind (&ds, + &cbc2.sig, + &bks, + &c_hash, + alg_values, + &dkp->pub)); + FAILIF (GNUNET_OK != + TALER_denom_pub_verify (&dkp->pub, + &ds, + &c_hash)); + TALER_denom_sig_free (&ds); + } RND_BLK (&coin_sig); RND_BLK (&coin_blind); RND_BLK (&deposit.coin.coin_pub); - GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key, - &deposit.coin.denom_pub_hash); - deposit.coin.denom_sig = cbc.sig; - deadline = GNUNET_TIME_absolute_get (); - (void) GNUNET_TIME_round_abs (&deadline); - FAILIF (TALER_EXCHANGEDB_CKS_ADDED != - plugin->ensure_coin_known (plugin->cls, - &deposit.coin)); + TALER_denom_pub_hash (&dkp->pub, + &deposit.coin.denom_pub_hash); + GNUNET_assert (GNUNET_OK == + TALER_denom_sig_unblind (&deposit.coin.denom_sig, + &cbc.sig, + &bks, + &c_hash, + alg_values, + &dkp->pub)); + deadline = GNUNET_TIME_timestamp_get (); + { + struct TALER_DenominationHashP dph; + struct TALER_AgeCommitmentHash agh; + + FAILIF (TALER_EXCHANGEDB_CKS_ADDED != + plugin->ensure_coin_known (plugin->cls, + &deposit.coin, + &known_coin_id, + &dph, + &agh)); + } + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->commit (plugin->cls)); + { + struct GNUNET_TIME_Timestamp deposit_timestamp + = GNUNET_TIME_timestamp_get (); + bool balance_ok; + uint32_t bad_balance_idx; + bool in_conflict; + struct TALER_PaytoHashP h_payto; + + RND_BLK (&h_payto); + bd.refund_deadline + = GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_MONTHS); + bd.wire_deadline + = GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_MONTHS); + deposit.amount_with_fee = value; + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->do_deposit (plugin->cls, + &bd, + &deposit_timestamp, + &balance_ok, + &bad_balance_idx, + &in_conflict)); + FAILIF (! balance_ok); + FAILIF (in_conflict); + } + + { + bool not_found; + bool refund_ok; + bool gone; + bool conflict; + + refund.coin = deposit.coin; + refund.details.merchant_pub = bd.merchant_pub; + RND_BLK (&refund.details.merchant_sig); + refund.details.h_contract_terms = bd.h_contract_terms; + refund.details.rtransaction_id = 1; + refund.details.refund_amount = value; + refund.details.refund_fee = fees.refund; + RND_BLK (&refund.details.merchant_sig); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->do_refund (plugin->cls, + &refund, + &fees.deposit, + known_coin_id, + ¬_found, + &refund_ok, + &gone, + &conflict)); + FAILIF (not_found); + FAILIF (! refund_ok); + FAILIF (gone); + FAILIF (conflict); + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->select_refunds_by_coin (plugin->cls, + &refund.coin.coin_pub, + &refund.details.merchant_pub, + &refund.details.h_contract_terms, + &check_refund_cb, + &refund)); + } + + /* test do_melt */ + { + bool zombie_required = false; + bool balance_ok; + + refresh.coin = deposit.coin; + RND_BLK (&refresh.coin_sig); + RND_BLK (&refresh.rc); + refresh.amount_with_fee = value; + refresh.noreveal_index = MELT_NOREVEAL_INDEX; + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->do_melt (plugin->cls, + NULL, + &refresh, + known_coin_id, + &zombie_required, + &balance_ok)); + FAILIF (! balance_ok); + FAILIF (zombie_required); + } + + /* test get_melt */ + { + struct TALER_EXCHANGEDB_Melt ret_refresh_session; + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->get_melt (plugin->cls, + &refresh.rc, + &ret_refresh_session, + &melt_serial_id)); + FAILIF (refresh.noreveal_index != + ret_refresh_session.session.noreveal_index); + FAILIF (0 != + TALER_amount_cmp (&refresh.amount_with_fee, + &ret_refresh_session.session.amount_with_fee)); + FAILIF (0 != + TALER_amount_cmp (&fees.refresh, + &ret_refresh_session.melt_fee)); + FAILIF (0 != + GNUNET_memcmp (&refresh.rc, + &ret_refresh_session.session.rc)); + FAILIF (0 != GNUNET_memcmp (&refresh.coin_sig, + &ret_refresh_session.session.coin_sig)); + FAILIF (0 != + GNUNET_memcmp (&refresh.coin.coin_pub, + &ret_refresh_session.session.coin.coin_pub)); + FAILIF (0 != + GNUNET_memcmp (&refresh.coin.denom_pub_hash, + &ret_refresh_session.session.coin.denom_pub_hash)); + } + + { + /* test 'select_refreshes_above_serial_id' */ + auditor_row_cnt = 0; + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->select_refreshes_above_serial_id (plugin->cls, + 0, + &audit_refresh_session_cb, + NULL)); + FAILIF (1 != auditor_row_cnt); + } + + /* do refresh-reveal */ + { + new_dkp = GNUNET_new_array (MELT_NEW_COINS, + struct DenomKeyPair *); + new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS, + struct TALER_DenominationPublicKey); + revealed_coins + = GNUNET_new_array (MELT_NEW_COINS, + struct TALER_EXCHANGEDB_RefreshRevealedCoin); + for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) + { + struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin; + struct GNUNET_TIME_Timestamp now; + struct GNUNET_CRYPTO_BlindedMessage *rp; + struct GNUNET_CRYPTO_RsaBlindedMessage *rsa; + struct TALER_BlindedPlanchet *bp; + + now = GNUNET_TIME_timestamp_get (); + new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE, + now, + &value, + &fees); + GNUNET_assert (NULL != new_dkp[cnt]); + new_denom_pubs[cnt] = new_dkp[cnt]->pub; + ccoin = &revealed_coins[cnt]; + bp = &ccoin->blinded_planchet; + rp = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage); + bp->blinded_message = rp; + rp->cipher = GNUNET_CRYPTO_BSA_RSA; + rp->rc = 1; + rsa = &rp->details.rsa_blinded_message; + rsa->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 ( + GNUNET_CRYPTO_QUALITY_WEAK, + (RSA_KEY_SIZE / 8) - 1); + rsa->blinded_msg = GNUNET_malloc (rsa->blinded_msg_size); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, + rsa->blinded_msg, + rsa->blinded_msg_size); + TALER_denom_pub_hash (&new_dkp[cnt]->pub, + &ccoin->h_denom_pub); + TALER_denom_ewv_copy (&ccoin->exchange_vals, + alg_values); + TALER_coin_ev_hash (bp, + &ccoin->h_denom_pub, + &ccoin->coin_envelope_hash); + GNUNET_assert (GNUNET_OK == + TALER_denom_sign_blinded (&ccoin->coin_sig, + &new_dkp[cnt]->priv, + true, + bp)); + } + RND_BLK (&tprivs); + RND_BLK (&tpub); + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->get_refresh_reveal (plugin->cls, + &refresh.rc, + &never_called_cb, + NULL)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->insert_refresh_reveal (plugin->cls, + melt_serial_id, + MELT_NEW_COINS, + revealed_coins, + TALER_CNC_KAPPA - 1, + tprivs, + &tpub)); + { + struct TALER_BlindedCoinHashP h_coin_ev; + struct TALER_CoinSpendPublicKeyP ocp; + struct TALER_DenominationHashP denom_hash; + + TALER_denom_pub_hash (&new_denom_pubs[0], + &denom_hash); + TALER_coin_ev_hash (&revealed_coins[0].blinded_planchet, + &denom_hash, + &h_coin_ev); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->get_old_coin_by_h_blind (plugin->cls, + &h_coin_ev, + &ocp, + &rrc_serial)); + FAILIF (0 != + GNUNET_memcmp (&ocp, + &refresh.coin.coin_pub)); + } + FAILIF (0 >= + plugin->get_refresh_reveal (plugin->cls, + &refresh.rc, + &check_refresh_reveal_cb, + NULL)); + qs = plugin->get_link_data (plugin->cls, + &refresh.coin.coin_pub, + &handle_link_data_cb, + NULL); + FAILIF (0 >= qs); + { + /* Just to test fetching a coin with melt history */ + struct TALER_EXCHANGEDB_TransactionList *tl; + enum GNUNET_DB_QueryStatus qs; + uint64_t etag; + struct TALER_Amount balance; + struct TALER_DenominationHashP h_denom_pub; + + qs = plugin->get_coin_transactions (plugin->cls, + &refresh.coin.coin_pub, + 0, + 0, + &etag, + &balance, + &h_denom_pub, + &tl); + FAILIF (0 >= qs); + FAILIF (NULL == tl); + plugin->free_coin_transaction_list (plugin->cls, + tl); + } + } + + /* do recoup-refresh */ + { + struct GNUNET_TIME_Timestamp recoup_timestamp + = GNUNET_TIME_timestamp_get (); + union GNUNET_CRYPTO_BlindingSecretP coin_bks; + uint64_t new_known_coin_id; + struct TALER_CoinPublicInfo new_coin; + struct TALER_DenominationHashP dph; + struct TALER_AgeCommitmentHash agh; + bool recoup_ok; + bool internal_failure; + + new_coin = deposit.coin; /* steal basic data */ + RND_BLK (&new_coin.coin_pub); + FAILIF (TALER_EXCHANGEDB_CKS_ADDED != + plugin->ensure_coin_known (plugin->cls, + &new_coin, + &new_known_coin_id, + &dph, + &agh)); + RND_BLK (&coin_bks); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->do_recoup_refresh (plugin->cls, + &deposit.coin.coin_pub, + rrc_serial, + &coin_bks, + &new_coin.coin_pub, + new_known_coin_id, + &coin_sig, + &recoup_timestamp, + &recoup_ok, + &internal_failure)); + FAILIF (! recoup_ok); + FAILIF (internal_failure); + } + + /* do recoup */ { struct TALER_EXCHANGEDB_Reserve pre_reserve; struct TALER_EXCHANGEDB_Reserve post_reserve; struct TALER_Amount delta; + bool recoup_ok; + bool internal_failure; + struct GNUNET_TIME_Timestamp recoup_timestamp + = GNUNET_TIME_timestamp_get (); pre_reserve.pub = reserve_pub; FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->reserves_get (plugin->cls, &pre_reserve)); + FAILIF (! TALER_amount_is_zero (&pre_reserve.balance)); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->insert_recoup_request (plugin->cls, - &reserve_pub, - &deposit.coin, - &coin_sig, - &coin_blind, - &value, - &cbc.h_coin_envelope, - deadline)); + plugin->do_recoup (plugin->cls, + &reserve_pub, + reserve_out_serial_id, + &coin_blind, + &deposit.coin.coin_pub, + known_coin_id, + &coin_sig, + &recoup_timestamp, + &recoup_ok, + &internal_failure)); + FAILIF (internal_failure); + FAILIF (! recoup_ok); post_reserve.pub = reserve_pub; FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->reserves_get (plugin->cls, @@ -1710,39 +1834,67 @@ run (void *cls) TALER_amount_cmp (&delta, &value)); } + + FAILIF (GNUNET_OK != + plugin->start (plugin->cls, + "test-3")); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->select_recoup_above_serial_id (plugin->cls, 0, &recoup_cb, &coin_blind)); - - GNUNET_assert (0 <= - TALER_amount_add (&amount_with_fee, - &value, - &value)); + /* Do reserve close */ + now = GNUNET_TIME_timestamp_get (); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":0.000010", &fee_closing)); - now = GNUNET_TIME_absolute_get (); - (void) GNUNET_TIME_round_abs (&now); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->insert_reserve_closed (plugin->cls, - &reserve_pub, + &reserve_pub2, now, sndr, &wire_out_wtid, &amount_with_fee, - &fee_closing)); + &fee_closing, + 0)); + FAILIF (GNUNET_OK != + check_reserve (&reserve_pub2, + 0, + 0, + value.currency)); + now = GNUNET_TIME_timestamp_get (); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->insert_reserve_closed (plugin->cls, + &reserve_pub, + now, + sndr, + &wire_out_wtid, + &value, + &fee_closing, + 0)); FAILIF (GNUNET_OK != check_reserve (&reserve_pub, 0, 0, value.currency)); - result = 7; - qs = plugin->get_reserve_history (plugin->cls, - &reserve_pub, - &rh); + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->commit (plugin->cls)); + + /* check reserve history */ + { + struct TALER_Amount balance; + uint64_t etag_out; + + qs = plugin->get_reserve_history (plugin->cls, + &reserve_pub, + 0, + 0, + &etag_out, + &balance, + &rh); + } FAILIF (0 > qs); FAILIF (NULL == rh); rh_head = rh; @@ -1752,9 +1904,9 @@ run (void *cls) { case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE: bt = rh_head->details.bank; - FAILIF (0 != memcmp (&bt->reserve_pub, - &reserve_pub, - sizeof (reserve_pub))); + FAILIF (0 != + GNUNET_memcmp (&bt->reserve_pub, + &reserve_pub)); /* this is the amount we transferred twice*/ FAILIF (1 != bt->amount.value); FAILIF (1000 != bt->amount.fraction); @@ -1763,31 +1915,32 @@ run (void *cls) 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))); + FAILIF (0 != + GNUNET_memcmp (&withdraw->reserve_pub, + &reserve_pub)); + FAILIF (0 != + GNUNET_memcmp (&withdraw->h_coin_envelope, + &cbc.h_coin_envelope)); break; case TALER_EXCHANGEDB_RO_RECOUP_COIN: { struct TALER_EXCHANGEDB_Recoup *recoup = rh_head->details.recoup; - FAILIF (0 != memcmp (&recoup->coin_sig, - &coin_sig, - sizeof (coin_sig))); - FAILIF (0 != memcmp (&recoup->coin_blind, - &coin_blind, - sizeof (coin_blind))); - FAILIF (0 != memcmp (&recoup->reserve_pub, - &reserve_pub, - sizeof (reserve_pub))); - FAILIF (0 != memcmp (&recoup->coin.coin_pub, - &deposit.coin.coin_pub, - sizeof (deposit.coin.coin_pub))); - FAILIF (0 != TALER_amount_cmp (&recoup->value, - &value)); + FAILIF (0 != + GNUNET_memcmp (&recoup->coin_sig, + &coin_sig)); + FAILIF (0 != + GNUNET_memcmp (&recoup->coin_blind, + &coin_blind)); + FAILIF (0 != + GNUNET_memcmp (&recoup->reserve_pub, + &reserve_pub)); + FAILIF (0 != + GNUNET_memcmp (&recoup->coin.coin_pub, + &deposit.coin.coin_pub)); + FAILIF (0 != + TALER_amount_cmp (&recoup->value, + &value)); } break; case TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK: @@ -1795,18 +1948,39 @@ run (void *cls) struct TALER_EXCHANGEDB_ClosingTransfer *closing = rh_head->details.closing; - FAILIF (0 != memcmp (&closing->reserve_pub, - &reserve_pub, - sizeof (reserve_pub))); + FAILIF (0 != + GNUNET_memcmp (&closing->reserve_pub, + &reserve_pub)); FAILIF (0 != TALER_amount_cmp (&closing->amount, &amount_with_fee)); FAILIF (0 != TALER_amount_cmp (&closing->closing_fee, &fee_closing)); } break; + case TALER_EXCHANGEDB_RO_PURSE_MERGE: + { + /* FIXME: not yet tested */ + break; + } + case TALER_EXCHANGEDB_RO_HISTORY_REQUEST: + { + /* FIXME: not yet tested */ + break; + } + case TALER_EXCHANGEDB_RO_OPEN_REQUEST: + { + /* FIXME: not yet tested */ + break; + } + case TALER_EXCHANGEDB_RO_CLOSE_REQUEST: + { + /* FIXME: not yet tested */ + break; + } } } - FAILIF (5 != cnt); + GNUNET_assert (4 == cnt); + FAILIF (4 != cnt); auditor_row_cnt = 0; FAILIF (0 >= @@ -1821,227 +1995,6 @@ run (void *cls) NULL)); FAILIF (3 != auditor_row_cnt); - /* Tests for deposits */ - memset (&deposit, - 0, - sizeof (deposit)); - RND_BLK (&deposit.coin.coin_pub); - GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key, - &deposit.coin.denom_pub_hash); - deposit.coin.denom_sig = cbc.sig; - RND_BLK (&deposit.csig); - RND_BLK (&deposit.merchant_pub); - RND_BLK (&deposit.h_contract_terms); - GNUNET_assert (GNUNET_OK == - TALER_JSON_merchant_wire_signature_hash (wire, - &deposit.h_wire)); - deposit.receiver_wire_account = wire; - deposit.amount_with_fee = value; - deposit.deposit_fee = fee_deposit; - - deposit.refund_deadline = deadline; - deposit.wire_deadline = deadline; - result = 8; - FAILIF (TALER_EXCHANGEDB_CKS_ADDED != - plugin->ensure_coin_known (plugin->cls, - &deposit.coin)); - { - struct GNUNET_TIME_Absolute now; - struct GNUNET_TIME_Absolute r; - struct TALER_Amount deposit_fee; - - now = GNUNET_TIME_absolute_get (); - GNUNET_TIME_round_abs (&now); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->insert_deposit (plugin->cls, - now, - &deposit)); - FAILIF (1 != - plugin->have_deposit (plugin->cls, - &deposit, - GNUNET_YES, - &deposit_fee, - &r)); - FAILIF (now.abs_value_us != r.abs_value_us); - } - { - struct GNUNET_TIME_Absolute start_range; - struct GNUNET_TIME_Absolute end_range; - - start_range = GNUNET_TIME_absolute_subtract (deadline, - GNUNET_TIME_UNIT_SECONDS); - end_range = GNUNET_TIME_absolute_add (deadline, - GNUNET_TIME_UNIT_SECONDS); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->select_deposits_missing_wire (plugin->cls, - start_range, - end_range, - &wire_missing_cb, - &deposit)); - FAILIF (8 != result); - } - auditor_row_cnt = 0; - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->select_deposits_above_serial_id (plugin->cls, - 0, - &audit_deposit_cb, - NULL)); - FAILIF (1 != auditor_row_cnt); - result = 9; - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->iterate_matching_deposits (plugin->cls, - &deposit.h_wire, - &deposit.merchant_pub, - &matching_deposit_cb, - &deposit, - 2)); - sleep (2); /* give deposit time to be ready */ - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->get_ready_deposit (plugin->cls, - 0, - INT32_MAX, - &deposit_cb, - &deposit)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->commit (plugin->cls)); - FAILIF (GNUNET_OK != - plugin->start (plugin->cls, - "test-2")); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->mark_deposit_tiny (plugin->cls, - deposit_rowid)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->get_ready_deposit (plugin->cls, - 0, - INT32_MAX, - &deposit_cb, - &deposit)); - plugin->rollback (plugin->cls); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->get_ready_deposit (plugin->cls, - 0, - INT32_MAX, - &deposit_cb, - &deposit)); - FAILIF (GNUNET_OK != - plugin->start (plugin->cls, - "test-3")); - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->test_deposit_done (plugin->cls, - &deposit.coin.coin_pub, - &deposit.merchant_pub, - &deposit.h_contract_terms, - &deposit.h_wire)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->mark_deposit_done (plugin->cls, - deposit_rowid)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->commit (plugin->cls)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->test_deposit_done (plugin->cls, - &deposit.coin.coin_pub, - &deposit.merchant_pub, - &deposit.h_contract_terms, - &deposit.h_wire)); - - result = 10; - deposit2 = deposit; - FAILIF (GNUNET_OK != - plugin->start (plugin->cls, - "test-2")); - RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */ - { - struct GNUNET_TIME_Absolute r; - struct TALER_Amount deposit_fee; - - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->have_deposit (plugin->cls, - &deposit2, - GNUNET_YES, - &deposit_fee, - &r)); - deposit2.merchant_pub = deposit.merchant_pub; - RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */ - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->have_deposit (plugin->cls, - &deposit2, - GNUNET_YES, - &deposit_fee, - &r)); - } - FAILIF (GNUNET_OK != - test_melting ()); - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->commit (plugin->cls)); - - - /* test insert_refund! */ - refund.coin = deposit.coin; - refund.details.merchant_pub = deposit.merchant_pub; - RND_BLK (&refund.details.merchant_sig); - refund.details.h_contract_terms = deposit.h_contract_terms; - refund.details.rtransaction_id - = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT64_MAX); - refund.details.refund_amount = deposit.amount_with_fee; - refund.details.refund_fee = fee_refund; - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->insert_refund (plugin->cls, - &refund)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->select_refunds_by_coin (plugin->cls, - &refund.coin.coin_pub, - &refund.details.merchant_pub, - &refund.details.h_contract_terms, - &check_refund_cb, - &refund)); - - /* test recoup / revocation */ - RND_BLK (&master_sig); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->insert_denomination_revocation (plugin->cls, - &dkp_pub_hash, - &master_sig)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->commit (plugin->cls)); - plugin->preflight (plugin->cls); - FAILIF (GNUNET_OK != - plugin->start (plugin->cls, - "test-4")); - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->insert_denomination_revocation (plugin->cls, - &dkp_pub_hash, - &master_sig)); - plugin->rollback (plugin->cls); - plugin->preflight (plugin->cls); - FAILIF (GNUNET_OK != - plugin->start (plugin->cls, - "test-5")); - { - struct TALER_MasterSignatureP msig; - uint64_t rev_rowid; - - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->get_denomination_revocation (plugin->cls, - &dkp_pub_hash, - &msig, - &rev_rowid)); - FAILIF (0 != GNUNET_memcmp (&msig, - &master_sig)); - } - - - RND_BLK (&coin_sig); - RND_BLK (&coin_blind); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->insert_recoup_request (plugin->cls, - &reserve_pub, - &deposit.coin, - &coin_sig, - &coin_blind, - &value, - &cbc.h_coin_envelope, - deadline)); auditor_row_cnt = 0; FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != @@ -2049,12 +2002,21 @@ run (void *cls) 0, &audit_refund_cb, NULL)); - FAILIF (1 != auditor_row_cnt); - qs = plugin->get_coin_transactions (plugin->cls, - &refund.coin.coin_pub, - GNUNET_YES, - &tl); + { + uint64_t etag = 0; + struct TALER_Amount balance; + struct TALER_DenominationHashP h_denom_pub; + + qs = plugin->get_coin_transactions (plugin->cls, + &refund.coin.coin_pub, + 0, + 0, + &etag, + &balance, + &h_denom_pub, + &tl); + } FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs); GNUNET_assert (NULL != tl); matched = 0; @@ -2069,40 +2031,39 @@ run (void *cls) /* Note: we're not comparing the denomination keys, as there is still the question of whether we should even bother exporting them here. */ - FAILIF (0 != memcmp (&have->csig, - &deposit.csig, - sizeof (struct TALER_CoinSpendSignatureP))); - FAILIF (0 != memcmp (&have->merchant_pub, - &deposit.merchant_pub, - sizeof (struct TALER_MerchantPublicKeyP))); - FAILIF (0 != memcmp (&have->h_contract_terms, - &deposit.h_contract_terms, - sizeof (struct GNUNET_HashCode))); - FAILIF (0 != memcmp (&have->h_wire, - &deposit.h_wire, - sizeof (struct GNUNET_HashCode))); - /* Note: not comparing 'wire', seems truly redundant and would be tricky */ - FAILIF (have->timestamp.abs_value_us != deposit.timestamp.abs_value_us); - FAILIF (have->refund_deadline.abs_value_us != - deposit.refund_deadline.abs_value_us); - FAILIF (have->wire_deadline.abs_value_us != - deposit.wire_deadline.abs_value_us); + FAILIF (0 != + GNUNET_memcmp (&have->csig, + &deposit.csig)); + FAILIF (0 != + GNUNET_memcmp (&have->merchant_pub, + &bd.merchant_pub)); + FAILIF (0 != + GNUNET_memcmp (&have->h_contract_terms, + &bd.h_contract_terms)); + FAILIF (0 != + GNUNET_memcmp (&have->wire_salt, + &bd.wire_salt)); + FAILIF (GNUNET_TIME_timestamp_cmp (have->timestamp, + !=, + bd.wallet_timestamp)); + FAILIF (GNUNET_TIME_timestamp_cmp (have->refund_deadline, + !=, + bd.refund_deadline)); + FAILIF (GNUNET_TIME_timestamp_cmp (have->wire_deadline, + !=, + bd.wire_deadline)); FAILIF (0 != TALER_amount_cmp (&have->amount_with_fee, &deposit.amount_with_fee)); - FAILIF (0 != TALER_amount_cmp (&have->deposit_fee, - &deposit.deposit_fee)); matched |= 1; break; } -#if 0 /* this coin pub was actually never melted... */ case TALER_EXCHANGEDB_TT_MELT: - FAILIF (0 != memcmp (&melt, - &tlp->details.melt, - sizeof (struct TALER_EXCHANGEDB_Melt))); + FAILIF (0 != + GNUNET_memcmp (&refresh.rc, + &tlp->details.melt->rc)); matched |= 2; break; -#endif case TALER_EXCHANGEDB_TT_REFUND: { struct TALER_EXCHANGEDB_RefundListEntry *have = tlp->details.refund; @@ -2140,21 +2101,316 @@ run (void *cls) matched |= 8; break; } + case TALER_EXCHANGEDB_TT_OLD_COIN_RECOUP: + /* TODO: check fields better... */ + matched |= 16; + break; default: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected coin history transaction type: %d\n", + tlp->type); FAILIF (1); break; } } - FAILIF (13 != matched); + FAILIF (31 != matched); plugin->free_coin_transaction_list (plugin->cls, tl); + + /* Tests for deposits+wire */ + TALER_denom_sig_free (&deposit.coin.denom_sig); + memset (&deposit, + 0, + sizeof (deposit)); + RND_BLK (&deposit.coin.coin_pub); + TALER_denom_pub_hash (&dkp->pub, + &deposit.coin.denom_pub_hash); + GNUNET_assert (GNUNET_OK == + TALER_denom_sig_unblind (&deposit.coin.denom_sig, + &cbc.sig, + &bks, + &c_hash, + alg_values, + &dkp->pub)); + RND_BLK (&deposit.csig); + RND_BLK (&bd.merchant_pub); + RND_BLK (&bd.h_contract_terms); + RND_BLK (&bd.wire_salt); + bd.receiver_wire_account = + "payto://iban/DE67830654080004822650?receiver-name=Test"; + TALER_merchant_wire_signature_hash ( + "payto://iban/DE67830654080004822650?receiver-name=Test", + &bd.wire_salt, + &h_wire_wt); + deposit.amount_with_fee = value; + bd.refund_deadline = deadline; + bd.wire_deadline = deadline; + result = 8; + FAILIF (GNUNET_OK != + plugin->start (plugin->cls, + "test-3")); + { + uint64_t known_coin_id; + struct TALER_DenominationHashP dph; + struct TALER_AgeCommitmentHash agh; + + FAILIF (TALER_EXCHANGEDB_CKS_ADDED != + plugin->ensure_coin_known (plugin->cls, + &deposit.coin, + &known_coin_id, + &dph, + &agh)); + } + { + struct GNUNET_TIME_Timestamp now; + struct GNUNET_TIME_Timestamp r; + struct TALER_Amount deposit_fee; + struct TALER_MerchantWireHashP h_wire; + bool balance_ok; + uint32_t bad_idx; + bool ctr_conflict; + + now = GNUNET_TIME_timestamp_get (); + TALER_payto_hash (bd.receiver_wire_account, + &bd.wire_target_h_payto); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->do_deposit (plugin->cls, + &bd, + &now, + &balance_ok, + &bad_idx, + &ctr_conflict)); + TALER_merchant_wire_signature_hash (bd.receiver_wire_account, + &bd.wire_salt, + &h_wire); + FAILIF (1 != + plugin->have_deposit2 (plugin->cls, + &bd.h_contract_terms, + &h_wire, + &deposit.coin.coin_pub, + &bd.merchant_pub, + bd.refund_deadline, + &deposit_fee, + &r)); + FAILIF (GNUNET_TIME_timestamp_cmp (now, + !=, + r)); + } + { + result = 66; + FAILIF (0 >= + plugin->select_batch_deposits_missing_wire (plugin->cls, + 0, + &wire_missing_cb, + &deposit)); + FAILIF (8 != result); + } + auditor_row_cnt = 0; + FAILIF (0 >= + plugin->select_coin_deposits_above_serial_id (plugin->cls, + 0, + &audit_deposit_cb, + NULL)); + FAILIF (0 == auditor_row_cnt); + result = 8; + sleep (2); /* give deposit time to be ready */ + { + struct TALER_MerchantPublicKeyP merchant_pub2; + char *payto_uri2; + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->get_ready_deposit (plugin->cls, + 0, + INT32_MAX, + &merchant_pub2, + &payto_uri2)); + FAILIF (0 != GNUNET_memcmp (&merchant_pub2, + &bd.merchant_pub)); + FAILIF (0 != strcmp (payto_uri2, + bd.receiver_wire_account)); + TALER_payto_hash (payto_uri2, + &wire_target_h_payto); + GNUNET_free (payto_uri2); + } + + { + struct TALER_Amount total; + struct TALER_WireTransferIdentifierRawP wtid; + + memset (&wtid, + 41, + sizeof (wtid)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->aggregate (plugin->cls, + &wire_target_h_payto, + &bd.merchant_pub, + &wtid, + &total)); + } + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->commit (plugin->cls)); + FAILIF (GNUNET_OK != + plugin->start (plugin->cls, + "test-3")); + { + struct TALER_WireTransferIdentifierRawP wtid; + struct TALER_Amount total; + struct TALER_WireTransferIdentifierRawP wtid2; + struct TALER_Amount total2; + + memset (&wtid, + 42, + sizeof (wtid)); + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (CURRENCY ":42", + &total)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->select_aggregation_transient (plugin->cls, + &wire_target_h_payto, + &bd.merchant_pub, + "x-bank", + &wtid2, + &total2)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->create_aggregation_transient (plugin->cls, + &wire_target_h_payto, + "x-bank", + &bd.merchant_pub, + &wtid, + 0, + &total)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->select_aggregation_transient (plugin->cls, + &wire_target_h_payto, + &bd.merchant_pub, + "x-bank", + &wtid2, + &total2)); + FAILIF (0 != + GNUNET_memcmp (&wtid2, + &wtid)); + FAILIF (0 != + TALER_amount_cmp (&total2, + &total)); + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (CURRENCY ":43", + &total)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->update_aggregation_transient (plugin->cls, + &wire_target_h_payto, + &wtid, + 0, + &total)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->select_aggregation_transient (plugin->cls, + &wire_target_h_payto, + &bd.merchant_pub, + "x-bank", + &wtid2, + &total2)); + FAILIF (0 != + GNUNET_memcmp (&wtid2, + &wtid)); + FAILIF (0 != + TALER_amount_cmp (&total2, + &total)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->delete_aggregation_transient (plugin->cls, + &wire_target_h_payto, + &wtid)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->select_aggregation_transient (plugin->cls, + &wire_target_h_payto, + &bd.merchant_pub, + "x-bank", + &wtid2, + &total2)); + } + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->commit (plugin->cls)); + + result = 10; + FAILIF (GNUNET_OK != + plugin->start (plugin->cls, + "test-2")); + RND_BLK (&mpub2); /* should fail if merchant is different */ + { + struct TALER_MerchantWireHashP h_wire; + struct GNUNET_TIME_Timestamp r; + struct TALER_Amount deposit_fee; + + TALER_merchant_wire_signature_hash (bd.receiver_wire_account, + &bd.wire_salt, + &h_wire); + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->have_deposit2 (plugin->cls, + &bd.h_contract_terms, + &h_wire, + &deposit.coin.coin_pub, + &mpub2, + bd.refund_deadline, + &deposit_fee, + &r)); + RND_BLK (&cpub2); /* should fail if coin is different */ + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->have_deposit2 (plugin->cls, + &bd.h_contract_terms, + &h_wire, + &cpub2, + &bd.merchant_pub, + bd.refund_deadline, + &deposit_fee, + &r)); + } + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->commit (plugin->cls)); + + + /* test revocation */ + FAILIF (GNUNET_OK != + plugin->start (plugin->cls, + "test-3b")); + RND_BLK (&master_sig); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->insert_denomination_revocation (plugin->cls, + &cbc.denom_pub_hash, + &master_sig)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->commit (plugin->cls)); + plugin->preflight (plugin->cls); + FAILIF (GNUNET_OK != + plugin->start (plugin->cls, + "test-4")); + FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->insert_denomination_revocation (plugin->cls, + &cbc.denom_pub_hash, + &master_sig)); + plugin->rollback (plugin->cls); + plugin->preflight (plugin->cls); + FAILIF (GNUNET_OK != + plugin->start (plugin->cls, + "test-5")); + { + struct TALER_MasterSignatureP msig; + uint64_t rev_rowid; + + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->get_denomination_revocation (plugin->cls, + &cbc.denom_pub_hash, + &msig, + &rev_rowid)); + FAILIF (0 != GNUNET_memcmp (&msig, + &master_sig)); + } + + plugin->rollback (plugin->cls); FAILIF (GNUNET_OK != test_wire_prepare ()); FAILIF (GNUNET_OK != - test_wire_out (&deposit)); + test_wire_out (&bd)); FAILIF (GNUNET_OK != test_gc ()); FAILIF (GNUNET_OK != @@ -2173,14 +2429,29 @@ drop: rh = NULL; GNUNET_break (GNUNET_OK == plugin->drop_tables (plugin->cls)); +cleanup: 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.sig.rsa_signature) - GNUNET_CRYPTO_rsa_signature_free (cbc2.sig.rsa_signature); + if (NULL != revealed_coins) + { + for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) + { + TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig); + TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet); + } + GNUNET_free (revealed_coins); + revealed_coins = NULL; + } + GNUNET_free (new_denom_pubs); + for (unsigned int cnt = 0; + (NULL != new_dkp) && (cnt < MELT_NEW_COINS) && (NULL != new_dkp[cnt]); + cnt++) + destroy_denom_key_pair (new_dkp[cnt]); + GNUNET_free (new_dkp); + TALER_denom_sig_free (&deposit.coin.denom_sig); + TALER_blinded_denom_sig_free (&cbc.sig); + TALER_blinded_denom_sig_free (&cbc2.sig); dkp = NULL; - json_decref (wire); TALER_EXCHANGEDB_plugin_unload (plugin); plugin = NULL; } @@ -2195,6 +2466,7 @@ main (int argc, char *testname; struct GNUNET_CONFIGURATION_Handle *cfg; + (void) argc; result = -1; if (NULL == (plugin_name = strrchr (argv[0], (int) '-'))) { @@ -2202,8 +2474,9 @@ main (int argc, return -1; } GNUNET_log_setup (argv[0], - "WARNING", + "INFO", NULL); + TALER_OS_init (); plugin_name++; (void) GNUNET_asprintf (&testname, "test-exchange-db-%s", |