diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-01-19 21:53:23 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-01-19 21:53:23 +0100 |
commit | ed51946442e5e22a7dea68f14ff2bf563503c755 (patch) | |
tree | bcdca621df102a52337ff7348dc262be43a48514 | |
parent | f9347d23953f771689d339b544370d3f9fdd97ba (diff) | |
download | exchange-ed51946442e5e22a7dea68f14ff2bf563503c755.tar.gz exchange-ed51946442e5e22a7dea68f14ff2bf563503c755.zip |
more code refactoring to separate parsing, db and response generation nicely
-rw-r--r-- | src/include/taler_json_lib.h | 20 | ||||
-rw-r--r-- | src/mint/mint.h | 192 | ||||
-rw-r--r-- | src/mint/mint_db.h | 143 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd.c | 2 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.c | 278 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.h | 66 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_keys.c | 2 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_keys.h | 2 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_refresh.c | 18 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_responses.c | 62 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_responses.h | 25 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_withdraw.c | 337 | ||||
-rw-r--r-- | src/util/json.c | 28 |
13 files changed, 647 insertions, 528 deletions
diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index b224c4b33..ec354cce7 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h | |||
@@ -27,8 +27,7 @@ | |||
27 | 27 | ||
28 | 28 | ||
29 | /** | 29 | /** |
30 | * Convert a TALER amount to a JSON | 30 | * Convert a TALER amount to a JSON object. |
31 | * object. | ||
32 | * | 31 | * |
33 | * @param amount the amount | 32 | * @param amount the amount |
34 | * @return a json object describing the amount | 33 | * @return a json object describing the amount |
@@ -47,6 +46,17 @@ json_t * | |||
47 | TALER_JSON_from_abs (struct GNUNET_TIME_Absolute stamp); | 46 | TALER_JSON_from_abs (struct GNUNET_TIME_Absolute stamp); |
48 | 47 | ||
49 | 48 | ||
49 | /** | ||
50 | * Convert a signature (with purpose) to a JSON object representation. | ||
51 | * | ||
52 | * @param purpose purpose of the signature | ||
53 | * @param signature the signature | ||
54 | * @return the JSON reporesentation of the signature with purpose | ||
55 | */ | ||
56 | json_t * | ||
57 | TALER_JSON_from_sig (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, | ||
58 | const struct GNUNET_CRYPTO_EddsaSignature *signature); | ||
59 | |||
50 | 60 | ||
51 | /** | 61 | /** |
52 | * Convert binary data to a JSON string | 62 | * Convert binary data to a JSON string |
@@ -65,7 +75,7 @@ TALER_JSON_from_data (const void *data, size_t size); | |||
65 | * | 75 | * |
66 | * @param json the json object representing Amount | 76 | * @param json the json object representing Amount |
67 | * @param r_amount where the amount has to be written | 77 | * @param r_amount where the amount has to be written |
68 | * @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error | 78 | * @return #GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error |
69 | */ | 79 | */ |
70 | int | 80 | int |
71 | TALER_JSON_to_amount (json_t *json, | 81 | TALER_JSON_to_amount (json_t *json, |
@@ -76,7 +86,7 @@ TALER_JSON_to_amount (json_t *json, | |||
76 | * | 86 | * |
77 | * @param json the json object representing absolute time in seconds | 87 | * @param json the json object representing absolute time in seconds |
78 | * @param r_abs where the time has to be written | 88 | * @param r_abs where the time has to be written |
79 | * @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error | 89 | * @return #GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error |
80 | */ | 90 | */ |
81 | int | 91 | int |
82 | TALER_JSON_to_abs (json_t *json, | 92 | TALER_JSON_to_abs (json_t *json, |
@@ -88,7 +98,7 @@ TALER_JSON_to_abs (json_t *json, | |||
88 | * @param json the json object representing data | 98 | * @param json the json object representing data |
89 | * @param out the pointer to hold the parsed data. | 99 | * @param out the pointer to hold the parsed data. |
90 | * @param out_size the size of r_data. | 100 | * @param out_size the size of r_data. |
91 | * @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error | 101 | * @return #GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error |
92 | */ | 102 | */ |
93 | int | 103 | int |
94 | TALER_JSON_to_data (json_t *json, | 104 | TALER_JSON_to_data (json_t *json, |
diff --git a/src/mint/mint.h b/src/mint/mint.h index 644a9d292..39dda7d5f 100644 --- a/src/mint/mint.h +++ b/src/mint/mint.h | |||
@@ -13,14 +13,15 @@ | |||
13 | You should have received a copy of the GNU General Public License along with | 13 | You should have received a copy of the GNU General Public License along with |
14 | TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> | 14 | TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> |
15 | */ | 15 | */ |
16 | |||
17 | /** | 16 | /** |
18 | * @file taler_mint.h | 17 | * @file mint.h |
19 | * @brief Common functionality for the mint | 18 | * @brief Common functionality for the mint |
20 | * @author Florian Dold | 19 | * @author Florian Dold |
21 | * @author Benedikt Mueller | 20 | * @author Benedikt Mueller |
21 | * | ||
22 | * TODO: | ||
23 | * - revisit and document `struct Deposit` members. | ||
22 | */ | 24 | */ |
23 | |||
24 | #ifndef _MINT_H | 25 | #ifndef _MINT_H |
25 | #define _MINT_H | 26 | #define _MINT_H |
26 | 27 | ||
@@ -55,11 +56,195 @@ struct TALER_MINT_DenomKeyIssuePriv | |||
55 | * not available. | 56 | * not available. |
56 | */ | 57 | */ |
57 | struct TALER_RSA_PrivateKey *denom_priv; | 58 | struct TALER_RSA_PrivateKey *denom_priv; |
59 | |||
58 | struct TALER_MINT_DenomKeyIssue issue; | 60 | struct TALER_MINT_DenomKeyIssue issue; |
59 | }; | 61 | }; |
60 | 62 | ||
61 | 63 | ||
62 | 64 | ||
65 | /** | ||
66 | * Public information about a coin. | ||
67 | */ | ||
68 | struct TALER_CoinPublicInfo | ||
69 | { | ||
70 | /** | ||
71 | * The coin's public key. | ||
72 | */ | ||
73 | struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; | ||
74 | |||
75 | /* | ||
76 | * The public key signifying the coin's denomination. | ||
77 | */ | ||
78 | struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; | ||
79 | |||
80 | /** | ||
81 | * Signature over coin_pub by denom_pub. | ||
82 | */ | ||
83 | struct TALER_RSA_Signature denom_sig; | ||
84 | }; | ||
85 | |||
86 | |||
87 | |||
88 | |||
89 | |||
90 | |||
91 | |||
92 | struct CollectableBlindcoin | ||
93 | { | ||
94 | struct TALER_RSA_BlindedSignaturePurpose ev; | ||
95 | struct TALER_RSA_Signature ev_sig; | ||
96 | struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; | ||
97 | struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; | ||
98 | struct GNUNET_CRYPTO_EddsaSignature reserve_sig; | ||
99 | }; | ||
100 | |||
101 | |||
102 | struct RefreshSession | ||
103 | { | ||
104 | int has_commit_sig; | ||
105 | struct GNUNET_CRYPTO_EddsaSignature commit_sig; | ||
106 | struct GNUNET_CRYPTO_EddsaPublicKey session_pub; | ||
107 | uint16_t num_oldcoins; | ||
108 | uint16_t num_newcoins; | ||
109 | uint16_t kappa; | ||
110 | uint16_t noreveal_index; | ||
111 | uint8_t reveal_ok; | ||
112 | }; | ||
113 | |||
114 | |||
115 | #define TALER_REFRESH_SHARED_SECRET_LENGTH (sizeof (struct GNUNET_HashCode)) | ||
116 | #define TALER_REFRESH_LINK_LENGTH (sizeof (struct LinkData)) | ||
117 | |||
118 | struct RefreshCommitLink | ||
119 | { | ||
120 | struct GNUNET_CRYPTO_EddsaPublicKey session_pub; | ||
121 | struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub; | ||
122 | uint16_t cnc_index; | ||
123 | uint16_t oldcoin_index; | ||
124 | char shared_secret_enc[sizeof (struct GNUNET_HashCode)]; | ||
125 | }; | ||
126 | |||
127 | struct LinkData | ||
128 | { | ||
129 | struct GNUNET_CRYPTO_EcdsaPrivateKey coin_priv; | ||
130 | struct TALER_RSA_BlindingKeyBinaryEncoded bkey_enc; | ||
131 | }; | ||
132 | |||
133 | |||
134 | GNUNET_NETWORK_STRUCT_BEGIN | ||
135 | |||
136 | struct SharedSecretEnc | ||
137 | { | ||
138 | char data[TALER_REFRESH_SHARED_SECRET_LENGTH]; | ||
139 | }; | ||
140 | |||
141 | |||
142 | struct LinkDataEnc | ||
143 | { | ||
144 | char data[sizeof (struct LinkData)]; | ||
145 | }; | ||
146 | |||
147 | GNUNET_NETWORK_STRUCT_END | ||
148 | |||
149 | struct RefreshCommitCoin | ||
150 | { | ||
151 | struct GNUNET_CRYPTO_EddsaPublicKey session_pub; | ||
152 | struct TALER_RSA_BlindedSignaturePurpose coin_ev; | ||
153 | uint16_t cnc_index; | ||
154 | uint16_t newcoin_index; | ||
155 | char link_enc[sizeof (struct LinkData)]; | ||
156 | }; | ||
157 | |||
158 | |||
159 | struct KnownCoin | ||
160 | { | ||
161 | struct TALER_CoinPublicInfo public_info; | ||
162 | struct TALER_Amount expended_balance; | ||
163 | int is_refreshed; | ||
164 | /** | ||
165 | * Refreshing session, only valid if | ||
166 | * is_refreshed==1. | ||
167 | */ | ||
168 | struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; | ||
169 | }; | ||
170 | |||
171 | |||
172 | /** | ||
173 | * Specification for a /deposit operation. | ||
174 | */ | ||
175 | struct Deposit | ||
176 | { | ||
177 | /* FIXME: should be TALER_CoinPublicInfo */ | ||
178 | struct GNUNET_CRYPTO_EddsaPublicKey coin_pub; | ||
179 | |||
180 | struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; | ||
181 | |||
182 | struct TALER_RSA_Signature coin_sig; | ||
183 | |||
184 | struct TALER_RSA_Signature ubsig; | ||
185 | |||
186 | /** | ||
187 | * Type of the deposit (also purpose of the signature). Either | ||
188 | * #TALER_SIGNATURE_DEPOSIT or #TALER_SIGNATURE_INCREMENTAL_DEPOSIT. | ||
189 | */ | ||
190 | struct TALER_RSA_SignaturePurpose purpose; | ||
191 | |||
192 | uint64_t transaction_id; | ||
193 | |||
194 | struct TALER_AmountNBO amount; | ||
195 | |||
196 | struct GNUNET_CRYPTO_EddsaPublicKey merchant_pub; | ||
197 | |||
198 | struct GNUNET_HashCode h_contract; | ||
199 | |||
200 | struct GNUNET_HashCode h_wire; | ||
201 | |||
202 | /* TODO: uint16_t wire_size */ | ||
203 | char wire[]; /* string encoded wire JSON object */ | ||
204 | |||
205 | }; | ||
206 | |||
207 | |||
208 | /** | ||
209 | * Reserve row. Corresponds to table 'reserves' in the mint's | ||
210 | * database. FIXME: not sure this is how we want to store this | ||
211 | * information. Also, may currently used in different ways in the | ||
212 | * code, so we might need to separate the struct into different ones | ||
213 | * depending on the context it is used in. | ||
214 | */ | ||
215 | struct Reserve | ||
216 | { | ||
217 | /** | ||
218 | * Signature over the purse. | ||
219 | * Only valid if (blind_session_missing==GNUNET_YES). | ||
220 | */ | ||
221 | struct GNUNET_CRYPTO_EddsaSignature status_sig; | ||
222 | /** | ||
223 | * Signature with purpose TALER_SIGNATURE_PURSE. | ||
224 | * Only valid if (blind_session_missing==GNUNET_YES). | ||
225 | */ | ||
226 | struct GNUNET_CRYPTO_EccSignaturePurpose status_sig_purpose; | ||
227 | /** | ||
228 | * Signing key used to sign the purse. | ||
229 | * Only valid if (blind_session_missing==GNUNET_YES). | ||
230 | */ | ||
231 | struct GNUNET_CRYPTO_EddsaPublicKey status_sign_pub; | ||
232 | /** | ||
233 | * Withdraw public key, identifies the purse. | ||
234 | * Only the customer knows the corresponding private key. | ||
235 | */ | ||
236 | struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; | ||
237 | /** | ||
238 | * Remaining balance in the purse. | ||
239 | */ | ||
240 | struct TALER_AmountNBO balance; | ||
241 | |||
242 | /** | ||
243 | * Expiration date for the purse. | ||
244 | */ | ||
245 | struct GNUNET_TIME_AbsoluteNBO expiration; | ||
246 | }; | ||
247 | |||
63 | 248 | ||
64 | 249 | ||
65 | 250 | ||
@@ -153,4 +338,3 @@ TALER_TALER_DB_extract_amount_nbo (PGresult *result, unsigned int row, | |||
153 | int indices[3], struct TALER_AmountNBO *denom_nbo); | 338 | int indices[3], struct TALER_AmountNBO *denom_nbo); |
154 | 339 | ||
155 | #endif /* _MINT_H */ | 340 | #endif /* _MINT_H */ |
156 | |||
diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h index 5fab7c02a..d5a74a45d 100644 --- a/src/mint/mint_db.h +++ b/src/mint/mint_db.h | |||
@@ -29,149 +29,8 @@ | |||
29 | #include "taler_util.h" | 29 | #include "taler_util.h" |
30 | #include "taler_rsa.h" | 30 | #include "taler_rsa.h" |
31 | #include "taler-mint-httpd_db.h" | 31 | #include "taler-mint-httpd_db.h" |
32 | #include "mint.h" | ||
32 | 33 | ||
33 | /** | ||
34 | * Public information about a coin. | ||
35 | */ | ||
36 | struct TALER_CoinPublicInfo | ||
37 | { | ||
38 | /** | ||
39 | * The coin's public key. | ||
40 | */ | ||
41 | struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; | ||
42 | |||
43 | /* | ||
44 | * The public key signifying the coin's denomination. | ||
45 | */ | ||
46 | struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; | ||
47 | |||
48 | /** | ||
49 | * Signature over coin_pub by denom_pub. | ||
50 | */ | ||
51 | struct TALER_RSA_Signature denom_sig; | ||
52 | }; | ||
53 | |||
54 | |||
55 | |||
56 | |||
57 | |||
58 | |||
59 | /** | ||
60 | * Reserve row. Corresponds to table 'reserves' in | ||
61 | * the mint's database. | ||
62 | */ | ||
63 | struct Reserve | ||
64 | { | ||
65 | /** | ||
66 | * Signature over the purse. | ||
67 | * Only valid if (blind_session_missing==GNUNET_YES). | ||
68 | */ | ||
69 | struct GNUNET_CRYPTO_EddsaSignature status_sig; | ||
70 | /** | ||
71 | * Signature with purpose TALER_SIGNATURE_PURSE. | ||
72 | * Only valid if (blind_session_missing==GNUNET_YES). | ||
73 | */ | ||
74 | struct GNUNET_CRYPTO_EccSignaturePurpose status_sig_purpose; | ||
75 | /** | ||
76 | * Signing key used to sign the purse. | ||
77 | * Only valid if (blind_session_missing==GNUNET_YES). | ||
78 | */ | ||
79 | struct GNUNET_CRYPTO_EddsaPublicKey status_sign_pub; | ||
80 | /** | ||
81 | * Withdraw public key, identifies the purse. | ||
82 | * Only the customer knows the corresponding private key. | ||
83 | */ | ||
84 | struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; | ||
85 | /** | ||
86 | * Remaining balance in the purse. | ||
87 | */ | ||
88 | struct TALER_AmountNBO balance; | ||
89 | |||
90 | /** | ||
91 | * Expiration date for the purse. | ||
92 | */ | ||
93 | struct GNUNET_TIME_AbsoluteNBO expiration; | ||
94 | }; | ||
95 | |||
96 | |||
97 | struct CollectableBlindcoin | ||
98 | { | ||
99 | struct TALER_RSA_BlindedSignaturePurpose ev; | ||
100 | struct TALER_RSA_Signature ev_sig; | ||
101 | struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; | ||
102 | struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; | ||
103 | struct GNUNET_CRYPTO_EddsaSignature reserve_sig; | ||
104 | }; | ||
105 | |||
106 | |||
107 | struct RefreshSession | ||
108 | { | ||
109 | int has_commit_sig; | ||
110 | struct GNUNET_CRYPTO_EddsaSignature commit_sig; | ||
111 | struct GNUNET_CRYPTO_EddsaPublicKey session_pub; | ||
112 | uint16_t num_oldcoins; | ||
113 | uint16_t num_newcoins; | ||
114 | uint16_t kappa; | ||
115 | uint16_t noreveal_index; | ||
116 | uint8_t reveal_ok; | ||
117 | }; | ||
118 | |||
119 | |||
120 | #define TALER_REFRESH_SHARED_SECRET_LENGTH (sizeof (struct GNUNET_HashCode)) | ||
121 | #define TALER_REFRESH_LINK_LENGTH (sizeof (struct LinkData)) | ||
122 | |||
123 | struct RefreshCommitLink | ||
124 | { | ||
125 | struct GNUNET_CRYPTO_EddsaPublicKey session_pub; | ||
126 | struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub; | ||
127 | uint16_t cnc_index; | ||
128 | uint16_t oldcoin_index; | ||
129 | char shared_secret_enc[sizeof (struct GNUNET_HashCode)]; | ||
130 | }; | ||
131 | |||
132 | struct LinkData | ||
133 | { | ||
134 | struct GNUNET_CRYPTO_EcdsaPrivateKey coin_priv; | ||
135 | struct TALER_RSA_BlindingKeyBinaryEncoded bkey_enc; | ||
136 | }; | ||
137 | |||
138 | |||
139 | GNUNET_NETWORK_STRUCT_BEGIN | ||
140 | |||
141 | struct SharedSecretEnc | ||
142 | { | ||
143 | char data[TALER_REFRESH_SHARED_SECRET_LENGTH]; | ||
144 | }; | ||
145 | |||
146 | |||
147 | struct LinkDataEnc | ||
148 | { | ||
149 | char data[sizeof (struct LinkData)]; | ||
150 | }; | ||
151 | |||
152 | GNUNET_NETWORK_STRUCT_END | ||
153 | |||
154 | struct RefreshCommitCoin | ||
155 | { | ||
156 | struct GNUNET_CRYPTO_EddsaPublicKey session_pub; | ||
157 | struct TALER_RSA_BlindedSignaturePurpose coin_ev; | ||
158 | uint16_t cnc_index; | ||
159 | uint16_t newcoin_index; | ||
160 | char link_enc[sizeof (struct LinkData)]; | ||
161 | }; | ||
162 | |||
163 | |||
164 | struct KnownCoin | ||
165 | { | ||
166 | struct TALER_CoinPublicInfo public_info; | ||
167 | struct TALER_Amount expended_balance; | ||
168 | int is_refreshed; | ||
169 | /** | ||
170 | * Refreshing session, only valid if | ||
171 | * is_refreshed==1. | ||
172 | */ | ||
173 | struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; | ||
174 | }; | ||
175 | 34 | ||
176 | int | 35 | int |
177 | TALER_MINT_DB_prepare (PGconn *db_conn); | 36 | TALER_MINT_DB_prepare (PGconn *db_conn); |
diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index 2c3b3d2e1..9dc03cdea 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <libpq-fe.h> | 28 | #include <libpq-fe.h> |
29 | #include <pthread.h> | 29 | #include <pthread.h> |
30 | #include "mint.h" | 30 | #include "mint.h" |
31 | #include "mint_db.h" | ||
32 | #include "taler_signatures.h" | 31 | #include "taler_signatures.h" |
33 | #include "taler_rsa.h" | 32 | #include "taler_rsa.h" |
34 | #include "taler_json_lib.h" | 33 | #include "taler_json_lib.h" |
@@ -38,6 +37,7 @@ | |||
38 | #include "taler-mint-httpd_deposit.h" | 37 | #include "taler-mint-httpd_deposit.h" |
39 | #include "taler-mint-httpd_withdraw.h" | 38 | #include "taler-mint-httpd_withdraw.h" |
40 | #include "taler-mint-httpd_refresh.h" | 39 | #include "taler-mint-httpd_refresh.h" |
40 | #include "mint_db.h" | ||
41 | 41 | ||
42 | 42 | ||
43 | /** | 43 | /** |
diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 7a78f93ea..f3a22911c 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c | |||
@@ -25,12 +25,15 @@ | |||
25 | * - /deposit: check for leaks | 25 | * - /deposit: check for leaks |
26 | */ | 26 | */ |
27 | #include "platform.h" | 27 | #include "platform.h" |
28 | #include <pthread.h> | ||
29 | #include <jansson.h> | ||
28 | #include "taler-mint-httpd_db.h" | 30 | #include "taler-mint-httpd_db.h" |
29 | #include "taler_signatures.h" | 31 | #include "taler_signatures.h" |
32 | #include "taler-mint-httpd_keys.h" | ||
30 | #include "taler-mint-httpd_responses.h" | 33 | #include "taler-mint-httpd_responses.h" |
31 | #include "mint_db.h" | 34 | #include "mint_db.h" |
32 | #include "mint.h" | 35 | #include "mint.h" |
33 | #include <pthread.h> | 36 | #include "taler_json_lib.h" |
34 | 37 | ||
35 | 38 | ||
36 | /** | 39 | /** |
@@ -48,43 +51,39 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, | |||
48 | const struct Deposit *deposit) | 51 | const struct Deposit *deposit) |
49 | { | 52 | { |
50 | PGconn *db_conn; | 53 | PGconn *db_conn; |
54 | struct Deposit *existing_deposit; | ||
55 | int res; | ||
51 | 56 | ||
52 | if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) | 57 | if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) |
53 | { | 58 | { |
54 | GNUNET_break (0); | 59 | GNUNET_break (0); |
55 | return TALER_MINT_reply_internal_error (connection, | 60 | return TALER_MINT_reply_internal_error (connection, |
56 | "Failed to connect to database\n"); | 61 | "Failed to connect to database"); |
57 | } | 62 | } |
58 | 63 | res = TALER_MINT_DB_get_deposit (db_conn, | |
64 | &deposit->coin_pub, | ||
65 | &existing_deposit); | ||
66 | if (GNUNET_YES == res) | ||
59 | { | 67 | { |
60 | struct Deposit *existing_deposit; | 68 | // FIXME: memory leak |
61 | int res; | 69 | // FIXME: memcmp will not actually work here |
62 | 70 | if (0 == memcmp (existing_deposit, deposit, sizeof (struct Deposit))) | |
63 | res = TALER_MINT_DB_get_deposit (db_conn, | 71 | return TALER_MINT_reply_deposit_success (connection, deposit); |
64 | &deposit->coin_pub, | 72 | // FIXME: in the future, check if there's enough credits |
65 | &existing_deposit); | 73 | // left on the coin. For now: refuse |
66 | if (GNUNET_YES == res) | 74 | // FIXME: return more information here |
67 | { | 75 | return TALER_MINT_reply_json_pack (connection, |
68 | // FIXME: memory leak | 76 | MHD_HTTP_FORBIDDEN, |
69 | // FIXME: memcmp will not actually work here | 77 | "{s:s}", |
70 | if (0 == memcmp (existing_deposit, deposit, sizeof (struct Deposit))) | 78 | "error", |
71 | return TALER_MINT_reply_deposit_success (connection, deposit); | 79 | "double spending"); |
72 | // FIXME: in the future, check if there's enough credits | 80 | } |
73 | // left on the coin. For now: refuse | ||
74 | // FIXME: return more information here | ||
75 | return TALER_MINT_reply_json_pack (connection, | ||
76 | MHD_HTTP_FORBIDDEN, | ||
77 | "{s:s}", | ||
78 | "error", | ||
79 | "double spending"); | ||
80 | } | ||
81 | 81 | ||
82 | if (GNUNET_SYSERR == res) | 82 | if (GNUNET_SYSERR == res) |
83 | { | 83 | { |
84 | GNUNET_break (0); | 84 | GNUNET_break (0); |
85 | /* FIXME: return error message to client via MHD! */ | 85 | /* FIXME: return error message to client via MHD! */ |
86 | return MHD_NO; | 86 | return MHD_NO; |
87 | } | ||
88 | } | 87 | } |
89 | 88 | ||
90 | { | 89 | { |
@@ -133,3 +132,228 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, | |||
133 | TALER_MINT_DB_commit (db_conn); | 132 | TALER_MINT_DB_commit (db_conn); |
134 | return TALER_MINT_reply_deposit_success (connection, deposit); | 133 | return TALER_MINT_reply_deposit_success (connection, deposit); |
135 | } | 134 | } |
135 | |||
136 | |||
137 | /** | ||
138 | * Sign a reserve's status with the current signing key. | ||
139 | * FIXME: not sure why we do this. Should just return | ||
140 | * existing list of operations on the reserve. | ||
141 | * | ||
142 | * @param reserve the reserve to sign | ||
143 | * @param key_state the key state containing the current | ||
144 | * signing private key | ||
145 | */ | ||
146 | static void | ||
147 | sign_reserve (struct Reserve *reserve, | ||
148 | struct MintKeyState *key_state) | ||
149 | { | ||
150 | reserve->status_sign_pub = key_state->current_sign_key_issue.issue.signkey_pub; | ||
151 | reserve->status_sig_purpose.purpose = htonl (TALER_SIGNATURE_RESERVE_STATUS); | ||
152 | reserve->status_sig_purpose.size = htonl (sizeof (struct Reserve) - | ||
153 | offsetof (struct Reserve, status_sig_purpose)); | ||
154 | GNUNET_CRYPTO_eddsa_sign (&key_state->current_sign_key_issue.signkey_priv, | ||
155 | &reserve->status_sig_purpose, | ||
156 | &reserve->status_sig); | ||
157 | } | ||
158 | |||
159 | |||
160 | /** | ||
161 | * Execute a /withdraw/status. | ||
162 | * | ||
163 | * @param connection the MHD connection to handle | ||
164 | * @param reserve_pub public key of the reserve to check | ||
165 | * @return MHD result code | ||
166 | */ | ||
167 | int | ||
168 | TALER_MINT_db_execute_withdraw_status (struct MHD_Connection *connection, | ||
169 | const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub) | ||
170 | { | ||
171 | PGconn *db_conn; | ||
172 | int res; | ||
173 | struct Reserve reserve; | ||
174 | struct MintKeyState *key_state; | ||
175 | int must_update = GNUNET_NO; | ||
176 | |||
177 | |||
178 | if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) | ||
179 | { | ||
180 | GNUNET_break (0); | ||
181 | return TALER_MINT_reply_internal_error (connection, | ||
182 | "Failed to connect to database"); | ||
183 | } | ||
184 | res = TALER_MINT_DB_get_reserve (db_conn, | ||
185 | reserve_pub, | ||
186 | &reserve); | ||
187 | /* check if these are really the matching error codes, | ||
188 | seems odd... */ | ||
189 | if (GNUNET_SYSERR == res) | ||
190 | return TALER_MINT_reply_json_pack (connection, | ||
191 | MHD_HTTP_NOT_FOUND, | ||
192 | "{s:s}", | ||
193 | "error", | ||
194 | "Reserve not found"); | ||
195 | if (GNUNET_OK != res) | ||
196 | { | ||
197 | GNUNET_break (0); | ||
198 | return TALER_MINT_reply_internal_error (connection, | ||
199 | "Internal error"); | ||
200 | } | ||
201 | key_state = TALER_MINT_key_state_acquire (); | ||
202 | if (0 != memcmp (&key_state->current_sign_key_issue.issue.signkey_pub, | ||
203 | &reserve.status_sign_pub, | ||
204 | sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) | ||
205 | { | ||
206 | sign_reserve (&reserve, key_state); | ||
207 | must_update = GNUNET_YES; | ||
208 | } | ||
209 | if ((GNUNET_YES == must_update) && | ||
210 | (GNUNET_OK != TALER_MINT_DB_update_reserve (db_conn, &reserve, !must_update))) | ||
211 | { | ||
212 | GNUNET_break (0); | ||
213 | return MHD_YES; | ||
214 | } | ||
215 | return TALER_MINT_reply_withdraw_status_success (connection, | ||
216 | &reserve); | ||
217 | } | ||
218 | |||
219 | |||
220 | /** | ||
221 | * Execute a /withdraw/sign. | ||
222 | * | ||
223 | * @param connection the MHD connection to handle | ||
224 | * @param wsrd_ro details about the withdraw request | ||
225 | * @return MHD result code | ||
226 | */ | ||
227 | int | ||
228 | TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, | ||
229 | const struct TALER_WithdrawRequest *wsrd_ro) | ||
230 | { | ||
231 | PGconn *db_conn; | ||
232 | struct Reserve reserve; | ||
233 | struct MintKeyState *key_state; | ||
234 | struct CollectableBlindcoin collectable; | ||
235 | struct TALER_MINT_DenomKeyIssuePriv *dki; | ||
236 | struct TALER_RSA_Signature ev_sig; | ||
237 | struct TALER_Amount amount_required; | ||
238 | /* FIXME: the fact that we do this here is a sign that we | ||
239 | need to have different versions of this struct for | ||
240 | the different places it is used! */ | ||
241 | struct TALER_WithdrawRequest wsrd = *wsrd_ro; | ||
242 | int res; | ||
243 | |||
244 | if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) | ||
245 | { | ||
246 | // FIXME: return 'internal error'? | ||
247 | GNUNET_break (0); | ||
248 | return MHD_NO; | ||
249 | } | ||
250 | |||
251 | |||
252 | res = TALER_MINT_DB_get_collectable_blindcoin (db_conn, | ||
253 | &wsrd.coin_envelope, | ||
254 | &collectable); | ||
255 | if (GNUNET_SYSERR == res) | ||
256 | { | ||
257 | // FIXME: return 'internal error' | ||
258 | GNUNET_break (0); | ||
259 | return MHD_NO; | ||
260 | } | ||
261 | |||
262 | /* Don't sign again if we have already signed the coin */ | ||
263 | if (GNUNET_YES == res) | ||
264 | return TALER_MINT_reply_withdraw_sign_success (connection, | ||
265 | &collectable); | ||
266 | GNUNET_assert (GNUNET_NO == res); | ||
267 | res = TALER_MINT_DB_get_reserve (db_conn, | ||
268 | &wsrd.reserve_pub, | ||
269 | &reserve); | ||
270 | if (GNUNET_SYSERR == res) | ||
271 | { | ||
272 | // FIXME: return 'internal error' | ||
273 | GNUNET_break (0); | ||
274 | return MHD_NO; | ||
275 | } | ||
276 | if (GNUNET_NO == res) | ||
277 | return TALER_MINT_reply_json_pack (connection, | ||
278 | MHD_HTTP_NOT_FOUND, | ||
279 | "{s:s}", | ||
280 | "error", | ||
281 | "Reserve not found"); | ||
282 | |||
283 | // fill out all the missing info in the request before | ||
284 | // we can check the signature on the request | ||
285 | |||
286 | wsrd.purpose.purpose = htonl (TALER_SIGNATURE_WITHDRAW); | ||
287 | wsrd.purpose.size = htonl (sizeof (struct TALER_WithdrawRequest) - | ||
288 | offsetof (struct TALER_WithdrawRequest, purpose)); | ||
289 | |||
290 | if (GNUNET_OK != | ||
291 | GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WITHDRAW, | ||
292 | &wsrd.purpose, | ||
293 | &wsrd.sig, | ||
294 | &wsrd.reserve_pub)) | ||
295 | return TALER_MINT_reply_json_pack (connection, | ||
296 | MHD_HTTP_UNAUTHORIZED, | ||
297 | "{s:s}", | ||
298 | "error", "Invalid Signature"); | ||
299 | |||
300 | key_state = TALER_MINT_key_state_acquire (); | ||
301 | dki = TALER_MINT_get_denom_key (key_state, | ||
302 | &wsrd.denomination_pub); | ||
303 | TALER_MINT_key_state_release (key_state); | ||
304 | if (NULL == dki) | ||
305 | return TALER_MINT_reply_json_pack (connection, | ||
306 | MHD_HTTP_NOT_FOUND, | ||
307 | "{s:s}", | ||
308 | "error", | ||
309 | "Denomination not found"); | ||
310 | |||
311 | amount_required = TALER_amount_ntoh (dki->issue.value); | ||
312 | amount_required = TALER_amount_add (amount_required, | ||
313 | TALER_amount_ntoh (dki->issue.fee_withdraw)); | ||
314 | |||
315 | if (0 < TALER_amount_cmp (amount_required, | ||
316 | TALER_amount_ntoh (reserve.balance))) | ||
317 | return TALER_MINT_reply_json_pack (connection, | ||
318 | MHD_HTTP_PAYMENT_REQUIRED, | ||
319 | "{s:s}", | ||
320 | "error", | ||
321 | "Insufficient funds"); | ||
322 | if (GNUNET_OK != | ||
323 | TALER_RSA_sign (dki->denom_priv, | ||
324 | &wsrd.coin_envelope, | ||
325 | sizeof (struct TALER_RSA_BlindedSignaturePurpose), | ||
326 | &ev_sig)) | ||
327 | { | ||
328 | // FIXME: return 'internal error' | ||
329 | GNUNET_break (0); | ||
330 | return MHD_NO; | ||
331 | } | ||
332 | |||
333 | reserve.balance = TALER_amount_hton (TALER_amount_subtract (TALER_amount_ntoh (reserve.balance), | ||
334 | amount_required)); | ||
335 | if (GNUNET_OK != | ||
336 | TALER_MINT_DB_update_reserve (db_conn, | ||
337 | &reserve, | ||
338 | GNUNET_YES)) | ||
339 | { | ||
340 | // FIXME: return 'internal error' | ||
341 | GNUNET_break (0); | ||
342 | return MHD_NO; | ||
343 | } | ||
344 | |||
345 | collectable.ev = wsrd.coin_envelope; | ||
346 | collectable.ev_sig = ev_sig; | ||
347 | collectable.reserve_pub = wsrd.reserve_pub; | ||
348 | collectable.reserve_sig = wsrd.sig; | ||
349 | if (GNUNET_OK != | ||
350 | TALER_MINT_DB_insert_collectable_blindcoin (db_conn, | ||
351 | &collectable)) | ||
352 | { | ||
353 | // FIXME: return 'internal error' | ||
354 | GNUNET_break (0); | ||
355 | return GNUNET_NO;; | ||
356 | } | ||
357 | return TALER_MINT_reply_withdraw_sign_success (connection, | ||
358 | &collectable); | ||
359 | } | ||
diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index 1829f3d37..a479576da 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h | |||
@@ -17,9 +17,6 @@ | |||
17 | * @file mint/taler-mint_httpd_db.h | 17 | * @file mint/taler-mint_httpd_db.h |
18 | * @brief Mint-specific database access | 18 | * @brief Mint-specific database access |
19 | * @author Chrisitan Grothoff | 19 | * @author Chrisitan Grothoff |
20 | * | ||
21 | * TODO: | ||
22 | * - revisit and document `struct Deposit` members. | ||
23 | */ | 20 | */ |
24 | #ifndef TALER_MINT_HTTPD_DB_H | 21 | #ifndef TALER_MINT_HTTPD_DB_H |
25 | #define TALER_MINT_HTTPD_DB_H | 22 | #define TALER_MINT_HTTPD_DB_H |
@@ -29,46 +26,13 @@ | |||
29 | #include <gnunet/gnunet_util_lib.h> | 26 | #include <gnunet/gnunet_util_lib.h> |
30 | #include "taler_util.h" | 27 | #include "taler_util.h" |
31 | #include "taler_rsa.h" | 28 | #include "taler_rsa.h" |
29 | #include "taler-mint-httpd_keys.h" | ||
30 | #include "mint.h" | ||
32 | 31 | ||
33 | 32 | ||
34 | /** | ||
35 | * Specification for a /deposit operation. | ||
36 | */ | ||
37 | struct Deposit | ||
38 | { | ||
39 | /* FIXME: should be TALER_CoinPublicInfo */ | ||
40 | struct GNUNET_CRYPTO_EddsaPublicKey coin_pub; | ||
41 | |||
42 | struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; | ||
43 | |||
44 | struct TALER_RSA_Signature coin_sig; | ||
45 | |||
46 | struct TALER_RSA_Signature ubsig; | ||
47 | |||
48 | /** | ||
49 | * Type of the deposit (also purpose of the signature). Either | ||
50 | * #TALER_SIGNATURE_DEPOSIT or #TALER_SIGNATURE_INCREMENTAL_DEPOSIT. | ||
51 | */ | ||
52 | struct TALER_RSA_SignaturePurpose purpose; | ||
53 | |||
54 | uint64_t transaction_id; | ||
55 | |||
56 | struct TALER_AmountNBO amount; | ||
57 | |||
58 | struct GNUNET_CRYPTO_EddsaPublicKey merchant_pub; | ||
59 | |||
60 | struct GNUNET_HashCode h_contract; | ||
61 | |||
62 | struct GNUNET_HashCode h_wire; | ||
63 | |||
64 | /* TODO: uint16_t wire_size */ | ||
65 | char wire[]; /* string encoded wire JSON object */ | ||
66 | |||
67 | }; | ||
68 | |||
69 | 33 | ||
70 | /** | 34 | /** |
71 | * Execute a deposit. The validity of the coin and signature | 35 | * Execute a /deposit. The validity of the coin and signature |
72 | * have already been checked. The database must now check that | 36 | * have already been checked. The database must now check that |
73 | * the coin is not (double or over) spent, and execute the | 37 | * the coin is not (double or over) spent, and execute the |
74 | * transaction (record details, generate success or failure response). | 38 | * transaction (record details, generate success or failure response). |
@@ -82,4 +46,28 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, | |||
82 | const struct Deposit *deposit); | 46 | const struct Deposit *deposit); |
83 | 47 | ||
84 | 48 | ||
49 | /** | ||
50 | * Execute a /withdraw/status. | ||
51 | * | ||
52 | * @param connection the MHD connection to handle | ||
53 | * @param reserve_pub public key of the reserve to check | ||
54 | * @return MHD result code | ||
55 | */ | ||
56 | int | ||
57 | TALER_MINT_db_execute_withdraw_status (struct MHD_Connection *connection, | ||
58 | const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub); | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Execute a /withdraw/sign. | ||
63 | * | ||
64 | * @param connection the MHD connection to handle | ||
65 | * @param wsrd details about the withdraw request | ||
66 | * @return MHD result code | ||
67 | */ | ||
68 | int | ||
69 | TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, | ||
70 | const struct TALER_WithdrawRequest *wsrd); | ||
71 | |||
72 | |||
85 | #endif /* _NEURO_MINT_DB_H */ | 73 | #endif /* _NEURO_MINT_DB_H */ |
diff --git a/src/mint/taler-mint-httpd_keys.c b/src/mint/taler-mint-httpd_keys.c index 149e44d3f..8db32cd83 100644 --- a/src/mint/taler-mint-httpd_keys.c +++ b/src/mint/taler-mint-httpd_keys.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <libpq-fe.h> | 27 | #include <libpq-fe.h> |
28 | #include <pthread.h> | 28 | #include <pthread.h> |
29 | #include "mint.h" | 29 | #include "mint.h" |
30 | #include "mint_db.h" | ||
31 | #include "taler_signatures.h" | 30 | #include "taler_signatures.h" |
32 | #include "taler_rsa.h" | 31 | #include "taler_rsa.h" |
33 | #include "taler_json_lib.h" | 32 | #include "taler_json_lib.h" |
@@ -35,6 +34,7 @@ | |||
35 | #include "taler-mint-httpd_keys.h" | 34 | #include "taler-mint-httpd_keys.h" |
36 | 35 | ||
37 | 36 | ||
37 | |||
38 | /** | 38 | /** |
39 | * Mint key state. Never use directly, instead access via | 39 | * Mint key state. Never use directly, instead access via |
40 | * #TALER_MINT_key_state_acquire and #TALER_MINT_key_state_release. | 40 | * #TALER_MINT_key_state_acquire and #TALER_MINT_key_state_release. |
diff --git a/src/mint/taler-mint-httpd_keys.h b/src/mint/taler-mint-httpd_keys.h index 4fd3d0bdd..c156cff66 100644 --- a/src/mint/taler-mint-httpd_keys.h +++ b/src/mint/taler-mint-httpd_keys.h | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <gnunet/gnunet_util_lib.h> | 26 | #include <gnunet/gnunet_util_lib.h> |
27 | #include <microhttpd.h> | 27 | #include <microhttpd.h> |
28 | #include "taler-mint-httpd.h" | 28 | #include "taler-mint-httpd.h" |
29 | 29 | #include "mint.h" | |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * Snapshot of the (coin and signing) | 32 | * Snapshot of the (coin and signing) |
diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index ab21e814c..883da8a85 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c | |||
@@ -19,6 +19,9 @@ | |||
19 | * @author Florian Dold | 19 | * @author Florian Dold |
20 | * @author Benedikt Mueller | 20 | * @author Benedikt Mueller |
21 | * @author Christian Grothoff | 21 | * @author Christian Grothoff |
22 | * | ||
23 | * TODO: | ||
24 | * - split properly into parsing, DB-ops and response generation | ||
22 | */ | 25 | */ |
23 | #include "platform.h" | 26 | #include "platform.h" |
24 | #include <gnunet/gnunet_util_lib.h> | 27 | #include <gnunet/gnunet_util_lib.h> |
@@ -70,6 +73,9 @@ sign_as_json (struct GNUNET_CRYPTO_EccSignaturePurpose *purpose) | |||
70 | } | 73 | } |
71 | 74 | ||
72 | 75 | ||
76 | /** | ||
77 | * FIXME: document! | ||
78 | */ | ||
73 | static int | 79 | static int |
74 | link_iter (void *cls, | 80 | link_iter (void *cls, |
75 | const struct LinkDataEnc *link_data_enc, | 81 | const struct LinkDataEnc *link_data_enc, |
@@ -246,9 +252,9 @@ check_confirm_signature (struct MHD_Connection *connection, | |||
246 | * | 252 | * |
247 | * @param connection the connection to send error responses to | 253 | * @param connection the connection to send error responses to |
248 | * @param root the JSON object to extract the coin info from | 254 | * @param root the JSON object to extract the coin info from |
249 | * @return GNUNET_YES if coin public info in JSON was valid | 255 | * @return #GNUNET_YES if coin public info in JSON was valid |
250 | * GNUNET_NO otherwise | 256 | * #GNUNET_NO otherwise |
251 | * GNUNET_SYSERR on internal error | 257 | * #GNUNET_SYSERR on internal error |
252 | */ | 258 | */ |
253 | static int | 259 | static int |
254 | request_json_require_coin_public_info (struct MHD_Connection *connection, | 260 | request_json_require_coin_public_info (struct MHD_Connection *connection, |
@@ -298,9 +304,9 @@ request_json_require_coin_public_info (struct MHD_Connection *connection, | |||
298 | * @param root the JSON object | 304 | * @param root the JSON object |
299 | * @param hash_context the hash context that will receive | 305 | * @param hash_context the hash context that will receive |
300 | * the coin public keys of the melted coin | 306 | * the coin public keys of the melted coin |
301 | * @return a GNUnet result code, GNUNET_OK on success, | 307 | * @return #GNUNET_OK on success, |
302 | * GNUNET_NO if an error message was generated, | 308 | * #GNUNET_NO if an error message was generated, |
303 | * GNUNET_SYSERR on internal errors (no response generated) | 309 | * #GNUNET_SYSERR on internal errors (no response generated) |
304 | */ | 310 | */ |
305 | static int | 311 | static int |
306 | refresh_accept_melts (struct MHD_Connection *connection, | 312 | refresh_accept_melts (struct MHD_Connection *connection, |
diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 6ae219b63..78e239b7c 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c | |||
@@ -26,9 +26,14 @@ | |||
26 | * TODO: | 26 | * TODO: |
27 | * - when generating /deposit reply, do include signature of mint | 27 | * - when generating /deposit reply, do include signature of mint |
28 | * to say that we accepted it (check reply format) | 28 | * to say that we accepted it (check reply format) |
29 | * - when generating /withdraw/status reply, which signature do | ||
30 | * we use there? Might want to instead return *all* signatures on the | ||
31 | * existig withdraw operations, instead of Mint's signature | ||
32 | * (check reply format, adjust `struct Reserve` if needed) | ||
29 | */ | 33 | */ |
30 | #include "platform.h" | 34 | #include "platform.h" |
31 | #include "taler-mint-httpd_responses.h" | 35 | #include "taler-mint-httpd_responses.h" |
36 | #include "taler_json_lib.h" | ||
32 | 37 | ||
33 | 38 | ||
34 | /** | 39 | /** |
@@ -229,4 +234,61 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection, | |||
229 | "DEPOSIT_OK"); | 234 | "DEPOSIT_OK"); |
230 | } | 235 | } |
231 | 236 | ||
237 | |||
238 | /** | ||
239 | * Send reserve status information to client. | ||
240 | * | ||
241 | * @param connection connection to the client | ||
242 | * @param reserve reserve status information to return | ||
243 | * @return MHD result code | ||
244 | */ | ||
245 | int | ||
246 | TALER_MINT_reply_withdraw_status_success (struct MHD_Connection *connection, | ||
247 | const struct Reserve *reserve) | ||
248 | { | ||
249 | json_t *json; | ||
250 | |||
251 | /* Convert the public information of a reserve (i.e. | ||
252 | excluding private key) to a JSON object. */ | ||
253 | json = json_object (); | ||
254 | json_object_set_new (json, | ||
255 | "balance", | ||
256 | TALER_JSON_from_amount (TALER_amount_ntoh (reserve->balance))); | ||
257 | json_object_set_new (json, | ||
258 | "expiration", | ||
259 | TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (reserve->expiration))); | ||
260 | json_object_set_new (json, | ||
261 | "signature", | ||
262 | TALER_JSON_from_sig (&reserve->status_sig_purpose, | ||
263 | &reserve->status_sig)); | ||
264 | |||
265 | return TALER_MINT_reply_json (connection, | ||
266 | json, | ||
267 | MHD_HTTP_OK); | ||
268 | } | ||
269 | |||
270 | |||
271 | /** | ||
272 | * Send blinded coin information to client. | ||
273 | * | ||
274 | * @param connection connection to the client | ||
275 | * @param collectable blinded coin to return | ||
276 | * @return MHD result code | ||
277 | */ | ||
278 | int | ||
279 | TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, | ||
280 | const struct CollectableBlindcoin *collectable) | ||
281 | { | ||
282 | json_t *root = json_object (); | ||
283 | |||
284 | json_object_set_new (root, "ev_sig", | ||
285 | TALER_JSON_from_data (&collectable->ev_sig, | ||
286 | sizeof (struct TALER_RSA_Signature))); | ||
287 | return TALER_MINT_reply_json (connection, | ||
288 | root, | ||
289 | MHD_HTTP_OK); | ||
290 | } | ||
291 | |||
292 | |||
293 | |||
232 | /* end of taler-mint-httpd_responses.c */ | 294 | /* end of taler-mint-httpd_responses.c */ |
diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index 6dd8cda90..ce7557e1d 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h | |||
@@ -31,8 +31,8 @@ | |||
31 | #include <libpq-fe.h> | 31 | #include <libpq-fe.h> |
32 | #include <pthread.h> | 32 | #include <pthread.h> |
33 | #include "taler-mint-httpd.h" | 33 | #include "taler-mint-httpd.h" |
34 | #include "taler-mint-httpd_db.h" | ||
34 | #include "taler-mint-httpd_mhd.h" | 35 | #include "taler-mint-httpd_mhd.h" |
35 | #include "mint_db.h" | ||
36 | 36 | ||
37 | 37 | ||
38 | /** | 38 | /** |
@@ -135,5 +135,28 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection, | |||
135 | const struct Deposit *deposit); | 135 | const struct Deposit *deposit); |
136 | 136 | ||
137 | 137 | ||
138 | /** | ||
139 | * Send reserve status information to client. | ||
140 | * | ||
141 | * @param connection connection to the client | ||
142 | * @param reserve reserve status information to return | ||
143 | * @return MHD result code | ||
144 | */ | ||
145 | int | ||
146 | TALER_MINT_reply_withdraw_status_success (struct MHD_Connection *connection, | ||
147 | const struct Reserve *reserve); | ||
148 | |||
149 | |||
150 | /** | ||
151 | * Send blinded coin information to client. | ||
152 | * | ||
153 | * @param connection connection to the client | ||
154 | * @param collectable blinded coin to return | ||
155 | * @return MHD result code | ||
156 | */ | ||
157 | int | ||
158 | TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, | ||
159 | const struct CollectableBlindcoin *collectable); | ||
160 | |||
138 | 161 | ||
139 | #endif | 162 | #endif |
diff --git a/src/mint/taler-mint-httpd_withdraw.c b/src/mint/taler-mint-httpd_withdraw.c index cc0de7f6f..5259c7fbf 100644 --- a/src/mint/taler-mint-httpd_withdraw.c +++ b/src/mint/taler-mint-httpd_withdraw.c | |||
@@ -19,6 +19,9 @@ | |||
19 | * @author Florian Dold | 19 | * @author Florian Dold |
20 | * @author Benedikt Mueller | 20 | * @author Benedikt Mueller |
21 | * @author Christian Grothoff | 21 | * @author Christian Grothoff |
22 | * | ||
23 | * TODO: | ||
24 | * - support variable-size RSA keys | ||
22 | */ | 25 | */ |
23 | #include "platform.h" | 26 | #include "platform.h" |
24 | #include <gnunet/gnunet_util_lib.h> | 27 | #include <gnunet/gnunet_util_lib.h> |
@@ -33,63 +36,13 @@ | |||
33 | #include "taler_json_lib.h" | 36 | #include "taler_json_lib.h" |
34 | #include "taler-mint-httpd_parsing.h" | 37 | #include "taler-mint-httpd_parsing.h" |
35 | #include "taler-mint-httpd_keys.h" | 38 | #include "taler-mint-httpd_keys.h" |
39 | #include "taler-mint-httpd_db.h" | ||
36 | #include "taler-mint-httpd_mhd.h" | 40 | #include "taler-mint-httpd_mhd.h" |
37 | #include "taler-mint-httpd_withdraw.h" | 41 | #include "taler-mint-httpd_withdraw.h" |
38 | #include "taler-mint-httpd_responses.h" | 42 | #include "taler-mint-httpd_responses.h" |
39 | 43 | ||
40 | 44 | ||
41 | /** | 45 | /** |
42 | * Convert a signature (with purpose) to | ||
43 | * a JSON object representation. | ||
44 | * | ||
45 | * @param purpose purpose of the signature | ||
46 | * @param signature the signature | ||
47 | * @return the JSON reporesentation of the signature with purpose | ||
48 | */ | ||
49 | static json_t * | ||
50 | sig_to_json (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, | ||
51 | const struct GNUNET_CRYPTO_EddsaSignature *signature) | ||
52 | { | ||
53 | json_t *root; | ||
54 | json_t *el; | ||
55 | |||
56 | root = json_object (); | ||
57 | |||
58 | el = json_integer ((json_int_t) ntohl (purpose->size)); | ||
59 | json_object_set_new (root, "size", el); | ||
60 | |||
61 | el = json_integer ((json_int_t) ntohl (purpose->purpose)); | ||
62 | json_object_set_new (root, "purpose", el); | ||
63 | |||
64 | el = TALER_JSON_from_data (signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature)); | ||
65 | json_object_set_new (root, "sig", el); | ||
66 | |||
67 | return root; | ||
68 | } | ||
69 | |||
70 | |||
71 | /** | ||
72 | * Sign a reserve's status with the current signing key. | ||
73 | * | ||
74 | * @param reserve the reserve to sign | ||
75 | * @param key_state the key state containing the current | ||
76 | * signing private key | ||
77 | */ | ||
78 | static void | ||
79 | sign_reserve (struct Reserve *reserve, | ||
80 | struct MintKeyState *key_state) | ||
81 | { | ||
82 | reserve->status_sign_pub = key_state->current_sign_key_issue.issue.signkey_pub; | ||
83 | reserve->status_sig_purpose.purpose = htonl (TALER_SIGNATURE_RESERVE_STATUS); | ||
84 | reserve->status_sig_purpose.size = htonl (sizeof (struct Reserve) - | ||
85 | offsetof (struct Reserve, status_sig_purpose)); | ||
86 | GNUNET_CRYPTO_eddsa_sign (&key_state->current_sign_key_issue.signkey_priv, | ||
87 | &reserve->status_sig_purpose, | ||
88 | &reserve->status_sig); | ||
89 | } | ||
90 | |||
91 | |||
92 | /** | ||
93 | * Handle a "/withdraw/status" request | 46 | * Handle a "/withdraw/status" request |
94 | * | 47 | * |
95 | * @param rh context of the handler | 48 | * @param rh context of the handler |
@@ -107,100 +60,18 @@ TALER_MINT_handler_withdraw_status (struct RequestHandler *rh, | |||
107 | size_t *upload_data_size) | 60 | size_t *upload_data_size) |
108 | { | 61 | { |
109 | struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; | 62 | struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; |
110 | PGconn *db_conn; | ||
111 | int res; | 63 | int res; |
112 | struct Reserve reserve; | ||
113 | struct MintKeyState *key_state; | ||
114 | int must_update = GNUNET_NO; | ||
115 | json_t *json; | ||
116 | 64 | ||
117 | res = TALER_MINT_mhd_request_arg_data (connection, | 65 | res = TALER_MINT_mhd_request_arg_data (connection, |
118 | "reserve_pub", | 66 | "reserve_pub", |
119 | &reserve_pub, | 67 | &reserve_pub, |
120 | sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); | 68 | sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); |
121 | if (GNUNET_SYSERR == res) | ||
122 | { | ||
123 | // FIXME: return 'internal error' | ||
124 | GNUNET_break (0); | ||
125 | return MHD_NO; | ||
126 | } | ||
127 | if (GNUNET_OK != res) | ||
128 | return MHD_YES; | ||
129 | if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) | ||
130 | { | ||
131 | // FIXME: return 'internal error'? | ||
132 | GNUNET_break (0); | ||
133 | return MHD_NO; | ||
134 | } | ||
135 | res = TALER_MINT_DB_get_reserve (db_conn, | ||
136 | &reserve_pub, | ||
137 | &reserve); | ||
138 | if (GNUNET_SYSERR == res) | 69 | if (GNUNET_SYSERR == res) |
139 | return TALER_MINT_reply_json_pack (connection, | 70 | return MHD_NO; /* internal error */ |
140 | MHD_HTTP_NOT_FOUND, | 71 | if (GNUNET_NO == res) |
141 | "{s:s}", | 72 | return MHD_YES; /* parse error */ |
142 | "error", | 73 | return TALER_MINT_db_execute_withdraw_status (connection, |
143 | "Reserve not found"); | 74 | &reserve_pub); |
144 | if (GNUNET_OK != res) | ||
145 | { | ||
146 | // FIXME: return 'internal error'? | ||
147 | GNUNET_break (0); | ||
148 | return MHD_NO; | ||
149 | } | ||
150 | key_state = TALER_MINT_key_state_acquire (); | ||
151 | if (0 != memcmp (&key_state->current_sign_key_issue.issue.signkey_pub, | ||
152 | &reserve.status_sign_pub, | ||
153 | sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) | ||
154 | { | ||
155 | sign_reserve (&reserve, key_state); | ||
156 | must_update = GNUNET_YES; | ||
157 | } | ||
158 | if ((GNUNET_YES == must_update) && | ||
159 | (GNUNET_OK != TALER_MINT_DB_update_reserve (db_conn, &reserve, !must_update))) | ||
160 | { | ||
161 | GNUNET_break (0); | ||
162 | return MHD_YES; | ||
163 | } | ||
164 | |||
165 | /* Convert the public information of a reserve (i.e. | ||
166 | excluding private key) to a JSON object. */ | ||
167 | json = json_object (); | ||
168 | json_object_set_new (json, | ||
169 | "balance", | ||
170 | TALER_JSON_from_amount (TALER_amount_ntoh (reserve.balance))); | ||
171 | json_object_set_new (json, | ||
172 | "expiration", | ||
173 | TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (reserve.expiration))); | ||
174 | json_object_set_new (json, | ||
175 | "signature", | ||
176 | sig_to_json (&reserve.status_sig_purpose, | ||
177 | &reserve.status_sig)); | ||
178 | |||
179 | return TALER_MINT_reply_json (connection, | ||
180 | json, | ||
181 | MHD_HTTP_OK); | ||
182 | } | ||
183 | |||
184 | |||
185 | /** | ||
186 | * Send positive, normal response for "/withdraw/sign". | ||
187 | * | ||
188 | * @param connection the connection to send the response to | ||
189 | * @param collectable the collectable blindcoin (i.e. the blindly signed coin) | ||
190 | * @return a MHD result code | ||
191 | */ | ||
192 | static int | ||
193 | helper_withdraw_sign_send_reply (struct MHD_Connection *connection, | ||
194 | const struct CollectableBlindcoin *collectable) | ||
195 | { | ||
196 | json_t *root = json_object (); | ||
197 | |||
198 | json_object_set_new (root, "ev_sig", | ||
199 | TALER_JSON_from_data (&collectable->ev_sig, | ||
200 | sizeof (struct TALER_RSA_Signature))); | ||
201 | return TALER_MINT_reply_json (connection, | ||
202 | root, | ||
203 | MHD_HTTP_OK); | ||
204 | } | 75 | } |
205 | 76 | ||
206 | 77 | ||
@@ -223,180 +94,44 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh, | |||
223 | { | 94 | { |
224 | struct TALER_WithdrawRequest wsrd; | 95 | struct TALER_WithdrawRequest wsrd; |
225 | int res; | 96 | int res; |
226 | PGconn *db_conn; | ||
227 | struct Reserve reserve; | ||
228 | struct MintKeyState *key_state; | ||
229 | struct CollectableBlindcoin collectable; | ||
230 | struct TALER_MINT_DenomKeyIssuePriv *dki; | ||
231 | struct TALER_RSA_Signature ev_sig; | ||
232 | struct TALER_Amount amount_required; | ||
233 | 97 | ||
234 | memset (&wsrd, | ||
235 | 0, | ||
236 | sizeof (struct TALER_WithdrawRequest)); | ||
237 | res = TALER_MINT_mhd_request_arg_data (connection, | 98 | res = TALER_MINT_mhd_request_arg_data (connection, |
238 | "reserve_pub", | 99 | "reserve_pub", |
239 | &wsrd.reserve_pub, | 100 | &wsrd.reserve_pub, |
240 | sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); | 101 | sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); |
241 | if (GNUNET_SYSERR == res) | 102 | if (GNUNET_SYSERR == res) |
242 | { | 103 | return MHD_NO; /* internal error */ |
243 | // FIXME: return 'internal error'? | 104 | if (GNUNET_NO == res) |
244 | GNUNET_break (0); | 105 | return MHD_YES; /* invalid request */ |
245 | return MHD_NO; | 106 | |
246 | } | 107 | /* FIXME: handle variable-size signing keys! */ |
247 | if (GNUNET_OK != res) | ||
248 | return MHD_YES; | ||
249 | res = TALER_MINT_mhd_request_arg_data (connection, | 108 | res = TALER_MINT_mhd_request_arg_data (connection, |
250 | "denom_pub", | 109 | "denom_pub", |
251 | &wsrd.denomination_pub, | 110 | &wsrd.denomination_pub, |
252 | sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)); | 111 | sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)); |
253 | if (GNUNET_SYSERR == res) | 112 | if (GNUNET_SYSERR == res) |
254 | { | 113 | return MHD_NO; /* internal error */ |
255 | // FIXME: return 'internal error'? | 114 | if (GNUNET_NO == res) |
256 | GNUNET_break (0); | 115 | return MHD_YES; /* invalid request */ |
257 | return MHD_NO; | ||
258 | } | ||
259 | if (GNUNET_OK != res) | ||
260 | return MHD_YES; | ||
261 | res = TALER_MINT_mhd_request_arg_data (connection, | 116 | res = TALER_MINT_mhd_request_arg_data (connection, |
262 | "coin_ev", | 117 | "coin_ev", |
263 | &wsrd.coin_envelope, | 118 | &wsrd.coin_envelope, |
264 | sizeof (struct TALER_RSA_Signature)); | 119 | sizeof (struct TALER_RSA_Signature)); |
265 | if (GNUNET_SYSERR == res) | 120 | if (GNUNET_SYSERR == res) |
266 | { | 121 | return MHD_NO; /* internal error */ |
267 | // FIXME: return 'internal error'? | 122 | if (GNUNET_NO == res) |
268 | GNUNET_break (0); | 123 | return MHD_YES; /* invalid request */ |
269 | return MHD_NO; | ||
270 | } | ||
271 | if (GNUNET_OK != res) | ||
272 | return MHD_YES; | ||
273 | res = TALER_MINT_mhd_request_arg_data (connection, | 124 | res = TALER_MINT_mhd_request_arg_data (connection, |
274 | "reserve_sig", | 125 | "reserve_sig", |
275 | &wsrd.sig, | 126 | &wsrd.sig, |
276 | sizeof (struct GNUNET_CRYPTO_EddsaSignature)); | 127 | sizeof (struct GNUNET_CRYPTO_EddsaSignature)); |
277 | if (GNUNET_SYSERR == res) | 128 | if (GNUNET_SYSERR == res) |
278 | { | 129 | return MHD_NO; /* internal error */ |
279 | // FIXME: return 'internal error'? | ||
280 | GNUNET_break (0); | ||
281 | return MHD_NO; | ||
282 | } | ||
283 | if (GNUNET_OK != res) | ||
284 | return MHD_YES; | ||
285 | |||
286 | if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) | ||
287 | { | ||
288 | // FIXME: return 'internal error'? | ||
289 | GNUNET_break (0); | ||
290 | return MHD_NO; | ||
291 | } | ||
292 | |||
293 | res = TALER_MINT_DB_get_collectable_blindcoin (db_conn, | ||
294 | &wsrd.coin_envelope, | ||
295 | &collectable); | ||
296 | if (GNUNET_SYSERR == res) | ||
297 | { | ||
298 | // FIXME: return 'internal error' | ||
299 | GNUNET_break (0); | ||
300 | return MHD_NO; | ||
301 | } | ||
302 | |||
303 | /* Don't sign again if we have already signed the coin */ | ||
304 | if (GNUNET_YES == res) | ||
305 | return helper_withdraw_sign_send_reply (connection, | ||
306 | &collectable); | ||
307 | GNUNET_assert (GNUNET_NO == res); | ||
308 | res = TALER_MINT_DB_get_reserve (db_conn, | ||
309 | &wsrd.reserve_pub, | ||
310 | &reserve); | ||
311 | if (GNUNET_SYSERR == res) | ||
312 | { | ||
313 | // FIXME: return 'internal error' | ||
314 | GNUNET_break (0); | ||
315 | return MHD_NO; | ||
316 | } | ||
317 | if (GNUNET_NO == res) | 130 | if (GNUNET_NO == res) |
318 | return TALER_MINT_reply_json_pack (connection, | 131 | return MHD_YES; /* invalid request */ |
319 | MHD_HTTP_NOT_FOUND, | ||
320 | "{s:s}", | ||
321 | "error", | ||
322 | "Reserve not found"); | ||
323 | |||
324 | // fill out all the missing info in the request before | ||
325 | // we can check the signature on the request | ||
326 | |||
327 | wsrd.purpose.purpose = htonl (TALER_SIGNATURE_WITHDRAW); | ||
328 | wsrd.purpose.size = htonl (sizeof (struct TALER_WithdrawRequest) - | ||
329 | offsetof (struct TALER_WithdrawRequest, purpose)); | ||
330 | |||
331 | if (GNUNET_OK != | ||
332 | GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WITHDRAW, | ||
333 | &wsrd.purpose, | ||
334 | &wsrd.sig, | ||
335 | &wsrd.reserve_pub)) | ||
336 | return TALER_MINT_reply_json_pack (connection, | ||
337 | MHD_HTTP_UNAUTHORIZED, | ||
338 | "{s:s}", | ||
339 | "error", "Invalid Signature"); | ||
340 | |||
341 | key_state = TALER_MINT_key_state_acquire (); | ||
342 | dki = TALER_MINT_get_denom_key (key_state, | ||
343 | &wsrd.denomination_pub); | ||
344 | TALER_MINT_key_state_release (key_state); | ||
345 | if (NULL == dki) | ||
346 | return TALER_MINT_reply_json_pack (connection, | ||
347 | MHD_HTTP_NOT_FOUND, | ||
348 | "{s:s}", | ||
349 | "error", | ||
350 | "Denomination not found"); | ||
351 | |||
352 | amount_required = TALER_amount_ntoh (dki->issue.value); | ||
353 | amount_required = TALER_amount_add (amount_required, | ||
354 | TALER_amount_ntoh (dki->issue.fee_withdraw)); | ||
355 | |||
356 | if (0 < TALER_amount_cmp (amount_required, | ||
357 | TALER_amount_ntoh (reserve.balance))) | ||
358 | return TALER_MINT_reply_json_pack (connection, | ||
359 | MHD_HTTP_PAYMENT_REQUIRED, | ||
360 | "{s:s}", | ||
361 | "error", | ||
362 | "Insufficient funds"); | ||
363 | if (GNUNET_OK != | ||
364 | TALER_RSA_sign (dki->denom_priv, | ||
365 | &wsrd.coin_envelope, | ||
366 | sizeof (struct TALER_RSA_BlindedSignaturePurpose), | ||
367 | &ev_sig)) | ||
368 | { | ||
369 | // FIXME: return 'internal error' | ||
370 | GNUNET_break (0); | ||
371 | return MHD_NO; | ||
372 | } | ||
373 | |||
374 | reserve.balance = TALER_amount_hton (TALER_amount_subtract (TALER_amount_ntoh (reserve.balance), | ||
375 | amount_required)); | ||
376 | if (GNUNET_OK != | ||
377 | TALER_MINT_DB_update_reserve (db_conn, | ||
378 | &reserve, | ||
379 | GNUNET_YES)) | ||
380 | { | ||
381 | // FIXME: return 'internal error' | ||
382 | GNUNET_break (0); | ||
383 | return MHD_NO; | ||
384 | } | ||
385 | 132 | ||
386 | collectable.ev = wsrd.coin_envelope; | 133 | return TALER_MINT_db_execute_withdraw_sign (connection, |
387 | collectable.ev_sig = ev_sig; | 134 | &wsrd); |
388 | collectable.reserve_pub = wsrd.reserve_pub; | ||
389 | collectable.reserve_sig = wsrd.sig; | ||
390 | if (GNUNET_OK != | ||
391 | TALER_MINT_DB_insert_collectable_blindcoin (db_conn, | ||
392 | &collectable)) | ||
393 | { | ||
394 | // FIXME: return 'internal error' | ||
395 | GNUNET_break (0); | ||
396 | return GNUNET_NO;; | ||
397 | } | ||
398 | return helper_withdraw_sign_send_reply (connection, | ||
399 | &collectable); | ||
400 | } | 135 | } |
401 | 136 | ||
402 | /* end of taler-mint-httpd_withdraw.c */ | 137 | /* end of taler-mint-httpd_withdraw.c */ |
diff --git a/src/util/json.c b/src/util/json.c index 269e6cf26..d66c95c43 100644 --- a/src/util/json.c +++ b/src/util/json.c | |||
@@ -90,6 +90,34 @@ TALER_JSON_from_abs (struct GNUNET_TIME_Absolute stamp) | |||
90 | } | 90 | } |
91 | 91 | ||
92 | 92 | ||
93 | /** | ||
94 | * Convert a signature (with purpose) to a JSON object representation. | ||
95 | * | ||
96 | * @param purpose purpose of the signature | ||
97 | * @param signature the signature | ||
98 | * @return the JSON reporesentation of the signature with purpose | ||
99 | */ | ||
100 | json_t * | ||
101 | TALER_JSON_from_sig (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, | ||
102 | const struct GNUNET_CRYPTO_EddsaSignature *signature) | ||
103 | { | ||
104 | json_t *root; | ||
105 | json_t *el; | ||
106 | |||
107 | root = json_object (); | ||
108 | |||
109 | el = json_integer ((json_int_t) ntohl (purpose->size)); | ||
110 | json_object_set_new (root, "size", el); | ||
111 | |||
112 | el = json_integer ((json_int_t) ntohl (purpose->purpose)); | ||
113 | json_object_set_new (root, "purpose", el); | ||
114 | |||
115 | el = TALER_JSON_from_data (signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature)); | ||
116 | json_object_set_new (root, "sig", el); | ||
117 | |||
118 | return root; | ||
119 | } | ||
120 | |||
93 | 121 | ||
94 | /** | 122 | /** |
95 | * Convert binary data to a JSON string | 123 | * Convert binary data to a JSON string |