aboutsummaryrefslogtreecommitdiff
path: root/src/mint/taler-mint-httpd_db.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mint/taler-mint-httpd_db.c')
-rw-r--r--src/mint/taler-mint-httpd_db.c227
1 files changed, 121 insertions, 106 deletions
diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c
index c6f0fe2cb..bf10cd29e 100644
--- a/src/mint/taler-mint-httpd_db.c
+++ b/src/mint/taler-mint-httpd_db.c
@@ -22,12 +22,31 @@
22 * - actually abstract DB implementation (i.e. via plugin logic) 22 * - actually abstract DB implementation (i.e. via plugin logic)
23 * (this file should remain largely unchanged with the exception 23 * (this file should remain largely unchanged with the exception
24 * of the PQ-specific DB handle types) 24 * of the PQ-specific DB handle types)
25 * - /deposit: properly check existing deposits 25 * - /withdraw/sign: all
26 * - /deposit: properly perform commit (check return value) 26 * + properly check all conditions and handle errors
27 * - /deposit: check for leaks 27 * + properly check transaction logic
28 * - ALL: check API: given structs are usually not perfect, as they 28 * + check for leaks
29 * often contain too many fields for the context 29 * + check low-level API
30 * - ALL: check transactional behavior 30 * - /refresh/melt: all
31 * + properly check all conditions and handle errors
32 * + properly check transaction logic
33 * + check for leaks
34 * + check low-level API
35 * - /refresh/commit: all
36 * + properly check all conditions and handle errors
37 * + properly check transaction logic
38 * + check for leaks
39 * + check low-level API
40 * - /refresh/reveal: all
41 * + properly check all conditions and handle errors
42 * + properly check transaction logic
43 * + check for leaks
44 * + check low-level API
45 * - /refresh/link: all
46 * + properly check all conditions and handle errors
47 * + properly check transaction logic
48 * + check for leaks
49 * + check low-level API
31 */ 50 */
32#include "platform.h" 51#include "platform.h"
33#include <pthread.h> 52#include <pthread.h>
@@ -43,6 +62,26 @@
43 62
44 63
45/** 64/**
65 * Get an amount in the mint's currency that is zero.
66 *
67 * @return zero amount in the mint's currency
68 */
69static struct TALER_Amount
70mint_amount_native_zero ()
71{
72 struct TALER_Amount amount;
73
74 memset (&amount,
75 0,
76 sizeof (amount));
77 memcpy (amount.currency,
78 MINT_CURRENCY,
79 strlen (MINT_CURRENCY) + 1);
80 return amount;
81}
82
83
84/**
46 * Execute a deposit. The validity of the coin and signature 85 * Execute a deposit. The validity of the coin and signature
47 * have already been checked. The database must now check that 86 * have already been checked. The database must now check that
48 * the coin is not (double or over) spent, and execute the 87 * the coin is not (double or over) spent, and execute the
@@ -58,6 +97,15 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
58{ 97{
59 PGconn *db_conn; 98 PGconn *db_conn;
60 struct TALER_MINT_DB_TransactionList *tl; 99 struct TALER_MINT_DB_TransactionList *tl;
100 struct TALER_MINT_DB_TransactionList *pos;
101 struct TALER_Amount spent;
102 struct TALER_Amount value;
103 struct TALER_Amount fee_deposit;
104 struct TALER_Amount fee_withdraw;
105 struct TALER_Amount fee_refresh;
106 struct MintKeyState *mks;
107 struct TALER_MINT_DenomKeyIssuePriv *dki;
108 int ret;
61 109
62 if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) 110 if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
63 { 111 {
@@ -76,6 +124,14 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
76 &deposit->merchant_pub, 124 &deposit->merchant_pub,
77 &deposit->amount); 125 &deposit->amount);
78 } 126 }
127 mks = TALER_MINT_key_state_acquire ();
128 dki = TALER_MINT_get_denom_key (mks,
129 deposit->coin.denom_pub);
130 value = TALER_amount_ntoh (dki->issue.value);
131 fee_deposit = TALER_amount_ntoh (dki->issue.fee_deposit);
132 fee_refresh = TALER_amount_ntoh (dki->issue.fee_refresh);
133 TALER_MINT_key_state_release (mks);
134
79 if (GNUNET_OK != 135 if (GNUNET_OK !=
80 TALER_MINT_DB_transaction (db_conn)) 136 TALER_MINT_DB_transaction (db_conn))
81 { 137 {
@@ -84,19 +140,48 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
84 } 140 }
85 tl = TALER_MINT_DB_get_coin_transactions (db_conn, 141 tl = TALER_MINT_DB_get_coin_transactions (db_conn,
86 &deposit->coin.coin_pub); 142 &deposit->coin.coin_pub);
87 if (NULL != tl) 143 spent = fee_withdraw; /* fee for THIS transaction */
144 /* FIXME: need to deal better with integer overflows
145 in the logic that follows! (change amount.c API!) */
146 spent = TALER_amount_add (spent,
147 deposit->amount);
148
149 for (pos = tl; NULL != pos; pos = pos->next)
88 { 150 {
89 // FIXME: in the future, check if there's enough credits 151 switch (pos->type)
90 // left on the coin. For now: refuse 152 {
91 // FIXME: return more information here 153 case TALER_MINT_DB_TT_DEPOSIT:
92 TALER_MINT_DB_rollback (db_conn); 154 spent = TALER_amount_add (spent,
93 return TALER_MINT_reply_json_pack (connection, 155 pos->details.deposit->amount);
94 MHD_HTTP_FORBIDDEN, 156 spent = TALER_amount_add (spent,
95 "{s:s}", 157 fee_deposit);
96 "error", "insufficient funds"); 158 break;
159 case TALER_MINT_DB_TT_REFRESH_MELT:
160 spent = TALER_amount_add (spent,
161 pos->details.melt->amount);
162 spent = TALER_amount_add (spent,
163 fee_refresh);
164 break;
165 case TALER_MINT_DB_TT_LOCK:
166 /* should check if lock is still active,
167 and if it is for THIS operation; if
168 lock is inactive, delete it; if lock
169 is for THIS operation, ignore it;
170 if lock is for another operation,
171 count it! */
172 GNUNET_assert (0); // FIXME: not implemented!
173 break;
174 }
97 } 175 }
98 176
99 177 if (0 < TALER_amount_cmp (spent, value))
178 {
179 TALER_MINT_DB_rollback (db_conn);
180 ret = TALER_MINT_reply_insufficient_funds (connection,
181 tl);
182 TALER_MINT_DB_free_coin_transaction_list (tl);
183 return ret;
184 }
100 TALER_MINT_DB_free_coin_transaction_list (tl); 185 TALER_MINT_DB_free_coin_transaction_list (tl);
101 186
102 if (GNUNET_OK != 187 if (GNUNET_OK !=
@@ -124,37 +209,6 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection,
124} 209}
125 210
126 211
127
128
129
130
131
132
133
134
135/**
136 * Sign a reserve's status with the current signing key.
137 * FIXME: not sure why we do this. Should just return
138 * existing list of operations on the reserve.
139 *
140 * @param reserve the reserve to sign
141 * @param key_state the key state containing the current
142 * signing private key
143 */
144static void
145sign_reserve (struct Reserve *reserve,
146 struct MintKeyState *key_state)
147{
148 reserve->status_sign_pub = key_state->current_sign_key_issue.issue.signkey_pub;
149 reserve->status_sig_purpose.purpose = htonl (TALER_SIGNATURE_RESERVE_STATUS);
150 reserve->status_sig_purpose.size = htonl (sizeof (struct Reserve) -
151 offsetof (struct Reserve, status_sig_purpose));
152 GNUNET_CRYPTO_eddsa_sign (&key_state->current_sign_key_issue.signkey_priv,
153 &reserve->status_sig_purpose,
154 &reserve->status_sig);
155}
156
157
158/** 212/**
159 * Execute a /withdraw/status. 213 * Execute a /withdraw/status.
160 * 214 *
@@ -167,50 +221,25 @@ TALER_MINT_db_execute_withdraw_status (struct MHD_Connection *connection,
167 const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub) 221 const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub)
168{ 222{
169 PGconn *db_conn; 223 PGconn *db_conn;
224 struct ReserveHistory *rh;
170 int res; 225 int res;
171 struct Reserve reserve;
172 struct MintKeyState *key_state;
173 int must_update = GNUNET_NO;
174 226
175 if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) 227 if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
176 { 228 {
177 GNUNET_break (0); 229 GNUNET_break (0);
178 return TALER_MINT_reply_internal_db_error (connection); 230 return TALER_MINT_reply_internal_db_error (connection);
179 } 231 }
180 res = TALER_MINT_DB_get_reserve (db_conn, 232 rh = TALER_MINT_DB_get_reserve_history (db_conn,
181 reserve_pub, 233 reserve_pub);
182 &reserve); 234 if (NULL == rh)
183 /* check if these are really the matching error codes,
184 seems odd... */
185 if (GNUNET_SYSERR == res)
186 return TALER_MINT_reply_json_pack (connection, 235 return TALER_MINT_reply_json_pack (connection,
187 MHD_HTTP_NOT_FOUND, 236 MHD_HTTP_NOT_FOUND,
188 "{s:s}", 237 "{s:s}",
189 "error", 238 "error", "Reserve not found");
190 "Reserve not found"); 239 res = TALER_MINT_reply_withdraw_status_success (connection,
191 if (GNUNET_OK != res) 240 rh);
192 { 241 TALER_MINT_DB_free_reserve_history (rh);
193 GNUNET_break (0); 242 return res;
194 return TALER_MINT_reply_internal_error (connection,
195 "Internal error");
196 }
197 key_state = TALER_MINT_key_state_acquire ();
198 if (0 != memcmp (&key_state->current_sign_key_issue.issue.signkey_pub,
199 &reserve.status_sign_pub,
200 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
201 {
202 sign_reserve (&reserve, key_state);
203 must_update = GNUNET_YES;
204 }
205 if ((GNUNET_YES == must_update) &&
206 (GNUNET_OK != TALER_MINT_DB_update_reserve (db_conn, &reserve, !must_update)))
207 {
208 GNUNET_break (0);
209 return MHD_YES;
210 }
211 return TALER_MINT_reply_withdraw_status_success (connection,
212 TALER_amount_ntoh (reserve.balance),
213 GNUNET_TIME_absolute_ntoh (reserve.expiration));
214} 243}
215 244
216 245
@@ -234,7 +263,7 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection,
234 const struct GNUNET_CRYPTO_EddsaSignature *signature) 263 const struct GNUNET_CRYPTO_EddsaSignature *signature)
235{ 264{
236 PGconn *db_conn; 265 PGconn *db_conn;
237 struct Reserve db_reserve; 266 struct ReserveHistory *rh;
238 struct MintKeyState *key_state; 267 struct MintKeyState *key_state;
239 struct CollectableBlindcoin collectable; 268 struct CollectableBlindcoin collectable;
240 struct TALER_MINT_DenomKeyIssuePriv *dki; 269 struct TALER_MINT_DenomKeyIssuePriv *dki;
@@ -270,15 +299,9 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection,
270 return res; 299 return res;
271 } 300 }
272 GNUNET_assert (GNUNET_NO == res); 301 GNUNET_assert (GNUNET_NO == res);
273 res = TALER_MINT_DB_get_reserve (db_conn, 302 rh = TALER_MINT_DB_get_reserve_history (db_conn,
274 reserve, 303 reserve);
275 &db_reserve); 304 if (NULL == rh)
276 if (GNUNET_SYSERR == res)
277 {
278 GNUNET_break (0);
279 return TALER_MINT_reply_internal_db_error (connection);
280 }
281 if (GNUNET_NO == res)
282 return TALER_MINT_reply_json_pack (connection, 305 return TALER_MINT_reply_json_pack (connection,
283 MHD_HTTP_NOT_FOUND, 306 MHD_HTTP_NOT_FOUND,
284 "{s:s}", 307 "{s:s}",
@@ -298,6 +321,8 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection,
298 321
299 amount_required = TALER_amount_add (TALER_amount_ntoh (dki->issue.value), 322 amount_required = TALER_amount_add (TALER_amount_ntoh (dki->issue.value),
300 TALER_amount_ntoh (dki->issue.fee_withdraw)); 323 TALER_amount_ntoh (dki->issue.fee_withdraw));
324 // FIX LOGIC!
325#if 0
301 if (0 < TALER_amount_cmp (amount_required, 326 if (0 < TALER_amount_cmp (amount_required,
302 TALER_amount_ntoh (db_reserve.balance))) 327 TALER_amount_ntoh (db_reserve.balance)))
303 return TALER_MINT_reply_json_pack (connection, 328 return TALER_MINT_reply_json_pack (connection,
@@ -329,6 +354,8 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection,
329 GNUNET_break (0); 354 GNUNET_break (0);
330 return TALER_MINT_reply_internal_db_error (connection); 355 return TALER_MINT_reply_internal_db_error (connection);
331 } 356 }
357#endif
358
332 collectable.denom_pub = (struct GNUNET_CRYPTO_rsa_PublicKey *) denomination_pub; 359 collectable.denom_pub = (struct GNUNET_CRYPTO_rsa_PublicKey *) denomination_pub;
333 collectable.sig = sig; 360 collectable.sig = sig;
334 collectable.reserve_pub = *reserve; 361 collectable.reserve_pub = *reserve;
@@ -401,21 +428,6 @@ refresh_accept_denoms (struct MHD_Connection *connection,
401} 428}
402 429
403 430
404/**
405 * Get an amount in the mint's currency that is zero.
406 *
407 * @return zero amount in the mint's currency
408 */
409static struct TALER_Amount
410mint_amount_native_zero ()
411{
412 struct TALER_Amount amount;
413
414 memset (&amount, 0, sizeof (amount));
415 memcpy (amount.currency, MINT_CURRENCY, strlen (MINT_CURRENCY) + 1);
416
417 return amount;
418}
419 431
420 432
421/** 433/**
@@ -1290,3 +1302,6 @@ TALER_MINT_db_execute_refresh_link (struct MHD_Connection *connection,
1290 json_decref (root); 1302 json_decref (root);
1291 return res; 1303 return res;
1292} 1304}
1305
1306
1307/* end of taler-mint-httpd_db.c */