donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

commit 83e211889442205d1da1a434a03c06d230355e68
parent 87999a441ef2701437219be3016ca54e1285a4b5
Author: Casaburi Johannes <johannes.casaburi@students.bfh.ch>
Date:   Mon, 11 Dec 2023 14:35:38 +0100

[db] cleanup tests

Diffstat:
Asrc/donaudb/test-donau-db-postgres.conf | 19+++++++++++++++++++
Msrc/donaudb/test_donaudb.c | 2272-------------------------------------------------------------------------------
Msrc/pq/pq_query_helper.c | 1+
Asrc/testing/donau-unified-setup.sh | 822+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 842 insertions(+), 2272 deletions(-)

diff --git a/src/donaudb/test-donau-db-postgres.conf b/src/donaudb/test-donau-db-postgres.conf @@ -0,0 +1,19 @@ +[donau] +#The DB plugin to use +DB = postgres + +BASE_URL = http://localhost/ + +[donaudb-postgres] + +#The connection string the plugin has to use for connecting to the database +CONFIG = postgres:///talercheck + +# Where are the SQL files to setup our tables? +SQL_DIR = $DATADIR/sql/donau/ + +[taler] +CURRENCY = EUR + +[donaudb] + diff --git a/src/donaudb/test_donaudb.c b/src/donaudb/test_donaudb.c @@ -165,2278 +165,6 @@ drop: return GNUNET_SYSERR; } - -/** - * Test API relating to persisting the wire plugins preparation data. - * - * @return #GNUNET_OK on success - */ -static enum GNUNET_GenericReturnValue -test_wire_prepare (void) -{ - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->wire_prepare_data_get (plugin->cls, - 0, - 1, - &dead_prepare_cb, - NULL)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->wire_prepare_data_insert (plugin->cls, - "testcase", - "hello world", - 11)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->wire_prepare_data_get (plugin->cls, - 0, - 1, - &mark_prepare_cb, - NULL)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->wire_prepare_data_get (plugin->cls, - 0, - 1, - &dead_prepare_cb, - NULL)); - return GNUNET_OK; -drop: - return GNUNET_SYSERR; -} - - -/** - * Checks if the given reserve has the given amount of balance and expiry - * - * @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 enum GNUNET_GenericReturnValue -check_reserve (const struct TALER_ReservePublicKeyP *pub, - uint64_t value, - uint32_t fraction, - const char *currency) -{ - struct DONAUDB_Reserve reserve; - - reserve.pub = *pub; - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->reserves_get (plugin->cls, - &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 key pair to destroy - */ -static void -destroy_denom_key_pair (struct DenomKeyPair *dkp) -{ - TALER_denom_pub_free (&dkp->pub); - TALER_denom_priv_free (&dkp->priv); - GNUNET_free (dkp); -} - - -/** - * 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 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_Timestamp now, - const struct TALER_Amount *value, - const struct TALER_DenomFeeSet *fees) -{ - struct DenomKeyPair *dkp; - struct DONAUDB_DenominationKey dki; - struct DONAUDB_DenominationKeyInformation issue2; - - dkp = GNUNET_new (struct DenomKeyPair); - GNUNET_assert (GNUNET_OK == - TALER_denom_priv_create (&dkp->priv, - &dkp->pub, - TALER_DENOMINATION_RSA, - size)); - /* Using memset() as fields like master key and signature - are not properly initialized for this test. */ - memset (&dki, - 0, - sizeof (struct DONAUDB_DenominationKey)); - dki.denom_pub = dkp->pub; - 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, - &dki.issue)) - { - GNUNET_break (0); - 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.denom_hash, - &issue2)) - { - GNUNET_break (0); - destroy_denom_key_pair (dkp); - return NULL; - } - if (0 != GNUNET_memcmp (&dki.issue, - &issue2)) - { - GNUNET_break (0); - destroy_denom_key_pair (dkp); - return NULL; - } - return dkp; -} - - -static struct TALER_Amount value; -static struct TALER_DenomFeeSet fees; -static struct TALER_Amount fee_closing; -static struct TALER_Amount amount_with_fee; - - -/** - * Number of newly minted coins to use in the test. - */ -#define MELT_NEW_COINS 5 - -/** - * Which index was 'randomly' chosen for the reveal for the test? - */ -#define MELT_NOREVEAL_INDEX 1 - -/** - * How big do we make the RSA keys? - */ -#define RSA_KEY_SIZE 1024 - -static struct DONAUDB_RefreshRevealedCoin *revealed_coins; - -static struct TALER_TransferPrivateKeyP tprivs[TALER_CNC_KAPPA]; - -static struct TALER_TransferPublicKeyP tpub; - - -/** - * Function called with information about a refresh order. This - * one should not be called in a successful test. - * - * @param cls closure - * @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 - */ -static void -never_called_cb (void *cls, - uint32_t num_freshcoins, - const struct DONAUDB_RefreshRevealedCoin *rrcs) -{ - (void) cls; - (void) num_freshcoins; - (void) rrcs; - GNUNET_assert (0); /* should never be called! */ -} - - -/** - * Function called with information about a refresh order. - * Checks that the response matches what we expect to see. - * - * @param cls closure - * @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 - */ -static void -check_refresh_reveal_cb ( - void *cls, - uint32_t num_freshcoins, - const struct DONAUDB_RefreshRevealedCoin *rrcs) -{ - (void) cls; - /* compare the refresh commit coin arrays */ - for (unsigned int cnt = 0; cnt < num_freshcoins; cnt++) - { - const struct DONAUDB_RefreshRevealedCoin *acoin = - &revealed_coins[cnt]; - const struct DONAUDB_RefreshRevealedCoin *bcoin = &rrcs[cnt]; - - GNUNET_assert (0 == - TALER_blinded_planchet_cmp (&acoin->blinded_planchet, - &bcoin->blinded_planchet)); - GNUNET_assert (0 == - GNUNET_memcmp (&acoin->h_denom_pub, - &bcoin->h_denom_pub)); - } -} - - -/** - * Counter used in auditor-related db functions. Used to count - * expected rows. - */ -static unsigned int auditor_row_cnt; - - -/** - * Function called with details about coins that were melted, - * with the goal of auditing the refresh's execution. - * - * - * @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 - * @param num_freshcoins how many coins were issued - * @param noreveal_index which index was picked by the donau in cut-and-choose - * @param rc what is the session hash - * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop - */ -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; -} - - -/** - * Denomination keys used for fresh coins in melt test. - */ -static struct DenomKeyPair **new_dkp; - - -/** - * Function called with the session hashes and transfer secret - * information for a given coin. - * - * @param cls closure - * @param transfer_pub public transfer key for the session - * @param ldl link data for @a transfer_pub - */ -static void -handle_link_data_cb (void *cls, - const struct TALER_TransferPublicKeyP *transfer_pub, - const struct DONAUDB_LinkList *ldl) -{ - (void) cls; - (void) transfer_pub; - for (const struct DONAUDB_LinkList *ldlp = ldl; - NULL != ldlp; - ldlp = ldlp->next) - { - bool found; - - found = false; - for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) - { - if ( (0 == - TALER_denom_pub_cmp (&ldlp->denom_pub, - &new_dkp[cnt]->pub)) && - (0 == - TALER_blinded_denom_sig_cmp (&ldlp->ev_sig, - &revealed_coins[cnt].coin_sig)) ) - { - found = true; - break; - } - } - GNUNET_assert (GNUNET_NO != found); - } -} - - -/** - * Callback that should never be called. - */ -static void -cb_wt_never (void *cls, - uint64_t serial_id, - const struct DONAU_CharityPublicKeyP *charity_pub, - 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) charity_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 */ -} - - -static struct DONAU_CharityPublicKeyP charity_pub_wt; -static struct TALER_CharityWireHashP 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_Timestamp wire_out_date; -static struct TALER_WireTransferIdentifierRawP wire_out_wtid; - - -/** - * Callback that should be called with the WT data. - */ -static void -cb_wt_check (void *cls, - uint64_t rowid, - const struct DONAU_CharityPublicKeyP *charity_pub, - 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 (charity_pub, - &charity_pub_wt)); - GNUNET_assert (0 == strcmp (account_payto_uri, - "payto://iban/DE67830654080004822650?receiver-name=Test")); - 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, - &coin_pub_wt)); - GNUNET_assert (0 == TALER_amount_cmp (coin_value, - &coin_value_wt)); - GNUNET_assert (0 == TALER_amount_cmp (coin_fee, - &coin_fee_wt)); -} - - -/** - * Here we store the hash of the payto URI. - */ -static struct TALER_PaytoHashP wire_target_h_payto; - - -/** - * Callback for #select_coin_deposits_above_serial_id () - * - * @param cls closure - * @param rowid unique serial ID for the deposit in our DB - * @param donau_timestamp when did the deposit happen - * @param deposit deposit details - * @param denom_pub denomination of the @a coin_pub - * @param done flag set if the deposit was already executed (or not) - * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop - */ -static enum GNUNET_GenericReturnValue -audit_deposit_cb (void *cls, - uint64_t rowid, - struct GNUNET_TIME_Timestamp donau_timestamp, - const struct DONAUDB_Deposit *deposit, - const struct TALER_DenominationPublicKey *denom_pub, - bool done) -{ - (void) cls; - (void) rowid; - (void) donau_timestamp; - (void) deposit; - (void) denom_pub; - (void) done; - auditor_row_cnt++; - return GNUNET_OK; -} - - -/** - * Function called with details about coins that were refunding, - * with the goal of auditing the refund's execution. - * - * @param cls closure - * @param rowid unique serial ID for the refund in our DB - * @param denom_pub denomination of the @a coin_pub - * @param coin_pub public key of the coin - * @param charity_pub public key of the charity - * @param charity_sig signature of the charity - * @param h_contract_terms hash of the proposal data in - * the contract between charity and donor - * @param rtransaction_id refund transaction ID chosen by the charity - * @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 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 DONAU_CharityPublicKeyP *charity_pub, - const struct DONAU_CharitySignatureP *charity_sig, - const struct TALER_PrivateContractHashP *h_contract_terms, - uint64_t rtransaction_id, - bool full_refund, - const struct TALER_Amount *amount_with_fee) -{ - (void) cls; - (void) rowid; - (void) denom_pub; - (void) coin_pub; - (void) charity_pub; - (void) charity_sig; - (void) h_contract_terms; - (void) rtransaction_id; - (void) amount_with_fee; - (void) full_refund; - auditor_row_cnt++; - return GNUNET_OK; -} - - -/** - * Function called with details about incoming wire transfers. - * - * @param cls closure - * @param rowid unique serial ID for the refresh session in our DB - * @param reserve_pub public key of the reserve (also the WTID) - * @param credit amount that was received - * @param sender_account_details information about the sender's bank account - * @param wire_reference unique reference identifying the wire transfer - * @param execution_date when did we receive the funds - * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop - */ -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_Timestamp execution_date) -{ - (void) cls; - (void) rowid; - (void) reserve_pub; - (void) credit; - (void) sender_account_details; - (void) wire_reference; - (void) execution_date; - auditor_row_cnt++; - return GNUNET_OK; -} - - -/** - * Function called with details about withdraw operations. - * - * @param cls closure - * @param rowid unique serial ID for the refresh session in our DB - * @param h_blind_ev blinded hash of the coin's public key - * @param denom_pub public denomination key of the deposited coin - * @param reserve_pub public key of the reserve - * @param reserve_sig signature over the withdraw operation - * @param execution_date when did the wallet withdraw the coin - * @param amount_with_fee amount that was withdrawn - * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop - */ -static enum GNUNET_GenericReturnValue -audit_reserve_out_cb (void *cls, - uint64_t rowid, - 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_Timestamp execution_date, - const struct TALER_Amount *amount_with_fee) -{ - (void) cls; - (void) rowid; - (void) h_blind_ev; - (void) denom_pub; - (void) reserve_pub; - (void) reserve_sig; - (void) execution_date; - (void) amount_with_fee; - auditor_row_cnt++; - return GNUNET_OK; -} - - -/** - * Test garbage collection. - * - * @return #GNUNET_OK on success - */ -static enum GNUNET_GenericReturnValue -test_gc (void) -{ - struct DenomKeyPair *dkp; - struct GNUNET_TIME_Timestamp now; - struct GNUNET_TIME_Timestamp past; - struct DONAUDB_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, - &fees); - GNUNET_assert (NULL != dkp); - if (GNUNET_OK != - plugin->gc (plugin->cls)) - { - GNUNET_break (0); - destroy_denom_key_pair (dkp); - return GNUNET_SYSERR; - } - TALER_denom_pub_hash (&dkp->pub, - &denom_hash); - - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->get_denomination_info (plugin->cls, - &denom_hash, - &issue2)) - { - GNUNET_break (0); - destroy_denom_key_pair (dkp); - return GNUNET_SYSERR; - } - destroy_denom_key_pair (dkp); - return GNUNET_OK; -} - - -/** - * Test wire fee storage. - * - * @return #GNUNET_OK on success - */ -static enum GNUNET_GenericReturnValue -test_wire_fees (void) -{ - struct GNUNET_TIME_Timestamp start_date; - struct GNUNET_TIME_Timestamp end_date; - struct TALER_WireFeeSet fees; - struct TALER_MasterSignatureP master_sig; - struct GNUNET_TIME_Timestamp sd; - struct GNUNET_TIME_Timestamp ed; - struct TALER_WireFeeSet fees2; - struct TALER_MasterSignatureP ms; - - 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", - &fees.wire)); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount (CURRENCY ":2.424242", - &fees.closing)); - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, - &master_sig, - sizeof (master_sig)); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->insert_wire_fee (plugin->cls, - "wire-method", - start_date, - end_date, - &fees, - &master_sig)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->insert_wire_fee (plugin->cls, - "wire-method", - start_date, - end_date, - &fees, - &master_sig)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - /* This must fail as 'end_date' is NOT in the - half-open interval [start_date,end_date) */ - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->get_wire_fee (plugin->cls, - "wire-method", - end_date, - &sd, - &ed, - &fees2, - &ms)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->get_wire_fee (plugin->cls, - "wire-method", - start_date, - &sd, - &ed, - &fees2, - &ms)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - 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)) ) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -static struct TALER_Amount wire_out_amount; - - -/** - * Callback with data about an executed wire transfer. - * - * @param cls closure - * @param rowid identifier of the respective row in the database - * @param date timestamp of the wire transfer (roughly) - * @param wtid wire transfer subject - * @param wire wire transfer details of the receiver - * @param amount amount that was wired - * @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration - */ -static enum GNUNET_GenericReturnValue -audit_wire_cb (void *cls, - uint64_t rowid, - struct GNUNET_TIME_Timestamp date, - const struct TALER_WireTransferIdentifierRawP *wtid, - 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, - &wire_out_amount)); - GNUNET_assert (0 == - GNUNET_memcmp (wtid, - &wire_out_wtid)); - GNUNET_assert (GNUNET_TIME_timestamp_cmp (date, - ==, - wire_out_date)); - return GNUNET_OK; -} - - -/** - * Test API relating to wire_out handling. - * - * @param bd batch deposit to test - * @return #GNUNET_OK on success - */ -static enum GNUNET_GenericReturnValue -test_wire_out (const struct DONAUDB_BatchDeposit *bd) -{ - const struct DONAUDB_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, - 41, - sizeof (wire_out_wtid)); - wire_out_date = GNUNET_TIME_timestamp_get (); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount (CURRENCY ":1", - &wire_out_amount)); - - /* we will transiently violate the wtid constraint on - the aggregation table, so we need to start the special - transaction where this is allowed... */ - FAILIF (GNUNET_OK != - plugin->start_deferred_wire_out (plugin->cls)); - - /* setup values for wire transfer aggregation data */ - charity_pub_wt = bd->charity_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 = fees.deposit; - GNUNET_assert (0 < - TALER_amount_subtract (&transfer_value_wt, - &coin_value_wt, - &coin_fee_wt)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->lookup_wire_transfer (plugin->cls, - &wire_out_wtid, - &cb_wt_never, - NULL)); - - { - 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 DONAUDB_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, - &charity_pub_wt, - &pending, - &wtid2, - &execution_time2, - &coin_contribution2, - &coin_fee2, - &kyc, - &aml)); - } - { - 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 != - plugin->commit (plugin->cls)); - - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->lookup_wire_transfer (plugin->cls, - &wire_out_wtid, - &cb_wt_check, - &cb_wt_never)); - { - bool pending; - struct TALER_WireTransferIdentifierRawP wtid2; - struct TALER_Amount coin_contribution2; - struct TALER_Amount coin_fee2; - struct GNUNET_TIME_Timestamp execution_time2; - struct DONAUDB_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, - &charity_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, - &audit_wire_cb, - NULL)); - FAILIF (1 != auditor_row_cnt); - - return GNUNET_OK; -drop: - return GNUNET_SYSERR; -} - - -/** - * Function called about recoups the donau has to perform. - * - * @param cls closure with the expected value for @a coin_blind - * @param rowid row identifier used to uniquely identify the recoup operation - * @param timestamp when did we receive the recoup request - * @param amount how much should be added back to the reserve - * @param reserve_pub public key of the reserve - * @param coin public information about the coin - * @param denom_pub denomination key of @a coin - * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_RECOUP - * @param coin_blind blinding factor used to blind the coin - * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop - */ -static enum GNUNET_GenericReturnValue -recoup_cb (void *cls, - uint64_t rowid, - 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 union TALER_DenominationBlindingKeyP *coin_blind) -{ - const union TALER_DenominationBlindingKeyP *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)); - return GNUNET_OK; -drop: - return GNUNET_SYSERR; -} - - -/** - * Function called on deposits that are past their due date - * and have not yet seen a wire transfer. - * - * @param cls closure a `struct DONAUDB_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 payto_uri where should the funds be wired - * @param deadline what was the requested wire transfer deadline - * @param done did the donau claim that it made a transfer? - */ -static void -wire_missing_cb (void *cls, - uint64_t rowid, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount, - const char *payto_uri, - struct GNUNET_TIME_Timestamp deadline, - bool done) -{ - const struct DONAUDB_CoinDepositInformation *deposit = cls; - - (void) payto_uri; - (void) deadline; - (void) rowid; - if (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; - } -} - - -/** - * Callback invoked with information about refunds applicable - * to a particular coin. - * - * @param cls closure with the `struct DONAUDB_Refund *` we expect to get - * @param amount_with_fee amount being refunded - * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop - */ -static enum GNUNET_GenericReturnValue -check_refund_cb (void *cls, - const struct TALER_Amount *amount_with_fee) -{ - const struct DONAUDB_Refund *refund = cls; - - if (0 != TALER_amount_cmp (amount_with_fee, - &refund->details.refund_amount)) - { - GNUNET_break (0); - result = 66; - } - return GNUNET_OK; -} - - -/** - * Main function that will be run by the scheduler. - * - * @param cls closure with config - */ -static void -run (void *cls) -{ - struct GNUNET_CONFIGURATION_Handle *cfg = cls; - struct TALER_CoinSpendSignatureP coin_sig; - struct GNUNET_TIME_Timestamp deadline; - union TALER_DenominationBlindingKeyP coin_blind; - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_ReservePublicKeyP reserve_pub2; - struct TALER_ReservePublicKeyP reserve_pub3; - struct DenomKeyPair *dkp = NULL; - struct TALER_MasterSignatureP master_sig; - struct DONAUDB_CollectableBlindcoin cbc; - struct DONAUDB_CollectableBlindcoin cbc2; - struct DONAUDB_ReserveHistory *rh = NULL; - struct DONAUDB_ReserveHistory *rh_head; - struct DONAUDB_BankTransfer *bt; - struct DONAUDB_CollectableBlindcoin *withdraw; - struct DONAUDB_CoinDepositInformation deposit; - struct DONAUDB_BatchDeposit bd; - struct TALER_CoinSpendPublicKeyP cpub2; - struct DONAU_CharityPublicKeyP mpub2; - struct DONAUDB_Refund refund; - struct DONAUDB_TransactionList *tl; - struct DONAUDB_TransactionList *tlp; - 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; - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Timestamp now; - struct TALER_WireSaltP salt; - struct TALER_CoinPubHashP c_hash; - uint64_t known_coin_id; - uint64_t rrc_serial; - struct DONAUDB_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 TALER_DenominationBlindingKeyP bks; - struct TALER_DonauWithdrawValues alg_values = { - /* RSA is simpler, and for the DB there is no real difference between - CS and RSA, just one should be used, so we use RSA */ - .cipher = TALER_DENOMINATION_RSA - }; - - 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 == - (plugin = DONAUDB_plugin_load (cfg))) - { - result = 77; - return; - } - (void) plugin->drop_tables (plugin->cls); - if (GNUNET_OK != - plugin->create_tables (plugin->cls, - true, - num_partitions)) - { - result = 77; - goto cleanup; - } - plugin->preflight (plugin->cls); - FAILIF (GNUNET_OK != - plugin->start (plugin->cls, - "test-1")); - - /* test DB is empty */ - FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != - plugin->select_recoup_above_serial_id (plugin->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", - &fees.withdraw)); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount (CURRENCY ":0.000010", - &fees.deposit)); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount (CURRENCY ":0.000010", - &fees.refresh)); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount (CURRENCY ":0.000010", - &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->commit (plugin->cls)); - now = GNUNET_TIME_timestamp_get (); - { - struct DONAUDB_ReserveInInfo reserve = { - .reserve_pub = &reserve_pub, - .balance = &value, - .execution_time = now, - .sender_account_details = sndr, - .donau_account_name = "donau-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_timestamp_get (); - RND_BLK (&reserve_pub2); - { - struct DONAUDB_ReserveInInfo reserve = { - .reserve_pub = &reserve_pub2, - .balance = &value, - .execution_time = now, - .sender_account_details = sndr, - .donau_account_name = "donau-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, - value.fraction, - value.currency)); - FAILIF (GNUNET_OK != - check_reserve (&reserve_pub2, - value.value, - value.fraction, - value.currency)); - result = 5; - now = GNUNET_TIME_timestamp_get (); - dkp = create_denom_key_pair (RSA_KEY_SIZE, - now, - &value, - &fees); - GNUNET_assert (NULL != dkp); - TALER_denom_pub_hash (&dkp->pub, - &cbc.denom_pub_hash); - RND_BLK (&cbc.reserve_sig); - 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, - p_ah[i], - &coin_pub, - &alg_values, - &c_hash, - &pd.blinded_planchet)); - GNUNET_assert (GNUNET_OK == - 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)); - - { - bool found; - bool nonce_ok; - bool balance_ok; - bool age_ok; - uint16_t maximum_age; - uint64_t ruuid; - - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->do_withdraw (plugin->cls, - NULL, - &cbc, - now, - false, - &found, - &balance_ok, - &nonce_ok, - &age_ok, - &maximum_age, - &ruuid)); - GNUNET_assert (found); - GNUNET_assert (nonce_ok); - 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_pub3, - &reserve_out_serial_id)); - FAILIF (0 != GNUNET_memcmp (&reserve_pub, - &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)); - result = 6; - - { - 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); - 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 (DONAUDB_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.charity_pub = bd.charity_pub; - RND_BLK (&refund.details.charity_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.charity_sig); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->do_refund (plugin->cls, - &refund, - &fees.deposit, - known_coin_id, - &not_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.charity_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 DONAUDB_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 DONAUDB_RefreshRevealedCoin); - for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) - { - struct DONAUDB_RefreshRevealedCoin *ccoin; - struct GNUNET_TIME_Timestamp now; - struct TALER_BlindedRsaPlanchet *rp; - 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; - bp->cipher = TALER_DENOMINATION_RSA; - rp = &bp->details.rsa_blinded_planchet; - rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 ( - GNUNET_CRYPTO_QUALITY_WEAK, - (RSA_KEY_SIZE / 8) - 1); - rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size); - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, - rp->blinded_msg, - rp->blinded_msg_size); - TALER_denom_pub_hash (&new_dkp[cnt]->pub, - &ccoin->h_denom_pub); - ccoin->donau_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 DONAUDB_TransactionList *tl; - enum GNUNET_DB_QueryStatus qs; - - qs = plugin->get_coin_transactions (plugin->cls, - &refresh.coin.coin_pub, - &tl); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs); - plugin->free_coin_transaction_list (plugin->cls, - tl); - } - } - - /* do recoup-refresh */ - { - struct GNUNET_TIME_Timestamp recoup_timestamp - = GNUNET_TIME_timestamp_get (); - union TALER_DenominationBlindingKeyP 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 (DONAUDB_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 DONAUDB_Reserve pre_reserve; - struct DONAUDB_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->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, - &post_reserve)); - FAILIF (0 >= - TALER_amount_subtract (&delta, - &post_reserve.balance, - &pre_reserve.balance)); - FAILIF (0 != - 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)); - /* Do reserve close */ - now = GNUNET_TIME_timestamp_get (); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount (CURRENCY ":0.000010", - &fee_closing)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->insert_reserve_closed (plugin->cls, - &reserve_pub2, - now, - sndr, - &wire_out_wtid, - &amount_with_fee, - &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; - - /* check reserve history */ - { - struct TALER_Amount balance; - - qs = plugin->get_reserve_history (plugin->cls, - &reserve_pub, - &balance, - &rh); - } - FAILIF (0 > qs); - FAILIF (NULL == rh); - rh_head = rh; - for (cnt = 0; NULL != rh_head; rh_head = rh_head->next, cnt++) - { - switch (rh_head->type) - { - case DONAUDB_RO_BANK_TO_DONAU: - bt = rh_head->details.bank; - 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); - FAILIF (0 != strcmp (CURRENCY, bt->amount.currency)); - FAILIF (NULL == bt->sender_account_details); - break; - case DONAUDB_RO_WITHDRAW_COIN: - withdraw = rh_head->details.withdraw; - FAILIF (0 != - GNUNET_memcmp (&withdraw->reserve_pub, - &reserve_pub)); - FAILIF (0 != - GNUNET_memcmp (&withdraw->h_coin_envelope, - &cbc.h_coin_envelope)); - break; - case DONAUDB_RO_RECOUP_COIN: - { - struct DONAUDB_Recoup *recoup = rh_head->details.recoup; - - 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 DONAUDB_RO_DONAU_TO_BANK: - { - struct DONAUDB_ClosingTransfer *closing - = rh_head->details.closing; - - 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 DONAUDB_RO_PURSE_MERGE: - { - /* FIXME: not yet tested */ - break; - } - case DONAUDB_RO_HISTORY_REQUEST: - { - /* FIXME: not yet tested */ - break; - } - case DONAUDB_RO_OPEN_REQUEST: - { - /* FIXME: not yet tested */ - break; - } - case DONAUDB_RO_CLOSE_REQUEST: - { - /* FIXME: not yet tested */ - break; - } - } - } - GNUNET_assert (4 == cnt); - FAILIF (4 != cnt); - - auditor_row_cnt = 0; - FAILIF (0 >= - plugin->select_reserves_in_above_serial_id (plugin->cls, - 0, - &audit_reserve_in_cb, - NULL)); - FAILIF (0 >= - plugin->select_withdrawals_above_serial_id (plugin->cls, - 0, - &audit_reserve_out_cb, - NULL)); - FAILIF (3 != auditor_row_cnt); - - - auditor_row_cnt = 0; - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->select_refunds_above_serial_id (plugin->cls, - 0, - &audit_refund_cb, - NULL)); - FAILIF (1 != auditor_row_cnt); - qs = plugin->get_coin_transactions (plugin->cls, - &refund.coin.coin_pub, - &tl); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs); - GNUNET_assert (NULL != tl); - matched = 0; - for (tlp = tl; NULL != tlp; tlp = tlp->next) - { - switch (tlp->type) - { - case DONAUDB_TT_DEPOSIT: - { - struct DONAUDB_DepositListEntry *have = tlp->details.deposit; - - /* 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 != - GNUNET_memcmp (&have->csig, - &deposit.csig)); - FAILIF (0 != - GNUNET_memcmp (&have->charity_pub, - &bd.charity_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)); - matched |= 1; - break; - } - /* this coin pub was actually never melted... */ - case DONAUDB_TT_MELT: - FAILIF (0 != - GNUNET_memcmp (&refresh.rc, - &tlp->details.melt->rc)); - matched |= 2; - break; - case DONAUDB_TT_REFUND: - { - struct DONAUDB_RefundListEntry *have = tlp->details.refund; - - /* 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 != GNUNET_memcmp (&have->charity_pub, - &refund.details.charity_pub)); - FAILIF (0 != GNUNET_memcmp (&have->charity_sig, - &refund.details.charity_sig)); - FAILIF (0 != GNUNET_memcmp (&have->h_contract_terms, - &refund.details.h_contract_terms)); - FAILIF (have->rtransaction_id != refund.details.rtransaction_id); - FAILIF (0 != TALER_amount_cmp (&have->refund_amount, - &refund.details.refund_amount)); - FAILIF (0 != TALER_amount_cmp (&have->refund_fee, - &refund.details.refund_fee)); - matched |= 4; - break; - } - case DONAUDB_TT_RECOUP: - { - struct DONAUDB_RecoupListEntry *recoup = - tlp->details.recoup; - - 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 != TALER_amount_cmp (&recoup->value, - &value)); - matched |= 8; - break; - } - case DONAUDB_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 (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.charity_pub); - RND_BLK (&bd.h_contract_terms); - RND_BLK (&bd.wire_salt); - bd.receiver_wire_account = - "payto://iban/DE67830654080004822650?receiver-name=Test"; - TALER_charity_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; - { - uint64_t known_coin_id; - struct TALER_DenominationHashP dph; - struct TALER_AgeCommitmentHash agh; - - FAILIF (DONAUDB_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_CharityWireHashP 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_charity_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.charity_pub, - bd.refund_deadline, - &deposit_fee, - &r)); - FAILIF (GNUNET_TIME_timestamp_cmp (now, - !=, - r)); - } - { - struct GNUNET_TIME_Timestamp start_range; - struct GNUNET_TIME_Timestamp end_range; - - start_range = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_subtract (deadline.abs_time, - GNUNET_TIME_UNIT_SECONDS)); - end_range = GNUNET_TIME_absolute_to_timestamp ( - GNUNET_TIME_absolute_add (deadline.abs_time, - GNUNET_TIME_UNIT_SECONDS)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->select_batch_deposits_missing_wire (plugin->cls, - start_range, - end_range, - &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 DONAU_CharityPublicKeyP charity_pub2; - char *payto_uri2; - - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->get_ready_deposit (plugin->cls, - 0, - INT32_MAX, - &charity_pub2, - &payto_uri2)); - FAILIF (0 != GNUNET_memcmp (&charity_pub2, - &bd.charity_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.charity_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.charity_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.charity_pub, - &wtid, - 0, - &total)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->select_aggregation_transient (plugin->cls, - &wire_target_h_payto, - &bd.charity_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.charity_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.charity_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 charity is different */ - { - struct TALER_CharityWireHashP h_wire; - struct GNUNET_TIME_Timestamp r; - struct TALER_Amount deposit_fee; - - TALER_charity_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.charity_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 (&bd)); - FAILIF (GNUNET_OK != - test_gc ()); - FAILIF (GNUNET_OK != - test_wire_fees ()); - - plugin->preflight (plugin->cls); - - result = 0; - -drop: - if (0 != result) - plugin->rollback (plugin->cls); - if (NULL != rh) - plugin->free_reserve_history (plugin->cls, - rh); - rh = NULL; - GNUNET_break (GNUNET_OK == - plugin->drop_tables (plugin->cls)); -cleanup: - if (NULL != dkp) - destroy_denom_key_pair (dkp); - 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; - DONAUDB_plugin_unload (plugin); - plugin = NULL; -} - - int main (int argc, char *const argv[]) diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c @@ -121,4 +121,5 @@ TALER_PQ_query_param_donation_unit_pub ( return res; } + /* end of pq/pq_query_helper.c */ diff --git a/src/testing/donau-unified-setup.sh b/src/testing/donau-unified-setup.sh @@ -0,0 +1,822 @@ +#!/bin/bash +# +# This file is part of TALER +# Copyright (C) 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 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, see +# <http://www.gnu.org/licenses/> +# +# Author: Christian Grothoff +# +# This script configures and launches various GNU Taler services. +# Which ones depend on command-line options. Use "-h" to find out. +# Prints "<<READY>>" on a separate line once all requested services +# are running. Close STDIN (or input 'NEWLINE') to stop all started +# services again. +# +# shellcheck disable=SC2317 + +set -eu + +EXIT_STATUS=2 + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: " "$@" >&2 + EXIT_STATUS=77 + exit "$EXIT_STATUS" +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " FAIL: " "$@" >&2 + EXIT_STATUS=1 + exit "$EXIT_STATUS" +} + +# Cleanup to run whenever we exit +function cleanup() +{ + echo "Taler unified setup terminating!" >&2 + + for n in $(jobs -p) + do + kill "$n" 2> /dev/null || true + done + wait + rm -f libeufin-nexus.pid libeufin-sandbox.pid + exit "$EXIT_STATUS" +} + +# Install cleanup handler (except for kill -9) +trap cleanup EXIT + +WAIT_FOR_SIGNAL=0 +START_AUDITOR=0 +START_BACKUP=0 +START_EXCHANGE=0 +START_FAKEBANK=0 +START_DONAU=0 +START_CHALLENGER=0 +START_AGGREGATOR=0 +START_MERCHANT=0 +START_NEXUS=0 +START_BANK=0 +START_TRANSFER=0 +START_WIREWATCH=0 +USE_ACCOUNT="exchange-account-1" +USE_VALGRIND="" +WIRE_DOMAIN="x-taler-bank" +CONF_ORIG="$HOME/.config/taler.conf" +LOGLEVEL="DEBUG" +DEFAULT_SLEEP="0.2" + +# Parse command-line options +while getopts ':abc:d:efghkL:mnr:stu:vwW' OPTION; do + case "$OPTION" in + a) + START_AUDITOR="1" + ;; + b) + START_BANK="1" + ;; + c) + CONF_ORIG="$OPTARG" + ;; + d) + WIRE_DOMAIN="$OPTARG" + ;; + e) + START_EXCHANGE="1" + ;; + f) + START_FAKEBANK="1" + ;; + h) + echo 'Supported options:' + echo ' -a -- start auditor' + echo ' -b -- start bank' + # shellcheck disable=SC2016 + echo ' -c $CONF -- set configuration' + # shellcheck disable=SC2016 + echo ' -d $METHOD -- use wire method (default: x-taler-bank)' + echo ' -e -- start exchange' + echo ' -f -- start fakebank' + echo ' -g -- start aggregator' + echo ' -h -- print this help' + # shellcheck disable=SC2016 + echo ' -L $LOGLEVEL -- set log level' + echo ' -m -- start merchant' + echo ' -n -- start nexus' + echo ' -o -- start donau' + # shellcheck disable=SC2016 + echo ' -r $MEX -- which exchange to use at the merchant (optional)' + echo ' -s -- start backup/sync' + echo ' -t -- start transfer' + # shellcheck disable=SC2016 + echo ' -u $SECTION -- exchange account to use' + echo ' -v -- use valgrind' + echo ' -w -- start wirewatch' + exit 0 + ;; + g) + START_AGGREGATOR="1" + ;; + k) + START_CHALLENGER="1" + ;; + L) + LOGLEVEL="$OPTARG" + ;; + m) + START_MERCHANT="1" + ;; + n) + START_NEXUS="1" + ;; + o) + START_DONAU="1" + ;; + r) + USE_MERCHANT_EXCHANGE="$OPTARG" + ;; + s) + START_BACKUP="1" + ;; + t) + START_TRANSFER="1" + ;; + u) + USE_ACCOUNT="$OPTARG" + ;; + v) + USE_VALGRIND="valgrind --leak-check=yes" + DEFAULT_SLEEP="2" + ;; + w) + START_WIREWATCH="1" + ;; + W) + WAIT_FOR_SIGNAL="1" + ;; + ?) + exit_fail "Unrecognized command line option" + ;; + esac +done + +echo "Starting with configuration file at: $CONF_ORIG" +CONF="$CONF_ORIG.edited" +cp "${CONF_ORIG}" "${CONF}" + +echo -n "Testing for jq" +jq -h > /dev/null || exit_skip " jq required" +echo " FOUND" + +if [ "1" = "$START_EXCHANGE" ] +then + echo -n "Testing for Taler exchange" + taler-exchange-httpd -h > /dev/null || exit_skip " taler-exchange-httpd required" + echo " FOUND" +fi + +if [ "1" = "$START_DONAU" ] +then + echo -n "Testing for Taler donau" + taler-donau-httpd -h > /dev/null || exit_skip " taler-donau-httpd required" + echo " FOUND" +fi + +if [ "1" = "$START_MERCHANT" ] +then + echo -n "Testing for Taler merchant" + taler-merchant-httpd -h > /dev/null || exit_skip " taler-merchant-httpd required" + echo " FOUND" +fi + +if [ "1" = "$START_CHALLENGER" ] +then + echo -n "Testing for Taler challenger" + challenger-httpd -h > /dev/null || exit_skip " challenger-httpd required" + echo " FOUND" +fi + +if [ "1" = "$START_BACKUP" ] +then + echo -n "Testing for sync-httpd" + sync-httpd -h > /dev/null || exit_skip " sync-httpd required" + echo " FOUND" +fi + +if [ "1" = "$START_NEXUS" ] +then + echo -n "Testing for libeufin-cli" + libeufin-cli --help >/dev/null </dev/null || exit_skip " MISSING" + echo " FOUND" +fi + +EXCHANGE_URL=$(taler-config -c "$CONF" -s "EXCHANGE" -o "BASE_URL") +CURRENCY=$(taler-config -c "$CONF" -s "TALER" -o "CURRENCY") + +echo "Setting up for $CURRENCY at $EXCHANGE_URL" + +register_bank_account() { + wget \ + --http-user="$AUSER" \ + --http-password="$APASS" \ + --method=DELETE \ + -o /dev/null \ + -O /dev/null \ + -a wget-delete-account.log \ + "http://localhost:${BANK_PORT}/accounts/$1" \ + || true # deletion may fail, that's OK! + if [ "$1" = "exchange" ] || [ "$1" = "Exchange" ] + then + IS_EXCHANGE="true" + else + IS_EXCHANGE="false" + fi + MAYBE_IBAN="${4:-}" + if test -n "$MAYBE_IBAN"; + then + # shellcheck disable=SC2001 + ENAME=$(echo "$3" | sed -e "s/ /+/g") + # Note: this assumes that $3 has no spaces. Should probably escape in the future.. + PAYTO="payto://iban/SANDBOXX/${MAYBE_IBAN}?receiver-name=$ENAME" + BODY='{"username":"'"$1"'","password":"'"$2"'","is_taler_exchange":'"$IS_EXCHANGE"',"name":"'"$3"'","internal_payto_uri":"'"$PAYTO"'"}' + else + BODY='{"username":"'"$1"'","password":"'"$2"'","is_taler_exchange":'"$IS_EXCHANGE"',"name":"'"$3"'"}' + fi + wget \ + --http-user="$AUSER" \ + --http-password="$APASS" \ + --method=POST \ + --header='Content-type: application/json' \ + --body-data="${BODY}" \ + --content-on-error \ + -a wget-register-account.log \ + -o /dev/null \ + -O /dev/null \ + "http://localhost:${BANK_PORT}/accounts" +} + +register_fakebank_account() { + if [ "$1" = "exchange" ] || [ "$1" = "Exchange" ] + then + IS_EXCHANGE="true" + else + IS_EXCHANGE="false" + fi + BODY='{"username":"'"$1"'","password":"'"$2"'","name":"'"$1"'","is_taler_exchange":'"$IS_EXCHANGE"'}' + wget \ + --post-data="$BODY" \ + --header='Content-type: application/json' \ + --tries=3 \ + --waitretry=1 \ + --timeout=30 \ + "http://localhost:$BANK_PORT/accounts" \ + -a wget-register-account.log \ + -o /dev/null \ + -O /dev/null \ + >/dev/null +} + + +if [[ "1" = "$START_BANK" || "1" = "$START_FAKEBANK" ]] +then + BANK_PORT=$(taler-config -c "$CONF" -s "BANK" -o "HTTP_PORT") + BANK_URL="http://localhost:${BANK_PORT}/" +fi + +if [ "1" = "$START_BANK" ] +then + echo -n "Setting up bank database ... " + libeufin-bank dbinit \ + -r \ + -c "$CONF" \ + &> libeufin-bank-reset.log + echo "DONE" + echo -n "Launching bank ... " + libeufin-bank serve \ + -c "$CONF" \ + > libeufin-bank-stdout.log \ + 2> libeufin-bank-stderr.log & + echo $! > libeufin-bank.pid + echo "DONE" + echo -n "Waiting for Bank ..." + OK="0" + for n in $(seq 1 100); do + echo -n "." + sleep "$DEFAULT_SLEEP" + wget --timeout=1 \ + --tries=3 \ + --waitretry=0 \ + -o /dev/null \ + -O /dev/null \ + "$BANK_URL/config" || continue + OK="1" + break + done + if [ "1" != "$OK" ] + then + exit_skip "Failed to launch services (bank)" + fi + echo "OK" + echo -n "Set admin password..." + AUSER="admin" + APASS="secret" + libeufin-bank \ + passwd \ + -c "$CONF" \ + "$AUSER" "$APASS" \ + &> libeufin-bank-passwd.log + libeufin-bank \ + edit-account \ + -c "$CONF" \ + --debit_threshold="$CURRENCY:1000000" \ + "$AUSER" \ + &> libeufin-bank-debit-threshold.log + echo " OK" +fi + +if [ "1" = "$START_NEXUS" ] +then + echo "Nexus currently not supported ..." +fi + +if [ "1" = "$START_FAKEBANK" ] +then + echo -n "Setting up fakebank ..." + $USE_VALGRIND taler-fakebank-run \ + -c "$CONF" \ + -L "$LOGLEVEL" \ + -n 4 \ + 2> taler-fakebank-run.log & + echo " OK" +fi + +if [[ "1" = "$START_NEXUS" || "1" = "$START_FAKEBANK" ]] +then + echo -n "Waiting for the bank" + # Wait for bank to be available (usually the slowest) + OK="0" + for n in $(seq 1 300) + do + echo -n "." + sleep "$DEFAULT_SLEEP" + # bank + wget --tries=1 \ + --waitretry=0 \ + --timeout=1 \ + --user admin \ + --password secret \ + "http://localhost:${BANK_PORT}/" \ + -o /dev/null \ + -O /dev/null >/dev/null || continue + OK="1" + break + done + if [ "1" != "$OK" ] + then + exit_skip "Failed to launch services (bank)" + fi + echo " OK" +fi + +if [ "1" = "$START_FAKEBANK" ] +then + echo -n "Register Fakebank users ..." + register_fakebank_account fortytwo x + register_fakebank_account fortythree x + register_fakebank_account exchange x + register_fakebank_account tor x + register_fakebank_account gnunet x + register_fakebank_account tutorial x + register_fakebank_account survey x + echo " DONE" +fi + +if [ "1" = "$START_BANK" ] +then + echo -n "Register bank users ..." + # The specified IBAN and name must match the ones hard-coded into + # the C helper for the add-incoming call. Without this value, + # libeufin-bank won't find the target account to debit along a /add-incoming + # call. + register_bank_account fortytwo x "User42" FR7630006000011234567890189 + register_bank_account fortythree x "Forty Three" + register_bank_account exchange x "Exchange Company" DE989651 + register_bank_account tor x "Tor Project" + register_bank_account gnunet x "GNUnet" + register_bank_account tutorial x "Tutorial" + register_bank_account survey x "Survey" + echo " DONE" +fi + +if [ "1" = "$START_EXCHANGE" ] +then + echo -n "Starting exchange ..." + EXCHANGE_PORT=$(taler-config -c "$CONF" -s EXCHANGE -o PORT) + SERVE=$(taler-config -c "$CONF" -s EXCHANGE -o SERVE) + if [ "${SERVE}" = "unix" ] + then + EXCHANGE_URL=$(taler-config -c "$CONF" -s EXCHANGE -o BASE_URL) + else + EXCHANGE_URL="http://localhost:${EXCHANGE_PORT}/" + fi + MASTER_PRIV_FILE=$(taler-config -f -c "${CONF}" -s "EXCHANGE-OFFLINE" -o "MASTER_PRIV_FILE") + MASTER_PRIV_DIR=$(dirname "$MASTER_PRIV_FILE") + mkdir -p "${MASTER_PRIV_DIR}" + if [ ! -e "$MASTER_PRIV_FILE" ] + then + gnunet-ecc -g1 "$MASTER_PRIV_FILE" > /dev/null 2> /dev/null + echo -n "." + fi + MASTER_PUB=$(gnunet-ecc -p "${MASTER_PRIV_FILE}") + MPUB=$(taler-config -c "$CONF" -s exchange -o MASTER_PUBLIC_KEY) + if [ "$MPUB" != "$MASTER_PUB" ] + then + echo -n " patching master_pub ($MASTER_PUB)..." + taler-config -c "$CONF" -s exchange -o MASTER_PUBLIC_KEY -V "$MASTER_PUB" + fi + taler-exchange-dbinit -c "$CONF" --reset + $USE_VALGRIND taler-exchange-secmod-eddsa -c "$CONF" -L "$LOGLEVEL" 2> taler-exchange-secmod-eddsa.log & + $USE_VALGRIND taler-exchange-secmod-rsa -c "$CONF" -L "$LOGLEVEL" 2> taler-exchange-secmod-rsa.log & + $USE_VALGRIND taler-exchange-secmod-cs -c "$CONF" -L "$LOGLEVEL" 2> taler-exchange-secmod-cs.log & + $USE_VALGRIND taler-exchange-httpd -c "$CONF" -L "$LOGLEVEL" 2> taler-exchange-httpd.log & + echo " DONE" +fi + +if [ "1" = "$START_DONAU" ] +then + echo -n "Starting donau ..." + DONAU_PORT=$(taler-config -c "$CONF" -s DONAU -o PORT) + SERVE=$(taler-config -c "$CONF" -s DONAU -o SERVE) + if [ "${SERVE}" = "unix" ] + then + DONAU_URL=$(taler-config -c "$CONF" -s DONAU -o BASE_URL) + else + DONAU_URL="http://localhost:${DONAU_PORT}/" + fi + MASTER_PRIV_FILE=$(taler-config -f -c "${CONF}" -s "DONAU-OFFLINE" -o "MASTER_PRIV_FILE") + MASTER_PRIV_DIR=$(dirname "$MASTER_PRIV_FILE") + mkdir -p "${MASTER_PRIV_DIR}" + if [ ! -e "$MASTER_PRIV_FILE" ] + then + gnunet-ecc -g1 "$MASTER_PRIV_FILE" > /dev/null 2> /dev/null + echo -n "." + fi + MASTER_PUB=$(gnunet-ecc -p "${MASTER_PRIV_FILE}") + MPUB=$(taler-config -c "$CONF" -s donau -o MASTER_PUBLIC_KEY) + if [ "$MPUB" != "$MASTER_PUB" ] + then + echo -n " patching master_pub ($MASTER_PUB)..." + taler-config -c "$CONF" -s donau -o MASTER_PUBLIC_KEY -V "$MASTER_PUB" + fi + taler-donau-dbinit -c "$CONF" --reset + $USE_VALGRIND taler-donau-secmod-eddsa -c "$CONF" -L "$LOGLEVEL" 2> taler-donau-secmod-eddsa.log & + $USE_VALGRIND taler-donau-secmod-rsa -c "$CONF" -L "$LOGLEVEL" 2> taler-donau-secmod-rsa.log & + $USE_VALGRIND taler-donau-secmod-cs -c "$CONF" -L "$LOGLEVEL" 2> taler-donau-secmod-cs.log & + $USE_VALGRIND taler-donau-httpd -c "$CONF" -L "$LOGLEVEL" 2> taler-donau-httpd.log & + echo " DONE" +fi + +if [ "1" = "$START_WIREWATCH" ] +then + echo -n "Starting wirewatch ..." + $USE_VALGRIND taler-exchange-wirewatch \ + --account="$USE_ACCOUNT" \ + -c "$CONF" \ + --longpoll-timeout="1 s" \ + 2> taler-exchange-wirewatch.log & + echo " DONE" +fi + +if [ "1" = "$START_AGGREGATOR" ] +then + echo -n "Starting aggregator ..." + $USE_VALGRIND taler-exchange-aggregator -c "$CONF" 2> taler-exchange-aggregator.log & + echo " DONE" +fi + +if [ "1" = "$START_TRANSFER" ] +then + echo -n "Starting transfer ..." + $USE_VALGRIND taler-exchange-transfer -c "$CONF" 2> taler-exchange-transfer.log & + echo " DONE" +fi + +if [ "1" = "$START_MERCHANT" ] +then + echo -n "Starting merchant ..." + if [ -n "${USE_MERCHANT_EXCHANGE+x}" ] + then + MEPUB=$(taler-config -c "$CONF" -s "${USE_MERCHANT_EXCHANGE}" -o MASTER_KEY) + MXPUB=${MASTER_PUB:-$(taler-config -c "$CONF" -s exchange -o MASTER_PUBLIC_KEY)} + if [ "$MEPUB" != "$MXPUB" ] + then + echo -n " patching master_pub ($MXPUB)..." + taler-config -c "$CONF" -s "${USE_MERCHANT_EXCHANGE}" -o MASTER_KEY -V "$MXPUB" + fi + fi + MERCHANT_TYPE=$(taler-config -c "$CONF" -s MERCHANT -o SERVE) + if [ "unix" = "$MERCHANT_TYPE" ] + then + MERCHANT_URL="$(taler-config -c "$CONF" -s MERCHANT -o BASE_URL)" + else + MERCHANT_PORT="$(taler-config -c "$CONF" -s MERCHANT -o PORT)" + MERCHANT_URL="http://localhost:${MERCHANT_PORT}/" + fi + taler-merchant-dbinit -c "$CONF" -L "$LOGLEVEL" --reset &> taler-merchant-dbinit.log + $USE_VALGRIND taler-merchant-httpd -c "$CONF" -L "$LOGLEVEL" 2> taler-merchant-httpd.log & + $USE_VALGRIND taler-merchant-webhook -c "$CONF" -L "$LOGLEVEL" 2> taler-merchant-webhook.log & + echo " DONE" +fi + +if [ "1" = "$START_BACKUP" ] +then + echo -n "Starting sync ..." + SYNC_PORT=$(taler-config -c "$CONF" -s SYNC -o PORT) + SERVE=$(taler-config -c "$CONF" -s SYNC -o SERVE) + if [ "${SERVE}" = "unix" ] + then + SYNC_URL=$(taler-config -c "$CONF" -s SYNC -o BASE_URL) + else + SYNC_URL="http://localhost:${SYNC_PORT}/" + fi + sync-dbinit -c "$CONF" --reset + $USE_VALGRIND sync-httpd -c "$CONF" -L "$LOGLEVEL" 2> sync-httpd.log & + echo " DONE" +fi + +if [ "1" = "$START_CHALLENGER" ] +then + echo -n "Starting challenger ..." + CHALLENGER_PORT=$(challenger-config -c "$CONF" -s CHALLENGER -o PORT) + SERVE=$(taler-config -c "$CONF" -s CHALLENGER -o SERVE) + if [ "${SERVE}" = "unix" ] + then + CHALLENGER_URL=$(taler-config -c "$CONF" -s CHALLENGER -o BASE_URL) + else + CHALLENGER_URL="http://localhost:${CHALLENGER_PORT}/" + fi + challenger-dbinit -c "$CONF" --reset + $USE_VALGRIND challenger-httpd -c "$CONF" -L "$LOGLEVEL" 2> challenger-httpd.log & + echo " DONE" + for SECTION in $(taler-config -c "$CONF" -S | grep kyc-provider) + do + LOGIC=$(taler-config -c "$CONF" -s "$SECTION" -o "LOGIC") + if [ "${LOGIC}" = "oauth2" ] + then + INFO=$(taler-config -c "$CONF" -s "$SECTION" -o "KYC_OAUTH2_INFO_URL") + if [ "${CHALLENGER_URL}info" = "$INFO" ] + then + echo -n "Enabling Challenger client for $SECTION" + CLIENT_SECRET=$(taler-config -c "$CONF" -s "$SECTION" -o "KYC_OAUTH2_CLIENT_SECRET") + RFC_8959_PREFIX="secret-token:" + if ! echo "${CLIENT_SECRET}" | grep ^${RFC_8959_PREFIX} > /dev/null + then + exit_fail "Client secret does not begin with '${RFC_8959_PREFIX}'" + fi + REDIRECT_URI="${EXCHANGE_URL}kyc-proof/kyc-provider-example-challeger" + CLIENT_ID=$(challenger-admin --add="${CLIENT_SECRET}" --quiet "${REDIRECT_URI}") + taler-config -c "$CONF" -s "$SECTION" -o KYC_OAUTH2_CLIENT_ID -V "$CLIENT_ID" + echo " DONE" + fi + fi + done +fi + + +if [ "1" = "$START_AUDITOR" ] +then + echo -n "Starting auditor ..." + AUDITOR_URL=$(taler-config -c "$CONF" -s AUDITOR -o BASE_URL) + AUDITOR_PRIV_FILE=$(taler-config -f -c "$CONF" -s AUDITOR -o AUDITOR_PRIV_FILE) + AUDITOR_PRIV_DIR=$(dirname "$AUDITOR_PRIV_FILE") + mkdir -p "$AUDITOR_PRIV_DIR" + if [ ! -e "$AUDITOR_PRIV_FILE" ] + then + gnunet-ecc -g1 "$AUDITOR_PRIV_FILE" > /dev/null 2> /dev/null + echo -n "." + fi + AUDITOR_PUB=$(gnunet-ecc -p "${AUDITOR_PRIV_FILE}") + MAPUB=${MASTER_PUB:-$(taler-config -c "$CONF" -s exchange -o MASTER_PUBLIC_KEY)} + taler-auditor-dbinit -c "$CONF" --reset + taler-auditor-exchange -c "$CONF" -m "$MAPUB" -u "$EXCHANGE_URL" + $USE_VALGRIND taler-auditor-httpd -L "$LOGLEVEL" -c "$CONF" 2> taler-auditor-httpd.log & + echo " DONE" +fi + + +echo -n "Waiting for Taler services ..." +# Wait for all other taler services to be available +E_DONE=0 +O_DONE=0 +M_DONE=0 +S_DONE=0 +K_DONE=0 +A_DONE=0 +for n in $(seq 1 20) +do + sleep "$DEFAULT_SLEEP" + OK="0" + if [ "0" = "$E_DONE" ] && [ "1" = "$START_EXCHANGE" ] + then + echo -n "E" + wget \ + --tries=1 \ + --timeout=1 \ + "${EXCHANGE_URL}config" \ + -o /dev/null \ + -O /dev/null >/dev/null || continue + E_DONE=1 + fi + if [ "0" = "$O_DONE" ] && [ "1" = "$START_DONAU" ] + then + echo -n "O" + wget \ + --tries=1 \ + --timeout=1 \ + "${DONAU_URL}config" \ + -o /dev/null \ + -O /dev/null >/dev/null || continue + O_DONE=1 + fi + if [ "0" = "$M_DONE" ] && [ "1" = "$START_MERCHANT" ] + then + echo -n "M" + wget \ + --tries=1 \ + --timeout=1 \ + "${MERCHANT_URL}config" \ + -o /dev/null \ + -O /dev/null >/dev/null || continue + M_DONE=1 + fi + if [ "0" = "$S_DONE" ] && [ "1" = "$START_BACKUP" ] + then + echo -n "S" + wget \ + --tries=1 \ + --timeout=1 \ + "${SYNC_URL}config" \ + -o /dev/null \ + -O /dev/null >/dev/null || continue + S_DONE=1 + fi + if [ "0" = "$K_DONE" ] && [ "1" = "$START_CHALLENGER" ] + then + echo -n "K" + wget \ + --tries=1 \ + --timeout=1 \ + "${CHALLENGER_URL}config" \ + -o /dev/null \ + -O /dev/null >/dev/null || continue + K_DONE=1 + fi + if [ "0" = "$A_DONE" ] && [ "1" = "$START_AUDITOR" ] + then + echo -n "A" + wget \ + --tries=1 \ + --timeout=1 \ + "${AUDITOR_URL}config" \ + -o /dev/null \ + -O /dev/null >/dev/null || continue + A_DONE=1 + fi + OK="1" + break +done +if [ 1 != "$OK" ] +then + exit_skip "Failed to launch (some) Taler services" +fi +echo " OK" + +if [ "1" = "$START_EXCHANGE" ] +then + echo -n "Wait for exchange /management/keys to be ready " + OK="0" + LAST_RESPONSE=$(mktemp tmp-last-response.XXXXXXXX) + for n in $(seq 1 10) + do + echo -n "." + sleep "$DEFAULT_SLEEP" + # exchange + wget \ + --tries=3 \ + --waitretry=0 \ + --timeout=30 \ + "${EXCHANGE_URL}management/keys"\ + -o /dev/null \ + -O "$LAST_RESPONSE" \ + >/dev/null || continue + OK="1" + break; + done + if [ "1" != "$OK" ] + then + cat "$LAST_RESPONSE" + exit_fail "Failed to setup exchange keys, check secmod logs" + fi + rm "$LAST_RESPONSE" + echo " OK" + + echo -n "Setting up exchange keys ..." + taler-exchange-offline -c "$CONF" \ + download \ + sign \ + wire-fee now "$WIRE_DOMAIN" "$CURRENCY:0.01" "$CURRENCY:0.01" \ + global-fee now "$CURRENCY:0.01" "$CURRENCY:0.01" "$CURRENCY:0.01" 1h 1year 5 \ + upload &> taler-exchange-offline.log + echo "OK" + ENABLED=$(taler-config -c "$CONF" -s "$USE_ACCOUNT" -o "ENABLE_CREDIT") + if [ "YES" = "$ENABLED" ] + then + echo -n "Configuring bank account $USE_ACCOUNT ..." + EXCHANGE_PAYTO_URI=$(taler-config -c "$CONF" -s "$USE_ACCOUNT" -o "PAYTO_URI") + taler-exchange-offline -c "$CONF" \ + enable-account "$EXCHANGE_PAYTO_URI" \ + upload &> "taler-exchange-offline-account.log" + echo " OK" + else + echo "WARNING: Account ${USE_ACCOUNT} not enabled (set to: '$ENABLED')" + fi + if [ "1" = "$START_AUDITOR" ] + then + echo -n "Enabling auditor ..." + taler-exchange-offline -c "$CONF" \ + enable-auditor "$AUDITOR_PUB" "$AUDITOR_URL" "$CURRENCY Auditor" \ + upload &> taler-exchange-offline-auditor.log + echo "OK" + fi + + echo -n "Checking /keys " + OK="0" + LAST_RESPONSE=$(mktemp tmp-last-response.XXXXXXXX) + for n in $(seq 1 10) + do + echo -n "." + sleep "$DEFAULT_SLEEP" + wget \ + --tries=1 \ + --timeout=5 \ + "${EXCHANGE_URL}keys" \ + -a wget-keys-check.log \ + -o /dev/null \ + -O "$LAST_RESPONSE" \ + >/dev/null || continue + OK="1" + break + done + if [ "1" != "$OK" ] + then + cat "$LAST_RESPONSE" + exit_fail " Failed to fetch ${EXCHANGE_URL}keys" + fi + rm "$LAST_RESPONSE" + echo " OK" +fi + +if [ "1" = "$START_AUDITOR" ] +then + echo -n "Setting up auditor signatures ..." + timeout 15 taler-auditor-offline -c "$CONF" \ + download \ + sign \ + upload &> taler-auditor-offline.log + echo " OK" +fi + +# Signal caller that we are ready. +echo "<<READY>>" + +if [ "1" = "$WAIT_FOR_SIGNAL" ] +then + while true + do + sleep 0.1 + done +else + # Wait until caller stops us. + # shellcheck disable=SC2162 + read +fi + +echo "Taler unified setup terminating!" >&2 +EXIT_STATUS=0 +exit "$EXIT_STATUS"