diff --git a/src/exchange/taler-exchange-httpd_age-withdraw.c b/src/exchange/taler-exchange-httpd_age-withdraw.c index 170cd06a5..0978421a4 100644 --- a/src/exchange/taler-exchange-httpd_age-withdraw.c +++ b/src/exchange/taler-exchange-httpd_age-withdraw.c @@ -222,7 +222,6 @@ age_withdraw_transaction (void *cls, awc->kyc.ok = true; qs = TEH_plugin->do_age_withdraw (TEH_plugin->cls, &awc->commitment, - awc->now, &found, &balance_ok, &ruuid); @@ -312,7 +311,7 @@ TEH_handler_age_withdraw (struct TEH_RequestContext *rc, const json_t *root) { MHD_RESULT mhd_ret; - struct AgeWithdrawContext awc; + struct AgeWithdrawContext awc = {0}; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("reserve_sig", &awc.commitment.reserve_sig), @@ -321,12 +320,11 @@ TEH_handler_age_withdraw (struct TEH_RequestContext *rc, TALER_JSON_spec_amount ("amount", TEH_currency, &awc.commitment.amount_with_fee), - GNUNET_JSON_spec_uint32 ("max_age", + GNUNET_JSON_spec_uint16 ("max_age", &awc.commitment.max_age), GNUNET_JSON_spec_end () }; - memset (&awc, 0, sizeof (awc)); awc.commitment.reserve_pub = *reserve_pub; diff --git a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c index 50d524a2f..31ff57c6b 100644 --- a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c +++ b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c @@ -306,7 +306,7 @@ find_original_commitment ( break; case GNUNET_DB_STATUS_SOFT_ERROR: - /* FIXME:oec: Do we queue a result in this case or retry? */ + /* FIXME oec: Do we queue a result in this case or retry? */ default: GNUNET_break (0); /* should be impossible */ *result = TALER_MHD_reply_with_error (connection, @@ -564,7 +564,7 @@ verify_commitment_and_max_age ( { size_t k = 0; /* either 0 or 1, to index into coin_evs */ - for (size_t idx = 0; idx<3; idx++) + for (size_t idx = 0; idx j); + GNUNET_assert ((TALER_CNC_KAPPA - 1) * num_coins > j); secret = &disclosed_coin_secrets[j]; k++; @@ -614,7 +615,6 @@ verify_commitment_and_max_age ( { struct TALER_CoinPubHashP c_hash; struct TALER_PlanchetDetail detail; - struct TALER_BlindedCoinHashP bch; struct TALER_CoinSpendPrivateKeyP coin_priv; union TALER_DenominationBlindingKeyP bks; struct TALER_ExchangeWithdrawValues alg_values = { @@ -640,9 +640,7 @@ verify_commitment_and_max_age ( false, &alg_values.details. cs_values); - -#pragma message ("FIXME:oec: return value of needs handling!") - /* FIXME:oec: Handle error */ + /* FIXME Handle error? */ GNUNET_assert (TALER_EC_NONE == ec); } } @@ -692,10 +690,13 @@ verify_commitment_and_max_age ( return ret; } - GNUNET_CRYPTO_hash_context_read (hash_context, - &detail.blinded_planchet, - sizeof(detail.blinded_planchet)); } + + /* Continue the running hash of all coin hashes with the calculated + * hash-value of the current, disclosed coin */ + GNUNET_CRYPTO_hash_context_read (hash_context, + &bch, + sizeof(bch)); } } } @@ -722,6 +723,37 @@ verify_commitment_and_max_age ( } +/** + * @brief Signs and persists the undisclosed coins + * + * @param connection HTTP-connection to the client + * @param h_commitment_orig Original commitment + * @param num_coins Number of coins + * @param coin_evs The Hashes of the undisclosed, blinded coins, @a num_coins many + * @param denom_keys The array of denomination keys, @a num_coins. Needed to detect Clause-Schnorr-based denominations + * @param[out] result On error, a HTTP-response will be queued and result set accordingly + * @return GNUNET_OK on success, GNUNET_SYSERR otherwise + */ +static enum GNUNET_GenericReturnValue +sign_and_persist_blinded_coins ( + struct MHD_Connection *connection, + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment_orig, + const uint32_t num_coins, + const struct TALER_BlindedCoinHashP *coin_evs, + const struct TEH_DenominationKey *denom_keys, + MHD_RESULT *result) +{ + enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR; + + /* TODO[oec]: + * - sign the planchets + * - in a transaction: save the coins. + */ + #pragma message "FIXME[oec]: implement sign_and_persist_blinded_coins" + return ret; +} + + MHD_RESULT TEH_handler_age_withdraw_reveal ( struct TEH_RequestContext *rc, @@ -803,7 +835,15 @@ TEH_handler_age_withdraw_reveal ( &result)) break; - /* TODO:oec: sign the coins */ + /* Finally, sign and persist the coins */ + if (GNUNET_OK != sign_and_persist_blinded_coins ( + rc->connection, + &actx.commitment.h_commitment, + actx.num_coins, + actx.coin_evs, + actx.denom_keys, + &result)) + break; } while(0); diff --git a/src/exchangedb/0003-withdraw_age_commitments.sql b/src/exchangedb/0003-withdraw_age_commitments.sql index 6c153598d..b8451129a 100644 --- a/src/exchangedb/0003-withdraw_age_commitments.sql +++ b/src/exchangedb/0003-withdraw_age_commitments.sql @@ -33,7 +33,6 @@ BEGIN ',reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_pub)=32)' ',reserve_sig BYTEA CHECK (LENGTH(reserve_sig)=64)' ',noreveal_index INT4 NOT NULL' - ',timestamp INT8 NOT NULL' ') %s ;' ,table_name ,'PARTITION BY HASH (reserve_pub)' @@ -51,7 +50,7 @@ BEGIN ,partition_suffix ); PERFORM comment_partitioned_column( - 'The maximum age that the client commits to with this request' + 'The maximum age (in years) that the client commits to with this request' ,'max_age' ,table_name ,partition_suffix @@ -74,12 +73,6 @@ BEGIN ,table_name ,partition_suffix ); - PERFORM comment_partitioned_column( - 'Timestamp with the time when the withdraw-age request was received by the exchange' - ,'timestamp' - ,table_name - ,partition_suffix - ); END $$; diff --git a/src/exchangedb/0003-withdraw_age_reveals.sql b/src/exchangedb/0003-withdraw_age_reveals.sql index 3353d9367..af66eab75 100644 --- a/src/exchangedb/0003-withdraw_age_reveals.sql +++ b/src/exchangedb/0003-withdraw_age_reveals.sql @@ -14,22 +14,25 @@ -- TALER; see the file COPYING. If not, see -- -CREATE FUNCTION create_table_withdraw_age_reveals( +CREATE FUNCTION create_table_withdraw_age_revealed_coins( IN partition_suffix VARCHAR DEFAULT NULL ) RETURNS VOID LANGUAGE plpgsql AS $$ DECLARE - table_name VARCHAR DEFAULT 'withdraw_age_reveals'; + table_name VARCHAR DEFAULT 'withdraw_age_revealed_coins'; BEGIN PERFORM create_partitioned_table( 'CREATE TABLE %I' - '(withdraw_age_reveals_id BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE - ',h_commitment BYTEA NOT NULL CHECK (LENGTH(h_commitment)=32)' + '(withdraw_age_revealed_coins_id BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE + ',h_commitment BYTEA NOT NULL CHECK (LENGTH(h_commitment)=64)' ',freshcoin_index INT4 NOT NULL' ',denominations_serial INT8 NOT NULL' - ',h_coin_ev BYTEA CHECK (LENGTH(h_coin_ev)=32)' + ',coin_ev BYTEA NOT NULL' + ',h_coin_ev BYTEA CHECK (LENGTH(h_coin_ev)=64)' + ',ev_sig BYTEA NOT NULL' + ',ewv BYTEA NOT NULL' ') %s ;' ,table_name ,'PARTITION BY HASH (h_commitment)' @@ -59,29 +62,47 @@ BEGIN ,partition_suffix ); PERFORM comment_partitioned_column( - 'Hash of the blinded coins' + 'Envelope of the new coin to be signed' + ,'coin_ev' + ,table_name + ,partition_suffix + ); + PERFORM comment_partitioned_column( + 'Hash of the envelope of the new coin to be signed (for lookups)' ,'h_coin_ev' ,table_name ,partition_suffix ); + PERFORM comment_partitioned_column( + 'Exchange signature over the envelope' + ,'ev_sig' + ,table_name + ,partition_suffix + ); + PERFORM comment_partitioned_column( + 'Exchange contributed values in the creation of the fresh coin (see /csr)' + ,'ewv' + ,table_name + ,partition_suffix + ); END $$; -CREATE FUNCTION constrain_table_withdraw_age_reveals( +CREATE FUNCTION constrain_table_withdraw_age_revealed_coins( IN partition_suffix VARCHAR ) RETURNS void LANGUAGE plpgsql AS $$ DECLARE - table_name VARCHAR DEFAULT 'withdraw_age_reveals'; + table_name VARCHAR DEFAULT 'withdraw_age_revealed_coins'; BEGIN table_name = concat_ws('_', table_name, partition_suffix); EXECUTE FORMAT ( 'ALTER TABLE ' || table_name || - ' ADD CONSTRAINT ' || table_name || '_withdraw_age_reveals_id_key' - ' UNIQUE (withdraw_age_reveals_id);' + ' ADD CONSTRAINT ' || table_name || '_withdraw_age_revealed_coins_id_key' + ' UNIQUE (withdraw_age_revealed_coins_id);' ); EXECUTE FORMAT ( 'ALTER TABLE ' || table_name || @@ -91,12 +112,12 @@ BEGIN END $$; -CREATE FUNCTION foreign_table_withdraw_age_reveals() +CREATE FUNCTION foreign_table_withdraw_age_revealed_coins() RETURNS void LANGUAGE plpgsql AS $$ DECLARE - table_name VARCHAR DEFAULT 'withdraw_age_reveals'; + table_name VARCHAR DEFAULT 'withdraw_age_revealed_coins'; BEGIN EXECUTE FORMAT ( 'ALTER TABLE ' || table_name || @@ -121,17 +142,17 @@ INSERT INTO exchange_tables ,partitioned ,by_range) VALUES - ('withdraw_age_reveals' + ('withdraw_age_revealed_coins' ,'exchange-0003' ,'create' ,TRUE ,FALSE), - ('withdraw_age_reveals' + ('withdraw_age_revealed_coins' ,'exchange-0003' ,'constrain' ,TRUE ,FALSE), - ('withdraw_age_reveals' + ('withdraw_age_revealed_coins' ,'exchange-0003' ,'foreign' ,TRUE diff --git a/src/exchangedb/pg_get_age_withdraw_info.c b/src/exchangedb/pg_get_age_withdraw_info.c index 02ccc84ac..754b572c9 100644 --- a/src/exchangedb/pg_get_age_withdraw_info.c +++ b/src/exchangedb/pg_get_age_withdraw_info.c @@ -35,6 +35,7 @@ TEH_PG_get_age_withdraw_info ( { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (reserve_pub), GNUNET_PQ_query_param_auto_from_type (ach), GNUNET_PQ_query_param_end }; @@ -45,14 +46,12 @@ TEH_PG_get_age_withdraw_info ( &awc->reserve_sig), GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", &awc->reserve_pub), - GNUNET_PQ_result_spec_uint32 ("max_age", + GNUNET_PQ_result_spec_uint16 ("max_age", &awc->max_age), TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", &awc->amount_with_fee), GNUNET_PQ_result_spec_uint32 ("noreveal_index", &awc->noreveal_index), - GNUNET_PQ_result_spec_timestamp ("timtestamp", - &awc->timestamp), GNUNET_PQ_result_spec_end }; @@ -70,9 +69,8 @@ TEH_PG_get_age_withdraw_info ( ",amount_with_fee_val" ",amount_with_fee_frac" ",noreveal_index" - ",timestamp" " FROM withdraw_age_commitments" - " WHERE h_commitment=$1;"); + " WHERE reserve_pub=$1 and h_commitment=$2;"); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "get_age_withdraw_info", params, diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c index 73e6ccda1..e790ec549 100644 --- a/src/exchangedb/pg_insert_records_by_table.c +++ b/src/exchangedb/pg_insert_records_by_table.c @@ -19,8 +19,9 @@ */ /** * @file exchangedb/pg_insert_records_by_table.c - * @brief insert_records_by_table implementation + * @brief replicate_records_by_table implementation * @author Christian Grothoff + * @author Özgür Kesim */ #include "platform.h" #include "taler_error_codes.h" @@ -28,6 +29,7 @@ #include "taler_pq_lib.h" #include "pg_insert_records_by_table.h" #include "pg_helper.h" +#include /** @@ -2110,40 +2112,56 @@ irbt_cb_table_withdraw_age_commitments (struct PostgresClosure *pg, /** - * Function called with withdraw_age_reveals records to insert into table. + * Function called with withdraw_age_revealed_coins records to insert into table. * * @param pg plugin context * @param td record to insert */ static enum GNUNET_DB_QueryStatus -irbt_cb_table_withdraw_age_reveals (struct PostgresClosure *pg, - const struct TALER_EXCHANGEDB_TableData *td) +irbt_cb_table_withdraw_age_revealed_coins (struct PostgresClosure *pg, + const struct + TALER_EXCHANGEDB_TableData *td) { + struct GNUNET_HashCode h_coin_ev; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&td->serial), -#if FIXME_OEC GNUNET_PQ_query_param_auto_from_type ( - &td->details.withdraw_age_reveals.h_commitment), -#endif + &td->details.withdraw_age_revealed_coins.h_commitment), GNUNET_PQ_query_param_uint32 ( - &td->details.withdraw_age_reveals.freshcoin_index), + &td->details.withdraw_age_revealed_coins.freshcoin_index), GNUNET_PQ_query_param_uint64 ( - &td->details.withdraw_age_reveals.denominations_serial), + &td->details.withdraw_age_revealed_coins.denominations_serial), + GNUNET_PQ_query_param_fixed_size ( + td->details.withdraw_age_revealed_coins.coin_ev, + td->details.withdraw_age_revealed_coins.coin_ev_size), + GNUNET_PQ_query_param_auto_from_type (&h_coin_ev), + TALER_PQ_query_param_blinded_denom_sig ( + &td->details.withdraw_age_revealed_coins.ev_sig), + TALER_PQ_query_param_exchange_withdraw_values ( + &td->details.withdraw_age_revealed_coins.ewv), GNUNET_PQ_query_param_end }; PREPARE (pg, - "insert_into_table_withdraw_age_reveals", - "INSERT INTO withdraw_age_reveals" - "(withdraw_age_reveals_id" - ",FIXME_OEC" + "insert_into_table_withdraw_age_revealed_coins", + "INSERT INTO withdraw_age_revealed_coins" + "(withdraw_age_revealed_coins_id" + ",h_commitment" ",freshcoin_index" ",denominations_serial" - ",FIXME_OEC" + ",coin_ev" + ",h_coin_ev" + ",ev_sig" + ",ewv" ") VALUES " - "($1, $2, $3, $4, $5);"); + "($1, $2, $3, $4, $5, $6, $7, $8);"); + + GNUNET_CRYPTO_hash (td->details.withdraw_age_revealed_coins.coin_ev, + td->details.withdraw_age_revealed_coins.coin_ev_size, + &h_coin_ev); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_into_table_withdraw_age_reveals", + "insert_into_table_withdraw_age_revealed_coins", params); } @@ -2298,8 +2316,8 @@ TEH_PG_insert_records_by_table (void *cls, case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS: rh = &irbt_cb_table_withdraw_age_commitments; break; - case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS: - rh = &irbt_cb_table_withdraw_age_reveals; + case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS: + rh = &irbt_cb_table_withdraw_age_revealed_coins; break; } if (NULL == rh) diff --git a/src/exchangedb/pg_lookup_records_by_table.c b/src/exchangedb/pg_lookup_records_by_table.c index 51894f23f..2e157360f 100644 --- a/src/exchangedb/pg_lookup_records_by_table.c +++ b/src/exchangedb/pg_lookup_records_by_table.c @@ -21,6 +21,7 @@ * @file exchangedb/pg_lookup_records_by_table.c * @brief implementation of lookup_records_by_table * @author Christian Grothoff + * @author Özgür Kesim */ #include "platform.h" #include "taler_error_codes.h" @@ -2807,9 +2808,6 @@ lrbt_cb_table_withdraw_age_commitments (void *cls, GNUNET_PQ_result_spec_uint32 ( "noreveal_index", &td.details.withdraw_age_commitments.noreveal_index), - GNUNET_PQ_result_spec_absolute_time ( - "timestamp", - &td.details.withdraw_age_commitments.timestamp), GNUNET_PQ_result_spec_end }; @@ -2830,40 +2828,48 @@ lrbt_cb_table_withdraw_age_commitments (void *cls, /** - * Function called with withdraw_age_reveals table entries. + * Function called with withdraw_age_revealed_coins table entries. * * @param cls closure * @param result the postgres result * @param num_results the number of results in @a result */ static void -lrbt_cb_table_withdraw_age_reveals (void *cls, - PGresult *result, - unsigned int num_results) +lrbt_cb_table_withdraw_age_revealed_coins (void *cls, + PGresult *result, + unsigned int num_results) { struct LookupRecordsByTableContext *ctx = cls; struct TALER_EXCHANGEDB_TableData td = { - .table = TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS + .table = TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS }; for (unsigned int i = 0; i $1" " ORDER BY withdraw_age_commitment_id ASC;"); rh = &lrbt_cb_table_withdraw_age_commitments; break; - + case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS: + XPREPARE ("select_above_serial_by_table_withdraw_age_revealed_coins", + "SELECT" + " withdraw_age_revealed_coins_serial_id" + ",h_commitment" + ",freshcoin_index" + ",denominations_serial" + ",coin_ev" + ",h_coin_ev" + ",ev_sig" + ",ewv" + " FROM withdraw_age_revealed_coins" + " WHERE withdraw_age_revealed_coins_serial_id > $1" + " ORDER BY withdraw_age_revealed_coins_serial_id ASC;"); + rh = &lrbt_cb_table_withdraw_age_revealed_coins; + break; } if (NULL == rh) { diff --git a/src/exchangedb/pg_lookup_serial_by_table.c b/src/exchangedb/pg_lookup_serial_by_table.c index d2554af2e..c98b4539e 100644 --- a/src/exchangedb/pg_lookup_serial_by_table.c +++ b/src/exchangedb/pg_lookup_serial_by_table.c @@ -435,14 +435,14 @@ TEH_PG_lookup_serial_by_table (void *cls, " LIMIT 1;"); statement = "select_serial_by_table_withdraw_age_commitments"; break; - case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS: - XPREPARE ("select_serial_by_table_withdraw_age_reveals", + case TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS: + XPREPARE ("select_serial_by_table_withdraw_age_revealed_coins", "SELECT" - " withdraw_age_reveals_id AS serial" - " FROM withdraw_age_reveals" - " ORDER BY withdraw_age_reveals_id DESC" + " withdraw_age_revealed_coins_id AS serial" + " FROM withdraw_age_revealed_coins" + " ORDER BY withdraw_age_revealed_coins_id DESC" " LIMIT 1;"); - statement = "select_serial_by_table_withdraw_age_reveals"; + statement = "select_serial_by_table_withdraw_age_revealed_coins"; break; } if (NULL == statement) diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 7e3aa2b1e..b3ebc7547 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -21,6 +21,7 @@ * @author Christian Grothoff * @author Sree Harsha Totakura * @author Marcello Stanisci + * @author Özgür Kesim */ #include "platform.h" #include diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index f60c3cf05..5b724953b 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -18,6 +18,7 @@ * @brief Low-level (statement-level) database access for the exchange * @author Florian Dold * @author Christian Grothoff + * @author Özgür Kesim */ #ifndef TALER_EXCHANGEDB_PLUGIN_H #define TALER_EXCHANGEDB_PLUGIN_H @@ -283,7 +284,7 @@ enum TALER_EXCHANGEDB_ReplicatedTable TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES, TALER_EXCHANGEDB_RT_PURSE_DELETION, TALER_EXCHANGEDB_RT_WITHDRAW_AGE_COMMITMENTS, - TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALS, + TALER_EXCHANGEDB_RT_WITHDRAW_AGE_REVEALED_COINS, }; @@ -764,11 +765,14 @@ struct TALER_EXCHANGEDB_TableData struct { struct TALER_AgeWithdrawCommitmentHashP h_commitment; - // FIXME-Oec: h_commitment --- schema says it is 32 byte, but it was 64 above??!? uint32_t freshcoin_index; uint64_t denominations_serial; - // FIXME-Oec: h_coin_ev --- schema says it is 32 byte!? - } withdraw_age_reveals; + void *coin_ev; + size_t coin_ev_size; + struct TALER_ExchangeWithdrawValues ewv; + // h_coin_ev omitted, to be recomputed! + struct TALER_BlindedDenominationSignature ev_sig; + } withdraw_age_revealed_coins; } details; @@ -1175,9 +1179,8 @@ struct TALER_EXCHANGEDB_AgeWithdrawCommitment /** * Maximum age that the coins are restricted to. - * FIXME-Oec: use 16-bit integer (see DB schema!) */ - uint32_t max_age; + uint16_t max_age; /** * The hash of the commitment of all n*kappa coins @@ -1206,11 +1209,6 @@ struct TALER_EXCHANGEDB_AgeWithdrawCommitment * The exchange's signature of the response. */ struct TALER_ExchangeSignatureP sig; - - /** - * Timestamp of the request being made - */ - struct GNUNET_TIME_Timestamp timestamp; }; @@ -3794,7 +3792,6 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param commitment corresponding commitment for the age-withdraw - * @param now current time (rounded) * @param[out] found set to true if the reserve was found * @param[out] balance_ok set to true if the balance was sufficient * @param[out] ruuid set to the reserve's UUID (reserves table row) @@ -3804,7 +3801,6 @@ struct TALER_EXCHANGEDB_Plugin (*do_age_withdraw)( void *cls, const struct TALER_EXCHANGEDB_AgeWithdrawCommitment *commitment, - struct GNUNET_TIME_Timestamp now, bool *found, bool *balance_ok, uint64_t *ruuid); @@ -5787,6 +5783,7 @@ struct TALER_EXCHANGEDB_Plugin * Insert record set into @a table. Used in exchange-auditor database * replication. * + memset (&awc, 0, sizeof (awc)); * @param cls closure * @param tb table data to insert * @return transaction status code, #GNUNET_DB_STATUS_HARD_ERROR if