add KYC errors for p2p payments

This commit is contained in:
Christian Grothoff 2022-06-04 15:19:57 +02:00
parent 3e99c50c0f
commit 93943bdb5b
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
13 changed files with 158 additions and 18 deletions

@ -1 +1 @@
Subproject commit aebd5420308d7599aadb8818a82d9ffc89492334 Subproject commit d4234f340c6e7261de36ab5fad3d53597ea8ecd0

View File

@ -150,7 +150,7 @@ batch_withdraw_transaction (void *cls,
{ {
*mhd_ret = TALER_MHD_reply_with_error (connection, *mhd_ret = TALER_MHD_reply_with_error (connection,
MHD_HTTP_NOT_FOUND, MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_WITHDRAW_RESERVE_UNKNOWN, TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN,
NULL); NULL);
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
} }
@ -171,7 +171,7 @@ batch_withdraw_transaction (void *cls,
/* Wallet-to-wallet payments _always_ require KYC */ /* Wallet-to-wallet payments _always_ require KYC */
*mhd_ret = TALER_MHD_REPLY_JSON_PACK ( *mhd_ret = TALER_MHD_REPLY_JSON_PACK (
connection, connection,
MHD_HTTP_ACCEPTED, MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
GNUNET_JSON_pack_uint64 ("payment_target_uuid", GNUNET_JSON_pack_uint64 ("payment_target_uuid",
wc->kyc.payment_target_uuid)); wc->kyc.payment_target_uuid));
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
@ -206,7 +206,7 @@ batch_withdraw_transaction (void *cls,
{ {
*mhd_ret = TALER_MHD_REPLY_JSON_PACK ( *mhd_ret = TALER_MHD_REPLY_JSON_PACK (
connection, connection,
MHD_HTTP_ACCEPTED, MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
GNUNET_JSON_pack_uint64 ("payment_target_uuid", GNUNET_JSON_pack_uint64 ("payment_target_uuid",
wc->kyc.payment_target_uuid)); wc->kyc.payment_target_uuid));
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;

View File

@ -223,6 +223,8 @@ merge_transaction (void *cls,
bool in_conflict = true; bool in_conflict = true;
bool no_balance = true; bool no_balance = true;
bool no_partner = true; bool no_partner = true;
bool no_kyc = true;
bool no_reserve = true;
// FIXME: add KYC-check logic! // FIXME: add KYC-check logic!
qs = TEH_plugin->do_purse_merge (TEH_plugin->cls, qs = TEH_plugin->do_purse_merge (TEH_plugin->cls,
@ -234,6 +236,8 @@ merge_transaction (void *cls,
&pcc->reserve_pub, &pcc->reserve_pub,
&no_partner, &no_partner,
&no_balance, &no_balance,
&no_reserve,
&no_kyc,
&in_conflict); &in_conflict);
if (qs < 0) if (qs < 0)
{ {
@ -257,6 +261,25 @@ merge_transaction (void *cls,
pcc->provider_url); pcc->provider_url);
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
} }
if (no_reserve)
{
*mhd_ret =
TALER_MHD_reply_with_error (connection,
MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN,
NULL);
return GNUNET_DB_STATUS_HARD_ERROR;
}
if (no_kyc)
{
*mhd_ret
= TALER_MHD_REPLY_JSON_PACK (
connection,
MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
TALER_JSON_pack_ec (
TALER_EC_EXCHANGE_GENERIC_KYC_REQUIRED));
return GNUNET_DB_STATUS_HARD_ERROR;
}
if (no_balance) if (no_balance)
{ {
*mhd_ret = *mhd_ret =

View File

@ -213,8 +213,6 @@ purse_transaction (void *cls,
{ {
bool in_conflict = true; bool in_conflict = true;
// FIXME: also check KYC state of the account
// FIXME: distinguish reserve-not-found!
/* 1) store purse */ /* 1) store purse */
qs = TEH_plugin->insert_purse_request (TEH_plugin->cls, qs = TEH_plugin->insert_purse_request (TEH_plugin->cls,
&rpc->purse_pub, &rpc->purse_pub,
@ -294,14 +292,14 @@ purse_transaction (void *cls,
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
} }
// FIXME: return 404 if reserve-not-found!
// FIXME: if KYC check failed, generate 451 response!
} }
/* 2) create purse with reserve (and debit reserve for purse creation!) */ /* 2) create purse with reserve (and debit reserve for purse creation!) */
{ {
bool in_conflict = true; bool in_conflict = true;
bool insufficient_funds = true; bool insufficient_funds = true;
bool no_reserve = true;
bool no_kyc = true;
qs = TEH_plugin->do_reserve_purse ( qs = TEH_plugin->do_reserve_purse (
TEH_plugin->cls, TEH_plugin->cls,
@ -315,6 +313,8 @@ purse_transaction (void *cls,
: &rpc->gf->fees.purse, : &rpc->gf->fees.purse,
rpc->reserve_pub, rpc->reserve_pub,
&in_conflict, &in_conflict,
&no_reserve,
&no_kyc,
&insufficient_funds); &insufficient_funds);
if (qs < 0) if (qs < 0)
{ {
@ -377,6 +377,26 @@ purse_transaction (void *cls,
GNUNET_free (partner_url); GNUNET_free (partner_url);
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
} }
if (no_reserve)
{
*mhd_ret
= TALER_MHD_REPLY_JSON_PACK (
connection,
MHD_HTTP_NOT_FOUND,
TALER_JSON_pack_ec (
TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN));
return GNUNET_DB_STATUS_HARD_ERROR;
}
if (no_kyc)
{
*mhd_ret
= TALER_MHD_REPLY_JSON_PACK (
connection,
MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
TALER_JSON_pack_ec (
TALER_EC_EXCHANGE_GENERIC_KYC_REQUIRED));
return GNUNET_DB_STATUS_HARD_ERROR;
}
if (insufficient_funds) if (insufficient_funds)
{ {
*mhd_ret *mhd_ret

View File

@ -133,7 +133,7 @@ withdraw_transaction (void *cls,
{ {
*mhd_ret = TALER_MHD_reply_with_error (connection, *mhd_ret = TALER_MHD_reply_with_error (connection,
MHD_HTTP_NOT_FOUND, MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_WITHDRAW_RESERVE_UNKNOWN, TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN,
NULL); NULL);
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
} }
@ -153,7 +153,7 @@ withdraw_transaction (void *cls,
/* Wallet-to-wallet payments _always_ require KYC */ /* Wallet-to-wallet payments _always_ require KYC */
*mhd_ret = TALER_MHD_REPLY_JSON_PACK ( *mhd_ret = TALER_MHD_REPLY_JSON_PACK (
connection, connection,
MHD_HTTP_ACCEPTED, MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
GNUNET_JSON_pack_uint64 ("payment_target_uuid", GNUNET_JSON_pack_uint64 ("payment_target_uuid",
wc->kyc.payment_target_uuid)); wc->kyc.payment_target_uuid));
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
@ -188,7 +188,7 @@ withdraw_transaction (void *cls,
{ {
*mhd_ret = TALER_MHD_REPLY_JSON_PACK ( *mhd_ret = TALER_MHD_REPLY_JSON_PACK (
connection, connection,
MHD_HTTP_ACCEPTED, MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
GNUNET_JSON_pack_uint64 ("payment_target_uuid", GNUNET_JSON_pack_uint64 ("payment_target_uuid",
wc->kyc.payment_target_uuid)); wc->kyc.payment_target_uuid));
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;

View File

@ -3092,6 +3092,8 @@ CREATE OR REPLACE FUNCTION exchange_do_purse_merge(
IN in_reserve_pub BYTEA, IN in_reserve_pub BYTEA,
OUT out_no_partner BOOLEAN, OUT out_no_partner BOOLEAN,
OUT out_no_balance BOOLEAN, OUT out_no_balance BOOLEAN,
OUT out_no_kyc BOOLEAN,
OUT out_no_reserve BOOLEAN,
OUT out_conflict BOOLEAN) OUT out_conflict BOOLEAN)
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
@ -3121,6 +3123,8 @@ ELSE
THEN THEN
out_no_partner=TRUE; out_no_partner=TRUE;
out_conflict=FALSE; out_conflict=FALSE;
out_no_kyc=FALSE;
out_no_reserve=FALSE;
RETURN; RETURN;
END IF; END IF;
END IF; END IF;
@ -3144,6 +3148,8 @@ IF NOT FOUND
THEN THEN
out_no_balance=TRUE; out_no_balance=TRUE;
out_conflict=FALSE; out_conflict=FALSE;
out_no_kyc=FALSE;
out_no_reserve=FALSE;
RETURN; RETURN;
END IF; END IF;
out_no_balance=FALSE; out_no_balance=FALSE;
@ -3176,17 +3182,49 @@ THEN
THEN THEN
-- Purse was merged, but to some other reserve. Not allowed. -- Purse was merged, but to some other reserve. Not allowed.
out_conflict=TRUE; out_conflict=TRUE;
out_no_kyc=FALSE;
out_no_reserve=FALSE;
RETURN; RETURN;
END IF; END IF;
-- "success" -- "success"
out_conflict=FALSE; out_conflict=FALSE;
out_no_kyc=FALSE;
out_no_reserve=FALSE;
RETURN; RETURN;
END IF; END IF;
out_conflict=FALSE; out_conflict=FALSE;
ASSERT NOT my_finished, 'internal invariant failed'; ASSERT NOT my_finished, 'internal invariant failed';
IF in_partner_url IS NULL
THEN
-- Need to do KYC check.
SELECT NOT kyc_passed
INTO out_no_kyc
FROM reserves
WHERE reserve_pub=in_reserve_pub;
IF NOT FOUND
THEN
out_no_kyc=TRUE;
out_no_reserve=TRUE;
RETURN;
END IF;
out_no_reserve=FALSE;
IF (out_no_kyc)
THEN
RETURN;
END IF;
ELSE
-- KYC is not our responsibility
out_no_reserve=FALSE;
out_no_kyc=FALSE;
END IF;
-- Store account merge signature. -- Store account merge signature.
INSERT INTO account_merges INSERT INTO account_merges
(reserve_pub (reserve_pub
@ -3248,6 +3286,8 @@ CREATE OR REPLACE FUNCTION exchange_do_reserve_purse(
IN in_purse_fee_frac INT4, IN in_purse_fee_frac INT4,
IN in_reserve_pub BYTEA, IN in_reserve_pub BYTEA,
OUT out_no_funds BOOLEAN, OUT out_no_funds BOOLEAN,
OUT out_no_kyc BOOLEAN,
OUT out_no_reserve BOOLEAN,
OUT out_conflict BOOLEAN) OUT out_conflict BOOLEAN)
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
@ -3281,16 +3321,40 @@ THEN
THEN THEN
-- Purse was merged, but to some other reserve. Not allowed. -- Purse was merged, but to some other reserve. Not allowed.
out_conflict=TRUE; out_conflict=TRUE;
out_no_kyc=FALSE;
out_no_reserve=FALSE;
out_no_funds=FALSE;
RETURN; RETURN;
END IF; END IF;
-- "success" -- "success"
out_conflict=FALSE; out_conflict=FALSE;
out_no_funds=FALSE; out_no_funds=FALSE;
out_no_kyc=FALSE;
out_no_reserve=FALSE;
RETURN; RETURN;
END IF; END IF;
out_conflict=FALSE; out_conflict=FALSE;
SELECT NOT kyc_passed
INTO out_no_kyc
FROM reserves
WHERE reserve_pub=in_reserve_pub;
IF NOT FOUND
THEN
out_no_kyc=TRUE;
out_no_reserve=TRUE;
out_no_funds=TRUE;
RETURN;
END IF;
out_no_reserve=FALSE;
IF (out_no_kyc)
THEN
out_no_funds=FALSE;
RETURN;
END IF;
IF (in_reserve_quota) IF (in_reserve_quota)
THEN THEN
@ -3303,6 +3367,7 @@ THEN
IF NOT FOUND IF NOT FOUND
THEN THEN
out_no_funds=TRUE; out_no_funds=TRUE;
RETURN;
END IF; END IF;
ELSE ELSE
-- UPDATE reserves balance (and check if balance is enough to pay the fee) -- UPDATE reserves balance (and check if balance is enough to pay the fee)
@ -3328,6 +3393,7 @@ ELSE
IF NOT FOUND IF NOT FOUND
THEN THEN
out_no_funds=TRUE; out_no_funds=TRUE;
RETURN;
END IF; END IF;
END IF; END IF;

View File

@ -3973,6 +3973,8 @@ prepare_statements (struct PostgresClosure *pg)
"SELECT" "SELECT"
" out_no_partner AS no_partner" " out_no_partner AS no_partner"
",out_no_balance AS no_balance" ",out_no_balance AS no_balance"
",out_no_kyc AS no_kyc"
",out_no_reserve AS no_reserve"
",out_conflict AS conflict" ",out_conflict AS conflict"
" FROM exchange_do_purse_merge" " FROM exchange_do_purse_merge"
" ($1, $2, $3, $4, $5, $6);", " ($1, $2, $3, $4, $5, $6);",
@ -3982,6 +3984,8 @@ prepare_statements (struct PostgresClosure *pg)
"call_reserve_purse", "call_reserve_purse",
"SELECT" "SELECT"
" out_no_funds AS insufficient_funds" " out_no_funds AS insufficient_funds"
",out_no_reserve AS no_reserve"
",out_no_kyc AS no_kyc"
",out_conflict AS conflict" ",out_conflict AS conflict"
" FROM exchange_do_reserve_purse" " FROM exchange_do_reserve_purse"
" ($1, $2, $3, $4, $5, $6, $7, $8);", " ($1, $2, $3, $4, $5, $6, $7, $8);",
@ -14490,6 +14494,8 @@ postgres_get_purse_deposit (
* @param reserve_pub public key of the reserve to credit * @param reserve_pub public key of the reserve to credit
* @param[out] no_partner set to true if @a partner_url is unknown * @param[out] no_partner set to true if @a partner_url is unknown
* @param[out] no_balance set to true if the @a purse_pub is not paid up yet * @param[out] no_balance set to true if the @a purse_pub is not paid up yet
* @param[out] no_reserve set to true if the @a reserve_pub is not known
* @param[out] no_kyc set to true if the @a reserve_pub lacks KYC
* @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already
* @return transaction status code * @return transaction status code
*/ */
@ -14504,6 +14510,8 @@ postgres_do_purse_merge (
const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReservePublicKeyP *reserve_pub,
bool *no_partner, bool *no_partner,
bool *no_balance, bool *no_balance,
bool *no_reserve,
bool *no_kyc,
bool *in_conflict) bool *in_conflict)
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
@ -14523,6 +14531,10 @@ postgres_do_purse_merge (
no_partner), no_partner),
GNUNET_PQ_result_spec_bool ("no_balance", GNUNET_PQ_result_spec_bool ("no_balance",
no_balance), no_balance),
GNUNET_PQ_result_spec_bool ("no_kyc",
no_kyc),
GNUNET_PQ_result_spec_bool ("no_reserve",
no_reserve),
GNUNET_PQ_result_spec_bool ("conflict", GNUNET_PQ_result_spec_bool ("conflict",
in_conflict), in_conflict),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end
@ -14561,6 +14573,8 @@ postgres_do_reserve_purse (
const struct TALER_Amount *purse_fee, const struct TALER_Amount *purse_fee,
const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReservePublicKeyP *reserve_pub,
bool *in_conflict, bool *in_conflict,
bool *no_reserve,
bool *no_kyc,
bool *insufficient_funds) bool *insufficient_funds)
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
@ -14582,6 +14596,10 @@ postgres_do_reserve_purse (
insufficient_funds), insufficient_funds),
GNUNET_PQ_result_spec_bool ("conflict", GNUNET_PQ_result_spec_bool ("conflict",
in_conflict), in_conflict),
GNUNET_PQ_result_spec_bool ("no_kyc",
no_kyc),
GNUNET_PQ_result_spec_bool ("no_reserve",
no_reserve),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end
}; };

View File

@ -5039,6 +5039,8 @@ struct TALER_EXCHANGEDB_Plugin
* @param reserve_pub public key of the reserve to credit * @param reserve_pub public key of the reserve to credit
* @param[out] no_partner set to true if @a partner_url is unknown * @param[out] no_partner set to true if @a partner_url is unknown
* @param[out] no_balance set to true if the @a purse_pub is not paid up yet * @param[out] no_balance set to true if the @a purse_pub is not paid up yet
* @param[out] no_reserve set to true if the @a reserve_pub is not known
* @param[out] no_kyc set to true if the @a reserve_pub lacks KYC
* @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already
* @return transaction status code * @return transaction status code
*/ */
@ -5053,6 +5055,8 @@ struct TALER_EXCHANGEDB_Plugin
const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReservePublicKeyP *reserve_pub,
bool *no_partner, bool *no_partner,
bool *no_balance, bool *no_balance,
bool *no_reserve,
bool *no_kyc,
bool *in_conflict); bool *in_conflict);
@ -5069,6 +5073,8 @@ struct TALER_EXCHANGEDB_Plugin
* @param purse_fee amount to charge the reserve for the purse creation, NULL to use the quota * @param purse_fee amount to charge the reserve for the purse creation, NULL to use the quota
* @param reserve_pub public key of the reserve to credit * @param reserve_pub public key of the reserve to credit
* @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already
* @param[out] no_reserve set to true if @a reserve_pub is not a known reserve
* @param[out] no_kyc set to true if @a reserve_pub has not passed KYC checks
* @param[out] insufficient_funds set to true if @a reserve_pub has insufficient capacity to create another purse * @param[out] insufficient_funds set to true if @a reserve_pub has insufficient capacity to create another purse
* @return transaction status code * @return transaction status code
*/ */
@ -5082,6 +5088,8 @@ struct TALER_EXCHANGEDB_Plugin
const struct TALER_Amount *purse_fee, const struct TALER_Amount *purse_fee,
const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReservePublicKeyP *reserve_pub,
bool *in_conflict, bool *in_conflict,
bool *no_reserve,
bool *no_kyc,
bool *insufficient_funds); bool *insufficient_funds);

View File

@ -203,7 +203,7 @@ handle_reserve_batch_withdraw_finished (
wr.details.success.num_coins = wh->num_coins; wr.details.success.num_coins = wh->num_coins;
break; break;
} }
case MHD_HTTP_ACCEPTED: case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
{ {
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_uint64 ("payment_target_uuid", GNUNET_JSON_spec_uint64 ("payment_target_uuid",

View File

@ -224,6 +224,11 @@ handle_purse_create_with_merge_finished (void *cls,
dr.hr.ec = TALER_JSON_get_error_code (j); dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j); dr.hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
/* aka KYC required */
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
dr.hr.ec = TALER_JSON_get_error_code (j); dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j); dr.hr.hint = TALER_JSON_get_error_hint (j);

View File

@ -157,7 +157,7 @@ handle_reserve_withdraw_finished (
wr.details.success.exchange_vals = wh->alg_values; wr.details.success.exchange_vals = wh->alg_values;
break; break;
} }
case MHD_HTTP_ACCEPTED: case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
{ {
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_uint64 ("payment_target_uuid", GNUNET_JSON_spec_uint64 ("payment_target_uuid",

View File

@ -106,7 +106,7 @@ run (void *cls,
"create-reserve-1", "create-reserve-1",
"EUR:10", "EUR:10",
0, /* age restriction off */ 0, /* age restriction off */
MHD_HTTP_ACCEPTED), MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS),
TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1", TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1",
"create-reserve-1", "create-reserve-1",
"EUR:5", "EUR:5",
@ -123,7 +123,7 @@ run (void *cls,
"create-reserve-1", "create-reserve-1",
"EUR:5", "EUR:5",
0, /* age restriction off */ 0, /* age restriction off */
MHD_HTTP_ACCEPTED), MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS),
TALER_TESTING_cmd_proof_kyc ("proof-kyc", TALER_TESTING_cmd_proof_kyc ("proof-kyc",
"create-reserve-1", "create-reserve-1",
"pass", "pass",

View File

@ -242,12 +242,12 @@ reserve_withdraw_cb (void *cls,
{ {
if (0 != ws->do_retry) if (0 != ws->do_retry)
{ {
if (TALER_EC_EXCHANGE_WITHDRAW_RESERVE_UNKNOWN != wr->hr.ec) if (TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN != wr->hr.ec)
ws->do_retry--; /* we don't count reserve unknown as failures here */ ws->do_retry--; /* we don't count reserve unknown as failures here */
if ( (0 == wr->hr.http_status) || if ( (0 == wr->hr.http_status) ||
(TALER_EC_GENERIC_DB_SOFT_FAILURE == wr->hr.ec) || (TALER_EC_GENERIC_DB_SOFT_FAILURE == wr->hr.ec) ||
(TALER_EC_EXCHANGE_WITHDRAW_INSUFFICIENT_FUNDS == wr->hr.ec) || (TALER_EC_EXCHANGE_WITHDRAW_INSUFFICIENT_FUNDS == wr->hr.ec) ||
(TALER_EC_EXCHANGE_WITHDRAW_RESERVE_UNKNOWN == wr->hr.ec) || (TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN == wr->hr.ec) ||
(MHD_HTTP_INTERNAL_SERVER_ERROR == wr->hr.http_status) ) (MHD_HTTP_INTERNAL_SERVER_ERROR == wr->hr.http_status) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@ -257,7 +257,7 @@ reserve_withdraw_cb (void *cls,
/* on DB conflicts, do not use backoff */ /* on DB conflicts, do not use backoff */
if (TALER_EC_GENERIC_DB_SOFT_FAILURE == wr->hr.ec) if (TALER_EC_GENERIC_DB_SOFT_FAILURE == wr->hr.ec)
ws->backoff = GNUNET_TIME_UNIT_ZERO; ws->backoff = GNUNET_TIME_UNIT_ZERO;
else if (TALER_EC_EXCHANGE_WITHDRAW_RESERVE_UNKNOWN != wr->hr.ec) else if (TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN != wr->hr.ec)
ws->backoff = EXCHANGE_LIB_BACKOFF (ws->backoff); ws->backoff = EXCHANGE_LIB_BACKOFF (ws->backoff);
else else
ws->backoff = GNUNET_TIME_relative_max (UNKNOWN_MIN_BACKOFF, ws->backoff = GNUNET_TIME_relative_max (UNKNOWN_MIN_BACKOFF,