summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/exchange/taler-exchange-httpd_csr.c4
-rw-r--r--src/exchange/taler-exchange-httpd_keys.c14
-rw-r--r--src/exchange/taler-exchange-httpd_withdraw.c164
-rw-r--r--src/include/taler_testing_lib.h24
-rw-r--r--src/json/json_helper.c24
-rw-r--r--src/json/json_pack.c21
-rw-r--r--src/lib/exchange_api_withdraw.c88
-rw-r--r--src/lib/exchange_api_withdraw2.c74
-rw-r--r--src/pq/pq_query_helper.c20
-rw-r--r--src/pq/pq_result_helper.c11
-rw-r--r--src/testing/test_exchange_api.c58
-rw-r--r--src/testing/testing_api_cmd_withdraw.c32
12 files changed, 425 insertions, 109 deletions
diff --git a/src/exchange/taler-exchange-httpd_csr.c b/src/exchange/taler-exchange-httpd_csr.c
index 0e330fe30..415dc7acf 100644
--- a/src/exchange/taler-exchange-httpd_csr.c
+++ b/src/exchange/taler-exchange-httpd_csr.c
@@ -37,10 +37,6 @@ TEH_handler_csr (struct TEH_RequestContext *rc,
const json_t *root,
const char *const args[])
{
- // TODO: should we have something similar to struct WithdrawContext?
- // as far as I can tell this isn't necessary because we don't have
- // other functions that the context should be passed to
- // struct CsRContext csrc;
struct TALER_WithdrawNonce nonce;
struct TALER_DenominationHash denom_pub_hash;
struct TALER_DenominationCsPublicR r_pub;
diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c
index dd5928fb9..66c0f69e2 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -2442,7 +2442,19 @@ TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub,
msg,
msg_size,
ec);
- // TODO: case TALER_DENOMINATION_CS:
+ case TALER_DENOMINATION_CS:
+ if (sizeof (struct TALER_BlindedCsPlanchet) != msg_size)
+ {
+ *ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
+ return none;
+ }
+ struct TALER_BlindedCsPlanchet *blinded_cs_planchet = ((struct
+ TALER_BlindedCsPlanchet
+ *) msg);
+ return TALER_CRYPTO_helper_cs_sign (ksh->helpers->csdh,
+ &hd->h_details.h_cs,
+ blinded_cs_planchet,
+ ec);
default:
*ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
return none;
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c
index 53ba270ba..ed54fe278 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -98,15 +98,13 @@ struct WithdrawContext
/**
* Blinded planchet.
*/
- void *blinded_msg;
+ //FIXME:
/**
* Number of bytes in @e blinded_msg.
*/
size_t blinded_msg_len;
-
- /**
- * Set to the resulting signed coin data to be returned to the client.
+ struct TALER_BlindedPlanchet blinded_planchet;
*/
struct TALER_EXCHANGEDB_CollectableBlindcoin collectable;
@@ -324,15 +322,48 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
{
struct WithdrawContext wc;
struct GNUNET_JSON_Specification spec[] = {
+ //FIXME:
GNUNET_JSON_spec_varsize ("coin_ev",
&wc.blinded_msg,
&wc.blinded_msg_len),
+ // field "coin_ev" will be parsed later due to different parsing depending
+ // on denomination cipher, see coin_ev_..._spec
GNUNET_JSON_spec_fixed_auto ("reserve_sig",
&wc.collectable.reserve_sig),
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&wc.collectable.denom_pub_hash),
GNUNET_JSON_spec_end ()
};
+ // holds pointer to coin_ev_rsa/cs_spec for freeing
+ struct GNUNET_JSON_Specification *coin_ev_spec = NULL;
+ struct GNUNET_JSON_Specification coin_ev_rsa_spec[] = {
+ GNUNET_JSON_spec_varsize (
+ "coin_ev",
+ (void **) &wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
+ &wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size),
+ GNUNET_JSON_spec_end ()
+ };
+ json_t *coin_ev_cs_json;
+ struct GNUNET_JSON_Specification coin_ev_cs_json_spec[] = {
+ GNUNET_JSON_spec_json ("coin_ev",
+ &coin_ev_cs_json),
+ GNUNET_JSON_spec_end ()
+ };
+ struct GNUNET_JSON_Specification coin_ev_cs_spec[] = {
+ GNUNET_JSON_spec_fixed (
+ "nonce",
+ &wc.blinded_planchet.details.cs_blinded_planchet.nonce,
+ sizeof (wc.blinded_planchet.details.cs_blinded_planchet.nonce)),
+ GNUNET_JSON_spec_fixed (
+ "c0",
+ &wc.blinded_planchet.details.cs_blinded_planchet.c[0],
+ sizeof (wc.blinded_planchet.details.cs_blinded_planchet.c[0])),
+ GNUNET_JSON_spec_fixed (
+ "c1",
+ &wc.blinded_planchet.details.cs_blinded_planchet.c[1],
+ sizeof (wc.blinded_planchet.details.cs_blinded_planchet.c[1])),
+ GNUNET_JSON_spec_end ()
+ };
enum TALER_ErrorCode ec;
struct TEH_DenominationKey *dk;
@@ -445,7 +476,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
return mret;
}
}
-
+//FIXME:
if (0 >
TALER_amount_add (&wc.collectable.amount_with_fee,
&dk->meta.value,
@@ -456,6 +487,61 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW,
NULL);
+ // parse coin_ev field, must be done after dk lookup to know denom cipher
+ {
+ enum GNUNET_GenericReturnValue res;
+ wc.blinded_planchet.cipher = dk->denom_pub.cipher;
+ switch (wc.blinded_planchet.cipher)
+ {
+ case TALER_DENOMINATION_RSA:
+ res = TALER_MHD_parse_json_data (rc->connection,
+ root,
+ coin_ev_rsa_spec);
+ if (GNUNET_OK != res)
+ return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
+ coin_ev_spec = coin_ev_rsa_spec;
+ break;
+ case TALER_DENOMINATION_CS:
+ // coin_ev for CS is nested
+ res = TALER_MHD_parse_json_data (rc->connection,
+ root,
+ coin_ev_cs_json_spec);
+ if (GNUNET_OK != res)
+ return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
+ res = TALER_MHD_parse_json_data (rc->connection,
+ coin_ev_cs_json,
+ coin_ev_cs_spec);
+ GNUNET_JSON_parse_free (coin_ev_cs_json_spec);
+ if (GNUNET_OK != res)
+ return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
+ coin_ev_spec = coin_ev_cs_spec;
+ break;
+ default:
+ GNUNET_break (0);
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ NULL);
+ }
+ }
+
+ {
+ if (0 >
+ TALER_amount_add (&wc.collectable.amount_with_fee,
+ &dk->meta.value,
+ &dk->meta.fee_withdraw))
+ {
+ GNUNET_JSON_parse_free (spec);
+ if (NULL != coin_ev_spec)
+ GNUNET_JSON_parse_free (coin_ev_spec);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW,
+ NULL);
+ }
+ TALER_amount_hton (&wc.wsrd.amount_with_fee,
+ &wc.collectable.amount_with_fee);
}
TALER_amount_hton (&wc.wsrd.amount_with_fee,
&wc.collectable.amount_with_fee);
@@ -468,9 +554,30 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
= htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
wc.wsrd.h_denomination_pub
= wc.collectable.denom_pub_hash;
- TALER_coin_ev_hash (wc.blinded_msg,
- wc.blinded_msg_len,
- &wc.wsrd.h_coin_envelope);
+ switch (wc.blinded_planchet.cipher)
+ {
+ case TALER_DENOMINATION_RSA:
+ TALER_coin_ev_hash (
+ wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
+ wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size,
+ &wc.wsrd.h_coin_envelope);
+ break;
+ case TALER_DENOMINATION_CS:
+ TALER_coin_ev_hash (
+ &wc.blinded_planchet.details.cs_blinded_planchet,
+ sizeof (wc.blinded_planchet.details.cs_blinded_planchet),
+ &wc.wsrd.h_coin_envelope);
+ break;
+ default:
+ GNUNET_break (0);
+ GNUNET_JSON_parse_free (spec);
+ if (NULL != coin_ev_spec)
+ GNUNET_JSON_parse_free (coin_ev_spec);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ NULL);
+ }
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW,
@@ -481,23 +588,50 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
TALER_LOG_WARNING (
"Client supplied invalid signature for withdraw request\n");
GNUNET_JSON_parse_free (spec);
+ if (NULL != coin_ev_spec)
+ GNUNET_JSON_parse_free (coin_ev_spec);
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_FORBIDDEN,
TALER_EC_EXCHANGE_WITHDRAW_RESERVE_SIGNATURE_INVALID,
NULL);
}
+ // TODO: if CS: check nonce for reuse
+
/* Sign before transaction! */
ec = TALER_EC_NONE;
- wc.collectable.sig
- = TEH_keys_denomination_sign (&wc.collectable.denom_pub_hash,
- wc.blinded_msg,
- wc.blinded_msg_len,
- &ec);
+ switch (wc.blinded_planchet.cipher)
+ {
+ case TALER_DENOMINATION_RSA:
+ wc.collectable.sig = TEH_keys_denomination_sign (
+ &wc.collectable.denom_pub_hash,
+ wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
+ wc.blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size,
+ &ec);
+ break;
+ case TALER_DENOMINATION_CS:
+ wc.collectable.sig = TEH_keys_denomination_sign (
+ &wc.collectable.denom_pub_hash,
+ &wc.blinded_planchet.details.cs_blinded_planchet,
+ sizeof (wc.blinded_planchet.details.cs_blinded_planchet),
+ &ec);
+ break;
+ default:
+ GNUNET_break (0);
+ GNUNET_JSON_parse_free (spec);
+ if (NULL != coin_ev_spec)
+ GNUNET_JSON_parse_free (coin_ev_spec);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ NULL);
+ }
if (TALER_EC_NONE != ec)
{
GNUNET_break (0);
GNUNET_JSON_parse_free (spec);
+ if (NULL != coin_ev_spec)
+ GNUNET_JSON_parse_free (coin_ev_spec);
return TALER_MHD_reply_with_ec (rc->connection,
ec,
NULL);
@@ -519,12 +653,16 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
(or we might have done it optimistically above). */
TALER_blinded_denom_sig_free (&wc.collectable.sig);
GNUNET_JSON_parse_free (spec);
+ if (NULL != coin_ev_spec)
+ GNUNET_JSON_parse_free (coin_ev_spec);
return mhd_ret;
}
}
/* Clean up and send back final response */
GNUNET_JSON_parse_free (spec);
+ if (NULL != coin_ev_spec)
+ GNUNET_JSON_parse_free (coin_ev_spec);
{
MHD_RESULT ret;
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index d5746c5c8..c6bebbeef 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -1333,6 +1333,30 @@ TALER_TESTING_cmd_withdraw_amount_reuse_key (
/**
+ * Create a CS withdraw command, letting the caller specify
+ * the desired amount as string and also re-using an existing
+ * coin private key in the process (violating the specification,
+ * which will result in an error when spending the coin!).
+ *
+ * @param label command label.
+ * @param reserve_reference command providing us with a reserve to withdraw from
+ * @param amount how much we withdraw.
+ * @param coin_ref reference to (withdraw/reveal) command of a coin
+ * from which we should re-use the private key
+ * @param expected_response_code which HTTP response code
+ * we expect from the exchange.
+ * @return the withdraw command to be executed by the interpreter.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_withdraw_cs_amount_reuse_key (
+ const char *label,
+ const char *reserve_reference,
+ const char *amount,
+ const char *coin_ref,
+ unsigned int expected_response_code);
+
+
+/**
* Create withdraw command, letting the caller specify the
* amount by a denomination key.
*
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index c07129d1a..6ee9c15a7 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -388,6 +388,7 @@ parse_denom_sig (void *cls,
}
return GNUNET_OK;
}
+ // TODO: case TALER_DENOMINATION_CS:
default:
GNUNET_break_op (0);
return GNUNET_SYSERR;
@@ -483,6 +484,29 @@ parse_blinded_denom_sig (void *cls,
}
return GNUNET_OK;
}
+ case TALER_DENOMINATION_CS:
+ {
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_uint32 ("b",
+ &denom_sig->details.blinded_cs_answer.b),
+ GNUNET_JSON_spec_fixed_auto ("s",
+ &denom_sig->details.blinded_cs_answer.
+ s_scalar),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (root,
+ ispec,
+ &emsg,
+ &eline))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+ }
+ break;
default:
GNUNET_break_op (0);
return GNUNET_SYSERR;
diff --git a/src/json/json_pack.c b/src/json/json_pack.c
index 869867189..cc147c4c0 100644
--- a/src/json/json_pack.c
+++ b/src/json/json_pack.c
@@ -125,14 +125,21 @@ TALER_JSON_pack_blinded_denom_sig (
switch (sig->cipher)
{
case TALER_DENOMINATION_RSA:
- ps.object
- = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_uint64 ("cipher",
- TALER_DENOMINATION_RSA),
- GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature",
- sig->details.blinded_rsa_signature));
+ ps.object = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_uint64 ("cipher",
+ TALER_DENOMINATION_RSA),
+ GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature",
+ sig->details.blinded_rsa_signature));
+ break;
+ case TALER_DENOMINATION_CS:
+ ps.object = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_uint64 ("cipher",
+ TALER_DENOMINATION_CS),
+ GNUNET_JSON_pack_uint64 ("b",
+ sig->details.blinded_cs_answer.b),
+ GNUNET_JSON_pack_data_auto ("s",
+ &sig->details.blinded_cs_answer.s_scalar));
break;
- // TODO: case TALER_DENOMINATION_CS:
default:
GNUNET_assert (0);
}
diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c
index 91838d4ce..2c57797fd 100644
--- a/src/lib/exchange_api_withdraw.c
+++ b/src/lib/exchange_api_withdraw.c
@@ -59,11 +59,21 @@ struct TALER_EXCHANGE_WithdrawHandle
void *cb_cls;
/**
+ * Reserve private key.
+ */
+ const struct TALER_ReservePrivateKeyP *reserve_priv;
+
+ /**
* Secrets of the planchet.
*/
struct TALER_PlanchetSecretsP ps;
/**
+ * Details of the planchet.
+ */
+ struct TALER_PlanchetDetail pd;
+
+ /**
* Denomination key we are withdrawing.
*/
struct TALER_EXCHANGE_DenomPublicKey pk;
@@ -162,24 +172,44 @@ withdraw_cs_stage_two_callback (void *cls,
const struct TALER_EXCHANGE_CsRResponse *csrr)
{
struct TALER_EXCHANGE_WithdrawHandle *wh = cls;
- // TODO: this should only be set for non-OK cases
- struct TALER_EXCHANGE_WithdrawResponse wr = {
- .hr = csrr->hr
- };
- // switch (csrr->hr.http_status)
- // {
- // case MHD_HTTP_OK:
- // // TODO: implement rest of withdraw
- // break;
- // default:
- // break;
- // }
+ wh->csrh = NULL;
- // TODO: this should only be called for non-OK cases
- wh->cb (wh->cb_cls,
- &wr);
- TALER_EXCHANGE_withdraw_cancel (wh);
+ GNUNET_assert (TALER_DENOMINATION_CS == wh->pk.key.cipher);
+
+ switch (csrr->hr.http_status)
+ {
+ case MHD_HTTP_OK:
+ wh->ps.cs_r_pub = csrr->details.success.r_pubs;
+ TALER_blinding_secret_create (&wh->ps.blinding_key,
+ wh->pk.key.cipher,
+ &wh->ps.coin_priv,
+ &wh->ps.cs_r_pub);
+ if (GNUNET_OK !=
+ TALER_planchet_prepare (&wh->pk.key,
+ &wh->ps,
+ &wh->c_hash,
+ &wh->pd))
+ {
+ GNUNET_break (0);
+ GNUNET_free (wh);
+ }
+ wh->wh2 = TALER_EXCHANGE_withdraw2 (wh->exchange,
+ &wh->pd,
+ wh->reserve_priv,
+ &handle_reserve_withdraw_finished,
+ wh);
+ break;
+ default:
+ // the CSR request went wrong -> serve response to the callback
+ struct TALER_EXCHANGE_WithdrawResponse wr = {
+ .hr = csrr->hr
+ };
+ wh->cb (wh->cb_cls,
+ &wr);
+ TALER_EXCHANGE_withdraw_cancel (wh);
+ break;
+ }
}
@@ -210,16 +240,19 @@ TALER_EXCHANGE_withdraw (
TALER_EXCHANGE_WithdrawCallback res_cb,
void *res_cb_cls)
{
- struct TALER_PlanchetDetail pd;
struct TALER_EXCHANGE_WithdrawHandle *wh;
wh = GNUNET_new (struct TALER_EXCHANGE_WithdrawHandle);
wh->exchange = exchange;
wh->cb = res_cb;
wh->cb_cls = res_cb_cls;
- wh->pk = *pk;
+ wh->reserve_priv = reserve_priv;
wh->ps = *ps;
+ wh->pk = *pk;
wh->csrh = NULL;
+
+ TALER_denom_pub_deep_copy (&wh->pk.key,
+ &pk->key);
switch (pk->key.cipher)
{
case TALER_DENOMINATION_RSA:
@@ -227,27 +260,28 @@ TALER_EXCHANGE_withdraw (
TALER_planchet_prepare (&pk->key,
ps,
&wh->c_hash,
- &pd))
+ &wh->pd))
{
GNUNET_break (0);
GNUNET_free (wh);
return NULL;
}
- TALER_denom_pub_deep_copy (&wh->pk.key,
- &pk->key);
wh->wh2 = TALER_EXCHANGE_withdraw2 (exchange,
- &pd,
- reserve_priv,
+ &wh->pd,
+ wh->reserve_priv,
&handle_reserve_withdraw_finished,
wh);
- GNUNET_free (pd.blinded_planchet.details.rsa_blinded_planchet.blinded_msg);
+ GNUNET_free (
+ wh->pd.blinded_planchet.details.rsa_blinded_planchet.blinded_msg);
return wh;
case TALER_DENOMINATION_CS:
- struct TALER_WithdrawNonce nonce;
- TALER_cs_withdraw_nonce_derive (&ps->coin_priv, &nonce);
+ TALER_cs_withdraw_nonce_derive (&ps->coin_priv,
+ &wh->pd.blinded_planchet.details.
+ cs_blinded_planchet.nonce);
wh->csrh = TALER_EXCHANGE_csr (exchange,
pk,
- &nonce,
+ &wh->pd.blinded_planchet.details.
+ cs_blinded_planchet.nonce,
&withdraw_cs_stage_two_callback,
wh);
return wh;
diff --git a/src/lib/exchange_api_withdraw2.c b/src/lib/exchange_api_withdraw2.c
index c8eb31822..cb767e434 100644
--- a/src/lib/exchange_api_withdraw2.c
+++ b/src/lib/exchange_api_withdraw2.c
@@ -437,11 +437,26 @@ TALER_EXCHANGE_withdraw2 (
TALER_amount_hton (&req.amount_with_fee,
&wh->requested_amount);
- TALER_coin_ev_hash (
- pd->blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
- pd->blinded_planchet.details.rsa_blinded_planchet.
- blinded_msg_size,
- &req.h_coin_envelope);
+ switch (dk->key.cipher)
+ {
+ case TALER_DENOMINATION_RSA:
+ TALER_coin_ev_hash (
+ pd->blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
+ pd->blinded_planchet.details.rsa_blinded_planchet.
+ blinded_msg_size,
+ &req.h_coin_envelope);
+ break;
+ case TALER_DENOMINATION_CS:
+ TALER_coin_ev_hash (
+ &pd->blinded_planchet.details.cs_blinded_planchet,
+ sizeof (pd->blinded_planchet.details.cs_blinded_planchet),
+ &req.h_coin_envelope);
+ break;
+ default:
+ GNUNET_break (0);
+ GNUNET_free (wh);
+ return NULL;
+ }
GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
&req,
&reserve_sig.eddsa_signature);
@@ -449,17 +464,44 @@ TALER_EXCHANGE_withdraw2 (
{
json_t *withdraw_obj;
-
- withdraw_obj = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_data_auto ("denom_pub_hash",
- &pd->denom_pub_hash),
- GNUNET_JSON_pack_data_varsize ("coin_ev",
- pd->blinded_planchet.details.
- rsa_blinded_planchet.blinded_msg,
- pd->blinded_planchet.details.
- rsa_blinded_planchet.blinded_msg_size),
- GNUNET_JSON_pack_data_auto ("reserve_sig",
- &reserve_sig));
+ switch (dk->key.cipher)
+ {
+ case TALER_DENOMINATION_RSA:
+ withdraw_obj = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_data_auto ("denom_pub_hash",
+ &pd->denom_pub_hash),
+ GNUNET_JSON_pack_data_varsize ("coin_ev",
+ pd->blinded_planchet.details.
+ rsa_blinded_planchet.blinded_msg,
+ pd->blinded_planchet.details.
+ rsa_blinded_planchet.blinded_msg_size),
+ GNUNET_JSON_pack_data_auto ("reserve_sig",
+ &reserve_sig));
+ break;
+ case TALER_DENOMINATION_CS:
+ json_t *coin_ev_object = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_data_auto ("nonce",
+ &pd->blinded_planchet.details.
+ cs_blinded_planchet.nonce),
+ GNUNET_JSON_pack_data_auto ("c0",
+ &pd->blinded_planchet.details.
+ cs_blinded_planchet.c[0]),
+ GNUNET_JSON_pack_data_auto ("c1",
+ &pd->blinded_planchet.details.
+ cs_blinded_planchet.c[1]));
+ withdraw_obj = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_data_auto ("denom_pub_hash",
+ &pd->denom_pub_hash),
+ GNUNET_JSON_pack_object_steal ("coin_ev",
+ coin_ev_object),
+ GNUNET_JSON_pack_data_auto ("reserve_sig",
+ &reserve_sig));
+ break;
+ default:
+ GNUNET_break (0);
+ GNUNET_free (wh);
+ return NULL;
+ }
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Attempting to withdraw from reserve %s\n",
TALER_B2S (&wh->reserve_pub));
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c
index c04161d0e..ca1e94efb 100644
--- a/src/pq/pq_query_helper.c
+++ b/src/pq/pq_query_helper.c
@@ -290,7 +290,9 @@ qconv_denom_sig (void *cls,
denom_sig->details.rsa_signature,
&tbuf);
break;
- // TODO: add case for Clause-Schnorr
+ case TALER_DENOMINATION_CS:
+ tlen = sizeof (denom_sig->details.cs_signature);
+ break;
default:
GNUNET_assert (0);
}
@@ -307,7 +309,11 @@ qconv_denom_sig (void *cls,
tlen);
GNUNET_free (tbuf);
break;
- // TODO: add case for Clause-Schnorr
+ case TALER_DENOMINATION_CS:
+ memcpy (&buf[sizeof (be)],
+ &denom_sig->details.cs_signature,
+ tlen);
+ break;
default:
GNUNET_assert (0);
}
@@ -380,7 +386,9 @@ qconv_blinded_denom_sig (void *cls,
denom_sig->details.blinded_rsa_signature,
&tbuf);
break;
- // TODO: add case for Clause-Schnorr
+ case TALER_DENOMINATION_CS:
+ tlen = sizeof (denom_sig->details.blinded_cs_answer);
+ break;
default:
GNUNET_assert (0);
}
@@ -397,7 +405,11 @@ qconv_blinded_denom_sig (void *cls,
tlen);
GNUNET_free (tbuf);
break;
- // TODO: add case for Clause-Schnorr
+ case TALER_DENOMINATION_CS:
+ memcpy (&buf[sizeof (be)],
+ &denom_sig->details.blinded_cs_answer,
+ tlen);
+ break;
default:
GNUNET_assert (0);
}
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
index d6b0eb7bb..2009f0e33 100644
--- a/src/pq/pq_result_helper.c
+++ b/src/pq/pq_result_helper.c
@@ -670,7 +670,16 @@ extract_blinded_denom_sig (void *cls,
return GNUNET_SYSERR;
}
return GNUNET_OK;
- // FIXME: add CS case!
+ case TALER_DENOMINATION_CS:
+ if (sizeof (sig->details.blinded_cs_answer) != len)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ memcpy (&sig->details.blinded_cs_answer,
+ res,
+ len);
+ return GNUNET_OK;
default:
GNUNET_break (0);
}
diff --git a/src/testing/test_exchange_api.c b/src/testing/test_exchange_api.c
index 29a3e5c6f..ba293d4b9 100644
--- a/src/testing/test_exchange_api.c
+++ b/src/testing/test_exchange_api.c
@@ -413,49 +413,49 @@ run (void *cls,
/**
* Move money to the exchange's bank account.
*/
- CMD_TRANSFER_TO_EXCHANGE ("create-reserve-1",
+ CMD_TRANSFER_TO_EXCHANGE ("create-reserve-cs-1",
"EUR:6.02"),
- TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-1",
+ TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-cs-1",
"EUR:6.02",
bc.user42_payto,
bc.exchange_payto,
- "create-reserve-1"),
+ "create-reserve-cs-1"),
/**
* Make a reserve exist, according to the previous
* transfer.
*/
- CMD_EXEC_WIREWATCH ("wirewatch-1"),
+ CMD_EXEC_WIREWATCH ("wirewatch-cs-1"),
/**
* Withdraw EUR:5.
*/
TALER_TESTING_cmd_withdraw_cs_amount ("withdraw-cs-coin-1",
- "create-reserve-1",
+ "create-reserve-cs-1",
"EUR:5",
MHD_HTTP_OK),
- // TODO: rest of the tests
- // /**
- // * Withdraw EUR:1 using the SAME private coin key as for the previous coin
- // * (in violation of the specification, to be detected on spending!).
- // */
- // TALER_TESTING_cmd_withdraw_amount_reuse_key ("withdraw-coin-1x",
- // "create-reserve-1",
- // "EUR:1",
- // "withdraw-coin-1",
- // MHD_HTTP_OK),
- // /**
- // * Check the reserve is depleted.
- // */
- // TALER_TESTING_cmd_status ("status-1",
- // "create-reserve-1",
- // "EUR:0",
- // MHD_HTTP_OK),
- // /*
- // * Try to overdraw.
- // */
- // TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2",
- // "create-reserve-1",
- // "EUR:5",
- // MHD_HTTP_CONFLICT),
+ /**
+ * Withdraw EUR:1 using the SAME private coin key as for the previous coin
+ * (in violation of the specification, to be detected on spending!).
+ */
+ TALER_TESTING_cmd_withdraw_cs_amount_reuse_key ("withdraw-cs-coin-1x",
+ "create-reserve-cs-1",
+ "EUR:1",
+ "withdraw-cs-coin-1",
+ MHD_HTTP_OK),
+ /**
+ * Check the reserve is depleted.
+ */
+ TALER_TESTING_cmd_status ("status-cs-1",
+ "create-reserve-cs-1",
+ "EUR:0",
+ MHD_HTTP_OK),
+ /*
+ * Try to overdraw.
+ */
+ TALER_TESTING_cmd_withdraw_cs_amount ("withdraw-cs-coin-2",
+ "create-reserve-cs-1",
+ "EUR:5",
+ MHD_HTTP_CONFLICT),
+ // TODO: add test for nonce reuse
TALER_TESTING_cmd_end ()
};
diff --git a/src/testing/testing_api_cmd_withdraw.c b/src/testing/testing_api_cmd_withdraw.c
index e07eac341..2a98765f4 100644
--- a/src/testing/testing_api_cmd_withdraw.c
+++ b/src/testing/testing_api_cmd_withdraw.c
@@ -266,13 +266,6 @@ reserve_withdraw_cb (void *cls,
switch (wr->hr.http_status)
{
case MHD_HTTP_OK:
- // TODO: remove
- // temporary make test successful when CS
- if (TALER_DENOMINATION_CS == ws->cipher)
- {
- break;
- }
-
TALER_denom_sig_deep_copy (&ws->sig,
&wr->details.success.sig);
if (0 != ws->total_backoff.rel_value_us)
@@ -661,6 +654,8 @@ TALER_TESTING_cmd_withdraw_amount_reuse_key (
const char *coin_ref,
unsigned int expected_response_code)
{
+ // TODO: ATM this is hardcoded to RSA denominations
+ // (use TALER_TESTING_cmd_withdraw_cs_amount for Clause Schnorr)
struct TALER_TESTING_Command cmd;
cmd = TALER_TESTING_cmd_withdraw_amount (label,
@@ -676,6 +671,29 @@ TALER_TESTING_cmd_withdraw_amount_reuse_key (
}
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_withdraw_cs_amount_reuse_key (
+ const char *label,
+ const char *reserve_reference,
+ const char *amount,
+ const char *coin_ref,
+ unsigned int expected_response_code)
+{
+ struct TALER_TESTING_Command cmd;
+
+ cmd = TALER_TESTING_cmd_withdraw_cs_amount (label,
+ reserve_reference,
+ amount,
+ expected_response_code);
+ {
+ struct WithdrawState *ws = cmd.cls;
+
+ ws->reuse_coin_key_ref = coin_ref;
+ }
+ return cmd;
+}
+
+
/**
* Create withdraw command, letting the caller specify the
* amount by a denomination key.