work on purse creation logic
This commit is contained in:
parent
747ae5ef09
commit
caf66486e7
@ -1 +1 @@
|
|||||||
Subproject commit 25eb78f2d0e20a137020dd0ab1c6474123843dbe
|
Subproject commit b799c63db9beda99e9151e7611a1ac4e810786ab
|
@ -178,7 +178,6 @@ deposit_transaction (void *cls,
|
|||||||
}
|
}
|
||||||
if (in_conflict)
|
if (in_conflict)
|
||||||
{
|
{
|
||||||
TEH_plugin->rollback (TEH_plugin->cls);
|
|
||||||
*mhd_ret
|
*mhd_ret
|
||||||
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
||||||
connection,
|
connection,
|
||||||
@ -188,7 +187,6 @@ deposit_transaction (void *cls,
|
|||||||
}
|
}
|
||||||
if (! balance_ok)
|
if (! balance_ok)
|
||||||
{
|
{
|
||||||
TEH_plugin->rollback (TEH_plugin->cls);
|
|
||||||
*mhd_ret
|
*mhd_ret
|
||||||
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
||||||
connection,
|
connection,
|
||||||
@ -323,6 +321,16 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
|||||||
GNUNET_JSON_parse_free (spec);
|
GNUNET_JSON_parse_free (spec);
|
||||||
return mret;
|
return mret;
|
||||||
}
|
}
|
||||||
|
if (0 > TALER_amount_cmp (&dk->meta.value,
|
||||||
|
&deposit.amount_with_fee))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
return TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_BAD_REQUEST,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_AMOUNT_EXCEEDS_DENOMINATION_VALUE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_deposit.abs_time))
|
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_deposit.abs_time))
|
||||||
{
|
{
|
||||||
/* This denomination is past the expiration time for deposits */
|
/* This denomination is past the expiration time for deposits */
|
||||||
|
@ -183,7 +183,6 @@ melt_transaction (void *cls,
|
|||||||
if (rmc->zombie_required)
|
if (rmc->zombie_required)
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
TEH_plugin->rollback (TEH_plugin->cls);
|
|
||||||
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_BAD_REQUEST,
|
MHD_HTTP_BAD_REQUEST,
|
||||||
TALER_EC_EXCHANGE_MELT_COIN_EXPIRED_NO_ZOMBIE,
|
TALER_EC_EXCHANGE_MELT_COIN_EXPIRED_NO_ZOMBIE,
|
||||||
@ -193,7 +192,6 @@ melt_transaction (void *cls,
|
|||||||
if (! balance_ok)
|
if (! balance_ok)
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
TEH_plugin->rollback (TEH_plugin->cls);
|
|
||||||
*mhd_ret
|
*mhd_ret
|
||||||
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
||||||
connection,
|
connection,
|
||||||
|
@ -58,6 +58,11 @@ struct Coin
|
|||||||
* Deposit fee applicable for this coin.
|
* Deposit fee applicable for this coin.
|
||||||
*/
|
*/
|
||||||
struct TALER_Amount deposit_fee;
|
struct TALER_Amount deposit_fee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount to be put into the purse from this coin.
|
||||||
|
*/
|
||||||
|
struct TALER_Amount amount_minus_fee;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -147,22 +152,22 @@ reply_create_success (struct MHD_Connection *connection,
|
|||||||
{
|
{
|
||||||
struct TALER_ExchangePublicKeyP pub;
|
struct TALER_ExchangePublicKeyP pub;
|
||||||
struct TALER_ExchangeSignatureP sig;
|
struct TALER_ExchangeSignatureP sig;
|
||||||
// FIXME: define what exactly we sign over!
|
|
||||||
struct TALER_DepositConfirmationPS dc = {
|
|
||||||
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION),
|
|
||||||
.purpose.size = htonl (sizeof (dc)),
|
|
||||||
.h_contract_terms = pcc->h_contract_terms,
|
|
||||||
.purse_pub = *pcc->purse_pub
|
|
||||||
};
|
|
||||||
enum TALER_ErrorCode ec;
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
TALER_amount_hton (&dc.amount_without_fee,
|
|
||||||
&pcc->amount);
|
|
||||||
if (TALER_EC_NONE !=
|
if (TALER_EC_NONE !=
|
||||||
(ec = TEH_keys_exchange_sign (&dc,
|
(ec = TALER_exchange_online_purse_created_sign (
|
||||||
&pub,
|
&TEH_keys_exchange_sign_,
|
||||||
&sig)))
|
pcc->exchange_timestamp,
|
||||||
|
pcc->purse_expiration,
|
||||||
|
&pcc->amount,
|
||||||
|
&pcc->total_deposited,
|
||||||
|
pcc->purse_pub,
|
||||||
|
&pcc->merge_pub,
|
||||||
|
&pcc->h_contract_terms,
|
||||||
|
&pub,
|
||||||
|
&sig)))
|
||||||
{
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
return TALER_MHD_reply_with_ec (connection,
|
return TALER_MHD_reply_with_ec (connection,
|
||||||
ec,
|
ec,
|
||||||
NULL);
|
NULL);
|
||||||
@ -170,8 +175,10 @@ reply_create_success (struct MHD_Connection *connection,
|
|||||||
return TALER_MHD_REPLY_JSON_PACK (
|
return TALER_MHD_REPLY_JSON_PACK (
|
||||||
connection,
|
connection,
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
// GNUNET_JSON_pack_timestamp ("exchange_timestamp",
|
GNUNET_JSON_pack_amount ("total_deposited",
|
||||||
// pcc->exchange_timestamp),
|
&pcc->deposit_total),
|
||||||
|
GNUNET_JSON_pack_timestamp ("exchange_timestamp",
|
||||||
|
pcc->exchange_timestamp),
|
||||||
GNUNET_JSON_pack_data_auto ("exchange_sig",
|
GNUNET_JSON_pack_data_auto ("exchange_sig",
|
||||||
&sig),
|
&sig),
|
||||||
GNUNET_JSON_pack_data_auto ("exchange_pub",
|
GNUNET_JSON_pack_data_auto ("exchange_pub",
|
||||||
@ -199,14 +206,120 @@ create_transaction (void *cls,
|
|||||||
{
|
{
|
||||||
struct PurseCreateContext *pcc = cls;
|
struct PurseCreateContext *pcc = cls;
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
bool balance_ok;
|
bool in_conflict = true;
|
||||||
bool in_conflict;
|
|
||||||
|
|
||||||
// 1) create purse
|
/* 1) create purse */
|
||||||
// 2) deposit all coins
|
qs = TEH_plugin->insert_purse_request (TEH_plugin->cls,
|
||||||
// 3) if present, persist contract
|
&pcc->purse_pub,
|
||||||
// Also: nicely report errors...
|
&pcc->merge_pub,
|
||||||
qs = TEH_plugin->XXX (TEH_plugin->cls, ...);
|
pcc->purse_expiration,
|
||||||
|
&pcc->h_contract_terms,
|
||||||
|
pcc->min_age,
|
||||||
|
&pcc->amount,
|
||||||
|
&pcc->purse_sig,
|
||||||
|
&in_conflict);
|
||||||
|
if (qs < 0)
|
||||||
|
{
|
||||||
|
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
||||||
|
return qs;
|
||||||
|
TALER_LOG_WARNING (
|
||||||
|
"Failed to store create purse information in database\n");
|
||||||
|
*mhd_ret =
|
||||||
|
TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_GENERIC_DB_STORE_FAILED,
|
||||||
|
"purse create");
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
if (in_conflict)
|
||||||
|
{
|
||||||
|
struct TALER_PurseMergePublicKeyP merge_pub;
|
||||||
|
struct GNUNET_TIME_Timestamp purse_expiration;
|
||||||
|
struct TALER_PrivateContractHashP h_contract_terms;
|
||||||
|
struct TALER_Amount target_amount;
|
||||||
|
struct TALER_Amount balance;
|
||||||
|
struct TALER_PurseContractSignatureP purse_sig;
|
||||||
|
|
||||||
|
TEH_plugin->rollback (TEH_plugin->cls);
|
||||||
|
qs = TEH_plugin->select_purse_request (TEH_plugin->cls,
|
||||||
|
pcc->purse_pub,
|
||||||
|
&merge_pub,
|
||||||
|
&purse_expiration,
|
||||||
|
&h_contract_terms,
|
||||||
|
&target_amount,
|
||||||
|
&balance,
|
||||||
|
&purse_sig);
|
||||||
|
if (qs < 0)
|
||||||
|
{
|
||||||
|
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
|
||||||
|
TALER_LOG_WARNING ("Failed to fetch purse information from database\n");
|
||||||
|
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||||
|
"select purse request");
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
}
|
||||||
|
*mhd_ret
|
||||||
|
= return TALER_MHD_REPLY_JSON_PACK (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_CONFLICT,
|
||||||
|
TALER_JSON_pack_ec (
|
||||||
|
TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA),
|
||||||
|
GNUNET_JSON_pack_amount ("amount",
|
||||||
|
&amount),
|
||||||
|
GNUNET_JSON_pack_timestamp ("purse_expiration",
|
||||||
|
purse_expiration),
|
||||||
|
GNUNET_JSON_pack_data_auto ("purse_sig",
|
||||||
|
&purse_sig),
|
||||||
|
GNUNET_JSON_pack_data_auto ("h_contract_terms",
|
||||||
|
&h_contract_terms),
|
||||||
|
GNUNET_JSON_pack_data_auto ("merge_pub",
|
||||||
|
&merge_pub));
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
}
|
||||||
|
/* 2) deposit all coins */
|
||||||
|
for (unsigned int i = 0; i<pcc->num_coins; i++)
|
||||||
|
{
|
||||||
|
struct Coin *coin = &pcc->coins[i];
|
||||||
|
bool balance_ok = false;
|
||||||
|
|
||||||
|
qs = TEH_plugin->do_purse_deposit (TEH_plugin->cls,
|
||||||
|
&pcc->purse_pub,
|
||||||
|
&coin->cpi.coin_pub,
|
||||||
|
&coin->amount,
|
||||||
|
&coin->coin_sig,
|
||||||
|
&coin->amount_minus_fee,
|
||||||
|
&balance_ok);
|
||||||
|
if (qs < 0)
|
||||||
|
{
|
||||||
|
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
||||||
|
return qs;
|
||||||
|
TALER_LOG_WARNING (
|
||||||
|
"Failed to store purse deposit information in database\n");
|
||||||
|
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_GENERIC_DB_STORE_FAILED,
|
||||||
|
"purse create deposit");
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
if (! balance_ok)
|
||||||
|
{
|
||||||
|
*mhd_ret
|
||||||
|
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
||||||
|
connection,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS,
|
||||||
|
&coin->pci.coin_pub);
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 3) if present, persist contract */
|
||||||
|
in_conflict = true;
|
||||||
|
qs = TEH_plugin->insert_contract (TEH_plugin->cls,
|
||||||
|
&pcc->purse_pub,
|
||||||
|
&pcc->contract_pub,
|
||||||
|
pcc->econtract_size,
|
||||||
|
pcc->econtract,
|
||||||
|
&in_conflict);
|
||||||
if (qs < 0)
|
if (qs < 0)
|
||||||
{
|
{
|
||||||
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
||||||
@ -215,27 +328,21 @@ create_transaction (void *cls,
|
|||||||
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
TALER_EC_GENERIC_DB_STORE_FAILED,
|
TALER_EC_GENERIC_DB_STORE_FAILED,
|
||||||
"purse create");
|
"purse create contract");
|
||||||
return qs;
|
return qs;
|
||||||
}
|
}
|
||||||
if (in_conflict)
|
if (in_conflict)
|
||||||
{
|
{
|
||||||
TEH_plugin->rollback (TEH_plugin->cls);
|
/* FIXME-DESIGN: we have no proof that the
|
||||||
|
client is at fault here!
|
||||||
|
=> need 2nd client signature over the encrypted
|
||||||
|
contract (and ECDHE public key)!!! */
|
||||||
*mhd_ret
|
*mhd_ret
|
||||||
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
= TEH_RESPONSE_reply_with_error (
|
||||||
connection,
|
connection,
|
||||||
TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_CONTRACT,
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
&coin->pci.coin_pub);
|
TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_CONTRACT_STORED,
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
NULL);
|
||||||
}
|
|
||||||
if (! balance_ok)
|
|
||||||
{
|
|
||||||
TEH_plugin->rollback (TEH_plugin->cls);
|
|
||||||
*mhd_ret
|
|
||||||
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
|
||||||
connection,
|
|
||||||
TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS,
|
|
||||||
&coin->pci.coin_pub);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
}
|
}
|
||||||
return qs;
|
return qs;
|
||||||
@ -289,7 +396,7 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
TALER_wallet_purse_deposit_verify ("http://FIXME-URL",
|
TALER_wallet_purse_deposit_verify (TEH_base_url,
|
||||||
&pcc->purse_pub,
|
&pcc->purse_pub,
|
||||||
&pcc->amount,
|
&pcc->amount,
|
||||||
&coin->coin_pub,
|
&coin->coin_pub,
|
||||||
@ -301,7 +408,7 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
TALER_MHD_reply_with_error (connection,
|
TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_UNAUTHORIZED,
|
MHD_HTTP_UNAUTHORIZED,
|
||||||
TALER_EC_EXCHANGE_PURSE_CREATE_COIN_SIGNATURE_INVALID,
|
TALER_EC_EXCHANGE_PURSE_CREATE_COIN_SIGNATURE_INVALID,
|
||||||
NULL))
|
TEH_base_url))
|
||||||
? GNUNET_NO : GNUNET_SYSERR;
|
? GNUNET_NO : GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
/* check denomination exists and is valid */
|
/* check denomination exists and is valid */
|
||||||
@ -317,6 +424,18 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
GNUNET_JSON_parse_free (spec);
|
GNUNET_JSON_parse_free (spec);
|
||||||
return (MHD_YES == mret) ? GNUNET_NO : GNUNET_SYSERR:
|
return (MHD_YES == mret) ? GNUNET_NO : GNUNET_SYSERR:
|
||||||
}
|
}
|
||||||
|
if (0 > TALER_amount_cmp (&dk->meta.value,
|
||||||
|
&coin->amount))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
return (MHD_YES ==
|
||||||
|
TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_BAD_REQUEST,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_AMOUNT_EXCEEDS_DENOMINATION_VALUE,
|
||||||
|
NULL))
|
||||||
|
? GNUNET_NO : GNUNET_SYSERR;
|
||||||
|
}
|
||||||
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_deposit.abs_time))
|
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_deposit.abs_time))
|
||||||
{
|
{
|
||||||
/* This denomination is past the expiration time for deposits */
|
/* This denomination is past the expiration time for deposits */
|
||||||
@ -366,6 +485,20 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
coin->deposit_fee = dk->meta.fees.deposit;
|
coin->deposit_fee = dk->meta.fees.deposit;
|
||||||
|
if (0 < TALER_amount_cmp (&coin->deposit_fee,
|
||||||
|
&coin->amount))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
return TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_BAD_REQUEST,
|
||||||
|
TALER_EC_EXCHANGE_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
GNUNET_assert (0 <=
|
||||||
|
TALER_amount_subtact (&coin->amount_minus_fee,
|
||||||
|
&coin->amount,
|
||||||
|
&coin->deposit_fee));
|
||||||
/* check coin signature */
|
/* check coin signature */
|
||||||
switch (dk->denom_pub.cipher)
|
switch (dk->denom_pub.cipher)
|
||||||
{
|
{
|
||||||
@ -391,6 +524,17 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
NULL))
|
NULL))
|
||||||
? GNUNET_NO : GNUNET_SYSERR;
|
? GNUNET_NO : GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
if (0 >
|
||||||
|
TALER_amount_add (&pcc->deposit_total,
|
||||||
|
&pcc->deposit_total,
|
||||||
|
&coin->amount_minus_fee))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_GENERIC_FAILED_COMPUTE_AMOUNT,
|
||||||
|
"total deposit contribution");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
MHD_RESULT mhd_ret = MHD_NO;
|
MHD_RESULT mhd_ret = MHD_NO;
|
||||||
@ -425,10 +569,10 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
|
|
||||||
|
|
||||||
MHD_RESULT
|
MHD_RESULT
|
||||||
TEH_handler_purses_create (struct MHD_Connection *connection,
|
TEH_handler_purses_create (
|
||||||
const struct
|
struct MHD_Connection *connection,
|
||||||
TALER_PurseContractPublicKeyP *purse_pub,
|
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
const json_t *root)
|
const json_t *root)
|
||||||
{
|
{
|
||||||
struct PurseCreateContext pcc = {
|
struct PurseCreateContext pcc = {
|
||||||
.purse_pub = purse_pub,
|
.purse_pub = purse_pub,
|
||||||
@ -461,6 +605,7 @@ TEH_handler_purses_create (struct MHD_Connection *connection,
|
|||||||
&pcc.purse_expiration),
|
&pcc.purse_expiration),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
const struct TEH_GlobalFee *gf;
|
||||||
|
|
||||||
{
|
{
|
||||||
enum GNUNET_GenericReturnValue res;
|
enum GNUNET_GenericReturnValue res;
|
||||||
@ -479,7 +624,9 @@ TEH_handler_purses_create (struct MHD_Connection *connection,
|
|||||||
return MHD_YES; /* failure */
|
return MHD_YES; /* failure */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_set_zero (TEH_currency,
|
||||||
|
&pcc.deposit_total));
|
||||||
if (GNUNET_TIME_timestamp_cmp (pcc.purse_expiration,
|
if (GNUNET_TIME_timestamp_cmp (pcc.purse_expiration,
|
||||||
<,
|
<,
|
||||||
pcc.exchange_timestamp))
|
pcc.exchange_timestamp))
|
||||||
@ -511,6 +658,17 @@ TEH_handler_purses_create (struct MHD_Connection *connection,
|
|||||||
TALER_EC_EXCHANGE_GENERIC_PARAMETER_MALFORMED,
|
TALER_EC_EXCHANGE_GENERIC_PARAMETER_MALFORMED,
|
||||||
"deposits");
|
"deposits");
|
||||||
}
|
}
|
||||||
|
gf = TEH_keys_global_fee_by_time (TEH_keys_get_state (),
|
||||||
|
pcc.exchange_timestamp);
|
||||||
|
if (NULL == gf)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"Cannot create purse: global fees not configured!\n");
|
||||||
|
return TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_GLOBAL_FEES_MISSING,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
/* parse deposits */
|
/* parse deposits */
|
||||||
pcc.coins = GNUNET_new_array (struct Coin,
|
pcc.coins = GNUNET_new_array (struct Coin,
|
||||||
pcc.num_coins);
|
pcc.num_coins);
|
||||||
@ -531,8 +689,7 @@ TEH_handler_purses_create (struct MHD_Connection *connection,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: get purse_fee!
|
if (0 < TALER_amount_cmp (&gf->fees.purse,
|
||||||
if (0 < TALER_amount_cmp (&purse_fee,
|
|
||||||
&pcc.deposit_total))
|
&pcc.deposit_total))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
@ -543,7 +700,6 @@ TEH_handler_purses_create (struct MHD_Connection *connection,
|
|||||||
TALER_EC_EXCHANGE_CREATE_PURSE_NEGATIVE_VALUE_AFTER_FEE,
|
TALER_EC_EXCHANGE_CREATE_PURSE_NEGATIVE_VALUE_AFTER_FEE,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
|
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
@ -560,7 +716,7 @@ TEH_handler_purses_create (struct MHD_Connection *connection,
|
|||||||
GNUNET_free (pcc.coins);
|
GNUNET_free (pcc.coins);
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_UNAUTHORIZED,
|
MHD_HTTP_UNAUTHORIZED,
|
||||||
TALER_EC_EXCHANGE_PURSE_CREATE_COIN_SIGNATURE_INVALID,
|
TALER_EC_EXCHANGE_PURSE_CREATE_SIGNATURE_INVALID,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,6 +724,7 @@ TEH_handler_purses_create (struct MHD_Connection *connection,
|
|||||||
TEH_plugin->preflight (TEH_plugin->cls))
|
TEH_plugin->preflight (TEH_plugin->cls))
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
GNUNET_free (pcc.coins);
|
GNUNET_free (pcc.coins);
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
@ -256,7 +256,6 @@ withdraw_transaction (void *cls,
|
|||||||
}
|
}
|
||||||
if (! below_limit)
|
if (! below_limit)
|
||||||
{
|
{
|
||||||
TEH_plugin->rollback (TEH_plugin->cls);
|
|
||||||
*mhd_ret = TALER_MHD_REPLY_JSON_PACK (
|
*mhd_ret = TALER_MHD_REPLY_JSON_PACK (
|
||||||
connection,
|
connection,
|
||||||
MHD_HTTP_ACCEPTED,
|
MHD_HTTP_ACCEPTED,
|
||||||
|
@ -12668,6 +12668,10 @@ postgres_insert_partner (void *cls,
|
|||||||
* @param pub_ckey ephemeral key for DH used to encrypt the contract
|
* @param pub_ckey ephemeral key for DH used to encrypt the contract
|
||||||
* @param econtract_size number of bytes in @a econtract
|
* @param econtract_size number of bytes in @a econtract
|
||||||
* @param econtract the encrypted contract
|
* @param econtract the encrypted contract
|
||||||
|
* @param[out] in_conflict set to true if @a econtract
|
||||||
|
* conflicts with an existing contract;
|
||||||
|
* in this case, the return value will be
|
||||||
|
* #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure
|
||||||
* @return transaction status code
|
* @return transaction status code
|
||||||
*/
|
*/
|
||||||
static enum GNUNET_DB_QueryStatus
|
static enum GNUNET_DB_QueryStatus
|
||||||
@ -12675,7 +12679,8 @@ postgres_insert_contract (void *cls,
|
|||||||
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
const struct TALER_ContractDiffiePublicP *pub_ckey,
|
const struct TALER_ContractDiffiePublicP *pub_ckey,
|
||||||
size_t econtract_size,
|
size_t econtract_size,
|
||||||
const void *econtract)
|
const void *econtract,
|
||||||
|
bool *in_conflict)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
@ -12715,6 +12720,10 @@ postgres_select_contract (void *cls,
|
|||||||
* @param age_limit age limit to enforce for payments into the purse
|
* @param age_limit age limit to enforce for payments into the purse
|
||||||
* @param amount target amount (with fees) to be put into the purse
|
* @param amount target amount (with fees) to be put into the purse
|
||||||
* @param purse_sig signature with @a purse_pub's private key affirming the above
|
* @param purse_sig signature with @a purse_pub's private key affirming the above
|
||||||
|
* @param[out] in_conflict set to true if the meta data
|
||||||
|
* conflicts with an existing purse;
|
||||||
|
* in this case, the return value will be
|
||||||
|
* #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure
|
||||||
* @return transaction status code
|
* @return transaction status code
|
||||||
*/
|
*/
|
||||||
static enum GNUNET_DB_QueryStatus
|
static enum GNUNET_DB_QueryStatus
|
||||||
@ -12726,7 +12735,8 @@ postgres_insert_purse_request (
|
|||||||
const struct TALER_PrivateContractHashP *h_contract_terms,
|
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||||
uint32_t age_limit,
|
uint32_t age_limit,
|
||||||
const struct TALER_Amount *amount,
|
const struct TALER_Amount *amount,
|
||||||
const struct TALER_PurseContractSignatureP *purse_sig)
|
const struct TALER_PurseContractSignatureP *purse_sig,
|
||||||
|
bool *in_conflict)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
@ -12806,6 +12816,11 @@ postgres_select_purse_by_merge_pub (
|
|||||||
* @param coin_pub coin to deposit (debit)
|
* @param coin_pub coin to deposit (debit)
|
||||||
* @param amount fraction of the coin's value to deposit
|
* @param amount fraction of the coin's value to deposit
|
||||||
* @param coin_sig signature affirming the operation
|
* @param coin_sig signature affirming the operation
|
||||||
|
* @param amount_minus_fee amount to add to the purse
|
||||||
|
* @param[out] balance_ok set to false if the coin's
|
||||||
|
* remaining balance is below @a amount;
|
||||||
|
* in this case, the return value will be
|
||||||
|
* #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure
|
||||||
* @return transaction status code
|
* @return transaction status code
|
||||||
*/
|
*/
|
||||||
static enum GNUNET_DB_QueryStatus
|
static enum GNUNET_DB_QueryStatus
|
||||||
@ -12814,7 +12829,9 @@ postgres_do_purse_deposit (
|
|||||||
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
const struct TALER_Amount *amount,
|
const struct TALER_Amount *amount,
|
||||||
const struct TALER_CoinSpendSignatureP *coin_sig)
|
const struct TALER_CoinSpendSignatureP *coin_sig,
|
||||||
|
const struct TALER_Amount *amount_minus_fee,
|
||||||
|
bool *balance_ok)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
@ -3811,6 +3811,33 @@ TALER_exchange_online_reserve_closed_verify (
|
|||||||
const struct TALER_ExchangeSignatureP *sig);
|
const struct TALER_ExchangeSignatureP *sig);
|
||||||
|
|
||||||
|
|
||||||
|
enum TALER_ErrorCode
|
||||||
|
TALER_exchange_online_purse_created_sign (
|
||||||
|
TALER_ExchangeSignCallback scb,
|
||||||
|
struct GNUNET_TIME_Timestamp exchange_time,
|
||||||
|
struct GNUNET_TIME_Timestamp purse_expiration,
|
||||||
|
const struct TALER_Amount *amount_without_fee,
|
||||||
|
const struct TALER_Amount *total_deposited,
|
||||||
|
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
|
const struct TALER_PurseMergePublicKeyP *merge_pub,
|
||||||
|
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||||
|
struct TALER_ExchangePublicKeyP *pub,
|
||||||
|
struct TALER_ExchangeSignatureP *sig);
|
||||||
|
|
||||||
|
|
||||||
|
enum GNUNET_GenericReturnValue
|
||||||
|
TALER_exchange_online_purse_created_verify (
|
||||||
|
struct GNUNET_TIME_Timestamp exchange_time,
|
||||||
|
struct GNUNET_TIME_Timestamp purse_expiration,
|
||||||
|
const struct TALER_Amount *amount_without_fee,
|
||||||
|
const struct TALER_Amount *total_deposited,
|
||||||
|
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
|
const struct TALER_PurseMergePublicKeyP *merge_pub,
|
||||||
|
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||||
|
const struct TALER_ExchangePublicKeyP *pub,
|
||||||
|
const struct TALER_ExchangeSignatureP *sig);
|
||||||
|
|
||||||
|
|
||||||
/* ********************* offline signing ************************** */
|
/* ********************* offline signing ************************** */
|
||||||
|
|
||||||
|
|
||||||
|
@ -4389,6 +4389,10 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
* @param pub_ckey ephemeral key for DH used to encrypt the contract
|
* @param pub_ckey ephemeral key for DH used to encrypt the contract
|
||||||
* @param econtract_size number of bytes in @a econtract
|
* @param econtract_size number of bytes in @a econtract
|
||||||
* @param econtract the encrypted contract
|
* @param econtract the encrypted contract
|
||||||
|
* @param[out] in_conflict set to true if @a econtract
|
||||||
|
* conflicts with an existing contract;
|
||||||
|
* in this case, the return value will be
|
||||||
|
* #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure
|
||||||
* @return transaction status code
|
* @return transaction status code
|
||||||
*/
|
*/
|
||||||
enum GNUNET_DB_QueryStatus
|
enum GNUNET_DB_QueryStatus
|
||||||
@ -4396,7 +4400,8 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
const struct TALER_ContractDiffiePublicP *pub_ckey,
|
const struct TALER_ContractDiffiePublicP *pub_ckey,
|
||||||
size_t econtract_size,
|
size_t econtract_size,
|
||||||
const void *econtract);
|
const void *econtract,
|
||||||
|
bool *in_conflict);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4428,6 +4433,10 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
* @param age_limit age limit to enforce for payments into the purse
|
* @param age_limit age limit to enforce for payments into the purse
|
||||||
* @param amount target amount (with fees) to be put into the purse
|
* @param amount target amount (with fees) to be put into the purse
|
||||||
* @param purse_sig signature with @a purse_pub's private key affirming the above
|
* @param purse_sig signature with @a purse_pub's private key affirming the above
|
||||||
|
* @param[out] in_conflict set to true if the meta data
|
||||||
|
* conflicts with an existing purse;
|
||||||
|
* in this case, the return value will be
|
||||||
|
* #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure
|
||||||
* @return transaction status code
|
* @return transaction status code
|
||||||
*/
|
*/
|
||||||
enum GNUNET_DB_QueryStatus
|
enum GNUNET_DB_QueryStatus
|
||||||
@ -4439,7 +4448,8 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
const struct TALER_PrivateContractHashP *h_contract_terms,
|
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||||
uint32_t age_limit,
|
uint32_t age_limit,
|
||||||
const struct TALER_Amount *amount,
|
const struct TALER_Amount *amount,
|
||||||
const struct TALER_PurseContractSignatureP *purse_sig);
|
const struct TALER_PurseContractSignatureP *purse_sig,
|
||||||
|
bool *in_conflict);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4507,6 +4517,11 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
* @param coin_pub coin to deposit (debit)
|
* @param coin_pub coin to deposit (debit)
|
||||||
* @param amount fraction of the coin's value to deposit
|
* @param amount fraction of the coin's value to deposit
|
||||||
* @param coin_sig signature affirming the operation
|
* @param coin_sig signature affirming the operation
|
||||||
|
* @param amount_minus_fee amount to add to the purse
|
||||||
|
* @param[out] balance_ok set to false if the coin's
|
||||||
|
* remaining balance is below @a amount;
|
||||||
|
* in this case, the return value will be
|
||||||
|
* #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure
|
||||||
* @return transaction status code
|
* @return transaction status code
|
||||||
*/
|
*/
|
||||||
enum GNUNET_DB_QueryStatus
|
enum GNUNET_DB_QueryStatus
|
||||||
@ -4515,7 +4530,9 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
const struct TALER_Amount *amount,
|
const struct TALER_Amount *amount,
|
||||||
const struct TALER_CoinSpendSignatureP *coin_sig);
|
const struct TALER_CoinSpendSignatureP *coin_sig,
|
||||||
|
const struct TALER_Amount *amount_minus_fee,
|
||||||
|
bool *balance_ok);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -176,6 +176,11 @@
|
|||||||
*/
|
*/
|
||||||
#define TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS 1044
|
#define TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS 1044
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signature by which the exchange affirms that a purse
|
||||||
|
* was created with a certain amount deposited into it.
|
||||||
|
*/
|
||||||
|
#define TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION 1045
|
||||||
|
|
||||||
/**********************/
|
/**********************/
|
||||||
/* Auditor signatures */
|
/* Auditor signatures */
|
||||||
|
@ -1261,4 +1261,117 @@ TALER_exchange_online_reserve_closed_verify (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GNUNET_NETWORK_STRUCT_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response by which the exchange affirms that it has
|
||||||
|
* received funds deposited into a purse.
|
||||||
|
*/
|
||||||
|
struct TALER_PurseCreateDepositConfirmationPS
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When did the exchange receive the deposits.
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_TimestampNBO exchange_time;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When will the purse expire?
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_TimestampNBO purse_expiration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How much should the purse ultimately contain.
|
||||||
|
*/
|
||||||
|
struct TALER_AmountNBO amount_without_fee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How much was deposited so far.
|
||||||
|
*/
|
||||||
|
struct TALER_AmountNBO total_deposited;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key of the purse.
|
||||||
|
*/
|
||||||
|
struct TALER_PurseContractPublicKeyP purse_pub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key of the merge capability.
|
||||||
|
*/
|
||||||
|
struct TALER_PurseMergePublicKeyP merge_pub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash of the contract of the purse.
|
||||||
|
*/
|
||||||
|
struct TALER_PrivateContractHashP h_contract_terms;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
GNUNET_NETWORK_STRUCT_END
|
||||||
|
|
||||||
|
|
||||||
|
enum TALER_ErrorCode
|
||||||
|
TALER_exchange_online_purse_created_sign (
|
||||||
|
TALER_ExchangeSignCallback scb,
|
||||||
|
struct GNUNET_TIME_Timestamp exchange_time,
|
||||||
|
struct GNUNET_TIME_Timestamp purse_expiration,
|
||||||
|
const struct TALER_Amount *amount_without_fee,
|
||||||
|
const struct TALER_Amount *total_deposited,
|
||||||
|
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
|
const struct TALER_PurseMergePublicKeyP *merge_pub,
|
||||||
|
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||||
|
struct TALER_ExchangePublicKeyP *pub,
|
||||||
|
struct TALER_ExchangeSignatureP *sig)
|
||||||
|
{
|
||||||
|
struct TALER_PurseCreateDepositConfirmationPS dc = {
|
||||||
|
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION),
|
||||||
|
.purpose.size = htonl (sizeof (dc)),
|
||||||
|
.h_contract_terms = *h_contract_terms,
|
||||||
|
.purse_pub = *purse_pub,
|
||||||
|
.merge_pub = *merge_pub,
|
||||||
|
.purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
|
||||||
|
.exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
|
||||||
|
};
|
||||||
|
|
||||||
|
return scb (&dc.purpose,
|
||||||
|
pub,
|
||||||
|
sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum GNUNET_GenericReturnValue
|
||||||
|
TALER_exchange_online_purse_created_verify (
|
||||||
|
struct GNUNET_TIME_Timestamp exchange_time,
|
||||||
|
struct GNUNET_TIME_Timestamp purse_expiration,
|
||||||
|
const struct TALER_Amount *amount_without_fee,
|
||||||
|
const struct TALER_Amount *total_deposited,
|
||||||
|
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
|
const struct TALER_PurseMergePublicKeyP *merge_pub,
|
||||||
|
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||||
|
const struct TALER_ExchangePublicKeyP *pub,
|
||||||
|
const struct TALER_ExchangeSignatureP *sig)
|
||||||
|
{
|
||||||
|
struct TALER_PurseCreateDepositConfirmationPS dc = {
|
||||||
|
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION),
|
||||||
|
.purpose.size = htonl (sizeof (dc)),
|
||||||
|
.h_contract_terms = *h_contract_terms,
|
||||||
|
.purse_pub = *purse_pub,
|
||||||
|
.merge_pub = *merge_pub,
|
||||||
|
.purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
|
||||||
|
.exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
|
||||||
|
};
|
||||||
|
|
||||||
|
return
|
||||||
|
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION,
|
||||||
|
&dc,
|
||||||
|
&sig->eddsa_signature,
|
||||||
|
&pub->eddsa_pub);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end of exchange_signatures.c */
|
/* end of exchange_signatures.c */
|
||||||
|
Loading…
Reference in New Issue
Block a user