adapt to latest GNUnet API: GNUNET_JSON_spec_mark_optional() changed
This commit is contained in:
parent
7191641406
commit
f3a4b00907
@ -1 +1 @@
|
|||||||
Subproject commit 8e5eda9507f42af6a394d218a65082b3294855b7
|
Subproject commit 313216ee11fe604d39ea5f1b71b1ad96a60391d9
|
@ -103,6 +103,7 @@ taler_exchange_httpd_SOURCES = \
|
|||||||
taler-exchange-httpd_melt.c taler-exchange-httpd_melt.h \
|
taler-exchange-httpd_melt.c taler-exchange-httpd_melt.h \
|
||||||
taler-exchange-httpd_metrics.c taler-exchange-httpd_metrics.h \
|
taler-exchange-httpd_metrics.c taler-exchange-httpd_metrics.h \
|
||||||
taler-exchange-httpd_mhd.c taler-exchange-httpd_mhd.h \
|
taler-exchange-httpd_mhd.c taler-exchange-httpd_mhd.h \
|
||||||
|
taler-exchange-httpd_purses_create.c taler-exchange-httpd_purses_create.h \
|
||||||
taler-exchange-httpd_recoup.c taler-exchange-httpd_recoup.h \
|
taler-exchange-httpd_recoup.c taler-exchange-httpd_recoup.h \
|
||||||
taler-exchange-httpd_recoup-refresh.c taler-exchange-httpd_recoup-refresh.h \
|
taler-exchange-httpd_recoup-refresh.c taler-exchange-httpd_recoup-refresh.h \
|
||||||
taler-exchange-httpd_refreshes_reveal.c taler-exchange-httpd_refreshes_reveal.h \
|
taler-exchange-httpd_refreshes_reveal.c taler-exchange-httpd_refreshes_reveal.h \
|
||||||
|
@ -224,14 +224,16 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
|||||||
&deposit.h_contract_terms),
|
&deposit.h_contract_terms),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
||||||
&deposit.coin.h_age_commitment)),
|
&deposit.coin.h_age_commitment),
|
||||||
|
&deposit.coin.no_age_commitment),
|
||||||
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
||||||
&deposit.csig),
|
&deposit.csig),
|
||||||
GNUNET_JSON_spec_timestamp ("timestamp",
|
GNUNET_JSON_spec_timestamp ("timestamp",
|
||||||
&deposit.timestamp),
|
&deposit.timestamp),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_timestamp ("refund_deadline",
|
GNUNET_JSON_spec_timestamp ("refund_deadline",
|
||||||
&deposit.refund_deadline)),
|
&deposit.refund_deadline),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
|
GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
|
||||||
&deposit.wire_deadline),
|
&deposit.wire_deadline),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
|
@ -120,9 +120,9 @@ struct MeltContext
|
|||||||
bool coin_is_dirty;
|
bool coin_is_dirty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if @e rms is set.
|
* True if @e rms is missing.
|
||||||
*/
|
*/
|
||||||
bool have_rms;
|
bool no_rms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -161,9 +161,9 @@ melt_transaction (void *cls,
|
|||||||
|
|
||||||
if (0 >
|
if (0 >
|
||||||
(qs = TEH_plugin->do_melt (TEH_plugin->cls,
|
(qs = TEH_plugin->do_melt (TEH_plugin->cls,
|
||||||
rmc->have_rms
|
rmc->no_rms
|
||||||
? &rmc->rms
|
? NULL
|
||||||
: NULL,
|
: &rmc->rms,
|
||||||
&rmc->refresh_session,
|
&rmc->refresh_session,
|
||||||
rmc->known_coin_id,
|
rmc->known_coin_id,
|
||||||
&rmc->zombie_required,
|
&rmc->zombie_required,
|
||||||
@ -443,7 +443,8 @@ TEH_handler_melt (struct MHD_Connection *connection,
|
|||||||
&rmc.refresh_session.coin.denom_pub_hash),
|
&rmc.refresh_session.coin.denom_pub_hash),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("age_commitment_hash",
|
GNUNET_JSON_spec_fixed_auto ("age_commitment_hash",
|
||||||
&rmc.refresh_session.coin.h_age_commitment)),
|
&rmc.refresh_session.coin.h_age_commitment),
|
||||||
|
&rmc.refresh_session.coin.no_age_commitment),
|
||||||
GNUNET_JSON_spec_fixed_auto ("confirm_sig",
|
GNUNET_JSON_spec_fixed_auto ("confirm_sig",
|
||||||
&rmc.refresh_session.coin_sig),
|
&rmc.refresh_session.coin_sig),
|
||||||
TALER_JSON_spec_amount ("value_with_fee",
|
TALER_JSON_spec_amount ("value_with_fee",
|
||||||
@ -453,7 +454,8 @@ TEH_handler_melt (struct MHD_Connection *connection,
|
|||||||
&rmc.refresh_session.rc),
|
&rmc.refresh_session.rc),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("rms",
|
GNUNET_JSON_spec_fixed_auto ("rms",
|
||||||
&rmc.rms)),
|
&rmc.rms),
|
||||||
|
&rmc.no_rms),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -469,9 +471,6 @@ TEH_handler_melt (struct MHD_Connection *connection,
|
|||||||
return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES;
|
return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
rmc.have_rms = (NULL != json_object_get (root,
|
|
||||||
"rms"));
|
|
||||||
|
|
||||||
{
|
{
|
||||||
MHD_RESULT res;
|
MHD_RESULT res;
|
||||||
|
|
||||||
|
@ -35,7 +35,8 @@ enum TEH_MetricTypeRequest
|
|||||||
TEH_MT_REQUEST_DEPOSIT = 1,
|
TEH_MT_REQUEST_DEPOSIT = 1,
|
||||||
TEH_MT_REQUEST_WITHDRAW = 2,
|
TEH_MT_REQUEST_WITHDRAW = 2,
|
||||||
TEH_MT_REQUEST_MELT = 3,
|
TEH_MT_REQUEST_MELT = 3,
|
||||||
TEH_MT_REQUEST_COUNT = 4 /* MUST BE LAST! */
|
TEH_MT_REQUEST_PURSE_CREATE = 4,
|
||||||
|
TEH_MT_REQUEST_COUNT = 5 /* MUST BE LAST! */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,6 +63,11 @@ struct Coin
|
|||||||
* Amount to be put into the purse from this coin.
|
* Amount to be put into the purse from this coin.
|
||||||
*/
|
*/
|
||||||
struct TALER_Amount amount_minus_fee;
|
struct TALER_Amount amount_minus_fee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the coin in known_coins.
|
||||||
|
*/
|
||||||
|
uint64_t known_coin_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -141,6 +146,10 @@ struct PurseCreateContext
|
|||||||
*/
|
*/
|
||||||
unsigned int num_coins;
|
unsigned int num_coins;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum age for deposits into this purse.
|
||||||
|
*/
|
||||||
|
uint32_t min_age;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -165,7 +174,7 @@ reply_create_success (struct MHD_Connection *connection,
|
|||||||
pcc->exchange_timestamp,
|
pcc->exchange_timestamp,
|
||||||
pcc->purse_expiration,
|
pcc->purse_expiration,
|
||||||
&pcc->amount,
|
&pcc->amount,
|
||||||
&pcc->total_deposited,
|
&pcc->deposit_total,
|
||||||
pcc->purse_pub,
|
pcc->purse_pub,
|
||||||
&pcc->merge_pub,
|
&pcc->merge_pub,
|
||||||
&pcc->h_contract_terms,
|
&pcc->h_contract_terms,
|
||||||
@ -180,7 +189,7 @@ 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_amount ("total_deposited",
|
TALER_JSON_pack_amount ("total_deposited",
|
||||||
&pcc->deposit_total),
|
&pcc->deposit_total),
|
||||||
GNUNET_JSON_pack_timestamp ("exchange_timestamp",
|
GNUNET_JSON_pack_timestamp ("exchange_timestamp",
|
||||||
pcc->exchange_timestamp),
|
pcc->exchange_timestamp),
|
||||||
@ -215,7 +224,7 @@ create_transaction (void *cls,
|
|||||||
|
|
||||||
/* 1) create purse */
|
/* 1) create purse */
|
||||||
qs = TEH_plugin->insert_purse_request (TEH_plugin->cls,
|
qs = TEH_plugin->insert_purse_request (TEH_plugin->cls,
|
||||||
&pcc->purse_pub,
|
pcc->purse_pub,
|
||||||
&pcc->merge_pub,
|
&pcc->merge_pub,
|
||||||
pcc->purse_expiration,
|
pcc->purse_expiration,
|
||||||
&pcc->h_contract_terms,
|
&pcc->h_contract_terms,
|
||||||
@ -244,6 +253,7 @@ create_transaction (void *cls,
|
|||||||
struct TALER_Amount target_amount;
|
struct TALER_Amount target_amount;
|
||||||
struct TALER_Amount balance;
|
struct TALER_Amount balance;
|
||||||
struct TALER_PurseContractSignatureP purse_sig;
|
struct TALER_PurseContractSignatureP purse_sig;
|
||||||
|
uint32_t min_age;
|
||||||
|
|
||||||
TEH_plugin->rollback (TEH_plugin->cls);
|
TEH_plugin->rollback (TEH_plugin->cls);
|
||||||
qs = TEH_plugin->select_purse_request (TEH_plugin->cls,
|
qs = TEH_plugin->select_purse_request (TEH_plugin->cls,
|
||||||
@ -251,6 +261,7 @@ create_transaction (void *cls,
|
|||||||
&merge_pub,
|
&merge_pub,
|
||||||
&purse_expiration,
|
&purse_expiration,
|
||||||
&h_contract_terms,
|
&h_contract_terms,
|
||||||
|
&min_age,
|
||||||
&target_amount,
|
&target_amount,
|
||||||
&balance,
|
&balance,
|
||||||
&purse_sig);
|
&purse_sig);
|
||||||
@ -270,8 +281,10 @@ create_transaction (void *cls,
|
|||||||
MHD_HTTP_CONFLICT,
|
MHD_HTTP_CONFLICT,
|
||||||
TALER_JSON_pack_ec (
|
TALER_JSON_pack_ec (
|
||||||
TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA),
|
TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA),
|
||||||
GNUNET_JSON_pack_amount ("amount",
|
TALER_JSON_pack_amount ("amount",
|
||||||
&amount),
|
&target_amount),
|
||||||
|
GNUNET_JSON_pack_uint64 ("min_age",
|
||||||
|
min_age),
|
||||||
GNUNET_JSON_pack_timestamp ("purse_expiration",
|
GNUNET_JSON_pack_timestamp ("purse_expiration",
|
||||||
purse_expiration),
|
purse_expiration),
|
||||||
GNUNET_JSON_pack_data_auto ("purse_sig",
|
GNUNET_JSON_pack_data_auto ("purse_sig",
|
||||||
@ -287,15 +300,17 @@ create_transaction (void *cls,
|
|||||||
{
|
{
|
||||||
struct Coin *coin = &pcc->coins[i];
|
struct Coin *coin = &pcc->coins[i];
|
||||||
bool balance_ok = false;
|
bool balance_ok = false;
|
||||||
|
bool conflict = true;
|
||||||
|
|
||||||
qs = TEH_plugin->do_purse_deposit (TEH_plugin->cls,
|
qs = TEH_plugin->do_purse_deposit (TEH_plugin->cls,
|
||||||
&pcc->purse_pub,
|
pcc->purse_pub,
|
||||||
&coin->cpi.coin_pub,
|
&coin->cpi.coin_pub,
|
||||||
&coin->amount,
|
&coin->amount,
|
||||||
&coin->coin_sig,
|
&coin->coin_sig,
|
||||||
&coin->amount_minus_fee,
|
&coin->amount_minus_fee,
|
||||||
&balance_ok);
|
&balance_ok,
|
||||||
if (qs < 0)
|
&conflict);
|
||||||
|
if (qs <= 0)
|
||||||
{
|
{
|
||||||
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
||||||
return qs;
|
return qs;
|
||||||
@ -313,14 +328,58 @@ create_transaction (void *cls,
|
|||||||
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
||||||
connection,
|
connection,
|
||||||
TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS,
|
TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS,
|
||||||
&coin->pci.coin_pub);
|
&coin->cpi.coin_pub);
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
}
|
||||||
|
if (conflict)
|
||||||
|
{
|
||||||
|
struct TALER_Amount amount;
|
||||||
|
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||||
|
struct TALER_CoinSpendSignatureP coin_sig;
|
||||||
|
char *partner_url = NULL;
|
||||||
|
|
||||||
|
TEH_plugin->rollback (TEH_plugin->cls);
|
||||||
|
qs = TEH_plugin->get_purse_deposit (TEH_plugin->cls,
|
||||||
|
pcc->purse_pub,
|
||||||
|
&coin->cpi.coin_pub,
|
||||||
|
&amount,
|
||||||
|
&coin_sig,
|
||||||
|
&partner_url);
|
||||||
|
if (qs < 0)
|
||||||
|
{
|
||||||
|
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
|
||||||
|
TALER_LOG_WARNING (
|
||||||
|
"Failed to fetch purse deposit information from database\n");
|
||||||
|
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||||
|
"get purse deposit");
|
||||||
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*mhd_ret
|
||||||
|
= TALER_MHD_REPLY_JSON_PACK (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_CONFLICT,
|
||||||
|
TALER_JSON_pack_ec (
|
||||||
|
TALER_EC_EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA),
|
||||||
|
GNUNET_JSON_pack_data_auto ("coin_pub",
|
||||||
|
&coin_pub),
|
||||||
|
GNUNET_JSON_pack_data_auto ("coin_sig",
|
||||||
|
&coin_sig),
|
||||||
|
GNUNET_JSON_pack_allow_null (
|
||||||
|
GNUNET_JSON_pack_string ("partner_url",
|
||||||
|
partner_url)),
|
||||||
|
TALER_JSON_pack_amount ("amount",
|
||||||
|
&amount));
|
||||||
|
GNUNET_free (partner_url);
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* 3) if present, persist contract */
|
/* 3) if present, persist contract */
|
||||||
in_conflict = true;
|
in_conflict = true;
|
||||||
qs = TEH_plugin->insert_contract (TEH_plugin->cls,
|
qs = TEH_plugin->insert_contract (TEH_plugin->cls,
|
||||||
&pcc->purse_pub,
|
pcc->purse_pub,
|
||||||
&pcc->contract_pub,
|
&pcc->contract_pub,
|
||||||
pcc->econtract_size,
|
pcc->econtract_size,
|
||||||
pcc->econtract,
|
pcc->econtract,
|
||||||
@ -345,8 +404,8 @@ create_transaction (void *cls,
|
|||||||
void *econtract;
|
void *econtract;
|
||||||
struct GNUNET_HashCode h_econtract;
|
struct GNUNET_HashCode h_econtract;
|
||||||
|
|
||||||
qs = select_contract (cls,
|
qs = TEH_plugin->select_contract (TEH_plugin->cls,
|
||||||
&pcc->purse_pub,
|
pcc->purse_pub,
|
||||||
&pub_ckey,
|
&pub_ckey,
|
||||||
&econtract_sig,
|
&econtract_sig,
|
||||||
&econtract_size,
|
&econtract_size,
|
||||||
@ -411,7 +470,7 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
&coin->cpi.denom_sig),
|
&coin->cpi.denom_sig),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
||||||
&coin->cpi.h_age_commitment)),
|
&coin->cpi.h_age_commitment),
|
||||||
&coin->cpi.no_age_commitment),
|
&coin->cpi.no_age_commitment),
|
||||||
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
||||||
&coin->coin_sig),
|
&coin->coin_sig),
|
||||||
@ -432,10 +491,10 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
TALER_wallet_purse_deposit_verify (TEH_base_url,
|
TALER_wallet_purse_deposit_verify (TEH_base_url,
|
||||||
&pcc->purse_pub,
|
pcc->purse_pub,
|
||||||
&pcc->amount,
|
&pcc->amount,
|
||||||
&coin->coin_pub,
|
&coin->cpi.coin_pub,
|
||||||
&coin->csig))
|
&coin->coin_sig))
|
||||||
{
|
{
|
||||||
TALER_LOG_WARNING ("Invalid signature on /purses/$PID/create request\n");
|
TALER_LOG_WARNING ("Invalid signature on /purses/$PID/create request\n");
|
||||||
GNUNET_JSON_parse_free (spec);
|
GNUNET_JSON_parse_free (spec);
|
||||||
@ -451,13 +510,13 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
struct TEH_DenominationKey *dk;
|
struct TEH_DenominationKey *dk;
|
||||||
MHD_RESULT mret;
|
MHD_RESULT mret;
|
||||||
|
|
||||||
dk = TEH_keys_denomination_by_hash (&coin->denom_pub_hash,
|
dk = TEH_keys_denomination_by_hash (&coin->cpi.denom_pub_hash,
|
||||||
connection,
|
connection,
|
||||||
&mret);
|
&mret);
|
||||||
if (NULL == dk)
|
if (NULL == dk)
|
||||||
{
|
{
|
||||||
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,
|
if (0 > TALER_amount_cmp (&dk->meta.value,
|
||||||
&coin->amount))
|
&coin->amount))
|
||||||
@ -478,10 +537,10 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
return (MHD_YES ==
|
return (MHD_YES ==
|
||||||
TEH_RESPONSE_reply_expired_denom_pub_hash (
|
TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||||
connection,
|
connection,
|
||||||
&coin->denom_pub_hash,
|
&coin->cpi.denom_pub_hash,
|
||||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||||
"PURSE CREATE"))
|
"PURSE CREATE"))
|
||||||
? GNUNET_NO : GNUNET_SYSERR:
|
? GNUNET_NO : GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
|
if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
|
||||||
{
|
{
|
||||||
@ -490,7 +549,7 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
return (MHD_YES ==
|
return (MHD_YES ==
|
||||||
TEH_RESPONSE_reply_expired_denom_pub_hash (
|
TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||||
connection,
|
connection,
|
||||||
&coin->denom_pub_hash,
|
&coin->cpi.denom_pub_hash,
|
||||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
|
||||||
"PURSE CREATE"))
|
"PURSE CREATE"))
|
||||||
? GNUNET_NO : GNUNET_SYSERR;
|
? GNUNET_NO : GNUNET_SYSERR;
|
||||||
@ -502,12 +561,12 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
return (MHD_YES ==
|
return (MHD_YES ==
|
||||||
TEH_RESPONSE_reply_expired_denom_pub_hash (
|
TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||||
connection,
|
connection,
|
||||||
&deposit.coin.denom_pub_hash,
|
&coin->cpi.denom_pub_hash,
|
||||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
|
||||||
"PURSE CREATE"))
|
"PURSE CREATE"))
|
||||||
? GNUNET_NO : GNUNET_SYSERR;
|
? GNUNET_NO : GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
if (dk->denom_pub.cipher != deposit.coin.denom_sig.cipher)
|
if (dk->denom_pub.cipher != coin->cpi.denom_sig.cipher)
|
||||||
{
|
{
|
||||||
/* denomination cipher and denomination signature cipher not the same */
|
/* denomination cipher and denomination signature cipher not the same */
|
||||||
GNUNET_JSON_parse_free (spec);
|
GNUNET_JSON_parse_free (spec);
|
||||||
@ -531,7 +590,7 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
GNUNET_assert (0 <=
|
GNUNET_assert (0 <=
|
||||||
TALER_amount_subtact (&coin->amount_minus_fee,
|
TALER_amount_subtract (&coin->amount_minus_fee,
|
||||||
&coin->amount,
|
&coin->amount,
|
||||||
&coin->deposit_fee));
|
&coin->deposit_fee));
|
||||||
/* check coin signature */
|
/* check coin signature */
|
||||||
@ -547,7 +606,7 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (GNUNET_YES !=
|
if (GNUNET_YES !=
|
||||||
TALER_test_coin_valid (&deposit.coin,
|
TALER_test_coin_valid (&coin->cpi,
|
||||||
&dk->denom_pub))
|
&dk->denom_pub))
|
||||||
{
|
{
|
||||||
TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
|
TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
|
||||||
@ -578,9 +637,9 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
/* make sure coin is 'known' in database */
|
/* make sure coin is 'known' in database */
|
||||||
for (unsigned int tries = 0; tries<MAX_TRANSACTION_COMMIT_RETRIES; tries++)
|
for (unsigned int tries = 0; tries<MAX_TRANSACTION_COMMIT_RETRIES; tries++)
|
||||||
{
|
{
|
||||||
qs = TEH_make_coin_known (&deposit.coin,
|
qs = TEH_make_coin_known (&coin->cpi,
|
||||||
connection,
|
connection,
|
||||||
&pcc.known_coin_id,
|
&coin->known_coin_id,
|
||||||
&mhd_ret);
|
&mhd_ret);
|
||||||
/* no transaction => no serialization failures should be possible */
|
/* no transaction => no serialization failures should be possible */
|
||||||
if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
|
if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
|
||||||
@ -611,7 +670,7 @@ TEH_handler_purses_create (
|
|||||||
{
|
{
|
||||||
struct PurseCreateContext pcc = {
|
struct PurseCreateContext pcc = {
|
||||||
.purse_pub = purse_pub,
|
.purse_pub = purse_pub,
|
||||||
.exchange_timestamp = GNUNET_TIME_timestamp_get ();
|
.exchange_timestamp = GNUNET_TIME_timestamp_get ()
|
||||||
};
|
};
|
||||||
json_t *deposits;
|
json_t *deposits;
|
||||||
json_t *deposit;
|
json_t *deposit;
|
||||||
@ -623,15 +682,18 @@ TEH_handler_purses_create (
|
|||||||
GNUNET_JSON_spec_uint32 ("min_age",
|
GNUNET_JSON_spec_uint32 ("min_age",
|
||||||
&pcc.min_age),
|
&pcc.min_age),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_var_size ("econtract",
|
GNUNET_JSON_spec_varsize ("econtract",
|
||||||
&pcc.econtract,
|
&pcc.econtract,
|
||||||
&pcc.ecotract_size)),
|
&pcc.econtract_size),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("econtract_sig",
|
GNUNET_JSON_spec_fixed_auto ("econtract_sig",
|
||||||
&pcc.econtract_sig)),
|
&pcc.econtract_sig),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("contract_pub",
|
GNUNET_JSON_spec_fixed_auto ("contract_pub",
|
||||||
&pcc.contract_pub)),
|
&pcc.contract_pub),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_fixed_auto ("merge_pub",
|
GNUNET_JSON_spec_fixed_auto ("merge_pub",
|
||||||
&pcc.merge_pub),
|
&pcc.merge_pub),
|
||||||
GNUNET_JSON_spec_fixed_auto ("purse_sig",
|
GNUNET_JSON_spec_fixed_auto ("purse_sig",
|
||||||
@ -694,7 +756,7 @@ TEH_handler_purses_create (
|
|||||||
GNUNET_JSON_parse_free (spec);
|
GNUNET_JSON_parse_free (spec);
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_BAD_REQUEST,
|
MHD_HTTP_BAD_REQUEST,
|
||||||
TALER_EC_EXCHANGE_GENERIC_PARAMETER_MALFORMED,
|
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||||
"deposits");
|
"deposits");
|
||||||
}
|
}
|
||||||
gf = TEH_keys_global_fee_by_time (TEH_keys_get_state (),
|
gf = TEH_keys_global_fee_by_time (TEH_keys_get_state (),
|
||||||
@ -709,8 +771,8 @@ TEH_handler_purses_create (
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
/* parse deposits */
|
/* parse deposits */
|
||||||
pcc.coins = GNUNET_new_array (struct Coin,
|
pcc.coins = GNUNET_new_array (pcc.num_coins,
|
||||||
pcc.num_coins);
|
struct Coin);
|
||||||
json_array_foreach (deposits, idx, deposit)
|
json_array_foreach (deposits, idx, deposit)
|
||||||
{
|
{
|
||||||
enum GNUNET_GenericReturnValue res;
|
enum GNUNET_GenericReturnValue res;
|
||||||
@ -742,12 +804,12 @@ TEH_handler_purses_create (
|
|||||||
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
|
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
TALER_wallet_purse_create_verify (&pcc.purse_expiration,
|
TALER_wallet_purse_create_verify (pcc.purse_expiration,
|
||||||
&pcc.h_contract_terms,
|
&pcc.h_contract_terms,
|
||||||
&pcc.merge_pub,
|
&pcc.merge_pub,
|
||||||
pcc.min_age,
|
pcc.min_age,
|
||||||
&pcc.amount,
|
&pcc.amount,
|
||||||
&pcc.purse_pub,
|
pcc.purse_pub,
|
||||||
&pcc.purse_sig))
|
&pcc.purse_sig))
|
||||||
{
|
{
|
||||||
TALER_LOG_WARNING ("Invalid signature on /purses/$PID/create request\n");
|
TALER_LOG_WARNING ("Invalid signature on /purses/$PID/create request\n");
|
||||||
|
47
src/exchange/taler-exchange-httpd_purses_create.h
Normal file
47
src/exchange/taler-exchange-httpd_purses_create.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
This file is part of TALER
|
||||||
|
Copyright (C) 2022 Taler Systems SA
|
||||||
|
|
||||||
|
TALER is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU Affero 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 Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License along with
|
||||||
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file taler-exchange-httpd_purses_create.h
|
||||||
|
* @brief Handle /purses/$PID/create requests
|
||||||
|
* @author Christian Grothoff
|
||||||
|
*/
|
||||||
|
#ifndef TALER_EXCHANGE_HTTPD_PURSES_CREATE_H
|
||||||
|
#define TALER_EXCHANGE_HTTPD_PURSES_CREATE_H
|
||||||
|
|
||||||
|
#include <gnunet/gnunet_util_lib.h>
|
||||||
|
#include <microhttpd.h>
|
||||||
|
#include "taler-exchange-httpd.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a "/purses/$PURSE_PUB/create" request. Parses the JSON, and, if
|
||||||
|
* successful, passes the JSON data to #create_transaction() to further check
|
||||||
|
* the details of the operation specified. If everything checks out, this
|
||||||
|
* will ultimately lead to the "purses create" being executed, or rejected.
|
||||||
|
*
|
||||||
|
* @param connection the MHD connection to handle
|
||||||
|
* @param purse_pub public key of the purse
|
||||||
|
* @param root uploaded JSON data
|
||||||
|
* @return MHD result code
|
||||||
|
*/
|
||||||
|
MHD_RESULT
|
||||||
|
TEH_handler_purses_create (struct MHD_Connection *connection,
|
||||||
|
const struct
|
||||||
|
TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
|
const json_t *root);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -390,10 +390,12 @@ TEH_handler_recoup_refresh (struct MHD_Connection *connection,
|
|||||||
&coin_sig),
|
&coin_sig),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
||||||
&coin.h_age_commitment)),
|
&coin.h_age_commitment),
|
||||||
|
&coin.no_age_commitment),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("cs_nonce",
|
GNUNET_JSON_spec_fixed_auto ("cs_nonce",
|
||||||
&nonce)),
|
&nonce),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -403,10 +403,12 @@ TEH_handler_recoup (struct MHD_Connection *connection,
|
|||||||
&coin_sig),
|
&coin_sig),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
||||||
&coin.h_age_commitment)),
|
&coin.h_age_commitment),
|
||||||
|
&coin.no_age_commitment),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("cs_nonce",
|
GNUNET_JSON_spec_fixed_auto ("cs_nonce",
|
||||||
&nonce)),
|
&nonce),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -132,9 +132,9 @@ struct RevealContext
|
|||||||
unsigned int num_fresh_coins;
|
unsigned int num_fresh_coins;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if @e rms was provided.
|
* True if @e rms was not provided.
|
||||||
*/
|
*/
|
||||||
bool have_rms;
|
bool no_rms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -337,9 +337,9 @@ check_commitment (struct RevealContext *rctx,
|
|||||||
}
|
}
|
||||||
TALER_refresh_get_commitment (&rc_expected,
|
TALER_refresh_get_commitment (&rc_expected,
|
||||||
TALER_CNC_KAPPA,
|
TALER_CNC_KAPPA,
|
||||||
rctx->have_rms
|
rctx->no_rms
|
||||||
? &rctx->rms
|
? NULL
|
||||||
: NULL,
|
: &rctx->rms,
|
||||||
rctx->num_fresh_coins,
|
rctx->num_fresh_coins,
|
||||||
rcs,
|
rcs,
|
||||||
&rctx->melt.session.coin.coin_pub,
|
&rctx->melt.session.coin.coin_pub,
|
||||||
@ -484,7 +484,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
|||||||
if (NULL == dks[i])
|
if (NULL == dks[i])
|
||||||
return ret;
|
return ret;
|
||||||
if ( (TALER_DENOMINATION_CS == dks[i]->denom_pub.cipher) &&
|
if ( (TALER_DENOMINATION_CS == dks[i]->denom_pub.cipher) &&
|
||||||
(! rctx->have_rms) )
|
(rctx->no_rms) )
|
||||||
{
|
{
|
||||||
return TALER_MHD_reply_with_error (
|
return TALER_MHD_reply_with_error (
|
||||||
connection,
|
connection,
|
||||||
@ -937,10 +937,12 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
|
|||||||
&new_denoms_h),
|
&new_denoms_h),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_json ("old_age_commitment",
|
GNUNET_JSON_spec_json ("old_age_commitment",
|
||||||
&old_age_commitment)),
|
&old_age_commitment),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("rms",
|
GNUNET_JSON_spec_fixed_auto ("rms",
|
||||||
&rctx.rms)),
|
&rctx.rms),
|
||||||
|
&rctx.no_rms),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -981,8 +983,6 @@ TEH_handler_reveal (struct TEH_RequestContext *rc,
|
|||||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rctx.have_rms = (NULL != json_object_get (root,
|
|
||||||
"rms"));
|
|
||||||
|
|
||||||
/* Check we got enough transfer private keys */
|
/* Check we got enough transfer private keys */
|
||||||
/* Note we do +1 as 1 row (cut-and-choose!) is missing! */
|
/* Note we do +1 as 1 row (cut-and-choose!) is missing! */
|
||||||
|
@ -2469,22 +2469,108 @@ END $$;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION exchange_do_purse_deposit(
|
CREATE OR REPLACE FUNCTION exchange_do_purse_deposit(
|
||||||
|
IN in_partner_id INT8,
|
||||||
IN in_purse_pub BYTEA,
|
IN in_purse_pub BYTEA,
|
||||||
IN in_amount_with_fee_val INT8,
|
IN in_amount_with_fee_val INT8,
|
||||||
IN in_amount_with_fee_frac INT4,
|
IN in_amount_with_fee_frac INT4,
|
||||||
IN in_coin_pub BYTEA,
|
IN in_coin_pub BYTEA,
|
||||||
IN in_coin_sig BYTEA,
|
IN in_coin_sig BYTEA,
|
||||||
|
IN in_amount_without_fee_val INT8,
|
||||||
|
IN in_amount_without_fee_frac INT4,
|
||||||
OUT out_balance_ok BOOLEAN,
|
OUT out_balance_ok BOOLEAN,
|
||||||
OUT out_conflict BOOLEAN)
|
OUT out_conflict BOOLEAN)
|
||||||
LANGUAGE plpgsql
|
LANGUAGE plpgsql
|
||||||
AS $$
|
AS $$
|
||||||
BEGIN
|
BEGIN
|
||||||
-- FIXME
|
|
||||||
|
-- Store the deposit request.
|
||||||
|
INSERT INTO purse_deposits
|
||||||
|
(partner_serial_id
|
||||||
|
,purse_pub
|
||||||
|
,coin_pub
|
||||||
|
,amount_with_fee_val
|
||||||
|
,amount_with_fee_frac
|
||||||
|
,coin_sig)
|
||||||
|
VALUES
|
||||||
|
(in_partner_id
|
||||||
|
,in_purse_pub
|
||||||
|
,in_coin_pub
|
||||||
|
,in_amount_with_fee_val
|
||||||
|
,in_amount_with_fee_frac
|
||||||
|
,in_coin_sig)
|
||||||
|
ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
|
IF NOT FOUND
|
||||||
|
THEN
|
||||||
|
-- Idempotency check: check if coin_sig is the same,
|
||||||
|
-- if so, success, otherwise conflict!
|
||||||
|
SELECT
|
||||||
|
1
|
||||||
|
FROM purse_deposits
|
||||||
|
WHERE coin_pub = in_coin_pub
|
||||||
|
AND purse_pub = in_purse_pub
|
||||||
|
AND coin_sig = in_cion_sig;
|
||||||
|
IF NOT FOUND
|
||||||
|
THEN
|
||||||
|
-- Deposit exists, but with differences. Not allowed.
|
||||||
|
out_balance_ok=FALSE;
|
||||||
|
out_conflict=TRUE;
|
||||||
|
RETURN;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
|
||||||
|
-- Debit the coin
|
||||||
|
-- Check and update balance of the coin.
|
||||||
|
UPDATE known_coins
|
||||||
|
SET
|
||||||
|
remaining_frac=remaining_frac-in_amount_with_fee_frac
|
||||||
|
+ CASE
|
||||||
|
WHEN remaining_frac < in_amount_with_fee_frac
|
||||||
|
THEN 100000000
|
||||||
|
ELSE 0
|
||||||
|
END,
|
||||||
|
remaining_val=remaining_val-in_amount_with_fee_val
|
||||||
|
- CASE
|
||||||
|
WHEN remaining_frac < in_amount_with_fee_frac
|
||||||
|
THEN 1
|
||||||
|
ELSE 0
|
||||||
|
END
|
||||||
|
WHERE coin_pub=in_coin_pub
|
||||||
|
AND ( (remaining_val > in_amount_with_fee_val) OR
|
||||||
|
( (remaining_frac >= in_amount_with_fee_frac) AND
|
||||||
|
(remaining_val >= in_amount_with_fee_val) ) );
|
||||||
|
|
||||||
|
IF NOT FOUND
|
||||||
|
THEN
|
||||||
|
-- Insufficient balance.
|
||||||
|
out_balance_ok=FALSE;
|
||||||
|
out_conflict=FALSE;
|
||||||
|
RETURN;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
|
||||||
|
-- Credit the purse.
|
||||||
|
UPDATE purse_requests
|
||||||
|
SET
|
||||||
|
balance_frac=balance_frac+in_amount_without_fee_frac
|
||||||
|
- CASE
|
||||||
|
WHEN balance_frac+in_amount_without_fee_frac >= 100000000
|
||||||
|
THEN 100000000
|
||||||
|
ELSE 0
|
||||||
|
END,
|
||||||
|
balance_val=balance_val+in_amount_without_fee_val
|
||||||
|
+ CASE
|
||||||
|
WHEN balance_frac+in_amount_without_fee_frac >= 100000000
|
||||||
|
THEN 1
|
||||||
|
ELSE 0
|
||||||
|
END
|
||||||
|
WHERE purse_pub=in_purse_pub;
|
||||||
|
|
||||||
|
out_conflict=FALSE;
|
||||||
|
out_balance_ok=TRUE;
|
||||||
|
|
||||||
END $$;
|
END $$;
|
||||||
|
|
||||||
|
|
||||||
|
@ -799,6 +799,15 @@ prepare_statements (struct PostgresClosure *pg)
|
|||||||
" FROM exchange_do_deposit"
|
" FROM exchange_do_deposit"
|
||||||
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17);",
|
" ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17);",
|
||||||
17),
|
17),
|
||||||
|
/* used in postgres_do_purse_deposit() */
|
||||||
|
GNUNET_PQ_make_prepare (
|
||||||
|
"call_purse_deposit",
|
||||||
|
"SELECT "
|
||||||
|
" out_balance_ok AS balance_ok"
|
||||||
|
",out_conflict AS conflict"
|
||||||
|
" FROM exchange_do_purse_deposit"
|
||||||
|
" ($1,$2,$3,$4,$5,$6,$7,$8);",
|
||||||
|
8),
|
||||||
/* Used in #postgres_do_melt() to melt a coin. */
|
/* Used in #postgres_do_melt() to melt a coin. */
|
||||||
GNUNET_PQ_make_prepare (
|
GNUNET_PQ_make_prepare (
|
||||||
"call_melt",
|
"call_melt",
|
||||||
@ -3342,13 +3351,19 @@ prepare_statements (struct PostgresClosure *pg)
|
|||||||
" FROM purse_requests"
|
" FROM purse_requests"
|
||||||
" WHERE merge_pub=$1;",
|
" WHERE merge_pub=$1;",
|
||||||
1),
|
1),
|
||||||
/* Used in #postgres_do_purse_deposit() */
|
/* Used in #postgres_get_purse_deposit */
|
||||||
GNUNET_PQ_make_prepare (
|
GNUNET_PQ_make_prepare (
|
||||||
"call_purse_deposit",
|
"select_purse_deposit_by_coin_pub",
|
||||||
"SELECT 1"
|
"SELECT "
|
||||||
" FROM exchange_do_purse_deposit"
|
" coin_sig"
|
||||||
" ($1, $2, $3, $4, $5);",
|
",amount_with_fee_val"
|
||||||
5),
|
",amount_with_fee_frac"
|
||||||
|
",partner_base_url"
|
||||||
|
" FROM purse_deposits"
|
||||||
|
" LEFT JOIN partners USING (partner_serial_id)"
|
||||||
|
" WHERE coin_pub=$2"
|
||||||
|
" AND purse_pub=$1;",
|
||||||
|
2),
|
||||||
/* Used in #postgres_do_purse_merge() */
|
/* Used in #postgres_do_purse_merge() */
|
||||||
GNUNET_PQ_make_prepare (
|
GNUNET_PQ_make_prepare (
|
||||||
"call_purse_merge",
|
"call_purse_merge",
|
||||||
@ -13181,10 +13196,79 @@ postgres_do_purse_deposit (
|
|||||||
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,
|
const struct TALER_Amount *amount_minus_fee,
|
||||||
bool *balance_ok)
|
bool *balance_ok,
|
||||||
|
bool *conflict)
|
||||||
{
|
{
|
||||||
GNUNET_break (0); // FIXME
|
struct PostgresClosure *pg = cls;
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
|
GNUNET_PQ_query_param_uint64 (0), /* FIXME: partner ID */
|
||||||
|
GNUNET_PQ_query_param_auto_from_type (purse_pub),
|
||||||
|
TALER_PQ_query_param_amount (amount),
|
||||||
|
GNUNET_PQ_query_param_auto_from_type (coin_pub),
|
||||||
|
GNUNET_PQ_query_param_auto_from_type (coin_sig),
|
||||||
|
TALER_PQ_query_param_amount (amount_minus_fee),
|
||||||
|
GNUNET_PQ_query_param_end
|
||||||
|
};
|
||||||
|
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||||
|
GNUNET_PQ_result_spec_bool ("balance_ok",
|
||||||
|
balance_ok),
|
||||||
|
GNUNET_PQ_result_spec_bool ("conflict",
|
||||||
|
conflict),
|
||||||
|
GNUNET_PQ_result_spec_end
|
||||||
|
};
|
||||||
|
|
||||||
|
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
||||||
|
"call_purse_deposit",
|
||||||
|
params,
|
||||||
|
rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called to obtain a coin deposit data from
|
||||||
|
* depositing the coin into a purse.
|
||||||
|
*
|
||||||
|
* @param cls the @e cls of this struct with the plugin-specific state
|
||||||
|
* @param purse_pub purse to credit
|
||||||
|
* @param coin_pub coin to deposit (debit)
|
||||||
|
* @param[out] amount set fraction of the coin's value that was deposited (with fee)
|
||||||
|
* @param[out] coin_sig set to signature affirming the operation
|
||||||
|
* @param[out] partner_url set to the URL of the partner exchange, or NULL for ourselves, must be freed by caller
|
||||||
|
* @return transaction status code
|
||||||
|
*/
|
||||||
|
static enum GNUNET_DB_QueryStatus
|
||||||
|
postgres_get_purse_deposit (
|
||||||
|
void *cls,
|
||||||
|
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
|
struct TALER_Amount *amount,
|
||||||
|
struct TALER_CoinSpendSignatureP *coin_sig,
|
||||||
|
char **partner_url)
|
||||||
|
{
|
||||||
|
struct PostgresClosure *pg = cls;
|
||||||
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
|
GNUNET_PQ_query_param_auto_from_type (purse_pub),
|
||||||
|
GNUNET_PQ_query_param_auto_from_type (coin_pub),
|
||||||
|
GNUNET_PQ_query_param_end
|
||||||
|
};
|
||||||
|
bool is_null;
|
||||||
|
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||||
|
GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
|
||||||
|
coin_sig),
|
||||||
|
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
|
||||||
|
amount),
|
||||||
|
GNUNET_PQ_result_spec_allow_null (
|
||||||
|
GNUNET_PQ_result_spec_string ("partner_base_url",
|
||||||
|
partner_url),
|
||||||
|
&is_null),
|
||||||
|
GNUNET_PQ_result_spec_end
|
||||||
|
};
|
||||||
|
|
||||||
|
*partner_url = NULL;
|
||||||
|
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
|
||||||
|
"select_purse_deposit_by_coin_pub",
|
||||||
|
params,
|
||||||
|
rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -13589,6 +13673,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
|
|||||||
= &postgres_select_purse_by_merge_pub;
|
= &postgres_select_purse_by_merge_pub;
|
||||||
plugin->do_purse_deposit
|
plugin->do_purse_deposit
|
||||||
= &postgres_do_purse_deposit;
|
= &postgres_do_purse_deposit;
|
||||||
|
plugin->get_purse_deposit
|
||||||
|
= &postgres_get_purse_deposit;
|
||||||
plugin->do_purse_merge
|
plugin->do_purse_merge
|
||||||
= &postgres_do_purse_merge;
|
= &postgres_do_purse_merge;
|
||||||
plugin->select_purse_merge
|
plugin->select_purse_merge
|
||||||
|
@ -4567,6 +4567,8 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
* remaining balance is below @a amount;
|
* remaining balance is below @a amount;
|
||||||
* in this case, the return value will be
|
* in this case, the return value will be
|
||||||
* #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure
|
* #GNUNET_DB_STATUS_SUCCESS_ONE despite the failure
|
||||||
|
* @param[out] conflict the same coin was deposited into
|
||||||
|
* this purse with a different amount already
|
||||||
* @return transaction status code
|
* @return transaction status code
|
||||||
*/
|
*/
|
||||||
enum GNUNET_DB_QueryStatus
|
enum GNUNET_DB_QueryStatus
|
||||||
@ -4577,7 +4579,30 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
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,
|
const struct TALER_Amount *amount_minus_fee,
|
||||||
bool *balance_ok);
|
bool *balance_ok,
|
||||||
|
bool *conflict);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called to obtain a coin deposit data from
|
||||||
|
* depositing the coin into a purse.
|
||||||
|
*
|
||||||
|
* @param cls the @e cls of this struct with the plugin-specific state
|
||||||
|
* @param purse_pub purse to credit
|
||||||
|
* @param coin_pub coin to deposit (debit)
|
||||||
|
* @param[out] amount set fraction of the coin's value that was deposited (with fee)
|
||||||
|
* @param[out] coin_sig set to signature affirming the operation
|
||||||
|
* @param[out] partner_url set to the URL of the partner exchange, or NULL for ourselves, must be freed by caller
|
||||||
|
* @return transaction status code
|
||||||
|
*/
|
||||||
|
enum GNUNET_DB_QueryStatus
|
||||||
|
(*get_purse_deposit)(
|
||||||
|
void *cls,
|
||||||
|
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||||
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
|
struct TALER_Amount *amount,
|
||||||
|
struct TALER_CoinSpendSignatureP *coin_sig,
|
||||||
|
char **partner_url);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -447,7 +447,8 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
struct TALER_MerchantPublicKeyP merchant_pub;
|
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||||
struct GNUNET_TIME_Timestamp refund_deadline = {0};
|
struct GNUNET_TIME_Timestamp refund_deadline = {0};
|
||||||
struct TALER_CoinSpendSignatureP sig;
|
struct TALER_CoinSpendSignatureP sig;
|
||||||
struct TALER_AgeCommitmentHash hac = {0};
|
struct TALER_AgeCommitmentHash hac;
|
||||||
|
bool no_hac;
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
||||||
&sig),
|
&sig),
|
||||||
@ -459,12 +460,14 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
h_denom_pub),
|
h_denom_pub),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
||||||
&hac)),
|
&hac),
|
||||||
|
&no_hac),
|
||||||
GNUNET_JSON_spec_timestamp ("timestamp",
|
GNUNET_JSON_spec_timestamp ("timestamp",
|
||||||
&wallet_timestamp),
|
&wallet_timestamp),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_timestamp ("refund_deadline",
|
GNUNET_JSON_spec_timestamp ("refund_deadline",
|
||||||
&refund_deadline)),
|
&refund_deadline),
|
||||||
|
NULL),
|
||||||
TALER_JSON_spec_amount_any ("deposit_fee",
|
TALER_JSON_spec_amount_any ("deposit_fee",
|
||||||
&fee),
|
&fee),
|
||||||
GNUNET_JSON_spec_fixed_auto ("merchant_pub",
|
GNUNET_JSON_spec_fixed_auto ("merchant_pub",
|
||||||
@ -486,7 +489,7 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
&fee,
|
&fee,
|
||||||
&h_wire,
|
&h_wire,
|
||||||
&h_contract_terms,
|
&h_contract_terms,
|
||||||
TALER_AgeCommitmentHash_isNullOrZero (&hac) ? NULL : &hac,
|
no_hac ? NULL : &hac,
|
||||||
NULL /* h_extensions! */,
|
NULL /* h_extensions! */,
|
||||||
h_denom_pub,
|
h_denom_pub,
|
||||||
wallet_timestamp,
|
wallet_timestamp,
|
||||||
@ -519,7 +522,8 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
{
|
{
|
||||||
struct TALER_CoinSpendSignatureP sig;
|
struct TALER_CoinSpendSignatureP sig;
|
||||||
struct TALER_RefreshCommitmentP rc;
|
struct TALER_RefreshCommitmentP rc;
|
||||||
struct TALER_AgeCommitmentHash h_age_commitment = {0};
|
struct TALER_AgeCommitmentHash h_age_commitment;
|
||||||
|
bool no_hac;
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
||||||
&sig),
|
&sig),
|
||||||
@ -529,7 +533,8 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
h_denom_pub),
|
h_denom_pub),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
||||||
&h_age_commitment)),
|
&h_age_commitment),
|
||||||
|
&no_hac),
|
||||||
TALER_JSON_spec_amount_any ("melt_fee",
|
TALER_JSON_spec_amount_any ("melt_fee",
|
||||||
&fee),
|
&fee),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
@ -566,8 +571,9 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
&fee,
|
&fee,
|
||||||
&rc,
|
&rc,
|
||||||
h_denom_pub,
|
h_denom_pub,
|
||||||
TALER_AgeCommitmentHash_isNullOrZero (&h_age_commitment) ?
|
no_hac
|
||||||
NULL : &h_age_commitment,
|
? NULL
|
||||||
|
: &h_age_commitment,
|
||||||
coin_pub,
|
coin_pub,
|
||||||
&sig))
|
&sig))
|
||||||
{
|
{
|
||||||
|
@ -333,7 +333,8 @@ handle_deposit_finished (void *cls,
|
|||||||
&dh->exchange_pub),
|
&dh->exchange_pub),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_string ("transaction_base_url",
|
GNUNET_JSON_spec_string ("transaction_base_url",
|
||||||
&dr.details.success.transaction_base_url)),
|
&dr.details.success.transaction_base_url),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_timestamp ("exchange_timestamp",
|
GNUNET_JSON_spec_timestamp ("exchange_timestamp",
|
||||||
&dh->exchange_timestamp),
|
&dh->exchange_timestamp),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
|
@ -750,7 +750,8 @@ decode_keys_json (const json_t *resp_obj,
|
|||||||
¤cy),
|
¤cy),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
TALER_JSON_spec_amount_any ("wallet_balance_limit_without_kyc",
|
TALER_JSON_spec_amount_any ("wallet_balance_limit_without_kyc",
|
||||||
&key_data->wallet_balance_limit_without_kyc)),
|
&key_data->wallet_balance_limit_without_kyc),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -895,11 +896,13 @@ decode_keys_json (const json_t *resp_obj,
|
|||||||
struct GNUNET_JSON_Specification ext_spec[] = {
|
struct GNUNET_JSON_Specification ext_spec[] = {
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_json ("extensions",
|
GNUNET_JSON_spec_json ("extensions",
|
||||||
&extensions)),
|
&extensions),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto (
|
GNUNET_JSON_spec_fixed_auto (
|
||||||
"extensions_sig",
|
"extensions_sig",
|
||||||
&extensions_sig)),
|
&extensions_sig),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,6 +97,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
|||||||
union TALER_DenominationBlindingKeyP bks;
|
union TALER_DenominationBlindingKeyP bks;
|
||||||
struct TALER_ExchangeWithdrawValues alg_values;
|
struct TALER_ExchangeWithdrawValues alg_values;
|
||||||
struct TALER_CsNonce nonce;
|
struct TALER_CsNonce nonce;
|
||||||
|
bool no_nonce;
|
||||||
uint32_t coin_idx;
|
uint32_t coin_idx;
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
TALER_JSON_spec_denom_pub ("denom_pub",
|
TALER_JSON_spec_denom_pub ("denom_pub",
|
||||||
@ -111,7 +112,8 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
|||||||
&coin_idx),
|
&coin_idx),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("cs_nonce",
|
GNUNET_JSON_spec_fixed_auto ("cs_nonce",
|
||||||
&nonce)),
|
&nonce),
|
||||||
|
&no_nonce),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
struct TALER_TransferSecretP secret;
|
struct TALER_TransferSecretP secret;
|
||||||
@ -119,9 +121,6 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
|||||||
struct TALER_CoinPubHashP c_hash;
|
struct TALER_CoinPubHashP c_hash;
|
||||||
|
|
||||||
/* parse reply */
|
/* parse reply */
|
||||||
memset (&nonce,
|
|
||||||
0,
|
|
||||||
sizeof (nonce));
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_JSON_parse (json,
|
GNUNET_JSON_parse (json,
|
||||||
spec,
|
spec,
|
||||||
@ -180,7 +179,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
|||||||
}
|
}
|
||||||
if (TALER_DENOMINATION_CS == alg_values.cipher)
|
if (TALER_DENOMINATION_CS == alg_values.cipher)
|
||||||
{
|
{
|
||||||
if (GNUNET_is_zero (&nonce))
|
if (no_nonce)
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
GNUNET_JSON_parse_free (spec);
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
@ -259,7 +259,7 @@ TALER_EXCHANGE_purse_create_with_deposit (
|
|||||||
struct TALER_ContractDiffiePublicP contract_pub;
|
struct TALER_ContractDiffiePublicP contract_pub;
|
||||||
char arg_str[sizeof (pch->purse_pub) * 2 + 32];
|
char arg_str[sizeof (pch->purse_pub) * 2 + 32];
|
||||||
char *url;
|
char *url;
|
||||||
uint32_t min_age;
|
uint32_t min_age = 0;
|
||||||
|
|
||||||
pch = GNUNET_new (struct TALER_EXCHANGE_PurseCreateDepositHandle);
|
pch = GNUNET_new (struct TALER_EXCHANGE_PurseCreateDepositHandle);
|
||||||
pch->exchange = exchange;
|
pch->exchange = exchange;
|
||||||
@ -272,7 +272,8 @@ TALER_EXCHANGE_purse_create_with_deposit (
|
|||||||
&pch->purse_value_after_fees),
|
&pch->purse_value_after_fees),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_uint32 ("minimum_age",
|
GNUNET_JSON_spec_uint32 ("minimum_age",
|
||||||
&min_age)),
|
&min_age),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -231,7 +231,8 @@ verify_conflict_history_ok (struct TALER_EXCHANGE_RefundHandle *rh,
|
|||||||
struct TALER_Amount deposit_fee;
|
struct TALER_Amount deposit_fee;
|
||||||
struct TALER_MerchantWireHashP h_wire;
|
struct TALER_MerchantWireHashP h_wire;
|
||||||
struct TALER_PrivateContractHashP h_contract_terms;
|
struct TALER_PrivateContractHashP h_contract_terms;
|
||||||
struct TALER_AgeCommitmentHash h_age_commitment = {{{0}}};
|
struct TALER_AgeCommitmentHash h_age_commitment;
|
||||||
|
bool no_hac;
|
||||||
// struct TALER_ExtensionContractHashP h_extensions; // FIXME!
|
// struct TALER_ExtensionContractHashP h_extensions; // FIXME!
|
||||||
struct TALER_DenominationHashP h_denom_pub;
|
struct TALER_DenominationHashP h_denom_pub;
|
||||||
struct GNUNET_TIME_Timestamp wallet_timestamp;
|
struct GNUNET_TIME_Timestamp wallet_timestamp;
|
||||||
@ -249,7 +250,8 @@ verify_conflict_history_ok (struct TALER_EXCHANGE_RefundHandle *rh,
|
|||||||
&h_denom_pub),
|
&h_denom_pub),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
||||||
&h_age_commitment)),
|
&h_age_commitment),
|
||||||
|
&no_hac),
|
||||||
GNUNET_JSON_spec_timestamp ("timestamp",
|
GNUNET_JSON_spec_timestamp ("timestamp",
|
||||||
&wallet_timestamp),
|
&wallet_timestamp),
|
||||||
GNUNET_JSON_spec_timestamp ("refund_deadline",
|
GNUNET_JSON_spec_timestamp ("refund_deadline",
|
||||||
@ -275,8 +277,10 @@ verify_conflict_history_ok (struct TALER_EXCHANGE_RefundHandle *rh,
|
|||||||
&deposit_fee,
|
&deposit_fee,
|
||||||
&h_wire,
|
&h_wire,
|
||||||
&h_contract_terms,
|
&h_contract_terms,
|
||||||
&h_age_commitment,
|
no_hac
|
||||||
NULL /* h_extensions! */,
|
? NULL
|
||||||
|
: &h_age_commitment,
|
||||||
|
NULL /* FIXME-OEC: h_extensions! */,
|
||||||
&h_denom_pub,
|
&h_denom_pub,
|
||||||
wallet_timestamp,
|
wallet_timestamp,
|
||||||
&merchant_pub,
|
&merchant_pub,
|
||||||
|
@ -291,7 +291,8 @@ deposit_confirmation_run (void *cls,
|
|||||||
×tamp),
|
×tamp),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_timestamp ("refund_deadline",
|
GNUNET_JSON_spec_timestamp ("refund_deadline",
|
||||||
&refund_deadline)),
|
&refund_deadline),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user