include purse deposits in coin history

This commit is contained in:
Christian Grothoff 2022-05-23 16:02:55 +02:00
parent a509a91f92
commit 76b8a2a8de
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
7 changed files with 193 additions and 7 deletions

View File

@ -391,8 +391,33 @@ TEH_RESPONSE_compile_transaction_history (
}
break;
}
default:
GNUNET_assert (0);
case TALER_EXCHANGEDB_TT_PURSE_DEPOSIT:
{
struct TALER_EXCHANGEDB_PurseDepositListEntry *pd
= pos->details.purse_deposit;
if (0 !=
json_array_append_new (
history,
GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("type",
"PURSE-DEPOSIT"),
TALER_JSON_pack_amount ("amount",
&pd->amount),
GNUNET_JSON_pack_string ("exchange_base_url",
pd->exchange_base_url),
GNUNET_JSON_pack_data_auto ("purse_pub",
&pd->purse_pub),
GNUNET_JSON_pack_data_auto ("coin_sig",
&pd->coin_sig))))
{
GNUNET_break (0);
json_decref (history);
return NULL;
}
break;
}
}
}
return history;

View File

@ -119,6 +119,18 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (
return GNUNET_SYSERR;
}
break;
case TALER_EXCHANGEDB_TT_PURSE_DEPOSIT:
/* spent += pos->amount_with_fee */
if (0 >
TALER_amount_add (&spent,
&spent,
&pos->details.purse_deposit->amount))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
deposit_fee = pos->details.purse_deposit->deposit_fee;
break;
}
}
if (have_refund)

View File

@ -150,6 +150,15 @@ common_free_coin_transaction_list (void *cls,
GNUNET_free (rr);
break;
}
case TALER_EXCHANGEDB_TT_PURSE_DEPOSIT:
{
struct TALER_EXCHANGEDB_PurseDepositListEntry *deposit;
deposit = tl->details.purse_deposit;
GNUNET_free (deposit->exchange_base_url);
GNUNET_free (deposit);
break;
}
}
{
struct TALER_EXCHANGEDB_TransactionList *next;

View File

@ -1235,7 +1235,8 @@ prepare_statements (struct PostgresClosure *pg)
" WHERE melt_serial_id>=$1"
" ORDER BY melt_serial_id ASC;",
1),
/* Query the 'refresh_commitments' by coin public key */
/* Query the 'refresh_commitments' by coin public key,
used in #postgres_get_coin_transactions() */
GNUNET_PQ_make_prepare (
"get_refresh_session_by_coin",
"SELECT"
@ -1255,6 +1256,30 @@ prepare_statements (struct PostgresClosure *pg)
" USING (denominations_serial)"
" WHERE old_coin_pub=$1;",
1),
/* Find purse deposits by coin,
used in #postgres_get_coin_transactions() */
GNUNET_PQ_make_prepare (
"get_purse_deposit_by_coin_pub",
"SELECT"
" partner_url"
",amount_with_fee_val"
",amount_with_fee_frac"
",denoms.fee_deposit_val"
",denoms.fee_deposit_frac"
",purse_pub"
",coin_sig"
",purse_deposit_serial_id"
" FROM purse_deposits pd"
" LEFT JOIN partners"
" USING (partner_serial_id)"
" JOIN known_coins kc"
" ON (refresh_commitments.old_coin_pub = kc.coin_pub)"
" JOIN denominations denoms"
" USING (denominations_serial)"
// FIXME: use to-be-created materialized index
// on coin_pub (query crosses partitions!)
" WHERE coin_pub=$1;",
1),
/* Store information about the desired denominations for a
refresh operation, used in #postgres_insert_refresh_reveal() */
GNUNET_PQ_make_prepare (
@ -7941,6 +7966,70 @@ add_coin_deposit (void *cls,
}
/**
* Function to be called with the results of a SELECT statement
* that has returned @a num_results results.
*
* @param cls closure of type `struct CoinHistoryContext`
* @param result the postgres result
* @param num_results the number of results in @a result
*/
static void
add_coin_purse_deposit (void *cls,
PGresult *result,
unsigned int num_results)
{
struct CoinHistoryContext *chc = cls;
struct PostgresClosure *pg = chc->pg;
for (unsigned int i = 0; i < num_results; i++)
{
struct TALER_EXCHANGEDB_PurseDepositListEntry *deposit;
struct TALER_EXCHANGEDB_TransactionList *tl;
uint64_t serial_id;
chc->have_deposit_or_melt = true;
deposit = GNUNET_new (struct TALER_EXCHANGEDB_PurseDepositListEntry);
{
struct GNUNET_PQ_ResultSpec rs[] = {
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
&deposit->amount),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
&deposit->deposit_fee),
GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
&deposit->purse_pub),
GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
&serial_id),
GNUNET_PQ_result_spec_allow_null (
GNUNET_PQ_result_spec_string ("partner_url",
&deposit->exchange_base_url),
NULL),
GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
&deposit->coin_sig),
GNUNET_PQ_result_spec_end
};
if (GNUNET_OK !=
GNUNET_PQ_extract_result (result,
rs,
i))
{
GNUNET_break (0);
GNUNET_free (deposit);
chc->failed = true;
return;
}
}
tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
tl->next = chc->head;
tl->type = TALER_EXCHANGEDB_TT_PURSE_DEPOSIT;
tl->details.purse_deposit = deposit;
tl->serial_id = serial_id;
chc->head = tl;
}
}
/**
* Function to be called with the results of a SELECT statement
* that has returned @a num_results results.
@ -8309,6 +8398,9 @@ postgres_get_coin_transactions (
/** #TALER_EXCHANGEDB_TT_MELT */
{ "get_refresh_session_by_coin",
&add_coin_melt },
/** #TALER_EXCHANGEDB_TT_PURSE_DEPOSIT */
{ "get_purse_deposit_by_coin_pub",
&add_coin_purse_deposit },
/** #TALER_EXCHANGEDB_TT_REFUND */
{ "get_refunds_by_coin",
&add_coin_refund },
@ -8321,6 +8413,9 @@ postgres_get_coin_transactions (
/** #TALER_EXCHANGEDB_TT_MELT */
{ "get_refresh_session_by_coin",
&add_coin_melt },
/** #TALER_EXCHANGEDB_TT_PURSE_DEPOSIT */
{ "get_purse_deposit_by_coin_pub",
&add_coin_purse_deposit },
/** #TALER_EXCHANGEDB_TT_REFUND */
{ "get_refunds_by_coin",
&add_coin_refund },

View File

@ -1536,6 +1536,40 @@ struct TALER_EXCHANGEDB_MeltListEntry
};
/**
* Information about a /purses/$PID/deposit operation in a coin transaction history.
*/
struct TALER_EXCHANGEDB_PurseDepositListEntry
{
/**
* Exchange hosting the purse, NULL for this exchange.
*/
char *exchange_base_url;
/**
* Public key of the purse.
*/
struct TALER_PurseContractPublicKeyP purse_pub;
/**
* Contribution of the coin to the purse, including
* deposit fee.
*/
struct TALER_Amount amount;
/**
* Depositing fee.
*/
struct TALER_Amount deposit_fee;
/**
* Signature by the coin affirming the deposit.
*/
struct TALER_CoinSpendSignatureP coin_sig;
};
/**
* Information about a melt operation.
*/
@ -1639,7 +1673,12 @@ enum TALER_EXCHANGEDB_TransactionType
/**
* Recoup-refresh operation (on the new coin, eliminating its value)
*/
TALER_EXCHANGEDB_TT_RECOUP_REFRESH = 5
TALER_EXCHANGEDB_TT_RECOUP_REFRESH = 5,
/**
* Purse deposit operation.
*/
TALER_EXCHANGEDB_TT_PURSE_DEPOSIT = 6
};
@ -1709,6 +1748,12 @@ struct TALER_EXCHANGEDB_TransactionList
*/
struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup_refresh;
/**
* Coin was deposited into a purse.
* (#TALER_EXCHANGEDB_TT_PURSE_DEPOSIT)
*/
struct TALER_EXCHANGEDB_PurseDepositListEntry *purse_deposit;
} details;
};

View File

@ -378,6 +378,7 @@ handle_purse_deposit_finished (void *cls,
break;
}
/* everything OK, proof of double-spending was provided */
break;
}
case TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY:
{
@ -455,6 +456,7 @@ handle_purse_deposit_finished (void *cls,
break;
}
/* everything OK, proof of conflicting denomination was provided */
break;
}
default:
GNUNET_break_op (0);

View File

@ -251,14 +251,12 @@ run (void *cls,
"create-reserve-1",
"EUR:2",
MHD_HTTP_OK),
#if 1
/* POST history doesn't yet support P2P transfers */
TALER_TESTING_cmd_reserve_status (
"push-check-post-merge-reserve-balance-post",
"create-reserve-1",
"EUR:2",
MHD_HTTP_OK),
#endif
/* create 2nd purse for a deposit conflict */
TALER_TESTING_cmd_purse_create_with_reserve (
"purse-create-with-reserve-2",
@ -267,7 +265,7 @@ run (void *cls,
true /* upload contract */,
GNUNET_TIME_UNIT_MINUTES, /* expiration */
"create-reserve-1"),
#if FIXME_RESERVE_HISTORY
#if 1
TALER_TESTING_cmd_purse_deposit_coins (
"purse-deposit-coins-conflict",
MHD_HTTP_CONFLICT,