aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-01-08 18:37:20 +0100
committerChristian Grothoff <christian@grothoff.org>2015-01-08 18:37:20 +0100
commit57d1f08dbca256f5fe16d57b29bfa523dec8f6c4 (patch)
tree3b3ee5f3b8c174887217e5c465048dea4e79bae2
downloadexchange-57d1f08dbca256f5fe16d57b29bfa523dec8f6c4.tar.gz
exchange-57d1f08dbca256f5fe16d57b29bfa523dec8f6c4.zip
-initial import for mint
-rw-r--r--.gitignore26
-rw-r--r--.gitmodules3
-rw-r--r--AUTHORS4
-rw-r--r--COPYING661
-rw-r--r--ChangeLog0
-rw-r--r--INSTALL370
-rw-r--r--Makefile.am3
-rw-r--r--NEWS0
-rw-r--r--README0
-rwxr-xr-xbootstrap2
-rw-r--r--configure.ac156
-rw-r--r--contrib/mint-template/README1
-rw-r--r--contrib/mint-template/config/mint-common.conf6
-rw-r--r--contrib/mint-template/config/mint-keyup.conf79
-rw-r--r--doc/.gitignore12
-rw-r--r--doc/Makefile.am5
-rw-r--r--doc/logos/ai/logotalerv2.ai3474
-rw-r--r--doc/logos/eps/icon_taler.epsbin0 -> 242881387 bytes
-rw-r--r--doc/logos/eps/logo_taler.epsbin0 -> 10731812 bytes
-rwxr-xr-xdoc/logos/fonts/OldNewspaperTypes.ttfbin0 -> 85804 bytes
-rw-r--r--doc/logos/fonts/perpetue/Perpetua Bold Italic.ttfbin0 -> 75620 bytes
-rw-r--r--doc/logos/fonts/perpetue/Perpetua Bold.ttfbin0 -> 58512 bytes
-rw-r--r--doc/logos/fonts/perpetue/Perpetua Italic.ttfbin0 -> 76080 bytes
-rw-r--r--doc/logos/fonts/perpetue/Perpetua.ttfbin0 -> 60216 bytes
-rwxr-xr-xdoc/logos/fonts/smoth_bight/End User Licence Agreement.txt133
-rwxr-xr-xdoc/logos/fonts/smoth_bight/Licencia de la fuente - Version en Espa§ol.txt77
-rwxr-xr-xdoc/logos/fonts/smoth_bight/Smoth-Bight - Por Kustren.otfbin0 -> 50396 bytes
-rwxr-xr-xdoc/logos/fonts/smoth_bight/Smoth-Bight Italic - Por Kustren.otfbin0 -> 50820 bytes
-rw-r--r--doc/logos/ico/favicon1616.icobin0 -> 1150 bytes
-rw-r--r--doc/logos/ico/favicon4848.icobin0 -> 15086 bytes
-rw-r--r--doc/logos/png/icon_taler.pngbin0 -> 1835737 bytes
-rw-r--r--doc/logos/png/logo_taler.pngbin0 -> 377176 bytes
-rw-r--r--doc/paper/.latexmkrc15
-rw-r--r--doc/paper/taler.bib94
-rw-r--r--doc/paper/taler.tex995
-rw-r--r--src/.gitignore9
-rw-r--r--src/Makefile.am2
-rw-r--r--src/include/Makefile.am7
-rw-r--r--src/include/platform.h56
-rw-r--r--src/include/taler_db_lib.h132
-rw-r--r--src/include/taler_json_lib.h101
-rw-r--r--src/include/taler_microhttpd_lib.h119
-rw-r--r--src/include/taler_mint_service.h303
-rw-r--r--src/include/taler_rsa.h357
-rw-r--r--src/include/taler_signatures.h106
-rw-r--r--src/include/taler_types.h120
-rw-r--r--src/include/taler_util.h255
-rw-r--r--src/mint/.gitignore6
-rw-r--r--src/mint/Makefile.am131
-rw-r--r--src/mint/mint.h198
-rw-r--r--src/mint/mint_api.c1121
-rw-r--r--src/mint/mint_common.c283
-rw-r--r--src/mint/mint_db.c1838
-rw-r--r--src/mint/mint_db.h344
-rw-r--r--src/mint/taler-mint-dbinit.c285
-rw-r--r--src/mint/taler-mint-httpd.c376
-rw-r--r--src/mint/taler-mint-httpd.h106
-rw-r--r--src/mint/taler-mint-httpd_deposit.c270
-rw-r--r--src/mint/taler-mint-httpd_deposit.h48
-rw-r--r--src/mint/taler-mint-httpd_keys.c512
-rw-r--r--src/mint/taler-mint-httpd_keys.h155
-rw-r--r--src/mint/taler-mint-httpd_mhd.c300
-rw-r--r--src/mint/taler-mint-httpd_mhd.h132
-rw-r--r--src/mint/taler-mint-httpd_refresh.c1497
-rw-r--r--src/mint/taler-mint-httpd_refresh.h103
-rw-r--r--src/mint/taler-mint-httpd_withdraw.c400
-rw-r--r--src/mint/taler-mint-httpd_withdraw.h65
-rw-r--r--src/mint/taler-mint-keycheck.c169
-rw-r--r--src/mint/taler-mint-keyup.c657
-rw-r--r--src/mint/taler-mint-reservemod.c215
-rw-r--r--src/mint/test_mint_api.c211
-rw-r--r--src/mint/test_mint_common.c83
-rw-r--r--src/mint/test_mint_deposits.c149
-rw-r--r--src/mint/test_mint_nayapaisa.eccbin0 -> 32 bytes
-rw-r--r--src/mint/test_mint_nayapaisa/README1
-rw-r--r--src/mint/test_mint_nayapaisa/config/mint-common.conf6
-rw-r--r--src/mint/test_mint_nayapaisa/config/mint-keyup.conf79
-rw-r--r--src/mint/test_mint_nyadirahim.ecc1
-rw-r--r--src/mint/test_mint_nyadirahim/README1
-rw-r--r--src/mint/test_mint_nyadirahim/config/mint-common.conf6
-rw-r--r--src/mint/test_mint_nyadirahim/config/mint-keyup.conf79
-rw-r--r--src/util/Makefile.am39
-rw-r--r--src/util/db.c196
-rw-r--r--src/util/json.c194
-rw-r--r--src/util/microhttpd.c417
-rw-r--r--src/util/misc.supp28
-rw-r--r--src/util/rsa.c925
-rw-r--r--src/util/test_hash_context.c48
-rw-r--r--src/util/test_rsa.c112
-rw-r--r--src/util/util.c528
90 files changed, 19997 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..6fe514889
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
1*~
2*Makefile.in
3*Makefile
4aclocal.m4
5autom4te.cache
6autoscan.log
7compile
8configure
9depcomp
10missing
11taler_config.h.in
12install-sh
13config.log
14config.status
15stamp-h1
16taler_config.h
17config.guess
18config.sub
19libtool
20ltmain.sh
21test-driver
22m4/
23GPATH
24GRTAGS
25GTAGS
26*.swp
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..7625aa983
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
1[submodule "doc/api"]
2 path = doc/api
3 url = git@git.taler.net:api
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 000000000..75e08df1c
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,4 @@
1Sree Harsha Totakura <sreeharsha@totakura.in>
2Florian Dold
3Christian Grothoff <christian@grothoff.org>
4Benedikt Mueller
diff --git a/COPYING b/COPYING
new file mode 100644
index 000000000..dba13ed2d
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,661 @@
1 GNU AFFERO GENERAL PUBLIC LICENSE
2 Version 3, 19 November 2007
3
4 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5 Everyone is permitted to copy and distribute verbatim copies
6 of this license document, but changing it is not allowed.
7
8 Preamble
9
10 The GNU Affero General Public License is a free, copyleft license for
11software and other kinds of works, specifically designed to ensure
12cooperation with the community in the case of network server software.
13
14 The licenses for most software and other practical works are designed
15to take away your freedom to share and change the works. By contrast,
16our General Public Licenses are intended to guarantee your freedom to
17share and change all versions of a program--to make sure it remains free
18software for all its users.
19
20 When we speak of free software, we are referring to freedom, not
21price. Our General Public Licenses are designed to make sure that you
22have the freedom to distribute copies of free software (and charge for
23them if you wish), that you receive source code or can get it if you
24want it, that you can change the software or use pieces of it in new
25free programs, and that you know you can do these things.
26
27 Developers that use our General Public Licenses protect your rights
28with two steps: (1) assert copyright on the software, and (2) offer
29you this License which gives you legal permission to copy, distribute
30and/or modify the software.
31
32 A secondary benefit of defending all users' freedom is that
33improvements made in alternate versions of the program, if they
34receive widespread use, become available for other developers to
35incorporate. Many developers of free software are heartened and
36encouraged by the resulting cooperation. However, in the case of
37software used on network servers, this result may fail to come about.
38The GNU General Public License permits making a modified version and
39letting the public access it on a server without ever releasing its
40source code to the public.
41
42 The GNU Affero General Public License is designed specifically to
43ensure that, in such cases, the modified source code becomes available
44to the community. It requires the operator of a network server to
45provide the source code of the modified version running there to the
46users of that server. Therefore, public use of a modified version, on
47a publicly accessible server, gives the public access to the source
48code of the modified version.
49
50 An older license, called the Affero General Public License and
51published by Affero, was designed to accomplish similar goals. This is
52a different license, not a version of the Affero GPL, but Affero has
53released a new version of the Affero GPL which permits relicensing under
54this license.
55
56 The precise terms and conditions for copying, distribution and
57modification follow.
58
59 TERMS AND CONDITIONS
60
61 0. Definitions.
62
63 "This License" refers to version 3 of the GNU Affero General Public License.
64
65 "Copyright" also means copyright-like laws that apply to other kinds of
66works, such as semiconductor masks.
67
68 "The Program" refers to any copyrightable work licensed under this
69License. Each licensee is addressed as "you". "Licensees" and
70"recipients" may be individuals or organizations.
71
72 To "modify" a work means to copy from or adapt all or part of the work
73in a fashion requiring copyright permission, other than the making of an
74exact copy. The resulting work is called a "modified version" of the
75earlier work or a work "based on" the earlier work.
76
77 A "covered work" means either the unmodified Program or a work based
78on the Program.
79
80 To "propagate" a work means to do anything with it that, without
81permission, would make you directly or secondarily liable for
82infringement under applicable copyright law, except executing it on a
83computer or modifying a private copy. Propagation includes copying,
84distribution (with or without modification), making available to the
85public, and in some countries other activities as well.
86
87 To "convey" a work means any kind of propagation that enables other
88parties to make or receive copies. Mere interaction with a user through
89a computer network, with no transfer of a copy, is not conveying.
90
91 An interactive user interface displays "Appropriate Legal Notices"
92to the extent that it includes a convenient and prominently visible
93feature that (1) displays an appropriate copyright notice, and (2)
94tells the user that there is no warranty for the work (except to the
95extent that warranties are provided), that licensees may convey the
96work under this License, and how to view a copy of this License. If
97the interface presents a list of user commands or options, such as a
98menu, a prominent item in the list meets this criterion.
99
100 1. Source Code.
101
102 The "source code" for a work means the preferred form of the work
103for making modifications to it. "Object code" means any non-source
104form of a work.
105
106 A "Standard Interface" means an interface that either is an official
107standard defined by a recognized standards body, or, in the case of
108interfaces specified for a particular programming language, one that
109is widely used among developers working in that language.
110
111 The "System Libraries" of an executable work include anything, other
112than the work as a whole, that (a) is included in the normal form of
113packaging a Major Component, but which is not part of that Major
114Component, and (b) serves only to enable use of the work with that
115Major Component, or to implement a Standard Interface for which an
116implementation is available to the public in source code form. A
117"Major Component", in this context, means a major essential component
118(kernel, window system, and so on) of the specific operating system
119(if any) on which the executable work runs, or a compiler used to
120produce the work, or an object code interpreter used to run it.
121
122 The "Corresponding Source" for a work in object code form means all
123the source code needed to generate, install, and (for an executable
124work) run the object code and to modify the work, including scripts to
125control those activities. However, it does not include the work's
126System Libraries, or general-purpose tools or generally available free
127programs which are used unmodified in performing those activities but
128which are not part of the work. For example, Corresponding Source
129includes interface definition files associated with source files for
130the work, and the source code for shared libraries and dynamically
131linked subprograms that the work is specifically designed to require,
132such as by intimate data communication or control flow between those
133subprograms and other parts of the work.
134
135 The Corresponding Source need not include anything that users
136can regenerate automatically from other parts of the Corresponding
137Source.
138
139 The Corresponding Source for a work in source code form is that
140same work.
141
142 2. Basic Permissions.
143
144 All rights granted under this License are granted for the term of
145copyright on the Program, and are irrevocable provided the stated
146conditions are met. This License explicitly affirms your unlimited
147permission to run the unmodified Program. The output from running a
148covered work is covered by this License only if the output, given its
149content, constitutes a covered work. This License acknowledges your
150rights of fair use or other equivalent, as provided by copyright law.
151
152 You may make, run and propagate covered works that you do not
153convey, without conditions so long as your license otherwise remains
154in force. You may convey covered works to others for the sole purpose
155of having them make modifications exclusively for you, or provide you
156with facilities for running those works, provided that you comply with
157the terms of this License in conveying all material for which you do
158not control copyright. Those thus making or running the covered works
159for you must do so exclusively on your behalf, under your direction
160and control, on terms that prohibit them from making any copies of
161your copyrighted material outside their relationship with you.
162
163 Conveying under any other circumstances is permitted solely under
164the conditions stated below. Sublicensing is not allowed; section 10
165makes it unnecessary.
166
167 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168
169 No covered work shall be deemed part of an effective technological
170measure under any applicable law fulfilling obligations under article
17111 of the WIPO copyright treaty adopted on 20 December 1996, or
172similar laws prohibiting or restricting circumvention of such
173measures.
174
175 When you convey a covered work, you waive any legal power to forbid
176circumvention of technological measures to the extent such circumvention
177is effected by exercising rights under this License with respect to
178the covered work, and you disclaim any intention to limit operation or
179modification of the work as a means of enforcing, against the work's
180users, your or third parties' legal rights to forbid circumvention of
181technological measures.
182
183 4. Conveying Verbatim Copies.
184
185 You may convey verbatim copies of the Program's source code as you
186receive it, in any medium, provided that you conspicuously and
187appropriately publish on each copy an appropriate copyright notice;
188keep intact all notices stating that this License and any
189non-permissive terms added in accord with section 7 apply to the code;
190keep intact all notices of the absence of any warranty; and give all
191recipients a copy of this License along with the Program.
192
193 You may charge any price or no price for each copy that you convey,
194and you may offer support or warranty protection for a fee.
195
196 5. Conveying Modified Source Versions.
197
198 You may convey a work based on the Program, or the modifications to
199produce it from the Program, in the form of source code under the
200terms of section 4, provided that you also meet all of these conditions:
201
202 a) The work must carry prominent notices stating that you modified
203 it, and giving a relevant date.
204
205 b) The work must carry prominent notices stating that it is
206 released under this License and any conditions added under section
207 7. This requirement modifies the requirement in section 4 to
208 "keep intact all notices".
209
210 c) You must license the entire work, as a whole, under this
211 License to anyone who comes into possession of a copy. This
212 License will therefore apply, along with any applicable section 7
213 additional terms, to the whole of the work, and all its parts,
214 regardless of how they are packaged. This License gives no
215 permission to license the work in any other way, but it does not
216 invalidate such permission if you have separately received it.
217
218 d) If the work has interactive user interfaces, each must display
219 Appropriate Legal Notices; however, if the Program has interactive
220 interfaces that do not display Appropriate Legal Notices, your
221 work need not make them do so.
222
223 A compilation of a covered work with other separate and independent
224works, which are not by their nature extensions of the covered work,
225and which are not combined with it such as to form a larger program,
226in or on a volume of a storage or distribution medium, is called an
227"aggregate" if the compilation and its resulting copyright are not
228used to limit the access or legal rights of the compilation's users
229beyond what the individual works permit. Inclusion of a covered work
230in an aggregate does not cause this License to apply to the other
231parts of the aggregate.
232
233 6. Conveying Non-Source Forms.
234
235 You may convey a covered work in object code form under the terms
236of sections 4 and 5, provided that you also convey the
237machine-readable Corresponding Source under the terms of this License,
238in one of these ways:
239
240 a) Convey the object code in, or embodied in, a physical product
241 (including a physical distribution medium), accompanied by the
242 Corresponding Source fixed on a durable physical medium
243 customarily used for software interchange.
244
245 b) Convey the object code in, or embodied in, a physical product
246 (including a physical distribution medium), accompanied by a
247 written offer, valid for at least three years and valid for as
248 long as you offer spare parts or customer support for that product
249 model, to give anyone who possesses the object code either (1) a
250 copy of the Corresponding Source for all the software in the
251 product that is covered by this License, on a durable physical
252 medium customarily used for software interchange, for a price no
253 more than your reasonable cost of physically performing this
254 conveying of source, or (2) access to copy the
255 Corresponding Source from a network server at no charge.
256
257 c) Convey individual copies of the object code with a copy of the
258 written offer to provide the Corresponding Source. This
259 alternative is allowed only occasionally and noncommercially, and
260 only if you received the object code with such an offer, in accord
261 with subsection 6b.
262
263 d) Convey the object code by offering access from a designated
264 place (gratis or for a charge), and offer equivalent access to the
265 Corresponding Source in the same way through the same place at no
266 further charge. You need not require recipients to copy the
267 Corresponding Source along with the object code. If the place to
268 copy the object code is a network server, the Corresponding Source
269 may be on a different server (operated by you or a third party)
270 that supports equivalent copying facilities, provided you maintain
271 clear directions next to the object code saying where to find the
272 Corresponding Source. Regardless of what server hosts the
273 Corresponding Source, you remain obligated to ensure that it is
274 available for as long as needed to satisfy these requirements.
275
276 e) Convey the object code using peer-to-peer transmission, provided
277 you inform other peers where the object code and Corresponding
278 Source of the work are being offered to the general public at no
279 charge under subsection 6d.
280
281 A separable portion of the object code, whose source code is excluded
282from the Corresponding Source as a System Library, need not be
283included in conveying the object code work.
284
285 A "User Product" is either (1) a "consumer product", which means any
286tangible personal property which is normally used for personal, family,
287or household purposes, or (2) anything designed or sold for incorporation
288into a dwelling. In determining whether a product is a consumer product,
289doubtful cases shall be resolved in favor of coverage. For a particular
290product received by a particular user, "normally used" refers to a
291typical or common use of that class of product, regardless of the status
292of the particular user or of the way in which the particular user
293actually uses, or expects or is expected to use, the product. A product
294is a consumer product regardless of whether the product has substantial
295commercial, industrial or non-consumer uses, unless such uses represent
296the only significant mode of use of the product.
297
298 "Installation Information" for a User Product means any methods,
299procedures, authorization keys, or other information required to install
300and execute modified versions of a covered work in that User Product from
301a modified version of its Corresponding Source. The information must
302suffice to ensure that the continued functioning of the modified object
303code is in no case prevented or interfered with solely because
304modification has been made.
305
306 If you convey an object code work under this section in, or with, or
307specifically for use in, a User Product, and the conveying occurs as
308part of a transaction in which the right of possession and use of the
309User Product is transferred to the recipient in perpetuity or for a
310fixed term (regardless of how the transaction is characterized), the
311Corresponding Source conveyed under this section must be accompanied
312by the Installation Information. But this requirement does not apply
313if neither you nor any third party retains the ability to install
314modified object code on the User Product (for example, the work has
315been installed in ROM).
316
317 The requirement to provide Installation Information does not include a
318requirement to continue to provide support service, warranty, or updates
319for a work that has been modified or installed by the recipient, or for
320the User Product in which it has been modified or installed. Access to a
321network may be denied when the modification itself materially and
322adversely affects the operation of the network or violates the rules and
323protocols for communication across the network.
324
325 Corresponding Source conveyed, and Installation Information provided,
326in accord with this section must be in a format that is publicly
327documented (and with an implementation available to the public in
328source code form), and must require no special password or key for
329unpacking, reading or copying.
330
331 7. Additional Terms.
332
333 "Additional permissions" are terms that supplement the terms of this
334License by making exceptions from one or more of its conditions.
335Additional permissions that are applicable to the entire Program shall
336be treated as though they were included in this License, to the extent
337that they are valid under applicable law. If additional permissions
338apply only to part of the Program, that part may be used separately
339under those permissions, but the entire Program remains governed by
340this License without regard to the additional permissions.
341
342 When you convey a copy of a covered work, you may at your option
343remove any additional permissions from that copy, or from any part of
344it. (Additional permissions may be written to require their own
345removal in certain cases when you modify the work.) You may place
346additional permissions on material, added by you to a covered work,
347for which you have or can give appropriate copyright permission.
348
349 Notwithstanding any other provision of this License, for material you
350add to a covered work, you may (if authorized by the copyright holders of
351that material) supplement the terms of this License with terms:
352
353 a) Disclaiming warranty or limiting liability differently from the
354 terms of sections 15 and 16 of this License; or
355
356 b) Requiring preservation of specified reasonable legal notices or
357 author attributions in that material or in the Appropriate Legal
358 Notices displayed by works containing it; or
359
360 c) Prohibiting misrepresentation of the origin of that material, or
361 requiring that modified versions of such material be marked in
362 reasonable ways as different from the original version; or
363
364 d) Limiting the use for publicity purposes of names of licensors or
365 authors of the material; or
366
367 e) Declining to grant rights under trademark law for use of some
368 trade names, trademarks, or service marks; or
369
370 f) Requiring indemnification of licensors and authors of that
371 material by anyone who conveys the material (or modified versions of
372 it) with contractual assumptions of liability to the recipient, for
373 any liability that these contractual assumptions directly impose on
374 those licensors and authors.
375
376 All other non-permissive additional terms are considered "further
377restrictions" within the meaning of section 10. If the Program as you
378received it, or any part of it, contains a notice stating that it is
379governed by this License along with a term that is a further
380restriction, you may remove that term. If a license document contains
381a further restriction but permits relicensing or conveying under this
382License, you may add to a covered work material governed by the terms
383of that license document, provided that the further restriction does
384not survive such relicensing or conveying.
385
386 If you add terms to a covered work in accord with this section, you
387must place, in the relevant source files, a statement of the
388additional terms that apply to those files, or a notice indicating
389where to find the applicable terms.
390
391 Additional terms, permissive or non-permissive, may be stated in the
392form of a separately written license, or stated as exceptions;
393the above requirements apply either way.
394
395 8. Termination.
396
397 You may not propagate or modify a covered work except as expressly
398provided under this License. Any attempt otherwise to propagate or
399modify it is void, and will automatically terminate your rights under
400this License (including any patent licenses granted under the third
401paragraph of section 11).
402
403 However, if you cease all violation of this License, then your
404license from a particular copyright holder is reinstated (a)
405provisionally, unless and until the copyright holder explicitly and
406finally terminates your license, and (b) permanently, if the copyright
407holder fails to notify you of the violation by some reasonable means
408prior to 60 days after the cessation.
409
410 Moreover, your license from a particular copyright holder is
411reinstated permanently if the copyright holder notifies you of the
412violation by some reasonable means, this is the first time you have
413received notice of violation of this License (for any work) from that
414copyright holder, and you cure the violation prior to 30 days after
415your receipt of the notice.
416
417 Termination of your rights under this section does not terminate the
418licenses of parties who have received copies or rights from you under
419this License. If your rights have been terminated and not permanently
420reinstated, you do not qualify to receive new licenses for the same
421material under section 10.
422
423 9. Acceptance Not Required for Having Copies.
424
425 You are not required to accept this License in order to receive or
426run a copy of the Program. Ancillary propagation of a covered work
427occurring solely as a consequence of using peer-to-peer transmission
428to receive a copy likewise does not require acceptance. However,
429nothing other than this License grants you permission to propagate or
430modify any covered work. These actions infringe copyright if you do
431not accept this License. Therefore, by modifying or propagating a
432covered work, you indicate your acceptance of this License to do so.
433
434 10. Automatic Licensing of Downstream Recipients.
435
436 Each time you convey a covered work, the recipient automatically
437receives a license from the original licensors, to run, modify and
438propagate that work, subject to this License. You are not responsible
439for enforcing compliance by third parties with this License.
440
441 An "entity transaction" is a transaction transferring control of an
442organization, or substantially all assets of one, or subdividing an
443organization, or merging organizations. If propagation of a covered
444work results from an entity transaction, each party to that
445transaction who receives a copy of the work also receives whatever
446licenses to the work the party's predecessor in interest had or could
447give under the previous paragraph, plus a right to possession of the
448Corresponding Source of the work from the predecessor in interest, if
449the predecessor has it or can get it with reasonable efforts.
450
451 You may not impose any further restrictions on the exercise of the
452rights granted or affirmed under this License. For example, you may
453not impose a license fee, royalty, or other charge for exercise of
454rights granted under this License, and you may not initiate litigation
455(including a cross-claim or counterclaim in a lawsuit) alleging that
456any patent claim is infringed by making, using, selling, offering for
457sale, or importing the Program or any portion of it.
458
459 11. Patents.
460
461 A "contributor" is a copyright holder who authorizes use under this
462License of the Program or a work on which the Program is based. The
463work thus licensed is called the contributor's "contributor version".
464
465 A contributor's "essential patent claims" are all patent claims
466owned or controlled by the contributor, whether already acquired or
467hereafter acquired, that would be infringed by some manner, permitted
468by this License, of making, using, or selling its contributor version,
469but do not include claims that would be infringed only as a
470consequence of further modification of the contributor version. For
471purposes of this definition, "control" includes the right to grant
472patent sublicenses in a manner consistent with the requirements of
473this License.
474
475 Each contributor grants you a non-exclusive, worldwide, royalty-free
476patent license under the contributor's essential patent claims, to
477make, use, sell, offer for sale, import and otherwise run, modify and
478propagate the contents of its contributor version.
479
480 In the following three paragraphs, a "patent license" is any express
481agreement or commitment, however denominated, not to enforce a patent
482(such as an express permission to practice a patent or covenant not to
483sue for patent infringement). To "grant" such a patent license to a
484party means to make such an agreement or commitment not to enforce a
485patent against the party.
486
487 If you convey a covered work, knowingly relying on a patent license,
488and the Corresponding Source of the work is not available for anyone
489to copy, free of charge and under the terms of this License, through a
490publicly available network server or other readily accessible means,
491then you must either (1) cause the Corresponding Source to be so
492available, or (2) arrange to deprive yourself of the benefit of the
493patent license for this particular work, or (3) arrange, in a manner
494consistent with the requirements of this License, to extend the patent
495license to downstream recipients. "Knowingly relying" means you have
496actual knowledge that, but for the patent license, your conveying the
497covered work in a country, or your recipient's use of the covered work
498in a country, would infringe one or more identifiable patents in that
499country that you have reason to believe are valid.
500
501 If, pursuant to or in connection with a single transaction or
502arrangement, you convey, or propagate by procuring conveyance of, a
503covered work, and grant a patent license to some of the parties
504receiving the covered work authorizing them to use, propagate, modify
505or convey a specific copy of the covered work, then the patent license
506you grant is automatically extended to all recipients of the covered
507work and works based on it.
508
509 A patent license is "discriminatory" if it does not include within
510the scope of its coverage, prohibits the exercise of, or is
511conditioned on the non-exercise of one or more of the rights that are
512specifically granted under this License. You may not convey a covered
513work if you are a party to an arrangement with a third party that is
514in the business of distributing software, under which you make payment
515to the third party based on the extent of your activity of conveying
516the work, and under which the third party grants, to any of the
517parties who would receive the covered work from you, a discriminatory
518patent license (a) in connection with copies of the covered work
519conveyed by you (or copies made from those copies), or (b) primarily
520for and in connection with specific products or compilations that
521contain the covered work, unless you entered into that arrangement,
522or that patent license was granted, prior to 28 March 2007.
523
524 Nothing in this License shall be construed as excluding or limiting
525any implied license or other defenses to infringement that may
526otherwise be available to you under applicable patent law.
527
528 12. No Surrender of Others' Freedom.
529
530 If conditions are imposed on you (whether by court order, agreement or
531otherwise) that contradict the conditions of this License, they do not
532excuse you from the conditions of this License. If you cannot convey a
533covered work so as to satisfy simultaneously your obligations under this
534License and any other pertinent obligations, then as a consequence you may
535not convey it at all. For example, if you agree to terms that obligate you
536to collect a royalty for further conveying from those to whom you convey
537the Program, the only way you could satisfy both those terms and this
538License would be to refrain entirely from conveying the Program.
539
540 13. Remote Network Interaction; Use with the GNU General Public License.
541
542 Notwithstanding any other provision of this License, if you modify the
543Program, your modified version must prominently offer all users
544interacting with it remotely through a computer network (if your version
545supports such interaction) an opportunity to receive the Corresponding
546Source of your version by providing access to the Corresponding Source
547from a network server at no charge, through some standard or customary
548means of facilitating copying of software. This Corresponding Source
549shall include the Corresponding Source for any work covered by version 3
550of the GNU General Public License that is incorporated pursuant to the
551following paragraph.
552
553 Notwithstanding any other provision of this License, you have
554permission to link or combine any covered work with a work licensed
555under version 3 of the GNU General Public License into a single
556combined work, and to convey the resulting work. The terms of this
557License will continue to apply to the part which is the covered work,
558but the work with which it is combined will remain governed by version
5593 of the GNU General Public License.
560
561 14. Revised Versions of this License.
562
563 The Free Software Foundation may publish revised and/or new versions of
564the GNU Affero General Public License from time to time. Such new versions
565will be similar in spirit to the present version, but may differ in detail to
566address new problems or concerns.
567
568 Each version is given a distinguishing version number. If the
569Program specifies that a certain numbered version of the GNU Affero General
570Public License "or any later version" applies to it, you have the
571option of following the terms and conditions either of that numbered
572version or of any later version published by the Free Software
573Foundation. If the Program does not specify a version number of the
574GNU Affero General Public License, you may choose any version ever published
575by the Free Software Foundation.
576
577 If the Program specifies that a proxy can decide which future
578versions of the GNU Affero General Public License can be used, that proxy's
579public statement of acceptance of a version permanently authorizes you
580to choose that version for the Program.
581
582 Later license versions may give you additional or different
583permissions. However, no additional obligations are imposed on any
584author or copyright holder as a result of your choosing to follow a
585later version.
586
587 15. Disclaimer of Warranty.
588
589 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597
598 16. Limitation of Liability.
599
600 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608SUCH DAMAGES.
609
610 17. Interpretation of Sections 15 and 16.
611
612 If the disclaimer of warranty and limitation of liability provided
613above cannot be given local legal effect according to their terms,
614reviewing courts shall apply local law that most closely approximates
615an absolute waiver of all civil liability in connection with the
616Program, unless a warranty or assumption of liability accompanies a
617copy of the Program in return for a fee.
618
619 END OF TERMS AND CONDITIONS
620
621 How to Apply These Terms to Your New Programs
622
623 If you develop a new program, and you want it to be of the greatest
624possible use to the public, the best way to achieve this is to make it
625free software which everyone can redistribute and change under these terms.
626
627 To do so, attach the following notices to the program. It is safest
628to attach them to the start of each source file to most effectively
629state the exclusion of warranty; and each file should have at least
630the "copyright" line and a pointer to where the full notice is found.
631
632 <one line to give the program's name and a brief idea of what it does.>
633 Copyright (C) <year> <name of author>
634
635 This program is free software: you can redistribute it and/or modify
636 it under the terms of the GNU Affero General Public License as published by
637 the Free Software Foundation, either version 3 of the License, or
638 (at your option) any later version.
639
640 This program is distributed in the hope that it will be useful,
641 but WITHOUT ANY WARRANTY; without even the implied warranty of
642 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643 GNU Affero General Public License for more details.
644
645 You should have received a copy of the GNU Affero General Public License
646 along with this program. If not, see <http://www.gnu.org/licenses/>.
647
648Also add information on how to contact you by electronic and paper mail.
649
650 If your software can interact with users remotely through a computer
651network, you should also make sure that it provides a way for users to
652get its source. For example, if your program is a web application, its
653interface could display a "Source" link that leads users to an archive
654of the code. There are many ways you could offer source, and different
655solutions will be better for different programs; see section 13 for the
656specific requirements.
657
658 You should also get your employer (if you work as a programmer) or school,
659if any, to sign a "copyright disclaimer" for the program, if necessary.
660For more information on this, and how to apply and follow the GNU AGPL, see
661<http://www.gnu.org/licenses/>.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ChangeLog
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 000000000..209984075
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,370 @@
1Installation Instructions
2*************************
3
4Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
5Inc.
6
7 Copying and distribution of this file, with or without modification,
8are permitted in any medium without royalty provided the copyright
9notice and this notice are preserved. This file is offered as-is,
10without warranty of any kind.
11
12Basic Installation
13==================
14
15 Briefly, the shell command `./configure && make && make install'
16should configure, build, and install this package. The following
17more-detailed instructions are generic; see the `README' file for
18instructions specific to this package. Some packages provide this
19`INSTALL' file but do not implement all of the features documented
20below. The lack of an optional feature in a given package is not
21necessarily a bug. More recommendations for GNU packages can be found
22in *note Makefile Conventions: (standards)Makefile Conventions.
23
24 The `configure' shell script attempts to guess correct values for
25various system-dependent variables used during compilation. It uses
26those values to create a `Makefile' in each directory of the package.
27It may also create one or more `.h' files containing system-dependent
28definitions. Finally, it creates a shell script `config.status' that
29you can run in the future to recreate the current configuration, and a
30file `config.log' containing compiler output (useful mainly for
31debugging `configure').
32
33 It can also use an optional file (typically called `config.cache'
34and enabled with `--cache-file=config.cache' or simply `-C') that saves
35the results of its tests to speed up reconfiguring. Caching is
36disabled by default to prevent problems with accidental use of stale
37cache files.
38
39 If you need to do unusual things to compile the package, please try
40to figure out how `configure' could check whether to do them, and mail
41diffs or instructions to the address given in the `README' so they can
42be considered for the next release. If you are using the cache, and at
43some point `config.cache' contains results you don't want to keep, you
44may remove or edit it.
45
46 The file `configure.ac' (or `configure.in') is used to create
47`configure' by a program called `autoconf'. You need `configure.ac' if
48you want to change it or regenerate `configure' using a newer version
49of `autoconf'.
50
51 The simplest way to compile this package is:
52
53 1. `cd' to the directory containing the package's source code and type
54 `./configure' to configure the package for your system.
55
56 Running `configure' might take a while. While running, it prints
57 some messages telling which features it is checking for.
58
59 2. Type `make' to compile the package.
60
61 3. Optionally, type `make check' to run any self-tests that come with
62 the package, generally using the just-built uninstalled binaries.
63
64 4. Type `make install' to install the programs and any data files and
65 documentation. When installing into a prefix owned by root, it is
66 recommended that the package be configured and built as a regular
67 user, and only the `make install' phase executed with root
68 privileges.
69
70 5. Optionally, type `make installcheck' to repeat any self-tests, but
71 this time using the binaries in their final installed location.
72 This target does not install anything. Running this target as a
73 regular user, particularly if the prior `make install' required
74 root privileges, verifies that the installation completed
75 correctly.
76
77 6. You can remove the program binaries and object files from the
78 source code directory by typing `make clean'. To also remove the
79 files that `configure' created (so you can compile the package for
80 a different kind of computer), type `make distclean'. There is
81 also a `make maintainer-clean' target, but that is intended mainly
82 for the package's developers. If you use it, you may have to get
83 all sorts of other programs in order to regenerate files that came
84 with the distribution.
85
86 7. Often, you can also type `make uninstall' to remove the installed
87 files again. In practice, not all packages have tested that
88 uninstallation works correctly, even though it is required by the
89 GNU Coding Standards.
90
91 8. Some packages, particularly those that use Automake, provide `make
92 distcheck', which can by used by developers to test that all other
93 targets like `make install' and `make uninstall' work correctly.
94 This target is generally not run by end users.
95
96Compilers and Options
97=====================
98
99 Some systems require unusual options for compilation or linking that
100the `configure' script does not know about. Run `./configure --help'
101for details on some of the pertinent environment variables.
102
103 You can give `configure' initial values for configuration parameters
104by setting variables in the command line or in the environment. Here
105is an example:
106
107 ./configure CC=c99 CFLAGS=-g LIBS=-lposix
108
109 *Note Defining Variables::, for more details.
110
111Compiling For Multiple Architectures
112====================================
113
114 You can compile the package for more than one kind of computer at the
115same time, by placing the object files for each architecture in their
116own directory. To do this, you can use GNU `make'. `cd' to the
117directory where you want the object files and executables to go and run
118the `configure' script. `configure' automatically checks for the
119source code in the directory that `configure' is in and in `..'. This
120is known as a "VPATH" build.
121
122 With a non-GNU `make', it is safer to compile the package for one
123architecture at a time in the source code directory. After you have
124installed the package for one architecture, use `make distclean' before
125reconfiguring for another architecture.
126
127 On MacOS X 10.5 and later systems, you can create libraries and
128executables that work on multiple system types--known as "fat" or
129"universal" binaries--by specifying multiple `-arch' options to the
130compiler but only a single `-arch' option to the preprocessor. Like
131this:
132
133 ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
134 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
135 CPP="gcc -E" CXXCPP="g++ -E"
136
137 This is not guaranteed to produce working output in all cases, you
138may have to build one architecture at a time and combine the results
139using the `lipo' tool if you have problems.
140
141Installation Names
142==================
143
144 By default, `make install' installs the package's commands under
145`/usr/local/bin', include files under `/usr/local/include', etc. You
146can specify an installation prefix other than `/usr/local' by giving
147`configure' the option `--prefix=PREFIX', where PREFIX must be an
148absolute file name.
149
150 You can specify separate installation prefixes for
151architecture-specific files and architecture-independent files. If you
152pass the option `--exec-prefix=PREFIX' to `configure', the package uses
153PREFIX as the prefix for installing programs and libraries.
154Documentation and other data files still use the regular prefix.
155
156 In addition, if you use an unusual directory layout you can give
157options like `--bindir=DIR' to specify different values for particular
158kinds of files. Run `configure --help' for a list of the directories
159you can set and what kinds of files go in them. In general, the
160default for these options is expressed in terms of `${prefix}', so that
161specifying just `--prefix' will affect all of the other directory
162specifications that were not explicitly provided.
163
164 The most portable way to affect installation locations is to pass the
165correct locations to `configure'; however, many packages provide one or
166both of the following shortcuts of passing variable assignments to the
167`make install' command line to change installation locations without
168having to reconfigure or recompile.
169
170 The first method involves providing an override variable for each
171affected directory. For example, `make install
172prefix=/alternate/directory' will choose an alternate location for all
173directory configuration variables that were expressed in terms of
174`${prefix}'. Any directories that were specified during `configure',
175but not in terms of `${prefix}', must each be overridden at install
176time for the entire installation to be relocated. The approach of
177makefile variable overrides for each directory variable is required by
178the GNU Coding Standards, and ideally causes no recompilation.
179However, some platforms have known limitations with the semantics of
180shared libraries that end up requiring recompilation when using this
181method, particularly noticeable in packages that use GNU Libtool.
182
183 The second method involves providing the `DESTDIR' variable. For
184example, `make install DESTDIR=/alternate/directory' will prepend
185`/alternate/directory' before all installation names. The approach of
186`DESTDIR' overrides is not required by the GNU Coding Standards, and
187does not work on platforms that have drive letters. On the other hand,
188it does better at avoiding recompilation issues, and works well even
189when some directory options were not specified in terms of `${prefix}'
190at `configure' time.
191
192Optional Features
193=================
194
195 If the package supports it, you can cause programs to be installed
196with an extra prefix or suffix on their names by giving `configure' the
197option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
198
199 Some packages pay attention to `--enable-FEATURE' options to
200`configure', where FEATURE indicates an optional part of the package.
201They may also pay attention to `--with-PACKAGE' options, where PACKAGE
202is something like `gnu-as' or `x' (for the X Window System). The
203`README' should mention any `--enable-' and `--with-' options that the
204package recognizes.
205
206 For packages that use the X Window System, `configure' can usually
207find the X include and library files automatically, but if it doesn't,
208you can use the `configure' options `--x-includes=DIR' and
209`--x-libraries=DIR' to specify their locations.
210
211 Some packages offer the ability to configure how verbose the
212execution of `make' will be. For these packages, running `./configure
213--enable-silent-rules' sets the default to minimal output, which can be
214overridden with `make V=1'; while running `./configure
215--disable-silent-rules' sets the default to verbose, which can be
216overridden with `make V=0'.
217
218Particular systems
219==================
220
221 On HP-UX, the default C compiler is not ANSI C compatible. If GNU
222CC is not installed, it is recommended to use the following options in
223order to use an ANSI C compiler:
224
225 ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
226
227and if that doesn't work, install pre-built binaries of GCC for HP-UX.
228
229 HP-UX `make' updates targets which have the same time stamps as
230their prerequisites, which makes it generally unusable when shipped
231generated files such as `configure' are involved. Use GNU `make'
232instead.
233
234 On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
235parse its `<wchar.h>' header file. The option `-nodtk' can be used as
236a workaround. If GNU CC is not installed, it is therefore recommended
237to try
238
239 ./configure CC="cc"
240
241and if that doesn't work, try
242
243 ./configure CC="cc -nodtk"
244
245 On Solaris, don't put `/usr/ucb' early in your `PATH'. This
246directory contains several dysfunctional programs; working variants of
247these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
248in your `PATH', put it _after_ `/usr/bin'.
249
250 On Haiku, software installed for all users goes in `/boot/common',
251not `/usr/local'. It is recommended to use the following options:
252
253 ./configure --prefix=/boot/common
254
255Specifying the System Type
256==========================
257
258 There may be some features `configure' cannot figure out
259automatically, but needs to determine by the type of machine the package
260will run on. Usually, assuming the package is built to be run on the
261_same_ architectures, `configure' can figure that out, but if it prints
262a message saying it cannot guess the machine type, give it the
263`--build=TYPE' option. TYPE can either be a short name for the system
264type, such as `sun4', or a canonical name which has the form:
265
266 CPU-COMPANY-SYSTEM
267
268where SYSTEM can have one of these forms:
269
270 OS
271 KERNEL-OS
272
273 See the file `config.sub' for the possible values of each field. If
274`config.sub' isn't included in this package, then this package doesn't
275need to know the machine type.
276
277 If you are _building_ compiler tools for cross-compiling, you should
278use the option `--target=TYPE' to select the type of system they will
279produce code for.
280
281 If you want to _use_ a cross compiler, that generates code for a
282platform different from the build platform, you should specify the
283"host" platform (i.e., that on which the generated programs will
284eventually be run) with `--host=TYPE'.
285
286Sharing Defaults
287================
288
289 If you want to set default values for `configure' scripts to share,
290you can create a site shell script called `config.site' that gives
291default values for variables like `CC', `cache_file', and `prefix'.
292`configure' looks for `PREFIX/share/config.site' if it exists, then
293`PREFIX/etc/config.site' if it exists. Or, you can set the
294`CONFIG_SITE' environment variable to the location of the site script.
295A warning: not all `configure' scripts look for a site script.
296
297Defining Variables
298==================
299
300 Variables not defined in a site shell script can be set in the
301environment passed to `configure'. However, some packages may run
302configure again during the build, and the customized values of these
303variables may be lost. In order to avoid this problem, you should set
304them in the `configure' command line, using `VAR=value'. For example:
305
306 ./configure CC=/usr/local2/bin/gcc
307
308causes the specified `gcc' to be used as the C compiler (unless it is
309overridden in the site shell script).
310
311Unfortunately, this technique does not work for `CONFIG_SHELL' due to
312an Autoconf limitation. Until the limitation is lifted, you can use
313this workaround:
314
315 CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
316
317`configure' Invocation
318======================
319
320 `configure' recognizes the following options to control how it
321operates.
322
323`--help'
324`-h'
325 Print a summary of all of the options to `configure', and exit.
326
327`--help=short'
328`--help=recursive'
329 Print a summary of the options unique to this package's
330 `configure', and exit. The `short' variant lists options used
331 only in the top level, while the `recursive' variant lists options
332 also present in any nested packages.
333
334`--version'
335`-V'
336 Print the version of Autoconf used to generate the `configure'
337 script, and exit.
338
339`--cache-file=FILE'
340 Enable the cache: use and save the results of the tests in FILE,
341 traditionally `config.cache'. FILE defaults to `/dev/null' to
342 disable caching.
343
344`--config-cache'
345`-C'
346 Alias for `--cache-file=config.cache'.
347
348`--quiet'
349`--silent'
350`-q'
351 Do not print messages saying which checks are being made. To
352 suppress all normal output, redirect it to `/dev/null' (any error
353 messages will still be shown).
354
355`--srcdir=DIR'
356 Look for the package's source code in directory DIR. Usually
357 `configure' can determine that directory automatically.
358
359`--prefix=DIR'
360 Use DIR as the installation prefix. *note Installation Names::
361 for more details, including other options available for fine-tuning
362 the installation locations.
363
364`--no-create'
365`-n'
366 Run the configure checks, but stop before creating any output
367 files.
368
369`configure' also accepts some other, not widely useful, options. Run
370`configure --help' for more details.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 000000000..ea5a667ef
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,3 @@
1AM_CPPFLAGS = -I$(top_srcdir)/src/include
2SUBDIRS = src doc
3ACLOCAL_AMFLAGS = -I m4
diff --git a/NEWS b/NEWS
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/README
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 000000000..4e7cc0537
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,2 @@
1#!/bin/sh
2autoreconf -if
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 000000000..789df8e46
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,156 @@
1# -*- Autoconf -*-
2# Process this file with autoconf to produce a configure script.
3
4AC_PREREQ([2.69])
5AC_INIT([taler-mint], [0.0.0], [taler-bug@gnunet.org])
6AC_CONFIG_SRCDIR([src/util/json.c])
7AC_CONFIG_HEADERS([taler_config.h])
8# support for non-recursive builds
9AM_INIT_AUTOMAKE([subdir-objects])
10
11# pretty build rules
12AM_SILENT_RULES([yes])
13
14AC_CONFIG_MACRO_DIR([m4])
15
16LT_INIT
17
18# Checks for programs.
19AC_PROG_CC
20
21CFLAGS="-Wall $CFLAGS"
22
23# Checks for header files.
24AC_CHECK_HEADERS([stdint.h stdlib.h string.h unistd.h])
25
26# Check for GNUnet's libgnunetutil.
27libgnunetutil=0
28AC_MSG_CHECKING([for libgnunetutil])
29AC_ARG_WITH(gnunet,
30 [AS_HELP_STRING([--with-gnunet=PFX], [base of GNUnet installation])],
31 [AC_MSG_RESULT([given as $with_gnunet])],
32 [AC_MSG_RESULT(not given)
33 with_gnunet=yes])
34AS_CASE([$with_gnunet],
35 [yes], [],
36 [no], [AC_MSG_ERROR([--with-gnunet is required])],
37 [LDFLAGS="-L$with_gnunet/lib $LDFLAGS"
38 CPPFLAGS="-I$with_gnunet/include $CPPFLAGS"])
39AC_CHECK_HEADERS([gnunet/platform.h gnunet/gnunet_util_lib.h],
40 [AC_CHECK_LIB([gnunetutil], [GNUNET_SCHEDULER_run], libgnunetutil=1)],
41 [], [#ifdef HAVE_GNUNET_PLATFORM_H
42 #include <gnunet/platform.h>
43 #endif])
44AS_IF([test $libgnunetutil != 1],
45 [AC_MSG_ERROR([[
46***
47*** You need libgnunetutil to build this program.
48*** This library is part of GNUnet, available at
49*** https://gnunet.org
50*** ]])])
51
52
53# check for libmicrohttpd
54microhttpd=0
55AC_MSG_CHECKING([for microhttpd])
56AC_ARG_WITH([microhttpd],
57 [AS_HELP_STRING([--with-microhttpd=PFX], [base of microhttpd installation])],
58 [AC_MSG_RESULT([given as $with_microhttpd])],
59 [AC_MSG_RESULT([not given])
60 with_microhttpd=yes])
61AS_CASE([$with_microhttpd],
62 [yes], [],
63 [no], [AC_MSG_ERROR([--with-microhttpd is required])],
64 [LDFLAGS="-L$with_microhttpd/lib $LDFLAGS"
65 CPPFLAGS="-I$with_microhttpd/include $CPPFLAGS"])
66AC_CHECK_LIB(microhttpd,MHD_start_daemon,
67 [AC_CHECK_HEADER([microhttpd.h],[microhttpd=1])])
68AS_IF([test $microhttpd = 0],
69 [AC_MSG_ERROR([[
70***
71*** You need libmicrohttpd to build this program.
72*** ]])])
73
74
75# check for libpq (postgresql)
76AX_LIB_POSTGRESQL([9.3])
77AS_IF([test ! "$found_postgresql" = "yes"],
78 [AC_MSG_ERROR([[
79***
80*** You need postgresql / libpq to build this program.
81*** ]])])
82
83
84# check for libjansson (Jansson JSON library)
85jansson=0
86AC_MSG_CHECKING([for jansson])
87AC_ARG_WITH([jansson],
88 [AS_HELP_STRING([--with-jansson=PFX], [base of jansson installation])],
89 [AC_MSG_RESULT([given as $with_jansson])],
90 [AC_MSG_RESULT([not given])
91 with_jansson=yes])
92AS_CASE([$with_jansson],
93 [yes], [],
94 [no], [AC_MSG_ERROR([--with-jansson is required])],
95 [LDFLAGS="-L$with_jansson/lib $LDFLAGS"
96 CPPFLAGS="-I$with_jansson/include $CPPFLAGS"])
97AC_CHECK_LIB(jansson,json_pack,
98 [AC_CHECK_HEADER([jansson.h],[jansson=1])])
99AS_IF([test $jansson = 0],
100 [AC_MSG_ERROR([[
101***
102*** You need libjansson to build this program.
103*** ]])])
104
105# check for libgnurl
106LIBGNURL_CHECK_CONFIG([], [7.34.0], [gnurl=1], [gnurl=0])
107if test "$gnurl" = 1
108then
109 AM_CONDITIONAL(HAVE_LIBGNURL, true)
110 AC_DEFINE([HAVE_LIBGNURL],[1],[Have libgnurl])
111else
112 AM_CONDITIONAL(HAVE_LIBGNURL, false)
113fi
114AS_IF([test $gnurl = 0],
115 [AC_MSG_ERROR([[
116***
117*** You need libgnurl to build this program.
118*** ]])])
119
120# Require minimum libgcrypt version
121need_libgcrypt_version=1.6.1
122AC_DEFINE_UNQUOTED([NEED_LIBGCRYPT_VERSION], ["$need_libgcrypt_version"],
123 [minimum version of libgcrypt required])
124AM_PATH_LIBGCRYPT([$need_libgcrypt_version])
125
126# logging
127extra_logging=0
128AC_ARG_ENABLE([logging],
129 AS_HELP_STRING([--enable-logging@<:@=value@:>@],[Enable logging calls. Possible values: yes,no,verbose ('yes' is the default)]),
130 [AS_IF([test "x$enableval" = "xyes"], [],
131 [test "x$enableval" = "xno"], [AC_DEFINE([GNUNET_CULL_LOGGING],[],[Define to cull all logging calls])],
132 [test "x$enableval" = "xverbose"], [extra_logging=1]
133 [test "x$enableval" = "xveryverbose"], [extra_logging=2])
134 ], [])
135AC_DEFINE_UNQUOTED([GNUNET_EXTRA_LOGGING],[$extra_logging],[1 if extra logging is enabled, 2 for very verbose extra logging, 0 otherwise])
136
137# Checks for typedefs, structures, and compiler characteristics.
138AC_TYPE_PID_T
139AC_TYPE_SIZE_T
140AC_TYPE_UINT16_T
141AC_TYPE_UINT32_T
142AC_TYPE_UINT64_T
143AC_TYPE_INTMAX_T
144AC_TYPE_UINTMAX_T
145
146# Checks for library functions.
147AC_CHECK_FUNCS([strdup])
148
149AC_CONFIG_FILES([Makefile
150 doc/Makefile
151 src/Makefile
152 src/include/Makefile
153 src/util/Makefile
154 src/mint/Makefile
155 ])
156AC_OUTPUT
diff --git a/contrib/mint-template/README b/contrib/mint-template/README
new file mode 100644
index 000000000..fce5e0180
--- /dev/null
+++ b/contrib/mint-template/README
@@ -0,0 +1 @@
This directory is a template for the mint directory.
diff --git a/contrib/mint-template/config/mint-common.conf b/contrib/mint-template/config/mint-common.conf
new file mode 100644
index 000000000..becf42435
--- /dev/null
+++ b/contrib/mint-template/config/mint-common.conf
@@ -0,0 +1,6 @@
1[mint]
2db = postgres:///taler
3port = 4241
4master_pub = ...
5refresh_security_parameter = 3
6
diff --git a/contrib/mint-template/config/mint-keyup.conf b/contrib/mint-template/config/mint-keyup.conf
new file mode 100644
index 000000000..1542d1a63
--- /dev/null
+++ b/contrib/mint-template/config/mint-keyup.conf
@@ -0,0 +1,79 @@
1[mint_keys]
2
3# how long is one signkey valid?
4signkey_duration = 4 weeks
5
6# how long do we generate denomination and signing keys
7# ahead of time?
8lookahead_sign = 32 weeks 1 day
9
10# how long do we provide to clients denomination and signing keys
11# ahead of time?
12lookahead_provide = 4 weeks 1 day
13
14# what coin types do we have available?
15coin_types = default_eur_ct_10 default_eur_5 default_eur_10 default_eur_1000
16
17
18
19[mint_denom_duration_overlap]
20default_eur_ct_10 = 5 minutes
21default_eur_5 = 5 minutes
22default_eur_10 = 5 minutes
23default_eur_1000 = 5 minutes
24
25
26
27[mint_denom_value]
28default_eur_ct_10 = EUR:0.10
29default_eur_5 = EUR:5
30default_eur_10 = EUR:10
31default_eur_1000 = EUR:1000
32
33
34
35[mint_denom_duration_withdraw]
36default_eur_ct_10 = 7 days
37default_eur_5 = 7 days
38default_eur_10 = 7 days
39default_eur_1000 = 1 day
40
41
42
43[mint_denom_duration_spend]
44default_eur_ct_10 = 30 days
45default_eur_5 = 30 days
46default_eur_10 = 30 days
47default_eur_1000 = 30 day
48
49
50
51[mint_denom_fee_withdraw]
52default_eur_ct_10 = EUR:0.01
53default_eur_5 = EUR:0.01
54default_eur_10 = EUR:0.01
55default_eur_1000 = EUR:0.01
56
57
58[mint_denom_fee_deposit]
59default_eur_ct_10 = EUR:0.01
60default_eur_5 = EUR:0.01
61default_eur_10 = EUR:0.01
62default_eur_1000 = EUR:0.01
63
64
65
66[mint_denom_fee_refresh]
67default_eur_ct_10 = EUR:0.01
68default_eur_5 = EUR:0.01
69default_eur_10 = EUR:0.01
70default_eur_1000 = EUR:0.01
71
72
73
74[mint_denom_kappa]
75default_eur_ct_10 = 3
76default_eur_5 = 3
77default_eur_10 = 3
78default_eur_1000 = 5
79
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 000000000..8fd4c0911
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1,12 @@
1*.aux
2*.dvi
3*.log
4*.pdf
5*.out
6*.snm
7*.toc
8*.vrb
9*.nav
10*/auto
11api-sphinx/_build
12api-sphinx/*.html
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 000000000..4af5c665c
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,5 @@
1EXTRA_DIST = \
2 paper/taler.tex
3 paper/ref.bib \
4 paper/Makefile
5
diff --git a/doc/logos/ai/logotalerv2.ai b/doc/logos/ai/logotalerv2.ai
new file mode 100644
index 000000000..d474079d3
--- /dev/null
+++ b/doc/logos/ai/logotalerv2.ai
@@ -0,0 +1,3474 @@
1%PDF-1.5 %
21 0 obj <</Metadata 2 0 R/OCProperties<</D<</ON[5 0 R 248 0 R 489 0 R 730 0 R]/Order 731 0 R/RBGroups[]>>/OCGs[5 0 R 248 0 R 489 0 R 730 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <</Length 50398/Subtype/XML/Type/Metadata>>stream
3<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
4<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27 ">
5 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
6 <rdf:Description rdf:about=""
7 xmlns:dc="http://purl.org/dc/elements/1.1/">
8 <dc:format>application/pdf</dc:format>
9 <dc:title>
10 <rdf:Alt>
11 <rdf:li xml:lang="x-default">logotalerv2</rdf:li>
12 </rdf:Alt>
13 </dc:title>
14 </rdf:Description>
15 <rdf:Description rdf:about=""
16 xmlns:xmp="http://ns.adobe.com/xap/1.0/"
17 xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/">
18 <xmp:CreatorTool>Adobe Illustrator CS6 (Macintosh)</xmp:CreatorTool>
19 <xmp:CreateDate>2014-09-16T12:36:31+02:00</xmp:CreateDate>
20 <xmp:ModifyDate>2014-09-18T11:52:58+02:00</xmp:ModifyDate>
21 <xmp:MetadataDate>2014-09-18T11:52:58+02:00</xmp:MetadataDate>
22 <xmp:Thumbnails>
23 <rdf:Alt>
24 <rdf:li rdf:parseType="Resource">
25 <xmpGImg:width>256</xmpGImg:width>
26 <xmpGImg:height>192</xmpGImg:height>
27 <xmpGImg:format>JPEG</xmpGImg:format>
28 <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA&#xA;AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK&#xA;DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f&#xA;Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAwAEAAwER&#xA;AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA&#xA;AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB&#xA;UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE&#xA;1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ&#xA;qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy&#xA;obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp&#xA;0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo&#xA;+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7&#xA;FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F&#xA;XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqkHn&#xA;Lz35W8naZ+kdfvktYmqIIftTTMP2Yox8THffsO5AxV4lqP55fmf5v5jyLpUWi6QWMUer6gY2kZqh&#xA;fh9T9yp5OoYBX41BJAxViV/5Y826oyt5w87zrLKob6pPctDGrcI2YKJGSIhGnUHgvVZBtxrgVJrn&#xA;yn5NW48x2ei3VvNBc2trHpV5qFeSTGaJ7hlkeNaHgsg5UGx232CrI28syWOl2d95U8z3OixW0U1x&#xA;eXsdxcMsscdsvFOCSUaQTW8hZBGPhkBPZcKo22/Pf81vImox6Z5yt7fW4CCSwaNLkKkjRN+9gqnJ&#xA;WQ1WROXiRir3TyD+ank7zxal9Gu6XkahrjTpwI7mP5pU8l/ylJGKsuxV2KuxV2KuxV2KuxV2KuxV&#xA;2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KsG/Nb80tO8iaRGwj+va9fkxaRpaVLSyHbmwX4vT&#xA;UkVpuTsPZV4GnlTUNVv280/mTPLqGrXgKWNjs9vzV2UWy/Vnd+akf3SJxUtVyxDpir1Hy9+WWp30&#xA;cE2pXcuk2jxktp9okdvM3xzKpd46rCXhmpJHDRflsALVnej+QfJukqPqOk2yuNzO6CWUnxMj8nr9&#xA;OBKerFEiBFRVQbBQABiqUar5L8p6sjJqGk2txyFC5iUP9DqA4+g4q8y8/wD/ADj/ABan6l/ot3LN&#xA;d8afVL2QyVVRskczfEPYPX5jDavnnUNH8w+Vdb+s2rT6Zq1hJUMKxyxN/Qg/Ij2xQ+nPyQ/O2Dzr&#xA;anSNY4W/ma1QFwKKlyg29WMdiP21+kbdCr1rFXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FUv1zzDoWg&#xA;2Rvda1CDTrUbercyLGCfBeR+I+w3xV5Tr3/OVX5c2EjRaZDe6y42EsEQhh2/ypyj/cmKsXk/5zCI&#xA;ciLygzJ2ZtQCn7hbN+vFUXp//OX2ku6/pPyzc20f7TW1zHcEfIOlvX78VeieVPz2/LLzLIlva6st&#xA;leyEBbO/H1ZyT0Cs37pifBXJxVn4IIqOmKuxV2KuxVB6zq9ho2k3mrahJ6VlYwvcXEngkaljQdzt&#xA;sO5xV8iwebtY8yeYtS82eYtHt7zTdYSQaUblDJ9UW0bjAsRhKXCJzkEbvGU5SGvKoIwK96/LnyC9&#xA;rOfNGuxV128QejAzNILSGlFjDPVjIV/vHO5NfE1BKUg/5yM8t2d1odnrJjv7q/tri2t4LW0SeWP0&#xA;DcpLdMyQq1CYUarNtQUG+IV2p3+teTvyj05vKz3c11LJDbQSSQPdyxIUdhyQglalAnJkNK0pWmKq&#xA;HmHzHrHmLyL5R1WeyuYdRGs2T3KRwTKyD05BI7KAWSOp/b26VxVX/MLV/wAx7Tzl5XOjTXcOhNDE&#xA;0v1eD14pbgzFbiO7+AqqegV4s0qcdyvJgFxVOTq3nqf8z/qkd3c2/l+Kzs5fqz2iC1mnlE4uFS5a&#xA;HmxSkLfDLsdqeCqZfmb+W9l5v0kvGqxa5bIfqdz0D9zDJ4q3Y/snfxBVfId4mr+Wddi1KyL2Wpaf&#xA;PUA/C0csbUZHHzBVh9GFD7S/LTzzaedfKdprUAEcrjhdQVqY5V2dT9PT2wqyrFXYq7FXYq7FXYq7&#xA;FXYq7FXYq7FXin5w/wDORVj5Xnm0Dywseo+YEql1cNVre0b+U0/vJR/KDRe+9VxV87vZ+cfO2r/X&#xA;tWubjU76c0V5KudzXjGg+FV8FUAe2BXp/lr/AJxs1y5jSW+WOzQ0NJ2q9P8AUQNT6aY2rMoP+ca9&#xA;LVBz1MBu4W3qPvMgxtUJqf8AzjTCyH6nfQyt2EsbRfipkxtXmPm/8kNf0ZWkltWWEdJk+OL/AIJa&#xA;0+mmKrPIv5vefPy8uI7OZm1PQVID6bcsTwUf8s8hqYj7br7d8VfV/knzz5d856KmraHcerCTxnha&#xA;izQyUqY5UqeLD7j1BIwqn+KuxV5D/wA5Da2fqWg+U4b02V3r94GSQQrcKfqjI0aSozIoR53jqzVF&#xA;AdiK4qlfljyvb3HnOy0WNIRp+jKdTvzayh4Jpmcrb0jiWKCMScfW4JGo6dTVmBV6j5xn1C38pa1P&#xA;pt3Dp+oRWNw9pf3JVYLeVYmKTSlw6hI2+JiykUG4wJfJDfmr+eXJkk/MLRpFBoSs+lUPyrBhQqR/&#xA;mr+cITg/n3S+P8q3Ojgfcbc4qxq5/wCcg/zohuJ7eLzOJIonaPnHa6e6MVNCVZYOLLtsw6jGlT2y&#xA;/OT83b60SVfPNjGDQqlzJpULU7Vje2qp9q40q9/zW/O4kFPP+j1HQtPpJp/yQxV7Z+QPmf8AMbWL&#xA;W4bzXqVtrMTuz2moWrQMhjACFAbdY0PF1bt9OApYt/zkh5PitdYt9bt0CwauhjuaDYXMIFG8P3kf&#xA;/EScIQlP/OLfmyXTfNN75amaltqA9eFSdhLH8LU/1gR92FX1ZirsVdirsVdirsVdirsVdirsVeKf&#xA;85FfnDN5XsF8saBP6fmHUY+VxcofitLZqiqntLJSi9wPi68Tirwz8svy01LzRqaRxoSCec0z14ot&#xA;d3c/51wK+tPKPkbQfK9msNhCGueNJrxwPUc96fyr/kjAlkOKuxV2KrXjSRGSRQ6MKMrCoIPYg4q8&#xA;j/M/8mLDULSbUNFgCyqC01ko2I7mL3/yfu8MNq8D8seZvMH5Z+bI9VsKyWzER31kxIjuIa7o3+UO&#xA;qN2PtUFQ+0vLvmDS/MOh2Wt6XL61hfRiWB+hodirDsysCrDsRhVMcVfOH51W0uqfnbo6TQxT6ZYW&#xA;AhZJ51hj+sSpcTDkxDsmwQ1VSRSo3xVn/wCTmnRxL5hvPTWKZtQ+pFEkkmASyhSJR6kxMjUNd23y&#xA;JS9BvLO1vbSezu4UuLS5jaG4t5VDxyRyAq6OrAhlZTQg4q82uf8AnHL8rJ53l/REMfMk8I4o1UV7&#xA;ABaAY2qn/wBC2flZ/wBWuP8A4CP/AJpxtXyZ5g8tW9p5m8w2donG1s9UvraBadI4bmSNRt4Bckh7&#xA;f+Rn5KeQ/Mnke01LVbFJrqRFLuVQmpHuDgJS9E/6Fs/Kz/q1x/8AAR/804LVlPk78t/LXlEt+hoj&#xA;CjKV9IEBACeRooAA3xVJPz809Lr8tr2cir6fNb3Mfz9UQsf+AmbEK+YfId6+mfmdo1yhp/pQU08H&#xA;BX+OSQ+60bkgbxFcVbxV2KuxV2KuxV2KuxV2KoHXdZstE0W+1i+bhaafBJcznvxiUsQK9zSgHjir&#xA;4WW61Xzt5yu9YvgZLzUrgysgq3EMaRxL34otFX2GBX2T5A8n2vlfy/BZIi/W5AHvZR1aSn2a+C9B&#xA;9/fAljmqf85E/k7pWqXmlX+vmK/0+eS1u4RZ3z8JoXMci8kgZTRlIqCRjSqSf85J/ku/2Nfkb5af&#xA;qJ/7F8aVbL/zkv8AkpC3GXzC8bHcB7DUVNPpt8aVdH/zkn+TEq84tekkUdWXT9RI+8W+NKtb/nJb&#xA;8lU+15gdfnYaiP8AsXxpU88mfnF+XHnTVZdK8s6v9fv4YGupYfq11DSFHSNm5TxRr9qRRStd8Vea&#xA;/n5+XsCE6vaRhYLsn1VA2Saldv8AW6/fhCEu/wCcVvOk1pq2oeSL2T9zOGvNMVj9mWPaeNf9dKPT&#xA;/JPjhV9L4q+WP+ciPNHmLQPzHnstMuWs49RtrO8e4iLLKREJYAlQ3EpUE/ZrXvir1H/nHy5a58j3&#xA;E8knq3EmoTvO9KEu6RuTtQb8siUvTcVdirsVfIFzoBvNb8z3AWtdc1YVp4X0wySHs3/ONIp+W9kP&#xA;BV/VkSl6zirsVYH+eU0cX5W64XNOa26KPFmuYgMQr5M0NTJ570lV3P1qI0Hsa4UPvS3/ALiP/VH6&#xA;sKqmKuxV2KuxV2KuxV2KuxV4/wD85Ta5Jp/5YGxiYq+sXsFo9OvppyuG3+cIB+eKvK/+cb/Lkd95&#xA;nhuZUqlmrXRB8Uoqfc7A4Cr6rwJeJ+YPy0/Me817Uruz8q/lvcWtxdTy29xqFhdPeSRvIzI9y6xl&#xA;WmZTWQjq1cVQI/K381R08o/lcP8At3Xn/VPFXhf54+WvMemedbSy1zT9B026OmxTpbeWYZbezKNP&#xA;Mgd0lCsZiUIY/wAoXwwhDLvyK8l+edY8q38+iaJ5N1O0g1GSBp/M1rcXF4riCFzHG0SsohpIGA/m&#xA;LHviVein8rPzUPXyh+Vp/wC3def9U8CWcflb5J17QrrULvzBoPlLS7uRI4rG48rWklvI0ZLNOlw8&#xA;qKxUssZUL4GvbFWT+dtJTVfK2o2rLyb0mli8ecY5inzpTFXyFpF+3ln80NE1VTwS3voTMen7p39O&#xA;YfTG7DCh9xYVfNX/ADl55fdLry95jjUmMiXT7l+wIPqwj6f3n3Yqjv8AnGDzJGy6hokjgNMi3Vup&#xA;/mj+CQD3IKn6MBV79gS7FXYq+bNI1Cyhl80RSgeodd1ihPvfTZJDO/8AnGw1/Lm0I6UXIlL1jFXY&#xA;q8k/P/UUurfQvKUcnGXVLsXN2RU+naWwPN3ChiFDMGrQ/ZOxxCvKtHn0rzd+dOnNokFv+jrMoxub&#xA;aORPUbioPISpEwChOKjj798kh9cgUAHhirsVdirsVdirsVdirsVdir54/wCcwZWGl+V4duD3Ny58&#xA;aokYH/EzgVd/zi/Egj1CTbkIIwPGhap/ViVe+YEuxV2Kvl3/AJyP003v5s2wArw0K0/G8vP6YQhn&#xA;n/OLVsbbybr8J2467L+NjZnAUvZsVdirTqrqVbdWBBHscVfDP5jLw1Esp4sCSCNiCMKH3hhViP5r&#xA;eSo/OXkbUtFoPrTJ61g5/ZuIvij37An4T7E4q+O/InmTU/KvmaGfi0N9p85WWB6qQyEpJE/hUVU4&#xA;Ffa/lzzBp3mDRrbVtPfnb3C1p+0jD7SNToynY4EplirsVfFesa41r5l80wBqcdb1Xb53spySHvX/&#xA;ADjQa/lrZHxRf1ZEpetYqhdT1Ow0vT7jUdQmW3srVGlnmfYKqip/sHfFXzZf+bbrULrXPzIvY2ij&#xA;9P6tolsJza3cVpG4XnCxVl+PmVdlaodiFr9lihkv/OM3lK9kN95t1RSbu9laQOVCVZ6liFUBQKno&#xA;NsKvoHFXYq7FXYq7FXYq7FXYq7FXhv8Azlvpkk/kbS9RQEix1FVlA6BJ4nXkf9mqj6cVY3/zjBqs&#xA;a6jcWTGhnt24DxaNgaf8DywFX0bgS7FXYq8L/MzTEv8A84nRv2fL9kRX/mMvcIQyb8h7VbXTfNMC&#xA;9E11x/3LrLAUvTsVdiqF1W8Wy0y7u2NBbwvJX/VUnFXxVrlodc856dpMY5NfXcNsAP8Ai6VU7fPC&#xA;h90YVdir5s/5yN/J6dbp/Ovl6DkW31e1jG5Kj+/UeNPtAfPFWB/lT+beo+Vb4UJuLCagu7Jmor9g&#xA;6nfi48foOBX1V5V85+XvNFkLrSLpZSADNbNRZoiezx1qPn0PY4Ep5ir89vPmoGHz95ujrSmtal+N&#xA;3JkkPq7/AJxl/wDJZ2H/ABjT9WRKXo3mLzPoPlywN9rN4lpBuEDGryN/JHGKu7eyjFXhfm384dSu&#xA;9WjvdS0s23lGGUxR2zshuw6ShTePEGYMEZeHFkKbleXMgg0hiei2Oqfmhr1tpljYwWXlzTJBxaKN&#xA;k9VY5JPTkb1GdwAszcU5bVpvQYVfV+haLZaLpcGn2aBIYVoABSp7nFUfirsVdirsVdirsVdirsVd&#xA;irGfzL8qDzZ5F1nQQB693bk2hbYC4iIkhJPYeoi19sVfIH5VeZ7ny55ntpnVkltpaSxNs23wSIQe&#xA;hpUYFfa1nd295aQ3ds4kt50WSJx0KsKg4Eq2KuxV8+/nDqx0783uYbiX0CyH3Xl7hCGW/wDOPV39&#xA;b0PzNcVrz119/lp9kMBS9VxV2KvOvzq81Q6V5cOno4Fze7uK7iJTX/hmFPvxCvGP+cevLcvmT80G&#xA;1yWMvp+go1wzn7JnkBjgX5/akH+rkkPrXFXYqtkjSRGjkUMjCjKdwQcVfO/5tf8AOOHrzz655RKw&#xA;zNWSfTqURm7lOI+EnFXhyal5k8samEu0uNPv7dvgkBaKRSO6OtPwOBXo+hf85IedLKNY5riDUEUB&#xA;R9ci+IAf5cRiJPu1caViXmz8mb/Wdb1rVLTUTNquqSpqcVosMaQ89Rmjkki5md3AiF4vxOi1ofnh&#xA;VnXkC9/MLy75cPlpNWsNHktrVp7doYxeXEsUUpheXYzIIlEcjM6qSApNOmClSjVLzQtN1S6vNdvp&#xA;vMfmO2aezkiuf38sV1G7xBPq0p+xGQsgZiY2WqcQ1DhVNdI8n+evzNv63iPpPlzkGS1ZnkJVT8Hq&#xA;ysAZWChV7A8QTVt8VfRXk7yZo/lbTFstPjANB6ktAGYgUqaYqn+KuxV2KuxV2KuxV2KuxV2KuxV2&#xA;KvlP/nI/8tJ/L3mI+ddJiP6J1SUHUFQbQXjdXP8Akzdf9aviMVZH+Rv5uWsdtHoerS8bZm/0adjt&#xA;E7dVb/IY717H57AhXv4IIqNwehwJbxV8o/8AOT9+bT82LMg056Fa/heXeEIehf8AOJ9wbjyLrkx/&#xA;a12b8LK0GApe2YqlPmXzLpnl7TXvr5wAKiKIH4pG/lX+J7Yq+S/zB836x5u8w/VrVWur++lWGC2i&#xA;BJJY8UjQYUPp/wDKP8vYPIvk630tuL6lOfrOqzruGuHABVT/ACxgBF+Ve5wqzTFXYq7FXYqx/wAy&#xA;+Q/K/mOFo9Vskm5dX6HFXlet/wDOKnla4dn027ltSTUJ1A/HFUJcfkF56L1j81XI+wDIrBHPpMjR&#xA;lnWjMUMScSTtQYquh/5xnvb2NINb8w3d3bJIZVt5JHdA7dWVGYqCfGmKs58rfkX5H0BklW3NzOm/&#xA;OQ7V8aDFXoMMEMEaxwoEjUUVRsAMVX4q7FXYq7FXYq7FXYq7FXYq7FXYq7FUNqmmafqunXGnajAl&#xA;zY3cbRXEEgqrowoQcVfJH5ofkt5i/L+9k1jRBLqHlgkt6yjlLagn7FwB+yO0nTxoeoVOPy3/AD9v&#xA;9Lhjsb7/AEuyWgWKRqOg/wCK3329jt8saV7lon5peS9WjUx362srdYrn93T/AGZ+D/hsFJfL/wDz&#xA;l5qVtJ+Z+mTW0yTRHRIB6kbB1qLu62qtcIQ9G/5xI8w6NYflnqz6hfQ2zNrc7BJHVWK/VLUVC/aP&#xA;TsMSlnPmr89PLumxOmlj63OAaTSVSIe9DR2/DBSvA/MfnjzT531tLKwWbUdRum9OCGIV28FUbKo6&#xA;k9B1OFD3j8lfyPg8nKNc1wrd+aJ0K7UeK0VuqxHvIw2d/oG1SxV63irsVdirsVUJr2CGT025s9Ax&#xA;WOOSQgEkAngrUrQ4qs/Sdt/JP/0jz/8ANGKu/Sdt/JP/ANI8/wDzRirv0nbfyT/9I8//ADRirv0n&#xA;bfyT/wDSPP8A80Yq79J238k//SPP/wA0Yq79J238k/8A0jz/APNGKuXUrUsqkSpyIUF4ZUWrGgHJ&#xA;lA3OKorFXYq7FXYq7FXYq7FXYq7FXYq7FXYq0yqylWAKkUIO4IOKvJPPX/ONXknzDLJe6QzeXtSc&#xA;lma2UPbOx7tbkqF/55svyOKvJtU/5x8/ODRXY6b9X1i3WpRradY34jxSf0t/ZScVSZ/Kf5z2zenJ&#xA;5b1Bm8Y4mkHh9pOQxVEWv5c/nfqhCxaDcQq1KtcPFbgA+Pquh/DArMPLv/OLPmS/kWbzbrUdrAd2&#xA;tbGs0pHgZHCxofkr4Ve5+TPy88o+TbM22g2CW7uAJ7pv3lxLT/fkrfERXfiPhHYYqyPFXYqw/wA2&#xA;+b/N2nawmmeWvKx8xOlsLu9kN9FYrEru6RIvqo/N3MT+A264qi/IXnzS/OOlTXVrDNY31jO9nqul&#xA;XahLm0uY/tRyKPvVhsR71AVZLiqFj/46tx/xgg/4nLiqKxVak0Lu6I6s8dBIoIJUncVHbFWoZ4J0&#xA;LwSLKgZ4yyMGAeNijrUd1dSpHYimKvKfLsn5uyfm9rUd9c6HHp0dlpb3sMUd7K4s2nvzAsBaSNRO&#xA;SriV2Xj9khdiMVes4q87/wCcgLu6s/yp1S7tJWguYLrS5IZoyVZWXVLYggjFWdan/vMn/Ge3/wCT&#xA;6YqisVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVSa1/5TLVP+2dp/8Ayfvc&#xA;VYNp/o6L/wA5D69DGyw2et+WrfV9QJPFBPZXRtfUYn4R+6bc4qyny/L5f1LzJe69Za8uqyXcEcNj&#xA;aRTAwQWsdC7RRqxDmWU8mlpuOKjYbqovzJc3Nrpuv3NqxS6g0tpIHUVIkRZ2Ugb7gjFWC+WPLOkL&#xA;+T2j+ZrSD6v5lXQItSbWYdr2a6lsfUlaafeSb1HY8lcnt3Aoqhvy68s69ceSfJt3Y2+kWVs1vpOo&#xA;T6ohl/SMjMsM95zfgFZ7kmRHq2/I4qxfyP5Y0ZP+cfdS85mASeaLSLW9Ts9YkJe6gmsru5kjEMrV&#xA;eNGeHk6qaMS3IGpxVGfn3LLFp35lNG7IzaR5VRipIJWTWLxHU07MrEEdxirNYvJHkx/zCuNFbRLC&#xA;30i30q2vbfSorWGO2uriW4uIppZokVUmNskUQTmDw9UkbnFXjXmcJDB+demW11Jc6fpt35VtbCN5&#xA;GkEEYv8AmbeMkmixSOyBe1KYq+o9T/3mT/jPb/8AJ9MVSyTzLbWms6zFqd/p9ppel2tncPI83CWH&#xA;6w06u90ZOMUcbekoj3rs1e2KrtM88eStVjuZdL1/Tb+KzjMt5JbXcEywxjq8rI7BF92xVQ8rfoi5&#xA;vtU1ey1j9LS6m8cnESco7e3RfThjiiqeCHiz8qfGxJ6UoqyLFXYq7FXYq7FXYq7FXYq7FXYq7FXY&#xA;q7FXYq7FXYq7FXYqxK+80+WtE87Xses6raaY1zplnJB9cnjgDrDPd+oVMjLXj6i1+eKvG/OX1nzh&#xA;5f8AzP8AzDsY5W0ltJj0Ly5NxZWuLO1l9e8uFBofSeUnie4BxV69baZPc67oV/c+Zra6skkmvNF0&#xA;63t4ofVja2kiokiyOzxxxXHLYUrxOKsmmE0d5LKLdriOaKOMhCmxRnJ5B2TrzxVIdM8m+XdLnhks&#xA;tFuo47Zme0s2umktIGcEMYLSS5a3hNHYD00FATTqcVWaZ5H8s6ZcQzWOiXcUdrIZrSy+ts9lBIa/&#xA;HBZvctbRMORoUjFKmnXFUVHonl+w8tXOgLorW/l+4W5S4s2eERFL53edatNsJHmbYHatBTFUFN5P&#xA;8o6pBrX1jRptQh8wmIas0t164lFu5eFFZrlvSWJ2LIkXEKegxVNNa0ix1r0DfaZd+tbFjbXNtcfV&#xA;LiPnQOEntriKVVfiOShqN3xVKB+XXkoWd7aR+WpIoNS+qfXhFMI2lawnNzbO7pcK5dJmLl68mP2i&#xA;cVZBHBKLWGyitrhI45I29W5mEzUSUSHlI0ssrdNq1+7FXnt75aHmT8wfPuleuluzWvle5jlkiFxH&#xA;6lldXV0iyQlk9RGaEK68hUE74qx7849S8y2Ply/8uX+oadqVpNZpqM62Fm9nJbJYavpqyeqpuboG&#xA;N4bmQtVRQIeorir0rSNJvF822+oal5ih1O7TT7hLOxht44P9HuZrd2mJWSRnUNAqqem5xVluKuxV&#xA;2KuxV2KuxV2KuxV2KuxV2KuxVRu722tER7h+IkdY4wAWZnboFVQWO1SdtgCTsDiqsCCAQag7gjFX&#xA;Yq7FXYq7FUq1ryn5W114X1zRrHVXt6/V2vbaG4MddzwMqtxrTtiqZRwQxwrBHGqQooRIlAChQKBQ&#xA;o2pTtiqX6T5W8saPPNcaTpFlp1xcbTzWlvFA8gry+No1UtvvvirH9W8p+crvzwNXtPMUllov1L6u&#xA;lpGsbNDNzBLLHLFLHJ6ndiVZaUFQdlUd/hrzV/1N97/0i6f/ANk+Ku/w15q/6m+9/wCkXT/+yfFV&#xA;ax0nWLC7S61DV7jWYEVgsUkFuhidqD1VFvHGzHjVe/XFW7/S9Y1G8Nzp+rXOjwcFQqkEDGVlLEsy&#xA;3McjLSoA6V+VMVUP8Neav+pvvf8ApF0//snxV3+GvNX/AFN97/0i6f8A9k+KpfaeTvN8Pniy1qfz&#xA;NPdaVb2kkNzaSLEn1h3aqK0MUUcarH9r1Klz9nYdVWU3ei6PeC6F1YwTi+jSG99SJG9aKMsUjlqP&#xA;jRS7UVttz44qgdH8k+TNFeZ9G0DTtMe5T0rhrO0ggMkZ34OY0XkvscVROj+W/LuiLKujaXaaYs5D&#xA;TCzgitw5HQt6aryO/fFUxxV2KuxV2KuxV2KuxV2KuxV2KuxV2KsV8+NcTLpemx29u63V0JTc3QnZ&#xA;I3tB9YjVUtyjyPI0dOHMBl5V5CqlVk1q0z20LzKiTMimRI2LorEbhXITkoPQ8RXwxVUxV2KuxV2K&#xA;vmLVf+c0Y9P1S8sD5aMhtJ5IDIJwAxjcpWlDStMVQv8A0O/F/wBSw3/SQP8AmnFXf9Dvxf8AUsN/&#xA;0kD/AJpxV3/Q78X/AFLDf9JA/wCacVd/0O/F/wBSw3/SQP8AmnFXf9Dvxf8AUsN/0kD/AJpxV3/Q&#xA;78X/AFLDf9JA/wCacVd/0O/F/wBSw3/SQP8AmnFXf9Dvxf8AUsN/0kD/AJpxV3/Q78X/AFLDf9JA&#xA;/wCacVd/0O/F/wBSw3/SQP8AmnFXf9Dvxf8AUsN/0kD/AJpxV3/Q78X/AFLDf9JA/wCacVd/0O/F&#xA;/wBSw3/SQP8AmnFXpf5I/n0v5n6hqloulHThpsMcpYyepz9VitOgpTjir1zFXYq7FXYq7FXYq7FX&#xA;Yq7FXYq7FWHefdU1OzlRYbu5s7RLG9ulFmsXr3d1bhGhtI3ljnCsylmVVTk9NtlYFVkmjG7OnRC7&#xA;m+sTKXX6xRVMqK5VJCEotXQBjxFPDbFUbirsVdirsVfmP5gsry986apaWUElzdz6hcJBbwo0kjsZ&#xA;moqIoLMT4DFULrXlvzFoUqQ63pd5pc0gJjjvYJbdmA6kCVVJxVLcVRmlKpvPiVXCxTOFYBhySF2W&#xA;oNQaEYqrfX5v99wf9I8H/NGKu+vzf77g/wCkeD/mjFXfX5v99wf9I8H/ADRirOfy1/LbzT55e+ls&#xA;LOA2Flb3TNccLGKt1HayS28I9bhUPKqK5GyqakjrirFNatdV0XVbnStRhtEvbR/TuEiSznVWoCR6&#xA;kIkjald6NsduuKoH6/N/vuD/AKR4P+aMVZR590AeWrjREgeKePV9F07V/jtrfkj3kAeSPaMVAkDc&#xA;fanzxViGqKq3nwqFDRwuQoCjk8Ss1ANhucVQmKuxV9Nf84P/APHf81f8wlt/ycfFX11irsVdirsV&#xA;dirsVdirsVdirsVdirsVdirsVdirsVdir84LK8u7H8ytZvbOZ7e7tTrU1vPGSrxyR21yyOrDcFWF&#xA;QcVZd+VXmLV/PdnrP5beZLubVotTsrm88vSXbmaW11SziaeNopJCXVZERw6g7/SaqvMdF0/SLm21&#xA;O51O++qLZ2xezgRQ8tzcswSKJQSOK7l3fso8SMVQ+k/71t/xguP+TD4qzGTyx5Z0fyh5d13Wlvb6&#xA;bzGbqSGCzmitlt4LSc2xLNJDcmV3dWIHwgDxriqbw/lrpx8q2er6bbXnmKXWLu/isDC6Waw2dg8U&#xA;fqyq6ykyymcUXlRaH7WKo26/LjyXoXkrV9e15r24ntdVsLK1srWWKOX/AEnTjeSW8kxSaNXQy8Xf&#xA;0m3joFHLZVB+XNF07TvMP1vS3mbTNZ8p67f2aXJVpowNOv7aSOR0CK5Sa2cBgoqKGg6YqiPN35ce&#xA;T9J/MC48iWQvxd2kUVxda7c3ULW6QrYrf3U31NLVXpHDzovr9uuKobyl5F8jebrDzNc6ZNqOny+W&#xA;tIvdU+r3UkE5u1t4mMTq0cUQhpLx5xnnsdn2xVT/ADt/3p8lf+Afon/Jg4qwZtI1LVNRkhsIGnkt&#xA;7EXc4Wg4QW1oJppCSQKKiE+/Qb4qk+Kproun6Rc22p3Op331RbO2L2cCKHlublmCRRKCRxXcu79l&#xA;HiRir6F/5wf/AOO/5q/5hLb/AJOPir66xV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV+b&#xA;Q/5T/wAwf6muf9Ql1irIf+cck+rfmUnmCXaw8tafqGq38m1FijtZIxWu28kqjFUyu/IXlWzPlSwu&#xA;ZNMtNN1DTdN1HWtRvrtodQ5ahGJZngTmF4QJJSNfTIYr8XI4q8q0n/etv+MFx/yYfFWZHzN5Y1jy&#xA;foGg6617YzeXDdJbXFjBFdLPBdz/AFgq6yzW3pukjNRhyBB6bbqr280eUtW8oWHlrVhf6bHol5eX&#xA;Gk3drHDfM0F8Yy8NwjyWI5oYVIkVt9/gGKqN95x0Q/l7e+UNPtbmKN9dh1azmndJD6EdnLbMspUJ&#xA;8ZZlYcVp1HbdVFaL528v21haG7S7F7pnlzUtCtIoo43imn1KXUCZJJGkRo0jTUF6IxYg9OuKqvm3&#xA;8z7XVvzVuPOtpZP9Uu4Ybe606cgF4W05LC8i5py2kT1FVvAgkdsVRflHz15F8oad5mtdNh1HUZ/M&#xA;uk3mlm6uY4bc2i3ELBEVI5phNWUpzkJT4V2SppiqR/mD5q0fzImgTWbXKXGlaNp2kSwTQxolbK3C&#xA;SSLKs0hblJXjVF+H3xVvyTo+m6pruspfwidLTyzqN5ArEgLPb6UzxPsRujbj3xVkI8t6HfafpNh5&#xA;W8v+XtUvbyxsl+uXmtumoS6hPbxmeNbL6/aqrrcu8aJ6R5UHWuKq135C8q2Z8qWFzJplppuoabpu&#xA;o61qN9dtDqHLUIxLM8CcwvCBJKRr6ZDFfi5HFWcf84P/APHf81f8wlt/ycfFX11irsVdirsVdirs&#xA;VdirsVdirsVdirsVdirsVdirsVdir81zrlvof5lX2p3NiupWkN/eJdae7tEs8MzSRSxmRasvJHIq&#xA;OmKpp5g/M/SW8uXflvyZ5bj8q6VqjI+st9alv7u6ER5RxNcSqhSJTvwVdz361VQd7580bVrLSjru&#xA;htfavotjFptncx3ZhtpYLYFbf61biJ3kManjWOaPkAK4ql35eeXbXzH5z0rRbrVo9EgvZhG2pSkg&#xA;JsTRSKDm/wBlKkCp64qyfU/JENrqV3aj8xtIhEE0kQhuJtXEycHK8ZKWAHMUo1O+KoX/AAjF/wCX&#xA;L0P/AJHax/2Q4q7/AAjF/wCXL0P/AJHax/2Q4qkiXVxJrf6HN2YYjcG1OpNNc0RQ/D13ozfAv22o&#xA;nTFU7/wjF/5cvQ/+R2sf9kOKu/wjF/5cvQ/+R2sf9kOKpl5c/L+31PXtP0+T8xdKnju50heK0m1U&#xA;zkO1D6YksQnIdfiIHiR1xVIDqUfkbzj5js7W7h8wwyWmpaMNRhdljlW9t3t/XViGqU51I3BIoGpR&#xA;sVb8mebPJHlu+07V5PL9/qOuaZNFd287anHDa/WIHEkbfV1s2k4q6iqmbf2xV17580bVrLSjruht&#xA;favotjFptncx3ZhtpYLYFbf61biJ3kManjWOaPkAK4q9m/5wf/47/mr/AJhLb/k4+KvrrFXYq7FX&#xA;Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX55+Zfya/NafzHqs8PlPVJIZby4eKRbWQqytKxUg06&#xA;EYqln/KlPzc/6lDVf+kWX+mKu/5Up+bn/Uoar/0iy/0xV3/KlPzc/wCpQ1X/AKRZf6Yq7/lSn5uf&#xA;9Shqv/SLL/TFXf8AKlPzc/6lDVf+kWX+mKu/5Up+bn/Uoar/ANIsv9MVRB/KL85jD6R8qatxoFr9&#xA;UfkVHRC/HkV/ya0xVD/8qU/Nz/qUNV/6RZf6Yq7/AJUp+bn/AFKGq/8ASLL/AExV3/KlPzc/6lDV&#xA;f+kWX+mKu/5Up+bn/Uoar/0iy/0xV3/KlPzc/wCpQ1X/AKRZf6Yq7/lSn5uf9Shqv/SLL/TFX0F/&#xA;ziF5E85eWda8xy+YNFvNKiuba3SB7uFog7LI5YLyArSuKvp3FXYq7FXYq7FXYq7FXYq7FXYq7FXY&#xA;q7FXYq7FXYq7FX//2Q==</xmpGImg:image>
29 </rdf:li>
30 </rdf:Alt>
31 </xmp:Thumbnails>
32 </rdf:Description>
33 <rdf:Description rdf:about=""
34 xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
35 xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#"
36 xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#">
37 <xmpMM:OriginalDocumentID>uuid:AF0436EA903B11DB90DFD5CCDBF73423</xmpMM:OriginalDocumentID>
38 <xmpMM:DocumentID>xmp.did:0180117407206811822AA5DFA83DBEE8</xmpMM:DocumentID>
39 <xmpMM:InstanceID>uuid:a78d6ca4-ee25-5f4f-9857-efe87b47a9ff</xmpMM:InstanceID>
40 <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass>
41 <xmpMM:DerivedFrom rdf:parseType="Resource">
42 <stRef:instanceID>uuid:d0c80ddf-8d24-9c4a-b5a2-f5403c78eac7</stRef:instanceID>
43 <stRef:documentID>xmp.did:F87F11740720681183D1ECDDA24ACDE7</stRef:documentID>
44 <stRef:originalDocumentID>uuid:AF0436EA903B11DB90DFD5CCDBF73423</stRef:originalDocumentID>
45 <stRef:renditionClass>proof:pdf</stRef:renditionClass>
46 </xmpMM:DerivedFrom>
47 <xmpMM:History>
48 <rdf:Seq>
49 <rdf:li rdf:parseType="Resource">
50 <stEvt:action>saved</stEvt:action>
51 <stEvt:instanceID>xmp.iid:0380117407206811822AABA902D116C4</stEvt:instanceID>
52 <stEvt:when>2014-09-11T14:30:24+02:00</stEvt:when>
53 <stEvt:softwareAgent>Adobe Illustrator CS6 (Macintosh)</stEvt:softwareAgent>
54 <stEvt:changed>/</stEvt:changed>
55 </rdf:li>
56 <rdf:li rdf:parseType="Resource">
57 <stEvt:action>saved</stEvt:action>
58 <stEvt:instanceID>xmp.iid:0180117407206811822AA5DFA83DBEE8</stEvt:instanceID>
59 <stEvt:when>2014-09-16T12:36:28+02:00</stEvt:when>
60 <stEvt:softwareAgent>Adobe Illustrator CS6 (Macintosh)</stEvt:softwareAgent>
61 <stEvt:changed>/</stEvt:changed>
62 </rdf:li>
63 </rdf:Seq>
64 </xmpMM:History>
65 </rdf:Description>
66 <rdf:Description rdf:about=""
67 xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/">
68 <illustrator:StartupProfile>Video</illustrator:StartupProfile>
69 <illustrator:Type>Document</illustrator:Type>
70 </rdf:Description>
71 <rdf:Description rdf:about=""
72 xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/"
73 xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#"
74 xmlns:stFnt="http://ns.adobe.com/xap/1.0/sType/Font#"
75 xmlns:xmpG="http://ns.adobe.com/xap/1.0/g/">
76 <xmpTPg:NPages>1</xmpTPg:NPages>
77 <xmpTPg:HasVisibleTransparency>True</xmpTPg:HasVisibleTransparency>
78 <xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint>
79 <xmpTPg:MaxPageSize rdf:parseType="Resource">
80 <stDim:w>1920.000000</stDim:w>
81 <stDim:h>1080.000000</stDim:h>
82 <stDim:unit>Pixels</stDim:unit>
83 </xmpTPg:MaxPageSize>
84 <xmpTPg:Fonts>
85 <rdf:Bag>
86 <rdf:li rdf:parseType="Resource">
87 <stFnt:fontName>OldNewspaperTypes</stFnt:fontName>
88 <stFnt:fontFamily>OldNewspaperTypes</stFnt:fontFamily>
89 <stFnt:fontFace>Regular</stFnt:fontFace>
90 <stFnt:fontType>TrueType</stFnt:fontType>
91 <stFnt:versionString>1.0 2007-02-14</stFnt:versionString>
92 <stFnt:composite>False</stFnt:composite>
93 <stFnt:fontFileName>OldNewspaperTypes.ttf</stFnt:fontFileName>
94 </rdf:li>
95 <rdf:li rdf:parseType="Resource">
96 <stFnt:fontName>Perpetua</stFnt:fontName>
97 <stFnt:fontFamily>Perpetua</stFnt:fontFamily>
98 <stFnt:fontFace>Regular</stFnt:fontFace>
99 <stFnt:fontType>Open Type</stFnt:fontType>
100 <stFnt:versionString>Version 1.76</stFnt:versionString>
101 <stFnt:composite>False</stFnt:composite>
102 <stFnt:fontFileName>Perpetua.ttf</stFnt:fontFileName>
103 </rdf:li>
104 <rdf:li rdf:parseType="Resource">
105 <stFnt:fontName>SmothBight</stFnt:fontName>
106 <stFnt:fontFamily>Smoth Bight</stFnt:fontFamily>
107 <stFnt:fontFace>Regular</stFnt:fontFace>
108 <stFnt:fontType>Open Type</stFnt:fontType>
109 <stFnt:versionString>Version 1.00 (Kustren)</stFnt:versionString>
110 <stFnt:composite>False</stFnt:composite>
111 <stFnt:fontFileName>Smoth-Bight - Por Kustren.otf</stFnt:fontFileName>
112 </rdf:li>
113 </rdf:Bag>
114 </xmpTPg:Fonts>
115 <xmpTPg:PlateNames>
116 <rdf:Seq>
117 <rdf:li>Cyan</rdf:li>
118 <rdf:li>Magenta</rdf:li>
119 <rdf:li>Yellow</rdf:li>
120 <rdf:li>Black</rdf:li>
121 </rdf:Seq>
122 </xmpTPg:PlateNames>
123 <xmpTPg:SwatchGroups>
124 <rdf:Seq>
125 <rdf:li rdf:parseType="Resource">
126 <xmpG:groupName>Groupe de nuances par défaut</xmpG:groupName>
127 <xmpG:groupType>0</xmpG:groupType>
128 <xmpG:Colorants>
129 <rdf:Seq>
130 <rdf:li rdf:parseType="Resource">
131 <xmpG:swatchName>Blanc</xmpG:swatchName>
132 <xmpG:mode>RGB</xmpG:mode>
133 <xmpG:type>PROCESS</xmpG:type>
134 <xmpG:red>255</xmpG:red>
135 <xmpG:green>255</xmpG:green>
136 <xmpG:blue>255</xmpG:blue>
137 </rdf:li>
138 <rdf:li rdf:parseType="Resource">
139 <xmpG:swatchName>Noir</xmpG:swatchName>
140 <xmpG:mode>RGB</xmpG:mode>
141 <xmpG:type>PROCESS</xmpG:type>
142 <xmpG:red>0</xmpG:red>
143 <xmpG:green>0</xmpG:green>
144 <xmpG:blue>0</xmpG:blue>
145 </rdf:li>
146 <rdf:li rdf:parseType="Resource">
147 <xmpG:swatchName>Rouge RVB</xmpG:swatchName>
148 <xmpG:mode>RGB</xmpG:mode>
149 <xmpG:type>PROCESS</xmpG:type>
150 <xmpG:red>255</xmpG:red>
151 <xmpG:green>0</xmpG:green>
152 <xmpG:blue>0</xmpG:blue>
153 </rdf:li>
154 <rdf:li rdf:parseType="Resource">
155 <xmpG:swatchName>Jaune RVB</xmpG:swatchName>
156 <xmpG:mode>RGB</xmpG:mode>
157 <xmpG:type>PROCESS</xmpG:type>
158 <xmpG:red>255</xmpG:red>
159 <xmpG:green>255</xmpG:green>
160 <xmpG:blue>0</xmpG:blue>
161 </rdf:li>
162 <rdf:li rdf:parseType="Resource">
163 <xmpG:swatchName>Vert RVB</xmpG:swatchName>
164 <xmpG:mode>RGB</xmpG:mode>
165 <xmpG:type>PROCESS</xmpG:type>
166 <xmpG:red>0</xmpG:red>
167 <xmpG:green>255</xmpG:green>
168 <xmpG:blue>0</xmpG:blue>
169 </rdf:li>
170 <rdf:li rdf:parseType="Resource">
171 <xmpG:swatchName>Cyan RVB</xmpG:swatchName>
172 <xmpG:mode>RGB</xmpG:mode>
173 <xmpG:type>PROCESS</xmpG:type>
174 <xmpG:red>0</xmpG:red>
175 <xmpG:green>255</xmpG:green>
176 <xmpG:blue>255</xmpG:blue>
177 </rdf:li>
178 <rdf:li rdf:parseType="Resource">
179 <xmpG:swatchName>Bleu RVB</xmpG:swatchName>
180 <xmpG:mode>RGB</xmpG:mode>
181 <xmpG:type>PROCESS</xmpG:type>
182 <xmpG:red>0</xmpG:red>
183 <xmpG:green>0</xmpG:green>
184 <xmpG:blue>255</xmpG:blue>
185 </rdf:li>
186 <rdf:li rdf:parseType="Resource">
187 <xmpG:swatchName>Magenta RVB</xmpG:swatchName>
188 <xmpG:mode>RGB</xmpG:mode>
189 <xmpG:type>PROCESS</xmpG:type>
190 <xmpG:red>255</xmpG:red>
191 <xmpG:green>0</xmpG:green>
192 <xmpG:blue>255</xmpG:blue>
193 </rdf:li>
194 <rdf:li rdf:parseType="Resource">
195 <xmpG:swatchName>R=193 V=39 B=45</xmpG:swatchName>
196 <xmpG:mode>RGB</xmpG:mode>
197 <xmpG:type>PROCESS</xmpG:type>
198 <xmpG:red>193</xmpG:red>
199 <xmpG:green>39</xmpG:green>
200 <xmpG:blue>45</xmpG:blue>
201 </rdf:li>
202 <rdf:li rdf:parseType="Resource">
203 <xmpG:swatchName>R=237 V=28 B=36</xmpG:swatchName>
204 <xmpG:mode>RGB</xmpG:mode>
205 <xmpG:type>PROCESS</xmpG:type>
206 <xmpG:red>237</xmpG:red>
207 <xmpG:green>28</xmpG:green>
208 <xmpG:blue>36</xmpG:blue>
209 </rdf:li>
210 <rdf:li rdf:parseType="Resource">
211 <xmpG:swatchName>R=241 V=90 B=36</xmpG:swatchName>
212 <xmpG:mode>RGB</xmpG:mode>
213 <xmpG:type>PROCESS</xmpG:type>
214 <xmpG:red>241</xmpG:red>
215 <xmpG:green>90</xmpG:green>
216 <xmpG:blue>36</xmpG:blue>
217 </rdf:li>
218 <rdf:li rdf:parseType="Resource">
219 <xmpG:swatchName>R=247 V=147 B=30</xmpG:swatchName>
220 <xmpG:mode>RGB</xmpG:mode>
221 <xmpG:type>PROCESS</xmpG:type>
222 <xmpG:red>247</xmpG:red>
223 <xmpG:green>147</xmpG:green>
224 <xmpG:blue>30</xmpG:blue>
225 </rdf:li>
226 <rdf:li rdf:parseType="Resource">
227 <xmpG:swatchName>R=251 V=176 B=59</xmpG:swatchName>
228 <xmpG:mode>RGB</xmpG:mode>
229 <xmpG:type>PROCESS</xmpG:type>
230 <xmpG:red>251</xmpG:red>
231 <xmpG:green>176</xmpG:green>
232 <xmpG:blue>59</xmpG:blue>
233 </rdf:li>
234 <rdf:li rdf:parseType="Resource">
235 <xmpG:swatchName>R=252 V=238 B=33</xmpG:swatchName>
236 <xmpG:mode>RGB</xmpG:mode>
237 <xmpG:type>PROCESS</xmpG:type>
238 <xmpG:red>252</xmpG:red>
239 <xmpG:green>238</xmpG:green>
240 <xmpG:blue>33</xmpG:blue>
241 </rdf:li>
242 <rdf:li rdf:parseType="Resource">
243 <xmpG:swatchName>R=217 V=224 B=33</xmpG:swatchName>
244 <xmpG:mode>RGB</xmpG:mode>
245 <xmpG:type>PROCESS</xmpG:type>
246 <xmpG:red>217</xmpG:red>
247 <xmpG:green>224</xmpG:green>
248 <xmpG:blue>33</xmpG:blue>
249 </rdf:li>
250 <rdf:li rdf:parseType="Resource">
251 <xmpG:swatchName>R=140 V=198 B=63</xmpG:swatchName>
252 <xmpG:mode>RGB</xmpG:mode>
253 <xmpG:type>PROCESS</xmpG:type>
254 <xmpG:red>140</xmpG:red>
255 <xmpG:green>198</xmpG:green>
256 <xmpG:blue>63</xmpG:blue>
257 </rdf:li>
258 <rdf:li rdf:parseType="Resource">
259 <xmpG:swatchName>R=57 V=181 B=74</xmpG:swatchName>
260 <xmpG:mode>RGB</xmpG:mode>
261 <xmpG:type>PROCESS</xmpG:type>
262 <xmpG:red>57</xmpG:red>
263 <xmpG:green>181</xmpG:green>
264 <xmpG:blue>74</xmpG:blue>
265 </rdf:li>
266 <rdf:li rdf:parseType="Resource">
267 <xmpG:swatchName>R=0 V=146 B=69</xmpG:swatchName>
268 <xmpG:mode>RGB</xmpG:mode>
269 <xmpG:type>PROCESS</xmpG:type>
270 <xmpG:red>0</xmpG:red>
271 <xmpG:green>146</xmpG:green>
272 <xmpG:blue>69</xmpG:blue>
273 </rdf:li>
274 <rdf:li rdf:parseType="Resource">
275 <xmpG:swatchName>R=0 V=104 B=55</xmpG:swatchName>
276 <xmpG:mode>RGB</xmpG:mode>
277 <xmpG:type>PROCESS</xmpG:type>
278 <xmpG:red>0</xmpG:red>
279 <xmpG:green>104</xmpG:green>
280 <xmpG:blue>55</xmpG:blue>
281 </rdf:li>
282 <rdf:li rdf:parseType="Resource">
283 <xmpG:swatchName>R=34 V=181 B=115</xmpG:swatchName>
284 <xmpG:mode>RGB</xmpG:mode>
285 <xmpG:type>PROCESS</xmpG:type>
286 <xmpG:red>34</xmpG:red>
287 <xmpG:green>181</xmpG:green>
288 <xmpG:blue>115</xmpG:blue>
289 </rdf:li>
290 <rdf:li rdf:parseType="Resource">
291 <xmpG:swatchName>R=0 V=69 B=157</xmpG:swatchName>
292 <xmpG:mode>RGB</xmpG:mode>
293 <xmpG:type>PROCESS</xmpG:type>
294 <xmpG:red>0</xmpG:red>
295 <xmpG:green>169</xmpG:green>
296 <xmpG:blue>157</xmpG:blue>
297 </rdf:li>
298 <rdf:li rdf:parseType="Resource">
299 <xmpG:swatchName>R=41 V=71 B=226</xmpG:swatchName>
300 <xmpG:mode>RGB</xmpG:mode>
301 <xmpG:type>PROCESS</xmpG:type>
302 <xmpG:red>41</xmpG:red>
303 <xmpG:green>171</xmpG:green>
304 <xmpG:blue>226</xmpG:blue>
305 </rdf:li>
306 <rdf:li rdf:parseType="Resource">
307 <xmpG:swatchName>R=0 V=113 B=188</xmpG:swatchName>
308 <xmpG:mode>RGB</xmpG:mode>
309 <xmpG:type>PROCESS</xmpG:type>
310 <xmpG:red>0</xmpG:red>
311 <xmpG:green>113</xmpG:green>
312 <xmpG:blue>188</xmpG:blue>
313 </rdf:li>
314 <rdf:li rdf:parseType="Resource">
315 <xmpG:swatchName>R=46 V=49 B=146</xmpG:swatchName>
316 <xmpG:mode>RGB</xmpG:mode>
317 <xmpG:type>PROCESS</xmpG:type>
318 <xmpG:red>46</xmpG:red>
319 <xmpG:green>49</xmpG:green>
320 <xmpG:blue>146</xmpG:blue>
321 </rdf:li>
322 <rdf:li rdf:parseType="Resource">
323 <xmpG:swatchName>R=27 V=20 B=100</xmpG:swatchName>
324 <xmpG:mode>RGB</xmpG:mode>
325 <xmpG:type>PROCESS</xmpG:type>
326 <xmpG:red>27</xmpG:red>
327 <xmpG:green>20</xmpG:green>
328 <xmpG:blue>100</xmpG:blue>
329 </rdf:li>
330 <rdf:li rdf:parseType="Resource">
331 <xmpG:swatchName>R=102 V=45 B=145</xmpG:swatchName>
332 <xmpG:mode>RGB</xmpG:mode>
333 <xmpG:type>PROCESS</xmpG:type>
334 <xmpG:red>102</xmpG:red>
335 <xmpG:green>45</xmpG:green>
336 <xmpG:blue>145</xmpG:blue>
337 </rdf:li>
338 <rdf:li rdf:parseType="Resource">
339 <xmpG:swatchName>R=147 V=39 B=143</xmpG:swatchName>
340 <xmpG:mode>RGB</xmpG:mode>
341 <xmpG:type>PROCESS</xmpG:type>
342 <xmpG:red>147</xmpG:red>
343 <xmpG:green>39</xmpG:green>
344 <xmpG:blue>143</xmpG:blue>
345 </rdf:li>
346 <rdf:li rdf:parseType="Resource">
347 <xmpG:swatchName>R=158 V=0 B=93</xmpG:swatchName>
348 <xmpG:mode>RGB</xmpG:mode>
349 <xmpG:type>PROCESS</xmpG:type>
350 <xmpG:red>158</xmpG:red>
351 <xmpG:green>0</xmpG:green>
352 <xmpG:blue>93</xmpG:blue>
353 </rdf:li>
354 <rdf:li rdf:parseType="Resource">
355 <xmpG:swatchName>R=212 V=20 B=90</xmpG:swatchName>
356 <xmpG:mode>RGB</xmpG:mode>
357 <xmpG:type>PROCESS</xmpG:type>
358 <xmpG:red>212</xmpG:red>
359 <xmpG:green>20</xmpG:green>
360 <xmpG:blue>90</xmpG:blue>
361 </rdf:li>
362 <rdf:li rdf:parseType="Resource">
363 <xmpG:swatchName>R=237 V=30 B=121</xmpG:swatchName>
364 <xmpG:mode>RGB</xmpG:mode>
365 <xmpG:type>PROCESS</xmpG:type>
366 <xmpG:red>237</xmpG:red>
367 <xmpG:green>30</xmpG:green>
368 <xmpG:blue>121</xmpG:blue>
369 </rdf:li>
370 <rdf:li rdf:parseType="Resource">
371 <xmpG:swatchName>R=199 V=178 B=153</xmpG:swatchName>
372 <xmpG:mode>RGB</xmpG:mode>
373 <xmpG:type>PROCESS</xmpG:type>
374 <xmpG:red>199</xmpG:red>
375 <xmpG:green>178</xmpG:green>
376 <xmpG:blue>153</xmpG:blue>
377 </rdf:li>
378 <rdf:li rdf:parseType="Resource">
379 <xmpG:swatchName>R=153 V=134 B=117</xmpG:swatchName>
380 <xmpG:mode>RGB</xmpG:mode>
381 <xmpG:type>PROCESS</xmpG:type>
382 <xmpG:red>153</xmpG:red>
383 <xmpG:green>134</xmpG:green>
384 <xmpG:blue>117</xmpG:blue>
385 </rdf:li>
386 <rdf:li rdf:parseType="Resource">
387 <xmpG:swatchName>R=115 V=99 B=87</xmpG:swatchName>
388 <xmpG:mode>RGB</xmpG:mode>
389 <xmpG:type>PROCESS</xmpG:type>
390 <xmpG:red>115</xmpG:red>
391 <xmpG:green>99</xmpG:green>
392 <xmpG:blue>87</xmpG:blue>
393 </rdf:li>
394 <rdf:li rdf:parseType="Resource">
395 <xmpG:swatchName>R=83 V=71 B=65</xmpG:swatchName>
396 <xmpG:mode>RGB</xmpG:mode>
397 <xmpG:type>PROCESS</xmpG:type>
398 <xmpG:red>83</xmpG:red>
399 <xmpG:green>71</xmpG:green>
400 <xmpG:blue>65</xmpG:blue>
401 </rdf:li>
402 <rdf:li rdf:parseType="Resource">
403 <xmpG:swatchName>R=198 V=156 B=109</xmpG:swatchName>
404 <xmpG:mode>RGB</xmpG:mode>
405 <xmpG:type>PROCESS</xmpG:type>
406 <xmpG:red>198</xmpG:red>
407 <xmpG:green>156</xmpG:green>
408 <xmpG:blue>109</xmpG:blue>
409 </rdf:li>
410 <rdf:li rdf:parseType="Resource">
411 <xmpG:swatchName>R=166 V=124 B=82</xmpG:swatchName>
412 <xmpG:mode>RGB</xmpG:mode>
413 <xmpG:type>PROCESS</xmpG:type>
414 <xmpG:red>166</xmpG:red>
415 <xmpG:green>124</xmpG:green>
416 <xmpG:blue>82</xmpG:blue>
417 </rdf:li>
418 <rdf:li rdf:parseType="Resource">
419 <xmpG:swatchName>R=140 V=98 B=57</xmpG:swatchName>
420 <xmpG:mode>RGB</xmpG:mode>
421 <xmpG:type>PROCESS</xmpG:type>
422 <xmpG:red>140</xmpG:red>
423 <xmpG:green>98</xmpG:green>
424 <xmpG:blue>57</xmpG:blue>
425 </rdf:li>
426 <rdf:li rdf:parseType="Resource">
427 <xmpG:swatchName>R=117 V=76 B=36</xmpG:swatchName>
428 <xmpG:mode>RGB</xmpG:mode>
429 <xmpG:type>PROCESS</xmpG:type>
430 <xmpG:red>117</xmpG:red>
431 <xmpG:green>76</xmpG:green>
432 <xmpG:blue>36</xmpG:blue>
433 </rdf:li>
434 <rdf:li rdf:parseType="Resource">
435 <xmpG:swatchName>R=96 V=56 B=19</xmpG:swatchName>
436 <xmpG:mode>RGB</xmpG:mode>
437 <xmpG:type>PROCESS</xmpG:type>
438 <xmpG:red>96</xmpG:red>
439 <xmpG:green>56</xmpG:green>
440 <xmpG:blue>19</xmpG:blue>
441 </rdf:li>
442 <rdf:li rdf:parseType="Resource">
443 <xmpG:swatchName>R=66 V=33 B=11</xmpG:swatchName>
444 <xmpG:mode>RGB</xmpG:mode>
445 <xmpG:type>PROCESS</xmpG:type>
446 <xmpG:red>66</xmpG:red>
447 <xmpG:green>33</xmpG:green>
448 <xmpG:blue>11</xmpG:blue>
449 </rdf:li>
450 </rdf:Seq>
451 </xmpG:Colorants>
452 </rdf:li>
453 <rdf:li rdf:parseType="Resource">
454 <xmpG:groupName>Gris</xmpG:groupName>
455 <xmpG:groupType>1</xmpG:groupType>
456 <xmpG:Colorants>
457 <rdf:Seq>
458 <rdf:li rdf:parseType="Resource">
459 <xmpG:swatchName>R=0 V=0 B=0</xmpG:swatchName>
460 <xmpG:mode>RGB</xmpG:mode>
461 <xmpG:type>PROCESS</xmpG:type>
462 <xmpG:red>0</xmpG:red>
463 <xmpG:green>0</xmpG:green>
464 <xmpG:blue>0</xmpG:blue>
465 </rdf:li>
466 <rdf:li rdf:parseType="Resource">
467 <xmpG:swatchName>R=26 V=26 B=26</xmpG:swatchName>
468 <xmpG:mode>RGB</xmpG:mode>
469 <xmpG:type>PROCESS</xmpG:type>
470 <xmpG:red>26</xmpG:red>
471 <xmpG:green>26</xmpG:green>
472 <xmpG:blue>26</xmpG:blue>
473 </rdf:li>
474 <rdf:li rdf:parseType="Resource">
475 <xmpG:swatchName>R=51 V=51 B=51</xmpG:swatchName>
476 <xmpG:mode>RGB</xmpG:mode>
477 <xmpG:type>PROCESS</xmpG:type>
478 <xmpG:red>51</xmpG:red>
479 <xmpG:green>51</xmpG:green>
480 <xmpG:blue>51</xmpG:blue>
481 </rdf:li>
482 <rdf:li rdf:parseType="Resource">
483 <xmpG:swatchName>R=77 V=77 B=77</xmpG:swatchName>
484 <xmpG:mode>RGB</xmpG:mode>
485 <xmpG:type>PROCESS</xmpG:type>
486 <xmpG:red>77</xmpG:red>
487 <xmpG:green>77</xmpG:green>
488 <xmpG:blue>77</xmpG:blue>
489 </rdf:li>
490 <rdf:li rdf:parseType="Resource">
491 <xmpG:swatchName>R=102 V=102 B=102</xmpG:swatchName>
492 <xmpG:mode>RGB</xmpG:mode>
493 <xmpG:type>PROCESS</xmpG:type>
494 <xmpG:red>102</xmpG:red>
495 <xmpG:green>102</xmpG:green>
496 <xmpG:blue>102</xmpG:blue>
497 </rdf:li>
498 <rdf:li rdf:parseType="Resource">
499 <xmpG:swatchName>R=128 V=128 B=128</xmpG:swatchName>
500 <xmpG:mode>RGB</xmpG:mode>
501 <xmpG:type>PROCESS</xmpG:type>
502 <xmpG:red>128</xmpG:red>
503 <xmpG:green>128</xmpG:green>
504 <xmpG:blue>128</xmpG:blue>
505 </rdf:li>
506 <rdf:li rdf:parseType="Resource">
507 <xmpG:swatchName>R=153 V=153 B=153</xmpG:swatchName>
508 <xmpG:mode>RGB</xmpG:mode>
509 <xmpG:type>PROCESS</xmpG:type>
510 <xmpG:red>153</xmpG:red>
511 <xmpG:green>153</xmpG:green>
512 <xmpG:blue>153</xmpG:blue>
513 </rdf:li>
514 <rdf:li rdf:parseType="Resource">
515 <xmpG:swatchName>R=179 V=179 B=179</xmpG:swatchName>
516 <xmpG:mode>RGB</xmpG:mode>
517 <xmpG:type>PROCESS</xmpG:type>
518 <xmpG:red>179</xmpG:red>
519 <xmpG:green>179</xmpG:green>
520 <xmpG:blue>179</xmpG:blue>
521 </rdf:li>
522 <rdf:li rdf:parseType="Resource">
523 <xmpG:swatchName>R=204 V=204 B=204</xmpG:swatchName>
524 <xmpG:mode>RGB</xmpG:mode>
525 <xmpG:type>PROCESS</xmpG:type>
526 <xmpG:red>204</xmpG:red>
527 <xmpG:green>204</xmpG:green>
528 <xmpG:blue>204</xmpG:blue>
529 </rdf:li>
530 <rdf:li rdf:parseType="Resource">
531 <xmpG:swatchName>R=230 V=230 B=230</xmpG:swatchName>
532 <xmpG:mode>RGB</xmpG:mode>
533 <xmpG:type>PROCESS</xmpG:type>
534 <xmpG:red>230</xmpG:red>
535 <xmpG:green>230</xmpG:green>
536 <xmpG:blue>230</xmpG:blue>
537 </rdf:li>
538 <rdf:li rdf:parseType="Resource">
539 <xmpG:swatchName>R=242 V=242 B=242</xmpG:swatchName>
540 <xmpG:mode>RGB</xmpG:mode>
541 <xmpG:type>PROCESS</xmpG:type>
542 <xmpG:red>242</xmpG:red>
543 <xmpG:green>242</xmpG:green>
544 <xmpG:blue>242</xmpG:blue>
545 </rdf:li>
546 </rdf:Seq>
547 </xmpG:Colorants>
548 </rdf:li>
549 <rdf:li rdf:parseType="Resource">
550 <xmpG:groupName>Groupe de couleurs pour films et vidéos</xmpG:groupName>
551 <xmpG:groupType>1</xmpG:groupType>
552 <xmpG:Colorants>
553 <rdf:Seq>
554 <rdf:li rdf:parseType="Resource">
555 <xmpG:swatchName>R=123 V=112 B=49</xmpG:swatchName>
556 <xmpG:mode>RGB</xmpG:mode>
557 <xmpG:type>PROCESS</xmpG:type>
558 <xmpG:red>123</xmpG:red>
559 <xmpG:green>112</xmpG:green>
560 <xmpG:blue>49</xmpG:blue>
561 </rdf:li>
562 <rdf:li rdf:parseType="Resource">
563 <xmpG:swatchName>R=199 V=163 B=21</xmpG:swatchName>
564 <xmpG:mode>RGB</xmpG:mode>
565 <xmpG:type>PROCESS</xmpG:type>
566 <xmpG:red>199</xmpG:red>
567 <xmpG:green>163</xmpG:green>
568 <xmpG:blue>21</xmpG:blue>
569 </rdf:li>
570 <rdf:li rdf:parseType="Resource">
571 <xmpG:swatchName>R=182 V=165 B=85</xmpG:swatchName>
572 <xmpG:mode>RGB</xmpG:mode>
573 <xmpG:type>PROCESS</xmpG:type>
574 <xmpG:red>182</xmpG:red>
575 <xmpG:green>165</xmpG:green>
576 <xmpG:blue>85</xmpG:blue>
577 </rdf:li>
578 <rdf:li rdf:parseType="Resource">
579 <xmpG:swatchName>R=235 V=208 B=101</xmpG:swatchName>
580 <xmpG:mode>RGB</xmpG:mode>
581 <xmpG:type>PROCESS</xmpG:type>
582 <xmpG:red>235</xmpG:red>
583 <xmpG:green>208</xmpG:green>
584 <xmpG:blue>101</xmpG:blue>
585 </rdf:li>
586 <rdf:li rdf:parseType="Resource">
587 <xmpG:swatchName>R=122 V=111 B=185</xmpG:swatchName>
588 <xmpG:mode>RGB</xmpG:mode>
589 <xmpG:type>PROCESS</xmpG:type>
590 <xmpG:red>122</xmpG:red>
591 <xmpG:green>111</xmpG:green>
592 <xmpG:blue>185</xmpG:blue>
593 </rdf:li>
594 </rdf:Seq>
595 </xmpG:Colorants>
596 </rdf:li>
597 </rdf:Seq>
598 </xmpTPg:SwatchGroups>
599 </rdf:Description>
600 <rdf:Description rdf:about=""
601 xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
602 <pdf:Producer>Adobe PDF library 10.01</pdf:Producer>
603 </rdf:Description>
604 </rdf:RDF>
605</x:xmpmeta>
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627<?xpacket end="w"?> endstream endobj 3 0 obj <</Count 2/Kids[7 0 R 8 0 R]/Type/Pages>> endobj 7 0 obj <</ArtBox[224.515 66.2373 1617.31 1080.0]/BleedBox[0.0 0.0 1920.0 1080.0]/Contents 732 0 R/Group 733 0 R/LastModified(D:20140918115258+02'00')/MediaBox[0.0 0.0 1920.0 1080.0]/Parent 3 0 R/PieceInfo<</Illustrator 734 0 R>>/Resources<</ColorSpace<</CS0 735 0 R/CS1 736 0 R/CS2 737 0 R/CS3 738 0 R/CS4 739 0 R/CS5 740 0 R/CS6 741 0 R/CS7 742 0 R/CS8 743 0 R>>/ExtGState<</GS0 744 0 R/GS1 745 0 R/GS2 746 0 R/GS3 747 0 R/GS4 748 0 R/GS5 749 0 R/GS6 750 0 R/GS7 751 0 R>>/Font<</T1_0 752 0 R/TT0 753 0 R/TT1 754 0 R>>/ProcSet[/PDF/Text/ImageC/ImageI]/Properties<</MC0 730 0 R>>/Shading<</Sh0 755 0 R>>/XObject<</Fm0 756 0 R/Fm1 757 0 R/Fm2 758 0 R/Fm3 759 0 R/Fm4 760 0 R/Fm5 761 0 R/Fm6 762 0 R/Im0 763 0 R/Im1 764 0 R/Im2 765 0 R/Im3 766 0 R/Im4 763 0 R/Im5 767 0 R/Im6 768 0 R/Im7 769 0 R/Im8 770 0 R/Im9 771 0 R>>>>/TrimBox[0.0 0.0 1920.0 1080.0]/Type/Page>> endobj 8 0 obj <</ArtBox[6464.01 6726.74 7856.81 7766.5]/BleedBox[0.0 0.0 14400.0 14400.0]/Contents 772 0 R/Group 773 0 R/LastModified(D:20140918115258+02'00')/MediaBox[0.0 0.0 14400.0 14400.0]/Parent 3 0 R/PieceInfo<</Illustrator 734 0 R>>/Resources<</ColorSpace<</CS0 735 0 R/CS1 736 0 R/CS2 737 0 R/CS3 738 0 R/CS4 739 0 R/CS5 740 0 R/CS6 741 0 R/CS7 742 0 R/CS8 743 0 R>>/ExtGState<</GS0 744 0 R/GS1 745 0 R/GS2 774 0 R/GS3 747 0 R/GS4 775 0 R/GS5 776 0 R/GS6 777 0 R/GS7 778 0 R>>/Font<</T1_0 752 0 R/TT0 753 0 R/TT1 754 0 R>>/ProcSet[/PDF/Text/ImageC/ImageI]/Properties<</MC0 730 0 R>>/Shading<</Sh0 755 0 R>>/XObject<</Fm0 779 0 R/Fm1 780 0 R/Fm2 781 0 R/Fm3 782 0 R/Fm4 783 0 R/Fm5 784 0 R/Fm6 785 0 R/Im0 763 0 R/Im1 764 0 R/Im2 765 0 R/Im3 766 0 R/Im4 763 0 R/Im5 767 0 R/Im6 768 0 R/Im7 769 0 R/Im8 770 0 R/Im9 771 0 R>>>>/TrimBox[0.0 0.0 14400.0 14400.0]/Type/Page>> endobj 772 0 obj <</Filter/FlateDecode/Length 3434>>stream
628Hԗ[o%WWiqA`K\Ϸt&y
629sNuWZU7޽MW7]߸`)ΡG->ٻ1૫-N5eS[7ɻ?-<`O? {W?ӯTKD]%%5w璛5yZDⓜcε\v7
630_:Z{:.`nQ,6fE-Msx,/51*1y2B
631w:
632cqb;O/_=w^
633?zaaLfҜ{8e8!W,!?PO9y L뗸K)<oJaj:H.?mX
634貟+'PU#om%9(4)uH# +S"/|]yx2zRy3Ѱ\C[rƴ)7չFVC;u6-;: Ҫm
635
636χ!LzD[HK߬H!
637+1Cɐ*-<5&]a5/,
6384>/c,k y3Ez{ՄMIiE6޺-p] N+N!:HF,RC,)!U]aW :V g;+WtHu<j8%ےbTţ KZ0EgA ] ),2IۄÝ :9QuIaB^a`X;*-nmw
639__)δ TY^ &vypJOSҟNI)߷G񿻹|vܷn`&k &75Ћ,,ۃ6/+D`X3욹5i:0BH6'53R'Y⋻Otw6^hӋOqܖ }g]]xw~pQ=-yyTY CֳĠp yと.n Fͩ q>w`u߾ު/3 wƒnIrūF:O WGWNgh=活{z7o o5Qp;|B̭{ 4tV]Z.ytP߀z
640wH.lO^_^7[)@#IKuxZv䒪w˥ǵ IbeߍuhO?5%mo
6419 XϜǽ
642ym$1ڽ"dJ~#w2J +nn)|ѐʟ PDoO$ lOpsfnBHexWumDѧ.nWMe#ɭcx=OAA<be՜OBI<WBj1VTqP)l6j2_[zUpv!
6432$?ܦEʰ(=DE84fd|WuKs8deZ};bf ),G#+2OJ}u)vonR QX; N"IŒRJ!=:hj @jua2j;.5A7JO^Uؾ\[jp_)K
644 ",p2U? G cAlp^0lw9U4^Kel.Fh)O|#}[tg{(NƹN6.U1Y*j+~e"#z-+VB taψ;/hqHA#+q=uaO"pְd#6P|9XhVY&`ٺ\#ž/$rː*fJO~j~>`U4T OIZĶ8|%]2(.%.c
645q
646/GS0 gs
647486 0 0 480 6513.1162109 7207.1401367 cm
648/Im0 Do
649Q
650 endstream endobj 780 0 obj <</BBox[6557.12 7644.14 6955.12 7246.14]/Group 791 0 R/Length 61/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 792 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 793 0 R>>>>/Subtype/Form>>stream
651q
652/GS0 gs
653398 0 0 398 6557.1162109 7246.1401367 cm
654/Im0 Do
655Q
656 endstream endobj 781 0 obj <</BBox[6625.12 7519.14 6893.12 7475.14]/Group 794 0 R/Length 60/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 795 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 796 0 R>>>>/Subtype/Form>>stream
657q
658/GS0 gs
659268 0 0 44 6625.1162109 7475.1401367 cm
660/Im0 Do
661Q
662 endstream endobj 782 0 obj <</BBox[6622.12 7549.14 6896.12 7246.14]/Group 797 0 R/Length 61/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 798 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 799 0 R>>>>/Subtype/Form>>stream
663q
664/GS0 gs
665274 0 0 303 6622.1162109 7246.1401367 cm
666/Im0 Do
667Q
668 endstream endobj 783 0 obj <</BBox[6647.5 7607.5 6943.5 7516.5]/Group 800 0 R/Length 48/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 801 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 802 0 R>>>>/Subtype/Form>>stream
669q
670/GS0 gs
671296 0 0 91 6647.5 7516.5 cm
672/Im0 Do
673Q
674 endstream endobj 784 0 obj <</BBox[6485.5 7766.5 6957.5 7240.5]/Group 803 0 R/Length 49/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 804 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 805 0 R>>>>/Subtype/Form>>stream
675q
676/GS0 gs
677472 0 0 526 6485.5 7240.5 cm
678/Im0 Do
679Q
680 endstream endobj 785 0 obj <</BBox[6522.5 7682.5 7035.5 7180.5]/Group 806 0 R/Length 49/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 807 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 808 0 R>>>>/Subtype/Form>>stream
681q
682/GS0 gs
683513 0 0 502 6522.5 7180.5 cm
684/Im0 Do
685Q
686 endstream endobj 763 0 obj <</BitsPerComponent 8/ColorSpace 736 0 R/Decode[0.0 255.0]/Filter/FlateDecode/Height 87/Intent/RelativeColorimetric/Length 321/Name/X/SMask 809 0 R/Subtype/Image/Type/XObject/Width 310>>stream
687HgN@@uޝad"xVzj
688slBXiniYBru\(N[m.LCN~ݬ_֛n840-!+b-7NӴIEWLn5ql_l˯6t^QETPc`PO՞诪
689Hg{Jc6'9 Lw
690jH!T2#Wu\dt3           }? ^ؽ>{}`s3fz~p?xxv/^zkZ욣f(uP6ʲ$vf~{iv] N 0Ʒ)v8XL c<麆RPQd$ <q,0>Mӽ^ ˋfXTW3
691c>vڭf^Vʥb!fJ&s$>yƓTb;'gL]7JY*GA(x"t&rZ7v"BUSjz9w,$Pcˋ|x;.n *opԙ/NsXүRD,^_~ݿ?/..>]=>4l{S7`yHʕj+ϝ'GGD4SժL*y|-U`58;cM+phSu4uQÞ>YܝjLJC CC2ߴ!_ FSkTMgOofb#M{?-3-lmd8 M;)*S쾬4Fl}O1n>w~KƟeaX{Zw~=ې)'Vv?!t١ F= !5ʕ[ 'Ṿ-ڈ5Ն͊N$Lef{
692=kr\y=]<;15FtDn׳&
693NC1޴rcӳмl v'y%vr^XF@/؝Smh_>_f ܳ7 7Բw嬽f#zϗ?myKVDD[z v"wv,&n@6}r_ϴ;h!;,Uv_Y1*C7X wj"+Do^:k 휩c9/YGAv''Ʀ=`;1;Ұ$JDO!"v]r =UX3 vY6r@ zC͘ 얳)XnWoq{N*9ާMcv4rDOLgvHXeX')>lVDE,'ʚv/tۆ& XO9:Y* ݣ@R
694;ͦc^Gxq8B<;ۍrNq``皺<`\!z@LV<ڭ6cxY8`h7$Zsj]m"KcfIhVvCaFAz.+~kuvvӑ,Wֈ^e}
695vv˩.s6VD$m
696F`G;[/\ʧ/;:ۀYG;S+\*"zb͂]LeB%I-T[vL`D<A2Jvvvٰ,X.tܠ;эRŢ1^T] QGe]VHs҅jSSI, G^Wڲ vڕr^X/A- [;rMʼnܓO/ʖ:5Kd ==>X2Sl]-5D=^4.Ekvg*B!5 vky*rD/rUa
697va\*J}zT^hgj6rwwD/T`e',w{sK"4ؽn:G,w=T7`wb|1{_OX5{xJ܂i.x>]}"zI{JH]]^P$Qd' ; %X>`BvixnN%k8\noww Iq/>0٭Ozk\0˥!" ESYihx&#AzD/Ifh7e
698rzYXi턍- ꈞŎv VJ1 rZmhq xYM QkɊvNQrj-HavS)UD`F;X结Be҃R$zz+_ܢ1;rN]g1v 'ɉ oЎ߸dRӠxCB.ЫAN*=q;I$DOvvO7٠]9+S,Sx#v&`Anfzɵ6uvxvNniv=^~Frl'X}ts
699ܯ1=AYRѓ-ػ쿠/'ON>lhwߠ)J2ӛT;{Cv#߾_b{eRαtCo_X9ɛ\Ўߤ+WVKr#ܗ/oVa$g%fej響/h VN51g8
700X[bJ(z r{Pvȹ=^_=^n舟x@<^}D=RT vbmӱ"zDctmv]<@qz G8ډ5idz ‰t}]6 r@0̠HCf. r`(6vn"ӱp0H8`(sh'kzUP@.|s
701턁]1àrH4.HCv)E"rh,)N1T<=l Dz;grt"=ti_?A;~`Wx@.Hykdw{P)S\"J7h' L%StXA;v/wGRN@R4-Un"34M15x3(Nt&nNg,4\:-Kh7Ҫs \&+Vw/h'[mWKl@.˗lhzY1\qr|W;h7gPg<\Pdkh7dcQ.
702rbXXܣ0nsYaEb47n]tkUeJ%T[K'h'^i #rL^BɆvoze
703×{s{a;LwHj| u4({U[^^׷b:%kr
704=ȽO;ͥTct=ȽNz6~G`Wy' 7O曣T{b:Crt={աzLg˝bj"Gۯ) 7W{Վh';^fЃlX4'{]YЃ|u'{iZ,r=n\.Me^.jS /Tc߬VЃj٫N
705vvخЃz=hV@;. lvw ;.r~䶻pB=.yavb8QN;Ʈ=S=ЃpTM7*h';N w84ˋi'ؕI`=OnqI;. C=N=Ui@r Zek
706=ȩn!<4AN ˋJ:}uAN7 ۏvR[]āc^'gN紓kE8j g+7=ڕiڦ =ș "ϱ,Aβ/JK5v1cЃ8NYNOrYE;9q Vr}iܽ=$]zs=?L4].σ<?Ң\k1Cr~@oH0A.=Qhvbh#A.# ډM0(SA:"Nh;]i=E1#̒8ʺ9ivbhSA.NRaw\gWi@rI@8R,A.
707 ˧ fv7uvug==e
708 Է+T,/h7Xy=nchˢSA,]?؉?A zʪꦂvzv:7]uӃ\UwSA~]7;˹5~diׯgwE{.W vٹڣ]٥vpk7~qTn|ۏ~qTyyyc1c1c1c1c1cO
709HI
710Hҹ0Plc@ P
711kku.`A| i
712H{_t:if3q ."&"?#i~oaaaaaaaaaaa/Cv/^ڽ<{yyo~?۷ݒ?h;r߱Kfٜ|;^l.zɕ9I}K҂dsE2M˴z2c"^جWK{nNHO۶%Η9c|wnvϳ!*\LӦxe4e$!DZ`0>Mӽ^̀$U3=swZ΍",|9@aA/HQ'iA=AvO;Z)eDDrӽnj6j\*l&MQd"F"ch,r@z2~֎tAᇇAQdҙl._(ʕjhڝnϹ=,7*Xn6a]/&v(rۛϟ>^~_]8Z-ܯPx,t?|/.>\~.t)̩bu{U=3^a9Hʕj+^>O/O%br|"_Jydpk}|MjctX(Vf-,'6TH% }|@SɴǑUW\{\9w]iLSt2ɞš
7134U[s^suQve[nwDm|7-aWl)/ى
714f)€f zi|݈gz ר7@ 婉vvT WA礉vvDժ5Ь4Fvkc,6U+UkNWArrZ]F@N`:M+ʠyezBv3 W*@Ѧ# VhH W,Aq2\YB
715E#QKtKjJ\$$E |vJJΥV9{r^<)55K#=?c2]l]@;KlӉ݇A/
716uܠy]@ţ  ^4NkhNށ^1 vT̓blmLMF ws}zh"SeH<vAa%߃+л?R%V_y`G=C g chю+S;=DSŁ~B.A>Dvk-%#p z7pVhw%w ]߅hC8`vד䜳D"#298"mU#շ30qp,o_X`KEC녢,ډշ{id Q^
717Dv]&@8F;vt<9zPn^tNo @r/E;jL4˹.^/IU6λh'is:Gh'Z߮{Ye>
718vQPv! rvtD^Tj=Hkgh7o gXAMNrul=gW_No8Al2Ch56A g2@c_wh'le9zvvqv/glr@Π7On!;:=Yh'^J)[@NՁNnn!;-mh'tXM Qk@dumkb9J zF ډ=ߞ,"nTJ̮Pn}v†LzS*7x=b>2@N!W f珯Nа29i h'^ 9 Ie;#kN rY)nB|6Ы@nvfT:?:<hvJ=%Mh`w4 u
719LBk1kNJ$?%'G qvVoA4Vi_;^vٽ>vϪ܏?@OЩeF#r߿}'zh7~-j}IfUf*YٽHB/_zhqv˽z6f9ܗ_z=ɛ\<q;NϜg=n-I3ܧO^oZa+h7ݧ>[_.v Q1M"x+oG;AFow]{ r OSwEͳ;x~<>ُ=^7ڢJ8^_̪T{E;AB?z}Mo9h2>F6 ~Jj Hv.'F;ߦ̀i4ؿz|EFfgywYgt}4 u
720T*|LvFd2)#r2&4;z\zDN.WtS)G
721M{i/BNZ="T@f FӨTGT* Mow^̇]FZ zDN1ڍ5lh@i4:#ډ׳|{TMzV7B3 3t:#r:vqv/wŨbAF;_lߢ!;`
722Pn vvArs<t
723b: AȅS@;vsL2DbtyB;a`fSh\4OeJh'ֻ<cX,d^ rIG$C;v7 B:HK$R|yn턁]aI#r$)TNbeR)#r-Vn<4Εj h'һRgdl}"vr!NKv" +J1ɀdrrsչj)͂fJkD۽޵kl!r[[=FB-G"[_C;v'rP
724˂cJ}ne"vk j zD\6WwN]lo}YT@U*ڍE7Zj\Zo-ݿrJsRΉ`n]w*SO!%^^:Vm4(NqN-ﯯGrV]Hcin AdgV;h밓q=|}|gnXk|2ɍFhewlHn<.6'3`7luM&GrlU,a:tj>MNa'\^fGrbלv8n9|t7^k{iZ,XhN[/Grzw2ݠ. ,uYXV^1}IjRakzz$^o$v~m6Gr"ݰ. ]nYIwDz \S9vGrA10ݰ%<S=GrQ5vZ"-t8'v.uxd=;vZ2NGrjd]*\SS#9ELG$vZ* ]SWU#9UMWVYYiaaZnXgۦi{QV]a78pL`=3 a'awX鱜iAװڝDiə트oDvezeY㉤8nXgmٶi ;Iݥ8Gri9b==s=ь 솱] uY\q֮ư{N ^y^9duvi$|HEzsЊ `= v%%C#9͘$km$둜QъȮIGra%Y;Y]QrQ)X>
725IRfI#8Ɋvخiqή$a=K4vO]Y#4+*Ic˗;I]]YO䲼1 vEeYQְvͰ(H.ϋ
726vsЖEO䊲͎Haw$k>xU#a'ܧ`T\UUv:빮zz$ea'o`ܧv\7~[£vO쮗s}5]vOݟ:S vvWqۣSu.iVwy7Ͽ}ڿ?oo;B!B!B!B!B!
727H 
728H 0Qְ+Qs@+`䓋
729vG_
730H΁@
731H z--JRMX49jV&""""""ڟŇSrM'crfG
732'3ݞ<SSvA[*^HL+{,[Uw;лƔ0WL9E@}S T&"""""
733
734tttlllfffaaaZZZTTTOOOJJJDDD???;;;555222---)))!!! 
735HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽
736 
737V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'K
738x-
739ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9
740N')].uJr
741 wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4
742n3ܣkGݯz=[==<=G</z^^j^ ޡZQB0FX'+t<u-{__ߘ-G,}/Hh 8mW2p[AiAN#8$X?AKHI{!7<qWy(!46-aaaW @@`lYĎH,$((Yh7ъb<b*b<~L&Y&9%uMssNpJP%MI JlN<DHJIڐtCj'KwKgC%Nd |ꙪO=%mLuvx:HoL!ȨC&13#s$/Y=OsbsrnsO1v=ˏϟ\h٢#¼oZ<]TUt}`IÒsKV-Y,+>TB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O
743zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km
744H
745}}}tttlll^^^PPPCCC222((( 
746H1
747bbb[[[III444///+++###
748
749
750
751HA
752tttlllPPPJJJ222(((  endstream endobj 737 0 obj [/Indexed 735 0 R 121 823 0 R] endobj 813 0 obj <</BitsPerComponent 8/ColorSpace/DeviceGray/DecodeParms<</BitsPerComponent 4/Colors 1/Columns 316>>/Filter/FlateDecode/Height 345/Intent/RelativeColorimetric/Length 604/Name/X/Subtype/Image/Type/XObject/Width 316>>stream
753HA
754}}}{{{yyywwwvvvtttqqqpppnnnlllkkkhhhgggeeebbb___^^^\\\ZZZYYYWWWVVVTTTRRRQQQOOONNNLLLJJJHHHFFFEEECCCBBB@@@???>>><<<:::888777555444333222111///...---,,,+++)))((('''&&&%%%$$$###"""!!! 
755
756
757 
758
759rrrkkkWWWPPP???444///+++&&&""" 
760H1
761|||tttMMM@@@***!!! endstream endobj 810 0 obj <</BitsPerComponent 8/ColorSpace/DeviceGray/DecodeParms<</BitsPerComponent 4/Colors 1/Columns 316>>/Filter/FlateDecode/Height 345/Intent/RelativeColorimetric/Length 603/Name/X/Subtype/Image/Type/XObject/Width 316>>stream
762H
763H1
764kZaVX+
765kZa
766~~~wwwpppiiibbb\\\VVVQQQKKKFFF@@@<<<666222---)))%%%!!!
767
768
769
770HnFE/ b-Q Ϋ
771Hvv0< @ Ivot".V[
772c$
773Q _?c'I>jޟ?6S<?/EDƟLәL:J&T |,{>mT&ˋ\_sGe|TB^EHT\_zZ)T $
774К
775`<<Q`r|
776Tkcs:M:F\)
777'*hf9ﻎ5[RN  WZsa; +@
778p$FotA[-S
779W\7@:_mgkw<9)_'~=w%P&@c'<rRz)v
780@[0_
781Q噤8Eᨩ*0{d@B$6ǻy=#:*'dĹyLe
7824{4tCoȟOi
783
784^ʘ
785GL N$_Y}5
786rR)Z;(s^Ԕɰ Nƣa4
787O?o,o}] 0܃q׶uJ
788&|՟̌߀/oo/O\gihP
789,
790R5`9||~<ǘInTY6@HK@IR.`/ vmiLO N(/@ =<==7@TCa?ř_Y8h׊PT?G0L|b;]ms8Q0'>$
791<I'tP˪zE
792 Y
793 k! (rV4M(Xb@끅 4( _Bx%hbfTk*^D_Pub6@4%IE~_[UXb8 O!{
794l
795?-2Y>}`򉼦owzvqz '|o~  
796o S\:$I($eR
797k5;V#z:ڭ&å|}{A{fXt2mNpa6X$;ՙ{>
798{O39O2}+TbB}]k^p<<b9n%:Na#vZgR>/t0u;;wf9slۦm[Te_$d
799@}g<E+p
800`LWg0N I>
801$h
802'oiz26t*^X4B_/.a
803_`DgӢςHX6x|}]
804
805q
806/GS0 gs
807513 0 0 502 6522.5 7180.5 cm
808/Im0 Do
809Q
810 endstream endobj 832 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 833 0 obj <</BitsPerComponent 8/ColorSpace/DeviceGray/DecodeParms<</BitsPerComponent 4/Colors 1/Columns 513>>/Filter/FlateDecode/Height 502/Intent/RelativeColorimetric/Length 8911/Name/X/Subtype/Image/Type/XObject/Width 513>>stream
811Hvv0< @ Ivot".V[
812c$
813Q _?c'I>jޟ?6S<?/EDƟLәL:J&T |,{>mT&ˋ\_sGe|TB^EHT\_zZ)T $
814К
815`<<Q`r|
816Tkcs:M:F\)
817'*hf9ﻎ5[RN  WZsa; +@
818p$FotA[-S
819W\7@:_mgkw<9)_'~=w%P&@c'<rRz)v
820@[0_
821Q噤8Eᨩ*0{d@B$6ǻy=#:*'dĹyLe
8224{4tCoȟOi
823
824^ʘ
825GL N$_Y}5
826rR)Z;(s^Ԕɰ Nƣa4
827O?o,o}] 0܃q׶uJ
828&|՟̌߀/oo/O\gihP
829,
830R5`9||~<ǘInTY6@HK@IR.`/ vmiLO N(/@ =<==7@TCa?ř_Y8h׊PT?G0L|b;]ms8Q0'>$
831<I'tP˪zE
832 Y
833 k! (rV4M(Xb@끅 4( _Bx%hbfTk*^D_Pub6@4%IE~_[UXb8 O!{
834l
835?-2Y>}`򉼦owzvqz '|o~  
836o S\:$I($eR
837k5;V#z:ڭ&å|}{A{fXt2mNpa6X$;ՙ{>
838{O39O2}+TbB}]k^p<<b9n%:Na#vZgR>/t0u;;wf9slۦm[Te_$d
839@}g<E+p
840`LWg0N I>
841$h
842'oiz26t*^X4B_/.a
843_`DgӢςHX6x|}]
844HAnVDA䖚OfTĖ oo
845
846MH'Bz .5.oŮoy/tO~[~F=}o|u3& j]p[]ï҈7` x 7̶a#w_}T=rqg>!pU=iQEA-Q}L&t&t˚>Sd$kYugIV]YUaeuUUuEJ:ªα4SZimV]ڬ!k'Y+Pթ^1Utϯ UŦzUYRd$k'U+INvҵd$k'];ZJNvd$k)Y;INvUuǪʺ Y+ZINVeu ǚʺMuwZINVt$k%k'];IRvҵd$kSYu\UYӵNfu8Y+];INVvd-%k'];IRvҵtk)]KZJNvtk'Y+];IJvҵdk']+INvҵtk'];INVz6{tlV]tV]w|V]7r 8Umʪ.eu꺇Yu݃gu vҵtt8[еtk'];INvҵtk'];INvd$k)Y;IRvҳd-%k+Y[JU
847HviEV$9TE3Bm?̜U!px<=dx l{B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!(|8|4*?3yts"V\!nt~xPN? Jťpqg6O˫kq}}uya%$w^;.r9aʥz$K3hu5W׽RR%egёBK`0=nK_k<;%pk)jz bp'b/d^Y >81k.*Wǒt:@Z)ztA! <(|خ.?OgB.u)b/NG|(A,
848"}o~%'Èk(Η*F\$~NW*[7t&H!yI=S/vzdlju٢JkVbT*҉H+wQUE/U̙ao0)UNY-gaCZ#1Z,fZ5t\U}G+EJ_1}dhtz^iR bVh2jVըV/S˨ (h]Dϥ:44]{Ѱ׮0B SB٨5Z^mլ8;.a2Nsʧ%aPM^v6YYX'ɰ[/g`5KC1j֛p< nf=j<%q\Z>S|vT5g|65+8E`4-Tw}8dzg!@=?U9&A G衉D*\«J`X'|#S8 FrZikk= {Cva|')\.+ET5,ֺ#[L±T\mvzllnWixn5&[{ ղ*RT8 Z>dR|fsRBP.楈SERxZ/gk؏‰lĕ<̗vDM;Jꋋ7|Jzy ?
849#*P[(:hh6jID^O揤KdF mSMJ ^v\MDnܪdehB5e-h<ΈbDhJ]F8=hOW:lD8I\K6.֛aw[&'g*y!.sWn$ 5UDbbVZހѶd2qze+l٬d$Ry3b_T`F1J"aՖ\ݙxDH6֥BJ*VZt:]`KWY,l<C`,k^k4 F$ty+a}~y}}}~a: \fRIHX:dox"B*j;5
850ehu{pda],Wrmnת ~lIM-j! #x!Z^^?V^mJe3T2L=nam'ۉ?
851~]5D/Wi9_V?U^l#~7l*kKsXVETJ~jifVc{uM(}<Y/C۬=LNdmVBdQrV֒˯lUTeb\Kb[*@Q#BǶ(詓*3k aUb:굪 &ǣ&ɨi"{RltQ^
8522_3~Cj90YU~ױoVe8HcDG"lj#͢z
853U07~1Fr'(
854ىa ; aի\*8mv
8556/waVˌ<`jOX,Z>l1r$"AvN
856JR-V*^lҷTw'jkI9{YG泩X~cû}X*WV,P9 1daZy
8578,ޡmݡ[GTT!}vFF4Ɍ'32WIBmԪ$ ֫+(5ĥ@ ۠<%Ѕ +2tfK'/NSXCNZT!E,#OQzB0g- TmT5N%Ѱ^#K堒%4ŢX<A
858S 0ue31`ŜkըӱF {
859XL2Kk7" Q%֥ȥVP^Vc< AYE.Z #H8
860P$Z,RZ3znZ0yCé猅%aݨ2ŀ=qTŒTw;&VQ+ul4z (+e^TDju_[/-{Wpy>^ʖ\
861W&G:z}M&\dn h@[᪸Z)[SY-R9ѧ*qF G+6يZe`PsFڥfR^8.NYC!)ҀUMA%3ڴr=L]
862z8sRk$@jz
863ƹ"QH+حHץpUT.mifi׮z}}@ʪ$PĎ%l' W)an@dJ.-񀘹|: \v)^s2.
864h; UAݬf+5{IZ^^eOT2Մjva{|Ņ\/"LTk0r(0avho&UzL G64)RpȞS7#%OsS ^{Zy0x*tp`(bWԱo,Ei$XӹD C1ݭ6Z\5MzWe/ϳDm\_qfAQWa/,s~0EC`#=nJKU^)i@ ҩ]|ABFU<xQB*2ZT.$V]ݻdUIl*4Ɠ Z&Q`t6cPb|&*j~'z|GU%+]a0l"NBNa
865jcKZ504
866T^]LS5 x r,Ɓc}rUɪZ,!6x[.3q]A%R2U}=3=9$sьѠOXMnZ5]\WXcнmpvlT oQդ>'j/N{LڃeJVAcK߁\>aWɮDs9T_/TA`;C"-R-M\*9S %U*k?M^mV˶ .Knn'sL:KWkj'0H%Xz#jsxx:_Utrb:pd"έJXQMM9+ D~ڠh€:wZJ!э[
867_%~|W<LĚ̕mP%z[ Hud`vZj1T_ogG+uN倵q;V~eD4RU H<3}VKfg8]6v%l<wo[7:k6 .eo*^Q^
8688tZy%Zk4Hk/V<vkۘOvV5MT$^_ 3hKۃ1ǯoƆ
869VKY5O[Ot߮ǭcFVEEV"2d|BRpSout6ە kFfU(JĖJ*M,xA#k%tNFҴ׻z6*Q!E L&u8`D!Bm½x:[,͕Nts64ʪ,9<DV RI8ɰT}|4Lv7~`;Z8&Kg,C$ׯ'u</ 4kYI]׋f3id! Kz 7D
870V&ղ,jM4pƤ)P4J&T:C3l.c?kPg0
871+ܭyܭܰlǶWsXx
872ZU]a&p2"x~#'d:B_k*
8730A( @^n#RfA-h \Эu=ϗy%+c_/X NR /^{{z^ֵY%fMo;>2r9f|^uЮH+_}՗1TxUHq\Gzf0qH>+_wJZg4[X#rkVԂwu)dٟp|{1j/ ltbdΉj=ZጭB{MN]W,Z 'ԍ4E|Aw'=^_^ .ƽF(rwd5RfiDDؚ` w+
874պnk1*3Th 2)frp>_P+co׶VKZ v2LN%YVdPpfzEZmvMrDkЭ墦+iV5ZO Nʘz-Њ5%Z kBjzn[F^o:ttCk" ޙ`'/PB\ټU[h<~FӅl~ZL*Np[S"$f 4b>L&Srvj%pPz;z٬]{e(l?pV!,UPMVomzo
875ap<Bztخms>aB`KgwzlqqdЮE5\ ~C`EoWXکO[`X3Na2栵QV%%Z
876,Y^*UÙi:]]2Q]/ӉXh %I,kplqVNh !X4^ &a,ɨm7j"!8*"~`asb\Gt2;zU/)<k}"ZDT%\oV+
877V\6>!iXBĶ:n'0lDkVA+xEDT5&`[Mae"ZÃUd5R*WkZEG~XЀId*ar岯AzDkH+HM$T*Me,"t+ރcODkkEAMS $+ŢRa
878p7d
879tfe
880Cqךq\eˀX!/ycq%Z
881G+E3HV4E0iMi
882UQdnX+kx`N EYGҷ_xZS{\ժeM%Z3J|_YNTJj5UeQTjh TURzvbE8q_sIq, Q]UxF rH jY\ w7D|' ﮠS= R13-2P1Fh,N3n^ [-!XcFD2LRk~+%P`8(6ЩT*L| JMv/{a3^^.dSWVԩ|X*˕Z~&] ,g۬sןd~!"ЩJh4v?b˭t]S,7Z)ND^]1P‘X^%ix2_{E;v5z9Ah" 1MdX ˶-CSn26k<&1CPt6gYnI t:9QE5B'lS9\7~<1ک_$bgjv{Q a=_ΞcDcZ1 _zdqT-=_|_7+_oӟΜdXm6iܳWV3b8Fb=|٣&ZѺzz]/K[ Y_S9T|E`z߮yدĮx /:фоAX9GYXL]J~{ qV~|||m3V80waCag TwΗnqK<;!F]qӬx2xSBPPw] ﯠZFcd:[(_i&hW+os]P1GcD*Jfwpa_`0tԩv%vAG8勥Jg^9AܰtYJ슃5/+zZrS x]@]"]*VjVŘ[oEU7y.`Ռ6]qp\m{ј̹Fhئ4*4+z5+՚L Y7dةD5)T]U6*np̣rJ|]]^dXk[Z;7* 9=hUD슅\!!3_;@* Gz)G^vA˕]m]2, `~h o.zzf+Vױy/!vF_S٣N z}!a=a铉~:vaW
883n{~\osrH 㤗Kfp؆\?>׳K<;z%1돟ȰB \蜯'͜PMKA1Npl&
8849׫gGwQOOjk? ׻2R*Wr3ffyI`]ZφJP$qӃk*_nj_xJYR8*9TTŃy.1-GL^D^~s|%Ⱥ鸮cjfNW!ox*[6{tUݴmSWd*zR/?~&92Jaȳt/\? WX2+!|:U^.ވ;IQUy~b++fz5vԄ]m"ؕ7 vE|DYQ= | \]J3OXHaQVUEڭY+ W0<2:۽>0
885b=ʕ=C/aH (oDPmdzVTuòmda9*a bڵTRV:ܓZ9$a p< Nj.ںstkÄ+Vzp֡fj8]/K9;WpB 7z4K^7Zj:lzS//h$sfYleW@_oS
886qܳgҤ WR^\%t\읬C1\͓zR{գi;mUa\+B\#z'iAV3?rH@Ѣs9$HsmY51 Pvf5՚{6ҒUf9yUOr^Nr:Kyz3k<[|>DԊ*fNx:n=7Z!MW%9HBt U:Ui*FROt\a{JrnTFR_n"3Tmp|z~~z;Gk'/>r ˏorotU*qpo</^^^_U&誖Ϭh"ct+tUNֈRO÷y;rnY2k"/7|ݺn]`/aYӹbֺ>xMΫDWu80,R|}8?ۯCWE|<px2+Vw06ۣ~ihb:y>"t}|~~~ZٰSͧAGDW9X2+DF d:_k59G2kVo4[no02zw8Za2z1cMtUx*[l۝֗av۬f~Ka&u؟WHkT7۝Nj>jZ (5lRƭk,pG9}dLgb1zj!۟W*>X*'⻪ 3OD|65tYɧb!>]O*Xc ;Btr.BDXkixbf3Ӝ)r\Ȯz)DWE]DT SrZVZr^k4+7ylok{
887ZiFr;ÇnO]UsWZ}cdYvotUCk=0t: +y>*ՒUUkx-&y'"jZRy1m6z0֪2quٵ?6kyo֫b3s2{z9>]5_mFӹ|.dbx4vR$!MWU|v45}<5gё>z=MӺVV.dr6)*ޯzČ:fhj\̉V*ޯl*FR.B!fRX8Ǖ/Id
888zIWJQ3-Rd"U5.םSb۷V)iY3
889H8 %쾣:DWW|`|\VŬ
890KV8]x2+/j.GáQ=nɪp
891d:uHH[D#bnIy&
892v.FvH4ć5hgub~&[@0o;*Nta}~~/Wҗp ~II*v{Dۓ_ +fqG֯M
893
894q
895/GS0 gs
896472 0 0 526 6485.5 7240.5 cm
897/Im0 Do
898Q
899 endstream endobj 838 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 839 0 obj <</BitsPerComponent 8/ColorSpace/DeviceGray/DecodeParms<</BitsPerComponent 4/Colors 1/Columns 472>>/Filter/FlateDecode/Height 526/Intent/RelativeColorimetric/Length 11417/Name/X/Subtype/Image/Type/XObject/Width 472>>stream
900HviEV$9TE3Bm?̜U!px<=dx l{B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!(|8|4*?3yts"V\!nt~xPN? Jťpqg6O˫kq}}uya%$w^;.r9aʥz$K3hu5W׽RR%egёBK`0=nK_k<;%pk)jz bp'b/d^Y >81k.*Wǒt:@Z)ztA! <(|خ.?OgB.u)b/NG|(A,
901"}o~%'Èk(Η*F\$~NW*[7t&H!yI=S/vzdlju٢JkVbT*҉H+wQUE/U̙ao0)UNY-gaCZ#1Z,fZ5t\U}G+EJ_1}dhtz^iR bVh2jVըV/S˨ (h]Dϥ:44]{Ѱ׮0B SB٨5Z^mլ8;.a2Nsʧ%aPM^v6YYX'ɰ[/g`5KC1j֛p< nf=j<%q\Z>S|vT5g|65+8E`4-Tw}8dzg!@=?U9&A G衉D*\«J`X'|#S8 FrZikk= {Cva|')\.+ET5,ֺ#[L±T\mvzllnWixn5&[{ ղ*RT8 Z>dR|fsRBP.楈SERxZ/gk؏‰lĕ<̗vDM;Jꋋ7|Jzy ?
902#*P[(:hh6jID^O揤KdF mSMJ ^v\MDnܪdehB5e-h<ΈbDhJ]F8=hOW:lD8I\K6.֛aw[&'g*y!.sWn$ 5UDbbVZހѶd2qze+l٬d$Ry3b_T`F1J"aՖ\ݙxDH6֥BJ*VZt:]`KWY,l<C`,k^k4 F$ty+a}~y}}}~a: \fRIHX:dox"B*j;5
903ehu{pda],Wrmnת ~lIM-j! #x!Z^^?V^mJe3T2L=nam'ۉ?
904~]5D/Wi9_V?U^l#~7l*kKsXVETJ~jifVc{uM(}<Y/C۬=LNdmVBdQrV֒˯lUTeb\Kb[*@Q#BǶ(詓*3k aUb:굪 &ǣ&ɨi"{RltQ^
9052_3~Cj90YU~ױoVe8HcDG"lj#͢z
906U07~1Fr'(
907ىa ; aի\*8mv
9086/waVˌ<`jOX,Z>l1r$"AvN
909JR-V*^lҷTw'jkI9{YG泩X~cû}X*WV,P9 1daZy
9108,ޡmݡ[GTT!}vFF4Ɍ'32WIBmԪ$ ֫+(5ĥ@ ۠<%Ѕ +2tfK'/NSXCNZT!E,#OQzB0g- TmT5N%Ѱ^#K堒%4ŢX<A
911S 0ue31`ŜkըӱF {
912XL2Kk7" Q%֥ȥVP^Vc< AYE.Z #H8
913P$Z,RZ3znZ0yCé猅%aݨ2ŀ=qTŒTw;&VQ+ul4z (+e^TDju_[/-{Wpy>^ʖ\
914W&G:z}M&\dn h@[᪸Z)[SY-R9ѧ*qF G+6يZe`PsFڥfR^8.NYC!)ҀUMA%3ڴr=L]
915z8sRk$@jz
916ƹ"QH+حHץpUT.mifi׮z}}@ʪ$PĎ%l' W)an@dJ.-񀘹|: \v)^s2.
917h; UAݬf+5{IZ^^eOT2Մjva{|Ņ\/"LTk0r(0avho&UzL G64)RpȞS7#%OsS ^{Zy0x*tp`(bWԱo,Ei$XӹD C1ݭ6Z\5MzWe/ϳDm\_qfAQWa/,s~0EC`#=nJKU^)i@ ҩ]|ABFU<xQB*2ZT.$V]ݻdUIl*4Ɠ Z&Q`t6cPb|&*j~'z|GU%+]a0l"NBNa
918jcKZ504
919T^]LS5 x r,Ɓc}rUɪZ,!6x[.3q]A%R2U}=3=9$sьѠOXMnZ5]\WXcнmpvlT oQդ>'j/N{LڃeJVAcK߁\>aWɮDs9T_/TA`;C"-R-M\*9S %U*k?M^mV˶ .Knn'sL:KWkj'0H%Xz#jsxx:_Utrb:pd"έJXQMM9+ D~ڠh€:wZJ!э[
920_%~|W<LĚ̕mP%z[ Hud`vZj1T_ogG+uN倵q;V~eD4RU H<3}VKfg8]6v%l<wo[7:k6 .eo*^Q^
9218tZy%Zk4Hk/V<vkۘOvV5MT$^_ 3hKۃ1ǯoƆ
922VKY5O[Ot߮ǭcFVEEV"2d|BRpSout6ە kFfU(JĖJ*M,xA#k%tNFҴ׻z6*Q!E L&u8`D!Bm½x:[,͕Nts64ʪ,9<DV RI8ɰT}|4Lv7~`;Z8&Kg,C$ׯ'u</ 4kYI]׋f3id! Kz 7D
923V&ղ,jM4pƤ)P4J&T:C3l.c?kPg0
924+ܭyܭܰlǶWsXx
925ZU]a&p2"x~#'d:B_k*
9260A( @^n#RfA-h \Эu=ϗy%+c_/X NR /^{{z^ֵY%fMo;>2r9f|^uЮH+_}՗1TxUHq\Gzf0qH>+_wJZg4[X#rkVԂwu)dٟp|{1j/ ltbdΉj=ZጭB{MN]W,Z 'ԍ4E|Aw'=^_^ .ƽF(rwd5RfiDDؚ` w+
927պnk1*3Th 2)frp>_P+co׶VKZ v2LN%YVdPpfzEZmvMrDkЭ墦+iV5ZO Nʘz-Њ5%Z kBjzn[F^o:ttCk" ޙ`'/PB\ټU[h<~FӅl~ZL*Np[S"$f 4b>L&Srvj%pPz;z٬]{e(l?pV!,UPMVomzo
928ap<Bztخms>aB`KgwzlqqdЮE5\ ~C`EoWXکO[`X3Na2栵QV%%Z
929,Y^*UÙi:]]2Q]/ӉXh %I,kplqVNh !X4^ &a,ɨm7j"!8*"~`asb\Gt2;zU/)<k}"ZDT%\oV+
930V\6>!iXBĶ:n'0lDkVA+xEDT5&`[Mae"ZÃUd5R*WkZEG~XЀId*ar岯AzDkH+HM$T*Me,"t+ރcODkkEAMS $+ŢRa
931p7d
932tfe
933Cqךq\eˀX!/ycq%Z
934G+E3HV4E0iMi
935UQdnX+kx`N EYGҷ_xZS{\ժeM%Z3J|_YNTJj5UeQTjh TURzvbE8q_sIq, Q]UxF rH jY\ w7D|' ﮠS= R13-2P1Fh,N3n^ [-!XcFD2LRk~+%P`8(6ЩT*L| JMv/{a3^^.dSWVԩ|X*˕Z~&] ,g۬sןd~!"ЩJh4v?b˭t]S,7Z)ND^]1P‘X^%ix2_{E;v5z9Ah" 1MdX ˶-CSn26k<&1CPt6gYnI t:9QE5B'lS9\7~<1ک_$bgjv{Q a=_ΞcDcZ1 _zdqT-=_|_7+_oӟΜdXm6iܳWV3b8Fb=|٣&ZѺzz]/K[ Y_S9T|E`z߮yدĮx /:фоAX9GYXL]J~{ qV~|||m3V80waCag TwΗnqK<;!F]qӬx2xSBPPw] ﯠZFcd:[(_i&hW+os]P1GcD*Jfwpa_`0tԩv%vAG8勥Jg^9AܰtYJ슃5/+zZrS x]@]"]*VjVŘ[oEU7y.`Ռ6]qp\m{ј̹Fhئ4*4+z5+՚L Y7dةD5)T]U6*np̣rJ|]]^dXk[Z;7* 9=hUD슅\!!3_;@* Gz)G^vA˕]m]2, `~h o.zzf+Vױy/!vF_S٣N z}!a=a铉~:vaW
936n{~\osrH 㤗Kfp؆\?>׳K<;z%1돟ȰB \蜯'͜PMKA1Npl&
9379׫gGwQOOjk? ׻2R*Wr3ffyI`]ZφJP$qӃk*_nj_xJYR8*9TTŃy.1-GL^D^~s|%Ⱥ鸮cjfNW!ox*[6{tUݴmSWd*zR/?~&92Jaȳt/\? WX2+!|:U^.ވ;IQUy~b++fz5vԄ]m"ؕ7 vE|DYQ= | \]J3OXHaQVUEڭY+ W0<2:۽>0
938b=ʕ=C/aH (oDPmdzVTuòmda9*a bڵTRV:ܓZ9$a p< Nj.ںstkÄ+Vzp֡fj8]/K9;WpB 7z4K^7Zj:lzS//h$sfYleW@_oS
939qܳgҤ WR^\%t\읬C1\͓zR{գi;mUa\+B\#z'iAV3?rH@Ѣs9$HsmY51 Pvf5՚{6ҒUf9yUOr^Nr:Kyz3k<[|>DԊ*fNx:n=7Z!MW%9HBt U:Ui*FROt\a{JrnTFR_n"3Tmp|z~~z;Gk'/>r ˏorotU*qpo</^^^_U&誖Ϭh"ct+tUNֈRO÷y;rnY2k"/7|ݺn]`/aYӹbֺ>xMΫDWu80,R|}8?ۯCWE|<px2+Vw06ۣ~ihb:y>"t}|~~~ZٰSͧAGDW9X2+DF d:_k59G2kVo4[no02zw8Za2z1cMtUx*[l۝֗av۬f~Ka&u؟WHkT7۝Nj>jZ (5lRƭk,pG9}dLgb1zj!۟W*>X*'⻪ 3OD|65tYɧb!>]O*Xc ;Btr.BDXkixbf3Ӝ)r\Ȯz)DWE]DT SrZVZr^k4+7ylok{
940ZiFr;ÇnO]UsWZ}cdYvotUCk=0t: +y>*ՒUUkx-&y'"jZRy1m6z0֪2quٵ?6kyo֫b3s2{z9>]5_mFӹ|.dbx4vR$!MWU|v45}<5gё>z=MӺVV.dr6)*ޯzČ:fhj\̉V*ޯl*FR.B!fRX8Ǖ/Id
941zIWJQ3-Rd"U5.םSb۷V)iY3
942H8 %쾣:DWW|`|\VŬ
943KV8]x2+/j.GáQ=nɪp
944d:uHH[D#bnIy&
945v.FvH4ć5hgub~&[@0o;*Nta}~~/Wҗp ~II*v{Dۓ_ +fqG֯M
946
947HN@ i@RrM;'yY{4e1c<O>flc]DZT+A6L65)'|5&`HԂi—#j
948 _=!dMJ<i橫vJ4s\4v>g
949 esӸT>U4g8 mf_,'p3Lk̚uԆͬN)>nu< AOK XKvO=ѣKvyCO+(4QU=EyzBO^+= e)īVS쉖\3<kTO,=S'M=MĻ&{JdOW穧({bÞ6G)STZX7OT\O0(*c (jZZ45QIph']ǀ.gݥ-zPh8G3(`vgCkHڻd|ex8!<c1c1c̛!
950HWcCz
951()RT `&ƶ4ƨIxo'IZ>3{^׽u{ש tU'IM)4_QKUX
952JUE1@t:J!#T-7OR0eP &fsq\f1TJm@4߮J&BH$HRL&J%"âSɤ'pp6 q
953aP7
9540(,q~Pک 6O$Sj.bZm6ۭ]fV)r4r[狤*L 7U͗(6@ yLE ިp;
955h2pqiUDGbx"L'Hm3(B!3ܫ'VL鰚 *M'_&Wljv2!ƇSD.ShnRK,j{k˕ 5\
956#Rn8-8UPݯ4TRtPrTvrzX ZZ\(&RfP8trべvRTc{h8su< k&կAET+Qp239;hcsk{gwwwg{ɣɱS#1\|~"hlBoF#؀iHx8Qd hy_h2'L6vONN?\_ˍ{m
957J8RiXN9GG'fWo?uӗo߾|zwhR1F c19|1$ V%Xt
958n?HmvшעraCpnb6"Q\5t@Ǝk;N4Ha3Sh/_>szXL2( =6-Brf 8AˤW|v=fJ(M <rNLBڀ A/
959դS(qe*a4T2I'9A&,n8(6_6WӉթysЦQr.^oRSJtFe l8箁19huB!K`8uvb4A6tX=>/b) %eC'Qm=tnz~u۷7Wʅhlb.+mhu'Da8:* U3H027:ʉpMf\."Sogu1 .YO۝rL5ٺ}}Tyu듃T& F 6l*@79K$!5Df0OxwKN8:ٽLT*M3Ɉ: +VvX{Dj|"7ͤhMTjZ=%J s_$.<|{ųt<qTLs`Dcdn<]:]o3AWO"39==9Dx~S~LmZ]]]^(<D4WYX-2Ã!äҮZƟ {D1-@b|f{Of2^SjY!aoN$" `RIx``k8vԅlSt6*wbK)lЙ入奅 9.TxIw{AUxxnV?2/>^+G>'4BZVA&XA=
960%sb>Vdw #oﺠƑXc&s77dЮkOa`"j6QX:_TJ$ 3o^s2:ʦW
961Ɔ=O*vـy*f b9Fw7uʠu< 1$ㄠ)(@v>S Kmu$qXL% 4](WjR65̼p9<^p!:X`b#)7ڏ%2(DN\6C;al'
962Hٵ}ѥ-̓yR/%u/ή?9Ufxk%GI\Wc<3G 52;Z _u7Kg҉ۢe 'F]*) E3Im &
963״]Id<t]Tcxx[k߷jLҟl-N}b#D'Hfōx&6O xvR!JD @ierR): 1 ;5(Ntȩ&S]~h7+Ϭbdg&WP2% #9ɍD88U˅u<؍ ý]t< BgL8gBcpTJv?3!Blp2WfX TyDztmHd!btm1Yh `Ͼ`,!9!lKhV+ĽF9UĮ.'3JMʵc6v$(xGgҡǦ.YNd7w,׸orQqZ2>q<{Z n0}lxzy\wJЉz]N̗SPF.M`ٛJׯj>6A-MsG.r
964>(B'K_̸Iu0Ƨ:. }0Fs+
9651^݄Gil̜]+R_/K0(lP.h؏eDd"FIJ%0NnŨ a#N}1L(;H:h~~ylSW6*`(x|=ÎWءS*EN<CsyhQGzR6!sHe0(ۀ<`p"ĄU/oZ3ݬ⍦!4[UL&z 4TNF(@IEp
966ٶ|s 4>u,Rh fIv&G&ycL՛^w)n+i8L
967^4},RdCR&fNy}>Mv+)0/d {<RU+vدč r0Љ}_xN%d ϟ*UWFb:Zw4_?>}xz1mk$ѹ[lmB] 9vE˟?ÚW dl_^^_v5g[r٬fL~@I.ڃv^.ȐqFroq
968uw|Z_аC-J"ݖ.;8c9ѽW;0fs^-aQ%8c7Rj?ӋAVr:1('_ivry9 2)Cq:qZRHdo3;pr\}]ZLGVtxX^- NZ& o Y@q{=Rb FѰj\ct! \nTP8dN"nK5t;$vhױt:l<j\op0NլW\Ƙr%rJ^UDNIjvr@j
969cHcBfH4c2{d4s TFp,F(#v">
970
971S‘bGR
972 yV|8zr](lG9;
973î.Tq 't:J=E\o:/4 0
974q
975/GS0 gs
976296 0 0 91 6647.5 7516.5 cm
977/Im0 Do
978Q
979 endstream endobj 844 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 845 0 obj <</BitsPerComponent 8/ColorSpace/DeviceGray/DecodeParms<</BitsPerComponent 4/Colors 1/Columns 296>>/Filter/FlateDecode/Height 91/Intent/RelativeColorimetric/Length 6141/Name/X/Subtype/Image/Type/XObject/Width 296>>stream
980HWcCz
981()RT `&ƶ4ƨIxo'IZ>3{^׽u{ש tU'IM)4_QKUX
982JUE1@t:J!#T-7OR0eP &fsq\f1TJm@4߮J&BH$HRL&J%"âSɤ'pp6 q
983aP7
9840(,q~Pک 6O$Sj.bZm6ۭ]fV)r4r[狤*L 7U͗(6@ yLE ިp;
985h2pqiUDGbx"L'Hm3(B!3ܫ'VL鰚 *M'_&Wljv2!ƇSD.ShnRK,j{k˕ 5\
986#Rn8-8UPݯ4TRtPrTvrzX ZZ\(&RfP8trべvRTc{h8su< k&կAET+Qp239;hcsk{gwwwg{ɣɱS#1\|~"hlBoF#؀iHx8Qd hy_h2'L6vONN?\_ˍ{m
987J8RiXN9GG'fWo?uӗo߾|zwhR1F c19|1$ V%Xt
988n?HmvшעraCpnb6"Q\5t@Ǝk;N4Ha3Sh/_>szXL2( =6-Brf 8AˤW|v=fJ(M <rNLBڀ A/
989դS(qe*a4T2I'9A&,n8(6_6WӉթysЦQr.^oRSJtFe l8箁19huB!K`8uvb4A6tX=>/b) %eC'Qm=tnz~u۷7Wʅhlb.+mhu'Da8:* U3H027:ʉpMf\."Sogu1 .YO۝rL5ٺ}}Tyu듃T& F 6l*@79K$!5Df0OxwKN8:ٽLT*M3Ɉ: +VvX{Dj|"7ͤhMTjZ=%J s_$.<|{ųt<qTLs`Dcdn<]:]o3AWO"39==9Dx~S~LmZ]]]^(<D4WYX-2Ã!äҮZƟ {D1-@b|f{Of2^SjY!aoN$" `RIx``k8vԅlSt6*wbK)lЙ入奅 9.TxIw{AUxxnV?2/>^+G>'4BZVA&XA=
990%sb>Vdw #oﺠƑXc&s77dЮkOa`"j6QX:_TJ$ 3o^s2:ʦW
991Ɔ=O*vـy*f b9Fw7uʠu< 1$ㄠ)(@v>S Kmu$qXL% 4](WjR65̼p9<^p!:X`b#)7ڏ%2(DN\6C;al'
992Hٵ}ѥ-̓yR/%u/ή?9Ufxk%GI\Wc<3G 52;Z _u7Kg҉ۢe 'F]*) E3Im &
993״]Id<t]Tcxx[k߷jLҟl-N}b#D'Hfōx&6O xvR!JD @ierR): 1 ;5(Ntȩ&S]~h7+Ϭbdg&WP2% #9ɍD88U˅u<؍ ý]t< BgL8gBcpTJv?3!Blp2WfX TyDztmHd!btm1Yh `Ͼ`,!9!lKhV+ĽF9UĮ.'3JMʵc6v$(xGgҡǦ.YNd7w,׸orQqZ2>q<{Z n0}lxzy\wJЉz]N̗SPF.M`ٛJׯj>6A-MsG.r
994>(B'K_̸Iu0Ƨ:. }0Fs+
9951^݄Gil̜]+R_/K0(lP.h؏eDd"FIJ%0NnŨ a#N}1L(;H:h~~ylSW6*`(x|=ÎWءS*EN<CsyhQGzR6!sHe0(ۀ<`p"ĄU/oZ3ݬ⍦!4[UL&z 4TNF(@IEp
996ٶ|s 4>u,Rh fIv&G&ycL՛^w)n+i8L
997^4},RdCR&fNy}>Mv+)0/d {<RU+vدč r0Љ}_xN%d ϟ*UWFb:Zw4_?>}xz1mk$ѹ[lmB] 9vE˟?ÚW dl_^^_v5g[r٬fL~@I.ڃv^.ȐqFroq
998uw|Z_аC-J"ݖ.;8c9ѽW;0fs^-aQ%8c7Rj?ӋAVr:1('_ivry9 2)Cq:qZRHdo3;pr\}]ZLGVtxX^- NZ& o Y@q{=Rb FѰj\ct! \nTP8dN"nK5t;$vhױt:l<j\op0NլW\Ƙr%rJ^UDNIjvr@j
999cHcBfH4c2{d4s TFp,F(#v">
1000
1001S‘bGR
1002 yV|8zr](lG9;
1003î.Tq 't:J=E\o:/4 0
1004H @MM}ZÄ
1005f;q!!#ebH8R#eH9R#H9R#H9R#H9R#5Ƒp4Xr0Xruϯ\ yOM,#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#H9R#!H9R,#!!bb7so
1006H{Lg=PxB)VZ"
1007"iTj a+a5`R7 x"8  Cˈ8E$H!)'%/徯y>{lDZAheA&?c Z+0337701i{B1P{}X[<I ܘC'`kڊawc@V-ށH80?G=N#|Id ͕`0L ݕB!6 |Ґ,! v$
1008t`s<=LOOÝIRHv%@B$S,׏/|f|?_Š@%FkhL7 Cvm" <o6DD,KBapPiX,2*:ƄEICŁ|.E#Y6b E G(MّÊ?älChFHab,N<z,%-=#ӄHOK9vTI\6B!Y0ֈ,oH%WҳO9V3YgNd(͢<la5b!ؒl^D&OJ+T|g4VVzRA^Nj\& d[8azq\uQion^^Z;U7VYZMUƅ^L06FbYۻ<VW\Up~i-߿oֵbu`
1009%чRN_o
1010 A0 gǞ_!Mq3m隦k)2t4"fzЋ1E"8$*Ԃ"^Eu7^ftQ"&y~SiV 9O<೗o=o WΟ0 7w5G/8<lln3ᔌsJs3Rtp={|3q@hHzNrD.;Ksҏ#C64~Q_QC"I"%;)DEw^/H-%:KNoxmO'- E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QFdD~/"H"2[ԵHO[ko%.to&x21q >^8;d%k)kqu,,i]2O//̌wZꊅ^~"~`]T|oڇ<ˑ;͵Eif>X'GSK;{O-[}ޯ[z>yRTZ,ETBzfg3oWV=ff㎛MՅ'BD%CqIU7>}jfn~af^|tFcUxRىx4X1ۙݽCc/&gf_{jvfzjPow3cXF-3&<&ђWlua/'&=51ѡn5;,1D|AaQ 9kC#OƤ;q`׵jGNFjBTXWV"^޾Hj/w^qo_׉K}us],Ϸ[HmD!8%3kvtvuǤk]wo]x07bӇ(d&"Z5:>j+t64_qS.ם7o\mnpV٬)*q*ec0MW;.5zRSc0Ϟ~dRV_[:XmLreU5uRNL\(s-Ih]_V{#CO:jʹ)(txQXp&/Ǟi=#"mĽ!h#b5#f?y*ve:ieeX-)&cLV1"rF
1011KF 6ϝb6nKYF^bNA 0`6y~Yƾ
1012q
1013/GS0 gs
1014274 0 0 303 6622.1162109 7246.1401367 cm
1015/Im0 Do
1016Q
1017 endstream endobj 850 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 851 0 obj <</BitsPerComponent 8/ColorSpace/DeviceGray/DecodeParms<</BitsPerComponent 4/Colors 1/Columns 274>>/Filter/FlateDecode/Height 303/Intent/RelativeColorimetric/Length 4305/Name/X/Subtype/Image/Type/XObject/Width 274>>stream
1018H{Lg=PxB)VZ"
1019"iTj a+a5`R7 x"8  Cˈ8E$H!)'%/徯y>{lDZAheA&?c Z+0337701i{B1P{}X[<I ܘC'`kڊawc@V-ށH80?G=N#|Id ͕`0L ݕB!6 |Ґ,! v$
1020t`s<=LOOÝIRHv%@B$S,׏/|f|?_Š@%FkhL7 Cvm" <o6DD,KBapPiX,2*:ƄEICŁ|.E#Y6b E G(MّÊ?älChFHab,N<z,%-=#ӄHOK9vTI\6B!Y0ֈ,oH%WҳO9V3YgNd(͢<la5b!ؒl^D&OJ+T|g4VVzRA^Nj\& d[8azq\uQion^^Z;U7VYZMUƅ^L06FbYۻ<VW\Up~i-߿oֵbu`
1021%чRN_o
1022 A0 gǞ_!Mq3m隦k)2t4"fzЋ1E"8$*Ԃ"^Eu7^ftQ"&y~SiV 9O<೗o=o WΟ0 7w5G/8<lln3ᔌsJs3Rtp={|3q@hHzNrD.;Ksҏ#C64~Q_QC"I"%;)DEw^/H-%:KNoxmO'- E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QF"E0`(QFdD~/"H"2[ԵHO[ko%.to&x21q >^8;d%k)kqu,,i]2O//̌wZꊅ^~"~`]T|oڇ<ˑ;͵Eif>X'GSK;{O-[}ޯ[z>yRTZ,ETBzfg3oWV=ff㎛MՅ'BD%CqIU7>}jfn~af^|tFcUxRىx4X1ۙݽCc/&gf_{jvfzjPow3cXF-3&<&ђWlua/'&=51ѡn5;,1D|AaQ 9kC#OƤ;q`׵jGNFjBTXWV"^޾Hj/w^qo_׉K}us],Ϸ[HmD!8%3kvtvuǤk]wo]x07bӇ(d&"Z5:>j+t64_qS.ם7o\mnpV٬)*q*ec0MW;.5zRSc0Ϟ~dRV_[:XmLreU5uRNL\(s-Ih]_V{#CO:jʹ)(txQXp&/Ǟi=#"mĽ!h#b5#f?y*ve:ieeX-)&cLV1"rF
1023KF 6ϝb6nKYF^bNA 0`6y~Yƾ
1024Hױ 0CAfDa$ M@ :ߔ())-JAҢ()-JҢ(-JҢ(-JҢO--JK"ƒ-=Ϲ88MCkܗ8ǯ
1025HkY
1026A.W(l1cR@
1027`
1028hco5j
1029EOqiڇjV?)?ch_u6PL'x")y\Y~OcuL!?&х=5prbޓO_} )@߾n|Z_}W~rtq@t.g?ogNm~~k5o
1030=Bϻ,CX#R/di+kwz:yGwzvJ
1031lw-vdZ=E3vfw8m\)ث C26`A6( LJu
1032X ІZՑ`@$uZC . pL U*ZM RMҨb2\P(k`ĔC{KS A%hS
1033E쫢ncKv >Ф6 0
1034q
1035/GS0 gs
1036268 0 0 44 6625.1162109 7475.1401367 cm
1037/Im0 Do
1038Q
1039 endstream endobj 856 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 857 0 obj <</BitsPerComponent 8/ColorSpace/DeviceGray/DecodeParms<</BitsPerComponent 4/Colors 1/Columns 268>>/Filter/FlateDecode/Height 44/Intent/RelativeColorimetric/Length 1219/Name/X/Subtype/Image/Type/XObject/Width 268>>stream
1040HkY
1041A.W(l1cR@
1042`
1043hco5j
1044EOqiڇjV?)?ch_u6PL'x")y\Y~OcuL!?&х=5prbޓO_} )@߾n|Z_}W~rtq@t.g?ogNm~~k5o
1045=Bϻ,CX#R/di+kwz:yGwzvJ
1046lw-vdZ=E3vfw8m\)ث C26`A6( LJu
1047X ІZՑ`@$uZC . pL U*ZM RMҨb2\P(k`ĔC{KS A%hS
1048E쫢ncKv >Ф6 0
1049H F
1050H?'uV7$sL QKBT䆵%*rlk(3`|En}~~}5B)I7F}%Y^F}-iзF
1051胯Z~:koO[.%SMG:~o.qWNA8 },3D9>p2!y ЗF}-i ^F}%YF })IWB}5[0G`_g ~oKRȔB6M%t*S:(!+
1052Hy<{KeXNǾeɞٲg:gR2D#˄K!B"Iɒ%Fi;s}<u?x>d@}S Z\~vVFFfFV
1053;KWVeʯ;Ò
1054dK$AA m pq 
1055 Pk!!A~>^^n.$.ˆ&$["?O)h 0`@daQ1 I,/++#-& @!`$ppmTT@b_PXDL\v+)kZ45  u5Ue
1056r
10574
1058Lu'STRQ'h[XYw8t?]]99pgkmeanjblEPWQRKD
1059!<s..>1BJjZzFfVvvv
1060~fef\HJ;}:2"D()$qC]Mu ᄉ,fRp I)hhY"/`RɈظԴ+WKJ+*Q(/+-Z| ?7'+#-59)!.6:*d()8쒖d_ ޏZI+ ,WR ;'7O߀`3s/].ZRV~f}C㭦۔n56߬V^Vr쌋ɉc#Ï}<\a$5%yY
1061SǞ9v,$Dlhk(+YRF dSXθPT!Y;D<I
1062sN!Q1\+,.khjik ~:ltl Jp=599||l KoOwg{[KS}] d$Łȱo7'{k3#]X,NTX0:@a-[JP'Q:H<q*:.bVuM-w:`hxdt ϼ?PWfg_΀  r܌į#N}+H ȦZńBBZNI] "E'7ģAp~1_XxwH ~[\|͛`f^LON`[o7U"9c"HANVZjx)1!4KFXefWT20w/OF&d_)Fc}b98DÇ?B ݀c4fTf_|$tuk%W2SbH>nv{0~nV+-8yĤ4t-|I@uv[Gw'C179, 0?C+m[Csd2?$Ϟ=jomRVjBld1P[m7 ۃbX K˫hZ;x"UuwL l=ʖRh M~x5?;3=9>
1063"{mn*/s*4>=zJrp`rmXU\|B2
1064چ{C#Ƨ u-]" 8 VVV,lxL(?Bܙ/]ؘhK Xg_kEP1?@<y&BF~QY}<8261=3 o OrƅB&A"d{rnZRlÎv{Ud$NQ恆B,,xIs_ܗ?hnsgJ)eI
1065aR
1066PMԡ\#ʈk%)#eKٳɚc> s络Tw9O<~@?8e C 
1067l ٴ丘ۡ.gľ56c<|}5GtK
1068Xw,t-)nqIJ 4L`B},8dzdldpWWLM޽y1'tKjpMK00urIJF^qEu=Jd's"$I $0'=9~D#X_D<x="$,xx I gw(jBZVA٫֎~H;
1069!2# Ã}oj*J^d<pˇ*a>^T)oyxWIJG,<|&r^V74wP ?13@|Vz]UYAvZ5*,
1070O_+n,Vqn:~m׭Y)H cp @yoTV۽99ƢݏbQAB^[YGps<avHwVE\W\Ā%$%e!nX_$?+yUGoXX`=(@X2:FyDx_65ܣa-3|" )U ¢/ 1UAx<wB\Noi+`/GN)?,)Ymz&V\CPYY E1b,@P@Ɔ0Źć<Zއt
10719.sJ`lP 28{~H-DY0b6,<E,IuPGa)11P0Ե Z;^S ;=G0{ޮ+=M5%<h\qRX0`3sjgY5>dncX]{'GOg;Tx,ۃ ʜԷ<˅İ`0=q%8_^vg ѡ<Z>Qeo+R -_f<4)WiU -]}C<~h,]]:g P[Z" K VR28jx/$QJVQe]SG =_&Gk^g$Qo]vw8~Do6-mšjVڨ
1072FLBƶ#p_p4 sػ] U%iO!:ʲb8<X-ek+(ů[&&CY@̧ _3۹Yn+26R2J۴ (~QCoI(7~Ejk|]GxVUv.Kɩ5:}7(2S^of}6/LF\jgqhMbB`T~aR6Na4 hwzx}6o.M}|78JUNjՊWʀOZYZ̢ER3>6o(xs3ISͭ%ʃ.V4<v98*.5!)v]u$;%6'W;:۔rZy0X&sEu0Q0KRΦ'wC[j@y˃Spcj!\24 LO!,o1F`p# xLO¸n,Hq~<-^8Иk6(i۝ (574JfcluISj5sc[֭ƺp0ИZ).w{񸥰ƦD<*/-.*)sCm5 kifę`Q5>#&)Y
1073)RпxeR_Q~u%iq4؍ʎ}&6^ԧ%1K1`/l$TǍt+p
1074ooTCcvD;Yiʉ 3;h~@4~L! yk{L.?3hawG CmY1n`{.4cLfvAq9FyHmj?#?+)5Z2sؘh=;:- &mh}`F eI[ .@StC G`tҡ_L> 4f-lQK ̷G&eݸG3&񪮢,/#1wK%A3OIc>3w7ӫvK }\HA\ݩ̠J}{|3*;z~K3T[^zbQ]6V!H>JpAqyu];c oWԽBf>Q8#[iŊ6ЀuJuNи WK6xOf=_V?u%dŚe 狀bHt`eh+8\N`F?])чݶlX$5 |{ߊV|C2n|^AVRġMC$h!L\x O:|jy^y'/qg[Hr1Zc rj:&.3>mh~;8Lf񮯳qvXi)K
1075\G nKAiv5V mg&+o
1076Ǵiа~&^Ջ:ʲK G1tb9e,>ie-
1077x A v|
1078#++L[Pk`>a_W n93 6.go=k&Էߪ yo4Pf6Y!ȿWSdU=m eɊΦ"3sH`Sykw{O}[ \(;9gR%)!n6&[nAIEMK`j w7v0:O{lY.;p[Y5]S{p|jf|[ȋDX-[ %CU8P4ظa5]!GȟݿA EcSyw1w<a i}^QfւyԄ~ YF\).oNA0uyPꅅpFCnGϐ:hP47-oZ 씆 a`J)@8@0t~'Tcb4B2 Լ$N0yXy15 ~iOvK>~$aaTh,
10794>WύZF ە P(0$rP9`4,i"9R9(Jˌl\EѠZx8px9AI8M 3VPhfPO7)!n6Fr#+RCkgH5@£_Qr`q,3Ì*p&v^iUS#7ѠZuh$
1080Y
1081
1082vHRR 4. ![dD88Z~<󕗛ػJϿW7HD:hkxRle(!Jg0'&x%g?o!Aqƥ`wS9d\Rno@̅w^vh[:aik(r6gq~NrJ.b8zM\h 1^~zlfpqpV. EMCkCiW˞h}G0zp ֗N:mJ
10830*;|^)y I G7Nzn]*#Bbd/ "J/w=ߺ"sf2EdȔS&D ET
10844g*J
1085X eCDGwf6znkӽ z>|k|QcRѷt O)G-|?c#hɽsx\Q}:#cc.+ px4p8?l(M <.<>թ" ~:<|KjHC*-UEmMEǧ<U!jﯗ" ZrI?s
1086:`=UHe}!#}qve&6.g?H/F<T=Uhz~ gkÕB\ xow {^R~NUokMqo7])'x$ [JzNI卝Q
1087Ӣю&#BW$m+]? NAN觾vqcow3ՒYDOdmH*[>ۏ񎛝pFEq> iCXFhSWӊ`7&?%=* y-S;7cmgЎ;ZU}c\:N.;X(y7I6.h9șZA1xp I$qL8E_6p &8(C8Pm0)A`(@![SM9z
1088@gcyNrbj&ER! b`|JTTCRThJe
1089 >6Ry̜BjF[V*4ʂ'.{W)Uh
1090ɶn>}U+1AhRZUu Jjڻ=] "hVSs Vq9*.MM.kTm&Twƌ2)BA!>nfZr47$Vb302%MsGXp $ر^{(+- 07,x] XFcWSEnRţuy& 27$F+D`pDz: @SPZzߩk_V¹APh28& ?d ,msPGaZԕV*J6Gl1V2SD,@[xZCo=|G_{mq&И½dwHa87 yվz{㬋59-2w .m㏨`go;DCV8S iFGq]mj,[ h̚@Gtz;M]QAP(T1LcFWLaǣ“*>Ai|hٛjQLl:v H i@gCYv|-l|+t͝<#S^mAHX4 vJz.{RP38
1091iF@#};Bc15 ƅt?]WH| )+Wӊ[{Rq aR]cԵ/k 2- FfNAF[Q h|iicQ3q9[vHiХ1%$nlrFS@AX(:H@?S2 h4Ӏ \?SɫiEխat?]BߐNK,v{]gpt &CObg`dʋ-݃#A!h
1092q7Ք[2?0<˵;xI-o;q0F#Oīuh&͚'RPi>IRH(!J!q"RB(,%24i"͉QyNu߰wQ~{uz]z磩0yH*j<ZP۠W~;h"}t![c mH,2s?wyJ~e#l^h(MzjNC^0<v>qM|oFϯhm'h}e9Q78o3Re;ЧIy m!Xe OjXgD ^1yum.gnD%w6_c\q픓+6xDn=x:82!A6@uşޅy9ZQf%ͦ#GDNԵr[P8ڢ7طy"!.m&r ˨t
1093
10941۠Gn t|{ ҂ژ%Hy}'<|QT3
1095` EsB|\miȋ31lcKLnFGN.͎W60XgF'Ɋp#Gry_*%CKF>4򇶁
1096p|A` tս
1097pU8F&n:pT! u}⨁;f>O)lmQXCA|&>M-oAno$+>76pyG \ntpdB6U
1098oE>
1099oFEVT#``$ȪX9FU+8lG'UK{,V;bRa'QLU5-pTtRw6UܦL*NmPFDž;/>W5uQExp7罏fg5vR *Emn=Kίh':ɥgˋTbWXgs#*1UTt4P503ʭ\ktwumW
1100;T<Sn?OΫ
1101 8'?T`@C\^
11028A/x8XVec6hcF9e䶞[En7FeAkAC5PY`%`*  rʩ"x'&%g=JB}×K q
1103F[ |r|Z, 6ȉOةgbQFnbvi4if2>v[)A)19H,Z6O=z~k%ܹwlNPG&aϒrf\5]D2i!.֩1]mb}5/MuPF9wS_0JvT/ee93Hd+%C
1104cI)$5B"(k%$%dm""ٲk_R~<"Ms sݟbbUes9>1}+hb
1105\ln3:#*,4`4Ʒ(1,@~11E>#m R4TW.`w4p̙Ǿ U'p0
1106zq Fcl8Z=0)`k1h|` 9Jk[x8&p
1107jo(vb cw;C$vT?6FZJh2h`uB
1108F$ =q@m$#>\w?'+UIJOx}G݃SU9Tpg\w>dUQRw<A \6nA-΄%d"ߍek&#h`dbXR
1109L@׀k) GYghK,:H8@8p nifw*B>:}{??5|Xg-wL ptֺr',f+劬EE~=QIM3}؟no,zo^-%K8X,"8q:4>q96:^
1110 6:׀_ew%9E}+G*-C>$(X%Q{PԭlcmAV?k#m⟚ԠAUw[؟
1111MEяFХmCeQ c:>T *ث :_}?"ܴo{ Sԧ8^% *aaW
1112u8H
1113q_72ufPՁ@38\4] #*쾩S Wp,Yj 1iU7L@ >(;%*uxϙ?ဿj@'}4#ç8}]UrRc.T\eJv(?3bkP_DRrX;bҼq>'Qi,\
1114Zʁ#9_g#* N- JuH)m5rI)l
1115+BF8aRcuԅ[O_%10"mwk*J /uf1 |>;A!1UԷh3#=,(Is:ECiq2wF<s)6-5vƽA-*u'@L
1116{c}Co8ϊx|qK-嵠۲48V@X;
1117=X vm <;rH#8}/zPP^9q`0z m եF0~@MC
1118!6Tg&EN/ bpH)jgt?nl#A޼,H 8>0H8RؤcrU μx`~R_Qx4jy?:x_M{V3PDe\(NBDʴ\}{G`xARhMl-6.r {D)̉Tذs*O; 2yl|Bɪn3s G pyόV#ɇqVJ%_#f(v$N0:snr+!2C.!TT5$CҀB,)ǐ"t3ʐ1CVfLd.i{=ޜug=-[o.#׷t LZ(Rggiϟ$߸bk,IcK~
1119?mA9  Pj\8ni]AJd=/αG@TZqN.]WZ m9:bj0wK
1120_M0ǒiZ;{!,^*
1121V<F0L`-Uy7:ف*r֬ZW6XDVKVꮃv.烣ϯoǃj8`zIk}p^N@t7oob}3j|jnI 9Ϋ+@iT=I ww4١(S
1122&Eu]#n~72јwx
1123XǃAmȿ-jm
1124?
1125J@cOൄg(p\}$<M'mLd%.[ ?<`׮Sol{/1W"- ƀS#3z!]u%Y lLyZQܡchaz>Gc[=gb``%En`܊ v5߳MAJTp7uRjLOUPQ7jrb_|0K
1126+g NV͆ÿQbjJk
1127+މaSU[mzaIX<\|#Sr7ukm=-LӆzʼlPW m؂a~r̝⪆fjߋQ6gyT('ֵ`߳Gv| }KV 0<l񰴆Bƒ@p
1128>jsCU1*P?k+mRlAoӃoWGEL/" ;QE?RS0#)6"ȡ}Zf"?xqons/$VJvA.F>>B(iHVJMY~V ߳ǭLޮ(+ZX!IJ^UkiOTVx|[+Gx={,d܊
1129s2* /S08cs<(. RXԜB}52 az7Y ѡ,PI)Hm)-E~xCPDRNyǞ&G]GZ}
11302O_ <of&hC}혰K^.z$֭``ƁW
1131\RV.`X{ /\W2[Դt ̑OaicӬ /?R`k1`/Y]e̔hdq@WSUA.)#x,_ו,x5D )+[:{G&` X@" 1*IEQ^ƽЋ@WKm /YR k+!)Hxz_ w?53m2$`P@C v>*-IO rq\ Y A+8br'Dx~8xDM/4w a PY"tĄso1
1132G2Sn߸w YId [L>>!~9 eUud {H& Ijٞ@joV'݌
1133 u?eoiOXxs-%/+^W@BaC&f0n‚*o~'
1134: Dޒ$tRKV߱>by9Cmk
1135r3Sc"}N9XTSƶ{[]a1)9EU= Mw @R3s J*([ک}@2jlLf
1136" (
1137j`Q1
1138.뵭lu~g$_o`0y}ɛDx2?\_]Y;GMqs-jȏMLgHeu}s[Aȕkӷ?Xx_ϯ
1139?7wG53=y} &qa6qf O&I%D9,-,#jX4721#YSml$&A.ّWP":TwhۉށsãʱS7gTgBݹ۪S7ǔÊ{;[ApgT*jfX׃tS$16 Z1(c3@'5M ߼+aϲExU^>195}sJu[JukёaŅ}=][VW-)
1140q
1141/GS0 gs
1142398 0 0 398 6557.1162109 7246.1401367 cm
1143/Im0 Do
1144Q
1145 endstream endobj 862 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 863 0 obj <</BitsPerComponent 8/ColorSpace/DeviceGray/DecodeParms<</BitsPerComponent 4/Colors 1/Columns 398>>/Filter/FlateDecode/Height 398/Intent/RelativeColorimetric/Length 20921/Name/X/Subtype/Image/Type/XObject/Width 398>>stream
1146Hy<{KeXNǾeɞٲg:gR2D#˄K!B"Iɒ%Fi;s}<u?x>d@}S Z\~vVFFfFV
1147;KWVeʯ;Ò
1148dK$AA m pq 
1149 Pk!!A~>^^n.$.ˆ&$["?O)h 0`@daQ1 I,/++#-& @!`$ppmTT@b_PXDL\v+)kZ45  u5Ue
1150r
11514
1152Lu'STRQ'h[XYw8t?]]99pgkmeanjblEPWQRKD
1153!<s..>1BJjZzFfVvvv
1154~fef\HJ;}:2"D()$qC]Mu ᄉ,fRp I)hhY"/`RɈظԴ+WKJ+*Q(/+-Z| ?7'+#-59)!.6:*d()8쒖d_ ޏZI+ ,WR ;'7O߀`3s/].ZRV~f}C㭦۔n56߬V^Vr쌋ɉc#Ï}<\a$5%yY
1155SǞ9v,$Dlhk(+YRF dSXθPT!Y;D<I
1156sN!Q1\+,.khjik ~:ltl Jp=599||l KoOwg{[KS}] d$Łȱo7'{k3#]X,NTX0:@a-[JP'Q:H<q*:.bVuM-w:`hxdt ϼ?PWfg_΀  r܌į#N}+H ȦZńBBZNI] "E'7ģAp~1_XxwH ~[\|͛`f^LON`[o7U"9c"HANVZjx)1!4KFXefWT20w/OF&d_)Fc}b98DÇ?B ݀c4fTf_|$tuk%W2SbH>nv{0~nV+-8yĤ4t-|I@uv[Gw'C179, 0?C+m[Csd2?$Ϟ=jomRVjBld1P[m7 ۃbX K˫hZ;x"UuwL l=ʖRh M~x5?;3=9>
1157"{mn*/s*4>=zJrp`rmXU\|B2
1158چ{C#Ƨ u-]" 8 VVV,lxL(?Bܙ/]ؘhK Xg_kEP1?@<y&BF~QY}<8261=3 o OrƅB&A"d{rnZRlÎv{Ud$NQ恆B,,xIs_ܗ?hnsgJ)eI
1159aR
1160PMԡ\#ʈk%)#eKٳɚc> s络Tw9O<~@?8e C 
1161l ٴ丘ۡ.gľ56c<|}5GtK
1162Xw,t-)nqIJ 4L`B},8dzdldpWWLM޽y1'tKjpMK00urIJF^qEu=Jd's"$I $0'=9~D#X_D<x="$,xx I gw(jBZVA٫֎~H;
1163!2# Ã}oj*J^d<pˇ*a>^T)oyxWIJG,<|&r^V74wP ?13@|Vz]UYAvZ5*,
1164O_+n,Vqn:~m׭Y)H cp @yoTV۽99ƢݏbQAB^[YGps<avHwVE\W\Ā%$%e!nX_$?+yUGoXX`=(@X2:FyDx_65ܣa-3|" )U ¢/ 1UAx<wB\Noi+`/GN)?,)Ymz&V\CPYY E1b,@P@Ɔ0Źć<Zއt
11659.sJ`lP 28{~H-DY0b6,<E,IuPGa)11P0Ե Z;^S ;=G0{ޮ+=M5%<h\qRX0`3sjgY5>dncX]{'GOg;Tx,ۃ ʜԷ<˅İ`0=q%8_^vg ѡ<Z>Qeo+R -_f<4)WiU -]}C<~h,]]:g P[Z" K VR28jx/$QJVQe]SG =_&Gk^g$Qo]vw8~Do6-mšjVڨ
1166FLBƶ#p_p4 sػ] U%iO!:ʲb8<X-ek+(ů[&&CY@̧ _3۹Yn+26R2J۴ (~QCoI(7~Ejk|]GxVUv.Kɩ5:}7(2S^of}6/LF\jgqhMbB`T~aR6Na4 hwzx}6o.M}|78JUNjՊWʀOZYZ̢ER3>6o(xs3ISͭ%ʃ.V4<v98*.5!)v]u$;%6'W;:۔rZy0X&sEu0Q0KRΦ'wC[j@y˃Spcj!\24 LO!,o1F`p# xLO¸n,Hq~<-^8Иk6(i۝ (574JfcluISj5sc[֭ƺp0ИZ).w{񸥰ƦD<*/-.*)sCm5 kifę`Q5>#&)Y
1167)RпxeR_Q~u%iq4؍ʎ}&6^ԧ%1K1`/l$TǍt+p
1168ooTCcvD;Yiʉ 3;h~@4~L! yk{L.?3hawG CmY1n`{.4cLfvAq9FyHmj?#?+)5Z2sؘh=;:- &mh}`F eI[ .@StC G`tҡ_L> 4f-lQK ̷G&eݸG3&񪮢,/#1wK%A3OIc>3w7ӫvK }\HA\ݩ̠J}{|3*;z~K3T[^zbQ]6V!H>JpAqyu];c oWԽBf>Q8#[iŊ6ЀuJuNи WK6xOf=_V?u%dŚe 狀bHt`eh+8\N`F?])чݶlX$5 |{ߊV|C2n|^AVRġMC$h!L\x O:|jy^y'/qg[Hr1Zc rj:&.3>mh~;8Lf񮯳qvXi)K
1169\G nKAiv5V mg&+o
1170Ǵiа~&^Ջ:ʲK G1tb9e,>ie-
1171x A v|
1172#++L[Pk`>a_W n93 6.go=k&Էߪ yo4Pf6Y!ȿWSdU=m eɊΦ"3sH`Sykw{O}[ \(;9gR%)!n6&[nAIEMK`j w7v0:O{lY.;p[Y5]S{p|jf|[ȋDX-[ %CU8P4ظa5]!GȟݿA EcSyw1w<a i}^QfւyԄ~ YF\).oNA0uyPꅅpFCnGϐ:hP47-oZ 씆 a`J)@8@0t~'Tcb4B2 Լ$N0yXy15 ~iOvK>~$aaTh,
11734>WύZF ە P(0$rP9`4,i"9R9(Jˌl\EѠZx8px9AI8M 3VPhfPO7)!n6Fr#+RCkgH5@£_Qr`q,3Ì*p&v^iUS#7ѠZuh$
1174Y
1175
1176vHRR 4. ![dD88Z~<󕗛ػJϿW7HD:hkxRle(!Jg0'&x%g?o!Aqƥ`wS9d\Rno@̅w^vh[:aik(r6gq~NrJ.b8zM\h 1^~zlfpqpV. EMCkCiW˞h}G0zp ֗N:mJ
11770*;|^)y I G7Nzn]*#Bbd/ "J/w=ߺ"sf2EdȔS&D ET
11784g*J
1179X eCDGwf6znkӽ z>|k|QcRѷt O)G-|?c#hɽsx\Q}:#cc.+ px4p8?l(M <.<>թ" ~:<|KjHC*-UEmMEǧ<U!jﯗ" ZrI?s
1180:`=UHe}!#}qve&6.g?H/F<T=Uhz~ gkÕB\ xow {^R~NUokMqo7])'x$ [JzNI卝Q
1181Ӣю&#BW$m+]? NAN觾vqcow3ՒYDOdmH*[>ۏ񎛝pFEq> iCXFhSWӊ`7&?%=* y-S;7cmgЎ;ZU}c\:N.;X(y7I6.h9șZA1xp I$qL8E_6p &8(C8Pm0)A`(@![SM9z
1182@gcyNrbj&ER! b`|JTTCRThJe
1183 >6Ry̜BjF[V*4ʂ'.{W)Uh
1184ɶn>}U+1AhRZUu Jjڻ=] "hVSs Vq9*.MM.kTm&Twƌ2)BA!>nfZr47$Vb302%MsGXp $ر^{(+- 07,x] XFcWSEnRţuy& 27$F+D`pDz: @SPZzߩk_V¹APh28& ?d ,msPGaZԕV*J6Gl1V2SD,@[xZCo=|G_{mq&И½dwHa87 yվz{㬋59-2w .m㏨`go;DCV8S iFGq]mj,[ h̚@Gtz;M]QAP(T1LcFWLaǣ“*>Ai|hٛjQLl:v H i@gCYv|-l|+t͝<#S^mAHX4 vJz.{RP38
1185iF@#};Bc15 ƅt?]WH| )+Wӊ[{Rq aR]cԵ/k 2- FfNAF[Q h|iicQ3q9[vHiХ1%$nlrFS@AX(:H@?S2 h4Ӏ \?SɫiEխat?]BߐNK,v{]gpt &CObg`dʋ-݃#A!h
1186q7Ք[2?0<˵;xI-o;q0F#Oīuh&͚'RPi>IRH(!J!q"RB(,%24i"͉QyNu߰wQ~{uz]z磩0yH*j<ZP۠W~;h"}t![c mH,2s?wyJ~e#l^h(MzjNC^0<v>qM|oFϯhm'h}e9Q78o3Re;ЧIy m!Xe OjXgD ^1yum.gnD%w6_c\q픓+6xDn=x:82!A6@uşޅy9ZQf%ͦ#GDNԵr[P8ڢ7طy"!.m&r ˨t
1187
11881۠Gn t|{ ҂ژ%Hy}'<|QT3
1189` EsB|\miȋ31lcKLnFGN.͎W60XgF'Ɋp#Gry_*%CKF>4򇶁
1190p|A` tս
1191pU8F&n:pT! u}⨁;f>O)lmQXCA|&>M-oAno$+>76pyG \ntpdB6U
1192oE>
1193oFEVT#``$ȪX9FU+8lG'UK{,V;bRa'QLU5-pTtRw6UܦL*NmPFDž;/>W5uQExp7罏fg5vR *Emn=Kίh':ɥgˋTbWXgs#*1UTt4P503ʭ\ktwumW
1194;T<Sn?OΫ
1195 8'?T`@C\^
11968A/x8XVec6hcF9e䶞[En7FeAkAC5PY`%`*  rʩ"x'&%g=JB}×K q
1197F[ |r|Z, 6ȉOةgbQFnbvi4if2>v[)A)19H,Z6O=z~k%ܹwlNPG&aϒrf\5]D2i!.֩1]mb}5/MuPF9wS_0JvT/ee93Hd+%C
1198cI)$5B"(k%$%dm""ٲk_R~<"Ms sݟbbUes9>1}+hb
1199\ln3:#*,4`4Ʒ(1,@~11E>#m R4TW.`w4p̙Ǿ U'p0
1200zq Fcl8Z=0)`k1h|` 9Jk[x8&p
1201jo(vb cw;C$vT?6FZJh2h`uB
1202F$ =q@m$#>\w?'+UIJOx}G݃SU9Tpg\w>dUQRw<A \6nA-΄%d"ߍek&#h`dbXR
1203L@׀k) GYghK,:H8@8p nifw*B>:}{??5|Xg-wL ptֺr',f+劬EE~=QIM3}؟no,zo^-%K8X,"8q:4>q96:^
1204 6:׀_ew%9E}+G*-C>$(X%Q{PԭlcmAV?k#m⟚ԠAUw[؟
1205MEяFХmCeQ c:>T *ث :_}?"ܴo{ Sԧ8^% *aaW
1206u8H
1207q_72ufPՁ@38\4] #*쾩S Wp,Yj 1iU7L@ >(;%*uxϙ?ဿj@'}4#ç8}]UrRc.T\eJv(?3bkP_DRrX;bҼq>'Qi,\
1208Zʁ#9_g#* N- JuH)m5rI)l
1209+BF8aRcuԅ[O_%10"mwk*J /uf1 |>;A!1UԷh3#=,(Is:ECiq2wF<s)6-5vƽA-*u'@L
1210{c}Co8ϊx|qK-嵠۲48V@X;
1211=X vm <;rH#8}/zPP^9q`0z m եF0~@MC
1212!6Tg&EN/ bpH)jgt?nl#A޼,H 8>0H8RؤcrU μx`~R_Qx4jy?:x_M{V3PDe\(NBDʴ\}{G`xARhMl-6.r {D)̉Tذs*O; 2yl|Bɪn3s G pyόV#ɇqVJ%_#f(v$N0:snr+!2C.!TT5$CҀB,)ǐ"t3ʐ1CVfLd.i{=ޜug=-[o.#׷t LZ(Rggiϟ$߸bk,IcK~
1213?mA9  Pj\8ni]AJd=/αG@TZqN.]WZ m9:bj0wK
1214_M0ǒiZ;{!,^*
1215V<F0L`-Uy7:ف*r֬ZW6XDVKVꮃv.烣ϯoǃj8`zIk}p^N@t7oob}3j|jnI 9Ϋ+@iT=I ww4١(S
1216&Eu]#n~72јwx
1217XǃAmȿ-jm
1218?
1219J@cOൄg(p\}$<M'mLd%.[ ?<`׮Sol{/1W"- ƀS#3z!]u%Y lLyZQܡchaz>Gc[=gb``%En`܊ v5߳MAJTp7uRjLOUPQ7jrb_|0K
1220+g NV͆ÿQbjJk
1221+މaSU[mzaIX<\|#Sr7ukm=-LӆzʼlPW m؂a~r̝⪆fjߋQ6gyT('ֵ`߳Gv| }KV 0<l񰴆Bƒ@p
1222>jsCU1*P?k+mRlAoӃoWGEL/" ;QE?RS0#)6"ȡ}Zf"?xqons/$VJvA.F>>B(iHVJMY~V ߳ǭLޮ(+ZX!IJ^UkiOTVx|[+Gx={,d܊
1223s2* /S08cs<(. RXԜB}52 az7Y ѡ,PI)Hm)-E~xCPDRNyǞ&G]GZ}
12242O_ <of&hC}혰K^.z$֭``ƁW
1225\RV.`X{ /\W2[Դt ̑OaicӬ /?R`k1`/Y]e̔hdq@WSUA.)#x,_ו,x5D )+[:{G&` X@" 1*IEQ^ƽЋ@WKm /YR k+!)Hxz_ w?53m2$`P@C v>*-IO rq\ Y A+8br'Dx~8xDM/4w a PY"tĄso1
1226G2Sn߸w YId [L>>!~9 eUud {H& Ijٞ@joV'݌
1227 u?eoiOXxs-%/+^W@BaC&f0n‚*o~'
1228: Dޒ$tRKV߱>by9Cmk
1229r3Sc"}N9XTSƶ{[]a1)9EU= Mw @R3s J*([ک}@2jlLf
1230" (
1231j`Q1
1232.뵭lu~g$_o`0y}ɛDx2?\_]Y;GMqs-jȏMLgHeu}s[Aȕkӷ?Xx_ϯ
1233?7wG53=y} &qa6qf O&I%D9,-,#jX4721#YSml$&A.ّWP":TwhۉށsãʱS7gTgBݹ۪S7ǔÊ{;[ApgT*jfX׃tS$16 Z1(c3@'5M ߼+aϲExU^>195}sJu[JukёaŅ}=][VW-)
1234H #7
1235d}4 !#чCۧOD_ϟGxt/p+u%nD_:M[C$ч2}0#_.N3 }<c/.4
1236E6(BPd"+٠
1237UV(BlPd*+Y
1238E6BPd*+YUV(BlPd"TY
1239E6BlPd"TY
1240U6(B Pd*+YEVAlPd*YEVAlPd*+٠
1241U6(B Pe"TYEVA Pe"TYE6B lPe*٠
1242U6(AlPe"TYU6(AlPe"TYU6(AlPe"TYU6A Pe*T٠U6B lPe"T٠
1243U6A lPe"T٠UVA lPe*T٠U6A lPe*T٠U6A lPe*T٠U6A lPeGlPe*T٠U6A lPe*T٠U6AUU6A lPe* <,(@ lPe* <,(@ lPe* <e>_ lPe* <e>_ lPeG~\U٠D\T٠Dq>\T٠F.alPe* |GA>\T٠_D.1lPe/#U67|*TYe>@ \=ʻS˼*<Y;{6rwVe#ycU۪eӵUeUQ.G.,B2o/E.f,b2oe둫7*yD.ު\=[x3rPe#y*yu#"WyuC*ymc"Wyi"yi*y]"WyY#yYC+yMc#WyM+yE#WyA#yA7T.j\k)rr[2U^ƍ˼[+y Fn\ P̴ ̬IˌV̜yˌʐ̘̈<e\ɘU
1244\晰e\Ye\)eNсEp8:G~`tڟ_+CYGq$:GD'q_9 3/Gc~~ tʯ5CCs:@'|~ϢyS]A-:5[]E#+϶C{ f\
1245usK~otwm>хƠ_\gǕmF\f,EYF\ˡ܃~u-t.Nq+EF:8:,yASgCg&ПϧзOE >E?2.p?5E}gB׸z"я24G.3}D u[c~mCt6Egjkt'7.-S@_sSDG}oE-*lQ`{أ&k-
1246Hy<swk)a,c[ckK]R%e)BTԡVɉD*ʖȖ%[,Jۭ{۹7تxt۹ן13;"""~wLMEp;M&}Mk.Gz#ut8|2",&_A |;Ff`/6^ZdYY988vnbggceE∛Ƭ y!L/Z/]66v]ĹDEvDZ̹h"mcv1]n/
12475!K5E㙕΋tET\Bre2T'Reee-^")!.&JAHq)Ԅ/,80'
1248.•WT)khjjiiϙ2MIQA
1249Rb"B|<܋9'Y$=ůY1`د0EL\Rj U^q9073562]B[(Olq&3IwbOb$ )()͚vN]\]]f .8oprt_gfJKsScC}]mMu<u5:pi8IDd!1 eJ4U &f \7{nz5oV/M]{N- 8YzrJB1Ii9E
1250
1251aѲA~vr\3fZPD\ZVQy70$<Sgf^UR^USSF.ȾÇBd{$0X?{P[]y0*l:Ña^
1252ʚz&Vk\=}ęW߫mlFa/../ Y#W/FA6pNQA^vFZm.-/灃ZSfK1u:B£q’
1253qk{W/(
1254_BšFXaAvzr|LxϒLhB׮EΙcAq)m* w
1255OF)FZ;CfwO܌i ֦U
1256#C\[LPٶIFJ\DP
1257wil/ݼUPu1#oIcҟnoixV]Qs#츾pFq?j50»XȸGP]}Q3!fH1Ն]{;⺯ @[m'\Ӧr YO5_?͆i['Ok[;{̈'0#i0Ɔ= u%yB=lM DAx3gi"k`ÇE0s UXVY 1Sç5]4huqC<lOg5"KA<S8cH<|.GZ 3vƌӲ@ 0SO*QA& nyQ JF (+%|ɂ3ygpi;s%ťdaWcƗqbZNqyu}S[5xQO&'aƺ4
1258gsc}mUM2Bmeb!QIMʪq,f\SO$c47zd8YOkvuW.[4m63uY#Y[lu
1259jۢ>MS\QSߌSb<iG7744ww{S} ✈9ېTQ -LhL 25%H6xs7"UOjč97T<{8Z2صYVJLig:[0΃d-,&%y)kGP\?c|@#qqt5M둶g+13y?MjZMg<@0z ~čV4ΰR[߃ k03<TQ.XH{Xػ\JH.*G}EbL?8WeEz9ےtam ̛Ǟqf<XHֺF$[g";]Me<MT_ #
1260U߉sw{c]ei^zbLV9)1lgF KmQ3w IL+k0FęP$'5>2Xa+hq31̓Yd:eCf6^A9%kں#ar_gˋLmwZ{׈A;&&l=k:L֢',ܑ3 k^tن1:緯G^v4W'Fؑ# cG63fχiوd_VUrh[aq=@w[#vkV'8C; qfukSm kB?n٭yfuc[mÜ?9 k;#)693%p'aq ٹ#y7NC8gvܴΞv*')l1X3<|hv^=3WoƧ>kYBg+YӏA O+2oQ⬮qy,nmg΅%%W)1IO٭g;aO huB_sf<Xڸ
1261f>wK-I52vXaD] nbikJ'd ټ{ɳN^ףQ#C{Pٲeyi<ءV[%1*5Z^I!/vJ42dUmXa(I1֦GTڰg`9+_@H\Za>]3"?y'r + 975.AU%y rL x`kSkg'Ϛ: SVD#G65 O $F]v4>OyТM]W,uC97<vsH#3EAu%n\65ܥNBX6]SPPTjvuQ
1262+j{_9<4psfjقʙ6Z$$wuv ]dhq!v4H
1263<oq쐪䊥 <9S*.auPG~uWVf79!4ɱW.X@9oX#
126456m\%e!jl^ Gy=aکB9SAZl`0'7fvcPAIOꚻ Ga>dnvM`GE@ z6u]c WBn!5ؚ_ĝ|OSݤ#GBCYBEc\ELddI]
1265-x ),Ckɾc_ᖚ~s;LWg{~ޯ7ZW^9>줷
1266Tm^Td2k-wG'n_k~?5?I/# ޼xcJU% dƂRrxW\Rƃe-}C Θkӛ^,{+!/e&Uj
1267҂j>s?^Ϧ׵u ךjOh.}{fc`QE%!kZ;y x#!T~p_Ɔ;[k˞=H =vp:lQ "fdrw5@%k֬`=62VW^LJ}YTys 3;d-3[>A@n`V2~YA6,
1268jϩڠ$')&"p?lnL=IiMKg?dd~? YhUܸ b-d_p̵@[Y`  Qwrw1T& O!oؤ|(w{ UWE~J lkf,0
1269 dC
1270nAUi_9YPL ǥdP+h=\<8@XTOg\ #`ePAsrv.(\95,膋*?3)6
1271CY0iO~phMZr
1272
1273EA1Ow4UQ)jamU3ryA^kȩ/[
1274L)CemvպmιmX{W?x<tV_CQ0z;}ZPdjA舢2 幉Of{R[MVa FQ/ai&w%w~ zB춚1\-T~elz ̝}gU^͠M4WF]xZoJ |1 xOD_Oce xX#La`FՋi ^nc3ն} P^Ő:{(ogs Eq~Q/Z6^Q9TR *[z?gzj`' o"SFLZQ̜BR5I98> k w@{mI&"`Fvnزk4:y?ի 5 poseAJdUS?o[5^QZ'l܋HzתqHJܭ~9c+'2,8s.7Cb^ gNަG~^y1^6e  e.aUvW4yCܗ69 )NfeLFYBiøA2Wσ}5fQQ1Z@X|OӇ<xMٜRb߰tI(s(.kEtM3)J/fMʲj:fW
1275ZfFTE~ʳvڪ2\,KyY^
1276|l ZʞCYFMc 3t!="%DGʞ~#K72  欸\hȋ2lXHQgQ(c+$Z+ Rfcrx׎[_k֬zZeqF9e @Y;K3cB|+u"TBҪڦv^
1277p0n\̰{e`Sw (c)fOvԕ~#",q/:-[vkZXPNʞ8M;V(Io^ #*OجR2W@{mq`&#LOWFf#+T
1278.l:&NhF9\ڎA
1279h_kUAӀ+7f݋WL^M=f>i"a]fL2(9ڥibͨmc{a+0S#y1_q3,^>!Ȍ30/_<=9>؁){SmȿP_pae`똕݈ʖQ00*ωu9 _6^[TM!zUR@[!g.F݋GTn99(c,15U_
1280 Sj2BU6Z؛<d|᷀gm{1fȿZ`la!/JIe)Gz^̬Gzښhࠤf081w&,;6ua.W69$wizFՠ
1281{Ak2?鉿NA&63N>exȽ>ؿA^'g [Lgd$)o(llЛPeRP
1282 [Z0ȿ*;&,T>q=Pa1g:eG
1283VvSyŕ"g@ac4KlRas6(l\,{6 <İAac:l'e9YHa3oW4 J̫'w.[EyXUk@SHZUwHlVYc7(lLi`GmqzTv~v<hY38(16CƲoSB^0#gO\q+iE5ReT%>s;oOn7 =ͺ3iG حep҆n<(ll\5EiWTccX0#gKXV][a {G&᠕n(|຃- (#Kw䂪IPsbCnBحKge-L:;C;*:s@ Prʞh*Hw4BԂ>9T.vT(lz"a8#RƇvJ/x./߀&{-|㢙 ƯfYVYy}RX>023޼ u1?yY6
1284~URׅ'y|0]+#‡>˴Ig;$6>`Ga?Ȗ"J^Ey٘|0~J
1285(KM%˂tDMPX JzAP09{Mt=g3s]W%! \]H,ffzrż\<js׊XM.^[3jyXƇԲk@tJ~eXB(ў/:b'[ZƱʪygעZ%\j"MA-S2mݱ"n5tZ#\[eg&+Ê[_cd{{Gk< }!pgCYNRĹ'ޱ)(c0olf2ʋߔ?w#{/L-,z#(6m`2$yaf2/9
1286,Rm[h*ogVѳr I+i@\R3zKN
1287|쌴N)23Q tHA)R0
1288RPJM [bߴVy3>q#萂)xwCu%Bl)MLu!~z7= H;JɊ0eU[9l{^nESۙH
1289|MyQYOxRNR1_Dy# GDVlxbvYC0R._WބcU3K.Ŕ!e * ;,!)Õ`xe[[YÓH|2Nգ^!2K;2t!*`kLs PDʐf2=5eϐ: _EqAz*҂dxg eW#(YH*Sc=r;Q1=Pn)L tUƔ*3q
1290JӳvK/m@ʐei3Ph.HpQ
1291i*Р RH$dPdqoEua۶}z׿ps}m7Аo?*hZ;܈{KkhW[*?޿h.+H&6^y ;^M/n[Dl}yb7aj<K4 e^Us7yd ZFj}s]UiA.?ѵ#$;~&"ZSЖ:˲߽tbeR9Yh-(ga򾢱D ZO;J p۳yRI-s!k~΁oPˠfׯ>^[wd?3?Y8T_| -e<}h8;3-sK,]cxے+@ԏ/_u6R]4ef>qUƻ\QT7ZSF{ZcqڱAS^H-g`f_$eh{3/#?d'prwSUWO9ZX"H2$Ll"v8^P38^)R1
1292"7%&źB[f^/󪚺QG@g}yNRT~s]UiA.yZfd]gpLJnEc -wԕf=s}fmIN.AiU]QIQT{mqfBQ;5, t-wf~
1293|1O^ OSbB,kztu֯F" .pG]gN7UAKoQI9@pxeć3]Tr&/{"ߖԶ CFY.Hli E/qƻ\zK+f\:Ɗr2Аec&_4_qә򪚺`q,e?q`7Y+um^1)?5taCh\lZYf/Ζ}/F>*7 Agգ6,<aP^cȅO@ ruYh6H0)hmtf"fgb,S 惞90dc;,\Ge.LL7tD$-m3{BnOlYƶnƽ Agy{!ގV2mEWlSs+Hx?kiֳK'f#$\oߕudc;5͓ڙY*)2,<R*kMw Ka;)$bSeˇ84R}afW\ih}*$
1294@63Ge'EyܦDxYF+RAI(A˘
1295VJwcLZ0,S)VnrO,irhO(UJ*#GU0
1296ʼs)i8a^U6/19 =ODʬ9u#- dD823/U~A/8X'{ T"|f
1297 _;O_SSoY'ポ^ce.+|!c7Rs׶M1:gT_kջCKEjEl
1298g 4uԁV& p/qR7Z?02!UY]'S,)~vR_UzEиpLX@aΨ̤3wLKQBpA\^dɹc
1299Akzrt=Q[.]{0VշDՔխ}#D3ku=Ou1Ql^lL9y~;#*P+MKfQw/BƔ-:eIM[(q!\Y,9.; ]e0R^aLtғOMC_!,
1300_'^8Ql @yvL.]vG@čԜ5fro碬WnZE3ˡO * ,
1301_ukA63'7ALNhþo>)0@fe͖( r/2\|Rʺ+mw`gvX.(/pF`fc!k߾#)33QV Q9ETt-vhvcI33<e?2Vٜ<@KjF& L ^߿}i,ؘ0K0_N|[afj&"(JOD,(c
1302|f}eW`gfF(7U>K;,( >J[Cgd}v6sq47- /jfm{]KysKW/ݍދ sݴJ_,|R:ֻ~eui(`&FڪKrRoFz:n0efd˹+
1303+{ f&]mg*-B (l̒JfJL-m!BcBpm*~x="`zcMy*QF- &f`/4OȚWT7ݾtv?5(/WHBqg/K5;Pn,zoGn]k!'NeL
1304ضXSE 3']S|'͇Q"l׭%9z6AV7E ,$k
1305+fTH}=Q1/3)&Q/uZ(3k
1306]ާrJ[ag3.}]Y<%><`vD$ig*`n~!1Iyag3,}>7-bAg[ =zeJ2rv62ƆoY\C^2.`2z>AH};AA<=9u̴i׋0C:{-wag3,S>.j2bN"RJf u4<3}>婉6}-Ļv}l9 _35ql0 5fR"l<2y(Pt)|D T<Z_M} leggV4v ag13?5^[&#)&ߍ4U/ҙ):`9%U-=CgGΆO_ }^0.٨g$e)mnQ͟e޼pެ_ʳ <q_@ص:F' _3=B~Ȉzîk~M^ 2jz6ާ.|)߿Fԓ{qz8l0RO_gfG=[^c{ÿFJs
1307{̴'Ч F^;uUeDؙT2q\2j L`O>`DٽP]N\^}]lQU]sk'Y#S4n^|9}:cME a>.z5~f ,7E%fU6v @Ѧ]fuyW~;QҢh_xgs K(j9 ^sNIUs1|4 v)`^ Yϟ8fw1ݞ2~fDqllRҚ^h`̏ʢԄ W5]ż`Nꭴv<~5Iއ:kUЧ<WUIN`?7)"#}l0 V9{ml^=53bne"MEqs"sJQhC/&(hMG&WN zؕ9%"e~;b`i9şpцg:$o/JyҀ1ŐykVY/>_C$*4!a59hTBqNr!#FNIu{!zwxΓy_ИYUh
1308# t՗e$Dy;W_CIfFL3ň9܋K.nBDc!P=m ;Wmoߨ"')71aL10mcӞא)Amzr4
1309̜Q(# L\FQ]o'_/mB1
1310\+h<$R?c_(C]-%y,kMe 6/
1311fxŀhoeaM$2~
131299&ݑ`(#!~(I6+
13130kBqw}E DW]IVR@ y`c'!C/)kS] eYI~䇚 ì28
1314Y@e\Շc~ɐ{;kK EyC@3|~h)L/#-dv<6f9oÌsio. [B.cb&rKk;{Q9 z(`_7A _htRfnIMSGQPYq՞`̘G`V
1315q32d
1316f.~aemuߑ_+@omi6[W.L~Q]Xl\ <},$tM{\}>My_ZZ{j6?d\?a[GCE^z237+T5t|~,ƶ)ôm]_QlJInٜ c&yb@́] NL)mǙ|H[זgq~íd
1317U f/ dwukrOGK}%Xku?SN25q/&-~sl6wC cIۦ 2R֍e"]p1߭qj$OcI48sk/sxaQos+[ ~fyF1k+
1318ߓR?loo6uKā[Sښi!c Z6JZuY3 ֕s>.Eb[3w[6<yWKBPжYi) Fʚ(8 
1319]s[3y[6*a9X:y\u?&XXq%mlY3-ζr#9<dE9]8Zo)x;ͬ흽V7 <LǸ8AN
1320t)O5E9I1~6:ʲbdidbq ;{E%=y_U C>Nh<kˋr3co^dki|`ʶpZO 3!Ϋ *Z;܁\PF"jMO0n(~(%."sPZjқ7ii`+
1321lݦqūask(US%Ќjq|d*kM׬y5cXq^x9\ajw\Co")hfUxwv`7#yW-[4L f;3OKW&&[ #R#>ګ<{Y
1322RsqΛ}=cEV
1323KG;(2HAX{fV5Zcoq\錅 \֨?̓L`<N.\ۢT1qp ̜— -=zq^b۱#h}]m턌YˣZdŅ&A&g߸EZAuG7ȸҪ&8Ġf4"u<Hlm$\.e9 aXe=L 3\a еf&1E5M}IzqoM1FUMh~Yݰn0^9Cʚ9sJ+ <&1-YQYu}3[߸ĸxb ;#9.\ "1^3YCmz^+("!ͭ=oNHɄ⮬%@ = [H3A1li)ARlD7lƫZgF뙓k 7ᬩgdfuop$*rRF47)b:1jA*1TunVZbLx\ ctX/@ y&5k03>ð>]CNnѿ>A =I4xxPS9TuxF5kpm0|2;5t<w<uMmw|}-OB tk+K!Fz\>oejjB6z<|bwkYx+/I
1324YtCSk!=4 &s鼄/FQ@Bz:Ôب@kΎv͎bMJLXe~1kC8\Wشy=z-9\  .-F]=}PT#kYX3~"^(vwkK
1325'D@ hVQ^h!|Ɵ3ZШqŤU59aim}_IstUM=Acӵ7cuO1z /;48@ :ReYIa~㇩{_Z{v*In$ȿf%T5ճ_97
13264|ZJHoYMc?$e~1 IiHT@nnmk5 ڈ{ 93 U=w
1327OLNz_X\ZVQE얶vOPTm
13284jnWTٵwacK+[K.^a0:t)I
1329;%M_TRQ 7nv#cS3s ^Y[{? u~
1330/劁#B ldLu5ɪJ %ZV^QIM5064ٍ&E.Ҋm7;:{zo3844<<<44xޞΎm7Z[j*J
1331sEDpqdl43c4b5
1332XVKM+ _:Hưa;s|B"qI_PxjuMm]Ʀ렎jmxjUeEyYI‚,MMJD==\ٶL+lFFN%&hbim9
13339N\/ 84<2:6>19Ux.(3+BNnKEWKJJK\s!;+St>0591>6:2<48;[Zji a|؝5A/ c4t LiVLՃ  '$&%gD"QFzlJrRbB|\\l *2<,48כpuvd۱lЂ:tB{o >$'-!B¨̂ΰl).ϋ
13349-QaC|}|/2t 3`pц&IHKaԪd!`e[3OG'gW7w'˛yr=\]8l{;I%x 'zXFR'wi1"]#llC#cS3s n`XY0Yp8lPe1m K:faanfjldhGP_Uetw0A|ƩѪedp) :T>B7u`AQ: 4_^`BoWzF*$L!tL"V5
1335L&TUU.΋|ߨmi]#lX".V'U1VE'ee?&]85k 1n
1336q
1337/GS0 gs
1338486 0 0 480 6513.1162109 7207.1401367 cm
1339/Im0 Do
1340Q
1341 endstream endobj 868 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 869 0 obj <</BitsPerComponent 8/ColorSpace/DeviceGray/DecodeParms<</BitsPerComponent 4/Colors 1/Columns 486>>/Filter/FlateDecode/Height 480/Intent/RelativeColorimetric/Length 25812/Name/X/Subtype/Image/Type/XObject/Width 486>>stream
1342Hy<swk)a,c[ckK]R%e)BTԡVɉD*ʖȖ%[,Jۭ{۹7تxt۹ן13;"""~wLMEp;M&}Mk.Gz#ut8|2",&_A |;Ff`/6^ZdYY988vnbggceE∛Ƭ y!L/Z/]66v]ĹDEvDZ̹h"mcv1]n/
13435!K5E㙕΋tET\Bre2T'Reee-^")!.&JAHq)Ԅ/,80'
1344.•WT)khjjiiϙ2MIQA
1345Rb"B|<܋9'Y$=ůY1`د0EL\Rj U^q9073562]B[(Olq&3IwbOb$ )()͚vN]\]]f .8oprt_gfJKsScC}]mMu<u5:pi8IDd!1 eJ4U &f \7{nz5oV/M]{N- 8YzrJB1Ii9E
1346
1347aѲA~vr\3fZPD\ZVQy70$<Sgf^UR^USSF.ȾÇBd{$0X?{P[]y0*l:Ña^
1348ʚz&Vk\=}ęW߫mlFa/../ Y#W/FA6pNQA^vFZm.-/灃ZSfK1u:B£q’
1349qk{W/(
1350_BšFXaAvzr|LxϒLhB׮EΙcAq)m* w
1351OF)FZ;CfwO܌i ֦U
1352#C\[LPٶIFJ\DP
1353wil/ݼUPu1#oIcҟnoixV]Qs#츾pFq?j50»XȸGP]}Q3!fH1Ն]{;⺯ @[m'\Ӧr YO5_?͆i['Ok[;{̈'0#i0Ɔ= u%yB=lM DAx3gi"k`ÇE0s UXVY 1Sç5]4huqC<lOg5"KA<S8cH<|.GZ 3vƌӲ@ 0SO*QA& nyQ JF (+%|ɂ3ygpi;s%ťdaWcƗqbZNqyu}S[5xQO&'aƺ4
1354gsc}mUM2Bmeb!QIMʪq,f\SO$c47zd8YOkvuW.[4m63uY#Y[lu
1355jۢ>MS\QSߌSb<iG7744ww{S} ✈9ېTQ -LhL 25%H6xs7"UOjč97T<{8Z2صYVJLig:[0΃d-,&%y)kGP\?c|@#qqt5M둶g+13y?MjZMg<@0z ~čV4ΰR[߃ k03<TQ.XH{Xػ\JH.*G}EbL?8WeEz9ےtam ̛Ǟqf<XHֺF$[g";]Me<MT_ #
1356U߉sw{c]ei^zbLV9)1lgF KmQ3w IL+k0FęP$'5>2Xa+hq31̓Yd:eCf6^A9%kں#ar_gˋLmwZ{׈A;&&l=k:L֢',ܑ3 k^tن1:緯G^v4W'Fؑ# cG63fχiوd_VUrh[aq=@w[#vkV'8C; qfukSm kB?n٭yfuc[mÜ?9 k;#)693%p'aq ٹ#y7NC8gvܴΞv*')l1X3<|hv^=3WoƧ>kYBg+YӏA O+2oQ⬮qy,nmg΅%%W)1IO٭g;aO huB_sf<Xڸ
1357f>wK-I52vXaD] nbikJ'd ټ{ɳN^ףQ#C{Pٲeyi<ءV[%1*5Z^I!/vJ42dUmXa(I1֦GTڰg`9+_@H\Za>]3"?y'r + 975.AU%y rL x`kSkg'Ϛ: SVD#G65 O $F]v4>OyТM]W,uC97<vsH#3EAu%n\65ܥNBX6]SPPTjvuQ
1358+j{_9<4psfjقʙ6Z$$wuv ]dhq!v4H
1359<oq쐪䊥 <9S*.auPG~uWVf79!4ɱW.X@9oX#
136056m\%e!jl^ Gy=aکB9SAZl`0'7fvcPAIOꚻ Ga>dnvM`GE@ z6u]c WBn!5ؚ_ĝ|OSݤ#GBCYBEc\ELddI]
1361-x ),Ckɾc_ᖚ~s;LWg{~ޯ7ZW^9>줷
1362Tm^Td2k-wG'n_k~?5?I/# ޼xcJU% dƂRrxW\Rƃe-}C Θkӛ^,{+!/e&Uj
1363҂j>s?^Ϧ׵u ךjOh.}{fc`QE%!kZ;y x#!T~p_Ɔ;[k˞=H =vp:lQ "fdrw5@%k֬`=62VW^LJ}YTys 3;d-3[>A@n`V2~YA6,
1364jϩڠ$')&"p?lnL=IiMKg?dd~? YhUܸ b-d_p̵@[Y`  Qwrw1T& O!oؤ|(w{ UWE~J lkf,0
1365 dC
1366nAUi_9YPL ǥdP+h=\<8@XTOg\ #`ePAsrv.(\95,膋*?3)6
1367CY0iO~phMZr
1368
1369EA1Ow4UQ)jamU3ryA^kȩ/[
1370L)CemvպmιmX{W?x<tV_CQ0z;}ZPdjA舢2 幉Of{R[MVa FQ/ai&w%w~ zB춚1\-T~elz ̝}gU^͠M4WF]xZoJ |1 xOD_Oce xX#La`FՋi ^nc3ն} P^Ő:{(ogs Eq~Q/Z6^Q9TR *[z?gzj`' o"SFLZQ̜BR5I98> k w@{mI&"`Fvnزk4:y?ի 5 poseAJdUS?o[5^QZ'l܋HzתqHJܭ~9c+'2,8s.7Cb^ gNަG~^y1^6e  e.aUvW4yCܗ69 )NfeLFYBiøA2Wσ}5fQQ1Z@X|OӇ<xMٜRb߰tI(s(.kEtM3)J/fMʲj:fW
1371ZfFTE~ʳvڪ2\,KyY^
1372|l ZʞCYFMc 3t!="%DGʞ~#K72  欸\hȋ2lXHQgQ(c+$Z+ Rfcrx׎[_k֬zZeqF9e @Y;K3cB|+u"TBҪڦv^
1373p0n\̰{e`Sw (c)fOvԕ~#",q/:-[vkZXPNʞ8M;V(Io^ #*OجR2W@{mq`&#LOWFf#+T
1374.l:&NhF9\ڎA
1375h_kUAӀ+7f݋WL^M=f>i"a]fL2(9ڥibͨmc{a+0S#y1_q3,^>!Ȍ30/_<=9>؁){SmȿP_pae`똕݈ʖQ00*ωu9 _6^[TM!zUR@[!g.F݋GTn99(c,15U_
1376 Sj2BU6Z؛<d|᷀gm{1fȿZ`la!/JIe)Gz^̬Gzښhࠤf081w&,;6ua.W69$wizFՠ
1377{Ak2?鉿NA&63N>exȽ>ؿA^'g [Lgd$)o(llЛPeRP
1378 [Z0ȿ*;&,T>q=Pa1g:eG
1379VvSyŕ"g@ac4KlRas6(l\,{6 <İAac:l'e9YHa3oW4 J̫'w.[EyXUk@SHZUwHlVYc7(lLi`GmqzTv~v<hY38(16CƲoSB^0#gO\q+iE5ReT%>s;oOn7 =ͺ3iG حep҆n<(ll\5EiWTccX0#gKXV][a {G&᠕n(|຃- (#Kw䂪IPsbCnBحKge-L:;C;*:s@ Prʞh*Hw4BԂ>9T.vT(lz"a8#RƇvJ/x./߀&{-|㢙 ƯfYVYy}RX>023޼ u1?yY6
1380~URׅ'y|0]+#‡>˴Ig;$6>`Ga?Ȗ"J^Ey٘|0~J
1381(KM%˂tDMPX JzAP09{Mt=g3s]W%! \]H,ffzrż\<js׊XM.^[3jyXƇԲk@tJ~eXB(ў/:b'[ZƱʪygעZ%\j"MA-S2mݱ"n5tZ#\[eg&+Ê[_cd{{Gk< }!pgCYNRĹ'ޱ)(c0olf2ʋߔ?w#{/L-,z#(6m`2$yaf2/9
1382,Rm[h*ogVѳr I+i@\R3zKN
1383|쌴N)23Q tHA)R0
1384RPJM [bߴVy3>q#萂)xwCu%Bl)MLu!~z7= H;JɊ0eU[9l{^nESۙH
1385|MyQYOxRNR1_Dy# GDVlxbvYC0R._WބcU3K.Ŕ!e * ;,!)Õ`xe[[YÓH|2Nգ^!2K;2t!*`kLs PDʐf2=5eϐ: _EqAz*҂dxg eW#(YH*Sc=r;Q1=Pn)L tUƔ*3q
1386JӳvK/m@ʐei3Ph.HpQ
1387i*Р RH$dPdqoEua۶}z׿ps}m7Аo?*hZ;܈{KkhW[*?޿h.+H&6^y ;^M/n[Dl}yb7aj<K4 e^Us7yd ZFj}s]UiA.?ѵ#$;~&"ZSЖ:˲߽tbeR9Yh-(ga򾢱D ZO;J p۳yRI-s!k~΁oPˠfׯ>^[wd?3?Y8T_| -e<}h8;3-sK,]cxے+@ԏ/_u6R]4ef>qUƻ\QT7ZSF{ZcqڱAS^H-g`f_$eh{3/#?d'prwSUWO9ZX"H2$Ll"v8^P38^)R1
1388"7%&źB[f^/󪚺QG@g}yNRT~s]UiA.yZfd]gpLJnEc -wԕf=s}fmIN.AiU]QIQT{mqfBQ;5, t-wf~
1389|1O^ OSbB,kztu֯F" .pG]gN7UAKoQI9@pxeć3]Tr&/{"ߖԶ CFY.Hli E/qƻ\zK+f\:Ɗr2Аec&_4_qә򪚺`q,e?q`7Y+um^1)?5taCh\lZYf/Ζ}/F>*7 Agգ6,<aP^cȅO@ ruYh6H0)hmtf"fgb,S 惞90dc;,\Ge.LL7tD$-m3{BnOlYƶnƽ Agy{!ގV2mEWlSs+Hx?kiֳK'f#$\oߕudc;5͓ڙY*)2,<R*kMw Ka;)$bSeˇ84R}afW\ih}*$
1390@63Ge'EyܦDxYF+RAI(A˘
1391VJwcLZ0,S)VnrO,irhO(UJ*#GU0
1392ʼs)i8a^U6/19 =ODʬ9u#- dD823/U~A/8X'{ T"|f
1393 _;O_SSoY'ポ^ce.+|!c7Rs׶M1:gT_kջCKEjEl
1394g 4uԁV& p/qR7Z?02!UY]'S,)~vR_UzEиpLX@aΨ̤3wLKQBpA\^dɹc
1395Akzrt=Q[.]{0VշDՔխ}#D3ku=Ou1Ql^lL9y~;#*P+MKfQw/BƔ-:eIM[(q!\Y,9.; ]e0R^aLtғOMC_!,
1396_'^8Ql @yvL.]vG@čԜ5fro碬WnZE3ˡO * ,
1397_ukA63'7ALNhþo>)0@fe͖( r/2\|Rʺ+mw`gvX.(/pF`fc!k߾#)33QV Q9ETt-vhvcI33<e?2Vٜ<@KjF& L ^߿}i,ؘ0K0_N|[afj&"(JOD,(c
1398|f}eW`gfF(7U>K;,( >J[Cgd}v6sq47- /jfm{]KysKW/ݍދ sݴJ_,|R:ֻ~eui(`&FڪKrRoFz:n0efd˹+
1399+{ f&]mg*-B (l̒JfJL-m!BcBpm*~x="`zcMy*QF- &f`/4OȚWT7ݾtv?5(/WHBqg/K5;Pn,zoGn]k!'NeL
1400ضXSE 3']S|'͇Q"l׭%9z6AV7E ,$k
1401+fTH}=Q1/3)&Q/uZ(3k
1402]ާrJ[ag3.}]Y<%><`vD$ig*`n~!1Iyag3,}>7-bAg[ =zeJ2rv62ƆoY\C^2.`2z>AH};AA<=9u̴i׋0C:{-wag3,S>.j2bN"RJf u4<3}>婉6}-Ļv}l9 _35ql0 5fR"l<2y(Pt)|D T<Z_M} leggV4v ag13?5^[&#)&ߍ4U/ҙ):`9%U-=CgGΆO_ }^0.٨g$e)mnQ͟e޼pެ_ʳ <q_@ص:F' _3=B~Ȉzîk~M^ 2jz6ާ.|)߿Fԓ{qz8l0RO_gfG=[^c{ÿFJs
1403{̴'Ч F^;uUeDؙT2q\2j L`O>`DٽP]N\^}]lQU]sk'Y#S4n^|9}:cME a>.z5~f ,7E%fU6v @Ѧ]fuyW~;QҢh_xgs K(j9 ^sNIUs1|4 v)`^ Yϟ8fw1ݞ2~fDqllRҚ^h`̏ʢԄ W5]ż`Nꭴv<~5Iއ:kUЧ<WUIN`?7)"#}l0 V9{ml^=53bne"MEqs"sJQhC/&(hMG&WN zؕ9%"e~;b`i9şpцg:$o/JyҀ1ŐykVY/>_C$*4!a59hTBqNr!#FNIu{!zwxΓy_ИYUh
1404# t՗e$Dy;W_CIfFL3ň9܋K.nBDc!P=m ;Wmoߨ"')71aL10mcӞא)Amzr4
1405̜Q(# L\FQ]o'_/mB1
1406\+h<$R?c_(C]-%y,kMe 6/
1407fxŀhoeaM$2~
140899&ݑ`(#!~(I6+
14090kBqw}E DW]IVR@ y`c'!C/)kS] eYI~䇚 ì28
1410Y@e\Շc~ɐ{;kK EyC@3|~h)L/#-dv<6f9oÌsio. [B.cb&rKk;{Q9 z(`_7A _htRfnIMSGQPYq՞`̘G`V
1411q32d
1412f.~aemuߑ_+@omi6[W.L~Q]Xl\ <},$tM{\}>My_ZZ{j6?d\?a[GCE^z237+T5t|~,ƶ)ôm]_QlJInٜ c&yb@́] NL)mǙ|H[זgq~íd
1413U f/ dwukrOGK}%Xku?SN25q/&-~sl6wC cIۦ 2R֍e"]p1߭qj$OcI48sk/sxaQos+[ ~fyF1k+
1414ߓR?loo6uKā[Sښi!c Z6JZuY3 ֕s>.Eb[3w[6<yWKBPжYi) Fʚ(8 
1415]s[3y[6*a9X:y\u?&XXq%mlY3-ζr#9<dE9]8Zo)x;ͬ흽V7 <LǸ8AN
1416t)O5E9I1~6:ʲbdidbq ;{E%=y_U C>Nh<kˋr3co^dki|`ʶpZO 3!Ϋ *Z;܁\PF"jMO0n(~(%."sPZjқ7ii`+
1417lݦqūask(US%Ќjq|d*kM׬y5cXq^x9\ajw\Co")hfUxwv`7#yW-[4L f;3OKW&&[ #R#>ګ<{Y
1418RsqΛ}=cEV
1419KG;(2HAX{fV5Zcoq\錅 \֨?̓L`<N.\ۢT1qp ̜— -=zq^b۱#h}]m턌YˣZdŅ&A&g߸EZAuG7ȸҪ&8Ġf4"u<Hlm$\.e9 aXe=L 3\a еf&1E5M}IzqoM1FUMh~Yݰn0^9Cʚ9sJ+ <&1-YQYu}3[߸ĸxb ;#9.\ "1^3YCmz^+("!ͭ=oNHɄ⮬%@ = [H3A1li)ARlD7lƫZgF뙓k 7ᬩgdfuop$*rRF47)b:1jA*1TunVZbLx\ ctX/@ y&5k03>ð>]CNnѿ>A =I4xxPS9TuxF5kpm0|2;5t<w<uMmw|}-OB tk+K!Fz\>oejjB6z<|bwkYx+/I
1420YtCSk!=4 &s鼄/FQ@Bz:Ôب@kΎv͎bMJLXe~1kC8\Wشy=z-9\  .-F]=}PT#kYX3~"^(vwkK
1421'D@ hVQ^h!|Ɵ3ZШqŤU59aim}_IstUM=Acӵ7cuO1z /;48@ :ReYIa~㇩{_Z{v*In$ȿf%T5ճ_97
14224|ZJHoYMc?$e~1 IiHT@nnmk5 ڈ{ 93 U=w
1423OLNz_X\ZVQE얶vOPTm
14244jnWTٵwacK+[K.^a0:t)I
1425;%M_TRQ 7nv#cS3s ^Y[{? u~
1426/劁#B ldLu5ɪJ %ZV^QIM5064ٍ&E.Ҋm7;:{zo3844<<<44xޞΎm7Z[j*J
1427sEDpqdl43c4b5
1428XVKM+ _:Hưa;s|B"qI_PxjuMm]Ʀ렎jmxjUeEyYI‚,MMJD==\ٶL+lFFN%&hbim9
14299N\/ 84<2:6>19Ux.(3+BNnKEWKJJK\s!;+St>0591>6:2<48;[Zji a|؝5A/ c4t LiVLՃ  '$&%gD"QFzlJrRbB|\\l *2<,48כpuvd۱lЂ:tB{o >$'-!B¨̂ΰl).ϋ
14309-QaC|}|/2t 3`pц&IHKaԪd!`e[3OG'gW7w'˛yr=\]8l{;I%x 'zXFR'wi1"]#llC#cS3s n`XY0Yp8lPe1m K:faanfjldhGP_Uetw0A|ƩѪedp) :T>B7u`AQ: 4_^`BoWzF*$L!tL"V5
1431L&TUU.΋|ߨmi]#lX".V'U1VE'ee?&]85k 1n
1432HV{|SnUHpKK%-J
1433i£
14340Фm 
1435*/E|Tz, S`2>g:n0@vn}>cs}so.E{Z>w
1436w.BS0 H)+g+w]:J`ܟ(\&-$NTT1S(H&C1j(CPn1^ @Q1 dEK!P3.s""FRǶOhA I;SL|`]һf<͖ޣg9}?h2t_9h3W&>ׇ2Ɂ)SULQ9s̝7O,|rQ⧖<tYڕV?~uyao_|W_ݰqS-moλw~v]?l޳}?C>rϞ|˅ᨷNS"O"zl,yIw;ȝW4 !E0 V!]!Yt+gUY;Xu$klYZVڡ+PH- 6yB|!_z(._Z櫌|P(g =Zr![ƹDuqŵ 淬mR l!jho#{z|=
1437qDܷnklF<7K,j%M
1438A KPXuXpel5\ſo -kPO'8c8#8 qoc2ó88
1439!IF1Ym3Y,OVNi-tw)1SmH %:
1440dǍpU^b rAFβr9EJvydQ juM%1>!:qYh'40ҭld,p.gF2%MҜ2K^BDmISy"Y+`LR9$u80EI3+4(2rl"(r#8BP x.npXMvICHcȂAq ` Տv)wcN3g`:ў9S
1441eW68!7wH+DYQĄ%%R1n+0EF9p
14429a@J c"7.xYݶiQ^ļKws|Q*Ms2]`%
14437k
1444UF 6+^Z&ZZ4
1445[ˊo44gACo\a7.C2s~Ήb7=ENd_Q.*A@~EͶtjVPgجu0w6sfXg+4 ZunHM FuE0^Mw~w~ŏyG_.&89 I!44
1446Re(U`B mQ
1447zyv~9Oclw\'//w`O5kC
1448
14497Vʊ+{/Fw۫Eu/ :1+yT &t`lZلaXy-Ó9|!ҁ,t 04@œ~ WuZu:H஝Þw)wl8 71<_hh6&m
1450zQdr8",߂QcdP<d(i89TJL\Մ#5ᕎz
1451lZJe$xۘAcFFKlaY",F!2& DAuE4p#wjWG aF>FA0|\o,O뭌I-u;o~nEyi;i-7۶}C
1452vڲyk ?u@A;1ɂ19O.Nې$qS 1:nQGhf$ sې}I3BY6X;>z݁+OM/Wx2Yp>+01n`3KӚQQ>2}j\Uj:n:kL7 yɇd@i33٬/ =ڵkNW~.2Ķ}?yHoⷉ5_.
1453uxtésկx[- "Ql3}pEYD0*yRakL"a4BD0_jLJR Kh\Jܻ[{N*>r6a` Ʈ:RN q
1454VoTz8 Fj jwq5KWNxyuƍպNKGbop>d
14559B!_ț4b
1456U]j7'\q#Qx&/QA5׃ t `k @ =#=@=
1457\w1Y 3'$B 2_;Nza_w |x乒olzKc_:CҡC]CDy0<~:G1w|$g<a1V!igE4DS 3}]eFliP[MM=zG<ۻ7''o7nIv"yI f̀49JeNQ((7zc27n
1458Kxjd*<ܪ`M&H+/w7^v$)bFoe@c5
1459,Yҡ' ZuK6W&'d;T{؆QO6`5m77y5ZZ-49{_^^Z|? }Bدب+|޽wއ{׷Ư+c11]6i]55j֡+Bip*H.U%MK.QSEP( m$h!Xn #}wΜ93sΙsΩԲBu(432t0f7lj2Y_ʮj?ϏĜq9YX+f,fve>|^MbUG{pzvhq=ҩ4qyG2 '>3۬IiЕLy(>zcGa;hƘUFN~hHV%?4m?ԛX}]qR!2=l_\'pVDf_VNU5;TEt8N(G`,Cqrmf?a4oB߉gK:~cEԐ-ܺ'%! wŸg2lȕWdkTYzP'YBdSR:>*o:Z=f%e7-FlZj6xZiYǮ*Gf]18!)k9<ֹ,& Λ;1?#K+*yy>ɗːH!Dr#RtYdOY{Ÿ_WgK_h})Q|܋ , ~&rO֚W`uLkhMZW|ĽȨh|g_1 (B]w: â;g}b{ 6;1zxi^yo~~1T8a50rqW482D\Ԑrh YY*l (=L\kŵDl ?q&Zvً-% u<uʘ8'?&ʃCasYj*c.N4ujcV(BaQ^H^}xb5w9Gs:0HdU5sߒ}sR'][hBMiJ.uY@}J'y1N 
1460-$֑(m?қ4"\*t04%ͦ iGyj>ÎQ-GG=J;* 7Ej^+e]KTh>j{Nx}žƱ,
1461VkBPlWz,[H'O7ݫo CkKx B;P튆n.?PٶeږbD--@ 0)v
1462>BNQ<^#p#5 -SzDCJ*T?2J=ͭmiUsi,2^pBqޠs14ƆI|U΍#e%4X !|,#о@#!NU|7=W/d&kQЃ=T2CДn?̪FArVi |CCȶJ7 >pX``O#t+o';q$-q#
1463H|kxW;ϝ}ξ76<XH4!dBTZb(j
1464jVjVm->CZ̒ٹs
1465i%"00qg_#~۸ubn
1466<[݇gqN]bXɜ
1467[ eܸ"Arp&Y@Vr{4p$Zad*QU]S9+Wohl60cή K.[bWW֬]7~phxƑMha󖭣? ۭ@w3;>
1468w]|ⓟO|_~xC_z_yWڡǾ~7o>q[ǿS:~8?O:Og쳿xz~ ,I600XO! G)8籢.U0rG7 ͈icbKi$C8p
1469U@_nK|ϼlm^44onf^0ϛ5_6cC];zK
1470g
1471l'8ESpwIvMY"5QSctTw_hL&ncd`Ħ Ó:7ἢ?Vj/n,Zzز"j<asY*L\MQbҽK:Cb(3JgzKg:Cb'Ex&<3_UWaz1fY ig>RQWӽJt^`}QF%()_
1472$ED<r tSA._Sm6fWL2m^&!,0#$kKb+ /qZ1E,v C$=p(xRzV<G)R^-#ILWMUL\]}b4ȋveqйt~NSeYWX֨s{WK'vX
1473u^V<$W,Ӑolʧ9
1474찫ѰOd+N"H28yV܂ZE*B[i^J82$1R2Es.˟cUAE6ˡ9]v!OD4 CxS 9y(.q9⏗Rkm
1475Bnqyz_^d5'##"7:I$ O@C4!E_=ؖκULeu\Pg4c !:z :Uѡ(Av!nաHT`7)Q.͛o
1476#$BU9sE | -[yTbʇ*K[W2,t r0nB1ż(va"ي&ͱ+͢fZ9gL:h줟a܉V,cHFoT1*8+s/ v(f_3srX|6Mnuҍ2kՎэ.zanbx@<GqU5Mt!­ j/Rq{E?e1@Hʧ%|Y87&mulK x\z6jU̳4sx*P;;(BэՐ+UNÿȥ6A; KR\B㳸ZYz#|G[ZGZE8z+ߘyܼcwM9mbM{ɓS9, S*ٿ~ yr#7?VLwW]}&X%kr@
1477q
14780 g
1479/GS0 gs
148015.8993082 0 0 -16.1025677 7632.3847656 6956.671875 cm
1481BX /Sh0 sh EX Q
1482 endstream endobj 891 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 892 0 obj <</AntiAlias false/ColorSpace/DeviceGray/Coords[0.0 0.0 0.0 0.0 0.0 1.0]/Domain[0.0 1.0]/Extend[true true]/Function 893 0 R/ShadingType 3>> endobj 893 0 obj <</Bounds[0.210899 0.350209 0.494759 0.604521 0.917524]/Domain[0.0 1.0]/Encode[0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]/FunctionType 3/Functions[894 0 R 894 0 R 894 0 R 894 0 R 895 0 R 896 0 R]>> endobj 894 0 obj <</C0[0.5]/C1[0.5]/Domain[0.0 1.0]/FunctionType 2/N 1.0>> endobj 895 0 obj <</C0[0.5]/C1[0.987469]/Domain[0.0 1.0]/FunctionType 2/N 1.0>> endobj 896 0 obj <</C0[0.987469]/C1[1.0]/Domain[0.0 1.0]/FunctionType 2/N 1.0>> endobj 888 0 obj <</G 897 0 R/S/Luminosity/Type/Mask>> endobj 897 0 obj <</BBox[-32768.0 32767.0 32767.0 -32768.0]/Group 898 0 R/Length 86/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 744 0 R>>/Shading<</Sh0 892 0 R>>>>/Subtype/Form>>stream
1483q
14840 g
1485/GS0 gs
148611.9217148 0 0 -12.0797682 7632.2294922 6995.9882813 cm
1487BX /Sh0 sh EX Q
1488 endstream endobj 898 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 887 0 obj <</G 899 0 R/S/Luminosity/Type/Mask>> endobj 899 0 obj <</BBox[-32768.0 32767.0 32767.0 -32768.0]/Group 900 0 R/Length 88/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 744 0 R>>/Shading<</Sh0 892 0 R>>>>/Subtype/Form>>stream
1489q
14900 g
1491/GS0 gs
1492225.9361572 0 0 -225.9361572 7629.4453125 7389.2958984 cm
1493BX /Sh0 sh EX Q
1494 endstream endobj 900 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 886 0 obj <</G 901 0 R/S/Luminosity/Type/Mask>> endobj 901 0 obj <</BBox[-32768.0 32767.0 32767.0 -32768.0]/Group 902 0 R/Length 84/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 744 0 R>>/Shading<</Sh0 892 0 R>>>>/Subtype/Form>>stream
1495q
14960 g
1497/GS0 gs
14987.9551892 0 0 -8.0455885 7632.2294922 7026.9384766 cm
1499BX /Sh0 sh EX Q
1500 endstream endobj 902 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 885 0 obj <</G 903 0 R/S/Luminosity/Type/Mask>> endobj 903 0 obj <</BBox[-32768.0 32767.0 32767.0 -32768.0]/Group 904 0 R/Length 86/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 744 0 R>>/Shading<</Sh0 892 0 R>>>>/Subtype/Form>>stream
1501q
15020 g
1503/GS0 gs
1504225.9359131 0 0 -225.9359131 6749.46875 7454.5385742 cm
1505BX /Sh0 sh EX Q
1506 endstream endobj 904 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 734 0 obj <</LastModified(D:20140918115258+02'00')/Private 905 0 R>> endobj 905 0 obj <</AIMetaData 906 0 R/AIPrivateData1 907 0 R/AIPrivateData2 908 0 R/AIPrivateData3 909 0 R/AIPrivateData4 910 0 R/AIPrivateData5 911 0 R/ContainerVersion 11/CreatorVersion 16/NumBlock 5/RoundtripStreamType 1/RoundtripVersion 16>> endobj 906 0 obj <</Length 960>>stream
1507%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 16.0 %%AI8_CreatorVersion: 16.0.0 %%For: (Coraline Lafon) () %%Title: (logotalerv2.ai) %%CreationDate: 18/09/2014 11:52 %%Canvassize: 16383 %%BoundingBox: 224 -1014 1618 26 %%HiResBoundingBox: 224.5146 -1013.7627 1617.3057 26 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 12.0 %AI12_BuildNumber: 682 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Repérage]) %AI3_Cropmarks: 0 -1080 1920 0 %AI3_TemplateBox: 960.5 -540.5 960.5 -540.5 %AI3_TileBox: 582 -828 1316 -252 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 6 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: -307 125 0.5 1389 670 18 0 0 163 161 0 0 0 1 1 1 1 1 1 0 %AI5_OpenViewLayers: 7 %%PageOrigin:524 -780 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 907 0 obj <</Length 10404>>stream
1508%%BoundingBox: 224 -1014 1618 26 %%HiResBoundingBox: 224.5146 -1013.7627 1617.3057 26 %AI7_Thumbnail: 128 96 8 %%BeginData: 10254 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FDFCFFFDFCFFFDFCFFFDA4FFA8FFA8FFA8FD77FFA87D5227272752 %2752527D7DFD71FFA85227F826F82752277D27527DF8F8F8527DFD6CFFA8 %52F82727527DA87DA8277D52A87D7D7D52F827277DFD69FF5227F8527DA8 %7D7D527D5252527D52FD057DF827F8277DFD66FF27F8277D7D7D52527DA8 %A8FFCAFFFD04A8527D27522727F8277DFD64FF26F852A87D5252A7A8FD05 %FFCFFD05FFA87D27522727F82652FD41FFA8FFA8FD1EFFF8277DA87D7DA8 %FD11FF52522727262752FD3BFFA87D5252FD05275252A8A8FD18FFF8277D %A85252A8FFA8FFA8FFCFFFA8FFA8FFA8FFFFFFA8FFFFFF7D522727F8F852 %FD37FF7D52F827F8F8F827F827F827F8F8F82727A8FD15FF525252A8527D %FFFFA8512752A8FD04FF7D76FFFFA8A8FFCFFFFFFFA852275227277DFD34 %FFA85227F8FD042752275227522752FD0427F8527DFD12FF7DF87DA85252 %CAFFFFCF522752FFA8527DFF7D52CF7DF852FF5227A8CFFFA8522727F827 %A8FD32FF7CF827F82727522752527D527D527D525227522727F82751FD10 %FFA827F8525252A8FD04FFA827A8FFA8F852A87D52FF7D2752FF527DA8FF %FFFF7D522727F852FD30FFA852F8272752275252A8A8FFCFFFFFFFA8FFA8 %7D5252FD0527A8FD0EFF7DF87D5252A8FFA8FFFFFF7D527DFF7D5252CA7D %7DA8FF527DA87D7DFFFFFFA8FF52272727F8A8FD2EFFA827F8FD04277DA8 %FD05FFA8FFCFFFCFFFFFA87D7DFD0427F87DFD0DFF527C7D7D7DFD05FFA8 %FFA8A8A8FFA8FFA8FFA8CFA8FFA8FFCFFFA8FFA8FFFFFF2752272752FD2D %FFA827F827275252FD11FFA87D52522727F8A8FD0BFF7D277DA852FD04FF %52FD07F827F8F8F827F827F827FD05F827A8FFFF7D2727F8277DFD2BFFA8 %27F82727527DFD05FFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFA852522727F8 %A8FD0AFF527DA8527DFD04FF7D522727275227522727F8F8F82727522752 %2751272727A8FFFFA8522727F87DFD2BFF52F82727527DFD16FFA8525227 %27F8FD0AFFF852A8527DFFA8FFFF7D2752272727512752FD05F8FD042752 %2727277DA8FFA8FF52FD0427FD2AFF7DF82727527DFFA8FFCFFFA8FFCFFF %A8FFCFFFA8FFCFFFA8FFCFFFA8FFFFA8525227F827FD08FF7D27527D52FD %05FF7D272727F8FD0527F827F827F827F8272727F82752A8FFFFFFA82752 %2727A8FD29FFF82727527DFD1AFFA8525227277DFD07FF7DF87D527DFFFF %A8FFCFFFFD08A827F82727F87DFD06A8A7A8A8FFA8FFA8272727F87DFD28 %FF5226272752FFFFFFCFFD18FF7D5227F827FD07FF52277D527DFD0EFF7D %F8272727A7FD0DFF275227277DFD27FFA827F82752A8FD04FFA8FFCFFFA8 %FFA8FFA8FFCFFFA8FFA8FFA8FFCFFFA8FFFFFFA87D5227F8A8FD06FF7D52 %A8527DFFFFCFFFA8FFCFFFA8FFCFFFA8FF5227272726A8A8FFCFFFA8FFCF %FFA8FFCFFFA8522727F87DFD27FF7DF827277DFFFFA8FF52FD15F852FFCF %FF7D52272627FD06FF52A87D527DFD0EFF7D275227277DFD0DFF52522727 %52FD27FF27272752A8FD04FFA852FD047DA17DA827F8F8F852A8FD067D52 %A8FD04FF52522727A8FD05FF52272727A8FD04FFA8FFFFFFA8FFFFFFA8FF %5227525227A8CFFFFFFFA8FFFFFFA8FFFFFFA8522727F852FD26FFA827F8 %2752FFFFFFA8FF7D52527D5252527D5227F827F827527D5252527D527DCF %FFFFFFCF7D2727F87DFD05FF52F82752A8FD0EFF7D277D5227A7FD0DFF27 %52272752FD26FF7DF827277DFD05FFA8FD07527D27F8F82727FD0852FD05 %FFA752272752FD05FF7DF827277DFFFFA8FFCFFFA8FFCFFFA8FFCFFF5252 %7D5227A8FFFFA8FFCFFFA8FFCFFFA8FFA8272727F87DA8FD25FF52F8F852 %7DFFA8FFCFFD0AFF7DF827F87DFD08FFCFFFA8FFFFA85252F827FD05FF7D %2727527DFD0EFF7D52A87D52A7FD0CFFA8277D52277DFD26FF52F82752A8 %FD0EFF5227272752FD0DFFA87D272727FD05FFA8F8272752CFFFA8FFFFFF %A8FFFFFFA8FFFFFF52527D7D27A8FFFFA8FFFFFFA8FFFFFFA8FF7D27A87D %F87DFD26FF27272752A8FFA8FFFFFFA8FFFFFFA8FD04FF7DF827F87DFFFF %A8FFFFFFA8FFFFFFA8FFFFFF52522727FD06FF27F82727A8FD0DFF7D52A8 %7D277DFD0CFF5252A82727A8FD26FF52F82752FD0FFF5227522752FD0EFF %7D272727FD06FF52F8272752FFCFFFA8FFCFFFA8FFCFFFA8FFFD045227A8 %A8FFCFFFA8FFCFFFA8FFFFA8277D272727FD27FF27272752A8FFCFFFA8FF %CFFFA8FFCFFFA8FFFF7C2752277DFFFFCFFFA8FFCFFFA8FFCFFFA8FF5252 %F827FD06FFA8F8272752A8FD0CFF7D277D52277DFD0BFF5252A852F87DFD %27FF52F82752FD0FFFFD0552FD0EFF7D272727FD07FF52F827277DFFFFA8 %FFFFFFA8FFFFFFA8FF5227525227A8CFFFFFFFA8FFFFFFA8FFA8277D7DF8 %27A8FD27FF52272752A7FFFFFFA8FFFFFFA8FFFFFFA8FFFF7D277D527DFD %04FFA8FFFFFFA8FFFFFFCFFF5252F827FD07FF7DFD0427A8FD0BFF7D2752 %2727A7FD0AFF5252A8272752FD28FF7DF82727A8FD0EFF52527D7D7CFD0D %FFA87D272752FD08FF27F8272727FFFFFFA8FFCFFFA8FFCFFF52272727F8 %A8FFFFA8FFCFFFA8FFFF7DF87D7D2727A8FD28FF7DF8F82752FFA8FFCFFF %A8FFCFFFA8FFCFFFFF7D52A8527DFFFFA8FFCFFFA8FFCFFFA8FFFFA82727 %F87DFD08FFA82727275252FD0AFF7DF827F827A8FD08FFA8527DA852F87D %FD2AFF27272752A8FD0DFF52527D7D7DFD0DFF7D522727A8FD09FF7DF827 %272752FD05FFA8FFFFFF52FD04F8A8FFFFA8FD04FF7D52A87D7DF852A8FD %2AFF52F82727A8FD04FFA8FFFFFFA8FD04FF7D277D277DFFFFA8FFFFFFA8 %FFFFFFA8FFA852272727FD0BFF7DF827275252A8FD07FF7DF827F8277DFD %06FF5227525252F852A8FD2BFF7D27275252FD0DFFFD0552FD0CFFA85227 %F87DFD0BFFA852F8FD04277DA8FFFFFFA8FF52FD04F8A8CAFFFFFF7D5227 %7D5227F8277DFD2DFF272627527DFFA8FFCFFFA8FFCFFFA8FFFF76275227 %7DFFFFCFFFA8FFCFFFA8FFFFA85252F827A8FD0DFF7DF827275227527DCF %FFFFFF7DF827F827A8FFA8A8272752A87D5227527DFD2EFFA8F827277CA8 %FD0BFF5227522752FD0BFF7D52272752FD0FFF7DF827F8FD04275252A852 %FD04F852525227527DA87D27F8527DFD30FF52F827277DCFFFFFFFA8FFFF %FFA8FFFF7CF852F87CFD04FFA8FFFFFFCFFF7D52272727FD11FFA82727F8 %2727522727277D527D272727FD057D2727277DA8FD31FFA827F827527DFD %0AFF52F8272752FD09FF7D7D2727F8A8FD12FFA85227F827F82727277D7D %7DA87D7D527D52FD04277DA8FD33FF7DF8F827277DA8FFCFFFA8FFCFFFFF %7DF827F87DFFFFA8FFCFFFCFFF7D522727F87DFD15FFA87DFD0427F87D52 %7C525252FD0427527DFD37FF7D272752277DA8FD07FF52F8F8F852FD07FF %7D522751F852FD18FFA87D7D52522752FD0527527DA8A8FD39FF5227F827 %27527DFD06FF7DF8F8F87DFFFFCFFFFFA852522727F852FD1DFFFD07A8FD %3FFF7D27F827275252A8A8FFFFFF52F8F8F852FFFFFFA87D52522727F87D %FD65FF7D27F8272752275252A8A852F8F8F852A87D5252275227F8F87DFD %68FF7DFD0527FD04527DFD06522727F82752FD6CFF5227F8F8F8FD042752 %FD0427F8F82652A8FD6FFFA852522727F827F8FD0427527DFD1CFFA8A8A8 %FFA8A8A8FFA8A8A8FFA8A8A8FFA8A8A8FFA8A8A8FFA8FFA8FFA8FD3DFF7D %A87D7D7DA8A8FD1EFFA8FD0FFFA8FD09FF52FFFFFFA8FD56FFA8FD19FF7D %2727A8FD06FFA827A8FD58FFA8272752FD08FFA8FD0EFFA8277DFD08FF27 %FFFFFFA8FD55FF7DA8FF2752FD07FFA8A8FFFFA8A8FFA8A8A8FFA8FFA8FF %FF7DA8FFA8FFFFA8FFFFA827A8FFA8FD0BFFA8FD4AFFA8FFFFFFF8FFFFFF %7DA8FFFFA8FFFF7D7D7DA852A8A8A852527D7DFF52FF27FD057D52FF27FF %FFFFA8FD09FF7DFD4BFFA8A8FFFF527DFFFF7DA8FD04FF7D52FFFF5252FF %7D7D27A8FF7DA87D7D27FFA87DFF7DF8A827FFFFA8FFFFA8A8FD05FFA87D %FD4BFFA8FFFFFF5252FD06FFA8FF7D7DFFFF7D52A8A8A852FFFF7DFF7DA8 %27FF7DFFFFFFF8A827FFFFFFA8FF7DFD53FFA8A8FFFF7D52FF52A8A8FD04 %FF7D52FFFF7D27FFFFFFF8FFFF7DA87D7D27FF7D7DFF7DF8A827FFFFA8FF %FF7DA87D527DA8A87DA8A8FD4AFFA8FFFFFF527D52A8FF7DA8FFA8FFFF7D %7D7DA87D7D7DA87DA8FF7DA852FF52FFFF7D7D7D52A852A8FFFFA8FF52A8 %52FFFFFF27FFA87DFD4AFFA8A8FFFF277D527D7D52FD0BFFA8FD05FFA8FD %06FFA8FD04FFA8FD04FF52A8FD047D527D7D7DFD4AFF7DFFFFA827FF27FD %05FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FF %A8FFFFFF52FFFFFFA85252FD4DFF7D277DF8A8FF527DFF7DFD07FFA8FFFF %FFA8FFFFFFA8A8A8FFA8FFFFFFA8FFFFFFA8FD06FF52A8FFA87D52527DA8 %A8FD33FFA8A8FD15FFA87D52FD04FF7D7DFFFFFFA8A8FFFFA8FFFFFFA8FF %FFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFF7DA8FFFFA8FFA87D52FFFF7D %7DFD35FF7DFD21FF5227FD0B7DA8FFFFA852FD0A7D5227FD3FFFA87DA8FD %20FFA8A8FD0CFFA8FFA8FD0BFFA8A8FD3FFF7D7DFD30FFA8FD4DFF7DFD80 %FFA8FD14FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8 %FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8 %FFA8FD31FF7D7D7DFD13FF52F8272727F8272727F8272727F8272727F827 %2727F8272727F8272727F8272727F8272727F8272727F8272727F8272727 %F8272727F8272727F8A8FD2EFFFD04A8FD13FF27FD39F87DFD2FFF7DA8A8 %FD13FF52FD0FF827F8272727F8272727F8272727F827F827F8272727F827 %2727F8272727FD0DF8A8FD45FF27FD0EF827F8F8F827F8F8F827F8F8F827 %F8F8F827F8F8F827FD04F82727F827FD0EF87DFD45FF52FD1DF8525227FD %07F87D52F8F827FD0DF8A8FD45FF27F8F8527D52FD09F827FD0DF827A8FF %52FD07F8527DFD10F8A8FD45FF52F8277D7DA8A8FD07F8272727F8F8F827 %FD09F85252FD08F87D52F8F827FD0DF8A8FD45FF27F8F827F8F8A852F8F8 %F827F8F8F827F8275252F8275227F827525227F82752277D272727522727 %527DFD0DF827F8F8A8FD45FF52F82727F8F852A8F8F87D27F8F827F8277D %2727527D52F8527DFF275227277DA82727525227FF527D52F8F827FD09F8 %7D27F8F8A8FD45FF27F8F827F8F8F8A8FD07F827F8A8F8F8F8A82752527D %52F8F852F87D7DF8F87DF8F87D7D527DFD04F82752FD0AF87DFD45FF52F8 %2727F8F827A827F827F8F8F827F827A827F8F8A827F8F8527DF82752277D %A8F82752F8F8A87D7D52F8F827F82727F8F82727F8F827F8F8F8A8FD45FF %27F8F852F8F8F8A8277DF852F8F8F827F8A82727277D5227277D7DF82752 %277DA827F87D2727A87D527DFD04F82752277D5227277DF852F8F87DFD45 %FF52F82727F8F8277D7D52277D27FD04F827525227F8525227F827F82727 %522752F8F8F852522727275227F827F8FD045227F87D7D277D27F8A8FD45 %FF27F8F827F8F87D52527D2727F8F8F827FD1EF82752F852527D7D7D2727 %F8F8A8FD45FF52F82752F827FFF87D52F8F827F8F8F8272727F8272727F8 %272727F8272727F8272727F8272727F8272727F827F8527DF8F8F852A852 %F8F827F8A8FD45FF27F8F87DA8A827F8F87D5252F8F8F827FD0DF827FD0D %F827F8F82752F8527D7D277D5252F8F8A8FD45FF52F8F8F827FD05F827F8 %F8F827A8A8527D527D527D527D527D7D27F8F8277D527D527D527D527D52 %7DA8A8F8F8F8272727F8F8F827F8F8F8A8FD45FF27FD0EF87D52FD0A2752 %F8F8F8FD0C277D52FD0DF87DFD45FF52FD1BF827F827FD1BF8A8FD45FF27 %FD39F87DFD45FF27FD39F8A8FD45FFFD3A7DA8FD44FFFF %%EndData endstream endobj 908 0 obj <</Length 65536>>stream
1509%AI12_CompressedDataxr$7 m#ͶH^۶fdl$+Uul혌dJ%ɬjww!MYW8s_q3m.o~WW>arc?Hxy{;~<ûޝ_]\lޜrŗ/.ǫ۟nϯ.b/8'q:c~,v8Ǐ?G~ywync|ehF_.pq ;H&trwwo/>~^}f?/vquun9^?/.>B}݇O/w^6ᇳ˫ Xpt%f֟>|`j__C0
1510zW.߿?\ yݧ /a{0||3)DI:<
1511h9&twD@Tf`x1s:l
1512G[:r\
1513l0 qO~`
1514};oܩ;q[w&]pYggԞح=dM6dY G֨b(|\<Xg$1{JdE2ELK䖨8ycDSZ3sEAANv[QEB9KrgB9$ f!N аPqB2)=DZ255E@Q
1515:r "LDÉ8{Dr%Tuq2`,NF$["2c |04X"3XZ'Ds
1516(I>BD3
1517;*,14R̠'LO;`́qʥE@%(;ju <PBB[*߱F-eB]?_m8QSle1Y-7si6Ɗ`f=ٸz,ᩦUkYv@a&'>, 2˜ KԊhwUt"[3* :G&bis8s0=&?*6"ġIz5-}qnA5ױG7 = ڝݲiy<hgesVюݟyּUpw4N6k.Ӳݮrd[*iq+vw;QirDڔY<7*F2 Ƿ-6 f^o ކ'Q5T쩛]W$R(Ϋs:4!J6DYl]TՖH۩"Zz*= -b?kKD^/<-v o6I!7{%.TpJlCvo[ncc0s|{℞LKl4qMzC-AGVMqx%%v1n뒶qDףBv%e{t2SdJ6Ua-mokwf(o[5;#FCPx|hBCvWROِaX;<KbSJyҦ })նmL"7ښٟP6d-fyņa㨡 =GOrsul:zζ#w<"zTuTix1U_Hgo$u}
1518]g>a;ׇjqua3>P_vSOZަ}}ہ_K:?uIlog늙nrSS#s凋%ebåƑ)|l׶|Z^[wS-09U
1519qgq޹jJ J]~JISt5' <1Dɂ5cdb!ؑyĺ &O1)F4
1520+~r1YѲjy\Ee\xH#%պe].Nv8-δ
1521 ,1Jvf]b"CIsaBEVlhs,;Bౄ6F]6ҭ; G JG#]
1522C
1523֐=뎯%Tb>c[NM~frĝyyxr'(7cgڱe
1524ۮ~3=[~1vyV}S1K0\K]_TqQ|f9t4=)69=Òg_`~USY51#iD!T9WL 7О#\c]33
1525/ 2 4ܿ-YM;Z`|P 2کpi) 蛆{W>FŇj^tpsrOz;=l|ZZ$C/:t9Z\ iXE^{p٧Uz
1526">c(p,/D8 o9A Zp;ht}ςu:l*! Бf>-VqSQw33w?ѓ%!4XZo,M,m3)s0Q ϹV'F)%fR/^}dPR
1527 :.h %7"bAFLԴVjׇ 2$,Cd,K8BJIy]mO*ʴ]i=#RZֵ4I,/_.YVdP4WK)Q$,ԉJ J\^*he>=v@V b.,s{r K{9⠘^οY1QvL69.V,/b Tpn1a{0H
1528bPѲ EaŽ֬}a[o mLc
1529MhF#ΘaۦN28㪘:5h7G:S9 0V cwzLg'F-P{`rK,^i-UaJe")/{*ǖrlKvSo"CWdۺ1;Λ(s鋢Lg֖Ly}+wZV0/
1530׫Zȉ
1531f*w垏j?밽922kMv-T#{`'L=ªE״ZjPpM\Kc9 ZEX0ڲ$Dځl%Yj@9Iw$/(zaԢȯ'vSb( u ^lwm~ f’YNUۑ.;;H'v#t}Q개Ta2TPF/߽Z c$nt]sO@9Աgc_M17V?ʂ
1532D~6r+H5|%khy'v{04h *u΁
1533 Pkxb5{POUGK]OCRegہ}+H1j|a &lCPIaVzhӲay, v
1534d󛪏+J^TYj^;(>^
1535>(jutFGTA`s/o0>ƨst1)kOv âg.&ОsugSuο:rEڋwϒ-8u&A>LL|vqY{ e|SA`U~:WjJSёDvQGT\vrH=PRrLG%!?: jN03ʁ<VɱC꩞1OeIG;4,0L'c9e#0c=Q61qYG:wX!ʑݓP7F էAWl)ؤw Zdp,̃ ^M1$
1536P"7&z}dL:$Bxch W>[q݉t,WЫ/;%y߾CqZz}RJ3 ֒
1537HرS
15385F8ZU8i|uLi.ˎ FꊥEД-Us{y[h)*iXg;Ю:n< Zuuh"/
1539:w}\{/:'WIcQV(z0
1540RNFQ<PRq=Oi2#R۷GG ׋JXMձ)mq{F2ONqL^ }N^Ob5 u|q4ll)7"P*Q2h
1541-^L܁)>øa}iWF)n时d| fy <F~藎P
1542~滻˛˛g? |_6_]___|r(6mɚ1t`M;02W>/jo~7?}Ճ6oЛjncs /ᰛ۫G_ :~8}wy{˫p L[/H<=`c|
1543p'L#D2<4Mfi"Pq'-ƺB#q&d LL}DMj`ByDǒ<"79
1544
1545fTIE,n ȶɡAY6ʓ
1546LK
1547H bQ
1548^EICD0ٍ
1549F% Lv lD6CcР"A1,pWB̈́4 `EHlQfAs<4*3&@UrQ#܄aУ-T9򏃎ދőXMG` 5 ^{KO1Bܠ>".A_Rbk
1550ΆGE
1551/|8q@ l45QwBT& 48S I E5_p6dF@p!Ĉ
1552,>m$ OF  pVP ڡ-PmhF!c0Xd6lxbVX
1553iRY!
1554|nUiVMVm(X ELm(mu2rHLBVq+헀HCUhRGP4DXXӄ>TJxt%a5Rx T¹S#':nT[Bd(A:BJ ԥ-20@SԩNyt!}cSCERuh
1555j LF60#%O!KE40
1556J%1JP
1557>]sL
1558D1J&$ _"R菂#RkQ
1559!EyH*u
1560aPGw޶Q(hH BA2RPbP2EEن
1561B_'3s~3!JrL|-&*dJ ;H #6c 2Ɔ2 ml\˻Lx*B}K#ALO
1562p4VJJ7&8|#hIiѡtFs
1563otNΒotp f4߈T)F* P7:bp_o6KHoП}oDC1ohd4ΉM8z4@,pqFHaL"iN8:PT@Quq9k/YqY`\&<kڄ#>2PO$]@uqtfMȩw80gf6G&4QɬԔ\rt7!{HSqI9n2ȳi8 ("GjBi2r4S
1564snեa68:qƈf~#Vqnx ՜qKmэ0_#%s(uUkm\,@79^q`(ò%u,bՌXFi'M9r/6=>`g[(u;bev
1565M&3#IkbFcᭉG1$%hA@ I<
1566ML%>2Q(J 3\%Qm$'Kd+9t%l[6Z K\lkk}f
1567◌%d81%gi1%H%q$XmҢ%!92Ҵ%t$VD-P5-
15686iK&mi& KQWJk%aWѴ% -=V`JgW'GoSڲ }iڲ4#}F }iڲD4m4mY5mY^l^,A/M[-눗f-KK%ޥY&ܥY*N4kYǺ4iYB],.MZց.Y8,KJsMKrMs%%9&9ҜeoiβoIʲ4g4gYb[,-Y6-Y,K\KsMXK%IՒeҤeiiҲ$i4iYY,,MZ,IZ,IZ.Y,,ZPf-Hf-K K%YEssKҖmKҖs
1569^_e
15706y]l+mBIr~j!y[ȵ'1'Ҥ0*T3 pbDɊhd3 |Hp<Hba$lI؂ m LzB!HYE?54Я)x[0nE}4)Lzor 3p׿]#:yaCJ" &!X3XL\'rj?oG$ ,AasLơާe6ElӤ
1571a܊P1@nb7ܳAG\C'<9%X̄D<LjA,oh΢B>T-+Θ
1572[4B pE >0V^>(_]k- Ԃt6Y$W""+CIaD3f3= RBlPJmP(|lPiaܧ+nB-'jkO
15730ckɰ *0\zETQi%B60DZIfO-<g3Oopecl)PA+m
15746qs|(DN[ӲFcF@qN\#
15758A@Z@=,V:8pA > 
1576w|etյMlZWMoEx%ߊ| "f,DM#c̔ムo̔rf1fV(ݤ*vvT_{o"V
1577kjJiH`j1JciY
1578{6E4~͍,E@V֪Elߪ kaɵYvpS|Gߊgi~%I5ib ~m
1579%ME1<57Q'R*+Ԏ,bWQ`Wqq/rS(*qf|.s8t|9>i,2;wsčuG{\z'9մm1覴dٮ,ey9̲]/&҈{@LOd,]/FF}T_z\6bF|L4:ϫ2Uf$4w^ xn-
1580+p=Dzp):[ispRgB\|&CvvpphyC/0l턋yR,o˯ LΧ=n*s
1581Q{ >kPSYͶ#n[
1582
1583,m$5,ϓ׬uf0DFjQONE\=;q\tnF_rc5 HZq9D -ȉ—e6/aZt/(Dbܬ"!Ȭ=T@{ubOv$nԅ]m5zk rKXF=a'Mzgu \Nzz{+|$n^Sl
1584Ipcqi{xkZ~J ֳ ή\߫ͬwzċ‘ liԣfCWT$֌xGs@ 4nd̊m:n()U qdlx
1585ϯYS;5 `x X>nȲ}Usxhģ@<I7MTIHmPO~'tJ3x9? 7o:65tV/Vòoe5xx^۴nj\FCx%R)v:D
1586"-{-HC!RX):DJ"bH^KCC!Ri9k44u;Dk"M}"'ƞɻ[X%#WZvBG=Б#C{m#WN`!ksv#F{m#ZEءS)t:tZ/:whuNCԡS)vo_5tkH^[H}ii)w;tZ'`cGBO.Q"1w,HNSؼg;Xk^'`cG0Ŏ;lzήC&סr} 5,CСr} #L{m#`tJ:bNCx#`kXrNCx#`SGbG.Ta F_O-GGqE7-[i7I{R=)tQ4u4{Oʝ'-G&$>“׭R? ל4XO˅L8g4iUGiB f;M3j7t"[uEk{^dǕoay {c5܇=:i r6ˈ_jk4=F:L:\w݋l5efǜ^|zYVu=V#SXgjkV4=쩹?:;ӋUb 5+_scA/ ܿg ?f*bWܿ),}ָ=7&
1587S;AWc]xQ̓*\ɴΡTG3!~H<$vI^sǓnpWahzC&AuȲ+:"\2"CߡCu3zR\>GixCF)v+;Jbb@"yC!F-v3{Jbb@Gª6E]:>o%۪s\A+W=){O'-G\Kyc{]SksN1W_J/
1588ſ<Q:#pHU<D-M35{<`4*R\mqąC/S^irHfQi20d0e{[o6jƢ0{@6
1589_\jm=!8OolV|m[_PǞٵ<y dRyt͘zr~q 쳄~Ю`%*^-
1590ܤ̔+⢏+<-__t ݃kghT>ڇz]uզ!Cܹ)!NXAj1j/;'>@ezܫ#^l o:LNUkNP ޯFe%˹,ͺY i/m;]`jxh/fMe6n_AA̹%f
1591O<&vSnsm;X͙ڦg M'BSۡ<64{}V ._ n6N.O2cr"O5oSy:f䚆MG3~ł~>bZ5KztڟͶn퉍Gc|(t/!`a1dڦ -ܲOxmF-;JZvY^gP4qTp
1592Yt=S89Y`e)Ə`]%aߎ衏ٵuȳ?lZrɰVPD[6Pl$ffZMAW
1593vŵYbEmfe'Dq3}."/,:U/o>޼>W96
1594sRڳǖ}
1595UҘXasDG&k,9G66O۳}
15962}*n9}ZHYU(
1597ZTC{fG 1Q\wt٧_+$96bWyZ֭
1598NȺa! }Z]\YZQ:ɥX<qAfc3CbϮy~f
1599FK
1600^ϭsVt,Z?q;a3:WAKayIcz_ٟE%=s葵4 [{vK/:I kdS {I oK/)W~ /D޲y
1601}eآW%1t{I.ZIOIgL|wBxm_C6槯f8[0|ݧ?8_|sײ}/K{c? ;XUnܤ0U2@<1؀-o`zSZ]78y hA4J"rP%qS#<nGzN:#QPͿR`|/8~9㣷o?]~{? Yb
1602GN!'ȉ= = } =rb9C
1603i/r&.%iZ#("-rH`}$XҌ3o얭$C)"GXH`-pU")E_w5jH
1604B[UF]@FN\ŒW@ 5r\Fז W֍3r2y4Ox ș*p"YTO$ٱzD5@Aj`ԫ-UHvFFGUGenSq\\IZa)HVlv[j3?abhvtۃR_Kc
1605IOK87gdM  ?|wW
1606)Ƚ߻,<I_&|33AbH!
1607ЧLSa,H
1608Dd
1609>nY4
1610D+
1611NҘ@,8*xwʬp3r "_ڲ5F54f|gxif%aakhN9Lxoa *Ef8#ve ~U+[g_7'.l?+d}Xvކl:TvcGeNacxH
1612󬄻ҙBvX; =}-͘!f#6V)<쥑,4y`0E fqA`#ƞzesD
1613
1614YH$E%5xp
161545@I
16162
16176% Z*Q(<
1618 rOU@Ţ|)^+k
161974UT gѤ(/"jp#,GaZx~LBwhmYD
1620'tԓ9eXA*󢚠])</&~*"jX1psjΓRq$aǃ
1621ABH0;)9iz7j,}>BPlݙџiM~OyBZ!֒6KFlL,3&4H AΩ$$,~Ty-]`ɩ$?ZnA)()V|ȖpRqL23rx$Rب"e2^xJ<
1622\T/fkhd1JsfCv |p,)p$Q!Ҕ=. jX5줂j1ɫƮQ+T$;_M\ȑ &v'^
1623k uh(stvDy"tg Ohi J:. D
1624RR^<h7txF,$Rd;S-ńwV>Mqo*0<HT!kRW A c Ƌ
1625
1626s/2FSb"ҴY`? (06)wDz}:H' fUy
1627ɩKJWpɟA Msiàq2%P?Y`<7F1w { (iN2eZP%,sF8vRUOr|Ip)] :%5Ʊ ;MQw&-EPޕűQ"qVs?&H]5F1s}ɒ֩U֩,2*nд0;`)X%PVT3UFTX(yմS&_faJ00
1628K
1629,I#pq
1630,@@$Af2d&{W;>#VR8
1631؉-W*MfLuYP){1CoMm V߰+XcH<"C,qHR@F
1632z ղ+Xs}8|{q8 KhlrtP)J]5iHAPj-T DVl.S-'F1!8+H 4ic@0v;nhZpY۳A7tѱ
1633Zc
1634QLB(
1635o9=;$y\?/(󒴨лb|6wnt'sž|bu0㯤w
1636YX% b5*\`0/tTd\ԣ$o7"
1637$*B;(q-Bn޻\ QJ,",&c!`ֈ,01-B3UrK|,d1 Y bƀIe`hS/)\RY7j#x
1638K&]0Bs'Pߺz"S ^{nXӃW=~%e#J%AT5^lZڴF{ >ElZ=FAEAC!dޢۆ*4Ch(%1/xW&F@Ћ3co1越Yu1d OtdS1hc"i~28yAkY (ڍL).S~o~(I7{%̫m%`Q7_yߓ-Wޘd~;slwlˣ٬D:3&?M Ql<WoĒ'\/)DWtXqͽ'-[)lA(h}AsPQ5,i ڌUVRz<rqϒz_q pzU%.z*|c`8z_ᬙϦǎzW\v}=~ R ^#&O2U Ac
1639m=,(7Xd)`"ESY^'7NklLBnL5bf%4e3n B쭛iўg gw|
16403!t_8x\Fp&Eqf g™(.Z/ Dot gQ|p&*^^8Bv_XQ, )Cf Ԕe^d0 z XcA%+GÖ1
1641"^Znh9FT?FZPfG0Sc6.Fl\кlqJNb oQcߘ[/1Ko̾mzK*48#td^:f Y'
1642NtY'b(.diR/>$ݐ ѢCbrX5 |H~U2z 2:EUF]((h|v'>6O=[ҷcŢq
1643k=;m
1644ZJ'xKHuo_Ġͧ翾Rdԍ! ju6%|FB0/*}F5&ԛ_ :+D$tWZR !~czfYCȼ'=E{bSĜT+ǮD㰙)k%[bYP['~TaTC؃+rΊQ],pVDf/{EtVoVSQ~in,rW1XʆBsQ>_6F[E|U\ÆцFCqxFIU6D}mvᣬ#nBbI"WSZ壣{piߜ ۑy;־=?=>V>WO$f#?cNFn ⣺gpFiTonlG73EvhPzIYszG[(ch78O
1645Rc5>k}ԣFk]*=Fi3E>/;т+Ʉ
1646O;8f=1]֣8?gTܪs1uIu3ږ UH<<wŋZ*`IH;*a,s@d5^M-Ng2Zah>c%s.9h/V?!;}
1647\d=b WpѕOBa[
1648 n SR(:
1649ϘyKGFׁyʽ=ʼ`s $(VƐt2/*9ZoQ^ASQ|;D(x\uwb8Ab5yoZeY^(*!vdp-r,ش%tLSY)6o \`+q*㢼&'v"Kd }Q]P[RB"HQ6Q/7gݓ
1650
1651b
1652"] 1x5QJ[q
1653]#
1654
1655٠#;FkhWy`ϞT0il+(;R1Q`У
1656YȢ@(EQR;A`}, da kC $V8"%K#ȡT-;׿<CJ_WkTx]sys;s%2U?deAa$ƺ$W?lUW'*.^psU\dw[%xbU~OG*J(DpWSEQ0cQ&Re*.hAO-IrYHKg'Wc'%.)mz1tSFܜ&(5]Ajߤ8QpF
1657]V5Mtū,u\n]2@ꂀyM>+pkJʏ9 $)+) r ͩ* oD@S)D8ʚ;d@*2l5$QT"[3&H몽?Bx d JЄVv!+ʦ " Ds+5(۪"n^t*pHjQᏺF(H@URpokxE䨊 ĭ
1658&C
16590$^e ~PuNU^Ē/+:AqVQQG,ep*jT
1660ϋ"TJWxM (h<ϐPZr<<@&2:
16619x*XOJ
1662OhQ6]HC(X`9n- l@NF fUmfRdCt`d4z+]|(г_A Hb"ǀ̓9' R&0dFyND
1663rIK8a`xrB M"$E[ԈyuAm҆c:"A-\vSHnUۥø#(J,?q12@A96NFG1h1e`B9:+:ȍߩQ4P=C̃Gg>~ d @Oh2)M-5-%*`<zxe9L1Z51MZ1)E4b j O?ɚ9*kJY"s kEύJv/4L^ǥƵXVi ],.pz]E%mr!u oۉ
1664*P)N&
1665VomdhoTYpOC/˓9"p
1666nTCgpBRIH/B;$
1667$Tq9e Nl@
1668hsE5͉xE3:3 b> }A$XKExݕ!XO@ ^
1669 &uT\0Lyt7. l ƅ4Za)" :iYx&R)b55Ѡ =!4҄(*:e"<HGiC"4@1( bdF8eg$vuhoʣ1Ɉ!/mK.2Ms tU7)T?
1670LHxh9
1671Ku1 #-<T& #M8Dm#CMъ[^56|H0H4%VGUȈk&p")IY4Y<2,߀
1672,3fEG˯Qڊm?ɵ5S`Ȱ1+^TJF :q" Hl "R
1673D28$&_7$V[*m+$0[0
1674c :uvDxU!3$5s`{AXqdHwvpGhTP"'n4MY -LmFaz!/0H9)Ӵ]2l6ZGL(0* tq>Qx'cPt`hHGQ S~G>NP&"a$ .P<T 1aJB{!IԺP>AS7
1675;B>N8\<$s՘a洡
1676ICE=.0"Ow~7 *4XW*q*+6Q dBSiOP^%] X2eäA~F*D
16774T)GN F PNѫ%~]`LGǁGixq
1678O[h52*8΄= #qS}\ahP0_hLЬ@M59Nl>f21y}0-d.&* -ލ~y@mO{)i|@f4HD$ݒsVP
1679Ō0D'@tlseAq7`X'smF5@qu "7槈 Ԑ25> ="=шQ&` BwI'3D@gCY"Dn&]sdH
1680)G)I6bSovEH. ;FhX'!G}7(:g0ʑ ^
1681]Y+LHd2N1 *EDxF2g$c0%A]•D\C7OLB&e$`B9\2O!+$N
1682bp"o0o8AJ<OpD2I
1683_T**ۡCV]2YXy%$wc9}1T*\=y\$*pFzC&'McdTMb.n!Ih8TAD!ILfܱtľec'tIPZ+$$ F, /0
1684BL$ּHBP$:H\dTp9&0{ 3pFA$v3\ͅփ'YǠI;dqbh
1685^$YH+a+bK\Y[QuEJC{52
1686g"IRױ}ÅNgpa2FI؅S5߮KK" Sq't``.p/^ `(ux**qD2YNp9D(+.b
1687 ]}"S^'C?O(s]ARIնwoY.$~_i? +ͫ3SIM.Ϲ?dAxƃ\("#x v]A0҇xFE 44d\9WȼWstI Նg@2{_7A6kޢhѼy]{Uq7Y\㮼kif͚5'hyͥuͥM
1688_عy;/w0.zҗ6g*0v8y_}uqy6rn. vwΐ'
1689羘1?9|~y/?;u^k IVۺЯg7>nt@U0{_CΠ.3wϷ;{8éE?/vpo :%p3J)FXÞ[Lnwv7nqíj_];(o߾m۶m7m X:;NGL}/'Ϝcs:Kkl;wpBum oЗͱ oڱm57nGэd-]>`{kKμhH&
1690ނ|rgnΰAz&vk* V-[:k({}SYS`݇7.mxe <8ixHͣzr3.BW\
16910FC1s Usc2$>,:6
16920c*tYYx&
1693=YC}M5,'_ZLOx
1694nh:٢سwn;7ES8hTa1+owOJnoa0|yk۠a#|̾ w\հy\vS%)ηi/*%&2S5 ĥ- ]v:f1|/3Ǔ5-`̣ wz. f×wM<lIK3MZk :X u>4'gDfpxW61Aoiz ]eegMO>QڷdxȰ쬴⇊Up}R FfV"<٭0,* ggv1_"<-)* /Iʆ-`2uƑ.gXFnMO`s\vNїCowʰ ?;<'+WB|ƗWUܡ}:wfi cԜdf!G@* c^"#'/?/'fe 2 Yj 4m]a!fnA3tPwpXC{G K!‚P×YB߈촞ʭP#b򀬼‘*c8< dxм#Gzs{1B w847jdac8<01<fa&[ Gxa f{G}>zpX"_^&c8\\bp]Fe`_\42//c8Lؙ
1695pQI(p śy ppݠI[1|p cФmnIe G ײM\S3Y)oj åԖ1Iڛ3#Ksú\f0\\Zg `NAʰ3 ZpcNpIS;c8@ d (kf1>Ñc8` GH1i0# p4Ñc8` GH1i0# p4Ñc8` GH1i0# p4ÑpGp4Ñc8` GHHa GH1i0# pAÑc8` GHbXd G&Úh1\ '0#<XTÑ0/ȰPp]|%pdb;vaܱs'u й3~՝1 4iцS;u钀 \e %\;u5Aqڌ1\ڲرKbN*c8"U7)'$&%vV;0#^:^-6ppI[;h]ws5g =Y;&v=Q0#]HHѳ{bGpD;N={HJ4oB:DJ39Ac䆶rId GMnhtѧOopФ%0ܳO;w0#&-T{Mӽt2+%opdФe{-wJ=m@V0;<|\ڪܧ~v7
1696׻{3#Koؽ$w2#Kotw2pЀ>ڝ- L馷ou)2ءSiu
1697%#[z
1698
1699<Cuo _n0\L
1700۶V {F1 BC\{c>d؎-(y#F9=a+*r,OoDAvZ1nӁU xGCg akFCz1[!f 6QY~ނYvƍV
1701QU dNf>j
17029dޝ;l0]xi=edྑ9k w6xpZmZ2p{{ԔzpP3-RJfajd 2wPZɌ0 İw`Z>.;Z ߉ 蓤c 3g
1703&åO \maOؿ0|=c8 :ß1<1\` G`ec8l\a1Ñc8` GH1i0# p4.pWp` GH1i0# p4Ñc8` GE`1)0# p4Ñc8Ҹl#\0# p4ÑaÑp0p$ Q;1q;s8o3|'cw{axt ^ ] jfk; Õ0`xDv5u
1704}s?0q⽕nÝz <dH^^a:'=QY!BACf܁}.,%CSO}a=7q]eegMOqU>8gN4Wk|rٙgBM]J6k'?P6g2,$ MʾU{wSΟcW1x;;<oW[y\ݴY-P'hѼuWGʹoruF [l&׭3s_\4)DRlH(okH]s(k٪u;^V :uFt+:uJ訫2ucK-8,:kbbReT>_^b٢3& 5%|\qsp_R a%4fV7+izMHԹKR2d K1<<O6,kHFڀ>t/4eOg@̬Pt,'/=n̹^Y[oZG Qozg[^ 12ڌj'j%]Ik; 5=##3sH %W8xtŘq &k|Ą s壋|޼@Сڬ
1705z
1706|Ecaѡ?ć'O{/.֭{W=9(M ݦ A,}߄1ŞAnYKAA[ueTOЊmI0;p'//;bTQj;v'>2ef=SO͞=t]
1707lKTCT >裍7~ gm/y`Jힽ?p;u|ԁ_d{͛fفS:|O?9C U KWZj/
1708i{`b5vb Ο wiIn d ,w8 H_` G
1709o:$UtWJ=e]AĻ:$]m{xW?O?߮ |^d=!W<[`I[Qwq.9~_ƺx54s8? N1^nIMn%s J~B,*]*u^]E U$Lseŭ ޭȂU-k<d7/+n˂[/'3xxGn'Mtz/\(Te 47%wگ݂"+.,C!t7벫z-H$?
1710unY4nN%ey@/
1711,o%7'p2qF/a V(FoE[ST(2,IH/x%ޣr!x /ܒFkD*uM%Ttݺ[eȎ*I.Ip@^P]<ѼUssbgCa$.- K{]x|&$eyh ZKƁjDq+p&B+nl:yh1YD:u/R^&r>Pqh:zIyۦ{2O[\RM:Rv+IeDP.QDlX#?i<ޯc˪M2-$ H8 A܊EÅD}!)A/P@5T5+*PD{UWQjGՀ4蹲tsD(ɜ[I_5(
1712UU7)Ԥw듔V)ݰ5^y`,]%.j}!W\hӂ<o.y޲1ނܾr&O,.)vIHc%G 693C\I"U%ڙ@)`
1713Uhn@= ,y^Q1/Uhh1nj9fB+,v8U*t-3+g+E/lÐUϤ-3k-
1714
1715bEMӿM 4N9W6t<Epz$6ՌYB5/Ppj9VKtZ7[U_a̢$ěE]9efM"t|ޠOin3=K%ti Z/)*ONֽVX:efM$tl*Mft{ 7~%I4E
1716MU?ֻY%tgºӪtK`Gռm,}12K fx`{LW~-d-UG
1717hٟ͚8Q[Go6$
1718OUKȨTŞY>!0B끶bY"fc[/Y
1719gfY4l lƪRՇtfQ%360ӵ3g=XY"0KdzYs6aVl¬"-MX5^2[e0`z^e{fQfzpt2KdSf̚Y5nئ*MU|K5O%6iչ!I!ӛq2fLLwɤ~i^ifcpSmś-eVg[XwpgAUN-j<%Քh[1
1720/..(j
1721;dU}]_UΨ]2O<ye-r>cz˸&EρIk{PAvWPYQI,CZ}m},G4gSS`gBChiv{ӓEI0:J[͠AwMz:6ߺA5>["͠m`jCF8QoNͪp{;p!|Ј!'7mrDwwA[f͘K:xIfBf+_3憛esgtG}ɧvꝇc=h9SO?N>ྲྀF:<ISgv͘6C~@9O#'Õn"sþɞMen7~LDiܨ{rT]Gs;1Kg͹믹򒳧useÁ> .sos̳N8rNq3g^9o4KΚrW&sx#N82g5ͷ6!A&1uɬkLDnkQS622L~sxѧ;<c>892Qamxt7 >м[?«o=̜ќyE6ab>4̍}<be$s#gȑ'_<9 GٮM4skod^tґ2s]ǝ׿k//Y8%ۥ5v ]y,}7_ynx؝7Nut^^y㭷x9#s洱;u< 6Nc^|ü^$̹=esQH[rKn\2ͳ_9/>ǜ?ů'|W?쉃*C&_G^x냏?לQb g\},[ɪU\Sٜ2{T/dn59~uهpGkw{}ε ~Lgç\~ok^W6>_I9y˯׮z-Oҷ;>^t//_fuk׬Z[gN.gI+4wo*~.|2 ![/os.}ѫd2Isz/ۯ?}wɼ+PR>G^]a˦ +a6yK]1yzUSO"$8bڕ,L0[#e6a>ks>˼섡mGq7?]+;W|O:`
1722lsOj2WU'؝́'_+||\f7fs=?Jod'9S%YK̲/4O^STRgRc|k^{JsۃO7$ٓoXfd>08ו<jZ߭E7~%ꭅ7Vl}MO go?Q.0o3I&2ϺAfr62!2TL}]p +ҟݧn>st[I:.Ō<yܮгoyzm=$39fO2Ϲ72-ѽK?
1723r?kLi ;vcϽW21{22{#|go9{L{IGo,,z2,aWN_8W?{9W`gJ vK>ٝٓz-QfcYR]SM
1724 Aެ- 34&}EÖll
1725<ThJ,[ߤ)}`3ݘ__=ˤjyףpٓzcGԘ2^_evLzיf\A-ѯձ Uӹ@7,t&R>+219^Dz3g)R,˞<*/ps\[N=Tu2{;kse>eb,_ohrؠ4hi.id>z]驻7pڨ*hȤ֙v[|ל|`I|W`~9rG>2gF/ޣ{-2sMDo`W[uYG[~<qdtŴ2g\˖/7݋2Sd:'T{AQ\K?G<uk>~{W:,]o<u_x]rߑE 'ç^&z]ן/9`+o׭ͧܽ2KY"JvӯX嚯VѻK5US/?5k\cְhU.]kj dIe2iGI抷{`yڻOwf?b>\هMOeLŽieޠ27xw?Xr{o螫s
1726;,_b?]\| Ͼ{oUfl:+W,%~ũGZ8{Aw:Ȳ5zγwҷTcdnDbW<r ^.~񥗖>#w_7sZMm(1,|K_XăwιhalٝΟsO=Y&y8 'hd>ۮ:Cv,"qa /ɇ悮;2{+s]NQqǏ.cna 2?ff;|߮xw|ŧ=rMK*0'ngw7κiM;֍w SvN~w//#s_'^8;ϻcO0w2#qEWd7R <,/?w}9ؓϝy٬}_/<sQ{By'3oWΞ=K?}JA27+If灿f#N;g͞}e3|qG a2+ÜuF)iOc&LzaߝFu,<y7~Jv>casgL05|ร'L;v1vno 9iӧOr1G:lWo2I9xŸzI'a߮3l!9eډӧPCRD ?u'Nrܟ&ҜK a#Ua;[I6;=(0G;hDlږaSt}oI31%#G>hp~y,3_Ws?aޝ2qK-[8mʾ__~d6r~f}7MdoC~&cdnla&קuos`3ۃVz=ɫT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJURT*UJ?*j͠mv6v_5elUf|/sf,s#2x^7jD;={/"5vcȈ=zmnP*b͜?r!csRpsw=y}h=0j-
17277ܾwW~aںvM8yOއdpޟʘ[ <ϼG>d>{g99~>5Ly w' Ze<5oٝz5wϘOϿew'uTNfS^sVۀg__~nݺ>_wK*p']u>]v7'u'gŷ.|egk~󍕹 ~Kn_}y{Lbޖcwf2\vݺWΜ<o s.2׬Z.}/2oxҾ9SW}XRr_h0?{WN>;q)W[l߂́#]>[]N2ĜܲϾΖsi#zb~黋|ʰ2i; rU.wE݉|gMf6欛|{:.w_}sfMIz-O2|Cל|@ sO桗WVe~L栃fyd=Q/=xIe21W6N:q$Daԇ] o8mԠ
1728lwǒ3]jsۃO7>]Lj T߉<Tf#Ǜl`~k^wJƻz'sUA"sϿ~;Ot!ۖTv_p+^4Kmϼw>eR*APdTfn[ V*čwr1I "w=/ZeO|趒
1729t]tϋ<yә0ͷ2ۨ{~9<ޗFf#sSi]O|錿ޥj18y/eo\a칷=_&1=\dRJ&{RT-nzΘ
1730t9fkۙnur+ ~dK5wL_Ϊ5/CU`[zx~ݘOfi62P*pe6}_LfIև̞^ʊ?Ef.e60DVmdM_?DO[C6{C#dO٧QVF}Z?|:FEfo/Kٺ1t6ݒn[3_fs~ռ mЯȇ2L\ÜA;._5ܮ̘$tMsssfE/.ѣLhY|uLO֘"s'715ZcĜn7?Bfr62q̘_Le_o_}#M c1].7TnܶAd2_25Ok[Ĥ?Zϖ=7KpBV XfIl9fO2 ?Mfy98#4236fy埯5VwtQ.]F7_uZTڿؔ}Ozңç^~b\Gw_ۃLüO_ sĴ+dgůKdk)|5?c)Y2rO_^ŧ+\Be }9›]Ge23s͚/{ieFřU?@?t2WycKLKgc.{3|cw:H^l}9y?w^]mWZG6뮅/ފFeҪUw/|eX'yUw/z2`%\=2(| e2޳rҳ?|e3[m K_\ăw\}wܼm܌4g]xm\?yГ-}en .Q&3z)?^';c^t?<~-W3 #tڥrς^q޴#^R'#xڥsn{}Ϳ/;w}2f=jSλr
1731kRa#vR-ݝw#G oݶo߬?.?|ĈCks wsȰ#O:{e2s 9t[pv}o\KmٴOЯo{melF&9`=D9j&>H-O?T1KXT=ӯnu줱-~;;i1LuBm҄'=u{rw>uۚg1nI[g#I /?f'L<j4rZV3>\i.4ǵN>qZ7mesxK$7.9w5o6Ϳ\?mw?m5뤭ӞF^//i}
1732v+`G0jO({3G~dDn{n^9Lr3HrncR:qҚ/b,7{Yn̙n{eMN48uO<zbkJ֝JYӸ"lo~2:^Y9ݠ=sq{QAaT +>g石w+kY({B;ي*)QmN°s5d0nWa䴻iBb݉n-4H-Z na-+L波*>{H+
1733{uCŻ~*>sz{{^&^RP
1734]gl^F|:ACg։ 8o4mxi1 }q'!J|PZaYI:_)Հ!*{5i3Tk"2m"5uzPׁ釽Qx;dH34_9Tj"VV|]gutf5w!^=򕝃.\P<'__cӠ=LSNMo'C򵝡ΡRk;+uEVz<: ^
1735`[ᦵk4)?.@(ZC&LTȰ
1736kMUB^\qUmVղs5Ap-UIVa0/Ը}>ցE
1737ݭ{k;C>To*S6_٪ Zf'*u&jVP
1738ڧm *ؖPln)o:؃(jۛI_(IP_Չ5͙ װE UlQ[V%[b#{ }\!O3i2Bgԃ*RQWU\+*Vhւ>UcoW[|GQ>
1739@Nԅ*@yz9vT1Uj*U5W Ճ UUjA}j+Z>_*}Xn|v^΅:͡ZJTUTsڬ@ZT +ՂV֌}Rm1j6q*=Cڽz!5C^UmԊU2"Zj>Ui3 Wom-RjؖPln)qzk^ې5ĐocwܺIGN:f8чC&!;5k ͙݆4;v`CC:;]ƍ0QZ+x&3?[֝\d?Nn1 75^j0ʝ?4_I"G8q:倝nHC0i=5(=F Fadp[趧iZr ARdZEۍnLGK0 ]*; Ȥi irLh`N6Ej&c0)6HQJa520
1740MCq.8C-^/V4E8[{,r@Bm.ORʐ*4b3޳ 5O
1741d7@/> #s'XS1B "uf9IXd郅IFЄ*j;lgm6˧<+ :Wqb kaKӕ/u;%u9(r-e "I]re VR C9ѮRLEGK\ec _MԙET +QW2̹8kz>KVsQ((h
1742V\VE e<x<ae
1743Ji|
1744d@s3jOz=b@k 0GEsdZR֕aveFrRRB:bVkLjf^Dp3UR@U0 [/0b\1!E8E8<P79m$γH 4_hȗ̈ErQ*`
1745njY @r#t /*kʗaDԪ4ED{˜ga! `t\L1XJ0%M,V/1/Y31Y萩QxԒ ;~z$לiQwFeK0f
1746 R2O(H!(` [ Su`z$2.Fu Y\7 |g<*D
1747 +U)N`e-2T
1748yXѓ)dH7u(`5-IÆ5ee H
1749OQsHa󢩺Yd2? d͋c[(!#U3S ˡFǑ,,ފ
1750w-ߍiE[!!g,iH%1`{0-\Cu|SܞHȆ@%]k+N-rFK`#\Ix0 /)3Y7?plim.U_`  Z~2UO"Jhm:ƹv
1751q͓O_ųrLG/ Z
1752qc9bz3_neSjWZ`fqeI\߅2qWtH{m` #Xe\ @2cZjp+ElKpJa9(h܌CP7`+S֒aMGqJNDlcKXکC4,帼H֭$esԘeAx,? / 3AcO#v!2A c#VD4c:7@bo3}d,i2r M^x-Y3u LF
1753ك.gdKBZx$ǣ*C9Eż` Kck`NS8<\v"Ds50*S 7.T;ǟ3ʂ>Dv.!#$h}sEӏY\8\+G:8fWqa3F~S# #aѥ^א'q4kc:Xae>
1754tPILw ǃ%!
1755 |2r\lfX|}#߽,pIvdH-̋tQ+,J4T=cZDbq?"8VD]YO4Mgic`I棐 @d:<VwpΦf
1756g$̄x@$_p,I3|4/,ҕr|~YNB/h.3%8(À^{j2rQh$F
1757/SzfHJ[@'8 -4VKI3OKQ4(ܷ_?Zy%i9 3PDe$j6"5d43 ")D7AkL8OwO5zOמ3zM_}NDa" hl:uiY3h\aBmnľ
1758]`/eG͍5E C5m12ʉcD1 H$I9phmRsT|q(E4F~F0HHP!
1759Թs8d.y]~Q|%FWR %* k!$,c.4]>ԳNr#RdZW
1760$bC,,pir 9% "Ѽ4,rAЉvûZ,Fr
1761zfR rF,^cb>! j:wiY2a({z^
1762hNrnf",w
1763<sjʕΡ7qy[h "\p .6\Zah3X )| ߦǮ\A!,>0IaJ̐Xa&cfa&ǥA/G ?+R#EIZc#ORp%E8?l欔4mN@uBJ䒂NʁoZ|/T,rsE轅4IH>D
1764(burZk$A: "~[a"
1765]Z+4o"%- $%Uԟbڸ }
1766l3*;5]5% ƈ6?ְV1Po$ s6Q(Õa(ve0a+bs<B÷_cn!cY˃}N=0I|BJ=CQN^^^)ȣ&e͜K|xD<rao,tx
1767H<+`&5X6{*xHψ
1768@{H;d J
17692E~LQ
1770,gH0Z"S`Eaؽ{qةH'y! 4:^]#pϴJֳͬv|(Po[z|3'`8 '
1771pH%YY.v0bq`/pvlk^E1xl,NľΓ (`
1772Łn8ތ){
1773t
1774Ȝ
1775ӍYYƧ?U~X䤲jh.ZQ9b*@ADxE~l!iKѬuj4y1'PdNoET%\JU(cP5FeO
1776[8f{s{ri$pF#:/`L 8!dIa3X<0!'_L c2,"T,Z<K  *tߌ""'Fw'p jfbKB$"{ n(iTv
1777a\l@g/$wW3'ŷ d$ԥ3z0uf0-E ysbB
1778@ce*L$$Y~,л#[G'E\e)\CmeH$_رyٷ״Q7?\J
177918l5vNlhw,d<@(WCk9\XGۗ8tMѿ6XiĊBC0hs"Hd:v sݣij/D--\ d~C۟-4qYfj\l-y;X s I ~<y9Bmz$]k.Ԑ6g$Z㥦M:XhpKh!@:pe,x0.3
1780F==YY} Br,TKu˱X=VZжHBZ!C"Y@#AߙJ0nh9L/kȮgeA8&BHN+izh FR) NĖAEp&w%'ʗ
1781Q%ho!1$B!ˡʄՂ%?$(F@dRz0:G[,S"V@@8P/NYlmu wc8QC9d!c@;6"C~x\![àbŒ-qLoZrДhsvN}BAQp
1782/6si3!" x+B4] ƫYC|?'gI%\A0 2(DQ3x^t_֖m`eafЙAm|‡_+"Թ)5#>: u ]O;?9r@
1783x}9x65,'q# d+ccdL|s@5<1JF 8 2xߤTKf!Q"I!.W0rB(]#["$dEr#y9ry#k!ˡYLWT~~:\4Aᓄc5K1.qThQvQ9-b&S0É!ZO%M6 mf8|Үb9t@L`9u6hCHawZ'u
1784^d$
1785Y(҈*dlra<|96E,"e
1786ZR,`׃
1787=
17888 0GQ[R "8&ź.<J:-àqN9#BThڦzHhˢ$bXY<zM/VO jGez64}LcT)hU3[rf$m1y+7_nu~Ȏ%:!}=̾OdWB
1789 X+5T:Q^pLCET}䩫+$Be5GTb+u6 7{) 6i Pg
1790Cc)
1791e<M"c)n<d:Xa/3c焳P46,GTW@+͉g.6E]v@DfZ-"u)B(#+d9V ,Q㢲+:612]
1792d9miNZK];5 sz
1793K4yjG{1B_,5i&j-vg]CTk| ͠P9I*)quLϢ L7fry^g
1794Xӏb=.FS/#YƍC^5O;dG> pF+m9O\RD3.5Ej48GH +PAr=5
1795d d(jgIs1bVZm0|!=xP1)0,╅m`3]rPc/|@C d$mڔ5$ \"Kd{Q-Pgyz,R׌ UY!iC<(dLo(d1hJ:O#a)donpζ77`sS:-B4;Z(XӸKJAHP ҂*xAW##)
1796Q
1797Q2aQ
17985KenE&ώrr퍗K8բQq 
1799kA[L"YafJ(eSb ,g(>D7&@Ci^a5 'K]
1800IX8`v:Qd]cѡ5b]_ⱺЩ[b^׏$r8'-DK=Z }w\BZUZ&Iu1E<(/p*Vhk g$d/z8׵2]\Z8Ý"lmVD3cKe$x&,72x֏͡(G (IO*Y,l)6 :-Oz@.8cPfgQ[ErO6XӋy 2gqI#Ȓ :z^&l䏑d -Q z]'ˌFV?l(bthH +49|.yS;t,GY&=tÉƼa\e`ND[p7t䚊Xc
1801UcsZ@Z 'A" ^[7*oD0S"rku+"Ƕ)!!2ld5C98\h,<޵y:H#5 TDpqP)_Zi#Bayk[! D f Y,<1by"y7ZV쉷&Y,
18023$F('
1803'`i#vE:da4  8r+OA1IGMOÍ}~@A%s&9&F Oq=cN!oQ6&?ta-vqt G9M(@q0B[ChkǹMb NXFyp0C3W
1804Hz |PfƐ04 3 mlzȟc$s;,Q6`iI1bH k8wFh
1805 ' "c?\( i
1806Y,<| QQ:#*(}fwGdC2,`2yH“^lFA|Cdp" `
1807u鱥!3ψDS^( e Qv%L_&z9@`%klXy-P :%nhjeX`=o!]>zK13g80Cy, Q)11Cñ֓8yz]gsG`wj "4{
1808两I*T/DX
1809~-8
1810 X
1811
1812+Bԅ❅@MRVX}^ng/GҖT$:qx,5p,UQL5"jiVL93J8^mJ
1813{N5}&1*\C[TӦx͓pK@bz8M6%E0k> /
1814Kj.WJW$Q:y8R,,{02c4іsuDc> [Zd@wkEIYգpkX΃=֗:knG\b1Iʇ0 aKʇ#Dl)Lr* k0{Â[dbJd9Py56BEpoˮwDoEldecDtNjA~.iX
1815o8E.XvcʔXnGauGK3/48͡5vI܌"u7$Y)nF:ƘwsXB*b9#t0>ԮBX
1816jQw Jk(;H)Ov;qGT|<uӖ ||5t>-28Apl@NSGrEA.oQK% _$|;,P|ztb;0Ӽ\2 E"
1817Vc*
1818F,@ 17e/@<# +mrBˇżЦk^(cY{W-7l3!-XN
1819?z))=IJ.#ʀ'|;}+B1p l}ҘԝKuE)plT?q8AsJ\[@3vCaM2=xQw˨8XC̈pG=NX
1820m)^h-2( @p*Q,@">(b<egl Y#hKOXB J  0hGp$rLBN?7ݨbx  2ޠgV0R+
1821m4S+%!V?qfZ @MEC+0:aέKB~e2t)J1P@ chIe8~F (~OPBq"J+0H)t*nDq!.%(۫o"x7>8 o%H4=_W fګ0$ Pl<R`g, 3 hўuT=Fˮk-~3,h-
1822}jT1 p_Lfuư}m
1823gdJ-c,@?evGCxFKOzJ`` 14-:`(bNd,s%-Pf d.O`qd81 `60hqҸ^ ЯK3F@7`h4ړ́@f=K :q4)P6)XqP cܞ. YYhހva]S*,,йxu|FV[Px6fц/VGF
1824.f /Бi?N4[5tm?[b \e y jIN/1 "Y}kEJܞ3JB2sѼIN
1825| /5=ٔ`r !_Por fa'^x=8_ş]
1826טQElI::"6s^?Ix uO_7tL}F h`IM!G0"bv2c;[gVĆGL
18274"h
1828"2dn0
1829lj#bǚ\b Ʉ-߹tGZlkb{.R<.GVgݛn j,u]kkwS ? O!s(K> ߟC?'`[LnLѧG!Sz Yb*d/9H" 앭9;u-j.=P$wt0ɬ*~U}Mjwћhhџd
1830-_'pi6ހ7M-ކ4m`JZGFreYI6sЧF}Q$u -B@pBb`9x4S* ExdO_4Οh?}FY~O[ikik?m&M?>ZJ,'SO>ei?>gT="0l[׶[5Qsw_]Z34l{6?Ra> oS>W>||*$ ¯Hөx.4?翳PJ(TE jm!xW+;#09[0)r]<OR(AQ<-P Š-HNa ?SPJ8K~ft6k*<eADT_UO]vo6E$py'6`6[De-P~W[UZnh*J5uɋ28y1,'4
1831?Z+&
1832{*bXd8Cr 5P5i!q._dIcmV3+4,[\~ ֖XimIf~|f`fO g[SSC^YBy-Jp<gVUgKNrV,Dht'p?y:ZqRm8-qCK$M(ɀہK(8%vhlޱ͢~ <-!nFC͆XC ^4A$
1833H!;fDA*шLF[)F1xP/!K1 !$`
1834 M=⌆x@l`b,
1835-" B^w1h Pp  E
1836< V_uq#yZ$^,H))>6tgXU"OI8fEMPnw,zT,f1uxCun` 3 T8ضq74L@ִph"mZ-^h@) DX"`e%!(bZ4K Ϙd(4;V
1837fw 7],r,;JӋjJ#m'K#8hCޮuޕހ],Ue@} 6.@׌p ڊ
1838 9lྨ-&,6Vނ,`0^~_M)TODu8&89?t- Ņ"hZw૲Ⱥ/"ЌcAWVo2}4%P*(^E*%mMhA'7U$+2Hw1,TXkN@1e/C
1839 ;ѣ'Pe2b(`)$A|7)^!,L]eYO]pX[0o5P&ӅM^ھ("0< c$l+M t"a_I3IR$ cR6X1d_E#<ӆcAYJuc(pÑ
18401WeNmoزsfgg;AU봫N`3ω4
1841ͥDylKʙRM4Y _]$iםm@{ـ#U\Pl6j{a#@?mr={+T[jIGtL,6,ꩆ^"'<aCCƏSW
18428zKc>
1843ik*i v\w1E)Q$ì VѴVzbG+Qq+~G&]5 co?S<D"mDht.i&/iL+[U^l il kFj9_-?cTչ4樫Û ~ڕ& y,ֶ'kfiKӼ G[-"7%kw:!@KM鮖x!rS?&~BH6yd_:q-b_քD=p3=ufL>0)xǔ1 `踺ʬ:J16 `Bc?AJ5~Et‡rTDV:s5ٯB )SXq/ԕ,] 4XL]SfڰQU/RI|C"EGëC?'
18449m|m8NMyR@CUԞ4iąed,VHL @&0&,vhj21~x+ftaN5a2N\:y=NؼԓSd[o(W>X`lBb5
1845mE vVY,2i8Kb.iBUnNZD<,{!Q$sU{siua r-pr?mڣ ^ϔ!as(CܰV2WF )3gXbE+'+I=7nYƼꌔިe"~ 27;,Ol[Ug.%p6ekPq^$8m<1&_DrR{Z<~rU%ͮe8_mֽ
1846
1847je*5@sY洓~x:'쀸l|!ʄZᢏɳq1]lе{ +>;xIrrG̈#7[./2O'reK=^OS͐sp#W'.z73bcg)//ds+}z=i )ܠ2˜I""rU.T~%c#ڏԬX>,tJ8J-6 MJ&"ո7>#ҙ t9|F}
1848Q|D&f.0wBsjH}\HvBj6"pjĠ߁DLuɕ1x&{QT H$rA*{>tga^-X
1849ͷi9U{JW@n?OoBz;붹e%~.>@/Z0v
1850'd1\]N\e˟u:DÐ{Lnzp^eW0 :]$ <%&r1e2}-
18515VKdLì5QlרE bG1ˉE-j_1 c1r 1Z/{ν^'L̠CD /糾~yN0@wO 0:vQXfǁr
1852Q뙵5by%=3@̔tn]<]L34AH9aÀ/O)1VLqO|/6Km͘f->+:f&
1853YWY迂)Qk:z<ǽ+Jq{_+De!ތ.fa']7fC 4h!|2G3^(8m |r'A~;F"0Rvrd
1854\_礗a k /, w5- "YOV4'z\ʝ2rsK^]CArsZ;2-c~C 5w^KG̀ 
1855y}ä'tDc @BS}\b[oHb;Z0Fƴ*Uā }qt;|6`w[_Z-V(}bqI5Z 7__ưɏ)ih2]0#:(AǚlDeYУY.룁&[ًU06(vh'IC<;&ƤnpJ*j3[MrLtn8GܧM9O)H/VpJF/_y9򳌞h*f,j }N+ o!x?4+#Ͷ@EIGÏ, e9 }3$G0[2
1856GN$,# A6V
1857eՖc| QN'_+`F X˹%9~%A9 lϭQ ʘ9Q`vSj][HjKW\VI5ɽ|ɉ{]&tݿbЪ-cjtSY*L†4Tӻ\Vp_y
1858\tfgǺ1 mioO*`RM2dXIRSWUìǿHs0EVeJl`.Qbdd*F
1859\@q{6~|z̽J1Ӵ;5 ܺEc=+z~xP_8||No?r4
1860% ~/aH|DeZ!gd >^P%?$GdԨG4c@>ƿ1'*+~: S7i?h}uOp;+[^OdSD-U*{z%^d7 _Z.!
1861Q9{(M'.2z3?Å xF6(
1862R=EB@*K>]}/@b:fQ}cѰ| 0a F9Hy`=y՛*P!oU|>k i>q!㜞p\]
1863Aٶc f/Tkw`5Ⱦ'Jɽݗkv9i{Զrp7GJNLWvrvڹ<ӫkκ.\dg.$]3E{dzCړ32`OGY{lϹS{]{6wˡU^\^ws%U7؛*c&nի~s`yOWK ڻF޿D>R}&iͮ[f_^V<]uN;v2#p8sduzr p:bك#I͑5SqKGXsUј\vqKvRivt
1864NMTZ8^bgz^^Ԝ&wV:㸳p8[8Ź)%)S+U~=q9gȹp OO)+v(,9-ҩi5aOEN"uޟe:/ a=}sYqV]J3L\g+M j䪖>W']i2~s_Rwޗgܿrӹ1wN޻J{rv]-w0*t0޻gNؽ
1865:ȍi?=؃']VO{sOG=OQ3niY@yq7<oEWac7*Њ֬><H=ob^N]'-|L+i޲ _=<n.2ߋj/D `Mʾa=fEf/ҧʭJ[U~w'҃<}>(A}Ċn B $Щhɱp^B8t4WL|2xRE^ z gN{/t.8;!Ǭ5\@R['T P}C/jhnBaݝ9.prvb68.HFdVŧH-#wO l%A_;9+剋eIѽYb𒮒D$y鋐oD$J^<EvɌJΊ6zSRP-u䩷C1:þ\u> O4IVԈYfLw3s?]2YЧ 60/Y;B&b#5 -9?} K˧#Mh>s݉w½np=+<ov}M>-ZG8+B9fDRPWYKR"%bݞWљ".~*;@ghUZ+vZ1&SDzY">Vb΅'ug̫rVJg;{ܽC緙x/Q/>-,Z">&.R
1866+sy('.ڼR?6dV$S<I6.{?SqT;LuA#@9~MWi<'SLϵ^
1867FջiW' }>_gȸ<h O\hYyT[8S~7xRxs:\sfx1KfF_=}Γt7U~Ս5n߮w5.W {j$#} <:7x4Ey8^}5i{4k<bu^]V{C`:c=?^ΥYJܮHy긙&ɳtD/f<ì!j/Ջ"QGٜ"jy2WpMxIotX֒Ƕ k nDuhQ7>Tfb7)6xF[mϥq [=\1sQ vsZ*3x2}h- 8ow#D$P GK(m21Lgba pHq0Rx}ʄGw  "N> Z+9$9쒀>xZz T+ldoopduw0ɸnSEnP1i+fً)nY֞pߩ
1868,gB~֢)`9pL{X YXDUY@wbx,Lt\;qiZlq=5"4VF U;>ŽH95bGHX6B])Fz9. ޅx
1869Sݍ4zD{SGvK j4#{<[\eZ|am"}R(m#;>Z{Aӳݧ- ɻZ...<[rRvôREYl=V|V]H|*)t{ˎ2D^mv#-ytiJho!EX0=<Hs'\@wHS?'
18709S^.N9Gb߿7w=xuV$c53,aV U %v?o+Ş=Sʞ}yZv4kΖwkS㻸Do)O[|~kj>brb?c.^-3!y@Z]\b3&؀:) NN#ՓUi9JFLuf], ʈ|&e2H9߀fpM`ohςI{P(sX*<D$~s:#Jsȑ[W'^!Պ5(HG]+\+Rf?RGً9uhAw%!+E` y^+RyF
1871A2Ꮩh1)n.H'#O]c H߇TFHMlcJ_G
1872}>R8+uWu.#bk84A2Zd|u U6BگfN
1873ڞ:|8\ ʮg| ^AϽ5X׳lM%0M4,)DݭAo&uΎLd{h+ uvǬ̌ dqQ 0ĒUS[>0 7td$g]sdvuћ\IJ"ʐ :;W߉f0\+1>c1]L&![u~rKZ ")E-!wR8V39 b7a 7ߣzÍF҄ s#MrkVN]+ v}7+qchdCV .<[X7^MIB}kT؊eލG[?y1|6%Φwy7ؔlŴGV]r,#ufSYrݼRo5ͺ<L!+AS+yW^vn}8~&mjƂi%k{'A֮vya{Y¼Մ =VQ`{|5 Zu,o@JzOs,?"V=KTNg+ҍE.Y>c<X'>r鎞!K[M}nUn/<_5iP~l/'QlWDw?b[yem+p7O׷'|6ER<^읾fe'P}+Whcz}GR;> ms4¾R
1874eOW6;rtԲu w-pTG-?~;2>̖Z&[ȰK7toy-- G'A=.f>.o>r;tN-G~x-m)[<jl~]+ݞ<7${ؾ^I2=I2)I$'9$99
18754*" EiRD Eݫzw.۔$3g[yӝɋdxTMbTXU6qi-*2
1876KC |5pfnեXkOsӵay%R_9 V+$Kфvͣ)ھeXURSJ(R0֯}麏A/6 uZ,q> (krfA3kf(q[,&ә`p5&7mz?vF#nP1R#<Qw~uQM屽M.ug@MnRW
1877j܍O' {*z1VVXOSSilii]Vzl&rl:*ë4Nr,],T*Ž^igD5✛f{ a *w7׍^3213Djw%Ez1ཝL]^ԨhF(ڬf:3{hb6r\nE
1878sӍxc%+ߍb®cGCF+5콲˝IcWFNdo2Vnu(Wٻy|Z.7;ހM3 YfEV\+zs{Ԙ年XkP"*u^E3Ru'Mcg6$W}vUn7g}J֚GJzS4sVطbU `֚ҋZM<u[S'k#T`A*zC/*OHY85t1yJv1|`x_ƻodPZ|)bnv1ömkmRbk20K׺+W64dQ#K1E惚IZza4o6I\;cqCFyҋw-7b5Tbonf7db VAc_?1sUnM-.47,ـ8NNߝ][ɴlesrn:95kr7&oAW3<F 6"Kt:т5ЙGI9UꎡR947<S:/-GG VCgA'CgArw4 </ +I~fklfo tT-iVzMY9n؊R-1=k2ѯ‭|ɍ2jIexŔ$̖?6_Ŭl?a[ >TMREʕ-ɑ\VAsf9v9l@5a86vѝek\6{46RxMn`7'dM4~cfdc*k:淳Ԓ3r"b9 ϒƭ/vJG4å5y=zfz+'=V,\(m5d!i{1X:3\8#݀z$O &j0QՎfޤg3+E~^i,|{#/ `*Vf>S:!g9"OYKe,lY=j.foS]^Pb=dS/)"UNz<fk,[i떖r@h#Y,[vdO^O6؞]*s%'(%;ƌUi9aes-IT(%LGFa6raが5̱6*vd4Ӭ&e H-(!FUbU-^.)Ɣփr2XT˕+;q$_ֹԳ[ҩMfI9U"cNo-WdO+swАF+25{Z{<vWd^ipcVd|n"hGSZ[ձ"#G ս"Ct݃+"R-jYѬ<{9V9lgZmyI+ˇ#߸HU^F
1879sD#60nSբΈl#y4o=Nrb2b9ʸ:Me\]mNp9WWB)l B댓TU^64s#ٮu# px8uUx8ժB9"pxVxx6و?N\kt<sϭ"8K@#t#tc
18806"Mk Ӯs#0UffW*R לP^Hhc^Z1̼6pm lDlleR6Y76׷;zuT!}=S8.2^u+.H
1881dn7).`'i3
1882#ṽ.;?SriI1
18837ܘry~}ӻ%U3>oV}>sB<gDqKYj??~{XuSU3Z=utY9tFF Qtz#ⵞGi5 NRG)Nt;#Ӌ>Noзh:X:
1884F n|J Ӌ6_w4*27.NopYm@4T'L5$N/NLz.nt4?N/FUYb5FX58뱂zlوh:X:Eܠh:ݒHat&F44Τi`4xc
1885tNbF:?9L
1886Cz-YntChk겜:
1887crS5HfZ:/tS^X=#Έ*ݬ5mtg#f_q.Wy]9J@dtWk̘)Uq̝Ɋ|]m vkNfk;7[G_h1f;yFgq8 %h 勡:=]v}'yL31ξa_Ic茝8ZGs"e&<aS9Qx:7AWG
1888쒼ȍvXbcFyC)^|!QZc\JTsgN-PA$:R:]X3 [-$5bBv¾v|Z_˰(o3,J^M}g+tߌ< fF>#E4ÙF`8c#F۟=Y;xWg5ש?KxzOS; gIb3/{U6C7 +ƜpGQϭ;Ǻ愻NʳOdyR^CNf9:~{*> {-qh98ZD̲e3Re`l+V%Y
1889u.F>n'߲h,n+vW9"n6$\:yt] +k<.Onhs 1l1U11^~S! ӝ3?%0;6LFqלܽyqAL+D!%:6\U>u]* ͳ6ًq<32(MɉtE7[?iqRtzENyjj0ق+s'yMglJnNh2.,{D=l0zr|=mB4ojraؗf}hl6I?BӎO}B:= څ6xՐq/=q)L6:os+~i$w{iaW6t/#Q-wd%ZO폪_QSe <mwQ./Vg }u(/>M7n'3IᗺRKigڭDO![*olX|egrvn;RI"8tVd<rY˝ R6 N18i7g\+dBbr*k-gt2lʝXeηE1;Ekc%i!cõtXJ*
1890n _9ogDǞex·)VP>z(5P>o:SP>Ӳr(uʧ%e~SXjgS <ׯf_3 707ɩ~mT߹~sCg*z~P5gR:峝sEzC5\?-gdw3d]s|~epɹ~8OeSj65I6HasuhĹ~F7~ J,l3~S]tK s̯b|_u]oo~Wijй~*rDj}3_CR~[Xz3?O*:,p~:32\?]'~ugkwy|ugk~xY=xxH^<կ"|Ŷiw?|8_y~s,z+~IC<Tz?6Py_UGUD6\?-T?:kābUV0G[j=Oʳڳ6ys̯B}q y|Dղ\?qU1O1S,Wmgޥ<ѩ:Z~LۍىyRW˺gk^Y~ISj=|`H~#3$V}i</>KRT?xs '᥵gYb 9ozntm wQ՟g9l#Xuuj2F$Rgzn1iEUm:dZn%/=e!0rZTKI[J'vܩi}F=ٜaoTڱ˽osх Wr+Կ;M%}S靽H6dw=L$w3_O#mRbwDnldlndv,r38
1891x#Kۑid56Y\?>>ΆOzτ{g+ݞ6: :Mfa0]&[{'o칛qO w#6;B]gÎUf1m07=펴nmM0\KONh@+84ߡ8R:GgȠz:HaEVAY;sX{*no G'-˝4r%}_(_s+.x=ZaE[S2ͧMU<zGYm.ݤ+x" ^woyRL q+nw+iYj;j!ϼv]݁{tOUZXϷBjr*un
1892$iM#t5xBa+G|~䧿ٯO!(>!]ivc( Njѓ7"\nŻ0""VK9gP,
1893{aRHv#!`=^bod)-gonrӷ/ 垾K`:m4,];u_g>w D[䟮{bP>'՝{T$t.6secD[E!dbWZ~"$}Kl;ݻ콝әҭ'sgwӮ$zkr~ř|ΙL[jNཛMD|MnVYލc\eUi@`kmߦB4+<d?"c?Q[̓@_$6v~}4M$uȵ=Ok~n֢Y'hr^([frtLJ^̄z.O] 1h6.=6.ş}c鼵_>!T\\i)NFEшX[T"`RJ-˚ZAٌBC
1894XVî]Enc349#'|b+Vi2xzPj<.]cfG<tdSRhG3?@
1895P$c/tą Wrsau&"zPONvx(d{ R)!tx6uD~-#
1896}=LG2} eYU ь~@W3 crvb7!{O8k^ܒ.?%Wnr:#*
1897cBi:ڧV.wGn{&zb}qrnWhfshUR~lT~+mZ&6x|<'RcIgUŊ[:UWd4h/zSz7CD7wh|ngx'SƾUN%v\g|?Fddx>勵bl03l{@D?@K FHIQRSFU}\,Mz!vl!Mݟ?ؓPV}lA 7I3:
1898x T9[ oܞmMG}K4 3l%Unq2TNt5E1QH\ Rb:֖Y[O&3͌v@ -yi{IG)!68+Dq즊%a#yr+m]B^Jq gndK_|"O _rg}7Ūtc$#Mt71/it,NoNiOx}xхLt5[TP~vR>F >HԄ[ fH&##%AU?ا*[#m5DT'[H'ltsdʵ!UW>xs6iox"gQ)£B9A*tH(}Z$մ )Ijz<T!a}y[D6@zacjhyvvEF<ԃ~:ͺ"YR^Pi"N$eoty|4S@1ah?dC/;^ַI7w_zp4uf wkTޫ4~', Rwu^'8[y}
1899܊oY ǺJ,̄1/6J38ECLcCF=&$,gJm'ILjg6&űgIvVNX"hLqSl=\
1900$hq=yT:Q^:{rJ{}t]yUo[\26G^ uq-j;KubW^ Zv(nutP9rמ 3yu#NIܝ |5C:05O]Aژs4-ޓ -"#='v{a?޽(
1901aWwIZoHG8&L52ET`yIΓQaPeU"@q6C1ftA9>C[e*HmL2!  C᱃Tx'.Xo66^:m&K^ rsydtup[#j-SCBHr"I(D=Lf0NDb|Ի uz8kY]%Û{ȣh\8xQ( +?'"*p}"I>F:LE>FXMXXf`3 eTJ*MWf<h#_MH]sQN-mvXէz7MqFz˶F QhzzC!u.ʿJ/p>yvlWۭ*?_8Q4(KrA>[ _xt ;R&l.fVI8E[v.x5邦̵X`3r_o?'f}+g`b;~<RrCq0\k1̹Yqxh~YoZ$u#OFT'tP*3vu,vs~TzR1E\"E@fO& !sr\B8[(œErR=&TN<c.I`@b jޝQbӧwMIE=E1bxK5A]w9~U"0
1902SV.)i?}OPqoH})f@k%-1ֵO鐢e ᖓ>LqM@δGf].wpg:)󍗼D߻DT*| ʞ-W|doly,:NhVeq]B;ϼ>C ز ]o63l\b&{D&j(GWFHkJg7{##=)& ztCSc̉L~^Jh䠷$8ۃ%#iR
1903k
1904RnȳDwXRƄ<))h
19056gDcdx'N-yѺ6@: z3"ެ?y ivCX*f{>&D1~Jl
19066_,O7QogUN#^3 Dn/DǮhֻGnnVMOJqqSR1'uH=|Qop(~y6i݇nsӾPURHtfy/@:V5Uqir/ǥT bc|nzzI/_ oLg<-C1'2Tè 1\tѶSpg ri,?d8y+4)Ks錿ۛefKw%=y #?-4~%U/&)my6)H0`c^Zm.+J1cK13y t?#ʻO0Z9㈖UɭTtW|0TFa!;]:9P}C0jf?[^_t5J  !^ːBtSϑQƮNU [G讈't.d*4BnMT0%䷷鹓q1
1907/'
1908t>Nst>N~uY˻z;DW&K+S;ic
19093j$3@*>9e"DAZN 4d-:ӮO>K5-i?dvCQObU3%bxՓ
1910+4Zyz:rP[twKYbE`K^SNr&多 eAY4y$
1911Dwɤ1;LQdv'HqOy@TTO28L;޳u6N wX-\tVZc#i앿%CZ0N} y!Kz礒" Fe/!Jn{!K~RLωu,Gg]d>JuFN=T\6D `ѡX펮>&[C3j:v)T0<%Mg<r{uL[ ߨuhvKGS?2i.DCc>6dxl07U PZ- J1j,TzȤ˟?ʊ(,xiA }#Z3]k`3qpae.JJx@ǑQ']lOeNR&w"'qAi[)e6~K×->8,Q6z諑Jv̝KVB
1912jYN"yU͛Ԧb!qZjϔʙq[oޭOhC R|E!j(ژWd8$؜P?9TuU駠bRjIYoO0cd4R 0Vt2Z{'o*t2d9@ꝟ |a:Gg+
1913| I ?C2Ԥ;l7a-hcT9Vs[>2%̚NtieXFҘ0P^w:}Q2~}/^"ӑ'Ϣhw/99":˝Lͤ :N6
1914 ӽ>B91RWLB0LQ$Fn !2aa-Iv`R\`dP X$\u e^OD].OEȊhI~o[ҍ@P-ʕ<}K3 iSkYndD" 00Dbal5
1915eKBTlp"bB
1916 I7Z+d:e>70# |x q\֚{De>H=e^jKE=v"Wor @CNW)&2,pDg0$ⵐ褭s3C~.#(4]@CÅힵti=!eMS
1917+/jw? L 2jͰXfOld4]Sȣa!뢫B Ԣ.ti亴],Hh(@@ϬDs7\~k NF5Rz"`+w_q+C{J26:3uf"&<+gn =#ܖ`c2d,Z%VK.[r/[j^U &PI *uĂUʣbH*  ַ~f<~m鳱ݭmx+wK<)}9Xcu
1918xNgM&>Y:ʥhhH<GB}"a7_R,]`@o(Oý4qL* XC7x:wHify$$$ZM)!y1F94'U\VWbW+!uxDr6r!9[wC֭ҭ]iynKAe㖫mn(g,4%>w44E{EM -2+Rg7ݢ"6WTj6wFsvQA0R+2Zv|Hᰮݢ^wH>gchG':5Eth:{DkY
1919J3Zl̃-7Y /vs xJ
1920^*WqiӶO"굠{DԢ<mHSYY#^*%NZSR6ҽR\H_5wwn+;گ`ėDR&ax[T/)帘cvr\ 4 dSW4&\ Sgw'ww] 460so w5ֽk=ƒ7bw<qu- ntiv)g&rEv"Wh_܎'+BQAnHpɽudhQW0q#FQݓdtsV_p5wu3,1wݣBxl-?KVS}}:wp.?g+1 Bp`:1TZ%u<tޔZYbu:O~T*|. !i4S(ToCK5v8%e^8Wp0)7V[3ir3СKCY|]^$G2T$]RvbXۃ&UX]}\\[b.Yt{ƲȲ_k[rlDejmMyvr",zvYN.c7hƖi?]jaԟϏòU-RbvVd.3Q:dFNoh능eesU}k:SwUzMGYoA:}{wE^k<܊>!gqLXs:k]_&(Z.?ovKHݛ
1921E~+{"_K^،)^XvVJWǎҳ4,4R .G$5Ӧ<,ېzFRْLD"y|:5+iMrgt+0kws.-g=bLw56 y0VX;:7OD<!BVΑ<Z%j9k]L `ltޙ; V;?EZc\c}$ J*M&!TH'X{lhE][d5{S3ilt 猧Rpowc.7t|՚* ȌQOb˓F鈕yO==rb ݧ)-=bRPW њLJw SDR[F辨;='GѼ&Y^T
1922X,u
1923I(E*_6G:M*|v]#ԡ$ܾiѳvf4uByȹ x"%yWg-Hu؀dRRuRKsò ,?+[R3٪\X݉yau:q1Ңڴ;BK4i$\i{?#7<d#ug+6k/Hx)賤 Uҁ)7iA ѕI!uH7$%ۙc isA {T[忳?Xr7ߑ~hZf1AU?إ*WA-i?֖c=꧶9^
1924ͣ{h5ͦ%-^H:/'#ej=!Z_;LSQdam#ߖ]ܸ):4YzԚ6Hi+c,,m }9FQ1FPc6M#^ev?MW#QTpPXrnfɛ<Fr lJWUq+Az=IUF/uYHff$C_Cܨ|uDzF_[zgOF)4p\1;NWʦ{3cb.P`n/K$uoD)=4TF{c|v^; vFM8塯r[D&)b+.-l+x9Dѓ2F6s/1YԗuKS|ڌ}A@1'1S\lqZ3崓K rsyA&E{L/tdcߨ Aᝉ{Xk_*vjG<g1hԯOUh ecf)*ݹ%E ZV[%-e!QS>OUJm*gTe g`*bŰT◲ v3B~IeSʊ
1925%؞zBW.&ԼXK.f]ؿOKCztg^I{1,]"^fQM͠u޵qB=&][Is0TDgo8vx_~+/+Q*:^W[F;Bc˩H}u:Fs ԖZ?Pc&UDyXSfunvc %6WVb%az m^4kЉ\WaOuɭ]1
1926e%f1
1927BK LE-q2,/Q8 ).Hl$X,Am ~(WL5XZz!֙o &R_ ]䋍(5gJw]ۙM/ 'JNTP僬\W+nrRgdz7s䊃SBw({>A^Z,~9GHq+|2$AU&fFG2`=u*IåqA bFP>VH t4[^LGeɢ̛ǞYJZzmr𔥋(Q sFJyNQYLGF<†ۗak=d><=f4NEȀEA@KB7||y4P
1928 9F@θ#*4!
1929t/NB+w U]ኯgyiMmtelFGYMCѩehESOQ9&u 6aEt!qq/VqBƮgYYex~4I`m!2e/&A[Qz.!˭fWGΓ^y5+~֘TS42F.4Ixq%bKGy-SkfZ ),־Y.%!.5;Sy!TdpXxMTYP[yXfC<'(M!U1JخėR
1930ZFnSZQ:ʋ'gNmq ʯ ӳGlٿ+
19314|%֏nbaTTv6FQ(EfRA;RC,:L4J6Kf :¬!i! J4%ih,Y&La R(aR&a^ֆ%j Ct@m+ιV9;M=OAw~{杨etv?RX;lY'͕àY_yNIsvj1 0Sӊ{lgXw̑{h ;jUvtu~2d~Uڨ6JJQkߩ>wG9?jeiBiZ;U,;j#OnMS}= \di]DIu^Jvz9uKәhs}V Ғ9}w'^6 ڦ tѮ0fSC4"2%xp'Fz`25<R_9r{@gtz|##=N}"B~f}Zzt+"~ =$#]R^z-y\Ikoa-c6\?fD)&*S yFj]?A)T1J RC;=M0zCwz:iCAֱ875ҡН^nC;*zCwz08:0zCw&tuRS OɶN%._1P\i:B@9$m @R 3ޢ/գq=K!3fa44y ձf[=֙C8R߈>N$g}x.tPCn)  ⎀|U>i8H?l%(+{&!}C|ehk{Sk+qMv_8z'vl6zɽ<>l[;~ʵљbZ5+ͽ<~"+5/J\!6H7$ m򿩦ȵt/96AS/kѐ%kBصȵMzx""B4%$7EqG?vuu]qz}C
1932
1933oqZx
1934
1935oѭ%
1936 
1937
1938
1939
1940o»
1941ޒ
1942xV
1943
1944
1945 kw$~>Q wGߗ +[WgKf#&m~=z^WySOWoGm͏#pFcG=ơ@vdjnSx>Lo6#jᲁKշQEc+Lo_ϓ&~k^<O9\99& 剏%M;hYFmG<qD#ޡѓX4?O}/o~da3kò?{o㺾Ze4h M!eJQQ(T(CT*)
1946P2h̋u]}?CB?kN{-98뺟ڢ85#5OiuJo^|!-)>:2<tF/WǥVfǫ)bԸ7x(9eIS.]! dOdt|Rb,q' M/_PXH{T@nAyJlFAQ|jbܑ7;٣n0QCINzjР3M Q-kdbflЮG''?} ߉Kcn7}[њo߼jnϻv)cQ{wnvu\b9x̨HޠskM55_dcC@h)Yq#O{ߚoR{~)΍s ё׮Fƭ"?z
1947h4eakӶ%{5-#1p yJ㒦F]UvޭܧPAnt_ln:UOc9BTi,l\}9qKp/3n'B=|X\w-\r]VXB:bIsU7mʬjF l׬~XbڅwP3oj?BwBJS%ZܷQA9{pOŬi$o=Imʬ.q8.\ֵwU=~RXbvTZ@h^|GElYviطebxֽl6kEi%trn>@e MFͮ|?Ʃ97)軷#;7t:73m9Eg16{8T\FYD
19485j&-ZC2qyMݳ篰U2Mt)_@pDzZcmK0&u Xe-s윽C"%1qO縨<.em{`=&)+,P}b1`ǦQq|)yVͶmgxrXz񃻷mXh3&mq
1949cvl0.YϜovö'_X@c)c><й8?ҹ;ֹ[cFi{~b]
1950ypY[ۻ q 6ܥ\4;јmݾqt.+s=3ѽ!ȶMQV ) P!(M24Efɴw$ZPWUZxꅔ=A:,636V+9 `GFola토=Q)*,BS#]IO:#rTFʹT322
1951꓌f[ڹ<~%/A߼lz~~N`?3'Ws_̶F? }PUB<f_06묜6|e4tû/Ԕݾv!%@_VsrFaºknsO~QVÅlP\ʅkj4xß]Gc m4?vbPUKp9<| U΢ڌ[5`1gBH̺?x>*cx/mg&޳mR(l_Ϣڌ[IJNuᬅv.dozd_ݥ4|nȶQH=kJè&23nK .E ;IȾYXZ7t)#ԞmWfyD59Dܵyng
1952~{ل]䘽AKϠ3'*JzFz)<6:q
1953[wB05n?d;z
19548js{bD?d#v9qNIe[R xE򢛗]@KQfĠȘLMP(\O3E+":O^u{fdϝڹjqGDEL&(95󗺬߾XJfGͯy0ݫ'U%2NrcDMTYPdyu=c 5Cĥ^+B-pk謍7$ϟ<,ȹd3wDf|ј?s_4*jQKƛpk>LMs{cQ^mkF&*-EFc
1955we.zk| jhr~\^u.Kgɑ ,,ǖ](\_Pkz k(V߼'*c=uy.Rd+π=GΣpW! -2W&~L} y\YXɳG'_ạ.hɭd0*j߹~2j
1956K}MZfD0!+cNg(,{B̂GdڵԀ+I5#bOg>#rg-HPFIGx:X12se"kODN+/\rr~nn^pdnwDދE.k|נߢFFf́e's@BK7+И ۗjˋXf%';MyPJP'M`jec]EQ^VJLV/$C2Y-f@O$ќ,$25&Cn9|L=gvfTfHV$x T`&*48Ueb`e&3 9u}K/Aa g,3{[̘2f rI-A_5VMopAȴ3_kg>m<X\VUx
1957h Cδ7.&fdd#>FQ4}˞hXW^{TTF۹ڊ0csLGV0məyEu Ȍvmٽ'_m3g԰bdllϦ5Kodt#Io"_QDVx2|ZzBdӢY٭5̵uu|naym#0 aճq|VZ詳36S PhP֜<{!Od\WVH֚ Ao_4<s%@/3LNm͂3u$VPw x;ۗĆx,cNShE׶}qiQ"Ze~iYwo^k7%|ܙ $/*^+jG@ı+4x_ A7ϟTeRc<#mE*hwZk$^O:n)nT7K? #릺 xlv3YS^J`KApW<CeW=}=hl.q`LQ&Ӛ $4 PuBnQœ "Xfj;s-Q&?uJk2LV 3Ty-^y#3ӎbDex M5bHZW ߆uxcs} Rbl^h<N`њ8ym Mrᣆ@vlGLSGvnr LbHgf~Sל2oY8^
1958Dn/xc3n\8u(t=J`zjdѭY).rZxFq7xB2/OW~GT ORY)/t~ !#>lS(h_M;|*՚sSQSR?cLxvCwY2wdQܣY_,!5S.~$Lv̤a<r`G. )I7"w
19594]mgS+ffT1FUtʯfDHk<PߕƓd{3Ш,8aC(_S~ "w8<vfZ{#KK)~|.+NTO=f\$zQiÎ)WK!u욒[}L' F/A'/ݯnx ~ݙPw#9q{.;Y}x{05ҮݭxCw(GͥSdEXl[/ׅD%e~5\h~P}?I447Ԓ5]~oSTU\}
1960<4
1961`w.>~I u6Sʣ䴌̗{o?y^ם?85ƎHra2*]Ï^X^ rCugwnt~l5+ey>!Qɗ֋= =*yddMSL)7f͖\4E|ы%x{4DGYV#t)Jy]ӗꞿ[04HKV#T)F7v͖Űfd*~x̰_<moWp)Á#LSB|,jH1 l[
1962'ȿ|p+OJ9<2XfBJ*eMiJ ,rk;CMSrqV w ^& >?
1963s
1964s#M9b|9mpfٽ3(f,6QGSjBluP\0|ؑľ
1965>}Ed
1966Rt17T;zqRCգIΕ[`>L1זJ<i7oz0E`RV5q-p1],gLP6#q_42_BFA)s?izVK諎5'^Rd?<.FA)s
1967OEc,['.| 2+s_5T;gjo5r>GRV<}A]d07##ya&[;1lD;l
1968>⽜Tja%cjeR J[$W[,G^˽C Jc:|2dtFfʰ$0~j=sPB)s L`n!;r@[,1liKN)d/nG%y#]'- ˲aѩ
1969aM<rҡ es-6xXv?W{/]OٹHsl[,6a2*syJ_^܄Q#s.fNTle󶛚FwƤ]/nx{/mD0왋\6M*
1970eXvE6[vk]e=ͬD ux-fټ9Pʦ#_eSF)L"C:H+Ǐ/|KO9bﲝ'(Dl[&7tǨOb]Qn
1971/b4 _1Ry/;p\"TnˣϰBsT…𺱦8l,YY곍e|^Ivm`d"O0l#xbf)G}1۲<{#g%PYxf:Jl1ڲ ˽as,ȗoy_hmyބ59PMڰH󍙙I[v0G%Yms[nvBc-zSTf)r.tpݘ[e-Q"kYb[xZ,Ѝn_KlS[7޴ mY3o&W2 D-ރ,*3lL?&kcQڲhkҫlk+g8|;rZ,e Xb
1972ČW1;}s_?TtxM~r,EM~NӴ}TgAN_[Yڲ@V^3\$>_;>GS]8[Hce}+ɇܗUj%~Qډ࣊%@[Hc~Yuѵԣ^E/|j5+_^$07dW ;E$~-j"(|B+t6
1973_+-O_9%rs,x5aX@
1974—@/`es;՚iSxy&eA`nVM]6;y<UKd_MKnGCOC6u# 9v,xJ,"OX=u[1|1^%;u]mq&G›=B=C^-bl|l2IQb/6lź1gUl"/d>c,Onaƒ3<e~Z
1975Do"~X)2De<HiA/<آ ٘VMVb<p޼
1976hAo?8ZL=<0U0HQ&69-9VH[kLg"v扽k˵8e:)VD
1977z·uOR/޸ 'Ru[>D<0 =
1978;-_s6eCh`WtZ=FO~' ND  [LW6{
1979љc{>5%;QyJmk?Yd $GRaۿs.hU3kB8Ƶ2>^^| .ۿs0UWS{COU"7gW|T9ZSYP2uQ_lƁowx50-|,xU;4:R._Wz~`OXt>*"jU>sxg+*>_SJ
1980T=ڠ2,M/Ե/<e>8spO$׃ʢ
1981
1982|u.U
1983* <ɣ3On\/[GT,;{UpWDᄛHpJ*}lѥ V:mxzaQYya# eQ/g>_,\ѧM+$|3
1984 Ja-BP\ݹPӈMT&߆ݼ_D*|J=m?@UfNM6dӠ@xCҗԧKsȥ _?|eh&
1985_> _Am>—4-|᫵ D٘Sk_[pj`/
1986K0~[/ezD|K0~QĠܭGрP+~tي.x| kw#4fQ`'B4d-O/~5 >Ɲ~-B'ǎ:|#,lh̢
1987µ C'hJ:}l]e2ܷLesa@h6&W>ۖ?K)L0vׂn>xL_ m&bv:92o!id# m<*PDz9*2C)˖Qџ .esۛnvY4s=G}Ve'e^lٵUK~ް_ز9 mî(|h'2lU2sY'X6(xRwk[ uˆw.Բqʆ]6gJm5l˦S6^]6?r/aK~հ,,F]6$ia-[V G :_NbV"m0lbDZEomwcd({QTq[eP?jߞk_A["1:PCMXvS̖{Iɾ[#3a;YKfZ`|7Fl?qC*es *{~Vs?7MfWf,[l+7={/AeO+f^n6EkBw|~eA.)=셇ؘ(I iaӖݳ`I<2;eܸ_58@ȵ66eԖSp
1988P~^aYu4Ș^"׿tgٺE,`)׳bV[O@26{̣PZrΘ4j}!R{+!;ۢ2scwh5<L̺]01nq٫2߲y #`ƨ{W u ًlޑG%_/{Qo]<y p-{ k{32Y9")A1zZ쮍,W[U_rZF넇)}kKo1*nfV0=<L;qG?@1sj#CcqC>F XvOjZrԫ*Uoו_J
1989(|EY6_xR՟=Ld
1990J87=.e>sfX:m'Sf}J!>+̍41s~{1F}<; yX R~VsFF<و*K%P̽ GmF)b|ux#2
1991_Fæ/,FmF콶JʺS
1992>(57e/^1D6#f.r&kN\نJb<*ob7#c5 /'Ō;3,j)oۈ3ތ V1Y:3ٕ/6U¥`2e巁rT1fFf
19939WxVnR)$;6=͆bfIF-Qg6 <uf#Af6rU^{mYcC7SR̨3Oiz㮘ԫw9 $z}xT[zRrTÏlb8ryw+X}E}es7㵗we~1y8r%9FX#s[YWi`)31[l1js-n='KSTӊ{bw9/2Qk(eR<DRqB'_{Nz52w.tzœAfr?X MV՛e9:0MQgwnt9IIzmdfΙ嵧~(1jdR~}[ݗ͝1v@_~(ҫw+4aWw.>r ,e`rfvD0E/2EEl^c;[_m̈bqZ1gdlj.
1994S͗{n;pbBدo^ddvL0әi>Hٝ~}ur%L|9Kl?i,N3uTFoW l(͗{1 ix]WVk }z^B2fk B _f|zxE)jT񭗐xhg>F xvAYgCk@>Cˆ[YItV>Wʳ(F9;#?gw /^7֖g_cuF/FfϞij}᤬[%5 /q
1995dpS&Cԓœt
1996-ݷ>W\d^>!兹OEmt;EKAjX:)*S;0*h/X2|*
1997o\3ԚfFIȋ_cf.tudNhʫ(/3.7&(13DA{L,FĦ\:xaTe޳P*cFuL'_zG󔆾W |"rLxNJ:hB'D LWz fD zjPSOä4 fQ2mY"_J`i.'1PlEeZf46#'c]S9T_ lOdM0"C##JkSMyI4(xB2k&3D~ 
1998o*PEe 5 ʬkat#;m=ew/y2y߸ ek" ;O~PB"7(Uf<PeWf }qYL4'ou#E/1W@Oav!47<*{19((23ʌ.
1999k|K )ok\?ttODnMf13o=nx= έ_?Z ZƩ#x8XrS2|1n7x?͹% IUɝ'v4-e60r s45O2X xɕo_9p0oS-<:|*Z~I!]LP7/En\cga./9"YdrwQ'e߾_YH24gtKFE¼3wYj>CWM" ,?sۦio?~Fe0pmG~j'ؽAmͦMR+1XO,(0Iyu=ceOɺq e׼ugwי^܄u I>lN";̍Wk,3}gߠ1r
2000V?5^<~.Orcćey2?Tbꤩl|9qN in[WΞ8sլ)Fܗ'sWdCF*O0sˮg*.܀&?ݽ6߭_?)w# Mn M eF +EܻJړgYXsiMu(OܵoehP>ϯ?s^dFһ2(jۡ /ŜUO]2qk4%߾x4<p%I!{q^d̿&*u^-7 "ە3]$[?ZSZw9-!jQF<6`Wz朐v)6o?trWuĭS[j6
2001do@23l+ԜC;}z>^~,Pȯln]Fd D38-ԜE=}Qs4:wr:2T?wv
2002CX`9wyHGkqy#|]NF-Yb(DKd<`ɦ \|>v]~9w}j+Ks2ܱkrk=ME!Hp- n4g490YvXyٹ L4P\VDbn+MS2nɢA 7Rrf[ٯY-*.jyDkT9vmq^ja2YؒaJ涫6S6_}umј,^4>F9;#)f_yu5eF/&-9<RFA]gk6rFap
2003iאY?;rB@_ 'Rn-BMν=Kp9&gd*,~҈R؇uL5dYW=w%=1f_JZƌBٚ"+2ݜ}g!5tͱ^ 9+ vY!#F )qv[FK^z$^w[3Юy*gMP9{ILwmR{i2JĬN y]l-n@6†l7p (VM.o_>$ft,rG.du~5΃FHrin/xѓiY9w0= iyC]Ui᭫RmX Tn@6]Σp9Omi@l7
2004J*a<ES?.+s=udQ!5ܚAQFb!>}>=Ҟ_uтD㚲KcXjo=w*A])rhvdh`_pđ30+QXf޶a'h% BK*iMke%l4jFtF9LԌXH7d
2005߾,# 1(Z rtg4;W0xb[wF|)73adf{5qog;+lcF FњrWsk~9;pJaض-tXj7Y$
2006g5>dǒYˈЧ 2ν~?0%-i.9<*tX"`yV!߼DD5M 'cW ]# ҃
20073`xs흽C"#sV=~،qsQhUvѸe.X
2008i85)clϞ<xPx;R:x x4̨a&fͣ϶q{:RZNYKw,𞃱'Ϝ{A@A3BlS\ĪK޺u.90\ƪƤ!wI{*.#u^фȸ/#M:t P#Ϩة_2~\YZwbZ4>?1ɺ?mKߠa(M/w06EQA7QM TZiS772FV}:huOܐYk$tL̬V`̉KQ~НGAIQ₼kȪgO4Vf͇$!1lQ2rʚ:SZ.q\{#qIg/f]R^3J$u?~RĨ<**SǢnt_lns5qo#؞FI)iL4>fdžC'Rҳ=@BF֍UҸKnwS
2009Sǽ㪲;73%'DGvh, ݞ)oKɎS|e+|v?r<17 hQ{5͓=($0_aR/7"&#NO9xG&oW%sh*ɐ!#%(ha^hsC@Ȟ HGuϞ% X<|Km"njxZ[SYzRFj#wmdbtJrhv\c _g2BBYQq0&!9kyw/ %(k_R
2010Yx5EY)q2-}&.-kh<wA;OJ=u5ݢeU5OiiO]J_ȥ_D
20117<AE\VRTp+';3 8<,m*'i(9t htgoʸG+65Z9hG3\%׌ԔHlڌޭh;KKK%)\ gO<~@x6u.x!OqP:= nȸ%=VQU[gʌK]<|G9vy7*[X'ϚԤXlD5'5}X],/"pcӺՕeF>wh x&ODex_ θAcD
2012ZI}E]r%eՏ MH״شXo89Q;UۈH^Jߗϛak*ݽs3 gSNEܻ38`Z"Stƍ1Y5ՠW7nqAJAEcT+V޸ec`sn޹[taYEU:5kJl6=K4Nu"$.Ry#IҒ{n\ulJb|{‚6Zj%PwhɑUvϝ@вQ!D$V\=|@材r|֕k7`!6<kDj#_z5[":V=Qˊt}~իH\TD޺Hߊ)/]HO=}*>pd୛ֹ8-^hf:}x eԣ2f4n|qC;X$=,Zk`Ȯ1'Sϝϼ|5ƭ;?@bWV74<{9q+*MMWukoN'&;zh@^nN+Z[56Yg(1ϪAӣEAcUPV3y96vk7 hlɤ3i2/g_b#K+*k浵Du${C=QZS]]UUYQ^^-.WpV^KϥbD
2013rsv?H$PکϔЃuWRӚKz2oGg7/_P$ǐ֧Sf\ȼ} }
2014 ˰j~qqQaύwn˽彐q{2>(8lV >klL7ASuh)JbԸC=Zzhړfγspru^e[pخ}QGc'L<}&\ƅY._ɾzy7o1X[7n\vj˗.^8v{<hTA+/]l6ԟ|z8ŔĴSC'Dg?pnTT5 [.Zbs-CwyHt'O9v\ Xu R5sgRϜI9xD#"E=p޴VfϜ2NnĈa#k AGKo#%ed啐ғL9kE˖;:yx"w߁ȃ9{<.ĩĤ䤤S'D=r8u_o7'{,lFU":h
2015Cw<=>U5W1r
2016㔔UTT5'M44NQQA^Nvh)Q#C-'0i|AGHiJj\ս~L|R{{4},RɎP@ŲJKKIJJHB@ۯoJ_aA·4#55_l <xȐXt:UŲ2dAե%f FiJj5k,6잽zڻwo11~V}*U=;E矰R`P=(I]Dn$8'V]V26,.^,//-zhMrʼnHt:OD_oD] 0!$6QMD%o 0!_xA@TBڂ"DgTuj
2017
2018|iY/U-5E5%%m/h(j(i _[QYCYQ[SESOC_QSR2_Y֋{cQA2XK~- +4fv+ܖ9;k(ߠLl襢I+
2019E^ѿ^cdX#Ҡ mӪ_f=m~@iDUqFwsyxKnK?]\Ez;7y< c\O׶t MkeoCa]UUHT+HhEMuZmT*Sk`љ.0$ Mt\f?w^V7"zh/W"W
2020_{R7&+l4U{-=
2021l
2022
2023ۯ
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036T
2037
2038
2039p*
2040
2041
2042
2043
2044
2045
2046
2047EBI H!["$ !"4HysYk} }ܻ%u~%S
2048
2049
2050
2051-}
2052
2053
2054[B߅n3
2055
20565t
2057
20580t
2059ihjM700d``?UOWGKSCMUe
2060#?INVZJB\LDXHo,RҞ?C6T`ȃܤɊ*ȁ4#f3gYXζa`mm5bL3&F teɓdBJF!m`W01)B^AYE]S[Ox,ֶs~g8i"W77_WE ;mlYӍ 5U䑒 JٌVV1|(IB4m;:-\x+Wyy]ooU+=/[uB'G{6-gLJ&I"BX|b>~AJ*fff?R}`p7GDFEEoai!|}n. f3{R6EQ^NZ0r}B@HD\PОjhbD98-Z? ($4,|sԖ;w퉍 `¡C1 쏋ݳk-QBC}Wy/^왦zH 1!T"L!8m.,R!,".%;IQE]{6aVxist̎]{'$>t<3ig3MK=sd񤣇ݵ#&z kVXxf&I"B 6djBt 2asv)Τ8y1rvNn^ՂBWrs/g]<q6̩߷wa!kVy,uEEbmjDWSUI^Nj0)dUC=h,ߐe+-w8t$)tj Y^^|VYy*+n,~ ? SO''9t v׶舍}<ݑVfL< A- aD ^#G *Ե,m-pu_{xԶ]H's
2061]QrNͽj7 1߫S]UYQ~ky9/O?s{wn s˂yFjR"ae1vx*s.^7 dS9~LzfVv^AQqɭj
2062r]1zUϱ43F$/#!;*bq ԢPY%!#5P/h]8u܂ںOft_~w޿zݻo߼~
2063iFb<n_S}F2RO&ݹushbg9B4U'JEȠrZ,&*hZ*â=p82q)'Z1qC/_
2064ӧϟ|7W_|Ǐ !Mϟ"'߭]Vr0/9d$QaޞZ0UW,+ wհ6.pY(ΰ_T۰)zGɩ.^ɿvVEU  + ǟo@B Yyes3ޝbdBƙ#cwDo
2065psi
2066D|8a d] JNVќjlnmTK8v2ҊPE`o|%e|MB IN޾AJ?}~MUyKR% [q4] e Bȅ 9.V*ff_YVYL@EPq?k ^I!|W/>FFTݼw9ccGm Xby63Mj%*?`}q!,&9QQMgkB#bJʫ6<&Pk = >fR'߾*yOyT_{HQ~vfZ=1!뼖Οk9@[UANR!hݣHF6D?UTT{WϤ B/?HRH%H' UW !ϧ8WtX%NvVft'@g1PFȅrQ;%H=E&0Dm0"F>{F$ܬSIn_lomnK W]M
2067DvS.f8zmTzVXSԟޢ@5Aw"~k%T#(G޿myلܭ*+.r!-Q뽗8P><ǀhWd{71R.l]=mٛpeUwqU|M  D=*WB5K.e:{KXLC`oWTg ؅ …oP䴋9J*<hxO (8%F0ii~~uٍ {c6tu$CANBD?F'("!w8%=+{=kYAUѮwo^5=i]r-bZrbpi:
2068 =+fa=V`YUi(ťCkGM2&
2069uԱPܫu=/+=p`mf"/-ǫܮ \#x %.-mhf&8b;rq; O[~٠{*Z Ez=jX>[h*Ob~XdaW Vԟa5oǚ ܣN.jj ˢU3Q Ok߸JYlg9}"]`hGMJQ]yO ި}DeAv` iU ^xX[CH Z4wdܮxF`/jR:F38-
2070MDy]~=nQeѫ* |hPUm 'I
2071ʃE* 4I)iZ;ݲPrkE1˂ 뗄'
2072Y2o6nWhiNG?VQ
2073dU]ԤyD>xlV~q9Q/ߐ.eAV>7,;ySqw;MWR<.v 0 m,q )b^1Xu? fbh.+<}$.&ljW֦dy? Qda̶w]qkܑS9Eehjn YÃ쌔C{C|=Y1 ̩.o~ DaqZ;!9#~ V>޽n~ZͫYi]z-oC8޾߭]jĨR*(1]W ۶XjV6~w]`}||z.jW[C<QyiO$)"0fTVl]JH\FACvφ='\/y}o?}Qm䃻6y/o=cdi1!dꣳ[/1QYe.KUz3/ ͻ_?xiý7/9JrݪoG.7zRH\w럾xWᙶ/>>OZ?)+r.9aWDMtUnWg+"2~װK*juCFu#Ԥ>}}ծ%WPylw;u)Ɩn"v%¸׀_h {|i J+;6[b7ka `FK {45 J&_\`JU7/>'*{ V:S&J{ ).=Dƕw럽|'Ҥ`7"jʮ]>?&tr'[өjhѧ6 "2,湮
2074ܼ;ԅUQA5)/A+<]hFV,mL_ R2 1r\aKѴKj(FjR,ZǓեYg r4B!71LD[$ S[k7n;p"#711
2075?0㏯hzp(lҾ!k[!<nȾHMV7h]N^/}{(1abV_7=zPy#\r0?z$,:(xV05muP#d"kaPw[]x*qWO!G+uPk!&id'd˾+qB 7F <0Vڥԣ{V͛e G+u0eVVIxos7*]t_(ԭZluJ:%4 f*kX/X#䅫wꞠ.~߭a_lfmehAdMљn.|W21fQ$n˧uwJ^8#o|+cm%uP2F0q ۅ+os$r Yjt)D³eYgw{,6YK*zsWD=v5o
2076C6qSo^[8Wr7K1O/>~,62N cQcn^H>_ZS  /w`Ƿ^=DJSwH̫́5 [35XYY#^<b2ˈOp݆? |,G{;%yHGwH3F-}zf(3ewszwK\B2du@ʸev`SF+4:Q
2077ޒ1rΌ9Vo=@h~q`V,Tv5PQZu ^1%鶋Vma1p'۶P:d鈍\dm(-OܜzB /*=yeP̫OF:6X`e 5~9e"ҊZ& WF;)vt_ނX<X:r3Vcl#ɒF AS#F/ilw|>4dՁ- % :a4{ؤshohz=ep?wY'2 g۱Bꆖ#+2> Ft<sȮ0%̧ᵃIN$8m
2078?/|ܒ; >q%-qgo2hb}j4N37lב97럷 |P`êgmr3"hV3\DZItO+72gp`t.tƚ%`ŝSZ&VlK8}zçS*~ɃkSGx.=M}4X JtA&ӊ-'n" ֙w//+<y2Yr#dh@ n`|}Ծ |ǐ1hmP:Gwog۳i;3=܈Fh tmޤsW=zAGøMSCMI;C]qKFtBCQ{\Wml~ۿ _?}&aۆUFN` ckUBԝ7 {]Al+NovrGGаK+l;X t+4XfnoNFy~1
2079 e=s{wq'G-`X;޽xt%akV#8UCS|R
2080(4ք>c8E:fNZ2:&rSc'kٞSRC$8`ϹdU_:Ec jSѷp?u_82PICڊ 'b#ڙ*I1Cpcf/"FSf}d#Dtbk9YB*NU>[Mc[]l *踒b
2081<%7h 3:^<[mJٸWqb«ɪ>s wɳB ۧ7MŗNZUz|^#O K)-%7ih򬶂Uh"wԍyo܅9?:?|\W@E8Iq0V 婳=&} l?965*0>[A3WZ.^ } V_?ދzOr
2082q$*p#
2083U9 [=g),#OgSO \<W09.mnݲ6.>a{g^]TPC 3Yd"+2nTw BF{_<^EcSPV`n+#xIF8Z5~a.Ll6rq<q"x w"|
2084TP;WhI=%`<3sU[xԪ2::z≽a>ɉw8>jnBw'eN}XA~,졘@s]n4$tl9SJF8Awh#J _bc6Q;AZԦY/ {b] 򏯟Ֆ'n "C, E]sCgʨ-J;ŗR׸( 195 M*F-Bm88[Ѻ4%>{DO@9>#ն;Ѫ4\ׄǥ\*_⨸qx{7miNKyϱ^O*.J*5^ '!.FrAw2~;q_4kMP݆*7TqyBN<3WPBA~y` 5P
2085*|Z汝!+#(;r 9}=opx}o[+>? "|<:kUNdłU_~{(A!Tw L&OB{8~g6A=>BlhZhߕ'p^ <w=P=C{0zqbx )QDmal EPԲ!6Q䷥뷠 x-<S!+(׸XȈt3 Eݙ~23C.1ˈ}z\ ǍJF7b?Cs4R9^ub-ǭlTbxXs8vd8'`2G+GGjTzвD֍G>4zuXPuAẒQ|
2086~1Ш8r<H*?7|;8j78t uW:~ 9r
2087OUМY1ߎR֟ԕRg`<{RU f*H(8ODVhb脳W+ꚠQqU36q2"-<Aͷ4My8YT&*X
2088bӐ3.
2089QTpq X1a;88F؀/(28~q6" q27v `" 6_{ƉMҜa؅w`<,q6tf.XJy>:3Þ8BJSg;D? T܁qTurލ!t;8eTٸ{cm8ymY>Ζ61qrv5|o+!˻W&DٴadSG[? ~8dG0 8O[TKgs Ĺ[' ]9\{2[ Ulڨi܁79oBbo3TQOʨYo.8bm}] UwH,pLĹqb,H?ʹ*cu<'-sa UOT⓵
2090ݛF781N U^>o68S* =ޛι#hzrq-ꤊ5^fԼrO x~ivJU IUNК:o܁z8N
2091'pa<mFEۜwP7w<݁/Nx% c<3Qc3Cps[/c*3O溡e"dK0Rq̣xS\A˳֍gnp rhaY8 <_wʭ%.Z˟"^MqY*q.\8JSoN>uwcM,܅u~T\j)Lo|XpmzXmR&5Unp 7<@>6~`!OXkOc,Y66dT#`0WZ?cc/A=/16F0lP{x>=puF6EYLimݲ.17aT5TfOAΘ Ⰺslq[=<4c*n<-HO>Rg<+e=cpL5bzbd#ψCCƹ-ڷ8¥\S䁺.~$ F6ur8P& ۵AP_.@?u.5JS- 6Щ؀U:n__+6d 85-:?5ޣ+6nSoхMp'N,<Ћt<ӫt<֫t6x“Ttх+zοb
20920+{.|2|~oѥއlKt;[w}5:/zN#|^K- ^/ѕew[t;w'-݉;w]]{.|W{FC?Ҍ[t0R'q. ObUpn S؆*m*8] s̡Jeb- *ᤊt/C~yR?Кt'R'UV?nr.^ָÊq.՟hM݌%F?(bt񧽳Ÿb!\b~i0/'b.ę1Np?`2bxzO3-ɶ6!ΌqML=AA~;mnn8qߎcs#iҴ1br3|%Qįp%ۋ ơ:"+q!88_lG(6V8iԡ:ǸDpXŠŽc<hL!*NA=JEmTl?Npٶ888~ sAllg}osPTI;7x` q;}!w!ZvcqN0= Č |֖9y_7 ]}G8XK{BW-@<.Ү "8
2093J(Z͸n}S?=h<FA=82q9x Zg hM;f3MUvmqЌ;/*>5jU0Uq
2094l|x8ĞNz4*FTԝ9ﻎ_~%=Z6nd$,DE
2095:8Ƿ9Wx-w,nG1QG'|Wh smmWJmc'l\ ':ެhO,"x7Jgm p:0#&i].`*1Bf"M>*rWַ\qω׫_Mn?-hwdh Z3!7l݄ݼ|2.| oD;ًc"ﰽYw_di|Fqܑx۵Fmf<0&1=Pݛ٧ou5"TqC4kM)n<zIQJ hSӥժ
2096:A_e?GXx1* .TBC.ڸ &́*g^C(]q@]Y&؎o3SGp%Ux! k85@E.8#~
2097Zo^fϕF@vwπdqd;G` ^<ms@D_޽hq_9) Vqj"'.U7a"O66^i-SsJ1o!K5Ԯ,sZ9{N,]Cw *?<}PwPLn7KU
2098ڦvKξYܮBFMUEObmkx@ ӪG2
20997U]Sh}^iNj–ef:[A^ .^uMdC2w03iw!q_[(Sg9zJ˽E9`nof:T[Aۥ8V@=3ANnǰExy~Ƒ!+,UdE]DqXa)Eyq7 6rX::ߠ[hO-vu;xʝ
2100rj#^Tg8·zOYz<ϰئZd'g]G9ǖgH}
2101UUm:zSOmX4mb{`lJh zUQU
2102;?b
2103}TBd3TSŽ*(&6A;84>~^܉>%-MqPK&Uޡfߺ%D0ƚWRb<TWV:cR
210410C 3bS=Z5t0{G@tKDt I+"7 |XX[QxDlR;3b}+_lsh%vW"4/1B_CK?JXJA{\5a٢t0 =dq":p;8[ oDh[6w0qO6^+ >=8yze3f2Փ'b7VOY8Xt^5(:6l;zƝ7h $vJ/Z=,:y *>GJysQtlu$=.x:HDW>mBc9p>cg>oI箖#}S2}|PSsPo9ӵp?9٧:a|}Ծd"a"d"hzt%=.3#Cn9k=:ԍVm?Utr bz| Dufq#4(P2]:d[™h'Gs r}ƩkSGx.=M}neq"J:s|Bw$]Q]sb,_=]t+5'K
2105s%4t + F$߰]GܼSO h<}XU|̡!^.8Eq'4:Pt#\_cy5 h- F,-n\IK.Npa6 䆖{\-vmPd[_]͜Gv.g>UENLS F KN0ZD&v:d<s37p?wYh 88Jh@I+c+\(,xPNƱ- Չk Φ(GH+jOu^5k|7tQqlugiL$vp.KǿN.*3c 1O]*A322b7X`e 5SLp"Gs\W߷'&u`юNZhG2L`\9=sh <t2ҁw | %#.2`BkhS :
2106M@kyKlܙЁ :gS H6&J2#<Nց\c,aHǥ'>BAK2H^4Ham[qk^2t0d|Fx;2xzQ񒔎;Ne%tأus >C{6u( 1n<Z Ppn\_;}߽zZWeĶ mkx r~S2?kyx˧N `EP75owK={]<k׏o_<6`L;7-˽Y)^ˉIw~WE2<mt*(*.)=Feb fnztrڑ=<MhѪYILRj:gʀȽ^~Z<X 4>o[vҙ] hOxD+os$rQZ<P1pʃڿݫg5
2107.:3o|+cet 7EgǺ]QӀV1V>"Vg8XKvLD\VYzr '/\-ɋ7Q(KG*odؿ5g(2(ęlGwmroTxw0[1
2108Oe<oWQ}X\tۼY
2109}B"<cd5,lٗ}^sn՟}P˧u5
2110޳9`oꓥDyG/RVE=z֝/lÜ* bzf~Ʉy:1*/97Om;1l$/Z.Z>|סy7QBuyARK8-tuU&J7::-_qہWlGVy? K]J;{lcme B|m>!o̻h-8Eqφ#g
2111Jk7FY]ERDa4=zԅS7r5MMcG%{ tYs]+!|n1
2112sFyvŖ0]8=ydbާdhҕVP70/4fR<pC. R!k[OS$)dKZ<h%"cR=2so@շ3U3Qq=\J®Un,pd&>%x,7^BNYeź\ Wh?~|F0Ҏ pkn(# hCLFA]}͆(<*֣g]} T㺚r\vGy/q*/%*VxJɫXڻ\i
2113J4>tw}ALRDjwլTTWY. ~>,/<ANI|2<NϹ^^1jWx>ZjRjo]HNL_CR}22X0|h|uaKʿy^>iL80$E4G˜gi׻; ܝ]XZu 4Y.>{hRiwDz/Eaf>ޥP
2114*5\+7n;r*3>V.޿~AUiavFʡ=!k=Y]٭0!vRR/ߩ} TrYcmuYQnR1aV-v65PCZ fu8Z=QznoH'f`o>B0Q j]LM:#"}YF(1Ũ]٭偆+SkG[JNtFECV}i/fB37'
2115Y2oꊲPa]AW19iW@XLlbJkh/@Ew(/W/'ڻ%5)3C-IRlOd<p5AVQ]+e>d\>Pz%]!l*PpHHI ZꄛdqaDa.ŀUh?j"5A T(? *3-ȲmKFq}9Y&%'!"0?!,ڕǚ>; O[~ ]YI|EEVI Q?%;CXXԮTu8zG~~)~d;B( TYWuz^Ӆ6p5c'+5]#sGȏ뷪@onyn
2116"-޼jzP[sZŴX|&w~Y$+QI9Ec-#619bε;?'BZ v,ߴ4@-FAvf1 Gs#]5& (t}LTT| 7W˪>l];*
2117
2118ԡ?ixPs(RƩc񻷄x\(I
2119MF6MBb>a[v={fyO !e0T'?ķ/
2120܍V\|xΨ]P]ϛ!c8!L@y{}hԎ}'R_/*_`!_2B(a9&4ѝ _Ql{r2N%ܻ-"5BLaIj
2121rT]P.Db9Ums] G
2122AR^u/w>RJH'H
2123BjaaA Hij ߩ,y-rٓnfŒlfLT,򢵋%o}<9æ-ynU޹i~قJ,YPf IH !&T r/OK9#:,o2ǹt5e$.0}yWBF^Y]p%(!)i/\/)s1RU *- a? ߾r#M .'HŅy2$9#zSL}-Uʼn Lť&*hZqp^郄D=x$Lƅ%ek5<z 9y5| 1 _O/cuݩ&\<z2)QaޞZ0UWF-JLXʹ탼|¸@ԴfBâ9qrk%eUwb'&l5żRnǍ uީuzA^si'ݹushbg9Fz*,&wKF%
2124DV^YM)/(t֝ǒO=rN~e5>DV=~yAb^x 9x#da{5Օe7PI\j]1aZ~T-5%,5h\`X>p %7YYbm57Enݹw‘i2s o*Ss䥮H߬Cܿ[sV⢂̌ScM!k<,gB_[MY^VJ\DpQD4.0a;iKy \z] )9x8r~¥으kE7JJoWܮbQYyViɍky9ٗ.OO;rhb=;nۀLpwurk5k4TʓpBi1r8[,.0C  
2125QӚ:mLN.K=Vlu9v"ԙs.g_-((dQPp5?/7'rsigN8vPo{:_/OwׅY[j*cC β`*BT5u MgY͙7suA!#ؽ7C;|ԴsMK=}dcG:x n1["7^|aPOK}$YIq!R
2126qII
2127SԴ3-m~d*o_M[ص'6n J$Ao%??.vϮ۶FGFl
2128
2129^lBysfa*rbA}bp ^
2130brS4uδc0=Wy MQQ[XDGEEFo~>^</]pt#]-҄ X^
2131,X|/D$Q(#%FMgZXER]ܖ/\{ڵ~u]kJK\6V3MM 5TY&Ơnb h+d(\"ȈIIkL3nj>f\;{N -&Ao,r^4n+YӍhNQ<QVJB\;
21320P> C%2w 8!B4v;Ux 3YmXX[[Ͷen6cT]m- 5eɓdBdM$L,BxQ RҲ'MVPTM700da`?U9TWS0yDYi) bqcnjfaTtK*d,vDTL|DyEIIYy
2133;JJȁD9Yi) b"B#1*:`R Q~le("!))%%%JRR;-c )Lt 3j4 /BamAA
2134B Àz(ԓlB?` 
2135yfZ5 K@CX<D0 !
2136   g%t2!CZY!PfZ
2137
2138
2139
2140
2141
2142 6l#06l(*A(Е:lHQG" P6z(Ç WK_
2143|%F7_@P!<
2144SԵt (z:ZSĄC_CGQP71b
21452|G e{a _<ce4[9:-rqus[<
2146޺٬7JJKo 8JKKn\/:{|U UeExZ]aƉMT7uٸ3żUw U.IܹX}ظQZ_ ~I&s slvaIEU{0@н5U%g _x$1~?P#;0k}?k Θa7cfp:ˁ3>/ { {Ep½eyi(̗<jk]AAG
2147]]ܵ'^3U5Uʚڊz׵qMeyiUmO3ݛ\k涹Ğ T?й.<1 t؅2#Xwy]MUuUMuylȘ`?bppT{`kŶ ;042u^x /M#׍78`<l3Z8u_6\?@gw3V]Ymf ?YUZ[m>5ƓcN< f ob}67ؽŵ#|s[()pחVV׻rUV*WUk'U#coVp\skpUTկ߾)DG䉈t/M! H +C}!R)`kf!R)`kf!R[C4[l l2D
2148bkf!-hbkf!-hbkf!-hbkf!-hB7h)toB[C4[S[Ix [C$1]kX"$aq2l /aq| Ct <h+Eh}ab`GS.ÅithIhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖KԶhɱtOm鎖L춅PtOp[NPtOp[O3qEA43qBLAE|EGHEM5݁t`tGEt݅xf"t@DDD*t hYr!i*a,3,(:@4/_bE)>bg`PL#!(88$$$Afuy(G30"bexXHpuyGD'$BjdbDrY"yD'&2 ;JOMND&+yN@"2s JJK0?'3-9>:" Y@bӲ*kW^hW76Te%
21493RSE3}~E&dT|;<_zD~<G;/_]QM3F6- S/.%~c'ǯ=i"'z7֗d F?69MlQǨ=W_W3?Hȿ~g}uaFB1I3~V[?ϊ:FĦU~起gH~췿v^[Me8&%k>'~~eâsV5m7/"/|||֦U9abQ4l8q
2150 JF"{g^$hw~,1D:2Dn9ߢ4HD֔M&{GX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDb"VLĊX1+&bDՔD~S"?xyH;'.D|N/rJψĚ ~9ϼ~?Hwt"F"{|o=o32/>|lH L*[ݱ{x/w7W^|eYNLtg?Ǿ×o{~W?{եL$Ḩ򍧞ѫ|w7}~ꏞ{_F#&YҰyȍw_ͷ7WOt#;77d&8.e!񮢺p>G/_篾O=ཷp"W|DH2%^Xgp==SO?^|G޼ ?|{΍)LvZ"+WƦW6o=}<ط~'<=;NlmO]Q,Y"(<&9qsy='2~?>x;?:~oscYNrLxЊeKH`XTbfQͺ{>C=Vك|+_;>zbk]MQfbTXִƶ~?=myi8KV$b6YEM{p㙳nŻϝ=s {67Ue4z֠kFFq+cGGGjk)I rԁ<$:1=q=w޳׻=wnٺy]cuI^zb1Et1$$IJ)*il^߶}KGt:on[XS^!1jIWTVYSиz^PWSYVfLGfb"̜¢Ҳ镖d%G#@Mw$1ɩ̬2]ɉ1ᡎ " B&Q1q G q1Q#(
21512G ݲZ NQK,mr7ȳ8Y'[DDD)***cg7%=$M)TS)ݔar2MY'?}pg] <l6vR^ߏ6>|OD A!>&s=wA!@D8"(3R\t'H<Y6y<r@t}ggTTR̺w>Q:wDDDDT/(((,,,***...)))---+++//khhh4Yeݺu6lhmmm3m=Ww1camfvӳ||]a"=L_#
2152ۆ-tdw{W.!+$1I"O<
2153^#g!3E7q4qp_Ttt\%|1w"1[} zbZwtttvvvuuuwwl۶oǎvk<p:4<<<?>?:Fx <.mÖc
2154s^juw.Ӟ LϊY-8{Cq\NsXY^?Ŏx6nƫa\ `gUxDFkVDbǽ<uW¼,撘EGo79 f2&vGxcX9AQ"754qF0ymԕ"2,[v;LTKA2k%j}i/ﶈ(^dV,YRO/^eݹ.>xAě)Xmbq(.X$ \q%٢8UB?dagEw;E O+Q3O81N*
2155
2156*MXX{"<'Nκ_"kgDgɬlq1AGKX~vq'$EEEΖ?͊-*&&jHt8//c'YY>V|Y,kC<z~7ysEg㳲rrrp̵1lyvVK--sVV Y|=AhpeҥǫX;+i!oxo/ ZDYܟ;«j+^aX>ii'Isݯ⣉ZhD>~[V\Isݯb@/
2157Dd
2158ϏZ:뵭_=X>Q?C틇|JwDκ?/:ӵU%\h,>oyha-S;ybbq*l7|
2159ԏhYRY/3Swg"thwEvKs{N}\a-uGtv߭o/dgNY%4n߄3ok YY"5^;+~Ev[5Y WkP,Ig(7LJ~˜yvנL-/5mwb(qJYϋba<opb -,l;5-7[ ߫,.COD
2160문hinp4nߎ>o yᔖ%R浳q
2161EZ`Aܝ 0oΊ7z297J\
2162 agxqttX=A3~oP2x%R lLL=03~׌xA0 c ZvV9+. T|3~WwʳDʼvV#.@%N~3ʛAܝ `gfkΊ7zⰦE$m_-nHA0 .>V͖Ί7zPxiW6OV↤Ke([,lI:r%$$`MI
2163↤CP_͖8Ś7M˛A08٘%R0@wqB~~!i.PxvHto$%%aMI
2164↤CP,o\XӊPXX(nHA0 %ޢ]b;K4[΢\;8I[Hܐ4`(q***%R㵳 QTi8I[Xܐ4`(q*::)YF
2165↤CP ]D
2166v6""B233E$m
2167qC\ ex<;K`jgQ%Fʕ5-'i+TVVb %.C%$$!Y"uBE$m*qC\ eDvH(%.`MI
2168↤CP͖Ί7gQ\i8I[Vܐ4`(q*)) )٘
2169Ú Is1,:Z\XӢqBCC!i.P2TJJJll,;K`jgQ%
2170B
2171
2172
2173E$mFqC\ eT<DPP;K4[uB
2174 E$m$i.P2TZZ;Kf΢V(WQQִhk֬CPqqqtALY
2175*..ƚ Is1222Y"5S;*PURR5-'i+477b %.C\`vh,jrbMI
2176---↤CP,KgQ"tBP2iݯ^
2177֭7$ J\JHH agfk΢V(Wyy9ִ†  ys1 Y,YQ(
2178媨 cI[Uܐ4`(q*'''11|͖0:Z\XӢqB[[!i.P2Tnn.;KfjgQ%
2179BċyfqC\ e<<Dhh(;K4[uBQ44NVOb %.C糳Dj,EDgQ+kZ4NA0 UPP)UWW5-'i+tttb %.CDjvUBP+kZ4NV7$ J\***JNN |͖0:Z\8Ś Is1Y"5^;BV1ִWXmnqC\ epvh$E֬Y5#nțe(vHKP(
2180jjj cI[a۶m↤CP,IgQfi8I[Wܐ4`(q%R6
2181Z\---EVV7$ J\*++KKK[r,uAH:+.@hhcqC\ e(vH΢Pʵai8I[a׮]↤CP颳MwD(Wkk+ִh/nHA0 )tV|,
2182Z\mmmXӢq!i.P2TEEEFFԯ" ,ʅ3Pi8I[a޽↤CP,2¢>(j%.cMII\ eJ5,uAH:rcM:888cs1Y"e΢DXPс5-'i+8p@ܐ4`(q*33%R ,ى5-'i+<xPܐ4`(q%R6
2183Z\]]]XӢq¡C Is1~ջ0yguzm+ b %.CDʼvBPimqC\ 1lmmmvvvtt4:kuA;m60FGG Is1€,\X:aɊBV(Woo/ִhpqC\ 0`{{{]]]NNNLL,uA;'^d%m1qC\ 0 ;K4E}Y,YQ(
2184ڱcI
2185↤CaXvhݵkִhpqqC\ 0 ;K4΢DXPߏ5-'i+8qBܐ4`( ؘ{Zra- `MI
2186'O7$ 
2187Ds1
2188Z\8ŚN:%nHA0qqq"0cgE$mӧOb ͑ggQ,VY
2189BE$mnIܐ4`( ݽf͚xvhf,ִhpqC\ Y9t%’BP`MI
2190gϞ7$ 
2191455&$$._tAYi8I[ܹs↤CDs4XPuAi8I[[n7$ 
2192n۶(11%;5-'i+z↤CDsY%’BPCaMI
2193v!i.P_nbMI
2194' Is1bg]XGtUBP+kxxkZ4NV뮻 Is1€}}}֭+))IJJ
2195a-t>Obvh,bEP+kddhO}Jܐ4`( cǎ 6&''DKg8I[3!i.agγJ%+
2196Z\7t'i+|7$ 
2197ڵ,%%eʕ; E΢q Is1;K4wS;%+
2198Z\G9s 'i+{↤CaTvh|쬤↤,_xvAdEP+kllٳxՓCa͛7WTTfg|cgmfl.;K΢8XP5>>~9l%m/↤Ca{b@?{"{gk+河D~d,XPu[ngxqksEm1€*##Y
2199a-Զƒ>(nXggQKV
2200BN8q뭷~3,}Mܰ4׳CajNm~Xp7%(,(jr<yn??#<"n;CatvvfffFGG; E`.m7DmY"?P΢>XbɊBV(שS>O?~Ӆ$ 
2201<x.+++&&&88%_:㏳DY,VdEP+wu׽+/췾kA0<tPwwwCCCvvvlllHH;K;-.<%Z\xݘhqD ?ED ]?KX:SAY>(YEE--|>vC@L,h!YówϗΞ;wVbvh, Eg[ZZz{{O:u[LJ*
2202A0ġ
2203A0;K4GS;WPPf͚aM{$iCa@
2204p@apvhf#G=i4WVQX Y9t6888666??kpppttk&Is%m 
2205P X,/fִMJ*
2206A0;K4G]tiPP:vvvݻwxxkqb q(8,`֌=tִc&Is%m %mhh8x ִGLJ*
2207A0ġ
2208p@a!Y"_;cbM;l4WVQX 0 ;K4]d :][[y澾> kC&Is%m 
2209P XD%loo
2210A0dgـȬjtv۶m$͕U`( aq@ap"YYwg׮]۠I\I[EaCa@vh.v633{ǎXӊI+o+` YpX"uvvuu屛J*
2211A0dgbjg#""\.Weeekkkgggoo/ִ&Is%m 
2212P 88YYtvÆ ۶mÚ$iCa@
2213Y"eήXbʕ֭koovI\I[Ea1€8;K@ٖ{vwwcM$otm ,K.$:^^^܌uuuaMg4WVQX ".@P YYtk^bq
2214vH˗/OKK+++[fMkkkGGִLJ*
2215A(
2216p@a/`g|!lcc ۱1I+i(,p(`gyljjjii):n:bMm4WVQX ".@aXpX|ta-644KXv$͕U P,\LlXXXJJJIII]]]sss[[ִ&Is%m 8 ఀ%IgkkkZ[[K-H+i(,p(`gY:lٲ5klذuk7I+i(, P8;K@٪*q
2217kZQ:Ism ".@P)٤JTE,ݼ6WVQX ".@P YY XӶ$͕U P8ِĂ򺺺&i[MJ*
2218A(
2219p@a_Hb痕֮Yk &Is%m 8 Dj,]tl^^^iiiuu5@]g7wbq
2220,:[RR".cMb4WVQX ".@P;Kfjgrrr+++m6I+i(,p(|%;K:]TTTQQQWW'^jA\I[Ea1
2221
2222*,,,//E֘$͕U(
2223p@a,/lfffAAAYYYuu5ִt
2224D\¡
2225A(
2226p@`gLl@@@LLLrrrfff~~~II ִ&Is%m 8 /dg|1]g\.W^^^qq1ִ&Is%m 8 !Y"^;[TT5mI\I[Ea1
2227A(
2228٩_dbǧfeecM[b4WVQX ".@P;KfjgWX5mI\I[Ea1
2229vV|x6---++ k|bq
2230 |%;K JHHHMMĚ6$iD\Bgq@CD
2231v644Tݓr5I+i(,p()t6...999##kbq
2232 ِq8==klbq
2233ta-vuV#.CaMe4WVQX ".@aXY"5S;lٲ`tVݓ5mI\I[Ea1
2234v6((Hݓ5$iD\¡
2235$ONNƚ6$iD\¡
2236xG\š6$iDbX/bg|ᵳxEÚ6$iY `gLҥKQ(vOLLLBBִ)&Is%m ,2ygK-H+i(,0,CXD%ήX"88X\:CݒLJ*
2237 ,%R0K,A=2ִt
2238DbXY"5^;|rtV݃屛J*
2239AܝoZ~ ;K:+6$iD\¡%R&טּ %^jA\I[Ea1
2240A,,;K:yu2I+i(,;K^;~G\šVN\I[ag|!ұxu\I[Ea1;K4wu}8,, u0I+i(,/@DKYq2;ݛ,/$u_:vwV\I[EaY"K&7WV dz@;K IgݗKJ*
2241AܝF;K yge(-$i
2242YY"_;+.CaM+J'oAY"etVԺym%;IgݗP`º,\LK<.+ixu_bgͪJ*
2243QwDSZQ+i(8egbV4WVQXwg[Dby,H+o
2244MD@1 a!b2;d{/G_t? t=
2245]DtODSAݓ}alBL_pt?!tQ="Ʉ1_zgp[Bv5 hRVZy hËf7e/Fڟ-@~k/Rڟ#-@k.R iҵ /fҸz'"Ҹz'b/@sw/F һ 4wzb@/Asq/R һ4G'"@/Asq/R һ4G'"@/1?f@21>ab<_6c~8xOq:ytm<X8ݼPZ oиv?]3a2k7chSo"'EͰl}#kyx9N9=Ymck#?>/sy 77]#ٟef=ncn`ϔAycsgv?4ر?'' """"""""""""""""""""""""""""""""" """""5K/&ݦfjbRep{.1JYi$6RCх{懱'FF+"hR``
2246
2247 dDl;8c 18 'Ǝc Q+BU5B7W \=  OHH4$%%%''$''%DEz#< 8
2248>3!!)k6nwpѱ'NpԩN~cGG|m]injQ˒\c+VXNJdJǓս$q& 8 1
2249+״u[j=k'NVUTVVRb"&gR3r
2250 ?˃ڗShdBz^imƎ+w :|MPwyǭgo:yоunTnq5g)怱عb Rc#=ZjJT4~/9M5N.[f͚ƆD#(\Мu#dMĹl빵x#̬lX۶W=8r솏Wv빏9g畝mk+.J shc*jp>XW[U]KO2fcuaCǶW@.I,âR2K*״lҦ6֖_h,3cqfWqnl5O=Sst'X?IrV_ּasgO#Μsۻ[*s҉[cK*pNزn= ի.Hpo326%n]{O߮]}WXsgbɾz][˱"5 QfK/jhZ׊8Z77Vl<K*(_ށ?|cȩnݴnM]eI+8]a|Ml4ҭBڷtlm}vH}f]\vs;zzW:穬wUܺqfg&<:1=q]ۖ+z޺e389l|&gϫ[:tӇ?2s˪WMn1K'Źse-mWnƵ E٩񑓧oe ꦶumKN\i68p`po-xsx҉3ŬK+/[ybW]s{Ԯ*Sj=ewNf2s WU74u:kغWī8-,ohٴ8s
2251H40D\7A83k6v^KNtiSqڴC><2<4{SSMq1qębniff0 sZrןxT6\~Б'NLi%5jc ɗE񂗐QXgvSvrDNKr:i,sG;6vջϕx3(ÃC 0q*%i-'.-)%=+g];GƎ܉eeQ˸\2qqzr9]CCۍӒK\9m^[[
22522&%eK8ĉ׏U榪K͵{y~sU׌><<`"'r8|%>)53e};vо[ZJ\I;SFNc߱*Ñ##mY7q]!`z/o+IA.5VħWn*u#wniOUT#0k%y>K$]Tt=׌^gMUEYFܧ18VAe
2253$C>go-庾&}x׿Gi,G}Ufs+ҹMSN?<m3
2254Q ϾO?of`F_<z̭ۖ\zկ̦)'/Mg>Φt4M.O|
225534%*&ԧADw?MI dr!dw?g~K9]z ӊϮ'*z ?+=4_?| |9ͬO螘=*Q9I:>3}=^ʀ]"vPN3:2"^agf1y"{} vSǒskwy?w=iܟʩ V {x%/ӈ=6]?`>vB)5^\N~H{O}믟??3llXWNHp۲`eO,Ԇ&Vw2ws9v)+'[AS޽wk]֠PNν?_ 3ٴIeqλ}zW|h4v+.yJspE>oLN.o߹kjokuAt5%o׭2_tV L~sO˽;>4S&m2_,mn/brҥKb}>tauc{woow{cu!7{k^]O}fW6w_t=4?<|wom.yYՍZ̧Dt޺}޽{wo\[MF7QWc|09ZSgWVQ2mZ췼~KGptzfaiټPb~J} ؕ-vzݳ+*WWz&G`e}skksc}ueyia.NL ُM+n]t&ˤW_֯NSٙٹlʾL`Wx*IOOPixAyQa. wh|j:;;7?77˚ex*Tb^vd"ZUkqڻn%J2E{k:W~/F'e}),jȻMط;)oxo,rv Gx|*:91>6:<4lk7n6tt#vy֎E#cv@_W,]/^fWeS1ɭo2oo`(2<22~|1Tڏ#?pļ|_L"H.^=j ۍ0auoߓ{L[U흲Э%w8U-:7L=u*ힵV{C_$+/[ZeGy)YXS_vеDS޼4ծM UWٟ.bmiY4ygDџn3/ [#,.]_\?œ֚xvQt]k{[d㥢;j;h_]@_goܹhzay>v+/p{/哙_ڐmmc^P]Sᶝ_;#-w9ʕ_p^;vҗf3~ LE;~eX?~:Y%oi+q֫[._zů.v)P~}~ԯN
2256
2257pʼD~u|Q(Եp6%fBwnj_
2258\L5.:@vUFix@#?@iW_\d ..30UIs vMEʝvEEeJjh؁])Qq?@yѮDڟz\hET.>P+"*g( M(ӮE}Z~@v(7R<PVEF}΁]. [aO]1<B0΀v%]I;ho@NI؀ѮmK;2E\ODѮjH;&˾@$ѮjE;eX
2259
2260[..Ӻިml  u7ׇnJ`]YS[oTN^KJ?1iTזށ`_WkcJIu6y
2261hE9$ ߬mlN v4K+zÆD[P$jk
2262K\UGr!WY%7teLk싌Gxl|82^MX:$CãcjR?Wx^?${ZFT:D|SVΞ>ձhl*>i
2263K".B5uOݰ4QTy%7"CԪPc{x<eS^9fN%STrjUkaK hZ5QWY%sGWym&spi`CաƖ d,12ӱAZyS
22641"1ųV&0zQ 5t*=30?;M\754wGLL͘;[k6tKYzoFN㻀644655qhWW5xfnqia6=5P,g:-,-//-̤\{5<=G^\S7MXήR2=4̙-eL\ZjM_g`x<HegWVVsMܽ? ڑu{MPML]<M
226521d *J7n 5D&gWm\[M5oj
2266^rvvaie}csscm1%τy'wW2+jLut) NLFc1;Xg:OU7CmhjviTL|LZ_/D흝᮶f>ZU jQs(RЩDR+ɩ!NMWo8[^5qZF&&+k[;{{;[[!&~-NꞼԘ6Q馈F'&&'2 Mgٙl:3 &*5uMᑩڊkw[=ۻ{o
2267
2268tun n7fL'괊HS2UT!'EtF*KKK34VS5q]1q]qmoinn-Jepppkw˴Dtlx0mm2fWDJOiUMlԮ~7ALٜ",;`1ѴzƳ .VS륺f%{ dlbl$2809OtތE" 6{^d2Wra*t}}ccskkksDD@(C}]-5;-;wn\[^ɦS56:23ٛCdBUn]]b4VVȈq.iƜ++qֶlo-LGm"mh*5g6^Kk[LT޽+qX]^3 tj:&tDt\h/_&'%+WZ}~*QY?îo(nʹake4y)Ѹ78fU/.ۛ+K 3l6N%㱉QYM v޹Y[QT婨]:(Ӯn%RUGSY6 {ζ03lXwl\ӱсB\Ҧ"JQ)N,/a'qX$,ѝ".}zKd kxQ^SjƧ $S6s`'&[6& K8zkgxtӱ@|MLgַ|G⻶8?k"7X?v\+d޴|[% #cccBcIR\_GiBzK~c\Lff`dt r%wWowT{kɩhdOƵ&rTV-Wj]0:n'X7.!M3f:;oI4luIVU3Y^˥#2TW[[386҉{Ch ^/jd}#ӑZ7D~1QMڨkR䘴I 2d!73#Cՙbo{xږj;=?Oڐy֮D*ͦ&<x455_f޳/ ]0W75.s&AIhLd;Z3K^*UMU5%n'd 7'u&O 8?7#1ly b7wQͤxtbԌJMz2>usÒx%2p2l[ܑ&w_:+K g%Ilm]TcUVL&dttdZP~e`#;ok6۶K@$ۑXYQ]]#oh̀t|T!T$e0WV7ib\Tw9hީ?g+ -ISUMa{SΪbkL/,zpJ4\̥Sv.ah@K.Pka atvfn,+Y[.ˀxomQ oS2`FN
2269Y&9K1iR S4@s[]=dkȀxt\S 󉙱%΍l>?fГ^kYfDu/423I5yNQi*/#b͚_ڮt2<lF#v]R#kfYI32'ylr=4VwSm;fZtO 35xtl(dU)4tۻC_#ϸD!cpݲ};G`DIO"@(:91>& 2{\wZedG{{Lutʄ&Uv<eӒW쓡e&S/OʥѱH7=^q4ҴڰFUL2i* h|*F'''L(ݴȰ{bc&e{g: ( e)T۰[E#cv݅fiSX$L\_Q<MMJTIofV\eu"-bR?v{r~-]>B*UԺ婲ظU_+e]_ZI2?m\Ѫd̴8uŨaOalSe4i[o`ߋS'=/4AVYt?F"=-׮j4 vMDe465.t]uY- MDԸu-7MgeRUV[[mjzn\j+1֨{[Cx>#-!5S+isen1nL3eS8UVym캖hB}&Ӳ2+snVp֍Kpo7d\ًcSk_Y7y"\Ye.ͮd{h7b-K{jۘʺB3n5L՟wI|/޼Y®foICa 3l%ށ0v~z7֡pO#4Lʬផst*]7W
2270G&K?_u~%4nNӱ͔1*d[Z{ݠhgzDYM)LyffP'Y:BX+^e;o,YUUۖM~a7Cdŷ'~eWJGV͙U;Ú͸ldg5JySCbGG[}z&I0oo-,踺!]r&Ǵq'P$఩Gw滻ݻ,
2271F?!Oކi/]];d{{UIBiI<Uu@ZUB-so,s)T揚揶Mv k>QYUYa]][t.LFx- m('}9efcaGcVrXrzg%I].>Z2s|y{ߗ
2272um
2273_ozk6M]u]UIN}N.vhKYֶ8UVD˗f٦]Yb---y+Dox;ʏ*8DY!|IZv̜-0a-v)
2274'/Vpum1m ,edݳ8q\Gas<Ɵbae (meUvolxSvRb:cFHYwɵߒKGr^XIm?6G)PXVzUuXǥ鏗|mŦs JMvG]/ "2XpEUŌe=iauti:-M [e{KC&HaleI uppG[_[kbU@_3tD U#dnqm{쿳-a= 9P-/iITѰ3[{޿mIšJTe:{ITN~?<O.o{ٗtB؄lf\f][w?xt]Lz M\{$ϱspwy{I5'd7q-c
2275*щi9j;Xy!vG۸r57ka;w T|ҞtNꓵr]
2276[=#JMgDU^,s{<_Z-r>݋.T}Poh rwIN~xckW82KQٌGU;ǞAX㒫lwd<*&$QNTX
2277nMyuru!F '94:>11>j3pNKۏ]O}rue"Qݝiq+ުvq2Emv=x^c{]1,){{ީmVka :yFy[#.I!Ɇw:1GaS+MƦƆz uo8)5M&6OzXMG ջ;6]]~d5bN,twU֨F,¡/)a7᮶Kx 
2278TW1{\mt^O{}M /|w{wĘ_Y^g0YC;mhvǣSgր8:k('zN[N 2 5 P($gD*kcrCibC饚:3B)6yy"ͺ]m 
2279P\n-1LME81JM]5in̳Pn-.F9iq/P|kwo`ppphxt"sh66tl,!  X{ƒ<h<|쑖C{wȟoƦ≤2-o[kKsk#D^u:N>%
2280Aua]MƼsT@?4cؔuǝm O )@u꺳Krm:=N\ Yf͞ oq)5 Iw /4-Bt[ .{nnI\-`f80$mܒy;`zã=mMi]8v9=U7ؕ_q"Zl`R3 J\nnzZ‚9}x>۶^on_
2281WHJNx7\ݽd #9؅m$~`$q /rYm}s/k![˳^\_e GPA&wӠ г H\6amli봻bDo} 3gr [#mPn0E/epTqN`VmuauwHNL`FuzS] DܩU5 Mj67*Wyǘ堭r9h_`(226KE[$Y<(nǫ'.`pp(2<*ffgsdT.`z\7u E"ɩt:ͤYݦ5|G1{t*JNM 䟾@5aiWǍ1蔉t2.v[ D
2282\h,b6)X$]HSy`x<:H&D<H$NS!ACgE&LdF&J\&7+<<1F63Uu%
2283GhTp8jZSu*i88#;㜱1TSE:;֖붺׀ofnǯ}ݝ&MFcccC}]m a 9]ckGw_Tζ&fmmȨYu$oȯi5==օL4oVY7n\vkUM]Csk͍u7_1ArY0a EH M--TsSeԷkx:TW $o0Q]"AϹY5 k fě{fV|-Bp!&~* k׮_wCf .K$ZoHCX/ [B˘aLsQU
2284ert211΄d,H$d.Kf҉p&;K[X25 ? eӱ\<12Xm:g;Tl&JҙX2J6ϥ͟ųt<'ۘO/K$bd&ƒ霼ݙy ;sX&1-7zfZQ T81NSk_?g?W|g5ct. zP#)gO^>?<cL&1&x!0w_c1GsB6OCE% <xG^{SM#roSG:6{hG=☐By#clc/+;^~vO <G+;3n>;oݧ ?7 Ͽ~NOg;I2TX6mkxBx<k~{?~sfٗ?{ei4߿Z?ٓ{[013Jc'cű_ o.<m&_23_D;<8fM;7
2285
2286
2287v
2288
2289K!QWeR3x+E%XUui"^{,(Bjyx]!ދ
2290!ڇ*B=K !NڙB+vi%B 9^BH}o#nx]:!uNTrAy+ՑCx]!o^<R@yץ6#tx[N!
2291}ۅ׹M!)!^g)!e]ufB׬IB}g=uBHx>ksBNNV:!+1.ByxVk
2292יC!g׎ !ׇ3NxBy#>NiBy79^'0!xBjKuRBH}ww!]>}>!Y?B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!BHMh׎sX:$(_6T?…
2293xYtEB ֶ6YbE3ͭN^V~Aro=]*zG9
2294?8<
2295Tz%)8 0F{;}pU%KŦщ陙)c|txP;V
2296R._Nv~
22971f D:eӺ8!F:8KP
22985
2299
2300(/5
2301@nie }"qz:"wpLm +BD4u5Ϛ Զ@|z4D- ƓL&../`,L#P
230216&Ru8Z6[vV4X{ۀhdR*OM:B hñd6$cjA8& WW{ë6Bm
2303SBU @M 䊰X}'j2ڊfvrl@`ޫ7IdV7677֖sX{;:
2304HRp@}RT=2+뛗/_ސ~(P}R=4>Ng,fS¶ ͬ
2305.}s;
2306CH<_Y/ZBijZœ .,,Db̢ސl?Pi&RͭM9x8 Yp4A8Jer7vd4T\
2307Y
2308Z7
2309@VP_Q{fv
2310@5C?rd5>vU.e сb]
2311K wv]z`2/3Ila
2312/? J]=}}ݝm-h Bc3
2313ֱhOѭ2ydl|bbBmԯ]ؠGf
2314^X۾׻ oQ#'&d׿
2315݃
2316$/35[+`z!z:}Ni&E*i#eggGU[A0o`d\;X"-.k[Mg"{(|u啵uWvͿ/ 8_49
2317T
2318?9)_[ȼ8'I#G?-=tގ.cIfW}ݫepגo)VEDickT8潰ɃZ٧& ퟁ*
2319VϤL5k_Zxk88X8BR wCqW.OTk}ãzpN?\ڔ
2320O1’ B ]^O-)r0Pޡ4>*q!Ɣ:ԁ[/[z/:3 EW%V)3r+Y;RI֫e:g|W\}WE
2321 "5kY7Яi*j-@:diG~kZ (#o9Q!=)~ 2g hOZj@:pcǫ֋5ظ
2322jrO$t6~թ =z/c?mYM-ziZ5335iEgݙq}"mG&' ?#DR-Qk>d
2323YͤQ@q@s7Q|Uwx?CX$F6+"~en-WN^#j=g^ᗌQOM[ZZq*
2324
2325@<:朞P4tu^{G5g
2326
2327=(~/gxP
2328+`r"
2329_X@_%}$uClSLHOp
2330lpEj7WLdl-{AZwWm[PǾ
2331>=P
2332
2333T U
2334& @S[WTpAMͪ~=ύ 5-<eyhg
2335pH32 <rݭזu9#;z&f1 7s k_9_ ]O#`}U㫕jqi[[iM7Ⲁ,. P?oC !}\pVUlLUznOg>[.SX38jL32[kT9A5C/L@}/3u[{r1Xܶ_gZw:[MTK<'IC@kodHE݅*7@œ;{j~8xH-C|ɏZA.
2336U~1޾Zptڼ]m3w-QuE]7)Pϳ zC; [YC{:-ʪ|~P"MRMVLo[m |qm
2337ZU>3(nVzqͥZ7;^`,U~R϶1҆Q`;ėU~cj֝%*(\۹r{UQ̩7 _Tx aB!B!B!B!B!B!B!B!B!f\}7ߺՋ뾯}]ӼFg<˜dOwſGן>ZsϦ;_ƌGbLXHLƍ2x$ϘB"ɔ_sTLT֌rnH6}t6ʦsƂ:(ID2ɚ>lHĒ0t$x:I&30Oa.1D$=L3/ͤd"xL6ƿT2 '$r2tFO*c,rd,5*GaߢǏ<|ދGHU~񽧏}E/gCGw}ڮ{*y/?RLT^<W[_>M"y.U&KyߋmK帼~߫˸]}>i^y߫:{*9*я9ީbrb.{ _5ֿ~!}K_|ۻWϿw{򡯤4d1a#35nqqcU\0c{Ə&f<nᏇ>3G2r/C§
2338f# ӴŽ\ɛ>tO}ߡib,Z,}wz:̡O&c#Jm[z˒ү9~_2#D*.i.F6@ ̤rFC+=xxтwOJoqȋʋl|r}|YÃ8wi3TY( ?7ٍ PM,bfi)HӴ&n#L*)Y;|/I't(U  ƐG83{T\2wx8 ge7hgj]%KK?课_1i{ҠS%92s ppT*wz'(:X>߷, ^ۏrcB$+o߿ueG&
2339
2340U/hm-!B!B!B!B!uB!r'E 4HoAB!B ySČHΌ'3I#d3x
2341i3Mdp$ә{A`TF$siv@X1 }>n'"鄙uE̜,ޏGbd!3l$JR;>uxwQyfH2t<Wsg3I]Lc-_,ͥ*^T.eE.䲸2dG*.`Ʋ[Ì?
2342d:R
2343[!3CJ>4Kg&JOC?a[d%T(hYDT+l,ͤfKj{Ɋ7tJ!BBes*9ɭ/^S=gJyX;P^lIuUf\*L%sKX?v3*$7RIC\^ٜOL%bD,ݺKH*I?!+Q4VSNu)44lT:'Qپx ^\X֎DC1T(R}B*H+)q3`+CaH&tfV=PzM㟿WIt/bƋxgE(lwQ#ݳJa%oڟ}ybzѪUaJ{HMerZYk??T2kd$i­n.(ݹ $ef.~f}2>lx)uo{NJ7KxR*1*Kjy,%l:Q }2%d w6%j'AJ_m\)lJ7K_\JUOt􊯷j+%+ T9{uT~\.Yx D +DgxTZ7eH*nt=a)D>ʔ_jY+*~zԺR&ZR="V۷oY+Z̴P% |<KIbfJD<2bݤ f3YU۪*xό&2s+"lnͺe}-nU4g5\šyk{x~O~Gb_|߷UD6b<?xa͐ ύx2; lo*߅< doAG6Wwh6d.)3Iգ 2 $#TPR"TfH<L$%y-JTƩ#Ocif
2344nDEI$ 3fd3G}Yos O~'B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!zBtVxVYu444x
2345J:+N:AsNs^sQӨijj )˃^~=൒
2346ӵ8V}EӦitiz5r!7ayPPŧk%^Qd(U֌i&5~MHr!7ayPZ~El^+:]E"FP'KKKKkkkjnjh>|y\M|X؁59E"^-J:+NWxU1 gϞ}w7OO_׿5>'y<%f)*ZIg1PNW.\jRxt}plu-P\T$k%^+-G൒
2347ӵ9k%^kR\*ZIgJȫk%B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!Bycz녩V Lj`USjTZ50ժV Lj`USjRB!B!B!B!B!߿u|뻩=ֽ^?]}Eן_{ǭ/>7c~Ȉ~デFp}_qkxv ӈ}O/mCGwf<$DXHH6e)ӌ$Siv_^w_|QKws{7>j7nO>{nfT223Ft|`A5ʖ3޳_?||ӯ5:_wpO= -[?ݿزULB'V*st@6rc/W(/|/zyo]0>O$#D.m,H<Kc$kdJec?@Y#>я&?|7S?.o$X:hB!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!R Rxt%Z[gJYᵶ
2348ӕkm^+!g:+NWB
2349uVx^k:]듆WCYuzܥq5օ [L9Ay… \ɿ{x,*v.h<%M65-6Zmi|ǁx]xK) wYOO߂koo.,\^ž8'DgO<:+"Z&25Y
2350 ҋNMWWWGkOӯ  kF41͸fBch&5SE_O >gax=6~HxOm-%bH%$ ~;^ ?zJX?A~ "# %& hORIdIpI|{vHIf$va9 QCC8NVH*<Ԡ>%7QK%5@  CP8_XXD"h4x<H$d*d2l6/iVVVVWW666677w4W?3$0.
2351)HC$_ůF:#v?yAsx,-KfCH)0H@K}oz7nܼy֭[o߾sݻw?O>O?>?|ѣGO<y ?3<5{x%)$tS.I[<Ri$gxg/&~)Z~>i>0C )iM$mZ[gK=[VM k(]R+O|߈od8>Iڏv"[CVy+?G~Qj8U^kpl kkϊ_sVI_p(Y^Xƿwloر=?ׄd/+뤆+BRCxs斬%=g_'+U$-p2 ƁxQ$pZUr>[dq6pv4Ť9#guVduPP!RnU{;"OYj!XžZ[gZ{Ɓd0&C)k +W!R_G(ؗkm^kMYI;{U3
2352SfepV:2d=:2CR5+=e(rb\X& PTfe*CXEr\8)`MZ:!Zj*Y聾2rjZzpRX&mww75Kip,!EEVI t˦,!UPQДtCeZ4\X醒j8Y:DCEVI
2353\8)`MZ:nmmf  *CX+'9B!pR.,ً/RTf/9ZA8 'I;00FR5 MvPZT.jr\X4i@jꨨY((]
2354I
2355\8)`Mڱjq,}AekQQ$IpR.,uERe&hJ:2(]
2356R\8)`Mډ t5KHTԬ B_PZT.jLF. &aCCC===,!QQ}AekQQdYpR.,2CRN/ a-*J|>/NʅAvjjjdd%jjj, *CXE`iiI. &h___SS5KH8iʂ2(]jI
2357eA_P.jr\ Ѥ͖uJR8iʂ2(]
2358vvvI
2359eA_PZT.j7nܐ '‚ljD"uJR8iʂ2(]
2360n޼)Nʅ؁d29??OR55ʒNcV [Q֭[r\X4iSf B_PZw۷o˅raML&DYBLr(bWԆT&Z;wIIf5KHuh֢tQ+{\8)`M|>OrjjBʤuQ+IRբIieYz.(h Z'|"NʅiRE֢tQ+OI
2361>spR.,mllP` ,bWDiZ8)`Md2999yZSETZݕ &5Ki(,t+"X *CXEÇr\X4iS5KHuh֢tQ+x\8)`MڝjpTPbWDTZ'OI
2362={&NʕMZjSRYQ+bWD,TZ_~)NʅA|guJRk*JEŋr\jѤf 9%vBA,VĮ`Be*JoF. Ҥqloo/5KHk*CXEo 'IKrJ4 !jEq,TZw}'NʅA͛l fے{֢tQ+~&Nʅ YBNQBM],ıPZT.j?I
2363~_ʅravФ}j(f c5Z??ȅravYBNOf#D]"֢tQ+I
2364׿ErYB^9vBAVĮ`Y Z-S+w(S%?o~=|ƍL0&j:
2365?C.,Rf,VĮ`BewTZʅ2OoѣG7ofЬ 68fEBdKrvX*Y(*VĮ`Be$>l?w/~ɓ[nfjhYB^eE+"XıPŹ e/˧O޾}{iiizz%`=KHm,! -8>KHmyPoLHmu=\?KHmQYSA5y4} NYoL]<G7jpT<7h`,y'$~qQZAXf y%iظ{ӧOҸ(I ,@
2366-Mr+U
2367aE.jK1STGE^phMcuR
2368 PN=,!'] ŵi\VyP.=,!'IpZjUZ,5K)qѬuliENj=يYjYBXۢqWZ.,!'$֢r*t@QZPP\ENj%0f 9=N}u,UuRTV5Kix)ͺ(IG5u^!f&X:U ;,!4\'5Ҙf 9!jVcE.j`%kVR\'Z15KBVf]:YBNf߱mToEZH%ErB,&poN-D.,5K q׬]e\pE,!$ٖqTvq`YBNȱ+ KN+N BjjXEވ)AHmpz*N BjZ 6Z%N BjZ 6Z%N B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!g;B!B!B!B!B!r
2369LaUӮzvô]'r Z I!Y0}ag{l!Fb,C+zaaVHa]?7nNvzӣhG;=Nvzڽ
2370ǧY+^˞̟}&o4~ښseЋLVkVrZwd:yc2.;r žg
2371s$]ǫʘsel'IAݖU ][xa4c{QP2p3{6z2˓=<{ھ`Aֿ7|koͻN%Us&ġs,Y^& GiYj1Ⱥyx7x\tb<({gqG^o7-/oyU= = ܣ2\ޑ./f9ƎM`AW"DɨCXhlLMxQ.Gj=Ǝp]$n}kcǮd':U}N?]N=z_p=Ma%V]p`&7<&%ow?r kq%l6[SN,kΑioMU]6-0^knn8w'Mط6o
2372K7.3Y`Y%vj5ޕ+{ѷƺ\Xr<;IExIr h8n˪ޣ((}GYG{<yј;p\;e$gX=vmx=<{ھ`Aֿ7|koͻNUs&qЎ 4y{Y\ϳ޽LƏrӺbuw~p{o yPd k,oZQ_L~?{,9z GB.w/Y,c˳j]vimTlOO9^ٹ>Vw9eq<( $N';ϋC3XQ}{AZcmks乜}[ںiVðImv/h]/?9<FOyo=}z+ЫNw/]"ISM9}6-o6.t7<>
23730' 0'8ҜM Ѝ_3z+v5<lxӣ\Os兮i
2374HԗKI+ri/nvK6# n K1#w}=6AVEeDFF8ykskg=637Ə)X߂orSSɄm||==>LxӃ3ȇߛ7e<~->L6S{.6sIJu֥fbK69or6l붗KTbi(fs}_w=OM}.TANasdliu[^FČx+l{GoNGaͫzr~z\ݼsy̱9Ale1g7G<0].'NCFXC%X%Xm% 'eZfz(-ia ;tFIwCUsŗ]79[|,UѸ
2375ID.~i/WҺ߳=}f$'bɴ.]~zrk^;|4Oo6:<Yi8|&E)Ch*.+9,ĕoCL(f8lK+i6=EfH
2376f
2377z0M`FiK[ͦʙ*aÇZ7184Ӡo3``꾣/gOmm<%Ms(A=6H{'$;o]QQ*9;+,C-.Bx؎}VxG;XZdkM6 עΛ%ErlBFQxw|]-fG0Eyҍئԣ(ĺ] :.kK꜡j.FlId`kj`Ƅ
2378> p<ZjgY24=0
23797C\B@!tǛt?T~3^MD5Us(ҷPgUV)!p8
2380"XL}zfPAj'^; tR#V E >,9s NTF vԅiǑ6r1(d<<%*tjQ1"GIPu(2LTAЛ=X-ĜHz<@6L.ڛxLY|sl]! M>9fŨs\p
2381(3|]&dmdˬPa26<U8
2382JniΆLḦY]Y8Bٴ֡**TsfBo ,/~]L , R25R*u9n8t, %~
2383=Jɔ>Ta.`phv|jPU~A 
2384PpSYF4@4dA҆ uQlHGǮFcVos~tݗs;kLQ6Fq2p ȊOǖ< jJdZgIUaQ#'#63-*4>0 C<OH:ehG(ĔUJ-${<WI EJFkoW,N&Q& ڹD}#aƖ,?Hփn/!;PE(4H3q"
2385gbqQQJ9y=jg,&d. @L4cWגxdH7EԢRB E+vo;Y֪yV,/~[W4{FAj.@A'3%w:
2386($
2387ҵTi$bƆmwo
2388r Gt406܈FA,[kADRo$DT;$OYgOV (&Enwvd $},:3Inf@ a 7!3sC`7w 1H.+
2389oGh~w7|*.eU!Fd:r'K~ICq$PU#)P
2390q
2391/GS0 gs
2392486 0 0 480 273.6162109 546.6401367 cm
2393/Im0 Do
2394Q
2395 endstream endobj 757 0 obj <</BBox[317.616 983.64 715.616 585.64]/Group 915 0 R/Length 59/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 916 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 793 0 R>>>>/Subtype/Form>>stream
2396q
2397/GS0 gs
2398398 0 0 398 317.6162109 585.6401367 cm
2399/Im0 Do
2400Q
2401 endstream endobj 758 0 obj <</BBox[385.616 858.64 653.616 814.64]/Group 917 0 R/Length 58/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 918 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 796 0 R>>>>/Subtype/Form>>stream
2402q
2403/GS0 gs
2404268 0 0 44 385.6162109 814.6401367 cm
2405/Im0 Do
2406Q
2407 endstream endobj 759 0 obj <</BBox[382.616 888.64 656.616 585.64]/Group 919 0 R/Length 59/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 920 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 799 0 R>>>>/Subtype/Form>>stream
2408q
2409/GS0 gs
2410274 0 0 303 382.6162109 585.6401367 cm
2411/Im0 Do
2412Q
2413 endstream endobj 760 0 obj <</BBox[408.0 947.0 704.0 856.0]/Group 921 0 R/Length 42/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 922 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 802 0 R>>>>/Subtype/Form>>stream
2414q
2415/GS0 gs
2416296 0 0 91 408 856 cm
2417/Im0 Do
2418Q
2419 endstream endobj 761 0 obj <</BBox[246.0 1106.0 718.0 580.0]/Group 923 0 R/Length 43/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 924 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 805 0 R>>>>/Subtype/Form>>stream
2420q
2421/GS0 gs
2422472 0 0 526 246 580 cm
2423/Im0 Do
2424Q
2425 endstream endobj 762 0 obj <</BBox[283.0 1022.0 796.0 520.0]/Group 925 0 R/Length 43/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 788 0 R>>/ExtGState<</GS0 926 0 R>>/ProcSet[/PDF/ImageC/ImageI]/XObject<</Im0 808 0 R>>>>/Subtype/Form>>stream
2426q
2427/GS0 gs
2428513 0 0 502 283 520 cm
2429/Im0 Do
2430Q
2431 endstream endobj 925 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 926 0 obj <</AIS true/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 927 0 R/Type/ExtGState/ca 1.0/op false>> endobj 927 0 obj <</BC 928 0 R/G 929 0 R/S/Luminosity/Type/Mask>> endobj 928 0 obj [0.0 0.0 0.0] endobj 929 0 obj <</BBox[283.0 1022.0 796.0 520.0]/Group 930 0 R/Length 43/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 747 0 R>>/ProcSet[/PDF/ImageB]/XObject<</Im0 833 0 R>>>>/Subtype/Form>>stream
2432q
2433/GS0 gs
2434513 0 0 502 283 520 cm
2435/Im0 Do
2436Q
2437 endstream endobj 930 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 923 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 924 0 obj <</AIS true/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 931 0 R/Type/ExtGState/ca 1.0/op false>> endobj 931 0 obj <</BC 932 0 R/G 933 0 R/S/Luminosity/Type/Mask>> endobj 932 0 obj [0.0 0.0 0.0] endobj 933 0 obj <</BBox[246.0 1106.0 718.0 580.0]/Group 934 0 R/Length 43/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 747 0 R>>/ProcSet[/PDF/ImageB]/XObject<</Im0 839 0 R>>>>/Subtype/Form>>stream
2438q
2439/GS0 gs
2440472 0 0 526 246 580 cm
2441/Im0 Do
2442Q
2443 endstream endobj 934 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 921 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 922 0 obj <</AIS true/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 935 0 R/Type/ExtGState/ca 1.0/op false>> endobj 935 0 obj <</BC 936 0 R/G 937 0 R/S/Luminosity/Type/Mask>> endobj 936 0 obj [0.0 0.0 0.0] endobj 937 0 obj <</BBox[408.0 947.0 704.0 856.0]/Group 938 0 R/Length 42/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 747 0 R>>/ProcSet[/PDF/ImageB]/XObject<</Im0 845 0 R>>>>/Subtype/Form>>stream
2444q
2445/GS0 gs
2446296 0 0 91 408 856 cm
2447/Im0 Do
2448Q
2449 endstream endobj 938 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 919 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 920 0 obj <</AIS true/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 939 0 R/Type/ExtGState/ca 1.0/op false>> endobj 939 0 obj <</BC 940 0 R/G 941 0 R/S/Luminosity/Type/Mask>> endobj 940 0 obj [0.0 0.0 0.0] endobj 941 0 obj <</BBox[382.616 888.64 656.616 585.64]/Group 942 0 R/Length 59/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 747 0 R>>/ProcSet[/PDF/ImageB]/XObject<</Im0 851 0 R>>>>/Subtype/Form>>stream
2450q
2451/GS0 gs
2452274 0 0 303 382.6162109 585.6401367 cm
2453/Im0 Do
2454Q
2455 endstream endobj 942 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 917 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 918 0 obj <</AIS true/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 943 0 R/Type/ExtGState/ca 1.0/op false>> endobj 943 0 obj <</BC 944 0 R/G 945 0 R/S/Luminosity/Type/Mask>> endobj 944 0 obj [0.0 0.0 0.0] endobj 945 0 obj <</BBox[385.616 858.64 653.616 814.64]/Group 946 0 R/Length 58/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 747 0 R>>/ProcSet[/PDF/ImageB]/XObject<</Im0 857 0 R>>>>/Subtype/Form>>stream
2456q
2457/GS0 gs
2458268 0 0 44 385.6162109 814.6401367 cm
2459/Im0 Do
2460Q
2461 endstream endobj 946 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 915 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 916 0 obj <</AIS true/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 947 0 R/Type/ExtGState/ca 1.0/op false>> endobj 947 0 obj <</BC 948 0 R/G 949 0 R/S/Luminosity/Type/Mask>> endobj 948 0 obj [0.0 0.0 0.0] endobj 949 0 obj <</BBox[317.616 983.64 715.616 585.64]/Group 950 0 R/Length 59/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 747 0 R>>/ProcSet[/PDF/ImageB]/XObject<</Im0 863 0 R>>>>/Subtype/Form>>stream
2462q
2463/GS0 gs
2464398 0 0 398 317.6162109 585.6401367 cm
2465/Im0 Do
2466Q
2467 endstream endobj 950 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 913 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 914 0 obj <</AIS true/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 951 0 R/Type/ExtGState/ca 1.0/op false>> endobj 951 0 obj <</BC 952 0 R/G 953 0 R/S/Luminosity/Type/Mask>> endobj 952 0 obj [0.0 0.0 0.0] endobj 953 0 obj <</BBox[273.616 1026.64 759.616 546.64]/Group 954 0 R/Length 59/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 747 0 R>>/ProcSet[/PDF/ImageB]/XObject<</Im0 869 0 R>>>>/Subtype/Form>>stream
2468q
2469/GS0 gs
2470486 0 0 480 273.6162109 546.6401367 cm
2471/Im0 Do
2472Q
2473 endstream endobj 954 0 obj <</CS 735 0 R/I false/K false/S/Transparency/Type/Group>> endobj 746 0 obj <</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 955 0 R/Type/ExtGState/ca 1.0/op false>> endobj 748 0 obj <</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 956 0 R/Type/ExtGState/ca 1.0/op false>> endobj 749 0 obj <</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 957 0 R/Type/ExtGState/ca 1.0/op false>> endobj 750 0 obj <</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 958 0 R/Type/ExtGState/ca 1.0/op false>> endobj 751 0 obj <</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 959 0 R/Type/ExtGState/ca 1.0/op false>> endobj 959 0 obj <</G 960 0 R/S/Luminosity/Type/Mask>> endobj 960 0 obj <</BBox[-32768.0 32767.0 32767.0 -32768.0]/Group 961 0 R/Length 84/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 744 0 R>>/Shading<</Sh0 892 0 R>>>>/Subtype/Form>>stream
2474q
24750 g
2476/GS0 gs
247715.8993082 0 0 -16.1025677 1392.8847656 296.171875 cm
2478BX /Sh0 sh EX Q
2479 endstream endobj 961 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 958 0 obj <</G 962 0 R/S/Luminosity/Type/Mask>> endobj 962 0 obj <</BBox[-32768.0 32767.0 32767.0 -32768.0]/Group 963 0 R/Length 85/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 744 0 R>>/Shading<</Sh0 892 0 R>>>>/Subtype/Form>>stream
2480q
24810 g
2482/GS0 gs
248311.9217148 0 0 -12.0797682 1392.7294922 335.4882812 cm
2484BX /Sh0 sh EX Q
2485 endstream endobj 963 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 957 0 obj <</G 964 0 R/S/Luminosity/Type/Mask>> endobj 964 0 obj <</BBox[-32768.0 32767.0 32767.0 -32768.0]/Group 965 0 R/Length 87/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 744 0 R>>/Shading<</Sh0 892 0 R>>>>/Subtype/Form>>stream
2486q
24870 g
2488/GS0 gs
2489225.9361572 0 0 -225.9361572 1389.9453125 728.7958984 cm
2490BX /Sh0 sh EX Q
2491 endstream endobj 965 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 956 0 obj <</G 966 0 R/S/Luminosity/Type/Mask>> endobj 966 0 obj <</BBox[-32768.0 32767.0 32767.0 -32768.0]/Group 967 0 R/Length 83/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 744 0 R>>/Shading<</Sh0 892 0 R>>>>/Subtype/Form>>stream
2492q
24930 g
2494/GS0 gs
24957.9551892 0 0 -8.0455885 1392.7294922 366.4384766 cm
2496BX /Sh0 sh EX Q
2497 endstream endobj 967 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 955 0 obj <</G 968 0 R/S/Luminosity/Type/Mask>> endobj 968 0 obj <</BBox[-32768.0 32767.0 32767.0 -32768.0]/Group 969 0 R/Length 84/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 744 0 R>>/Shading<</Sh0 892 0 R>>>>/Subtype/Form>>stream
2498q
24990 g
2500/GS0 gs
2501225.9359131 0 0 -225.9359131 509.96875 794.0385742 cm
2502BX /Sh0 sh EX Q
2503 endstream endobj 969 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 912 0 obj [/ICCBased 819 0 R] endobj 5 0 obj <</Intent 154 0 R/Name(Calque 1)/Type/OCG/Usage 155 0 R>> endobj 248 0 obj <</Intent 395 0 R/Name(Calque 1)/Type/OCG/Usage 396 0 R>> endobj 489 0 obj <</Intent 636 0 R/Name(Calque 1)/Type/OCG/Usage 637 0 R>> endobj 636 0 obj [/View/Design] endobj 637 0 obj <</CreatorInfo<</Creator(Adobe Illustrator 16.0)/Subtype/Artwork>>>> endobj 395 0 obj [/View/Design] endobj 396 0 obj <</CreatorInfo<</Creator(Adobe Illustrator 16.0)/Subtype/Artwork>>>> endobj 154 0 obj [/View/Design] endobj 155 0 obj <</CreatorInfo<</Creator(Adobe Illustrator 16.0)/Subtype/Artwork>>>> endobj 731 0 obj [730 0 R] endobj 970 0 obj <</CreationDate(D:20140916123631+02'00')/Creator(Adobe Illustrator CS6 \(Macintosh\))/ModDate(D:20140918115258+02'00')/Producer(Adobe PDF library 10.01)/Title(logotalerv2)>> endobj xref 0 971 0000000004 65535 f
25040000000016 00000 n
25050000000194 00000 n
25060000050669 00000 n
25070000000006 00000 f
25080000539738 00000 n
25090000000009 00000 f
25100000050726 00000 n
25110000051599 00000 n
25120000000010 00000 f
25130000000011 00000 f
25140000000012 00000 f
25150000000013 00000 f
25160000000014 00000 f
25170000000015 00000 f
25180000000016 00000 f
25190000000017 00000 f
25200000000018 00000 f
25210000000019 00000 f
25220000000020 00000 f
25230000000021 00000 f
25240000000022 00000 f
25250000000023 00000 f
25260000000024 00000 f
25270000000025 00000 f
25280000000026 00000 f
25290000000027 00000 f
25300000000028 00000 f
25310000000029 00000 f
25320000000030 00000 f
25330000000031 00000 f
25340000000032 00000 f
25350000000033 00000 f
25360000000034 00000 f
25370000000035 00000 f
25380000000036 00000 f
25390000000037 00000 f
25400000000038 00000 f
25410000000039 00000 f
25420000000040 00000 f
25430000000041 00000 f
25440000000042 00000 f
25450000000043 00000 f
25460000000044 00000 f
25470000000045 00000 f
25480000000046 00000 f
25490000000047 00000 f
25500000000048 00000 f
25510000000049 00000 f
25520000000050 00000 f
25530000000051 00000 f
25540000000052 00000 f
25550000000053 00000 f
25560000000054 00000 f
25570000000055 00000 f
25580000000056 00000 f
25590000000057 00000 f
25600000000058 00000 f
25610000000059 00000 f
25620000000060 00000 f
25630000000061 00000 f
25640000000062 00000 f
25650000000063 00000 f
25660000000064 00000 f
25670000000065 00000 f
25680000000066 00000 f
25690000000067 00000 f
25700000000068 00000 f
25710000000069 00000 f
25720000000070 00000 f
25730000000071 00000 f
25740000000072 00000 f
25750000000073 00000 f
25760000000074 00000 f
25770000000075 00000 f
25780000000076 00000 f
25790000000077 00000 f
25800000000078 00000 f
25810000000079 00000 f
25820000000080 00000 f
25830000000081 00000 f
25840000000082 00000 f
25850000000083 00000 f
25860000000084 00000 f
25870000000085 00000 f
25880000000086 00000 f
25890000000087 00000 f
25900000000088 00000 f
25910000000089 00000 f
25920000000090 00000 f
25930000000091 00000 f
25940000000092 00000 f
25950000000093 00000 f
25960000000094 00000 f
25970000000095 00000 f
25980000000096 00000 f
25990000000097 00000 f
26000000000098 00000 f
26010000000099 00000 f
26020000000100 00000 f
26030000000101 00000 f
26040000000102 00000 f
26050000000103 00000 f
26060000000104 00000 f
26070000000105 00000 f
26080000000106 00000 f
26090000000107 00000 f
26100000000108 00000 f
26110000000109 00000 f
26120000000110 00000 f
26130000000111 00000 f
26140000000112 00000 f
26150000000113 00000 f
26160000000114 00000 f
26170000000115 00000 f
26180000000116 00000 f
26190000000117 00000 f
26200000000118 00000 f
26210000000119 00000 f
26220000000120 00000 f
26230000000121 00000 f
26240000000122 00000 f
26250000000123 00000 f
26260000000124 00000 f
26270000000125 00000 f
26280000000126 00000 f
26290000000127 00000 f
26300000000128 00000 f
26310000000129 00000 f
26320000000130 00000 f
26330000000131 00000 f
26340000000132 00000 f
26350000000133 00000 f
26360000000134 00000 f
26370000000135 00000 f
26380000000136 00000 f
26390000000137 00000 f
26400000000138 00000 f
26410000000139 00000 f
26420000000140 00000 f
26430000000141 00000 f
26440000000142 00000 f
26450000000143 00000 f
26460000000144 00000 f
26470000000145 00000 f
26480000000146 00000 f
26490000000147 00000 f
26500000000148 00000 f
26510000000149 00000 f
26520000000150 00000 f
26530000000151 00000 f
26540000000152 00000 f
26550000000153 00000 f
26560000000156 00000 f
26570000540197 00000 n
26580000540229 00000 n
26590000000157 00000 f
26600000000158 00000 f
26610000000159 00000 f
26620000000160 00000 f
26630000000161 00000 f
26640000000162 00000 f
26650000000163 00000 f
26660000000164 00000 f
26670000000165 00000 f
26680000000166 00000 f
26690000000167 00000 f
26700000000168 00000 f
26710000000169 00000 f
26720000000170 00000 f
26730000000171 00000 f
26740000000172 00000 f
26750000000173 00000 f
26760000000174 00000 f
26770000000175 00000 f
26780000000176 00000 f
26790000000177 00000 f
26800000000178 00000 f
26810000000179 00000 f
26820000000180 00000 f
26830000000181 00000 f
26840000000182 00000 f
26850000000183 00000 f
26860000000184 00000 f
26870000000185 00000 f
26880000000186 00000 f
26890000000187 00000 f
26900000000188 00000 f
26910000000189 00000 f
26920000000190 00000 f
26930000000191 00000 f
26940000000192 00000 f
26950000000193 00000 f
26960000000194 00000 f
26970000000195 00000 f
26980000000196 00000 f
26990000000197 00000 f
27000000000198 00000 f
27010000000199 00000 f
27020000000200 00000 f
27030000000201 00000 f
27040000000202 00000 f
27050000000203 00000 f
27060000000204 00000 f
27070000000205 00000 f
27080000000206 00000 f
27090000000207 00000 f
27100000000208 00000 f
27110000000209 00000 f
27120000000210 00000 f
27130000000211 00000 f
27140000000212 00000 f
27150000000213 00000 f
27160000000214 00000 f
27170000000215 00000 f
27180000000216 00000 f
27190000000217 00000 f
27200000000218 00000 f
27210000000219 00000 f
27220000000220 00000 f
27230000000221 00000 f
27240000000222 00000 f
27250000000223 00000 f
27260000000224 00000 f
27270000000225 00000 f
27280000000226 00000 f
27290000000227 00000 f
27300000000228 00000 f
27310000000229 00000 f
27320000000230 00000 f
27330000000231 00000 f
27340000000232 00000 f
27350000000233 00000 f
27360000000234 00000 f
27370000000235 00000 f
27380000000236 00000 f
27390000000237 00000 f
27400000000238 00000 f
27410000000239 00000 f
27420000000240 00000 f
27430000000241 00000 f
27440000000242 00000 f
27450000000243 00000 f
27460000000244 00000 f
27470000000245 00000 f
27480000000246 00000 f
27490000000247 00000 f
27500000000249 00000 f
27510000539811 00000 n
27520000000250 00000 f
27530000000251 00000 f
27540000000252 00000 f
27550000000253 00000 f
27560000000254 00000 f
27570000000255 00000 f
27580000000256 00000 f
27590000000257 00000 f
27600000000258 00000 f
27610000000259 00000 f
27620000000260 00000 f
27630000000261 00000 f
27640000000262 00000 f
27650000000263 00000 f
27660000000264 00000 f
27670000000265 00000 f
27680000000266 00000 f
27690000000267 00000 f
27700000000268 00000 f
27710000000269 00000 f
27720000000270 00000 f
27730000000271 00000 f
27740000000272 00000 f
27750000000273 00000 f
27760000000274 00000 f
27770000000275 00000 f
27780000000276 00000 f
27790000000277 00000 f
27800000000278 00000 f
27810000000279 00000 f
27820000000280 00000 f
27830000000281 00000 f
27840000000282 00000 f
27850000000283 00000 f
27860000000284 00000 f
27870000000285 00000 f
27880000000286 00000 f
27890000000287 00000 f
27900000000288 00000 f
27910000000289 00000 f
27920000000290 00000 f
27930000000291 00000 f
27940000000292 00000 f
27950000000293 00000 f
27960000000294 00000 f
27970000000295 00000 f
27980000000296 00000 f
27990000000297 00000 f
28000000000298 00000 f
28010000000299 00000 f
28020000000300 00000 f
28030000000301 00000 f
28040000000302 00000 f
28050000000303 00000 f
28060000000304 00000 f
28070000000305 00000 f
28080000000306 00000 f
28090000000307 00000 f
28100000000308 00000 f
28110000000309 00000 f
28120000000310 00000 f
28130000000311 00000 f
28140000000312 00000 f
28150000000313 00000 f
28160000000314 00000 f
28170000000315 00000 f
28180000000316 00000 f
28190000000317 00000 f
28200000000318 00000 f
28210000000319 00000 f
28220000000320 00000 f
28230000000321 00000 f
28240000000322 00000 f
28250000000323 00000 f
28260000000324 00000 f
28270000000325 00000 f
28280000000326 00000 f
28290000000327 00000 f
28300000000328 00000 f
28310000000329 00000 f
28320000000330 00000 f
28330000000331 00000 f
28340000000332 00000 f
28350000000333 00000 f
28360000000334 00000 f
28370000000335 00000 f
28380000000336 00000 f
28390000000337 00000 f
28400000000338 00000 f
28410000000339 00000 f
28420000000340 00000 f
28430000000341 00000 f
28440000000342 00000 f
28450000000343 00000 f
28460000000344 00000 f
28470000000345 00000 f
28480000000346 00000 f
28490000000347 00000 f
28500000000348 00000 f
28510000000349 00000 f
28520000000350 00000 f
28530000000351 00000 f
28540000000352 00000 f
28550000000353 00000 f
28560000000354 00000 f
28570000000355 00000 f
28580000000356 00000 f
28590000000357 00000 f
28600000000358 00000 f
28610000000359 00000 f
28620000000360 00000 f
28630000000361 00000 f
28640000000362 00000 f
28650000000363 00000 f
28660000000364 00000 f
28670000000365 00000 f
28680000000366 00000 f
28690000000367 00000 f
28700000000368 00000 f
28710000000369 00000 f
28720000000370 00000 f
28730000000371 00000 f
28740000000372 00000 f
28750000000373 00000 f
28760000000374 00000 f
28770000000375 00000 f
28780000000376 00000 f
28790000000377 00000 f
28800000000378 00000 f
28810000000379 00000 f
28820000000380 00000 f
28830000000381 00000 f
28840000000382 00000 f
28850000000383 00000 f
28860000000384 00000 f
28870000000385 00000 f
28880000000386 00000 f
28890000000387 00000 f
28900000000388 00000 f
28910000000389 00000 f
28920000000390 00000 f
28930000000391 00000 f
28940000000392 00000 f
28950000000393 00000 f
28960000000394 00000 f
28970000000397 00000 f
28980000540079 00000 n
28990000540111 00000 n
29000000000398 00000 f
29010000000399 00000 f
29020000000400 00000 f
29030000000401 00000 f
29040000000402 00000 f
29050000000403 00000 f
29060000000404 00000 f
29070000000405 00000 f
29080000000406 00000 f
29090000000407 00000 f
29100000000408 00000 f
29110000000409 00000 f
29120000000410 00000 f
29130000000411 00000 f
29140000000412 00000 f
29150000000413 00000 f
29160000000414 00000 f
29170000000415 00000 f
29180000000416 00000 f
29190000000417 00000 f
29200000000418 00000 f
29210000000419 00000 f
29220000000420 00000 f
29230000000421 00000 f
29240000000422 00000 f
29250000000423 00000 f
29260000000424 00000 f
29270000000425 00000 f
29280000000426 00000 f
29290000000427 00000 f
29300000000428 00000 f
29310000000429 00000 f
29320000000430 00000 f
29330000000431 00000 f
29340000000432 00000 f
29350000000433 00000 f
29360000000434 00000 f
29370000000435 00000 f
29380000000436 00000 f
29390000000437 00000 f
29400000000438 00000 f
29410000000439 00000 f
29420000000440 00000 f
29430000000441 00000 f
29440000000442 00000 f
29450000000443 00000 f
29460000000444 00000 f
29470000000445 00000 f
29480000000446 00000 f
29490000000447 00000 f
29500000000448 00000 f
29510000000449 00000 f
29520000000450 00000 f
29530000000451 00000 f
29540000000452 00000 f
29550000000453 00000 f
29560000000454 00000 f
29570000000455 00000 f
29580000000456 00000 f
29590000000457 00000 f
29600000000458 00000 f
29610000000459 00000 f
29620000000460 00000 f
29630000000461 00000 f
29640000000462 00000 f
29650000000463 00000 f
29660000000464 00000 f
29670000000465 00000 f
29680000000466 00000 f
29690000000467 00000 f
29700000000468 00000 f
29710000000469 00000 f
29720000000470 00000 f
29730000000471 00000 f
29740000000472 00000 f
29750000000473 00000 f
29760000000474 00000 f
29770000000475 00000 f
29780000000476 00000 f
29790000000477 00000 f
29800000000478 00000 f
29810000000479 00000 f
29820000000480 00000 f
29830000000481 00000 f
29840000000482 00000 f
29850000000483 00000 f
29860000000484 00000 f
29870000000485 00000 f
29880000000486 00000 f
29890000000487 00000 f
29900000000488 00000 f
29910000000000 00000 f
29920000539886 00000 n
29930000000000 00000 f
29940000000000 00000 f
29950000000000 00000 f
29960000000000 00000 f
29970000000000 00000 f
29980000000000 00000 f
29990000000000 00000 f
30000000000000 00000 f
30010000000000 00000 f
30020000000000 00000 f
30030000000000 00000 f
30040000000000 00000 f
30050000000000 00000 f
30060000000000 00000 f
30070000000000 00000 f
30080000000000 00000 f
30090000000000 00000 f
30100000000000 00000 f
30110000000000 00000 f
30120000000000 00000 f
30130000000000 00000 f
30140000000000 00000 f
30150000000000 00000 f
30160000000000 00000 f
30170000000000 00000 f
30180000000000 00000 f
30190000000000 00000 f
30200000000000 00000 f
30210000000000 00000 f
30220000000000 00000 f
30230000000000 00000 f
30240000000000 00000 f
30250000000000 00000 f
30260000000000 00000 f
30270000000000 00000 f
30280000000000 00000 f
30290000000000 00000 f
30300000000000 00000 f
30310000000000 00000 f
30320000000000 00000 f
30330000000000 00000 f
30340000000000 00000 f
30350000000000 00000 f
30360000000000 00000 f
30370000000000 00000 f
30380000000000 00000 f
30390000000000 00000 f
30400000000000 00000 f
30410000000000 00000 f
30420000000000 00000 f
30430000000000 00000 f
30440000000000 00000 f
30450000000000 00000 f
30460000000000 00000 f
30470000000000 00000 f
30480000000000 00000 f
30490000000000 00000 f
30500000000000 00000 f
30510000000000 00000 f
30520000000000 00000 f
30530000000000 00000 f
30540000000000 00000 f
30550000000000 00000 f
30560000000000 00000 f
30570000000000 00000 f
30580000000000 00000 f
30590000000000 00000 f
30600000000000 00000 f
30610000000000 00000 f
30620000000000 00000 f
30630000000000 00000 f
30640000000000 00000 f
30650000000000 00000 f
30660000000000 00000 f
30670000000000 00000 f
30680000000000 00000 f
30690000000000 00000 f
30700000000000 00000 f
30710000000000 00000 f
30720000000000 00000 f
30730000000000 00000 f
30740000000000 00000 f
30750000000000 00000 f
30760000000000 00000 f
30770000000000 00000 f
30780000000000 00000 f
30790000000000 00000 f
30800000000000 00000 f
30810000000000 00000 f
30820000000000 00000 f
30830000000000 00000 f
30840000000000 00000 f
30850000000000 00000 f
30860000000000 00000 f
30870000000000 00000 f
30880000000000 00000 f
30890000000000 00000 f
30900000000000 00000 f
30910000000000 00000 f
30920000000000 00000 f
30930000000000 00000 f
30940000000000 00000 f
30950000000000 00000 f
30960000000000 00000 f
30970000000000 00000 f
30980000000000 00000 f
30990000000000 00000 f
31000000000000 00000 f
31010000000000 00000 f
31020000000000 00000 f
31030000000000 00000 f
31040000000000 00000 f
31050000000000 00000 f
31060000000000 00000 f
31070000000000 00000 f
31080000000000 00000 f
31090000000000 00000 f
31100000000000 00000 f
31110000000000 00000 f
31120000000000 00000 f
31130000000000 00000 f
31140000000000 00000 f
31150000000000 00000 f
31160000000000 00000 f
31170000000000 00000 f
31180000000000 00000 f
31190000000000 00000 f
31200000000000 00000 f
31210000000000 00000 f
31220000000000 00000 f
31230000000000 00000 f
31240000000000 00000 f
31250000000000 00000 f
31260000000000 00000 f
31270000000000 00000 f
31280000000000 00000 f
31290000000000 00000 f
31300000000000 00000 f
31310000000000 00000 f
31320000000000 00000 f
31330000000000 00000 f
31340000000000 00000 f
31350000000000 00000 f
31360000000000 00000 f
31370000000000 00000 f
31380000000000 00000 f
31390000539961 00000 n
31400000539993 00000 n
31410000000000 00000 f
31420000000000 00000 f
31430000000000 00000 f
31440000000000 00000 f
31450000000000 00000 f
31460000000000 00000 f
31470000000000 00000 f
31480000000000 00000 f
31490000000000 00000 f
31500000000000 00000 f
31510000000000 00000 f
31520000000000 00000 f
31530000000000 00000 f
31540000000000 00000 f
31550000000000 00000 f
31560000000000 00000 f
31570000000000 00000 f
31580000000000 00000 f
31590000000000 00000 f
31600000000000 00000 f
31610000000000 00000 f
31620000000000 00000 f
31630000000000 00000 f
31640000000000 00000 f
31650000000000 00000 f
31660000000000 00000 f
31670000000000 00000 f
31680000000000 00000 f
31690000000000 00000 f
31700000000000 00000 f
31710000000000 00000 f
31720000000000 00000 f
31730000000000 00000 f
31740000000000 00000 f
31750000000000 00000 f
31760000000000 00000 f
31770000000000 00000 f
31780000000000 00000 f
31790000000000 00000 f
31800000000000 00000 f
31810000000000 00000 f
31820000000000 00000 f
31830000000000 00000 f
31840000000000 00000 f
31850000000000 00000 f
31860000000000 00000 f
31870000000000 00000 f
31880000000000 00000 f
31890000000000 00000 f
31900000000000 00000 f
31910000000000 00000 f
31920000000000 00000 f
31930000000000 00000 f
31940000000000 00000 f
31950000000000 00000 f
31960000000000 00000 f
31970000000000 00000 f
31980000000000 00000 f
31990000000000 00000 f
32000000000000 00000 f
32010000000000 00000 f
32020000000000 00000 f
32030000000000 00000 f
32040000000000 00000 f
32050000000000 00000 f
32060000000000 00000 f
32070000000000 00000 f
32080000000000 00000 f
32090000000000 00000 f
32100000000000 00000 f
32110000000000 00000 f
32120000000000 00000 f
32130000000000 00000 f
32140000000000 00000 f
32150000000000 00000 f
32160000000000 00000 f
32170000000000 00000 f
32180000000000 00000 f
32190000000000 00000 f
32200000000000 00000 f
32210000000000 00000 f
32220000000000 00000 f
32230000000000 00000 f
32240000000000 00000 f
32250000000000 00000 f
32260000000000 00000 f
32270000000000 00000 f
32280000000000 00000 f
32290000000000 00000 f
32300000000000 00000 f
32310000000000 00000 f
32320000000000 00000 f
32330000255776 00000 n
32340000540315 00000 n
32350000526925 00000 n
32360000530281 00000 n
32370000272389 00000 n
32380000072965 00000 n
32390000080180 00000 n
32400000077135 00000 n
32410000078917 00000 n
32420000078454 00000 n
32430000076711 00000 n
32440000076244 00000 n
32450000075807 00000 n
32460000072621 00000 n
32470000268801 00000 n
32480000268915 00000 n
32490000536963 00000 n
32500000100986 00000 n
32510000537080 00000 n
32520000537197 00000 n
32530000537314 00000 n
32540000537431 00000 n
32550000255969 00000 n
32560000257133 00000 n
32570000257476 00000 n
32580000254768 00000 n
32590000530345 00000 n
32600000530669 00000 n
32610000530992 00000 n
32620000531314 00000 n
32630000531637 00000 n
32640000531937 00000 n
32650000532239 00000 n
32660000058286 00000 n
32670000058829 00000 n
32680000064795 00000 n
32690000065059 00000 n
32700000065376 00000 n
32710000071367 00000 n
32720000071636 00000 n
32730000071964 00000 n
32740000072239 00000 n
32750000052478 00000 n
32760000055983 00000 n
32770000269032 00000 n
32780000269149 00000 n
32790000269266 00000 n
32800000269383 00000 n
32810000269500 00000 n
32820000056047 00000 n
32830000056374 00000 n
32840000056701 00000 n
32850000057027 00000 n
32860000057354 00000 n
32870000057664 00000 n
32880000057975 00000 n
32890000526888 00000 n
32900000199803 00000 n
32910000081996 00000 n
32920000228123 00000 n
32930000199867 00000 n
32940000155074 00000 n
32950000178049 00000 n
32960000155138 00000 n
32970000151139 00000 n
32980000153025 00000 n
32990000151203 00000 n
33000000140569 00000 n
33010000146002 00000 n
33020000140633 00000 n
33030000126432 00000 n
33040000133614 00000 n
33050000126496 00000 n
33060000101099 00000 n
33070000114198 00000 n
33080000101163 00000 n
33090000080732 00000 n
33100000091259 00000 n
33110000080796 00000 n
33120000080227 00000 n
33130000079327 00000 n
33140000078963 00000 n
33150000078501 00000 n
33160000077183 00000 n
33170000076758 00000 n
33180000076291 00000 n
33190000075854 00000 n
33200000072668 00000 n
33210000073002 00000 n
33220000073158 00000 n
33230000076140 00000 n
33240000076586 00000 n
33250000077043 00000 n
33260000078037 00000 n
33270000078795 00000 n
33280000079247 00000 n
33290000080558 00000 n
33300000082042 00000 n
33310000091204 00000 n
33320000091375 00000 n
33330000091441 00000 n
33340000091472 00000 n
33350000091749 00000 n
33360000091824 00000 n
33370000102529 00000 n
33380000114314 00000 n
33390000114380 00000 n
33400000114411 00000 n
33410000114688 00000 n
33420000114763 00000 n
33430000127223 00000 n
33440000133730 00000 n
33450000133796 00000 n
33460000133827 00000 n
33470000134103 00000 n
33480000134178 00000 n
33490000141446 00000 n
33500000146118 00000 n
33510000146184 00000 n
33520000146215 00000 n
33530000146508 00000 n
33540000146583 00000 n
33550000151556 00000 n
33560000153141 00000 n
33570000153207 00000 n
33580000153238 00000 n
33590000153530 00000 n
33600000153605 00000 n
33610000156876 00000 n
33620000178165 00000 n
33630000178231 00000 n
33640000178262 00000 n
33650000178555 00000 n
33660000178630 00000 n
33670000202059 00000 n
33680000228239 00000 n
33690000228305 00000 n
33700000228336 00000 n
33710000228629 00000 n
33720000228704 00000 n
33730000254922 00000 n
33740000255143 00000 n
33750000255262 00000 n
33760000255367 00000 n
33770000255458 00000 n
33780000255549 00000 n
33790000255655 00000 n
33800000255851 00000 n
33810000255883 00000 n
33820000268483 00000 n
33830000268571 00000 n
33840000265290 00000 n
33850000257856 00000 n
33860000258107 00000 n
33870000265561 00000 n
33880000271957 00000 n
33890000271527 00000 n
33900000271093 00000 n
33910000270661 00000 n
33920000269617 00000 n
33930000269672 00000 n
33940000269970 00000 n
33950000270048 00000 n
33960000270205 00000 n
33970000270426 00000 n
33980000270501 00000 n
33990000270581 00000 n
34000000270716 00000 n
34010000271015 00000 n
34020000271148 00000 n
34030000271449 00000 n
34040000271582 00000 n
34050000271879 00000 n
34060000272012 00000 n
34070000272311 00000 n
34080000272465 00000 n
34090000272712 00000 n
34100000273723 00000 n
34110000284180 00000 n
34120000349769 00000 n
34130000415358 00000 n
34140000480947 00000 n
34150000539701 00000 n
34160000536321 00000 n
34170000536385 00000 n
34180000535680 00000 n
34190000535744 00000 n
34200000535040 00000 n
34210000535104 00000 n
34220000534399 00000 n
34230000534463 00000 n
34240000533781 00000 n
34250000533845 00000 n
34260000533161 00000 n
34270000533225 00000 n
34280000532541 00000 n
34290000532605 00000 n
34300000532721 00000 n
34310000532787 00000 n
34320000532818 00000 n
34330000533086 00000 n
34340000533341 00000 n
34350000533407 00000 n
34360000533438 00000 n
34370000533706 00000 n
34380000533961 00000 n
34390000534027 00000 n
34400000534058 00000 n
34410000534324 00000 n
34420000534579 00000 n
34430000534645 00000 n
34440000534676 00000 n
34450000534965 00000 n
34460000535220 00000 n
34470000535286 00000 n
34480000535317 00000 n
34490000535605 00000 n
34500000535860 00000 n
34510000535926 00000 n
34520000535957 00000 n
34530000536246 00000 n
34540000536501 00000 n
34550000536567 00000 n
34560000536598 00000 n
34570000536888 00000 n
34580000539271 00000 n
34590000538842 00000 n
34600000538409 00000 n
34610000537978 00000 n
34620000537548 00000 n
34630000537603 00000 n
34640000537900 00000 n
34650000538033 00000 n
34660000538331 00000 n
34670000538464 00000 n
34680000538764 00000 n
34690000538897 00000 n
34700000539193 00000 n
34710000539326 00000 n
34720000539623 00000 n
34730000540342 00000 n
3474trailer <</Size 971/Root 1 0 R/Info 970 0 R/ID[<07511D2C75694DC89622C9F4B35B7624><8DE5252BE861447E9DAABAECF80D68A1>]>> startxref 540533 %%EOF \ No newline at end of file
diff --git a/doc/logos/eps/icon_taler.eps b/doc/logos/eps/icon_taler.eps
new file mode 100644
index 000000000..79ab648a6
--- /dev/null
+++ b/doc/logos/eps/icon_taler.eps
Binary files differ
diff --git a/doc/logos/eps/logo_taler.eps b/doc/logos/eps/logo_taler.eps
new file mode 100644
index 000000000..343128499
--- /dev/null
+++ b/doc/logos/eps/logo_taler.eps
Binary files differ
diff --git a/doc/logos/fonts/OldNewspaperTypes.ttf b/doc/logos/fonts/OldNewspaperTypes.ttf
new file mode 100755
index 000000000..7b9cf31b9
--- /dev/null
+++ b/doc/logos/fonts/OldNewspaperTypes.ttf
Binary files differ
diff --git a/doc/logos/fonts/perpetue/Perpetua Bold Italic.ttf b/doc/logos/fonts/perpetue/Perpetua Bold Italic.ttf
new file mode 100644
index 000000000..3882fe928
--- /dev/null
+++ b/doc/logos/fonts/perpetue/Perpetua Bold Italic.ttf
Binary files differ
diff --git a/doc/logos/fonts/perpetue/Perpetua Bold.ttf b/doc/logos/fonts/perpetue/Perpetua Bold.ttf
new file mode 100644
index 000000000..c73833dbb
--- /dev/null
+++ b/doc/logos/fonts/perpetue/Perpetua Bold.ttf
Binary files differ
diff --git a/doc/logos/fonts/perpetue/Perpetua Italic.ttf b/doc/logos/fonts/perpetue/Perpetua Italic.ttf
new file mode 100644
index 000000000..e4f295ed1
--- /dev/null
+++ b/doc/logos/fonts/perpetue/Perpetua Italic.ttf
Binary files differ
diff --git a/doc/logos/fonts/perpetue/Perpetua.ttf b/doc/logos/fonts/perpetue/Perpetua.ttf
new file mode 100644
index 000000000..846b3dca6
--- /dev/null
+++ b/doc/logos/fonts/perpetue/Perpetua.ttf
Binary files differ
diff --git a/doc/logos/fonts/smoth_bight/End User Licence Agreement.txt b/doc/logos/fonts/smoth_bight/End User Licence Agreement.txt
new file mode 100755
index 000000000..04209197c
--- /dev/null
+++ b/doc/logos/fonts/smoth_bight/End User Licence Agreement.txt
@@ -0,0 +1,133 @@
1End User License Agreement and Software Inclusion Agreement
2
3
4"Purchaser" and "User" may be used interchangeably in this agreement.
5
6
7The official release page is at kustren.deviantart.com/
8
9or
10
11
12
13 Copyright 2013 Kustren
14 Trademark 2013 Kustren licence
15 Commercial distribution, rendering and printing of the font and derived work is prohibited.
16
17
18
19
20
21Usage
22
23Smoth-Bight is freeware Font is free to use for personal and commercial purposes. No payment is necessary, and there is no limit to the amount of prints, pages, or other medium to be produced using them. However, you cannot offer the font for commercial sale, or offer for direct download. The inclusion othe font name and/or site URL in the credits or documentation when it is used is appreciated, but this is not mandatory.
24My font is for personal and commercial use, can be used for any type of work, while nature, neither will be able to be modified in any kind of way.
25This license is multipurpose, my font can be used on multiple computers at once.
26
27
28
29
30
31Payment
32
33Payment is not required for the use of kustren's freeware Font.
34
35
36
37Support
38
39If you experience problems with any Kustren's Freeware font (such as spacing issues or missing characters), please verify that you have the correct and current version of the fonts. In the case of Freeware font, downloading the font directly from the http://kustren.deviantart.com/ site will ensure that the font files have not been altered.
40
41
42
43
44Copyright (c) 2014 by Kustren. All rights reserved.
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
diff --git a/doc/logos/fonts/smoth_bight/Licencia de la fuente - Version en Espa§ol.txt b/doc/logos/fonts/smoth_bight/Licencia de la fuente - Version en Espa§ol.txt
new file mode 100755
index 000000000..39833a36a
--- /dev/null
+++ b/doc/logos/fonts/smoth_bight/Licencia de la fuente - Version en Espa§ol.txt
@@ -0,0 +1,77 @@
1Contrato de licencia de usuario final e Inclusin del acuerdo de Software
2
3"Comprador " y "Usuario " se pueden utilizar indistintamente en el presente acuerdo .
4
5
6La pgina oficial de lanzamiento de la fuente es:
7http://kustren.deviantart.com/
8
9
10
11 Derechos de autor 2013 Kustren
12 Marcas 2013 licencia Kustren
13 Se prohbe la distribucin comercial, la representacin y la impresin de la fuente y el trabajo derivado .
14
15
16
17
18
19Uso
20
21La fuente de Kustren llamada Smoth-Bight es freware en su mayoria, de uso libre, pero solo para fines personales y/o comerciales, no hay limite en la cantidad de copias realizadas de la mis ma fuente en los pcs que usted utilice.
22Sin embargo no pueden ofrecer esta tipografia ni como suyas y/o comercializarla, tampoco estara permitida la descarga directa en otras paginas web, a menos que sea con consentimiento de su creador Kustren.
23Si usted usa mi fuente deme creditos por ello y/o coloque la pagina web mia, esto es de agradecer.
24
25licencia del derecho de uso
26
27Esta fuente es para uso personal y/o comercial, puede ser usadas para cualquier tipo de trabajo, pero no podra ser modificadas de ningun tipo de manera.
28Recuerden que si ustedes compran alguna tipografia no se convierten en propietariuo de la fuente, solo obtienen la licencia de uso, es decir la misma que estan leyendo.
29Esta licencia es de multiuso, mi fuente pueden ser usadas en multiples computadores a la vez.
30
31
32
33
34
35pago
36
37El pago no es necesaria para el uso de esta fuente de software gratuito creada por kustren.
38
39
40
41apoyo
42
43Si tienen problema con la fuente (como problemas de espaciado o caracteres que faltan ) , por favor, compruebe que tiene la versin correcta y actualizada de la fuente. En el caso de fuentes de dominio pblico , la descarga de la fuente directamente desde el sitio http://kustren.deviantart.com/ se asegurar de que los archivos de fuentes no han sido alterados.
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
diff --git a/doc/logos/fonts/smoth_bight/Smoth-Bight - Por Kustren.otf b/doc/logos/fonts/smoth_bight/Smoth-Bight - Por Kustren.otf
new file mode 100755
index 000000000..33fd97934
--- /dev/null
+++ b/doc/logos/fonts/smoth_bight/Smoth-Bight - Por Kustren.otf
Binary files differ
diff --git a/doc/logos/fonts/smoth_bight/Smoth-Bight Italic - Por Kustren.otf b/doc/logos/fonts/smoth_bight/Smoth-Bight Italic - Por Kustren.otf
new file mode 100755
index 000000000..5fb25e646
--- /dev/null
+++ b/doc/logos/fonts/smoth_bight/Smoth-Bight Italic - Por Kustren.otf
Binary files differ
diff --git a/doc/logos/ico/favicon1616.ico b/doc/logos/ico/favicon1616.ico
new file mode 100644
index 000000000..141b93d3f
--- /dev/null
+++ b/doc/logos/ico/favicon1616.ico
Binary files differ
diff --git a/doc/logos/ico/favicon4848.ico b/doc/logos/ico/favicon4848.ico
new file mode 100644
index 000000000..3c04b1266
--- /dev/null
+++ b/doc/logos/ico/favicon4848.ico
Binary files differ
diff --git a/doc/logos/png/icon_taler.png b/doc/logos/png/icon_taler.png
new file mode 100644
index 000000000..b1dd9a587
--- /dev/null
+++ b/doc/logos/png/icon_taler.png
Binary files differ
diff --git a/doc/logos/png/logo_taler.png b/doc/logos/png/logo_taler.png
new file mode 100644
index 000000000..bdffc3c9c
--- /dev/null
+++ b/doc/logos/png/logo_taler.png
Binary files differ
diff --git a/doc/paper/.latexmkrc b/doc/paper/.latexmkrc
new file mode 100644
index 000000000..16bc358f0
--- /dev/null
+++ b/doc/paper/.latexmkrc
@@ -0,0 +1,15 @@
1add_cus_dep('glo', 'gls', 0, 'run_makeglossaries');
2add_cus_dep('acn', 'acr', 0, 'run_makeglossaries');
3
4sub run_makeglossaries {
5 if ( $silent ) {
6 system "makeglossaries -q '$_[0]'";
7 }
8 else {
9 system "makeglossaries '$_[0]'";
10 };
11}
12
13push @generated_exts, 'glo', 'gls', 'glg';
14push @generated_exts, 'acn', 'acr', 'alg';
15$clean_ext .= ' %R.ist %R.xdy';
diff --git a/doc/paper/taler.bib b/doc/paper/taler.bib
new file mode 100644
index 000000000..ce5b1cb11
--- /dev/null
+++ b/doc/paper/taler.bib
@@ -0,0 +1,94 @@
1@article{nakamoto2008bitcoin,
2 title={Bitcoin: A peer-to-peer electronic cash system},
3 author={Nakamoto, Satoshi},
4 year={2008}
5}
6
7@Article{blum1981,
8 author = {Manuel Blum},
9 title = {Coin Flipping by Telephone},
10 journal = {CRYPTO},
11 year = {1981},
12 pages = {11-15},
13}
14
15@inproceedings{chaum1990untraceable,
16 title={Untraceable electronic cash},
17 author={Chaum, David and Fiat, Amos and Naor, Moni},
18 booktitle={Proceedings on Advances in cryptology},
19 pages={319--327},
20 year={1990},
21 organization={Springer-Verlag New York, Inc.}
22}
23
24@inproceedings{chaum1983blind,
25 title={Blind signatures for untraceable payments},
26 author={Chaum, David},
27 booktitle={Advances in cryptology},
28 pages={199--203},
29 year={1983},
30 organization={Springer}
31}
32
33@inproceedings{rivest2004peppercoin,
34 title={Peppercoin micropayments},
35 author={Rivest, Ronald L},
36 booktitle={Financial Cryptography},
37 pages={2--8},
38 year={2004},
39 organization={Springer}
40}
41
42@inproceedings{miers2013zerocoin,
43 title={Zerocoin: Anonymous distributed e-cash from bitcoin},
44 author={Miers, Ian and Garman, Christina and Green, Matthew and Rubin, Aviel D},
45 booktitle={Security and Privacy (SP), 2013 IEEE Symposium on},
46 pages={397--411},
47 year={2013},
48 organization={IEEE}
49}
50
51@inproceedings{selby2004analyzing,
52 title={Analyzing the Success and Failure of Recent e-Payment Schemes},
53 author={Selby, Jack R},
54 booktitle={Financial Cryptography},
55 pages={1--1},
56 year={2004},
57 organization={Springer}
58}
59
60@misc{brands1993efficient,
61 title={An efficient off-line electronic cash system based on the representation problem},
62 author={Brands, Stefan A},
63 year={1993},
64 publisher={Centrum voor Wiskunde en Informatica}
65}
66
67@article{dent2008extensions,
68 title={Extensions to Chaum's Blind Signature Scheme and OpenCoin Requirements},
69 author={Dent, AW and Paterson, KG and Wild, PR},
70 year={2008}
71}
72
73@article{dent2008preliminary,
74 title={Preliminary Report on Chaum's Online E-Cash Architecture},
75 author={Dent, AW and Paterson, KG and Wild, PR},
76 journal={Royal Holloway, University of London},
77 year={2008}
78}
79
80
81
82@inproceedings{tor-design,
83 title = {Tor: The Second-Generation Onion Router},
84 author = {Roger Dingledine and Nick Mathewson and Paul Syverson},
85 booktitle = {Proceedings of the 13th USENIX Security Symposium},
86 year = {2004},
87 month = {August},
88 www_important = {1},
89 www_tags = {selected},
90 www_html_url = {https://www.torproject.org/svn/trunk/doc/design-paper/tor-design.html},
91 www_pdf_url = {https://www.torproject.org/svn/trunk/doc/design-paper/tor-design.pdf},
92 www_section = {Anonymous communication},
93}
94
diff --git a/doc/paper/taler.tex b/doc/paper/taler.tex
new file mode 100644
index 000000000..7a71d7636
--- /dev/null
+++ b/doc/paper/taler.tex
@@ -0,0 +1,995 @@
1\documentclass{llncs}
2%\usepackage[margin=1in,a4paper]{geometry}
3\usepackage[T1]{fontenc}
4\usepackage{palatino}
5\usepackage{xspace}
6\usepackage{microtype}
7\usepackage{tikz}
8\usepackage{amsmath,amssymb}
9\usepackage{enumitem}
10\usetikzlibrary{shapes,arrows}
11\usetikzlibrary{positioning}
12\usetikzlibrary{calc}
13
14
15
16% Terminology:
17% - SEPA-transfer -- avoid 'SEPA transaction' as we use
18% 'transaction' already when we talk about taxable
19% transfers of Taler coins and database 'transactions'.
20% - wallet = coins at customer
21% - reserve = currency entrusted to mint waiting for withdrawl
22% - deposit = SEPA to mint
23% - withdrawl = mint to customer
24% - spending = customer to merchant
25% - redeeming = merchant to mint (and then mint SEPA to merchant)
26% - refreshing = customer-mint-customer
27% - dirty coin = coin with exposed public key
28% - fresh coin = coin that was refreshed or is new
29% - coin signing key = mint's online key used to (blindly) sign coin
30% - message signing key = mint's online key to sign mint messages
31% - mint master key = mint's key used to sign other mint keys
32% - owner = entity that knows coin private key
33% - transaction = coin ownership transfer that should be taxed
34% - sharing = coin copying that should not be taxed
35
36
37\title{Taler: Taxable Anonymous Libre Electronic Reserves}
38
39\begin{document}
40\mainmatter
41
42%\author{Florian Dold \and Sree Harsha Totakura \and Benedikt M\"uller \and Christian Grothoff}
43%\institute{The GNUnet Project}
44
45
46\maketitle
47
48\begin{abstract}
49This paper introduces Taler, a Chaum-style digital currency using
50blind signatures that enables anonymous payments while ensuring that
51entities that receive payments are auditable and thus taxable. Taler
52differs from Chaum's original proposal in that customers can never defraud anyone,
53merchants can only fail to deliver the merchandise to the customer,
54and mints can be fully audited. Consequently, enforcement of honest
55behavior is better and more timely than with Chaum, and is at least as
56strict as with legacy credit card payment systems that do not provide
57for privacy. Furthermore, Taler allows fractional and incremental
58payments, and even in this case is still able to guarantee
59unlinkability of transactions via a new coin refreshing protocol.
60Finally, Taler also supports microdonations using probabilistic
61transactions. We argue that Taler provides a secure digital currency
62for modern liberal societies as it is a flexible, libre and efficient
63protocol and adequately balances the state's need for monetary control
64with the citizen's needs for private economic activity.
65\end{abstract}
66
67\section{Introduction}
68
69The design of payment systems shapes economies and societies. Strong,
70developed nation states are evolving towards fully transparent payment
71systems, such as the MasterCard and VisaCard credit card schemes and
72computerized bank transactions such as SWIFT. Such systems enable
73mass surveillance and thus extensive government control over the
74economy, from taxation to intrusion into private lives. Bribery and
75corruption are limited to elites that can afford to escape the
76dragnet. The other extreme are economies of developing, weak nation
77states where economic activity is based largely on coins, paper money
78or even barter. Here, the state is often unable to effectively
79monitor or tax economic activity, and this limits the ability of the
80state to shape the society. As bribery is virtually impossible to
81detect, it is widespread and not limited to social elites.
82ZeroCoin~\cite{miers2013zerocoin} is an example for translating such
83an economy into the digital realm.
84
85Taler is supposed to offer a middleground between an authoritarian
86state in total control of the population and weak states with almost
87anarchistic economies. Specifically, we believe that a liberal
88democracy needs a payment system with the following properties:
89
90\begin{description}
91 \item[Customer Anonymity] It must be impossible for mints, merchants
92 and even a global active adversary, to trace the spending behavior
93 of a customer.
94 \item[Unlinkability] Merchants must not be able to tell if two
95 transactions were performed by the same customer. It must be
96 infeasible to link a set of transactions to the same (anonymous)
97 customer. %, even when taking aborted transactions into account.
98 \item[Taxability] In many current legal systems, it is the
99 responsibility of the merchant to deduct (sales) taxes from
100 purchases made by customers, or to pay (income) taxes for payments
101 received for work.
102 %Taxation is neccessary for the state to
103 %provide legitimate social functions, such as education. Thus, a payment
104 %system must facilitate sales, income and transaction taxes.
105 This specifically means that it must be able to audit merchants (or
106 generally anybody receiving money), and thus the receiver of
107 electronic cash must be easily identifiable.
108 %non-anonymous, as this would enable tax fraud.
109 \item[Verifiability] The payment system should try to minimize the
110 trust necessary between the participants. In particular, digital
111 signatures should be used extensively in order to be able to
112 resolve disputes between the involved parties. Nevertheless,
113 customers must never be able to defraud anyone, and merchants must
114 at best be able to defraud their customers by not delivering the
115 on the agreed contract. Neither merchants nor customers must ever
116 be able to commit fraud against the mint. Both customers and
117 merchants must receive cryptographic proofs of bad behavior in
118 case of protocol violations by the mint. Thus, only the mint will
119 have to be tightly audited and regulated. The design must make it
120 easy to audit the finances of the mint.
121 \item[Ease of Deployment] %The system should be easy to deploy for
122 % real-world applications. In order to lower the entry barrier and
123 % acceptance of the system, a gateway to the existing financial
124 % system should be provided, i.e. by integrating internet-banking
125 % protocols such as HBCI/FinTAN.
126 The digital currency should be
127 tied 1:1 to existing currencies (such as EUR or USD) to avoid
128 exposing users to unnecessary risks from currency fluctuations.
129 Moreover, the system must have a free software reference
130 implementation and an open protocol standard.
131% The protocol should
132% be able to run easily over HTTP(S).
133 \item[Low resource consumption] In order to minimize the operating
134 costs and environmental impact of the payment system, it must
135 avoid the reliance on expensive and ``wasteful'' computations
136 such as proof-of-work.
137 \item[Large Payments and Microdonations] The payment system needs to
138 handle large payments in a reliable manner. Furthermore, for
139 microdonations the system should allow sacrificing reliability to
140 achieve economic viability.
141\end{description}
142
143Taler builds on ideas from Chaum~\cite{chaum1983blind}, who proposed a
144digital currency system that would provide (some) customer anonymity
145while disclosing the identity of the merchants. Chaum's digital cash
146system had some limitations and ultimately failed to be widely
147adopted. In our assessment, key reasons include:
148
149\begin{itemize}
150 \item The use of patents to protect the technology; a payment system
151 must be libre --- free software --- to have a chance for widespread
152 adoption.
153 \item The use of off-line payments and thus deferred detection of
154 double-spending, which could require the mint to attempt to recover
155 funds from customers via the legal system. This creates a
156 significant business risk for the mint, as the system is not
157 self-enforcing from the perspective of the mint. In 1983 off-line
158 payments might have been a necessary feature. However, today
159 requiring network connectivity is feasible and avoids the business
160 risks associated with deferred fraud detection.
161 \item % In addition to the risk of legal disputes with fradulent
162 % merchants and customers,
163 Chaum's published design does not clearly
164 limit the financial damage a mint might suffer from the
165 disclosure of its private online signing key.
166% \item Chaum did not support fractional payments, and Brand's
167% extensions for fractional payments broke unlinkability and thus
168% limited anonymity. Chaum also did not support microdonations,
169% leaving an opportunity for expanding payments into additional areas
170% unexplored.
171% \item Chaum's system was implemented at a time where the US market
172% was still dominated by paper checks and the European market was
173% fragmented into dozens of currencies. Today, SEPA provides a
174% unified currency and currency transfer method for most of Europe,
175% significantly lowering the barrier to entry into this domain for
176% a larger market.
177\end{itemize}
178
179This paper describes Taler, a simple and practical payment with the
180above goals in mind. The basic idea is to use Chaum's model of
181customer, merchant and mint (Figure~\ref{fig:cmm}) where the customer
182withdraws digital currency from the mint with unlinkability provided
183via blind signatures. In contrast to Chaum, Taler uses online
184detection of double-spending, thus ensuring the merchant instantly
185that a transaction is valid. Instead of using cryptographic methods
186to enable fractional payments, the customer can simply include
187the fraction of a coin's value that is to be paid to the merchant in
188his message to the merchant.
189
190
191\begin{figure}[h]
192\centering
193\begin{tikzpicture}
194
195
196\tikzstyle{def} = [node distance= 7em and 10em, inner sep=1em, outer sep=.3em];
197\node (origin) at (0,0) {};
198\node (mint) [def,above=of origin,draw]{Mint};
199\node (customer) [def, draw, below left=of origin] {Customer};
200\node (merchant) [def, draw, below right=of origin] {Merchant};
201
202\tikzstyle{C} = [color=black, line width=1pt]
203\draw [<-, C] (customer) -- (mint) node [midway, above, sloped] (TextNode) {withdraw coins};
204\draw [<-, C] (mint) -- (merchant) node [midway, above, sloped] (TextNode) {deposit coins};
205\draw [<-, C] (merchant) -- (customer) node [midway, above, sloped] (TextNode) {spend coins};
206\end{tikzpicture}
207\caption{Taler's system model for the payment system is based on Chaum~\cite{chaum1983blind}.}
208\label{fig:cmm}
209\end{figure}
210
211Online fraud detection can create problems if the network fails during
212the initial steps of a transaction. For example, a law enforcement
213agency might try to entrap a customer by offering illicit goods and
214then aborting the transaction after learning the public key of the
215coin. If the customer were to then later spend that coin on a
216purchase with shipping, the law enforcement agency could link the two
217transactions and might be able to use the shipping to deanonymize the
218customer. Similarly, fractional payments also lead to the
219possibility of customers wanting to legitimately use the same coin
220twice. Taler addresses this problem by allowing customers to {\em
221 refresh} coins. Refreshing means that a customer is able to
222exchange one coin for a fresh coin, with the old and the new coin
223being unlinkable (except for the customer himself). Taler ensures
224that the {\em entity} of the user owning the new coin is the same as the
225entity of the user owning the old coin, thus making sure that the
226refreshing protocol cannot be abused for money laundering or other
227illicit transactions.
228
229
230\section{Related Work}
231
232\subsection{Blockchain-based currencies}
233
234In recent years, a class of decentralized electronic payment systems,
235based on collectively recorded and verified append-only public
236ledgers, have gained immense popularity. The most well-known protocol
237in this class is Bitcoin~\cite{nakamoto2008bitcoin}. An initial
238concern with Bitcoin was the lack of anonymity, as all Bitcoin
239transactions are recorded for eternity, which can enable
240identification of users. In theory, this concern has been addressed
241with the Zerocoin extension to the protocol~\cite{miers2013zerocoin}.
242
243While these protocols dispense with the need for a central, trusted
244authority and provide anonymity, we argue there are some major,
245irredeemable problems inherent in these systems:
246
247\begin{itemize}
248 \item Bitcoins are not (easily) taxable. The legality and legitimacy of
249 this aspect is questionable. The Zerocoin extension would only make
250 this worse.
251 \item Bitcoins can not be bound to any fiat currency, and are subject to
252 significant value fluctuations. While such fluctuations may be
253 acceptable for high-risk investments, they make Bitcoin unsuitable as
254 a medium of exchange.
255 \item The computational puzzles solved by Bitcoin nodes with the purpose
256 of securing the block chain
257 consume a considerable amount of computational resources and thus
258 energy. Thus, Bitcoin does not represent an environmentally responsible
259 design.
260 \item Anyone can easily start an alternative Bitcoin transaction chain
261 (a so-called AltCoin) and, if successful, reap the benefits of the low
262 cost to initially create coins via computation. As a result, dozens of
263 AltCoins have been created, often without any significant changes to the
264 technology. A large number of AltCoins creates additional overheads for
265 currency exchange and exascerbates the problems with currency fluctuations.
266\end{itemize}
267
268\subsection{Chaum-style electronic cash}
269
270Chaum's original digital cash system~\cite{chaum1983blind} was
271extended by Brands~\cite{brands1993efficient} with the ability to
272perform fractional payments; however, the transactions performed with
273the same coin then become linkable.
274%
275%Some argue that the focus on technically perfect but overwhelmingly
276%complex protocols, as well as the the lack of usable, practical
277%solutions lead to an abandonment of these ideas by
278%practitioners~\cite{selby2004analyzing}.
279%
280To our knowledge, the only publicly available effort to implement
281Chaum's idea is
282Opencoin~\cite{dent2008extensions}. However,
283Opencoin seems to be neither actively developed nor used, and it is
284not clear to what degree the implementation is even complete. Only a
285partial description of the Opencoin protocol is available to date.
286
287\subsection{Peppercoin}
288
289Peppercoin~\cite{rivest2004peppercoin} is a microdonation protocol.
290The main idea of the protocol is to reduce transaction costs by
291minimizing the number of transactions that are processed directly by
292the mint. Instead of always paying, the customer ``gambles'' with the
293merchant for each microdonation. Only if the merchant wins, the
294microdonation is upgraded to a macropayment to be deposited at the
295mint. Peppercoin does not provide customer-anonymity. The proposed
296statistical method for mints detecting fraudulent cooperation between
297customers and merchants at the expense of the mint not only creates
298legal risks for the mint (who has to make a statistical argument), but
299also would require the mint to learn about microdonations where the
300merchant did not get upgraded to a macropayment. Thus, it is unclear
301how much Peppercoin would actually do to reduce the computational
302burden on the mint.
303
304
305\section{Design}
306
307The payment system we propose is built on the blind signature
308primitive proposed by Chaum, but extended with additional
309constructions to provide unlinkability, online fraud detection and
310taxability.
311
312As with Chaum, the Taler system comprises three principal types of
313actors: The \emph{customer} is interested in receiving goods or
314services from the \emph{merchant} in exchange for payment. When
315making a transaction, both the customer and the merchant must agree on
316the same \emph{mint}, which serves as an intermediary for the
317financial transaction between the two. The mint is responsible for
318allowing the customer to obtain the anonymous digital currency and for
319enabling the merchant to convert the anonymous digital currency back
320to some traditional currency.
321
322\subsection{Security model}
323
324Taler's security model assumes that cryptographic primitives are
325secure and that each participant is under full control of his system.
326The contact information of the mint is known to both customer and
327merchant from the start. Furthermore, the merchant is known to the
328customer and we assume that an anonymous, reliable bi-directional
329communication channel can be established by the customer to both the
330mint and the merchant.
331
332The mint is trusted to hold funds of its customers and to forward them
333when receiving the respective deposit instructions from the merchants.
334Customer and merchant can have some assurances about the mint's
335liquidity and operation, as the mint has proven reserves, is subject
336to the law, and can have its business is regularly audited (for
337example, by the government or a trusted third party auditor).
338Audits of the mint's accounts must reveal any possible fraud.
339%
340The merchant is trusted to deliver the service or goods to the
341customer upon receiving payment. The customer can seek legal relief
342to achieve this, as he must get cryptographic proofs of the contract
343and that he paid his obligations.
344%
345Neither the merchant nor the customer may have any ability to {\em
346 effectively} defraud the mint or the state collecting taxes. Here,
347``effectively'' means that the expected return for fraud is negative.
348%
349Note that customers do not need to be trusted in any way, and that in
350particular it is never necessary for anyone to try to recover funds
351from customers using legal means.
352
353
354\subsection{Taxability and Entities}
355
356Electronic coins are trivially copied between machines. Thus, we must
357clarify what kinds of operations can even be expected to be taxed.
358After all, without instrusive measures to take away control of the
359computing platform from its users, copying an electronic wallet from
360one computer to another can hardly be prevented by a payment system.
361Furthermore, it would also hardly be appropriate to tax the moving of
362funds between two computers owned by the same individual. We thus
363need to clarify which kinds of transfers we expect to tax.
364
365Taler is supposed to ensure that the state can tax {\em transactions}.
366We define a transaction as the transfer of funds between {\em mutually
367 distrustful} entities. Two entities are assumed to be mutually
368distrustful if they are unwilling to share control over assets. If a
369private key is shared between two entities, then both entities have
370equal access to the credentials represented by the private key. In a
371payment system this means that either entity could spent the
372associated funds. Assuming the payment system has effective
373double-spending detection, this means that either entity has to
374constantly fear that the funds might no longer be available to it.
375Thus, ``transfering'' funds by sharing a private key implies that
376receiving party must trust the sender. In Taler, making funds
377available by sharing a private key and thus sharing control is {\bf
378 not} considered a {\em transaction} and thus {\bf not} recorded for
379taxation.
380
381A {\em transaction} is a transfer where it is assured that one entity
382gains control over funds while at the same time another entity looses
383control over those funds. Taler ensures taxability only when some
384entity acquires exclusive control over digital coins. For
385transactions, the state can obtain information from the mint (or the
386bank) that identifies the entity that received the digital coins as
387well as the exact value of those coins. Taler also allows the mint
388(and thus the state) to learn the value of digital coins withdrawn by
389a customer --- but not how, where or when they were spent. Finally,
390to enable audits, the current balance and profits of the mint are also
391easily determined.
392
393\subsection{Anonymity}
394
395An anonymous communication channel (e.g. via Tor~\cite{tor-design}) is
396used for all communication between the customer and the merchant.
397Thus, the customer can remain anonymous; however, the system does reveal
398that the customer is one of the patrons of the mint. Naturally, the
399customer-merchant operation might leak other information about the
400customer, such as a shipping address. Such purchase-specific
401information leakage is outside of the scope of this work.
402
403The customer may use an anonymous communication channel for the
404communication with the mint to avoid leaking IP address information;
405however, the mint will anyway be able to determine the customer's
406identity from the (SEPA) transfer that the customer initiates to
407obtain anonymous digital cash. The scheme is anonymous
408because the mint will be unable to link the known identity of the
409customer that withdrew anonymous digital currency to the {\em
410 purchase} performed later at the merchant.
411% All the mint will be
412%able to confirm is that the customer is {\em one} of its patrons who
413%previously obtained the anonymous digital currency --- and of course
414%that the coin was not spent before.
415
416While the customer thus has anonymity for his purchase, the mint will
417always learn the merchant's identity (which is necessary for
418taxation), and thus the merchant has no reason to anonymize his
419communication with the mint.
420% Technically, the merchant could still
421%use an anonymous communication channel to communicate with the mint.
422%However, in order to receive the traditional currency the mint will
423%require (SEPA) account details for the deposit.
424
425%As both the initial transaction between the customer and the mint as
426%well as the transactions between the merchant and the mint do not have
427%to be done anonymously, there might be a formal business contract
428%between the customer and the mint and the merchant and the mint. Such
429%a contract may provide customers and merchants some assurance that
430%they will actually receive the traditional currency from the mint
431%given cryptographic proof about the validity of the transaction(s).
432%However, given the business overheads for establishing such contracts
433%and the natural goal for the mint to establish a reputation and to
434%minimize cost, it is more likely that the mint will advertise its
435%external auditors and proven reserves and thereby try to convince
436%customers and merchants to trust it without a formal contract.
437
438
439\subsection{Coins}
440
441A \emph{coin} is a digital token which derives its financial value
442from a signature on the coin's identifier by a mint. The mint is
443expected to have multiple {\em coin signing key} pairs available for
444signing, each representing a different coin denomination.
445
446The coin signing keys have an expiration date (typically measured in
447years), and coins signed with a coin signing key must be spent (or
448exchanged for new coins) before that expiration date. This allows the
449mint to limit the amount of state it needs to keep to detect
450double spending attempts. Furthermore, the mint is expected to use each coin
451signing key only for a limited number of coins, for example by
452limiting its use to sign coins to a week or a month. That way, if the
453private coin signing key were to be compromised, the mint can detect
454this once more coins are redeemed than the total that was signed into
455existence using the respective coin signing key. In this case, the
456mint can allow the original set of customers to exchange the coins
457that were signed with the compromised private key, while refusing
458further transactions from merchants if they involve those coins. As a
459result, the financial damage of loosing a private signing key can be
460limited to at most twice the amount originally signed with that key.
461To ensure that the mint does not enable deanonymization of users by
462signing each coin with a fresh coin signing key, the mint must
463publicly announce the coin signing keys in advance. Those
464announcements are expected to be signed with an off-line long-term
465private {\em master signing key} of the mint and possibly the auditor.
466
467Before a customer can withdraw a coin from the mint, he has to pay the
468mint the value of the coin, as well as processing fees. This is done
469using other means of payments, such as SEPA transfers~\cite{sepa}.
470The subject line of the transfer must contains {\em withdrawal
471 authorization key}, a public key for digital signatures generated by
472the customer. When the mint receives a transfer with a public key in
473the subject, it adds the funds to a {\em reserve} identified by the
474withdrawl authorization key. By signing the withdrawl messages using
475the withdrawl authorization key, the customer can prove to the mint
476that he is authorized to withdraw anonymous digital coins from the
477reserve. The mint will record the withdrawl messages with the reserve
478record as proof that the anonymous digital coin was created for the
479correct customer.
480
481After a coin is minted, the customer is the only entity that knows the
482private key of the coin, making him the \emph{owner} of the coin. The
483coin can be identified by the mint by its public key; however, due to
484the use of blind signatures, the mint does not learn the public key
485during the minting process. Knowledge of the private key of the coin
486enables the owner to spent the coin. If the private key is shared
487with others, they also become owners of the coin.
488
489\subsection{Coin spending}
490
491To spent a coin, the coin's owner needs to sign a {\em deposit
492 request} specifying the amount, the merchant's account information
493and a {\em business transaction-specific hash} using the coin's
494private key. A merchant can then transfer this permission of the
495coin's owner to the mint to obtain the amount in traditional currency.
496If the customer is cheating and the coin was already spent, the mint
497provides cryptographic proof of the fraud to the merchant, who will
498then refuse the transaction.
499% The mint is typically expected
500%to transfer the funds to the merchant using a SEPA transfer or similar
501%methods appropriate to the domain of the traditional currency.
502
503%The mint needs to ensure that a coin can only be spent once. This is
504%done by storing the public keys of all deposited coins (together with
505%the deposit request and the owner's signature confirming the
506%transaction). The mint's state can be limited as coins signed with
507%expired coin sigining keys do not have to be retained.
508
509\paragraph{Partial spending.}
510
511To allow exact payments without requiring the customer to keep a large
512amount of ``change'' in stock, the payment systems allows partial
513spending of coins. Consequently, the mint the must not only store the
514identifiers of spent coins, but also the fraction of the coin that has
515been spent.
516
517%\paragraph{Online checks.}
518%
519%For secure transactions (non-microdonations), the merchant is expected
520%to perform an online check to detect double-spending. In the simplest
521%case, the merchant simply directly confirms the validity of the
522%deposit permission signed by the coin's owner with the mint, and then
523%proceeds with the contract.
524
525\paragraph{Incremental payments.}
526
527For services that include pay-as-you-go billing, customers can over
528time sign deposit permissions for an increasing fraction of the value
529of a coin to be paid to a particular merchant. As checking with the
530mint for each increment might be expensive, the coin's owner can
531instead sign a {\em lock permission}, which allows the merchant to get
532an exclusive right to redeem deposit permissions for the coin for a
533limited duration. The merchant uses the lock permission to determine
534if the coin has already been spent and to ensure that it cannot be
535spent by another merchant for the {\em duration} of the lock as
536specified in the lock permission. If the coin has been spent or is
537already locked, the mint provides the owner's deposit or locking
538request and signature to prove the attempted fraud by the customer.
539Otherwise, the mint locks the coin for the expected duration of the
540transaction (and remembers the lock permission). The merchant and the
541customer can then finalize the business transaction, possibly
542exchanging a series of incremental payment permissions for services.
543Finally, the merchant then redeems the coin at the mint before the
544lock permission expires to ensure that no other merchant spends the
545coin first.
546
547
548\paragraph{Probabilistic spending.}
549
550Similar to Peppercoin, Taler supports probabilistic spending of coins to
551support cost-effective transactions for small amounts. Here, an
552ordinary transaction is performed based on the result of a biased coin
553flip with a probability related to the desired transaction amount in
554relation to the value of the coin. Unlike Peppercoin, in Taler either
555the merchant wins and the customer looses the coin, or the merchant
556looses and the customer keeps the coin. Thus, there is no opportunity
557for the merchant and the customer to conspire against the mint. To
558determine if the coin is to be transferred, merchant and customer
559execute a secure coin flipping protocol~\cite{blum1981}. The commit
560values are included in the business contract and are revealed after
561the contract has been signed using the private key of the coin. If
562the coin flip is decided in favor of the merchant, the merchant can
563redeem the coin at the mint.
564
565One issue in this protocol is that the customer may use a worthless
566coin by offering a coin that has already been spent. This kind of
567fraud would only be detected if the customer actually lost the coin
568flip, and at this point the merchant might not be able to recover from
569the loss. A fradulent anonymous customer may run the protocol using
570already spent coins until the coin flip is in his favor. As with
571incremental spending, lock permissions could be used to ensure that
572the customer cannot defraud the merchant by offering a coin that has
573already been spent. However, as this means involving the mint even if
574the merchant looses the coin flip, such a scheme is unsuitable for
575microdonations as the transaction costs from involving the mint might
576be disproportionate to the value of the transaction, and thus with
577locking the probabilistic scheme has no advantage over simply using
578fractional payments.
579
580Hence, Taler uses probabilistic transactions {\em without} the online
581double-spending detection. This enables the customer to defraud the
582merchant by paying with a coin that was already spent. However, as,
583by definition, such microdonations are for tiny amounts, the incentive
584for customers to pursue this kind of fraud is limited.
585
586
587\subsection{Refreshing Coins}
588
589In the payment scenarios there are several cases where a customer will
590reveal the public key of a coin to a merchant, but not ultimately sign
591over the full value of the coin. If the customer then continues to
592use the remainder of the value of the coin in other transactions,
593merchants and the mint could link the various transactions as they all
594share the same public key for the coin.
595
596Thus, the owner might want to exchange such a {\em dirty} coin for a
597{\em fresh} coin to ensure unlinkability of future transactions with
598the previous operation. Even if a coin is not dirty, the owner of a
599coin may want to exchange a coin if the respective coin signing key is
600about to expire. All of these operations are supported with the {\em
601 coin refreshing protocol}, which allows the owner of a coin to
602exchange existing coins (or their remaining value) for fresh coins
603with a new public-private key pairs. Refreshing does not use the
604ordinary spending operation as the owner of a coin should not have to
605pay taxes on this operation. Because of this, the refreshing protocol
606must assure that owner stays the same. After all, the coin refreshing
607protocol must not be usable for transactions, as transactions in Taler
608must be taxable.
609
610Thus, one main goal of the refreshing protocol is that the mint must
611not be able to link the fresh coin's public key to the public key of
612the dirty coin. The second main goal is to enable the mint to ensure
613that the owner of the dirty coin can determine the private key of the
614fresh coin. This way, refreshing cannot be used to construct a
615transaction --- the owner of the dirty coin remains in control of the
616fresh coin.
617
618As with other operations, the refreshing protocol must also protect
619the mint from double-spending; similarly, the customer has to have
620cryptographic evidence if there is any misbehaviour by the mint.
621Finally, the mint may choose to charge a transaction fee for
622refreshing by reducing the value of the generated fresh coins
623in relation to the value of the melted coins.
624%Naturally, all such transaction fees should be clearly stated as part
625%of the business contract offered by the mint to customers and
626%merchants.
627
628
629\section{Taler's Cryptographic Protocols}
630
631% In this section, we describe the protocols for Taler in detail.
632
633For the sake of brevity, we do not specifically state that the
634recipient of a signed message always first checks that the signature
635is valid. Also, whenever a signed message is transmitted, it is
636assumed that the receiver is told the public key (or knows it from the
637context) and that the signature contains additional identification as
638to the purpose of the signature (such that it is not possible to
639use a signature from one protocol step in a different context).
640
641When the mint signs messages (not coins), an {\em online message
642 signing key} of the mint is used. The mint's long-term offline key
643is used to certify both the coin signing keys as well as the online
644message signing key of the mint. The mint's long-term offline key is
645assumed to be well-known to both customers and merchants, for example
646because it is certified by the auditors.
647
648As we are dealing with financial transactions, we explicitly state
649whenever entities need to safely commit data to persistent storage.
650As long as those commitments persist, the protocol can be safely
651resumed at any step. Commitments to disk are cummulative, that is an
652additional commitment does not erase the previously committed
653information. Keys and thus coins always have a well-known expiration
654date; information committed to disk can be discarded after the
655expiration date of the respective public key. Customers can also
656discard information once the respective coins have been fully spent,
657and merchants may discard information once payments from the mint have
658been received (assuming records are also no longer needed for tax
659authorities). The mint's bank transfers dealing in traditional
660currency are expected to be recorded for tax authorities to ensure
661taxability.
662
663\subsection{Withdrawal}
664
665To withdraw anonymous digital coins, the customer performs the
666following interaction with the mint:
667
668\begin{enumerate}
669 \item The customer identifies a mint with an auditor-approved
670 coin signing public-private key pair $K := (K_s, K_p)$
671 and randomly generates:
672 \begin{itemize}
673 \item withdrawal key $W := (W_s,W_p)$ with private key $W_s$ and public key $W_p$,
674 \item coin key $C := (C_s,C_p)$ with private key $C_s$ and public key $C_p$,
675 \item blinding factor $b$,
676 \end{itemize}
677 and commits $\langle W, C, b \rangle$ to disk.
678 \item The customer transfers an amount of money corresponding to (at least) $K_p$ to the mint, with $W_p$ in the subject line of the transaction.
679 \item The mint receives the transaction and credits the $W_p$ reserve with the respective amount in its database.
680 \item The customer sends $S_W(E_b(C_p))$ to the mint to request withdrawl of $C$; here, $E_b$ denotes Chaum-style blinding with blinding factor $b$.
681 \item The mint checks if the same withdrawl request was issued before; in this case, it sends $S_{K}(E_b(C_p))$ to the customer.\footnote{Here $S_K$
682 denotes a Chaum-style blind signature with private key $K_s$.}
683 If this is a fresh withdrawl request, the mint performs the following transaction:
684 \begin{enumerate}
685 \item checks if the reserve $W_p$ has sufficient funds for a coin of value corresponding to $K_p$
686 \item stores the withdrawl request $\langle S_W(E_b(C_p)), S_K(E_b(C_p)) \rangle$ in its database for future reference,
687 \item deducts the amount corresponding to $K_p$ from the reserve,
688 \item and sends $S_{K}(E_b(C_p))$ to the customer.
689 \end{enumerate}
690 If the guards for the transaction fail, the mint sends an descriptive error back to the customer,
691 with proof that it operated correctly (i.e. by showing the transaction history for the reserve).
692 \item The customer computes (and verifies) the unblind signature $S_K(C_p) = D_b(S_K(E_b(C_p)))$.
693 The customer writes $\langle S_K(C_p), C_s \rangle$ to disk (effectively adding the coin to the
694 local wallet) for future use.
695\end{enumerate}
696
697\subsection{Exact, partial and incremental spending}
698
699A customer can spend coins at a merchant, under the condition that the
700merchant trusts the mint that minted the coin. Merchants are
701identified by their public key $M := (M_s, M_p)$, which must be known
702to the customer apriori.
703
704The following steps describe the protocol between customer, merchant and mint
705for a transaction involving a coin $C := (C_s, C_p)$ which is previously signed
706by a mint's denomination key $K$, i.e. the customer posses
707$\widetilde{C} := S_K(C_p)$:
708
709\begin{enumerate}
710\item\label{offer} The merchant sends an \emph{offer:} $\langle S_M(m, f),
711 \vec{D} \rangle$ containing the price of the offer $f$, a transaction
712 ID $m$ and the list of mints $D_1, \ldots, D_n$ accepted by the merchant
713 where each $D_i$ is a mint's public key.
714\item\label{lock} The customer must possess or acquire a coin minted by a mint that is
715 accepted by the merchant, i.e. $K$ should be publicly signed by some $D_i
716 \in \{D_1, D_2, \ldots, D_n\}$, and has a value $\geq f$.
717
718 Customer then generates a \emph{lock-permission} $\mathcal{L} :=
719 S_c(\widetilde{C}, t, m, f, M_p)$ where $t$ specifies the time until which the
720 lock is valid and sends $\langle \mathcal{L}, D_i\rangle$ to the merchant,
721 where $D_i$ is the mint which signed $K$.
722\item The merchant asks the mint to apply the lock by sending $\langle
723 \mathcal{L} \rangle$ to the mint.
724\item The mint validates $\widetilde{C}$ and detects double spending if there is
725 a lock-permission record $S_c(\widetilde{C}, t', m', f', M_p')$ where $(t',
726 m', f', M_p') \neq (t, m, f, M_p)$ or a \emph{deposit-permission} record for
727 $C$ and sends it to the merchant, who can then use it prove to the customer
728 and subsequently ask the customer to issue a new lock-permission.
729
730 If double spending is not found, the mint commits $\langle \mathcal{L} \rangle$ to disk
731 and notifies the merchant that locking was successful.
732\item\label{contract} The merchant creates a digitally signed contract
733 $\mathcal{A} := S_M(m, f, a, H(p, r))$ where $a$ is data relevant to the contract
734 indicating which services or goods the merchant will deliver to the customer, and $p$ is the
735 merchant's payment information (e.g. his IBAN number) and $r$ is an random nounce.
736 The merchant commits $\langle \mathcal{A} \rangle$ to disk and sends it to the customer.
737\item The customer creates a
738 \emph{deposit-permission} $\mathcal{D} := S_c(\widetilde{C}, f, m, M_p, H(a), H(p, r))$, commits
739 $\langle \mathcal{A}, \mathcal{D} \rangle$ to disk and sends $\mathcal{D}$ to the merchant.
740\item\label{invoice_paid} The merchant commits the received $\langle \mathcal{D} \rangle$ to disk.
741\item The merchant gives $(\mathcal{D}, p, r)$ to the mint, revealing his
742 payment information.
743\item The mint verifies $(\mathcal{D}, p, r)$ for its validity. A
744 \emph{deposit-permission} for a coin $C$ is valid if:
745 \begin{itemize}
746 \item $C$ is not refreshed already
747 \item there exists no other \emph{deposit-permission} on disk for \\
748 $\mathcal{D'} := S_c(\widetilde{C}, f', m', M_p', H(a'), H(p', r'))$ for $C$
749 such that \\ $(f', m',M_p', H(a')) \neq (f, m, M_p, H(a))$
750 \item $H(p, r) := H(p', r')$
751 \end{itemize}
752 If $C$ is valid and no other \emph{deposit-permission} for $C$ exists on disk, the
753 mint does the following:
754 \begin{enumerate}
755 \item if a \emph{lock-permission} exists for $C$, it is deleted from disk
756 \item\label{transfer} transfers an amount of $f$ to the merchant's bank account
757 given in $p$. The subject line of the transaction to $p$ must contain
758 $H(\mathcal{D})$.
759 \item $\langle \mathcal{D}, p, r \rangle$ is commited to disk.
760 \end{enumerate}
761 If the deposit record $\langle \mathcal{D}, p, r \rangle$ already exists,
762 the mint sends it to the merchant, but does not transfer money to $p$ again.
763\end{enumerate}
764
765To facilitate incremental spending of a coin $C$ in a single transaction, the
766merchant makes an offer in Step~\ref{offer} with a maximum amount $f_{max}$ he
767is willing to charge in this transaction from the coin $C$. After obtaining the
768lock on $C$ for $f_{max}$, the merchant makes a contract in Step~\ref{contract}
769with an amount $f \leq f_{max}$. The protocol follows with the following steps
770repeated after Step~\ref{invoice_paid} whenever the merchant wants to charge an
771incremental amount up to $f_{max}$:
772
773\begin{enumerate}
774 \setcounter{enumi}{4}
775\item The merchant generates a new contract $ \mathcal{A}' := S_M(m, f', a', H(p,
776 r)) $ after obtaining the deposit-permission for a previous contract. Here
777 $f'$ is the accumulated sum the merchant is charging the customer, of which
778 the merchant has received a deposit-permission for $f$ from the previous
779 contract \textit{i.e.}~$f <f' \leq f_{max}$. Similarly $a'$ is the new
780 contract data appended to older contract data $a$.
781 The merchant commits $\langle \mathcal{A}' \rangle$ to disk and sends it to the customer.
782\item Customer commits $\langle \mathcal{A}' \rangle$ to disk, creates
783 $\mathcal{D}' := S_c(\widetilde{C}, f', m, M_p, H(a'), H(p, r))$, commits
784 $\langle \mathcal{D'} \rangle$ and sends it to the merchant.
785\item The merchant commits the received $\langle \mathcal{D'} \rangle$ and
786 deletes the older $\mathcal{D}$
787\end{enumerate}
788
789%Figure~\ref{fig:spending_protocol_interactions} summarizes the interactions of the
790%coin spending protocol.
791
792For transactions with multiple coins, the steps of the protocol are executed in
793parallel for each coin.
794
795During the time a coin is locked, it may not be spent at a
796different merchant. To make the storage costs of the mint more predictable,
797only one lock per coin can be active at any time, even if the lock only covers a
798fraction of the coin's denomination. The mint will delete the locks when they
799expire. Thus the coins can be reused once their locks expire. However, doing
800so may link the new transaction to older transaction.
801
802Similarly, if a transaction is aborted after Step 2, subsequent transactions
803with the same coin can be linked to the coin, but not directly to the coin's
804owner. The same applies to partially spent coins. To unlink subsequent
805transactions from a coin, the customer has to execute the coin refreshing
806protocol with the mint.
807
808%\begin{figure}[h]
809%\centering
810%\begin{tikzpicture}
811%
812%\tikzstyle{def} = [node distance= 1em, inner sep=.5em, outer sep=.3em];
813%\node (origin) at (0,0) {};
814%\node (offer) [def,below=of origin]{make offer (merchant $\rightarrow$ customer)};
815%\node (A) [def,below=of offer]{permit lock (customer $\rightarrow$ merchant)};
816%\node (B) [def,below=of A]{apply lock (merchant $\rightarrow$ mint)};
817%\node (C) [def,below=of B]{confirm (or refuse) lock (mint $\rightarrow$ merchant)};
818%\node (D) [def,below=of C]{sign contract (merchant $\rightarrow$ customer)};
819%\node (E) [def,below=of D]{permit deposit (customer $\rightarrow$ merchant)};
820%\node (F) [def,below=of E]{make deposit (merchant $\rightarrow$ mint)};
821%\node (G) [def,below=of F]{transfer confirmation (mint $\rightarrow$ merchant)};
822%
823%\tikzstyle{C} = [color=black, line width=1pt]
824%\draw [->,C](offer) -- (A);
825%\draw [->,C](A) -- (B);
826%\draw [->,C](B) -- (C);
827%\draw [->,C](C) -- (D);
828%\draw [->,C](D) -- (E);
829%\draw [->,C](E) -- (F);
830%\draw [->,C](F) -- (G);
831%
832%\draw [->,C, bend right, shorten <=2mm] (E.east)
833% to[out=-135,in=-45,distance=3.8cm] node[left] {aggregate} (D.east);
834%\end{tikzpicture}
835%\caption{Interactions between a customer, merchant and mint in the coin spending
836% protocol}
837%\label{fig:spending_protocol_interactions}
838%\end{figure}
839
840
841\subsection{Probabilistic spending}
842
843The following steps are executed for microdonations with upgrade probability $p$:
844\begin{enumerate}
845 \item The merchant sends an offer to the customer.
846 \item The customer sends a commitment $H(r_c)$ to a random
847 value $r_c \in [0,2^R)$, where $R$ is a system parameter.
848 \item The merchant sends random $r_m \in [0,2^R)$ to the customer.
849 \item The customer computes $p' := (|r_c - r_m|) / (2^R)$.
850 If $p' < p$, the customer sends a coin with deposit-permission to the merchant.
851 Otherwise, the customer sends $r_c$ to the merchant.
852 \item The merchant deposits the coin, or checks if $r_c$ is consistent
853 with $H(r_c)$.
854\end{enumerate}
855
856\subsection{Refreshing}
857
858The following protocol is executed in order to refresh a coin $C'$ of denomination $K$ to
859a fresh coin $\widetilde{C}$ with the same denomination. In the protocol, $\kappa \ge 3$ is a security parameter.
860
861\begin{enumerate}
862 \item For each $i = 1,\ldots,\kappa$, the customer
863 \begin{itemize}
864 \item randomly generates transfer key $T^{(i)} := \left(t^{(i)}_s,T^{(i)}_p\right)$ where $T^{(i)}_p := t^{(i)}_s \cdot G$,
865 \item randomly generates coin key pair $C^{(i)} := \left(c_s^{(i)}, C_p^{(i)}\right)$ where $C^{(i)}_p := c^{(i)}_s \cdot G$,
866 \item randomly generates blinding factors $b_i$,
867 \item computes $E_i := E_{K_i}\left(c_s^{(i)}, b_i\right)$ where $K_i := c'_s \cdot T_p^{(i)}$ (The encryption key $K_i$ is
868 computed by multiplying the private key $c'_s$ of the original coin with the point on the curve
869 that represents the public key of the transfer key $T^{(i)}$.),
870 \end{itemize}
871 and commits $\langle C', \vec{T}, \vec{C}, \vec{b} \rangle$ to disk.
872 \item The customer computes $B_i := E_{b_i}(C^{(i)}_p)$ and sends commitments
873 $S_{C'}(\vec{E}, \vec{B}, \vec{T}))$ for $i=1,\ldots,\kappa$ to the mint;
874 here $E_{b_i}$ denotes Chaum-style blinding with blinding factor $b_i$.
875 \item The mint generates a random $\gamma$ with $1 \le \gamma \le \kappa$ and
876 marks $C'_p$ as spent by committing
877 $\langle C', \gamma, S_{C'}(\vec{E}, \vec{B}, \vec{T}) \rangle$ to disk
878 \item The mint sends $S_K(C'_p, \gamma)$ to the customer.\footnote{Instead of $K$, it is also
879 possible to use any equivalent mint signing key known to the customer here, as $K$ merely
880 serves as proof to the customer that the mint selected this particular $\gamma$.}
881 \item The customer commits $\langle C', S_K(C'_p, \gamma) \rangle$ to disk.
882 \item The customer computes $\mathfrak{R} := \left(t_s^{(i)}, C_p^{(i)}, b_i\right)_{i \ne \gamma}$
883 and sends $S_{C'}(\mathfrak{R})$ to the mint.
884 \item \label{step:refresh-ccheck} The mint checks whether $\mathfrak{R}$ is consistent with the commitments;
885 specifically, it computes for $i \not= \gamma$:
886 \begin{itemize}
887 \item $\overline{K}_i := t_s^{(i)} \cdot C_p'$,
888 \item $(\overline{c}_s^{(i)}, \overline{b}_i) := D_{\overline{K}_i}(E_i)$,
889 \item $\overline{C}^{(i)}_p := \overline{c}_s^{(i)} \cdot G$,
890 \item $\overline{B}_i := E_{b_i}(C_p^{(i)})$,
891 \item $\overline{T}_i := t_s^{(i)} G$,
892 \end{itemize}
893 and checks if $\overline{C}^{(i)}_p = C^{(i)}_p$ and $H(E_i, \overline{B}_i, \overline{T}^{(i)}_p) = H(E_i, B_i, T^{(i)}_p)$
894 and $\overline{T}_i = T_i$.
895
896 \item \label{step:refresh-done} If the commitments were consistent, the mint sends the blind signature
897 $\widetilde{C} := S_{K}(B_\gamma)$ to the customer.
898 Otherwise, the mint responds with an error and confiscates the value of $C'$,
899 committing $\langle C', \gamma, S_{C'}(\mathfrak{R}) \rangle$ to disk as proof for the attempted fraud.
900\end{enumerate}
901
902%\subsection{N-to-M Refreshing}
903%
904%TODO: Explain, especially subtleties regarding session key / the spoofing attack that requires signature.
905
906\subsection{Linking}
907
908For a coin that was successfully refreshed, the mint responds to
909a request $S_{C'}(\mathtt{link})$ with $(T^{(\gamma)}_p$, $E_{\gamma}, \widetilde{C})$.
910
911This allows the owner of the old coin to also obtain the private key
912of the new coin, even if the refreshing protocol was illicitly
913executed by another party who learned $C'_s$ from the old owner.
914
915
916\section{Discussion}
917
918\subsection{Offline Payments}
919
920Chaum's original proposals for anonymous digital cash avoided the
921locking and online spending steps detailed in this proposal by
922providing a means to deanonymize customers involved in
923double-spending. We believe that this is problematic as the mint or
924the merchant will then still need out-of-band means to recover funds
925from the customer, which may be impossible in practice. In contrast,
926in our design only the mint may try to defraud the other participants
927and disappear. While this is still a risk, this is likely manageable,
928especially compared to recovering funds via the court system from
929customers.
930
931
932\subsection{Bona-fide microdonations}
933
934Evidently the customer can ``cheat'' by aborting the transaction in
935Step 3 of the microdonation protocol if the outcome is unfavourable ---
936and repeat until he wins. This is why Taler is suitable for
937microdonations --- where the customer voluntarily contributes ---
938and not for micropayments.
939
940Naturally, if the donations requested are small, the incentive to
941cheat for minimal gain should be quite low. Payment software could
942embrace this fact by providing an appeal to conscience in form of an
943option labeled ``I am unethical and want to cheat'', which executes
944the dishonest version of the payment protocol.
945
946If an organization detects that it cannot support itself with
947microdonations, it can always choose to switch to the macropayment
948system with slightly higher transaction costs to remain in business.
949
950\subsection{Merchant Tax Audits}
951
952For a tax audit on the merchant, the mint includes the business
953transaction-specific hash in the transfer of the traditional
954currency. A tax auditor can then request the merchant to reveal
955(meaningful) details about the business transaction ($\mathcal{D}$,
956$a$, $p$, $r$), including proof that applicable taxes were paid.
957
958If a merchant is not able to provide theses values, he can be punished
959in relation to the amount transferred by the traditional currency
960transfer.
961
962
963\section{Future Work}
964
965%The legal status of the system needs to be investigated in the various
966%legal systems of the world. However, given that the system enables
967%taxation and is able to impose withdrawl limits and thus is not
968%suitable for money laundering, we are optimistic that states will find
969%the design desirable.
970
971We did not yet perform performance measurements for the various
972operations. However, we are pretty sure that the computational and
973bandwidth cost for transactions described in this paper is likely
974small compared to other business costs for the mint. We expect costs
975within the system to be dominated by the (replicated, transactional)
976database. However, these expenses are again likely small in relation
977to the business cost of currency transfers using traditional banking.
978Here, mint operators should be able to reduce their expenses by
979aggregating multiple transfers to the same merchant.
980
981
982\section{Conclusion}
983
984We have presented an efficient electronic payment system that
985simultaneously addresses the conflicting objectives created by the
986citizen's need for privacy and the state's need for taxation. The
987coin refreshing protocol makes the design flexible and enables a
988variety of payment methods. The libre implementation and open
989protocol may finally enable modern society to upgrade to proper
990electronic wallets with efficient, secure and privacy-preserving
991transactions.
992
993\bibliographystyle{alpha}
994\bibliography{taler}
995\end{document}
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 000000000..90ea1a047
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,9 @@
1*.o
2*.deps
3*.libs
4*.lo
5*.la
6*.log
7*.trs
8*/__pycache__
9test-* \ No newline at end of file
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 000000000..485c4f9d7
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,2 @@
1AM_CPPFLAGS = -I$(top_srcdir)/src/include
2SUBDIRS = include util mint
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
new file mode 100644
index 000000000..d10d6d70e
--- /dev/null
+++ b/src/include/Makefile.am
@@ -0,0 +1,7 @@
1EXTRA_DIST = \
2 platform.h \
3 taler_blind.h \
4 taler_signatures.h \
5 taler_types.h \
6 taler_util.h \
7 taler_rsa.h
diff --git a/src/include/platform.h b/src/include/platform.h
new file mode 100644
index 000000000..4cba7abfd
--- /dev/null
+++ b/src/include/platform.h
@@ -0,0 +1,56 @@
1/*
2 This file is part of TALER
3 (C) 2014 Chrisitan Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file include/platform.h
19 * @brief This file contains the includes and definitions which are used by the
20 * rest of the modules
21 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
22 */
23
24#ifndef PLATFORM_H_
25#define PLATFORM_H_
26
27/* Include our configuration header */
28#ifndef HAVE_USED_CONFIG_H
29# define HAVE_USED_CONFIG_H
30# ifdef HAVE_CONFIG_H
31# include "taler_config.h"
32# endif
33#endif
34
35
36#if (GNUNET_EXTRA_LOGGING >= 1)
37#define VERBOSE(cmd) cmd
38#else
39#define VERBOSE(cmd) do { break; }while(0)
40#endif
41
42/* Include the features available for GNU source */
43#define _GNU_SOURCE
44
45/* Include GNUnet's platform file */
46#include <gnunet/platform.h>
47
48/* Do not use shortcuts for gcrypt mpi */
49#define GCRYPT_NO_MPI_MACROS 1
50
51/* Do not use deprecated functions from gcrypt */
52#define GCRYPT_NO_DEPRECATED 1
53
54#endif /* PLATFORM_H_ */
55
56/* end of platform.h */
diff --git a/src/include/taler_db_lib.h b/src/include/taler_db_lib.h
new file mode 100644
index 000000000..41b46264e
--- /dev/null
+++ b/src/include/taler_db_lib.h
@@ -0,0 +1,132 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17
18/**
19 * @file include/taler_db_lib.h
20 * @brief helper functions for DB interactions
21 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
22 * @author Florian Dold
23 */
24
25#ifndef TALER_DB_LIB_H_
26#define TALER_DB_LIB_H_
27
28#include <libpq-fe.h>
29#include "taler_util.h"
30
31#define TALER_DB_QUERY_PARAM_END { NULL, 0, 0 }
32#define TALER_DB_QUERY_PARAM_PTR(x) { (x), sizeof (*(x)), 1 }
33#define TALER_DB_QUERY_PARAM_PTR_SIZED(x, s) { (x), (s), 1 }
34
35
36#define TALER_DB_RESULT_SPEC_END { NULL, 0, NULL }
37#define TALER_DB_RESULT_SPEC(name, dst) { (void *) (dst), sizeof (*(dst)), (name) }
38#define TALER_DB_RESULT_SPEC_SIZED(name, dst, s) { (void *) (dst), (s), (name) }
39
40
41/**
42 * Description of a DB query parameter.
43 */
44struct TALER_DB_QueryParam
45{
46 /**
47 * Data or NULL
48 */
49 const void *data;
50 /**
51 * Size of 'data'
52 */
53 size_t size;
54 /**
55 * Non-null if this is not the last parameter.
56 * This allows for null as sentinal value.
57 */
58 int more;
59};
60
61
62/**
63 * Description of a DB result cell.
64 */
65struct TALER_DB_ResultSpec
66{
67 /**
68 * Destination for the data.
69 */
70 void *dst;
71
72 /**
73 * Allowed size for the data.
74 */
75 size_t dst_size;
76
77 /**
78 * Field name of the desired result.
79 */
80 char *fname;
81};
82
83
84/**
85 * Execute a prepared statement.
86 */
87PGresult *
88TALER_DB_exec_prepared (PGconn *db_conn,
89 const char *name,
90 const struct TALER_DB_QueryParam *params);
91
92
93/**
94 * Extract results from a query result according to the given specification.
95 * If colums are NULL, the destination is not modified, and GNUNET_NO
96 * is returned.
97 *
98 * @return
99 * GNUNET_YES if all results could be extracted
100 * GNUNET_NO if at least one result was NULL
101 * GNUNET_SYSERR if a result was invalid (non-existing field)
102 */
103int
104TALER_DB_extract_result (PGresult *result, struct TALER_DB_ResultSpec *rs, int row);
105
106
107int
108TALER_DB_field_isnull (PGresult *result,
109 int row,
110 const char *fname);
111
112
113int
114TALER_DB_extract_amount_nbo (PGresult *result,
115 int row,
116 const char *val_name,
117 const char *frac_name,
118 const char *curr_name,
119 struct TALER_AmountNBO *r_amount_nbo);
120
121
122int
123TALER_DB_extract_amount (PGresult *result,
124 int row,
125 const char *val_name,
126 const char *frac_name,
127 const char *curr_name,
128 struct TALER_Amount *r_amount);
129
130#endif /* TALER_DB_LIB_H_ */
131
132/* end of include/taler_db_lib.h */
diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h
new file mode 100644
index 000000000..b224c4b33
--- /dev/null
+++ b/src/include/taler_json_lib.h
@@ -0,0 +1,101 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file include/taler_json_lib.h
19 * @brief helper functions for JSON processing using libjansson
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */
22
23#ifndef TALER_JSON_LIB_H_
24#define TALER_JSON_LIB_H_
25
26#include <jansson.h>
27
28
29/**
30 * Convert a TALER amount to a JSON
31 * object.
32 *
33 * @param amount the amount
34 * @return a json object describing the amount
35 */
36json_t *
37TALER_JSON_from_amount (struct TALER_Amount amount);
38
39
40/**
41 * Convert absolute timestamp to a json string.
42 *
43 * @param the time stamp
44 * @return a json string with the timestamp in @a stamp
45 */
46json_t *
47TALER_JSON_from_abs (struct GNUNET_TIME_Absolute stamp);
48
49
50
51/**
52 * Convert binary data to a JSON string
53 * with the base32crockford encoding.
54 *
55 * @param data binary data
56 * @param size size of @a data in bytes
57 * @return json string that encodes @a data
58 */
59json_t *
60TALER_JSON_from_data (const void *data, size_t size);
61
62
63/**
64 * Parse given JSON object to Amount
65 *
66 * @param json the json object representing Amount
67 * @param r_amount where the amount has to be written
68 * @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
69 */
70int
71TALER_JSON_to_amount (json_t *json,
72 struct TALER_Amount *r_amount);
73
74/**
75 * Parse given JSON object to absolute time.
76 *
77 * @param json the json object representing absolute time in seconds
78 * @param r_abs where the time has to be written
79 * @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
80 */
81int
82TALER_JSON_to_abs (json_t *json,
83 struct GNUNET_TIME_Absolute *r_abs);
84
85/**
86 * Parse given JSON object to data
87 *
88 * @param json the json object representing data
89 * @param out the pointer to hold the parsed data.
90 * @param out_size the size of r_data.
91 * @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
92 */
93int
94TALER_JSON_to_data (json_t *json,
95 void *out,
96 size_t out_size);
97
98
99#endif /* TALER_JSON_LIB_H_ */
100
101/* End of taler_json_lib.h */
diff --git a/src/include/taler_microhttpd_lib.h b/src/include/taler_microhttpd_lib.h
new file mode 100644
index 000000000..da601401f
--- /dev/null
+++ b/src/include/taler_microhttpd_lib.h
@@ -0,0 +1,119 @@
1
2
3#ifndef TALER_MICROHTTPD_LIB_H_
4#define TALER_MICROHTTPD_LIB_H_
5
6
7#include <microhttpd.h>
8#include <jansson.h>
9
10
11/**
12 * Constants for JSON navigation description.
13 */
14enum
15{
16 /**
17 * Access a field.
18 * Param: const char *
19 */
20 JNAV_FIELD,
21 /**
22 * Access an array index.
23 * Param: int
24 */
25 JNAV_INDEX,
26 /**
27 * Return base32crockford encoded data of
28 * constant size.
29 * Params: (void *, size_t)
30 */
31 JNAV_RET_DATA,
32 /**
33 * Return base32crockford encoded data of
34 * variable size.
35 * Params: (void **, size_t *)
36 */
37 JNAV_RET_DATA_VAR,
38 /**
39 * Return a json object, which must be
40 * of the given type (JSON_* type constants,
41 * or -1 for any type).
42 * Params: (int, json_t **)
43 */
44 JNAV_RET_TYPED_JSON
45};
46
47
48
49/**
50 * Send JSON object as response. Decreases
51 * the reference count of the JSON object.
52 *
53 * @param connection the MHD connection
54 * @param json the json object
55 * @param status_code the http status code
56 * @return MHD result code (MHD_YES on success)
57 */
58int
59send_response_json (struct MHD_Connection *connection,
60 json_t *json,
61 unsigned int status_code);
62
63
64/**
65 * Send a JSON object via an MHD connection,
66 * specified with the JANSSON pack syntax (see json_pack).
67 *
68 * @param connection connection to send the JSON over
69 * @param http_code HTTP status for the response
70 * @param fmt format string for pack
71 * @param ... varargs
72 * @return MHD_YES on success or MHD_NO on error
73 */
74int
75request_send_json_pack (struct MHD_Connection *connection,
76 unsigned int http_code,
77 const char *fmt, ...);
78
79
80/**
81 * Process a POST request containing a JSON object.
82 *
83 * @param connection the MHD connection
84 * @param con_cs the closure (contains a 'struct Buffer *')
85 * @param upload_data the POST data
86 * @param upload_data_size the POST data size
87 * @param json the JSON object for a completed request
88 *
89 * @returns
90 * GNUNET_YES if json object was parsed
91 * GNUNET_NO is request incomplete or invalid
92 * GNUNET_SYSERR on internal error
93 */
94int
95process_post_json (struct MHD_Connection *connection,
96 void **con_cls,
97 const char *upload_data,
98 size_t *upload_data_size,
99 json_t **json);
100
101
102/**
103 * Navigate through a JSON tree.
104 *
105 * Sends an error response if navigation is impossible (i.e.
106 * the JSON object is invalid)
107 *
108 * @param connection the connection to send an error response to
109 * @param root the JSON node to start the navigation at.
110 * @param ... navigation specification (see JNAV_*)
111 * @return GNUNET_YES if navigation was successful
112 * GNUNET_NO if json is malformed, error response was generated
113 * GNUNET_SYSERR on internal error
114 */
115int
116request_json_require_nav (struct MHD_Connection *connection,
117 const json_t *root, ...);
118
119#endif /* TALER_MICROHTTPD_LIB_H_ */
diff --git a/src/include/taler_mint_service.h b/src/include/taler_mint_service.h
new file mode 100644
index 000000000..ee3b30e39
--- /dev/null
+++ b/src/include/taler_mint_service.h
@@ -0,0 +1,303 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file include/taler_mint_service.h
19 * @brief C interface to the mint's HTTP API
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */
22
23#ifndef _TALER_MINT_SERVICE_H
24#define _TALER_MINT_SERVICE_H
25
26#include "taler_rsa.h"
27#include "taler_util.h"
28#include <jansson.h>
29
30/**
31 * Handle to this library context
32 */
33struct TALER_MINT_Context;
34
35/**
36 * Handle to the mint
37 */
38struct TALER_MINT_Handle;
39
40/**
41 * Mint's signature key
42 */
43struct TALER_MINT_SigningPublicKey
44{
45 /**
46 * The signing public key
47 */
48 struct GNUNET_CRYPTO_EddsaPublicKey key;
49
50 /**
51 * Validity start time
52 */
53 struct GNUNET_TIME_Absolute valid_from;
54
55 /**
56 * Validity expiration time
57 */
58 struct GNUNET_TIME_Absolute valid_until;
59};
60
61
62/**
63 * Mint's denomination key
64 */
65struct TALER_MINT_DenomPublicKey
66{
67 /**
68 * The public key
69 */
70 struct TALER_RSA_PublicKeyBinaryEncoded key;
71
72 /**
73 * Timestamp indicating when the denomination key becomes valid
74 */
75 struct GNUNET_TIME_Absolute valid_from;
76
77 /**
78 * Timestamp indicating when the denomination key can’t be used anymore to
79 * withdraw new coins.
80 */
81 struct GNUNET_TIME_Absolute withdraw_valid_until;
82
83 /**
84 * Timestamp indicating when coins of this denomination become invalid.
85 */
86 struct GNUNET_TIME_Absolute deposit_valid_until;
87
88 /**
89 * The value of this denomination
90 */
91 struct TALER_Amount value;
92
93 /**
94 * The applicable fee for withdrawing a coin of this denomination
95 */
96 struct TALER_Amount fee_withdraw;
97
98 /**
99 * The applicable fee to spend a coin of this denomination
100 */
101 struct TALER_Amount fee_deposit;
102
103 /**
104 *The applicable fee to refresh a coin of this denomination
105 */
106 struct TALER_Amount fee_refresh;
107};
108
109
110/**
111 * Initialise a context. A context should be used for each thread and should
112 * not be shared among multiple threads.
113 *
114 * @return the context
115 */
116struct TALER_MINT_Context *
117TALER_MINT_init ();
118
119
120/**
121 * Cleanup library initialisation resources. This function should be called
122 * after using this library to cleanup the resources occupied during library's
123 * initialisation.
124 *
125 * @param ctx the library context
126 */
127void
128TALER_MINT_cleanup (struct TALER_MINT_Context *ctx);
129
130
131/**
132 * Initialise a connection to the mint.
133 *
134 * @param ctx the context
135 * @param hostname the hostname of the mint
136 * @param port the point where the mint's HTTP service is running. If port is
137 * given as 0, ports 80 or 443 are chosen depending on @a url.
138 * @param mint_key the public key of the mint. This is used to verify the
139 * responses of the mint.
140 * @return the mint handle; NULL upon error
141 */
142struct TALER_MINT_Handle *
143TALER_MINT_connect (struct TALER_MINT_Context *ctx,
144 const char *hostname,
145 uint16_t port,
146 struct GNUNET_CRYPTO_EddsaPublicKey *mint_key);
147
148/**
149 * Disconnect from the mint
150 *
151 * @param mint the mint handle
152 */
153void
154TALER_MINT_disconnect (struct TALER_MINT_Handle *mint);
155
156
157/**
158 * A handle to get the keys of a mint
159 */
160struct TALER_MINT_KeysGetHandle;
161
162/**
163 * Functions of this type are called to signal completion of an asynchronous call.
164 *
165 * @param cls closure
166 * @param emsg if the asynchronous call could not be completed due to an error,
167 * this parameter contains a human readable error message
168 */
169typedef void (*TALER_MINT_ContinuationCallback) (void *cls,
170 const char *emsg);
171
172/**
173 * Functions of this type are called to provide the retrieved signing and
174 * denomination keys of the mint. No TALER_MINT_*() functions should be called
175 * in this callback.
176 *
177 * @param cls closure passed to TALER_MINT_keys_get()
178 * @param sign_keys NULL-terminated array of pointers to the mint's signing
179 * keys. NULL if no signing keys are retrieved.
180 * @param denom_keys NULL-terminated array of pointers to the mint's
181 * denomination keys; will be NULL if no signing keys are retrieved.
182 */
183typedef void (*TALER_MINT_KeysGetCallback) (void *cls,
184 struct TALER_MINT_SigningPublicKey **sign_keys,
185 struct TALER_MINT_DenomPublicKey **denom_keys);
186
187
188/**
189 * Get the signing and denomination key of the mint.
190 *
191 * @param mint handle to the mint
192 * @param cb the callback to call with the keys
193 * @param cls closure for the above callback
194 * @param cont_cb the callback to call after completing this asynchronous call
195 * @param cont_cls the closure for the continuation callback
196 * @return a handle to this asynchronous call; NULL upon eror
197 */
198struct TALER_MINT_KeysGetHandle *
199TALER_MINT_keys_get (struct TALER_MINT_Handle *mint,
200 TALER_MINT_KeysGetCallback cb, void *cls,
201 TALER_MINT_ContinuationCallback cont_cb, void *cont_cls);
202
203/**
204 * Cancel the asynchronous call initiated by TALER_MINT_keys_get(). This should
205 * not be called if either of the @a TALER_MINT_KeysGetCallback or @a
206 * TALER_MINT_ContinuationCallback passed to TALER_MINT_keys_get() have been
207 * called.
208 *
209 * @param get the handle for retrieving the keys
210 */
211void
212TALER_MINT_keys_get_cancel (struct TALER_MINT_KeysGetHandle *get);
213
214
215/**
216 * A Deposit Handle
217 */
218struct TALER_MINT_DepositHandle;
219
220
221/**
222 * Callbacks of this type are used to serve the result of submitting a deposit
223 * permission object to a mint
224 *
225 * @param cls closure
226 * @param status 1 for successful deposit, 2 for retry, 0 for failure
227 * @param obj the received JSON object; can be NULL if it cannot be constructed
228 * from the reply
229 * @param emsg in case of unsuccessful deposit, this contains a human readable
230 * explanation.
231 */
232typedef void (*TALER_MINT_DepositResultCallback) (void *cls,
233 int status,
234 json_t *obj,
235 char *emsg);
236
237/**
238 * Submit a deposit permission to the mint and get the mint's response
239 *
240 * @param mint the mint handle
241 * @param cb the callback to call when a reply for this request is available
242 * @param cls closure for the above callback
243 * @param deposit_obj the deposit permission received from the customer along
244 * with the wireformat JSON object
245 * @return a handle for this request; NULL if the JSON object could not be
246 * parsed or is of incorrect format or any other error. In this case,
247 * the callback is not called.
248 */
249struct TALER_MINT_DepositHandle *
250TALER_MINT_deposit_submit_json (struct TALER_MINT_Handle *mint,
251 TALER_MINT_DepositResultCallback cb,
252 void *cls,
253 json_t *deposit_obj);
254
255
256#if 0
257/**
258 * Submit a deposit permission to the mint and get the mint's response.
259 *
260 * @param mint the mint handle
261 * @param cb the callback to call when a reply for this request is available
262 * @param cls closure for the above callback
263 * @param coin the public key of the coin
264 * @param denom_key denomination key of the mint which is used to blind-sign the
265 * coin
266 * @param ubsig the mint's unblinded signature
267 * @param transaction_id transaction identifier
268 * @param amount the amount to deposit
269 * @param merchant_pub the public key of the merchant
270 * @param h_contract hash of the contract
271 * @param h_wire hash of the wire format used
272 * @param csig signature of the coin over the transaction_id, amount,
273 * merchant_pub, h_contract and, h_wire
274 * @param wire_obj the wireformat object corresponding to h_wire
275 * @return a handle for this request
276 */
277struct TALER_MINT_DepositHandle *
278TALER_MINT_deposit_submit_json_ (struct TALER_MINT_Handle *mint,
279 TALER_MINT_DepositResultCallback *cb,
280 void *cls,
281 struct GNUNET_CRYPTO_EddsaPublicKey *coin_pub,
282 struct TALER_BLIND_SigningPublicKey *denom_pub,
283 struct TALER_BLIND_Signature *ubsig,
284 uint64_t transaction_id,
285 struct TALER_Amount *amount,
286 struct GNUNET_CRYPTO_EddsaPublicKey *merchant_pub,
287 struct GNUNET_HashCode *h_contract,
288 struct GNUNET_HashCode *h_wire,
289 struct GNUNET_CRYPTO_EddsaSignature *csig,
290 json_t *wire_obj);
291#endif
292
293
294/**
295 * Cancel a deposit permission request. This function cannot be used on a
296 * request handle if a response is already served for it.
297 *
298 * @param the deposit permission request handle
299 */
300void
301TALER_MINT_deposit_submit_cancel (struct TALER_MINT_DepositHandle *deposit);
302
303#endif /* _TALER_MINT_SERVICE_H */
diff --git a/src/include/taler_rsa.h b/src/include/taler_rsa.h
new file mode 100644
index 000000000..1ed530013
--- /dev/null
+++ b/src/include/taler_rsa.h
@@ -0,0 +1,357 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file include/taler_rsa.h
19 * @brief RSA key management utilities. Some code is taken from gnunet-0.9.5a
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 *
22 * Authors of the gnunet code:
23 * Christian Grothoff
24 * Krista Bennett
25 * Gerd Knorr <kraxel@bytesex.org>
26 * Ioana Patrascu
27 * Tzvetan Horozov
28 */
29
30#ifndef TALER_RSA_H
31#define TALER_RSA_H
32
33#include <gnunet/gnunet_common.h>
34#include <gnunet/gnunet_crypto_lib.h>
35
36/**
37 * Length of an RSA KEY (n,e,len), 2048 bit (=256 octests) key n, 2 byte e
38 */
39#define TALER_RSA_KEY_LENGTH 258
40
41/**
42 * @brief Length of RSA encrypted data (2048 bit)
43 *
44 * We currently do not handle encryption of data
45 * that can not be done in a single call to the
46 * RSA methods (read: large chunks of data).
47 * We should never need that, as we can use
48 * the GNUNET_CRYPTO_hash for larger pieces of data for signing,
49 * and for encryption, we only need to encode sessionkeys!
50 */
51#define TALER_RSA_DATA_ENCODING_LENGTH 256
52
53/**
54 * The private information of an RSA key pair.
55 */
56struct TALER_RSA_PrivateKey;
57
58
59GNUNET_NETWORK_STRUCT_BEGIN
60
61/**
62 * GNUnet mandates a certain format for the encoding
63 * of private RSA key information that is provided
64 * by the RSA implementations. This format is used
65 * to serialize a private RSA key (typically when
66 * writing it to disk).
67 */
68struct TALER_RSA_PrivateKeyBinaryEncoded
69{
70 /**
71 * Total size of the structure, in bytes, in big-endian!
72 */
73 uint16_t len GNUNET_PACKED;
74 uint16_t sizen GNUNET_PACKED; /* in big-endian! */
75 uint16_t sizee GNUNET_PACKED; /* in big-endian! */
76 uint16_t sized GNUNET_PACKED; /* in big-endian! */
77 uint16_t sizep GNUNET_PACKED; /* in big-endian! */
78 uint16_t sizeq GNUNET_PACKED; /* in big-endian! */
79 uint16_t sizedmp1 GNUNET_PACKED; /* in big-endian! */
80 uint16_t sizedmq1 GNUNET_PACKED; /* in big-endian! */
81 /* followed by the actual values */
82};
83GNUNET_NETWORK_STRUCT_END
84
85
86/**
87 * @brief an RSA signature
88 */
89struct TALER_RSA_Signature
90{
91 unsigned char sig[TALER_RSA_DATA_ENCODING_LENGTH];
92};
93
94GNUNET_NETWORK_STRUCT_BEGIN
95/**
96 * @brief header of what an RSA signature signs
97 * this must be followed by "size - 8" bytes of
98 * the actual signed data
99 */
100struct TALER_RSA_SignaturePurpose
101{
102 /**
103 * How many bytes does this signature sign?
104 * (including this purpose header); in network
105 * byte order (!).
106 */
107 uint32_t size GNUNET_PACKED;
108
109 /**
110 * What does this signature vouch for? This
111 * must contain a GNUNET_SIGNATURE_PURPOSE_XXX
112 * constant (from gnunet_signatures.h). In
113 * network byte order!
114 */
115 uint32_t purpose GNUNET_PACKED;
116
117};
118
119
120struct TALER_RSA_BlindedSignaturePurpose
121{
122 unsigned char data[TALER_RSA_DATA_ENCODING_LENGTH];
123};
124
125
126/**
127 * @brief A public key.
128 */
129struct TALER_RSA_PublicKeyBinaryEncoded
130{
131 /**
132 * In big-endian, must be GNUNET_CRYPTO_RSA_KEY_LENGTH+4
133 */
134 uint16_t len GNUNET_PACKED;
135
136 /**
137 * Size of n in key; in big-endian!
138 */
139 uint16_t sizen GNUNET_PACKED;
140
141 /**
142 * The key itself, contains n followed by e.
143 */
144 unsigned char key[TALER_RSA_KEY_LENGTH];
145
146 /**
147 * Padding (must be 0)
148 */
149 uint16_t padding GNUNET_PACKED;
150};
151
152GNUNET_NETWORK_STRUCT_END
153
154/**
155 * Create a new private key. Caller must free return value.
156 *
157 * @return fresh private key
158 */
159struct TALER_RSA_PrivateKey *
160TALER_RSA_key_create ();
161
162
163/**
164 * Free memory occupied by the private key.
165 *
166 * @param key pointer to the memory to free
167 */
168void
169TALER_RSA_key_free (struct TALER_RSA_PrivateKey *key);
170
171
172/**
173 * Encode the private key in a format suitable for
174 * storing it into a file.
175 * @return encoding of the private key
176 */
177struct TALER_RSA_PrivateKeyBinaryEncoded *
178TALER_RSA_encode_key (const struct TALER_RSA_PrivateKey *hostkey);
179
180
181/**
182 * Extract the public key of the given private key.
183 *
184 * @param priv the private key
185 * @param pub where to write the public key
186 */
187void
188TALER_RSA_key_get_public (const struct TALER_RSA_PrivateKey *priv,
189 struct TALER_RSA_PublicKeyBinaryEncoded *pub);
190
191
192/**
193 * Decode the private key from the data-format back
194 * to the "normal", internal format.
195 *
196 * @param buf the buffer where the private key data is stored
197 * @param len the length of the data in 'buffer'
198 * @return NULL on error
199 */
200struct TALER_RSA_PrivateKey *
201TALER_RSA_decode_key (const char *buf, uint16_t len);
202
203
204/**
205 * Convert a public key to a string.
206 *
207 * @param pub key to convert
208 * @return string representing 'pub'
209 */
210char *
211TALER_RSA_public_key_to_string (const struct TALER_RSA_PublicKeyBinaryEncoded *pub);
212
213
214/**
215 * Convert a string representing a public key to a public key.
216 *
217 * @param enc encoded public key
218 * @param enclen number of bytes in enc (without 0-terminator)
219 * @param pub where to store the public key
220 * @return GNUNET_OK on success
221 */
222int
223TALER_RSA_public_key_from_string (const char *enc,
224 size_t enclen,
225 struct TALER_RSA_PublicKeyBinaryEncoded *pub);
226
227
228/**
229 * Sign a given block.h
230 *
231 * @param key private key to use for the signing
232 * @param msg the message
233 * @param size the size of the message
234 * @param sig where to write the signature
235 * @return GNUNET_SYSERR on error, GNUNET_OK on success
236 */
237int
238TALER_RSA_sign (const struct TALER_RSA_PrivateKey *key,
239 const void *msg,
240 size_t size,
241 struct TALER_RSA_Signature *sig);
242
243
244/**
245 * Verify signature with the given hash.
246 *
247 * @param hash the hash code to verify against the signature
248 * @param sig signature that is being validated
249 * @param publicKey public key of the signer
250 * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid
251 */
252int
253TALER_RSA_hash_verify (const struct GNUNET_HashCode *hash,
254 const struct TALER_RSA_Signature *sig,
255 const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey);
256
257
258/**
259 * Verify signature on the given message
260 *
261 * @param msg the message
262 * @param size the size of the message
263 * @param sig signature that is being validated
264 * @param publicKey public key of the signer
265 * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid
266 */
267int
268TALER_RSA_verify (const void *msg, size_t size,
269 const struct TALER_RSA_Signature *sig,
270 const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey);
271
272/**
273 * Key used to blind a message
274 */
275struct TALER_RSA_BlindingKey;
276
277/**
278 * Create a blinding key
279 *
280 * @return the newly created blinding key
281 */
282struct TALER_RSA_BlindingKey *
283TALER_RSA_blinding_key_create ();
284
285
286/**
287 * Destroy a blinding key
288 *
289 * @param bkey the blinding key to destroy
290 */
291void
292TALER_RSA_blinding_key_destroy (struct TALER_RSA_BlindingKey *bkey);
293
294
295/**
296 * Binary encoding for TALER_RSA_BlindingKey
297 */
298struct TALER_RSA_BlindingKeyBinaryEncoded
299{
300 unsigned char data[TALER_RSA_DATA_ENCODING_LENGTH];
301};
302
303
304/**
305 * Encode a blinding key
306 *
307 * @param bkey the blinding key to encode
308 * @param bkey_enc where to store the encoded binary key
309 * @return #GNUNET_OK upon successful encoding; #GNUNET_SYSERR upon failure
310 */
311int
312TALER_RSA_blinding_key_encode (struct TALER_RSA_BlindingKey *bkey,
313 struct TALER_RSA_BlindingKeyBinaryEncoded *bkey_enc);
314
315
316/**
317 * Decode a blinding key from its encoded form
318 *
319 * @param bkey_enc the encoded blinding key
320 * @return the decoded blinding key; NULL upon error
321 */
322struct TALER_RSA_BlindingKey *
323TALER_RSA_blinding_key_decode (struct TALER_RSA_BlindingKeyBinaryEncoded *bkey_enc);
324
325
326/**
327 * Blinds the given message with the given blinding key
328 *
329 * @param msg the message
330 * @param size the size of the message
331 * @param bkey the blinding key
332 * @param pkey the public key of the signer
333 * @return the blinding signature purpose; NULL upon any error
334 */
335struct TALER_RSA_BlindedSignaturePurpose *
336TALER_RSA_message_blind (const void *msg, size_t size,
337 struct TALER_RSA_BlindingKey *bkey,
338 struct TALER_RSA_PublicKeyBinaryEncoded *pkey);
339
340
341/**
342 * Unblind a signature made on blinding signature purpose. The signature
343 * purpose should have been generated with TALER_RSA_message_blind() function.
344 *
345 * @param sig the signature made on the blinded signature purpose
346 * @param bkey the blinding key used to blind the signature purpose
347 * @param pkey the public key of the signer
348 * @return GNUNET_SYSERR upon error; GNUNET_OK upon success.
349 */
350int
351TALER_RSA_unblind (struct TALER_RSA_Signature *sig,
352 struct TALER_RSA_BlindingKey *bkey,
353 struct TALER_RSA_PublicKeyBinaryEncoded *pkey);
354
355#endif /* TALER_RSA_H */
356
357/* end of include/taler_rsa.h */
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
new file mode 100644
index 000000000..8c142f61f
--- /dev/null
+++ b/src/include/taler_signatures.h
@@ -0,0 +1,106 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file taler-mint-keyup.c
19 * @brief Update the mint's keys for coins and signatures,
20 * using the mint's offline master key.
21 * @author Florian Dold
22 * @author Benedikt Mueller
23 */
24
25#ifndef TALER_SIGNATURES_H
26#define TALER_SIGNATURES_H
27
28/**
29 * Purpose for signing public keys signed
30 * by the mint master key.
31 */
32#define TALER_SIGNATURE_MASTER_SIGNKEY 1
33
34/**
35 * Purpose for denomination keys signed
36 * by the mint master key.
37 */
38#define TALER_SIGNATURE_MASTER_DENOM 2
39
40/**
41 * Purpose for the state of a reserve,
42 * signed by the mint's signing key.
43 */
44#define TALER_SIGNATURE_RESERVE_STATUS 3
45
46/**
47 * Signature where the reserve key
48 * confirms a withdraw request.
49 */
50#define TALER_SIGNATURE_WITHDRAW 4
51
52/**
53 * Signature where the refresh session confirms
54 * the list of melted coins and requested denominations.
55 */
56#define TALER_SIGNATURE_REFRESH_MELT 5
57
58/**
59 * Signature where the refresh session confirms
60 * the commits.
61 */
62#define TALER_SIGNATURE_REFRESH_COMMIT 6
63
64/**
65 * Signature where the mint (current signing key)
66 * confirms the list of blind session keys.
67 */
68#define TALER_SIGNATURE_REFRESH_MELT_RESPONSE 7
69
70/**
71 * Signature where the mint (current signing key)
72 * confirms the no-reveal index for cut-and-choose.
73 */
74#define TALER_SIGNATURE_REFRESH_COMMIT_RESPONSE 8
75
76/**
77 * Signature where coins confirm that they want
78 * to be melted into a certain session.
79 */
80#define TALER_SIGNATURE_REFRESH_MELT_CONFIRM 9
81
82/***********************/
83/* Merchant signatures */
84/***********************/
85
86/**
87 * Signature where the merchant confirms a contract
88 */
89#define TALER_SIGNATURE_MERCHANT_CONTRACT 101
90
91/*********************/
92/* Wallet signatures */
93/*********************/
94
95/**
96 * Signature made by the wallet of a user to confirm a deposit permission
97 */
98#define TALER_SIGNATURE_DEPOSIT 201
99
100/**
101 * Signature made by the wallet of a user to confirm a incremental deposit permission
102 */
103#define TALER_SIGNATURE_INCREMENTAL_DEPOSIT 202
104
105#endif
106
diff --git a/src/include/taler_types.h b/src/include/taler_types.h
new file mode 100644
index 000000000..c6c2c0209
--- /dev/null
+++ b/src/include/taler_types.h
@@ -0,0 +1,120 @@
1/**
2 * @file include/types.h
3 * @brief This files defines the various data and message types in TALER.
4 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
5 * @author Florian Dold
6 */
7
8#ifndef TYPES_H_
9#define TYPES_H_
10
11#include "taler_rsa.h"
12
13
14/**
15 * Public information about a coin.
16 */
17struct TALER_CoinPublicInfo
18{
19 /**
20 * The coin's public key.
21 */
22 struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
23
24 /*
25 * The public key signifying the coin's denomination.
26 */
27 struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
28
29 /**
30 * Signature over coin_pub by denom_pub.
31 */
32 struct TALER_RSA_Signature denom_sig;
33};
34
35
36/**
37 * Request to withdraw coins from a reserve.
38 */
39struct TALER_WithdrawRequest
40{
41 /**
42 * Signature over the rest of the message
43 * by the withdraw public key.
44 */
45 struct GNUNET_CRYPTO_EddsaSignature sig;
46
47 /**
48 * Purpose must be TALER_SIGNATURE_WITHDRAW.
49 */
50 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
51
52 /**
53 * Reserve public key.
54 */
55 struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
56
57 /**
58 * Denomination public key for the coin that is withdrawn.
59 */
60 struct TALER_RSA_PublicKeyBinaryEncoded denomination_pub;
61
62 /**
63 * Purpose containing coin's blinded public key.
64 */
65 struct TALER_RSA_BlindedSignaturePurpose coin_envelope;
66};
67
68
69
70/**
71 * Data type for messages
72 */
73struct TALER_MessageHeader
74{
75 /**
76 * The type of the message in Network-byte order (NBO)
77 */
78 uint16_t type;
79
80 /**
81 * The size of the message in NBO
82 */
83 uint16_t size;
84};
85
86/*****************/
87/* Message types */
88/*****************/
89
90/**
91 * The message type of a blind signature
92 */
93#define TALER_MSG_TYPE_BLINDED_SIGNATURE 1
94
95/**
96 * The message type of a blinded message
97 */
98#define TALER_MSG_TYPE_BLINDED_MESSAGE 2
99
100/**
101 * The message type of an unblinded signature
102 * @FIXME: Not currently used
103 */
104#define TALER_MSG_TYPE_UNBLINDED_SIGNATURE 3
105
106/**
107 * The type of a blinding residue message
108 * @FIXME: Not currently used
109 */
110#define TALER_MSG_TYPE_BLINDING_RESIDUE 4
111
112/**
113 * The type of a message containing the blinding factor
114 */
115#define TALER_MSG_TYPE_BLINDING_FACTOR 5
116
117
118#endif /* TYPES_H_ */
119
120/* end of include/types.h */
diff --git a/src/include/taler_util.h b/src/include/taler_util.h
new file mode 100644
index 000000000..a8a7c2013
--- /dev/null
+++ b/src/include/taler_util.h
@@ -0,0 +1,255 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file include/taler_util.h
19 * @brief Interface for common utility functions
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */
22
23#ifndef UTIL_H_
24#define UTIL_H_
25
26#include <gnunet/gnunet_util_lib.h>
27#include <gcrypt.h>
28
29/* Define logging functions */
30#define LOG_DEBUG(...) \
31 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
32
33#define LOG_WARNING(...) \
34 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, __VA_ARGS__)
35
36#define LOG_ERROR(...) \
37 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, __VA_ARGS__)
38
39
40/**
41 * Tests a given as assertion and if failed prints it as a warning with the
42 * given reason
43 *
44 * @param EXP the expression to test as assertion
45 * @param reason string to print as warning
46 */
47#define TALER_assert_as(EXP, reason) \
48 do { \
49 if (EXP) break; \
50 LOG_ERROR("%s at %s:%d\n", reason, __FILE__, __LINE__); \
51 abort(); \
52 } while(0)
53
54
55
56/**
57 * Log an error message at log-level 'level' that indicates
58 * a failure of the command 'cmd' with the message given
59 * by gcry_strerror(rc).
60 */
61#define LOG_GCRY_ERROR(cmd, rc) do { LOG_ERROR("`%s' failed at %s:%d with error: %s\n", cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
62
63
64#define TALER_gcry_ok(cmd) \
65 do {int rc; rc = cmd; if (!rc) break; LOG_ERROR("A Gcrypt call failed at %s:%d with error: %s\n", __FILE__, __LINE__, gcry_strerror(rc)); abort(); } while (0)
66
67
68#define TALER_CURRENCY_LEN 4
69
70
71GNUNET_NETWORK_STRUCT_BEGIN
72
73struct TALER_AmountNBO
74{
75 uint32_t value;
76 uint32_t fraction;
77 char currency[TALER_CURRENCY_LEN];
78};
79
80GNUNET_NETWORK_STRUCT_END
81
82struct TALER_HashContext
83{
84 gcry_md_hd_t hd;
85};
86
87
88
89/**
90 * Representation of monetary value in a given currency.
91 */
92struct TALER_Amount
93{
94 /**
95 * Value (numerator of fraction)
96 */
97 uint32_t value;
98 /**
99 * Fraction (denominator of fraction)
100 */
101 uint32_t fraction;
102 /**
103 * Currency string, left adjusted and padded with zeros.
104 */
105 char currency[4];
106};
107
108
109/**
110 * Initialize Gcrypt library.
111 */
112void
113TALER_gcrypt_init();
114
115
116/**
117 * Generate a ECC private key.
118 *
119 * @return the s-expression representing the generated ECC private key; NULL
120 * upon error
121 */
122gcry_sexp_t
123TALER_genkey ();
124
125
126/**
127 * Parse denomination description, in the format "T : V : F".
128 *
129 * @param str denomination description
130 * @param denom denomination to write the result to
131 * @return GNUNET_OK if the string is a valid denomination specification,
132 * GNUNET_SYSERR if it is invalid.
133 */
134int
135TALER_string_to_amount (const char *str, struct TALER_Amount *denom);
136
137
138/**
139 * FIXME
140 */
141struct TALER_AmountNBO
142TALER_amount_hton (struct TALER_Amount d);
143
144
145/**
146 * FIXME
147 */
148struct TALER_Amount
149TALER_amount_ntoh (struct TALER_AmountNBO dn);
150
151/**
152 * Compare the value/fraction of two amounts. Does not compare the currency,
153 * i.e. comparing amounts with the same value and fraction but different
154 * currency would return 0.
155 *
156 * @param a1 first amount
157 * @param a2 second amount
158 * @return result of the comparison
159 */
160int
161TALER_amount_cmp (struct TALER_Amount a1, struct TALER_Amount a2);
162
163
164/**
165 * Perform saturating subtraction of amounts.
166 *
167 * @param a1 amount to subtract from
168 * @param a2 amount to subtract
169 * @return (a1-a2) or 0 if a2>=a1
170 */
171struct TALER_Amount
172TALER_amount_subtract (struct TALER_Amount a1, struct TALER_Amount a2);
173
174
175/**
176 * Perform saturating addition of amounts
177 *
178 * @param a1 first amount to add
179 * @param a2 second amount to add
180 * @return sum of a1 and a2
181 */
182struct TALER_Amount
183TALER_amount_add (struct TALER_Amount a1, struct TALER_Amount a2);
184
185
186/**
187 * Normalize the given amount.
188 *
189 * @param amout amount to normalize
190 * @return normalized amount
191 */
192struct TALER_Amount
193TALER_amount_normalize (struct TALER_Amount amount);
194
195
196/**
197 * Convert amount to string.
198 *
199 * @param amount amount to convert to string
200 * @return freshly allocated string representation
201 */
202char *
203TALER_amount_to_string (struct TALER_Amount amount);
204
205
206/**
207 * Return the base32crockford encoding of the given buffer.
208 *
209 * The returned string will be freshly allocated, and must be free'd
210 * with GNUNET_free.
211 *
212 * @param buffer with data
213 * @param size size of the buffer
214 * @return freshly allocated, null-terminated string
215 */
216char *
217TALER_data_to_string_alloc (const void *buf, size_t size);
218
219
220/**
221 * Get encoded binary data from a configuration.
222 *
223 * @return GNUNET_OK on success
224 * GNUNET_NO is the value does not exist
225 * GNUNET_SYSERR on encoding error
226 */
227int
228TALER_configuration_get_data (const struct GNUNET_CONFIGURATION_Handle *cfg,
229 const char *section, const char *option,
230 void *buf, size_t buf_size);
231
232
233
234
235int
236TALER_refresh_decrypt (const void *input, size_t input_size, const struct GNUNET_HashCode *secret, void *result);
237
238int
239TALER_refresh_encrypt (const void *input, size_t input_size, const struct GNUNET_HashCode *secret, void *result);
240
241
242
243void
244TALER_hash_context_start (struct TALER_HashContext *hc);
245
246
247void
248TALER_hash_context_read (struct TALER_HashContext *hc, void *buf, size_t size);
249
250
251void
252TALER_hash_context_finish (struct TALER_HashContext *hc,
253 struct GNUNET_HashCode *r_hash);
254
255#endif
diff --git a/src/mint/.gitignore b/src/mint/.gitignore
new file mode 100644
index 000000000..a2e71d5da
--- /dev/null
+++ b/src/mint/.gitignore
@@ -0,0 +1,6 @@
1taler-mint-dbinit
2taler-mint-keycheck
3taler-mint-keyup
4taler-mint-pursemod
5taler-mint-reservemod
6taler-mint-httpd \ No newline at end of file
diff --git a/src/mint/Makefile.am b/src/mint/Makefile.am
new file mode 100644
index 000000000..2ae153485
--- /dev/null
+++ b/src/mint/Makefile.am
@@ -0,0 +1,131 @@
1AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS)
2
3lib_LTLIBRARIES = \
4 libtalermint.la \
5 libtalermintapi.la
6
7libtalermint_la_SOURCES = \
8 mint_common.c \
9 mint_db.c
10
11libtalermint_la_LIBADD = \
12 $(top_builddir)/src/util/libtalerutil.la \
13 -lgnunetutil \
14 -lpq
15
16libtalermint_la_LDFLAGS = \
17 $(POSTGRESQL_LDFLAGS) \
18 -version-info 0:0:0 \
19 -no-undefined
20
21libtalermintapi_la_SOURCES = \
22 mint_api.c
23
24libtalermintapi_la_LIBADD = \
25 -lgnunetutil \
26 -ljansson \
27 -lcurl
28
29libtalermintapi_la_LDFLAGS = \
30 -version-info 0:0:0 \
31 -no-undefined
32
33
34bin_PROGRAMS = \
35 taler-mint-keyup \
36 taler-mint-keycheck \
37 taler-mint-reservemod \
38 taler-mint-httpd \
39 taler-mint-dbinit
40
41taler_mint_keyup_SOURCES = \
42 taler-mint-keyup.c
43
44taler_mint_keyup_LDADD = \
45 $(LIBGCRYPT_LIBS) \
46 $(top_builddir)/src/util/libtalerutil.la \
47 $(top_builddir)/src/mint/libtalermint.la \
48 -lpq \
49 -lgnunetutil
50taler_mint_keyup_LDFLAGS = $(POSTGRESQL_LDFLAGS)
51
52
53taler_mint_keycheck_SOURCES = \
54 taler-mint-keycheck.c
55
56taler_mint_keycheck_LDADD = \
57 $(LIBGCRYPT_LIBS) \
58 $(top_builddir)/src/util/libtalerutil.la \
59 $(top_builddir)/src/mint/libtalermint.la \
60 -lgnunetutil \
61 -lpq
62taler_mint_keycheck_LDFLAGS = $(POSTGRESQL_LDFLAGS)
63
64taler_mint_reservemod_SOURCES = \
65 taler-mint-reservemod.c
66taler_mint_reservemod_LDADD = \
67 $(LIBGCRYPT_LIBS) \
68 $(top_builddir)/src/util/libtalerutil.la \
69 $(top_builddir)/src/mint/libtalermint.la \
70 -lpq \
71 -lgnunetutil
72taler_mint_reservemod_LDFLAGS = \
73 $(POSTGRESQL_LDFLAGS)
74
75taler_mint_httpd_SOURCES = \
76 taler-mint-httpd.c \
77 taler-mint-httpd_mhd.c \
78 taler-mint-httpd_keys.c \
79 taler-mint-httpd_deposit.c \
80 taler-mint-httpd_withdraw.c \
81 taler-mint-httpd_refresh.c
82taler_mint_httpd_LDADD = \
83 $(LIBGCRYPT_LIBS) \
84 $(top_builddir)/src/util/libtalerutil.la \
85 $(top_builddir)/src/mint/libtalermint.la \
86 -lpq \
87 -lmicrohttpd \
88 -ljansson \
89 -lgnunetutil \
90 -lpthread
91taler_mint_httpd_LDFLAGS = \
92 $(POSTGRESQL_LDFLAGS)
93
94
95taler_mint_dbinit_SOURCES = \
96 taler-mint-dbinit.c
97taler_mint_dbinit_LDADD = \
98 $(LIBGCRYPT_LIBS) \
99 $(top_builddir)/src/util/libtalerutil.la \
100 $(top_builddir)/src/mint/libtalermint.la \
101 -lpq \
102 -lgnunetutil
103taler_mint_dbinit_LDFLAGS = $(POSTGRESQL_LDFLAGS)
104
105check_PROGRAMS = \
106 test-mint-api \
107 test-mint-deposits \
108 test-mint-common
109
110test_mint_api_SOURCES = test_mint_api.c
111test_mint_api_LDADD = \
112 libtalermintapi.la \
113 $(LIBGCRYPT_LIBS) \
114 $(top_builddir)/src/util/libtalerutil.la \
115 -lgnunetutil \
116 -ljansson
117
118test_mint_deposits_SOURCES = \
119 test_mint_deposits.c
120test_mint_deposits_LDADD = \
121 libtalermint.la \
122 $(top_srcdir)/src/util/libtalerutil.la \
123 -lgnunetutil \
124 -lpq
125
126test_mint_common_SOURCES = \
127 test_mint_common.c
128test_mint_common_LDADD = \
129 libtalermint.la \
130 $(top_srcdir)/src/util/libtalerutil.la \
131 -lgnunetutil
diff --git a/src/mint/mint.h b/src/mint/mint.h
new file mode 100644
index 000000000..5adce03c6
--- /dev/null
+++ b/src/mint/mint.h
@@ -0,0 +1,198 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file taler_mint.h
19 * @brief Common functionality for the mint
20 * @author Florian Dold
21 * @author Benedikt Mueller
22 */
23
24#ifndef _MINT_H
25#define _MINT_H
26
27#include <gnunet/gnunet_util_lib.h>
28#include <gnunet/gnunet_common.h>
29#include <libpq-fe.h>
30#include "taler_util.h"
31#include "taler_rsa.h"
32
33#define DIR_SIGNKEYS "signkeys"
34#define DIR_DENOMKEYS "denomkeys"
35
36
37GNUNET_NETWORK_STRUCT_BEGIN
38
39
40/**
41 * FIXME
42 */
43struct TALER_MINT_SignKeyIssue
44{
45 struct GNUNET_CRYPTO_EddsaPrivateKey signkey_priv;
46 struct GNUNET_CRYPTO_EddsaSignature signature;
47 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
48 struct GNUNET_CRYPTO_EddsaPublicKey master_pub;
49 struct GNUNET_TIME_AbsoluteNBO start;
50 struct GNUNET_TIME_AbsoluteNBO expire;
51 struct GNUNET_CRYPTO_EddsaPublicKey signkey_pub;
52};
53
54struct TALER_MINT_DenomKeyIssue
55{
56 /**
57 * The private key of the denomination. Will be NULL if the private key is
58 * not available.
59 */
60 struct TALER_RSA_PrivateKey *denom_priv;
61 struct GNUNET_CRYPTO_EddsaSignature signature;
62 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
63 struct GNUNET_CRYPTO_EddsaPublicKey master;
64 struct GNUNET_TIME_AbsoluteNBO start;
65 struct GNUNET_TIME_AbsoluteNBO expire_withdraw;
66 struct GNUNET_TIME_AbsoluteNBO expire_spend;
67 struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
68 struct TALER_AmountNBO value;
69 struct TALER_AmountNBO fee_withdraw;
70 struct TALER_AmountNBO fee_deposit;
71 struct TALER_AmountNBO fee_refresh;
72};
73
74struct RefreshMeltSignatureBody
75{
76 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
77 struct GNUNET_HashCode melt_hash;
78};
79
80struct RefreshCommitSignatureBody
81{
82 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
83 struct GNUNET_HashCode commit_hash;
84};
85
86struct RefreshCommitResponseSignatureBody
87{
88 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
89 uint16_t noreveal_index;
90};
91
92struct RefreshMeltResponseSignatureBody
93{
94 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
95 struct GNUNET_HashCode melt_response_hash;
96};
97
98
99struct RefreshMeltConfirmSignRequestBody
100{
101 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
102 struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
103};
104
105
106GNUNET_NETWORK_STRUCT_END
107
108
109
110/**
111 * Iterator for sign keys.
112 *
113 * @param cls closure
114 * @param ski the sign key issue
115 * @return #GNUNET_OK to continue to iterate,
116 * #GNUNET_NO to stop iteration with no error,
117 * #GNUNET_SYSERR to abort iteration with error!
118 */
119typedef int (*TALER_MINT_SignkeyIterator)(void *cls,
120 const struct TALER_MINT_SignKeyIssue *ski);
121
122/**
123 * Iterator for denomination keys.
124 *
125 * @param cls closure
126 * @param dki the denomination key issue
127 * @param alias coin alias
128 * @return #GNUNET_OK to continue to iterate,
129 * #GNUNET_NO to stop iteration with no error,
130 * #GNUNET_SYSERR to abort iteration with error!
131 */
132typedef int (*TALER_MINT_DenomkeyIterator)(void *cls,
133 const char *alias,
134 const struct TALER_MINT_DenomKeyIssue *dki);
135
136
137
138/**
139 * FIXME
140 */
141int
142TALER_MINT_signkeys_iterate (const char *mint_base_dir,
143 TALER_MINT_SignkeyIterator it, void *cls);
144
145
146/**
147 * FIXME
148 */
149int
150TALER_MINT_denomkeys_iterate (const char *mint_base_dir,
151 TALER_MINT_DenomkeyIterator it, void *cls);
152
153
154/**
155 * Exports a denomination key to the given file
156 *
157 * @param filename the file where to write the denomination key
158 * @param dki the denomination key
159 * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
160 */
161int
162TALER_MINT_write_denom_key (const char *filename,
163 const struct TALER_MINT_DenomKeyIssue *dki);
164
165
166/**
167 * Import a denomination key from the given file
168 *
169 * @param filename the file to import the key from
170 * @param dki pointer to return the imported denomination key
171 * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
172 */
173int
174TALER_MINT_read_denom_key (const char *filename,
175 struct TALER_MINT_DenomKeyIssue *dki);
176
177
178/**
179 * Load the configuration for the mint in the given
180 * directory.
181 *
182 * @param mint_base_dir the mint's base directory
183 * @return the mint configuratin, or NULL on error
184 */
185struct GNUNET_CONFIGURATION_Handle *
186TALER_MINT_config_load (const char *mint_base_dir);
187
188
189int
190TALER_TALER_DB_extract_amount (PGresult *result, unsigned int row,
191 int indices[3], struct TALER_Amount *denom);
192
193int
194TALER_TALER_DB_extract_amount_nbo (PGresult *result, unsigned int row,
195 int indices[3], struct TALER_AmountNBO *denom_nbo);
196
197#endif /* _MINT_H */
198
diff --git a/src/mint/mint_api.c b/src/mint/mint_api.c
new file mode 100644
index 000000000..b8d42b274
--- /dev/null
+++ b/src/mint/mint_api.c
@@ -0,0 +1,1121 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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
15 <http://www.gnu.org/licenses/>
16*/
17
18/**
19 * @file mint/mint_api.c
20 * @brief Implementation of the client interface to mint's HTTP API
21 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
22 */
23
24#include "platform.h"
25#include <curl/curl.h>
26#include <jansson.h>
27#include <gnunet/gnunet_util_lib.h>
28#include "taler_mint_service.h"
29#include "taler_signatures.h"
30#include "mint.h"
31
32#define CURL_STRERROR(TYPE, FUNCTION, CODE) \
33 GNUNET_log (TYPE, "cURL function `%s' has failed at `%s:%d' with error: %s", \
34 FUNCTION, __FILE__, __LINE__, curl_easy_strerror (CODE));
35
36
37
38/**
39 * Print JSON parsing related error information
40 */
41#define JSON_WARN(error) \
42 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
43 "JSON parsing failed at %s:%u: %s (%s)", \
44 __FILE__, __LINE__, error.text, error.source)
45
46/**
47 * Failsafe flag
48 */
49static int fail;
50
51/**
52 * Context
53 */
54struct TALER_MINT_Context
55{
56 /**
57 * CURL multi handle
58 */
59 CURLM *multi;
60
61 /**
62 * CURL share handle
63 */
64 CURLSH *share;
65
66 /**
67 * Perform task handle
68 */
69 struct GNUNET_SCHEDULER_Task *perform_task;
70};
71
72/**
73 * Type of requests we currently have
74 */
75enum RequestType
76{
77 /**
78 * No request
79 */
80 REQUEST_TYPE_NONE,
81
82 /**
83 * Current request is to receive mint's keys
84 */
85 REQUEST_TYPE_KEYSGET,
86
87 /**
88 * Current request is to submit a deposit permission and get its status
89 */
90 REQUEST_TYPE_DEPOSIT
91};
92
93
94/**
95 * Handle to the mint
96 */
97struct TALER_MINT_Handle
98{
99 /**
100 * The context of this handle
101 */
102 struct TALER_MINT_Context *ctx;
103
104 /**
105 * The hostname of the mint
106 */
107 char *hostname;
108
109 /**
110 * The CURL handle
111 */
112 CURL *curl;
113
114 /**
115 * Error buffer for CURL
116 */
117 char emsg[CURL_ERROR_SIZE];
118
119 /**
120 * Download buffer
121 */
122 void *buf;
123
124 /**
125 * The currently active request
126 */
127 union {
128 /**
129 * Used to denote no request if set to NULL
130 */
131 void *none;
132
133 /**
134 * Denom keys get request if REQUEST_TYPE_KEYSGET
135 */
136 struct TALER_MINT_KeysGetHandle *keys_get;
137
138 /**
139 * Deposit request if REQUEST_TYPE_DEPOSIT
140 */
141 struct TALER_MINT_DepositHandle *deposit;
142 } req;
143
144 /**
145 * The size of the download buffer
146 */
147 size_t buf_size;
148
149 /**
150 * Active request type
151 */
152 enum RequestType req_type;
153
154 /**
155 * The service port of the mint
156 */
157 uint16_t port;
158
159 /**
160 * Are we connected to the mint?
161 */
162 uint8_t connected;
163
164};
165
166
167/**
168 * A handle to get the keys of a mint
169 */
170struct TALER_MINT_KeysGetHandle
171{
172 /**
173 * The connection to mint this request handle will use
174 */
175 struct TALER_MINT_Handle *mint;
176
177 /**
178 * The url for this handle
179 */
180 char *url;
181
182 TALER_MINT_KeysGetCallback cb;
183 void *cls;
184
185 TALER_MINT_ContinuationCallback cont_cb;
186 void *cont_cls;
187};
188
189
190/**
191 * A handle to submit a deposit permission and get its status
192 */
193struct TALER_MINT_DepositHandle
194{
195 /**
196 *The connection to mint this request handle will use
197 */
198 struct TALER_MINT_Handle *mint;
199
200 /**
201 * The url for this handle
202 */
203 char *url;
204
205 TALER_MINT_DepositResultCallback cb;
206 void *cls;
207
208 char *json_enc;
209
210 struct curl_slist *headers;
211
212};
213
214
215/**
216 * Parses the timestamp encoded as ASCII string as UNIX timstamp.
217 *
218 * @param abs successfully parsed timestamp will be returned thru this parameter
219 * @param tstamp_enc the ASCII encoding of the timestamp
220 * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
221 */
222static int
223parse_timestamp (struct GNUNET_TIME_Absolute *abs, const char *tstamp_enc)
224{
225 unsigned long tstamp;
226
227 if (1 != sscanf (tstamp_enc, "%lu", &tstamp))
228 return GNUNET_SYSERR;
229 *abs = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get_zero_ (),
230 GNUNET_TIME_relative_multiply
231 (GNUNET_TIME_UNIT_SECONDS, tstamp));
232 return GNUNET_OK;
233}
234
235
236#define EXITIF(cond) \
237 do { \
238 if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
239 } while (0)
240
241
242
243static int
244parse_json_signkey (struct TALER_MINT_SigningPublicKey **_sign_key,
245 json_t *sign_key_obj,
246 struct GNUNET_CRYPTO_EddsaPublicKey *master_key)
247{
248 json_t *valid_from_obj;
249 json_t *valid_until_obj;
250 json_t *key_obj;
251 json_t *sig_obj;
252 const char *valid_from_enc;
253 const char *valid_until_enc;
254 const char *key_enc;
255 const char *sig_enc;
256 struct TALER_MINT_SigningPublicKey *sign_key;
257 struct TALER_MINT_SignKeyIssue sign_key_issue;
258 struct GNUNET_CRYPTO_EddsaSignature sig;
259 struct GNUNET_TIME_Absolute valid_from;
260 struct GNUNET_TIME_Absolute valid_until;
261
262 EXITIF (JSON_OBJECT != json_typeof (sign_key_obj));
263 EXITIF (NULL == (valid_from_obj = json_object_get (sign_key_obj,
264 "stamp_start")));
265 EXITIF (NULL == (valid_until_obj = json_object_get (sign_key_obj,
266 "stamp_expire")));
267 EXITIF (NULL == (key_obj = json_object_get (sign_key_obj, "key")));
268 EXITIF (NULL == (sig_obj = json_object_get (sign_key_obj, "master_sig")));
269 EXITIF (NULL == (valid_from_enc = json_string_value (valid_from_obj)));
270 EXITIF (NULL == (valid_until_enc = json_string_value (valid_until_obj)));
271 EXITIF (NULL == (key_enc = json_string_value (key_obj)));
272 EXITIF (NULL == (sig_enc = json_string_value (sig_obj)));
273 EXITIF (GNUNET_SYSERR == parse_timestamp (&valid_from,
274 valid_from_enc));
275 EXITIF (GNUNET_SYSERR == parse_timestamp (&valid_until,
276 valid_until_enc));
277 EXITIF (52 != strlen (key_enc)); /* strlen(base32(char[32])) = 52 */
278 EXITIF (103 != strlen (sig_enc)); /* strlen(base32(char[64])) = 103 */
279 EXITIF (GNUNET_OK != GNUNET_STRINGS_string_to_data (sig_enc, 103,
280 &sig, sizeof (sig)));
281 (void) memset (&sign_key_issue, 0, sizeof (sign_key_issue));
282 EXITIF (GNUNET_SYSERR ==
283 GNUNET_CRYPTO_eddsa_public_key_from_string (key_enc,
284 52,
285 &sign_key_issue.signkey_pub));
286 sign_key_issue.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNKEY);
287 sign_key_issue.purpose.size =
288 htonl (sizeof (sign_key_issue)
289 - offsetof (struct TALER_MINT_SignKeyIssue, purpose));
290 sign_key_issue.master_pub = *master_key;
291 sign_key_issue.start = GNUNET_TIME_absolute_hton (valid_from);
292 sign_key_issue.expire = GNUNET_TIME_absolute_hton (valid_until);
293 EXITIF (GNUNET_OK !=
294 GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNKEY,
295 &sign_key_issue.purpose,
296 &sig,
297 master_key));
298 sign_key = GNUNET_new (struct TALER_MINT_SigningPublicKey);
299 sign_key->valid_from = valid_from;
300 sign_key->valid_until = valid_until;
301 sign_key->key = sign_key_issue.signkey_pub;
302 *_sign_key = sign_key;
303 return GNUNET_OK;
304
305 EXITIF_exit:
306 return GNUNET_SYSERR;
307}
308
309
310static int
311parse_json_amount (json_t *amount_obj, struct TALER_Amount *amt)
312{
313 json_t *obj;
314 const char *currency_str;
315 int value;
316 int fraction;
317
318 EXITIF (NULL == (obj = json_object_get (amount_obj, "currency")));
319 EXITIF (NULL == (currency_str = json_string_value (obj)));
320 EXITIF (NULL == (obj = json_object_get (amount_obj, "value")));
321 EXITIF (JSON_INTEGER != json_typeof (obj));
322 EXITIF (0 > (value = json_integer_value (obj)));
323 EXITIF (NULL == (obj = json_object_get (amount_obj, "fraction")));
324 EXITIF (JSON_INTEGER != json_typeof (obj));
325 EXITIF (0 > (fraction = json_integer_value (obj)));
326 (void) memset (amt->currency, 0, sizeof (amt->currency));
327 (void) strncpy (amt->currency, currency_str, sizeof (amt->currency) - 1);
328 amt->value = (uint32_t) value;
329 amt->fraction = (uint32_t) fraction;
330 return GNUNET_OK;
331
332 EXITIF_exit:
333 return GNUNET_SYSERR;
334}
335
336static int
337parse_json_denomkey (struct TALER_MINT_DenomPublicKey **_denom_key,
338 json_t *denom_key_obj,
339 struct GNUNET_CRYPTO_EddsaPublicKey *master_key)
340{
341 json_t *obj;
342 const char *sig_enc;
343 const char *deposit_valid_until_enc;
344 const char *withdraw_valid_until_enc;
345 const char *valid_from_enc;
346 const char *key_enc;
347 struct TALER_MINT_DenomPublicKey *denom_key;
348 struct GNUNET_TIME_Absolute valid_from;
349 struct GNUNET_TIME_Absolute withdraw_valid_until;
350 struct GNUNET_TIME_Absolute deposit_valid_until;
351 struct TALER_Amount value;
352 struct TALER_Amount fee_withdraw;
353 struct TALER_Amount fee_deposit;
354 struct TALER_Amount fee_refresh;
355 struct TALER_MINT_DenomKeyIssue denom_key_issue;
356 struct GNUNET_CRYPTO_EddsaSignature sig;
357
358 EXITIF (JSON_OBJECT != json_typeof (denom_key_obj));
359 EXITIF (NULL == (obj = json_object_get (denom_key_obj, "master_sig")));
360 EXITIF (NULL == (sig_enc = json_string_value (obj)));
361 EXITIF (103 != strlen (sig_enc));
362 EXITIF (GNUNET_OK != GNUNET_STRINGS_string_to_data (sig_enc, 103,
363 &sig, sizeof (sig)));
364 EXITIF (NULL == (obj = json_object_get (denom_key_obj, "stamp_expire_deposit")));
365 EXITIF (NULL == (deposit_valid_until_enc = json_string_value (obj)));
366 EXITIF (NULL == (obj = json_object_get (denom_key_obj, "stamp_expire_withdraw")));
367 EXITIF (NULL == (withdraw_valid_until_enc = json_string_value (obj)));
368 EXITIF (NULL == (obj = json_object_get (denom_key_obj, "stamp_start")));
369 EXITIF (NULL == (valid_from_enc = json_string_value (obj)));
370 EXITIF (NULL == (obj = json_object_get (denom_key_obj, "denom_pub")));
371 EXITIF (NULL == (key_enc = json_string_value (obj)));
372 EXITIF (52 != strlen (key_enc)); /* strlen(base32(char[32])) = 52 */
373 EXITIF (GNUNET_SYSERR == parse_timestamp (&valid_from, valid_from_enc));
374 EXITIF (GNUNET_SYSERR == parse_timestamp (&withdraw_valid_until,
375 withdraw_valid_until_enc));
376 EXITIF (GNUNET_SYSERR == parse_timestamp (&deposit_valid_until,
377 deposit_valid_until_enc));
378
379 (void) memset (&denom_key_issue, 0, sizeof (denom_key_issue));
380 EXITIF (GNUNET_OK != GNUNET_STRINGS_string_to_data (key_enc, 52,
381 &denom_key_issue.denom_pub,
382 sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)));
383 EXITIF (NULL == (obj = json_object_get (denom_key_obj, "value")));
384 EXITIF (GNUNET_SYSERR == parse_json_amount (obj, &value));
385 EXITIF (NULL == (obj = json_object_get (denom_key_obj, "fee_withdraw")));
386 EXITIF (GNUNET_SYSERR == parse_json_amount (obj, &fee_withdraw));
387 EXITIF (NULL == (obj = json_object_get (denom_key_obj, "fee_deposit")));
388 EXITIF (GNUNET_SYSERR == parse_json_amount (obj, &fee_deposit));
389 EXITIF (NULL == (obj = json_object_get (denom_key_obj, "fee_refresh")));
390 EXITIF (GNUNET_SYSERR == parse_json_amount (obj, &fee_refresh));
391 denom_key_issue.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOM);
392 denom_key_issue.purpose.size = htonl
393 (sizeof (struct TALER_MINT_DenomKeyIssue) -
394 offsetof (struct TALER_MINT_DenomKeyIssue, purpose));
395 denom_key_issue.master = *master_key;
396 denom_key_issue.start = GNUNET_TIME_absolute_hton (valid_from);
397 denom_key_issue.expire_withdraw = GNUNET_TIME_absolute_hton (withdraw_valid_until);
398 denom_key_issue.expire_spend = GNUNET_TIME_absolute_hton (deposit_valid_until);
399 denom_key_issue.value = TALER_amount_hton (value);
400 denom_key_issue.fee_withdraw = TALER_amount_hton (fee_withdraw);
401 denom_key_issue.fee_deposit = TALER_amount_hton (fee_deposit);
402 denom_key_issue.fee_refresh = TALER_amount_hton (fee_refresh);
403 EXITIF (GNUNET_SYSERR ==
404 GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_DENOM,
405 &denom_key_issue.purpose,
406 &sig,
407 master_key));
408 denom_key = GNUNET_new (struct TALER_MINT_DenomPublicKey);
409 denom_key->key = denom_key_issue.denom_pub;
410 denom_key->valid_from = valid_from;
411 denom_key->withdraw_valid_until = withdraw_valid_until;
412 denom_key->deposit_valid_until = deposit_valid_until;
413 denom_key->value = value;
414 denom_key->fee_withdraw = fee_withdraw;
415 denom_key->fee_deposit = fee_deposit;
416 denom_key->fee_refresh = fee_refresh;
417 *_denom_key = denom_key;
418 return GNUNET_OK;
419
420 EXITIF_exit:
421 return GNUNET_SYSERR;
422}
423
424static int
425parse_response_keys_get (const char *in, size_t size,
426 struct TALER_MINT_SigningPublicKey ***_sign_keys,
427 unsigned int *_n_sign_keys,
428 struct TALER_MINT_DenomPublicKey ***_denom_keys,
429 unsigned int *_n_denom_keys)
430{
431 json_t *resp_obj;
432 struct TALER_MINT_DenomPublicKey **denom_keys;
433 struct GNUNET_CRYPTO_EddsaPublicKey master_key;
434 struct GNUNET_TIME_Absolute list_issue_date;
435 struct TALER_MINT_SigningPublicKey **sign_keys;
436 unsigned int n_denom_keys;
437 unsigned int n_sign_keys;
438 json_error_t error;
439 unsigned int index;
440 int OK;
441
442 denom_keys = NULL;
443 n_denom_keys = 0;
444 sign_keys = NULL;
445 n_sign_keys = 0;
446 OK = 0;
447 resp_obj = json_loadb (in, size,
448 JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
449 &error);
450 if (NULL == resp_obj)
451 {
452 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
453 "Unable to parse received data as JSON object\n");
454 return GNUNET_SYSERR;
455 }
456
457 EXITIF (JSON_OBJECT != json_typeof (resp_obj));
458 {
459 /* parse the master public key */
460 json_t *master_key_obj;
461 const char *master_key_enc;
462
463 EXITIF (NULL == (master_key_obj = json_object_get (resp_obj, "master_pub")));
464 EXITIF (NULL == (master_key_enc = json_string_value (master_key_obj)));
465 EXITIF (52 != strlen (master_key_enc)); /* strlen(base32(char[32])) = 52 */
466 EXITIF (GNUNET_OK !=
467 GNUNET_CRYPTO_eddsa_public_key_from_string (master_key_enc,
468 52,
469 &master_key));
470 }
471 {
472 /* parse the issue date of the response */
473 json_t *list_issue_date_obj;
474 const char *tstamp_enc;
475
476 EXITIF (NULL == (list_issue_date_obj =
477 json_object_get(resp_obj, "list_issue_date")));
478 EXITIF (NULL == (tstamp_enc = json_string_value (list_issue_date_obj)));
479 EXITIF (GNUNET_SYSERR == parse_timestamp (&list_issue_date, tstamp_enc));
480 }
481 {
482 /* parse the signing keys */
483 json_t *sign_keys_array;
484 json_t *sign_key_obj;
485
486 EXITIF (NULL == (sign_keys_array =
487 json_object_get (resp_obj, "signkeys")));
488 EXITIF (JSON_ARRAY != json_typeof (sign_keys_array));
489 EXITIF (0 == (n_sign_keys = json_array_size (sign_keys_array)));
490 sign_keys = GNUNET_malloc (sizeof (struct TALER_MINT_SigningPublicKey *)
491 * (n_sign_keys + 1));
492 index = 0;
493 json_array_foreach (sign_keys_array, index, sign_key_obj) {
494 EXITIF (GNUNET_SYSERR == parse_json_signkey (&sign_keys[index],
495 sign_key_obj,
496 &master_key));
497 }
498 }
499 {
500 /* parse the denomination keys */
501 json_t *denom_keys_array;
502 json_t *denom_key_obj;
503
504 EXITIF (NULL == (denom_keys_array = json_object_get (resp_obj, "denoms")));
505 EXITIF (JSON_ARRAY != json_typeof (denom_keys_array));
506 EXITIF (0 == (n_denom_keys = json_array_size (denom_keys_array)));
507 denom_keys = GNUNET_malloc (sizeof (struct TALER_MINT_DenomPublicKey *)
508 * (n_denom_keys + 1));
509 index = 0;
510 json_array_foreach (denom_keys_array, index, denom_key_obj) {
511 EXITIF (GNUNET_SYSERR == parse_json_denomkey (&denom_keys[index],
512 denom_key_obj,
513 &master_key));
514 }
515 }
516 OK = 1;
517
518 EXITIF_exit:
519 json_decref (resp_obj);
520 if (!OK)
521 {
522 if (NULL != sign_keys)
523 {
524 for (index=0; NULL != sign_keys[index]; index++)
525 GNUNET_free_non_null (sign_keys[index]);
526 GNUNET_free (sign_keys);
527 }
528 if (NULL != denom_keys)
529 {
530 for (index=0; NULL != denom_keys[index]; index++)
531 GNUNET_free_non_null (denom_keys[index]);
532 GNUNET_free (denom_keys);
533 }
534 return GNUNET_SYSERR;
535 }
536
537 *_sign_keys = sign_keys;
538 *_n_sign_keys = n_sign_keys;
539 *_denom_keys = denom_keys;
540 *_n_denom_keys = n_denom_keys;
541 return GNUNET_OK;
542}
543
544
545int
546parse_deposit_response (void *buf, size_t size, int *r_status, json_t **r_obj)
547{
548 json_t *obj;
549 const char *status_str;
550 json_error_t error;
551
552 status_str = NULL;
553 obj = NULL;
554 obj = json_loadb (buf, size,
555 JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, &error);
556 if (NULL == obj)
557 {
558 JSON_WARN (error);
559 return GNUNET_SYSERR;
560 }
561 EXITIF (-1 == json_unpack (obj, "{s:s}", "status", &status_str));
562 LOG_DEBUG ("Received deposit response: %s from mint\n", status_str);
563 if (0 == strcmp ("DEPOSIT_OK", status_str))
564 *r_status = 1;
565 else if (0 == strcmp ("DEPOSIT_QUEUED", status_str))
566 *r_status = 2;
567 else
568 *r_status = 0;
569 *r_obj = obj;
570
571 return GNUNET_OK;
572 EXITIF_exit:
573 json_decref (obj);
574 return GNUNET_SYSERR;
575}
576
577#undef EXITIF
578
579static void
580mint_connect (struct TALER_MINT_Handle *mint)
581{
582 struct TALER_MINT_Context *ctx = mint->ctx;
583
584 GNUNET_assert (0 == mint->connected);
585 GNUNET_assert (CURLM_OK == curl_multi_add_handle (ctx->multi, mint->curl));
586 mint->connected = GNUNET_YES;
587}
588
589static void
590mint_disconnect (struct TALER_MINT_Handle *mint)
591{
592 struct TALER_MINT_Context *ctx = mint->ctx;
593
594 GNUNET_assert (GNUNET_YES == mint->connected);
595 GNUNET_break (CURLM_OK == curl_multi_remove_handle (ctx->multi,
596 mint->curl));
597 mint->connected = GNUNET_NO;
598 GNUNET_free_non_null (mint->buf);
599 mint->buf = NULL;
600 mint->buf_size = 0;
601 mint->req_type = REQUEST_TYPE_NONE;
602 mint->req.none = NULL;
603}
604
605static void
606cleanup_keys_get (struct TALER_MINT_KeysGetHandle *gh)
607{
608 GNUNET_free (gh->url);
609 GNUNET_free (gh);
610}
611
612static void
613cleanup_deposit (struct TALER_MINT_DepositHandle *dh)
614{
615 curl_slist_free_all (dh->headers);
616 GNUNET_free_non_null (dh->json_enc);
617 GNUNET_free (dh->url);
618 GNUNET_free (dh);
619}
620
621static void
622request_failed (struct TALER_MINT_Handle *mint, long resp_code)
623{
624 switch (mint->req_type)
625 {
626 case REQUEST_TYPE_NONE:
627 GNUNET_assert (0);
628 break;
629 case REQUEST_TYPE_KEYSGET:
630 {
631 struct TALER_MINT_KeysGetHandle *gh = mint->req.keys_get;
632 TALER_MINT_ContinuationCallback cont_cb;
633 void *cont_cls;
634 GNUNET_assert (NULL != gh);
635 cont_cb = gh->cont_cb;
636 cont_cls = gh->cont_cls;
637 cleanup_keys_get (gh);
638 mint_disconnect (mint);
639 cont_cb (cont_cls, mint->emsg);
640 }
641 break;
642 case REQUEST_TYPE_DEPOSIT:
643 {
644 struct TALER_MINT_DepositHandle *dh = mint->req.deposit;
645 TALER_MINT_DepositResultCallback cb = dh->cb;
646 void *cls = dh->cls;
647 GNUNET_assert (NULL != dh);
648 cleanup_deposit (dh);
649 mint_disconnect (mint);
650 cb (cls, 0, NULL, mint->emsg);
651 }
652 break;
653 }
654}
655
656static void
657request_succeeded (struct TALER_MINT_Handle *mint, long resp_code)
658{
659 char *emsg;
660
661 emsg = NULL;
662 switch (mint->req_type)
663 {
664 case REQUEST_TYPE_NONE:
665 GNUNET_assert (0);
666 break;
667 case REQUEST_TYPE_KEYSGET:
668 {
669 struct TALER_MINT_KeysGetHandle *gh = mint->req.keys_get;
670 TALER_MINT_ContinuationCallback cont_cb;
671 void *cont_cls;
672 struct TALER_MINT_SigningPublicKey **sign_keys;
673 struct TALER_MINT_DenomPublicKey **denom_keys;
674 unsigned int n_sign_keys;
675 unsigned int n_denom_keys;
676
677 GNUNET_assert (NULL != gh);
678 cont_cb = gh->cont_cb;
679 cont_cls = gh->cont_cls;
680 if (200 == resp_code)
681 {
682 /* parse JSON object from the mint->buf which is of size mint->buf_size */
683 if (GNUNET_OK ==
684 parse_response_keys_get (mint->buf, mint->buf_size,
685 &sign_keys, &n_sign_keys,
686 &denom_keys, &n_denom_keys))
687 gh->cb (gh->cls, sign_keys, denom_keys);
688 else
689 emsg = GNUNET_strdup ("Error parsing response");
690 }
691 else
692 GNUNET_asprintf (&emsg, "Failed with response code: %ld", resp_code);
693 cleanup_keys_get (gh);
694 mint_disconnect (mint);
695 cont_cb (cont_cls, emsg);
696 }
697 break;
698 case REQUEST_TYPE_DEPOSIT:
699 {
700 struct TALER_MINT_DepositHandle *dh = mint->req.deposit;
701 TALER_MINT_DepositResultCallback cb;
702 void *cls;
703 int status;
704 json_t *obj;
705
706 GNUNET_assert (NULL != dh);
707 obj = NULL;
708 cb = dh->cb;
709 cls = dh->cls;
710 status = 0;
711 if (200 == resp_code)
712 {
713 /* parse JSON object from the mint->buf which is of size mint->buf_size */
714 if (GNUNET_OK !=
715 parse_deposit_response (mint->buf, mint->buf_size,
716 &status, &obj))
717 emsg = GNUNET_strdup ("Error parsing response");
718 }
719 else
720 GNUNET_asprintf (&emsg, "Failed with response code: %ld", resp_code);
721 cleanup_deposit (dh);
722 mint_disconnect (mint);
723 cb (cls, status, obj, emsg);
724 }
725 break;
726 }
727 GNUNET_free_non_null (emsg);
728}
729
730
731static void
732do_perform (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
733
734static void
735perform (struct TALER_MINT_Context *ctx)
736{
737 fd_set fd_rs;
738 fd_set fd_ws;
739 struct GNUNET_NETWORK_FDSet rs;
740 struct GNUNET_NETWORK_FDSet ws;
741 CURLMsg *cmsg;
742 struct TALER_MINT_Handle *mint;
743 long timeout;
744 long resp_code;
745 static unsigned int n_old;
746 int n_running;
747 int n_completed;
748 int max_fd;
749
750 n_completed = 0;
751 curl_multi_perform (ctx->multi, &n_running);
752 GNUNET_assert (0 <= n_running);
753 if ((0 == n_running) || (n_running < n_old))
754 {
755 /* some requests were completed -- handle them */
756 while (NULL != (cmsg = curl_multi_info_read (ctx->multi, &n_completed)))
757 {
758 GNUNET_break (CURLMSG_DONE == cmsg->msg); /* curl only has CURLMSG_DONE */
759 GNUNET_assert (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
760 CURLINFO_PRIVATE,
761 (char *) &mint));
762 GNUNET_assert (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle,
763 CURLINFO_RESPONSE_CODE,
764 &resp_code));
765 GNUNET_assert (ctx == mint->ctx); /* did we get the correct one? */
766 if (CURLE_OK == cmsg->data.result)
767 request_succeeded (mint, resp_code);
768 else
769 request_failed (mint, resp_code);
770 }
771 }
772 n_old = n_running;
773 /* reschedule perform() */
774 if (0 != n_old)
775 {
776 FD_ZERO (&fd_rs);
777 FD_ZERO (&fd_ws);
778 GNUNET_assert (CURLM_OK == curl_multi_fdset (ctx->multi,
779 &fd_rs,
780 &fd_ws,
781 NULL,
782 &max_fd));
783 if (-1 == max_fd)
784 {
785 ctx->perform_task = GNUNET_SCHEDULER_add_delayed
786 (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100),
787 &do_perform, ctx);
788 return;
789 }
790 GNUNET_assert (CURLM_OK == curl_multi_timeout (ctx->multi, &timeout));
791 if (-1 == timeout)
792 {
793 timeout = 1000 * 60 * 5;
794 }
795 GNUNET_NETWORK_fdset_zero (&rs);
796 GNUNET_NETWORK_fdset_zero (&ws);
797 GNUNET_NETWORK_fdset_copy_native (&rs, &fd_rs, max_fd + 1);
798 GNUNET_NETWORK_fdset_copy_native (&ws, &fd_ws, max_fd + 1);
799 ctx->perform_task = GNUNET_SCHEDULER_add_select
800 (GNUNET_SCHEDULER_PRIORITY_KEEP,
801 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, timeout),
802 &rs, &ws,
803 &do_perform, ctx);
804 }
805}
806
807
808static void
809do_perform (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
810{
811 struct TALER_MINT_Context *ctx = cls;
812
813 GNUNET_assert (NULL != ctx->perform_task);
814 ctx->perform_task = NULL;
815 perform (ctx);
816}
817
818static void
819perform_now (struct TALER_MINT_Context *ctx)
820{
821 if (NULL != ctx->perform_task)
822 {
823 GNUNET_SCHEDULER_cancel (ctx->perform_task);
824 ctx->perform_task = NULL;
825 }
826 ctx->perform_task = GNUNET_SCHEDULER_add_now (&do_perform, ctx);
827}
828
829
830/* This function gets called by libcurl as soon as there is data received that */
831/* needs to be saved. The size of the data pointed to by ptr is size */
832/* multiplied with nmemb, it will not be zero terminated. Return the number */
833/* of bytes actually taken care of. If that amount differs from the amount passed */
834/* to your function, it'll signal an error to the library. This will abort the */
835/* transfer and return CURLE_WRITE_ERROR. */
836
837/* From 7.18.0, the function can return CURL_WRITEFUNC_PAUSE which then will */
838/* cause writing to this connection to become paused. See */
839/* curl_easy_pause(3) for further details. */
840
841/* This function may be called with zero bytes data if the transferred file is */
842/* empty. */
843
844/* Set this option to NULL to get the internal default function. The internal */
845/* default function will write the data to the FILE * given with */
846/* CURLOPT_WRITEDATA. */
847
848/* Set the userdata argument with the CURLOPT_WRITEDATA option. */
849
850/* The callback function will be passed as much data as possible in all invokes, */
851/* but you cannot possibly make any assumptions. It may be one byte, it may be */
852/* thousands. The maximum amount of body data that can be passed to the write */
853/* callback is defined in the curl.h header file: CURL_MAX_WRITE_SIZE (the usual */
854/* default is 16K). If you however have CURLOPT_HEADER set, which sends */
855/* header data to the write callback, you can get up to */
856/* CURL_MAX_HTTP_HEADER bytes of header data passed into it. This usually */
857/* means 100K. */
858static size_t
859download (char *bufptr, size_t size, size_t nitems, void *cls)
860{
861 struct TALER_MINT_Handle *mint = cls;
862 size_t msize;
863 void *buf;
864
865 if (0 == size * nitems)
866 {
867 /* file is empty */
868 return 0;
869 }
870 msize = size * nitems;
871 mint->buf = GNUNET_realloc (mint->buf, mint->buf_size + msize);
872 buf = mint->buf + mint->buf_size;
873 memcpy (buf, bufptr, msize);
874 mint->buf_size += msize;
875 return msize;
876}
877
878
879/**
880 * Initialise a connection to the mint.
881 *
882 * @param ctx the context
883 * @param hostname the hostname of the mint
884 * @param port the point where the mint's HTTP service is running.
885 * @param mint_key the public key of the mint. This is used to verify the
886 * responses of the mint.
887 * @return the mint handle; NULL upon error
888 */
889struct TALER_MINT_Handle *
890TALER_MINT_connect (struct TALER_MINT_Context *ctx,
891 const char *hostname,
892 uint16_t port,
893 struct GNUNET_CRYPTO_EddsaPublicKey *mint_key)
894{
895 struct TALER_MINT_Handle *mint;
896
897 mint = GNUNET_new (struct TALER_MINT_Handle);
898 mint->ctx = ctx;
899 mint->hostname = GNUNET_strdup (hostname);
900 mint->port = (0 != port) ? port : 80;
901 mint->curl = curl_easy_init ();
902 GNUNET_assert (CURLE_OK ==
903 curl_easy_setopt (mint->curl, CURLOPT_SHARE, ctx->share));
904 GNUNET_assert (CURLE_OK ==
905 curl_easy_setopt (mint->curl, CURLOPT_ERRORBUFFER, mint->emsg));
906 GNUNET_assert (CURLE_OK ==
907 curl_easy_setopt (mint->curl, CURLOPT_WRITEFUNCTION, &download));
908 GNUNET_assert (CURLE_OK ==
909 curl_easy_setopt (mint->curl, CURLOPT_WRITEDATA, mint));
910 GNUNET_assert (CURLE_OK == curl_easy_setopt (mint->curl, CURLOPT_PRIVATE, mint));
911 return mint;
912}
913
914/**
915 * Disconnect from the mint
916 *
917 * @param mint the mint handle
918 */
919void
920TALER_MINT_disconnect (struct TALER_MINT_Handle *mint)
921{
922 if (GNUNET_YES == mint->connected)
923 mint_disconnect (mint);
924 curl_easy_cleanup (mint->curl);
925 GNUNET_free (mint->hostname);
926 GNUNET_free (mint);
927}
928
929/**
930 * Get the signing and denomination key of the mint.
931 *
932 * @param mint handle to the mint
933 * @param cb the callback to call with each retrieved denomination key
934 * @param cls closure for the above callback
935 * @param cont_cb the callback to call after completing this asynchronous call
936 * @param cont_cls the closure for the continuation callback
937 * @return a handle to this asynchronous call; NULL upon eror
938 */
939struct TALER_MINT_KeysGetHandle *
940TALER_MINT_keys_get (struct TALER_MINT_Handle *mint,
941 TALER_MINT_KeysGetCallback cb, void *cls,
942 TALER_MINT_ContinuationCallback cont_cb, void *cont_cls)
943{
944 struct TALER_MINT_KeysGetHandle *gh;
945
946 GNUNET_assert (REQUEST_TYPE_NONE == mint->req_type);
947 gh = GNUNET_new (struct TALER_MINT_KeysGetHandle);
948 gh->mint = mint;
949 mint->req_type = REQUEST_TYPE_KEYSGET;
950 mint->req.keys_get = gh;
951 gh->cb = cb;
952 gh->cls = cls;
953 gh->cont_cb = cont_cb;
954 gh->cont_cls = cont_cls;
955 GNUNET_asprintf (&gh->url, "http://%s:%hu/keys", mint->hostname, mint->port);
956 GNUNET_assert (CURLE_OK ==
957 curl_easy_setopt (mint->curl, CURLOPT_URL, gh->url));
958 if (GNUNET_NO == mint->connected)
959 mint_connect (mint);
960 perform_now (mint->ctx);
961 return gh;
962}
963
964
965/**
966 * Cancel the asynchronous call initiated by TALER_MINT_keys_get(). This
967 * should not be called if either of the @a TALER_MINT_KeysGetCallback or
968 * @a TALER_MINT_ContinuationCallback passed to TALER_MINT_keys_get() have
969 * been called.
970 *
971 * @param get the handle for retrieving the keys
972 */
973void
974TALER_MINT_keys_get_cancel (struct TALER_MINT_KeysGetHandle *get)
975{
976 struct TALER_MINT_Handle *mint = get->mint;
977
978 mint_disconnect (mint);
979 cleanup_keys_get (get);
980}
981
982/**
983 * Submit a deposit permission to the mint and get the mint's response
984 *
985 * @param mint the mint handle
986 * @param cb the callback to call when a reply for this request is available
987 * @param cls closure for the above callback
988 * @param deposit_obj the deposit permission received from the customer along
989 * with the wireformat JSON object
990 * @return a handle for this request; NULL if the JSON object could not be
991 * parsed or is of incorrect format or any other error. In this case,
992 * the callback is not called.
993 */
994struct TALER_MINT_DepositHandle *
995TALER_MINT_deposit_submit_json (struct TALER_MINT_Handle *mint,
996 TALER_MINT_DepositResultCallback cb,
997 void *cls,
998 json_t *deposit_obj)
999{
1000 struct TALER_MINT_DepositHandle *dh;
1001
1002 GNUNET_assert (REQUEST_TYPE_NONE == mint->req_type);
1003 dh = GNUNET_new (struct TALER_MINT_DepositHandle);
1004 dh->mint = mint;
1005 mint->req_type = REQUEST_TYPE_DEPOSIT;
1006 mint->req.deposit = dh;
1007 dh->cb = cb;
1008 dh->cls = cls;
1009 GNUNET_asprintf (&dh->url, "http://%s:%hu/deposit", mint->hostname, mint->port);
1010 GNUNET_assert (NULL != (dh->json_enc = json_dumps (deposit_obj, JSON_COMPACT)));
1011 GNUNET_assert (CURLE_OK ==
1012 curl_easy_setopt (mint->curl, CURLOPT_URL, dh->url));
1013 GNUNET_assert (CURLE_OK ==
1014 curl_easy_setopt (mint->curl, CURLOPT_POSTFIELDS,
1015 dh->json_enc));
1016 GNUNET_assert (CURLE_OK ==
1017 curl_easy_setopt (mint->curl, CURLOPT_POSTFIELDSIZE,
1018 strlen (dh->json_enc)));
1019 GNUNET_assert (NULL != (dh->headers =
1020 curl_slist_append (dh->headers, "Content-Type: application/json")));
1021 GNUNET_assert (CURLE_OK ==
1022 curl_easy_setopt (mint->curl, CURLOPT_HTTPHEADER, dh->headers));
1023 if (GNUNET_NO == mint->connected)
1024 mint_connect (mint);
1025 perform_now (mint->ctx);
1026 return dh;
1027}
1028
1029
1030/**
1031 * Cancel a deposit permission request. This function cannot be used on a
1032 * request handle if a response is already served for it.
1033 *
1034 * @param the deposit permission request handle
1035 */
1036void
1037TALER_MINT_deposit_submit_cancel (struct TALER_MINT_DepositHandle *deposit)
1038{
1039 struct TALER_MINT_Handle *mint = deposit->mint;
1040
1041 mint_disconnect (mint);
1042 cleanup_deposit (deposit);
1043}
1044
1045
1046/**
1047 * Initialise this library. This function should be called before using any of
1048 * the following functions.
1049 *
1050 * @return library context
1051 */
1052struct TALER_MINT_Context *
1053TALER_MINT_init ()
1054{
1055 struct TALER_MINT_Context *ctx;
1056 CURLM *multi;
1057 CURLSH *share;
1058
1059 if (fail)
1060 {
1061 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "cURL was not initialised properly\n");
1062 return NULL;
1063 }
1064 if (NULL == (multi = curl_multi_init ()))
1065 {
1066 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot create a cURL multi handle\n");
1067 return NULL;
1068 }
1069 if (NULL == (share = curl_share_init ()))
1070 {
1071 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot create a cURL share handle\n");
1072 return NULL;
1073 }
1074 ctx = GNUNET_new (struct TALER_MINT_Context);
1075 ctx->multi = multi;
1076 ctx->share = share;
1077 return ctx;
1078}
1079
1080
1081/**
1082 * Cleanup library initialisation resources. This function should be called
1083 * after using this library to cleanup the resources occupied during library's
1084 * initialisation.
1085 *
1086 * @param ctx the library context
1087 */
1088void
1089TALER_MINT_cleanup (struct TALER_MINT_Context *ctx)
1090{
1091 curl_share_cleanup (ctx->share);
1092 curl_multi_cleanup (ctx->multi);
1093 if (NULL != ctx->perform_task)
1094 {
1095 GNUNET_break (0); /* investigate why this happens */
1096 GNUNET_SCHEDULER_cancel (ctx->perform_task);
1097 }
1098 GNUNET_free (ctx);
1099}
1100
1101
1102__attribute__ ((constructor))
1103void
1104TALER_MINT_constructor__ (void)
1105{
1106 CURLcode ret;
1107 if (CURLE_OK != (ret = curl_global_init (CURL_GLOBAL_DEFAULT)))
1108 {
1109 CURL_STRERROR (GNUNET_ERROR_TYPE_ERROR, "curl_global_init", ret);
1110 fail = 1;
1111 }
1112}
1113
1114__attribute__ ((destructor))
1115void
1116TALER_MINT_destructor__ (void)
1117{
1118 if (fail)
1119 return;
1120 curl_global_cleanup ();
1121}
diff --git a/src/mint/mint_common.c b/src/mint/mint_common.c
new file mode 100644
index 000000000..4afbf072b
--- /dev/null
+++ b/src/mint/mint_common.c
@@ -0,0 +1,283 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file mint_common.c
19 * @brief Common functionality for the mint
20 * @author Florian Dold
21 * @author Benedikt Mueller
22 * @author Sree Harsha Totakura
23 */
24
25#include "platform.h"
26#include "mint.h"
27
28struct SignkeysIterateContext
29{
30 TALER_MINT_SignkeyIterator it;
31 void *it_cls;
32};
33
34
35struct DenomkeysIterateContext
36{
37 const char *alias;
38 TALER_MINT_DenomkeyIterator it;
39 void *it_cls;
40};
41
42
43static int
44signkeys_iterate_dir_iter (void *cls,
45 const char *filename)
46{
47
48 struct SignkeysIterateContext *skc = cls;
49 ssize_t nread;
50 struct TALER_MINT_SignKeyIssue issue;
51 nread = GNUNET_DISK_fn_read (filename,
52 &issue,
53 sizeof (struct TALER_MINT_SignKeyIssue));
54 if (nread != sizeof (struct TALER_MINT_SignKeyIssue))
55 {
56 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid signkey file: '%s'\n", filename);
57 return GNUNET_OK;
58 }
59 return skc->it (skc->it_cls, &issue);
60}
61
62
63int
64TALER_MINT_signkeys_iterate (const char *mint_base_dir,
65 TALER_MINT_SignkeyIterator it, void *cls)
66{
67 char *signkey_dir;
68 size_t len;
69 struct SignkeysIterateContext skc;
70
71 len = GNUNET_asprintf (&signkey_dir, ("%s" DIR_SEPARATOR_STR DIR_SIGNKEYS), mint_base_dir);
72 GNUNET_assert (len > 0);
73
74 skc.it = it;
75 skc.it_cls = cls;
76
77 return GNUNET_DISK_directory_scan (signkey_dir, &signkeys_iterate_dir_iter, &skc);
78}
79
80
81/**
82 * Import a denomination key from the given file
83 *
84 * @param filename the file to import the key from
85 * @param dki pointer to return the imported denomination key
86 * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
87 */
88int
89TALER_MINT_read_denom_key (const char *filename,
90 struct TALER_MINT_DenomKeyIssue *dki)
91{
92 uint64_t size;
93 size_t offset;
94 void *data;
95 struct TALER_RSA_PrivateKey *priv;
96 int ret;
97
98 ret = GNUNET_SYSERR;
99 data = NULL;
100 offset = sizeof (struct TALER_MINT_DenomKeyIssue)
101 - offsetof (struct TALER_MINT_DenomKeyIssue, signature);
102 if (GNUNET_OK != GNUNET_DISK_file_size (filename,
103 &size,
104 GNUNET_YES,
105 GNUNET_YES))
106 goto cleanup;
107 if (size <= offset)
108 {
109 GNUNET_break (0);
110 goto cleanup;
111 }
112 data = GNUNET_malloc (size);
113 if (size != GNUNET_DISK_fn_read (filename,
114 data,
115 size))
116 goto cleanup;
117 if (NULL == (priv = TALER_RSA_decode_key (data + offset, size - offset)))
118 goto cleanup;
119 dki->denom_priv = priv;
120 (void) memcpy (&dki->signature, data, offset);
121 ret = GNUNET_OK;
122
123 cleanup:
124 GNUNET_free_non_null (data);
125 return ret;
126}
127
128
129/**
130 * Exports a denomination key to the given file
131 *
132 * @param filename the file where to write the denomination key
133 * @param dki the denomination key
134 * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
135 */
136int
137TALER_MINT_write_denom_key (const char *filename,
138 const struct TALER_MINT_DenomKeyIssue *dki)
139{
140 struct TALER_RSA_PrivateKeyBinaryEncoded *priv_enc;
141 struct GNUNET_DISK_FileHandle *fh;
142 ssize_t wrote;
143 size_t wsize;
144 int ret;
145
146 fh = NULL;
147 priv_enc = NULL;
148 ret = GNUNET_SYSERR;
149 if (NULL == (fh = GNUNET_DISK_file_open
150 (filename,
151 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_TRUNCATE,
152 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)))
153 goto cleanup;
154 if (NULL == (priv_enc = TALER_RSA_encode_key (dki->denom_priv)))
155 goto cleanup;
156 wsize = sizeof (struct TALER_MINT_DenomKeyIssue)
157 - offsetof (struct TALER_MINT_DenomKeyIssue, signature);
158 if (GNUNET_SYSERR == (wrote = GNUNET_DISK_file_write (fh,
159 &dki->signature,
160 wsize)))
161 goto cleanup;
162 if (wrote != wsize)
163 goto cleanup;
164 wsize = ntohs (priv_enc->len);
165 if (GNUNET_SYSERR == (wrote = GNUNET_DISK_file_write (fh,
166 priv_enc,
167 wsize)))
168 goto cleanup;
169 if (wrote != wsize)
170 goto cleanup;
171 ret = GNUNET_OK;
172 cleanup:
173 GNUNET_free_non_null (priv_enc);
174 if (NULL != fh)
175 (void) GNUNET_DISK_file_close (fh);
176 return ret;
177}
178
179
180static int
181denomkeys_iterate_keydir_iter (void *cls,
182 const char *filename)
183{
184
185 struct DenomkeysIterateContext *dic = cls;
186 struct TALER_MINT_DenomKeyIssue issue;
187
188 if (GNUNET_OK != TALER_MINT_read_denom_key (filename, &issue))
189 {
190 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid denomkey file: '%s'\n", filename);
191 return GNUNET_OK;
192 }
193 return dic->it (dic->it_cls, dic->alias, &issue);
194}
195
196
197static int
198denomkeys_iterate_topdir_iter (void *cls,
199 const char *filename)
200{
201
202 struct DenomkeysIterateContext *dic = cls;
203 dic->alias = GNUNET_STRINGS_get_short_name (filename);
204
205 // FIXME: differentiate between error case and normal iteration abortion
206 if (0 > GNUNET_DISK_directory_scan (filename, &denomkeys_iterate_keydir_iter, dic))
207 return GNUNET_SYSERR;
208 return GNUNET_OK;
209}
210
211
212int
213TALER_MINT_denomkeys_iterate (const char *mint_base_dir,
214 TALER_MINT_DenomkeyIterator it, void *cls)
215{
216 char *dir;
217 size_t len;
218 struct DenomkeysIterateContext dic;
219 len = GNUNET_asprintf (&dir, ("%s" DIR_SEPARATOR_STR DIR_DENOMKEYS),
220 mint_base_dir);
221 GNUNET_assert (len > 0);
222
223 dic.it = it;
224 dic.it_cls = cls;
225
226 // scan over alias dirs
227 return GNUNET_DISK_directory_scan (dir, &denomkeys_iterate_topdir_iter, &dic);
228}
229
230
231struct GNUNET_CONFIGURATION_Handle *
232TALER_MINT_config_load (const char *mint_base_dir)
233{
234 struct GNUNET_CONFIGURATION_Handle *cfg;
235 char *cfg_dir;
236 int res;
237
238 res = GNUNET_asprintf (&cfg_dir, "%s" DIR_SEPARATOR_STR "config", mint_base_dir);
239 GNUNET_assert (res > 0);
240
241 cfg = GNUNET_CONFIGURATION_create ();
242 res = GNUNET_CONFIGURATION_load_from (cfg, cfg_dir);
243 GNUNET_free (cfg_dir);
244 if (GNUNET_OK != res)
245 return NULL;
246 return cfg;
247}
248
249int
250TALER_TALER_DB_extract_amount_nbo (PGresult *result, unsigned int row,
251 int indices[3], struct TALER_AmountNBO *denom_nbo)
252{
253 if ((indices[0] < 0) || (indices[1] < 0) || (indices[2] < 0))
254 return GNUNET_NO;
255 if (sizeof (uint32_t) != PQgetlength (result, row, indices[0]))
256 return GNUNET_SYSERR;
257 if (sizeof (uint32_t) != PQgetlength (result, row, indices[1]))
258 return GNUNET_SYSERR;
259 if (PQgetlength (result, row, indices[2]) > TALER_CURRENCY_LEN)
260 return GNUNET_SYSERR;
261 denom_nbo->value = *(uint32_t *) PQgetvalue (result, row, indices[0]);
262 denom_nbo->fraction = *(uint32_t *) PQgetvalue (result, row, indices[1]);
263 memset (denom_nbo->currency, 0, TALER_CURRENCY_LEN);
264 memcpy (denom_nbo->currency, PQgetvalue (result, row, indices[2]), PQgetlength (result, row, indices[2]));
265 return GNUNET_OK;
266}
267
268
269int
270TALER_TALER_DB_extract_amount (PGresult *result, unsigned int row,
271 int indices[3], struct TALER_Amount *denom)
272{
273 struct TALER_AmountNBO denom_nbo;
274 int res;
275
276 res = TALER_TALER_DB_extract_amount_nbo (result, row, indices, &denom_nbo);
277 if (GNUNET_OK != res)
278 return res;
279 *denom = TALER_amount_ntoh (denom_nbo);
280 return GNUNET_OK;
281}
282
283/* end of mint_common.c */
diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c
new file mode 100644
index 000000000..6dc025877
--- /dev/null
+++ b/src/mint/mint_db.c
@@ -0,0 +1,1838 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file mint_db.c
19 * @brief Database access for the mint
20 * @author Florian Dold
21 */
22#include "platform.h"
23#include "taler_db_lib.h"
24#include "taler_signatures.h"
25#include "mint_db.h"
26#include "mint.h"
27#include <pthread.h>
28
29/**
30 * Thread-local database connection.
31 * Contains a pointer to PGconn or NULL.
32 */
33static pthread_key_t db_conn_threadlocal;
34
35
36/**
37 * Database connection string, as read from
38 * the configuration.
39 */
40static char *TALER_MINT_db_connection_cfg_str;
41
42
43#define break_db_err(result) do { \
44 GNUNET_break(0); \
45 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Database failure: %s\n", PQresultErrorMessage (result)); \
46 } while (0)
47
48/**
49 * Shorthand for exit jumps.
50 */
51#define EXITIF(cond) \
52 do { \
53 if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
54 } while (0)
55
56int
57TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn,
58 struct TALER_RSA_BlindedSignaturePurpose *blind_ev,
59 struct CollectableBlindcoin *collectable)
60{
61 PGresult *result;
62 struct TALER_DB_QueryParam params[] = {
63 TALER_DB_QUERY_PARAM_PTR (blind_ev),
64 TALER_DB_QUERY_PARAM_END
65 };
66 result = TALER_DB_exec_prepared (db_conn, "get_collectable_blindcoins", params);
67
68 if (PGRES_TUPLES_OK != PQresultStatus (result))
69 {
70 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Query failed: %s\n", PQresultErrorMessage (result));
71 PQclear (result);
72 return GNUNET_SYSERR;
73 }
74
75 if (0 == PQntuples (result))
76 {
77 PQclear (result);
78 return GNUNET_NO;
79 }
80
81 struct TALER_DB_ResultSpec rs[] = {
82 TALER_DB_RESULT_SPEC("blind_ev_sig", &collectable->ev_sig),
83 TALER_DB_RESULT_SPEC("denom_pub", &collectable->denom_pub),
84 TALER_DB_RESULT_SPEC("reserve_sig", &collectable->reserve_sig),
85 TALER_DB_RESULT_SPEC("reserve_pub", &collectable->reserve_pub),
86 TALER_DB_RESULT_SPEC_END
87 };
88
89 if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0))
90 {
91 GNUNET_break (0);
92 PQclear (result);
93 return GNUNET_SYSERR;
94 }
95 (void) memcpy (&collectable->ev, blind_ev, sizeof (struct TALER_RSA_BlindedSignaturePurpose));
96 PQclear (result);
97 return GNUNET_OK;
98}
99
100
101int
102TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn,
103 const struct CollectableBlindcoin *collectable)
104{
105 PGresult *result;
106 struct TALER_DB_QueryParam params[] = {
107 TALER_DB_QUERY_PARAM_PTR (&collectable->ev),
108 TALER_DB_QUERY_PARAM_PTR (&collectable->ev_sig),
109 TALER_DB_QUERY_PARAM_PTR (&collectable->denom_pub),
110 TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_pub),
111 TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_sig),
112 TALER_DB_QUERY_PARAM_END
113 };
114 result = TALER_DB_exec_prepared (db_conn, "insert_collectable_blindcoins", params);
115
116 if (PGRES_COMMAND_OK != PQresultStatus (result))
117 {
118 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Query failed: %s\n", PQresultErrorMessage (result));
119 PQclear (result);
120 return GNUNET_SYSERR;
121 }
122
123 if (0 != strcmp ("1", PQcmdTuples (result)))
124 {
125 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Insert failed (updated '%s' tupes instead of '1')\n",
126 PQcmdTuples (result));
127 PQclear (result);
128 return GNUNET_SYSERR;
129 }
130
131 PQclear (result);
132 return GNUNET_OK;
133}
134
135
136int
137TALER_MINT_DB_get_reserve (PGconn *db_conn,
138 const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub,
139 struct Reserve *reserve)
140{
141 PGresult *result;
142 int res;
143 struct TALER_DB_QueryParam params[] = {
144 TALER_DB_QUERY_PARAM_PTR (reserve_pub),
145 TALER_DB_QUERY_PARAM_END
146 };
147
148 result = TALER_DB_exec_prepared (db_conn, "get_reserve", params);
149
150 if (PGRES_TUPLES_OK != PQresultStatus (result))
151 {
152 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Query failed: %s\n", PQresultErrorMessage (result));
153 PQclear (result);
154 return GNUNET_SYSERR;
155 }
156
157 if (0 == PQntuples (result))
158 {
159 PQclear (result);
160 return GNUNET_NO;
161 }
162
163 reserve->reserve_pub = *reserve_pub;
164
165 struct TALER_DB_ResultSpec rs[] = {
166 TALER_DB_RESULT_SPEC("status_sig", &reserve->status_sig),
167 TALER_DB_RESULT_SPEC("status_sign_pub", &reserve->status_sign_pub),
168 TALER_DB_RESULT_SPEC_END
169 };
170
171 res = TALER_DB_extract_result (result, rs, 0);
172 if (GNUNET_SYSERR == res)
173 {
174 GNUNET_break (0);
175 PQclear (result);
176 return GNUNET_SYSERR;
177 }
178
179 {
180 int fnums[] = {
181 PQfnumber (result, "balance_value"),
182 PQfnumber (result, "balance_fraction"),
183 PQfnumber (result, "balance_currency"),
184 };
185 if (GNUNET_OK != TALER_TALER_DB_extract_amount_nbo (result, 0, fnums, &reserve->balance))
186 {
187 GNUNET_break (0);
188 PQclear (result);
189 return GNUNET_SYSERR;
190 }
191 }
192
193 /* FIXME: Add expiration?? */
194
195 PQclear (result);
196 return GNUNET_OK;
197}
198
199
200/* If fresh is GNUNET_YES, set some fields to NULL as they are not actually valid */
201int
202TALER_MINT_DB_update_reserve (PGconn *db_conn,
203 const struct Reserve *reserve,
204 int fresh)
205{
206 PGresult *result;
207 uint64_t stamp_sec;
208
209 stamp_sec = GNUNET_ntohll (GNUNET_TIME_absolute_ntoh (reserve->expiration).abs_value_us / 1000000);
210
211 struct TALER_DB_QueryParam params[] = {
212 TALER_DB_QUERY_PARAM_PTR (&reserve->reserve_pub),
213 TALER_DB_QUERY_PARAM_PTR (&reserve->balance.value),
214 TALER_DB_QUERY_PARAM_PTR (&reserve->balance.fraction),
215 TALER_DB_QUERY_PARAM_PTR_SIZED (&reserve->balance.currency,
216 strlen (reserve->balance.currency)),
217 TALER_DB_QUERY_PARAM_PTR (&reserve->status_sig),
218 TALER_DB_QUERY_PARAM_PTR (&reserve->status_sign_pub),
219 TALER_DB_QUERY_PARAM_PTR (&stamp_sec),
220 TALER_DB_QUERY_PARAM_END
221 };
222
223 /* set some fields to NULL if they are not actually valid */
224
225 if (GNUNET_YES == fresh)
226 {
227 unsigned i;
228 for (i = 4; i <= 7; i += 1)
229 {
230 params[i].data = NULL;
231 params[i].size = 0;
232 }
233 }
234
235 result = TALER_DB_exec_prepared (db_conn, "update_reserve", params);
236
237 if (PGRES_COMMAND_OK != PQresultStatus (result))
238 {
239 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Query failed: %s\n", PQresultErrorMessage (result));
240 PQclear (result);
241 return GNUNET_SYSERR;
242 }
243
244 if (0 != strcmp ("1", PQcmdTuples (result)))
245 {
246 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Update failed (updated '%s' tupes instead of '1')\n",
247 PQcmdTuples (result));
248 return GNUNET_SYSERR;
249 }
250
251 PQclear (result);
252 return GNUNET_OK;
253}
254
255
256
257int
258TALER_MINT_DB_prepare (PGconn *db_conn)
259{
260 PGresult *result;
261
262 result = PQprepare (db_conn, "get_reserve",
263 "SELECT "
264 " balance_value, balance_fraction, balance_currency "
265 ",expiration_date, blind_session_pub, blind_session_priv"
266 ",status_sig, status_sign_pub "
267 "FROM reserves "
268 "WHERE reserve_pub=$1 "
269 "LIMIT 1; ",
270 1, NULL);
271 if (PGRES_COMMAND_OK != PQresultStatus(result))
272 {
273 break_db_err (result);
274 PQclear (result);
275 return GNUNET_SYSERR;
276 }
277 PQclear (result);
278
279 result = PQprepare (db_conn, "update_reserve",
280 "UPDATE reserves "
281 "SET"
282 " balance_value=$2 "
283 ",balance_fraction=$3 "
284 ",balance_currency=$4 "
285 ",status_sig=$5 "
286 ",status_sign_pub=$6 "
287 ",expiration_date=$7 "
288 "WHERE reserve_pub=$1 ",
289 9, NULL);
290 if (PGRES_COMMAND_OK != PQresultStatus(result))
291 {
292 break_db_err (result);
293 PQclear (result);
294 return GNUNET_SYSERR;
295 }
296 PQclear (result);
297 result = PQprepare (db_conn, "insert_collectable_blindcoins",
298 "INSERT INTO collectable_blindcoins ( "
299 " blind_ev, blind_ev_sig "
300 ",denom_pub, reserve_pub, reserve_sig) "
301 "VALUES ($1, $2, $3, $4, $5)",
302 6, NULL);
303 if (PGRES_COMMAND_OK != PQresultStatus(result))
304 {
305 break_db_err (result);
306 PQclear (result);
307 return GNUNET_SYSERR;
308 }
309 PQclear (result);
310
311 result = PQprepare (db_conn, "get_collectable_blindcoins",
312 "SELECT "
313 "blind_ev_sig, denom_pub, reserve_sig, reserve_pub "
314 "FROM collectable_blindcoins "
315 "WHERE blind_ev = $1",
316 1, NULL);
317 if (PGRES_COMMAND_OK != PQresultStatus(result))
318 {
319 break_db_err (result);
320 PQclear (result);
321 return GNUNET_SYSERR;
322 }
323 PQclear (result);
324
325 result = PQprepare (db_conn, "insert_reserve_order",
326 "SELECT "
327 " blind_ev, blind_ev_sig, denom_pub, reserve_sig, reserve_pub "
328 "FROM collectable_blindcoins "
329 "WHERE blind_session_pub = $1",
330 1, NULL);
331 if (PGRES_COMMAND_OK != PQresultStatus(result))
332 {
333 break_db_err (result);
334 PQclear (result);
335 return GNUNET_SYSERR;
336 }
337 PQclear (result);
338
339 /* FIXME: does it make sense to store these computed values in the DB? */
340 result = PQprepare (db_conn, "get_refresh_session",
341 "SELECT "
342 " (SELECT count(*) FROM refresh_melt WHERE session_pub = $1)::INT2 as num_oldcoins "
343 ",(SELECT count(*) FROM refresh_blind_session_keys "
344 " WHERE session_pub = $1 and cnc_index = 0)::INT2 as num_newcoins "
345 ",(SELECT count(*) FROM refresh_blind_session_keys "
346 " WHERE session_pub = $1 and newcoin_index = 0)::INT2 as kappa "
347 ",noreveal_index"
348 ",session_commit_sig "
349 ",reveal_ok "
350 "FROM refresh_sessions "
351 "WHERE session_pub = $1",
352 1, NULL);
353 if (PGRES_COMMAND_OK != PQresultStatus(result))
354 {
355 break_db_err (result);
356 PQclear (result);
357 return GNUNET_SYSERR;
358 }
359 PQclear (result);
360
361 result = PQprepare (db_conn, "get_known_coin",
362 "SELECT "
363 " coin_pub, denom_pub, denom_sig "
364 ",expended_value, expended_fraction, expended_currency "
365 ",refresh_session_pub "
366 "FROM known_coins "
367 "WHERE coin_pub = $1",
368 1, NULL);
369 if (PGRES_COMMAND_OK != PQresultStatus(result))
370 {
371 break_db_err (result);
372 PQclear (result);
373 return GNUNET_SYSERR;
374 }
375 PQclear (result);
376
377 result = PQprepare (db_conn, "update_known_coin",
378 "UPDATE known_coins "
379 "SET "
380 " denom_pub = $2 "
381 ",denom_sig = $3 "
382 ",expended_value = $4 "
383 ",expended_fraction = $5 "
384 ",expended_currency = $6 "
385 ",refresh_session_pub = $7 "
386 "WHERE "
387 " coin_pub = $1 ",
388 7, NULL);
389 if (PGRES_COMMAND_OK != PQresultStatus(result))
390 {
391 break_db_err (result);
392 PQclear (result);
393 return GNUNET_SYSERR;
394 }
395 PQclear (result);
396
397 result = PQprepare (db_conn, "insert_known_coin",
398 "INSERT INTO known_coins ("
399 " coin_pub"
400 ",denom_pub"
401 ",denom_sig"
402 ",expended_value"
403 ",expended_fraction"
404 ",expended_currency"
405 ",refresh_session_pub"
406 ")"
407 "VALUES ($1,$2,$3,$4,$5,$6,$7)",
408 7, NULL);
409 if (PGRES_COMMAND_OK != PQresultStatus(result))
410 {
411 break_db_err (result);
412 PQclear (result);
413 return GNUNET_SYSERR;
414 }
415 PQclear (result);
416
417 result = PQprepare (db_conn, "get_refresh_commit_link",
418 "SELECT "
419 " transfer_pub "
420 ",link_secret_enc "
421 "FROM refresh_commit_link "
422 "WHERE session_pub = $1 AND cnc_index = $2 AND oldcoin_index = $3",
423 3, NULL);
424 if (PGRES_COMMAND_OK != PQresultStatus(result))
425 {
426 break_db_err (result);
427 PQclear (result);
428 return GNUNET_SYSERR;
429 }
430 PQclear (result);
431
432 result = PQprepare (db_conn, "get_refresh_commit_coin",
433 "SELECT "
434 " link_vector_enc "
435 ",coin_ev "
436 "FROM refresh_commit_coin "
437 "WHERE session_pub = $1 AND cnc_index = $2 AND newcoin_index = $3",
438 3, NULL);
439 if (PGRES_COMMAND_OK != PQresultStatus(result))
440 {
441 break_db_err (result);
442 PQclear (result);
443 return GNUNET_SYSERR;
444 }
445 PQclear (result);
446
447 result = PQprepare (db_conn, "insert_refresh_order",
448 "INSERT INTO refresh_order ( "
449 " newcoin_index "
450 ",session_pub "
451 ",denom_pub "
452 ") "
453 "VALUES ($1, $2, $3) ",
454 3, NULL);
455 if (PGRES_COMMAND_OK != PQresultStatus(result))
456 {
457 break_db_err (result);
458 PQclear (result);
459 return GNUNET_SYSERR;
460 }
461 PQclear (result);
462
463 result = PQprepare (db_conn, "insert_refresh_melt",
464 "INSERT INTO refresh_melt ( "
465 " session_pub "
466 ",oldcoin_index "
467 ",coin_pub "
468 ",denom_pub "
469 ") "
470 "VALUES ($1, $2, $3, $4) ",
471 3, NULL);
472 if (PGRES_COMMAND_OK != PQresultStatus(result))
473 {
474 break_db_err (result);
475 PQclear (result);
476 return GNUNET_SYSERR;
477 }
478 PQclear (result);
479
480 result = PQprepare (db_conn, "get_refresh_order",
481 "SELECT denom_pub "
482 "FROM refresh_order "
483 "WHERE session_pub = $1 AND newcoin_index = $2",
484 2, NULL);
485 if (PGRES_COMMAND_OK != PQresultStatus(result))
486 {
487 break_db_err (result);
488 PQclear (result);
489 return GNUNET_SYSERR;
490 }
491 PQclear (result);
492
493 result = PQprepare (db_conn, "get_refresh_collectable",
494 "SELECT ev_sig "
495 "FROM refresh_collectable "
496 "WHERE session_pub = $1 AND newcoin_index = $2",
497 2, NULL);
498 if (PGRES_COMMAND_OK != PQresultStatus(result))
499 {
500 break_db_err (result);
501 PQclear (result);
502 return GNUNET_SYSERR;
503 }
504 PQclear (result);
505
506 result = PQprepare (db_conn, "get_refresh_melt",
507 "SELECT coin_pub "
508 "FROM refresh_melt "
509 "WHERE session_pub = $1 AND oldcoin_index = $2",
510 2, NULL);
511 if (PGRES_COMMAND_OK != PQresultStatus(result))
512 {
513 break_db_err (result);
514 PQclear (result);
515 return GNUNET_SYSERR;
516 }
517 PQclear (result);
518
519 result = PQprepare (db_conn, "insert_refresh_session",
520 "INSERT INTO refresh_sessions ( "
521 " session_pub "
522 ",noreveal_index "
523 ") "
524 "VALUES ($1, $2) ",
525 2, NULL);
526 if (PGRES_COMMAND_OK != PQresultStatus(result))
527 {
528 break_db_err (result);
529 PQclear (result);
530 return GNUNET_SYSERR;
531 }
532 PQclear (result);
533
534 result = PQprepare (db_conn, "insert_refresh_commit_link",
535 "INSERT INTO refresh_commit_link ( "
536 " session_pub "
537 ",transfer_pub "
538 ",cnc_index "
539 ",oldcoin_index "
540 ",link_secret_enc "
541 ") "
542 "VALUES ($1, $2, $3, $4, $5) ",
543 5, NULL);
544 if (PGRES_COMMAND_OK != PQresultStatus(result))
545 {
546 break_db_err (result);
547 PQclear (result);
548 return GNUNET_SYSERR;
549 }
550 PQclear (result);
551
552 result = PQprepare (db_conn, "insert_refresh_commit_coin",
553 "INSERT INTO refresh_commit_coin ( "
554 " session_pub "
555 ",coin_ev "
556 ",cnc_index "
557 ",newcoin_index "
558 ",link_vector_enc "
559 ") "
560 "VALUES ($1, $2, $3, $4, $5) ",
561 5, NULL);
562 if (PGRES_COMMAND_OK != PQresultStatus(result))
563 {
564 break_db_err (result);
565 PQclear (result);
566 return GNUNET_SYSERR;
567 }
568 PQclear (result);
569
570 result = PQprepare (db_conn, "insert_refresh_collectable",
571 "INSERT INTO refresh_collectable ( "
572 " session_pub "
573 ",newcoin_index "
574 ",ev_sig "
575 ") "
576 "VALUES ($1, $2, $3) ",
577 3, NULL);
578 if (PGRES_COMMAND_OK != PQresultStatus(result))
579 {
580 break_db_err (result);
581 PQclear (result);
582 return GNUNET_SYSERR;
583 }
584 PQclear (result);
585
586 result = PQprepare (db_conn, "set_reveal_ok",
587 "UPDATE refresh_sessions "
588 "SET reveal_ok = TRUE "
589 "WHERE session_pub = $1 ",
590 1, NULL);
591 if (PGRES_COMMAND_OK != PQresultStatus(result))
592 {
593 break_db_err (result);
594 PQclear (result);
595 return GNUNET_SYSERR;
596 }
597 PQclear (result);
598
599 result = PQprepare (db_conn, "get_link",
600 "SELECT link_vector_enc, ro.denom_pub, ev_sig "
601 "FROM refresh_melt rm "
602 " JOIN refresh_order ro USING (session_pub) "
603 " JOIN refresh_commit_coin rcc USING (session_pub) "
604 " JOIN refresh_sessions rs USING (session_pub) "
605 " JOIN refresh_collectable rc USING (session_pub) "
606 "WHERE rm.coin_pub = $1 "
607 "AND ro.newcoin_index = rcc.newcoin_index "
608 "AND ro.newcoin_index = rc.newcoin_index "
609 "AND rcc.cnc_index = rs.noreveal_index % ( "
610 " SELECT count(*) FROM refresh_commit_coin rcc2 "
611 " WHERE rcc2.newcoin_index = 0 AND rcc2.session_pub = rs.session_pub "
612 " ) ",
613 1, NULL);
614 if (PGRES_COMMAND_OK != PQresultStatus(result))
615 {
616 break_db_err (result);
617 PQclear (result);
618 return GNUNET_SYSERR;
619 }
620 PQclear (result);
621
622 result = PQprepare (db_conn, "get_transfer",
623 "SELECT transfer_pub, link_secret_enc "
624 "FROM refresh_melt rm "
625 " JOIN refresh_commit_link rcl USING (session_pub) "
626 " JOIN refresh_sessions rs USING (session_pub) "
627 "WHERE rm.coin_pub = $1 "
628 "AND rm.oldcoin_index = rcl.oldcoin_index "
629 "AND rcl.cnc_index = rs.noreveal_index % ( "
630 " SELECT count(*) FROM refresh_commit_coin rcc2 "
631 " WHERE newcoin_index = 0 AND rcc2.session_pub = rm.session_pub "
632 " ) ",
633 1, NULL);
634 if (PGRES_COMMAND_OK != PQresultStatus(result))
635 {
636 break_db_err (result);
637 PQclear (result);
638 return GNUNET_SYSERR;
639 }
640 PQclear (result);
641
642 if (GNUNET_OK != TALER_MINT_DB_prepare_deposits (db_conn))
643 {
644 GNUNET_break (0);
645 return GNUNET_SYSERR;
646 }
647
648 return GNUNET_OK;
649}
650
651
652/**
653 * Roll back the current transaction of a database connection.
654 *
655 * @param db_conn the database connection
656 * @return GNUNET_OK on success
657 */
658int
659TALER_MINT_DB_rollback (PGconn *db_conn)
660{
661 PGresult *result;
662
663 result = PQexec(db_conn, "ROLLBACK");
664 if (PGRES_COMMAND_OK != PQresultStatus (result))
665 {
666 PQclear (result);
667 GNUNET_break (0);
668 return GNUNET_SYSERR;
669 }
670
671 PQclear (result);
672 return GNUNET_OK;
673}
674
675
676/**
677 * Roll back the current transaction of a database connection.
678 *
679 * @param db_conn the database connection
680 * @return GNUNET_OK on success
681 */
682int
683TALER_MINT_DB_commit (PGconn *db_conn)
684{
685 PGresult *result;
686
687 result = PQexec(db_conn, "COMMIT");
688 if (PGRES_COMMAND_OK != PQresultStatus (result))
689 {
690 PQclear (result);
691 GNUNET_break (0);
692 return GNUNET_SYSERR;
693 }
694
695 PQclear (result);
696 return GNUNET_OK;
697}
698
699
700/**
701 * Start a transaction.
702 *
703 * @param db_conn the database connection
704 * @return GNUNET_OK on success
705 */
706int
707TALER_MINT_DB_transaction (PGconn *db_conn)
708{
709 PGresult *result;
710
711 result = PQexec(db_conn, "BEGIN");
712 if (PGRES_COMMAND_OK != PQresultStatus (result))
713 {
714 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't start transaction: %s\n", PQresultErrorMessage (result));
715 PQclear (result);
716 GNUNET_break (0);
717 return GNUNET_SYSERR;
718 }
719
720 PQclear (result);
721 return GNUNET_OK;
722}
723
724
725/**
726 * Insert a refresh order into the database.
727 */
728int
729TALER_MINT_DB_insert_refresh_order (PGconn *db_conn,
730 uint16_t newcoin_index,
731 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
732 const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub)
733{
734 uint16_t newcoin_index_nbo = htons (newcoin_index);
735 struct TALER_DB_QueryParam params[] = {
736 TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo),
737 TALER_DB_QUERY_PARAM_PTR(session_pub),
738 TALER_DB_QUERY_PARAM_PTR(denom_pub),
739 TALER_DB_QUERY_PARAM_END
740 };
741
742 PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_order", params);
743
744 if (PGRES_COMMAND_OK != PQresultStatus (result))
745 {
746 break_db_err (result);
747 PQclear (result);
748 return GNUNET_SYSERR;
749 }
750
751 if (0 != strcmp ("1", PQcmdTuples (result)))
752 {
753 GNUNET_break (0);
754 return GNUNET_SYSERR;
755 }
756
757 PQclear (result);
758 return GNUNET_OK;
759}
760
761
762int
763TALER_MINT_DB_get_refresh_session (PGconn *db_conn,
764 const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
765 struct RefreshSession *session)
766{
767 int res;
768 struct TALER_DB_QueryParam params[] = {
769 TALER_DB_QUERY_PARAM_PTR(refresh_session_pub),
770 TALER_DB_QUERY_PARAM_END
771 };
772
773 PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_session", params);
774
775 if (PGRES_TUPLES_OK != PQresultStatus (result))
776 {
777 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Query failed: %s\n", PQresultErrorMessage (result));
778 PQclear (result);
779 return GNUNET_SYSERR;
780 }
781
782 if (0 == PQntuples (result))
783 return GNUNET_NO;
784
785 GNUNET_assert (1 == PQntuples (result));
786
787 /* We're done if the caller is only interested in
788 * whether the session exists or not */
789
790 if (NULL == session)
791 return GNUNET_YES;
792
793 memset (session, 0, sizeof (struct RefreshSession));
794
795 session->session_pub = *refresh_session_pub;
796
797 struct TALER_DB_ResultSpec rs[] = {
798 TALER_DB_RESULT_SPEC("num_oldcoins", &session->num_oldcoins),
799 TALER_DB_RESULT_SPEC("num_newcoins", &session->num_newcoins),
800 TALER_DB_RESULT_SPEC("kappa", &session->kappa),
801 TALER_DB_RESULT_SPEC("noreveal_index", &session->noreveal_index),
802 TALER_DB_RESULT_SPEC("reveal_ok", &session->reveal_ok),
803 TALER_DB_RESULT_SPEC_END
804 };
805
806 res = TALER_DB_extract_result (result, rs, 0);
807
808 if (GNUNET_OK != res)
809 {
810 GNUNET_break (0);
811 PQclear (result);
812 return GNUNET_SYSERR;
813 }
814
815 if (TALER_DB_field_isnull (result, 0, "session_commit_sig"))
816 session->has_commit_sig = GNUNET_NO;
817 else
818 session->has_commit_sig = GNUNET_YES;
819
820 session->num_oldcoins = ntohs (session->num_oldcoins);
821 session->num_newcoins = ntohs (session->num_newcoins);
822 session->kappa = ntohs (session->kappa);
823 session->noreveal_index = ntohs (session->noreveal_index);
824
825 PQclear (result);
826 return GNUNET_YES;
827}
828
829
830int
831TALER_MINT_DB_get_known_coin (PGconn *db_conn, struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
832 struct KnownCoin *known_coin)
833{
834 int res;
835 struct TALER_DB_QueryParam params[] = {
836 TALER_DB_QUERY_PARAM_PTR(coin_pub),
837 TALER_DB_QUERY_PARAM_END
838 };
839
840 PGresult *result = TALER_DB_exec_prepared (db_conn, "get_known_coin", params);
841
842 if (PGRES_TUPLES_OK != PQresultStatus (result))
843 {
844 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Query failed: %s\n", PQresultErrorMessage (result));
845 PQclear (result);
846 return GNUNET_SYSERR;
847 }
848
849 if (0 == PQntuples (result))
850 return GNUNET_NO;
851
852 GNUNET_assert (1 == PQntuples (result));
853
854 /* extract basic information about the known coin */
855
856 {
857 struct TALER_DB_ResultSpec rs[] = {
858 TALER_DB_RESULT_SPEC("coin_pub", &known_coin->public_info.coin_pub),
859 TALER_DB_RESULT_SPEC("denom_pub", &known_coin->public_info.denom_pub),
860 TALER_DB_RESULT_SPEC("denom_sig", &known_coin->public_info.denom_sig),
861 TALER_DB_RESULT_SPEC_END
862 };
863
864 if (GNUNET_OK != (res = TALER_DB_extract_result (result, rs, 0)))
865 {
866 GNUNET_break (0);
867 PQclear (result);
868 return GNUNET_SYSERR;
869 }
870 }
871
872 /* extract the expended amount of the coin */
873
874 if (GNUNET_OK != TALER_DB_extract_amount (result, 0,
875 "expended_value",
876 "expended_fraction",
877 "expended_currency",
878 &known_coin->expended_balance))
879 {
880 GNUNET_break (0);
881 PQclear (result);
882 return GNUNET_SYSERR;
883 }
884
885 /* extract the refresh session of the coin or mark it as missing */
886
887 {
888 struct TALER_DB_ResultSpec rs[] = {
889 TALER_DB_RESULT_SPEC("refresh_session_pub", &known_coin->refresh_session_pub),
890 TALER_DB_RESULT_SPEC_END
891 };
892
893 if (GNUNET_SYSERR == (res = TALER_DB_extract_result (result, rs, 0)))
894 {
895 GNUNET_break (0);
896 PQclear (result);
897 return GNUNET_SYSERR;
898 }
899 if (GNUNET_NO == res)
900 {
901 known_coin->is_refreshed = GNUNET_NO;
902 memset (&known_coin->refresh_session_pub, 0, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
903 }
904 else
905 {
906 known_coin->is_refreshed = GNUNET_YES;
907 }
908 }
909
910 PQclear (result);
911 return GNUNET_YES;
912}
913
914
915int
916TALER_MINT_DB_create_refresh_session (PGconn *db_conn,
917 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub)
918{
919 uint16_t noreveal_index;
920 struct TALER_DB_QueryParam params[] = {
921 TALER_DB_QUERY_PARAM_PTR(session_pub),
922 TALER_DB_QUERY_PARAM_PTR(&noreveal_index),
923 TALER_DB_QUERY_PARAM_END
924 };
925
926 noreveal_index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1<<15);
927 noreveal_index = htonl (noreveal_index);
928
929 PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_session", params);
930
931 if (PGRES_COMMAND_OK != PQresultStatus (result))
932 {
933 break_db_err (result);
934 PQclear (result);
935 return GNUNET_SYSERR;
936 }
937
938 PQclear (result);
939 return GNUNET_OK;
940}
941
942
943int
944TALER_MINT_DB_set_commit_signature (PGconn *db_conn,
945 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
946 const struct GNUNET_CRYPTO_EddsaSignature *commit_sig)
947{
948 GNUNET_break (0);
949 return GNUNET_SYSERR;
950}
951
952
953int
954TALER_MINT_DB_set_reveal_ok (PGconn *db_conn,
955 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub)
956{
957 struct TALER_DB_QueryParam params[] = {
958 TALER_DB_QUERY_PARAM_PTR(session_pub),
959 TALER_DB_QUERY_PARAM_END
960 };
961
962 PGresult *result = TALER_DB_exec_prepared (db_conn, "set_reveal_ok", params);
963
964 if (PGRES_COMMAND_OK != PQresultStatus (result))
965 {
966 break_db_err (result);
967 PQclear (result);
968 return GNUNET_SYSERR;
969 }
970
971 if (0 != strcmp ("1", PQcmdTuples (result)))
972 {
973 GNUNET_break (0);
974 return GNUNET_SYSERR;
975 }
976
977 PQclear (result);
978 return GNUNET_OK;
979}
980
981
982int
983TALER_MINT_DB_update_known_coin (PGconn *db_conn,
984 const struct KnownCoin *known_coin)
985{
986 struct TALER_AmountNBO expended_nbo = TALER_amount_hton (known_coin->expended_balance);
987 struct TALER_DB_QueryParam params[] = {
988 TALER_DB_QUERY_PARAM_PTR(&known_coin->public_info.coin_pub),
989 TALER_DB_QUERY_PARAM_PTR(&known_coin->public_info.denom_pub),
990 TALER_DB_QUERY_PARAM_PTR(&known_coin->public_info.denom_sig),
991 TALER_DB_QUERY_PARAM_PTR(&expended_nbo.value),
992 TALER_DB_QUERY_PARAM_PTR(&expended_nbo.fraction),
993 TALER_DB_QUERY_PARAM_PTR_SIZED(expended_nbo.currency, strlen (expended_nbo.currency)),
994 TALER_DB_QUERY_PARAM_PTR(&known_coin->refresh_session_pub),
995 TALER_DB_QUERY_PARAM_END
996 };
997
998 if (GNUNET_NO == known_coin->is_refreshed)
999 {
1000 // Mind the magic index!
1001 params[6].data = NULL;
1002 params[6].size = 0;
1003 }
1004
1005 PGresult *result = TALER_DB_exec_prepared (db_conn, "update_known_coin", params);
1006
1007 if (PGRES_COMMAND_OK != PQresultStatus (result))
1008 {
1009 break_db_err (result);
1010 PQclear (result);
1011 return GNUNET_SYSERR;
1012 }
1013
1014 if (0 != strcmp ("1", PQcmdTuples (result)))
1015 {
1016 PQclear (result);
1017 // return 'no' here (don't fail) so that we can
1018 // insert if update fails (=> "upsert")
1019 return GNUNET_NO;
1020 }
1021
1022 PQclear (result);
1023 return GNUNET_YES;
1024}
1025
1026int
1027TALER_MINT_DB_insert_known_coin (PGconn *db_conn,
1028 const struct KnownCoin *known_coin)
1029{
1030 struct TALER_AmountNBO expended_nbo = TALER_amount_hton (known_coin->expended_balance);
1031 struct TALER_DB_QueryParam params[] = {
1032 TALER_DB_QUERY_PARAM_PTR(&known_coin->public_info.coin_pub),
1033 TALER_DB_QUERY_PARAM_PTR(&known_coin->public_info.denom_pub),
1034 TALER_DB_QUERY_PARAM_PTR(&known_coin->public_info.denom_sig),
1035 TALER_DB_QUERY_PARAM_PTR(&expended_nbo.value),
1036 TALER_DB_QUERY_PARAM_PTR(&expended_nbo.fraction),
1037 TALER_DB_QUERY_PARAM_PTR_SIZED(&expended_nbo.currency, strlen (expended_nbo.currency)),
1038 TALER_DB_QUERY_PARAM_PTR(&known_coin->refresh_session_pub),
1039 TALER_DB_QUERY_PARAM_END
1040 };
1041
1042 if (GNUNET_NO == known_coin->is_refreshed)
1043 {
1044 // Mind the magic index!
1045 params[6].data = NULL;
1046 params[6].size = 0;
1047 }
1048
1049 PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_known_coin", params);
1050
1051 if (PGRES_COMMAND_OK != PQresultStatus (result))
1052 {
1053 break_db_err (result);
1054 PQclear (result);
1055 return GNUNET_SYSERR;
1056 }
1057
1058 if (0 != strcmp ("1", PQcmdTuples (result)))
1059 {
1060 PQclear (result);
1061 // return 'no' here (don't fail) so that we can
1062 // update if insert fails (=> "upsert")
1063 return GNUNET_NO;
1064 }
1065
1066 PQclear (result);
1067 return GNUNET_YES;
1068}
1069
1070
1071int
1072TALER_MINT_DB_upsert_known_coin (PGconn *db_conn, struct KnownCoin *known_coin)
1073{
1074 int ret;
1075 ret = TALER_MINT_DB_update_known_coin (db_conn, known_coin);
1076 if (GNUNET_SYSERR == ret)
1077 {
1078 GNUNET_break (0);
1079 return GNUNET_SYSERR;
1080 }
1081 if (GNUNET_YES == ret)
1082 return GNUNET_YES;
1083 return TALER_MINT_DB_insert_known_coin (db_conn, known_coin);
1084}
1085
1086
1087int
1088TALER_MINT_DB_insert_refresh_commit_link (PGconn *db_conn, struct RefreshCommitLink *commit_link)
1089{
1090 uint16_t cnc_index_nbo = htons (commit_link->cnc_index);
1091 uint16_t oldcoin_index_nbo = htons (commit_link->oldcoin_index);
1092 struct TALER_DB_QueryParam params[] = {
1093 TALER_DB_QUERY_PARAM_PTR(&commit_link->session_pub),
1094 TALER_DB_QUERY_PARAM_PTR(&commit_link->transfer_pub),
1095 TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo),
1096 TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo),
1097 TALER_DB_QUERY_PARAM_PTR_SIZED(&commit_link->shared_secret_enc, sizeof (struct GNUNET_HashCode)),
1098 TALER_DB_QUERY_PARAM_END
1099 };
1100
1101 PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_commit_link", params);
1102
1103 if (PGRES_COMMAND_OK != PQresultStatus (result))
1104 {
1105 break_db_err (result);
1106 PQclear (result);
1107 return GNUNET_SYSERR;
1108 }
1109
1110 if (0 != strcmp ("1", PQcmdTuples (result)))
1111 {
1112 GNUNET_break (0);
1113 return GNUNET_SYSERR;
1114 }
1115
1116 PQclear (result);
1117 return GNUNET_OK;
1118}
1119
1120
1121int
1122TALER_MINT_DB_insert_refresh_commit_coin (PGconn *db_conn, struct RefreshCommitCoin *commit_coin)
1123{
1124 uint16_t cnc_index_nbo = htons (commit_coin->cnc_index);
1125 uint16_t newcoin_index_nbo = htons (commit_coin->newcoin_index);
1126 struct TALER_DB_QueryParam params[] = {
1127 TALER_DB_QUERY_PARAM_PTR(&commit_coin->session_pub),
1128 TALER_DB_QUERY_PARAM_PTR(&commit_coin->coin_ev),
1129 TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo),
1130 TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo),
1131 TALER_DB_QUERY_PARAM_PTR_SIZED(&commit_coin->link_enc, sizeof (struct LinkData)),
1132 TALER_DB_QUERY_PARAM_END
1133 };
1134
1135 PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_commit_coin", params);
1136
1137 if (PGRES_COMMAND_OK != PQresultStatus (result))
1138 {
1139 break_db_err (result);
1140 PQclear (result);
1141 return GNUNET_SYSERR;
1142 }
1143
1144 if (0 != strcmp ("1", PQcmdTuples (result)))
1145 {
1146 GNUNET_break (0);
1147 return GNUNET_SYSERR;
1148 }
1149
1150 PQclear (result);
1151 return GNUNET_OK;
1152}
1153
1154
1155int
1156TALER_MINT_DB_get_refresh_commit_link (PGconn *db_conn,
1157 const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
1158 int cnc_index, int oldcoin_index,
1159 struct RefreshCommitLink *cc)
1160{
1161 uint16_t cnc_index_nbo = htons (cnc_index);
1162 uint16_t oldcoin_index_nbo = htons (oldcoin_index);
1163
1164 struct TALER_DB_QueryParam params[] = {
1165 TALER_DB_QUERY_PARAM_PTR(refresh_session_pub),
1166 TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo),
1167 TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo),
1168 TALER_DB_QUERY_PARAM_END
1169 };
1170
1171 cc->cnc_index = cnc_index;
1172 cc->oldcoin_index = oldcoin_index;
1173 cc->session_pub = *refresh_session_pub;
1174
1175 PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_commit_link", params);
1176
1177 if (PGRES_TUPLES_OK != PQresultStatus (result))
1178 {
1179 break_db_err (result);
1180 PQclear (result);
1181 return GNUNET_SYSERR;
1182 }
1183
1184 if (0 == PQntuples (result))
1185 {
1186 PQclear (result);
1187 return GNUNET_NO;
1188 }
1189
1190 struct TALER_DB_ResultSpec rs[] = {
1191 TALER_DB_RESULT_SPEC("transfer_pub", &cc->transfer_pub),
1192 TALER_DB_RESULT_SPEC_SIZED("link_secret_enc", &cc->shared_secret_enc,
1193 TALER_REFRESH_SHARED_SECRET_LENGTH),
1194 TALER_DB_RESULT_SPEC_END
1195 };
1196
1197 if (GNUNET_YES != TALER_DB_extract_result (result, rs, 0))
1198 {
1199 PQclear (result);
1200 GNUNET_free (cc);
1201 return GNUNET_SYSERR;
1202 }
1203
1204 PQclear (result);
1205 return GNUNET_YES;
1206}
1207
1208
1209int
1210TALER_MINT_DB_get_refresh_commit_coin (PGconn *db_conn,
1211 const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
1212 int cnc_index, int newcoin_index,
1213 struct RefreshCommitCoin *cc)
1214{
1215 uint16_t cnc_index_nbo = htons (cnc_index);
1216 uint16_t newcoin_index_nbo = htons (newcoin_index);
1217
1218 cc->cnc_index = cnc_index;
1219 cc->newcoin_index = newcoin_index;
1220 cc->session_pub = *refresh_session_pub;
1221
1222 struct TALER_DB_QueryParam params[] = {
1223 TALER_DB_QUERY_PARAM_PTR(refresh_session_pub),
1224 TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo),
1225 TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo),
1226 TALER_DB_QUERY_PARAM_END
1227 };
1228
1229 PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_commit_coin", params);
1230
1231 if (PGRES_TUPLES_OK != PQresultStatus (result))
1232 {
1233 break_db_err (result);
1234 PQclear (result);
1235 return GNUNET_SYSERR;
1236 }
1237
1238 if (0 == PQntuples (result))
1239 {
1240 PQclear (result);
1241 return GNUNET_NO;
1242 }
1243
1244 struct TALER_DB_ResultSpec rs[] = {
1245 TALER_DB_RESULT_SPEC("coin_ev", &cc->coin_ev),
1246 TALER_DB_RESULT_SPEC_SIZED("link_vector_enc", &cc->link_enc,
1247 TALER_REFRESH_LINK_LENGTH),
1248 TALER_DB_RESULT_SPEC_END
1249 };
1250
1251 if (GNUNET_YES != TALER_DB_extract_result (result, rs, 0))
1252 {
1253 PQclear (result);
1254 return GNUNET_SYSERR;
1255 }
1256
1257 PQclear (result);
1258 return GNUNET_YES;
1259}
1260
1261
1262int
1263TALER_MINT_DB_get_refresh_order (PGconn *db_conn,
1264 uint16_t newcoin_index,
1265 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
1266 struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub)
1267{
1268 uint16_t newcoin_index_nbo = htons (newcoin_index);
1269
1270 struct TALER_DB_QueryParam params[] = {
1271 TALER_DB_QUERY_PARAM_PTR(session_pub),
1272 TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo),
1273 TALER_DB_QUERY_PARAM_END
1274 };
1275
1276 PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_order", params);
1277
1278 if (PGRES_TUPLES_OK != PQresultStatus (result))
1279 {
1280 break_db_err (result);
1281 PQclear (result);
1282 return GNUNET_SYSERR;
1283 }
1284
1285 if (0 == PQntuples (result))
1286 {
1287 PQclear (result);
1288 return GNUNET_NO;
1289 }
1290
1291 GNUNET_assert (1 == PQntuples (result));
1292
1293 struct TALER_DB_ResultSpec rs[] = {
1294 TALER_DB_RESULT_SPEC("denom_pub", denom_pub),
1295 TALER_DB_RESULT_SPEC_END
1296 };
1297
1298 if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0))
1299 {
1300 PQclear (result);
1301 GNUNET_break (0);
1302 return GNUNET_SYSERR;
1303 }
1304
1305 PQclear (result);
1306 return GNUNET_OK;
1307}
1308
1309
1310int
1311TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn,
1312 uint16_t newcoin_index,
1313 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
1314 const struct TALER_RSA_Signature *ev_sig)
1315{
1316 uint16_t newcoin_index_nbo = htons (newcoin_index);
1317 struct TALER_DB_QueryParam params[] = {
1318 TALER_DB_QUERY_PARAM_PTR(session_pub),
1319 TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo),
1320 TALER_DB_QUERY_PARAM_PTR(ev_sig),
1321 TALER_DB_QUERY_PARAM_END
1322 };
1323
1324 PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_collectable", params);
1325
1326 if (PGRES_COMMAND_OK != PQresultStatus (result))
1327 {
1328 break_db_err (result);
1329 PQclear (result);
1330 return GNUNET_SYSERR;
1331 }
1332
1333 PQclear (result);
1334 return GNUNET_OK;
1335}
1336
1337
1338int
1339TALER_MINT_DB_get_refresh_collectable (PGconn *db_conn,
1340 uint16_t newcoin_index,
1341 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
1342 struct TALER_RSA_Signature *ev_sig)
1343{
1344
1345 uint16_t newcoin_index_nbo = htons (newcoin_index);
1346
1347 struct TALER_DB_QueryParam params[] = {
1348 TALER_DB_QUERY_PARAM_PTR(session_pub),
1349 TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo),
1350 TALER_DB_QUERY_PARAM_END
1351 };
1352
1353 PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_collectable", params);
1354
1355 if (PGRES_TUPLES_OK != PQresultStatus (result))
1356 {
1357 break_db_err (result);
1358 PQclear (result);
1359 return GNUNET_SYSERR;
1360 }
1361
1362 if (0 == PQntuples (result))
1363 {
1364 PQclear (result);
1365 return GNUNET_NO;
1366 }
1367
1368 GNUNET_assert (1 == PQntuples (result));
1369
1370 struct TALER_DB_ResultSpec rs[] = {
1371 TALER_DB_RESULT_SPEC("ev_sig", ev_sig),
1372 TALER_DB_RESULT_SPEC_END
1373 };
1374
1375 if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0))
1376 {
1377 PQclear (result);
1378 GNUNET_break (0);
1379 return GNUNET_SYSERR;
1380 }
1381
1382 PQclear (result);
1383 return GNUNET_OK;
1384}
1385
1386
1387
1388int
1389TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn,
1390 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
1391 uint16_t oldcoin_index,
1392 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
1393 const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub)
1394{
1395 uint16_t oldcoin_index_nbo = htons (oldcoin_index);
1396 struct TALER_DB_QueryParam params[] = {
1397 TALER_DB_QUERY_PARAM_PTR(session_pub),
1398 TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo),
1399 TALER_DB_QUERY_PARAM_PTR(coin_pub),
1400 TALER_DB_QUERY_PARAM_PTR(denom_pub),
1401 TALER_DB_QUERY_PARAM_END
1402 };
1403
1404 PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_melt", params);
1405
1406 if (PGRES_COMMAND_OK != PQresultStatus (result))
1407 {
1408 break_db_err (result);
1409 PQclear (result);
1410 return GNUNET_SYSERR;
1411 }
1412 PQclear (result);
1413 return GNUNET_OK;
1414}
1415
1416
1417
1418int
1419TALER_MINT_DB_get_refresh_melt (PGconn *db_conn,
1420 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
1421 uint16_t oldcoin_index,
1422 struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub)
1423{
1424 uint16_t oldcoin_index_nbo = htons (oldcoin_index);
1425 struct TALER_DB_QueryParam params[] = {
1426 TALER_DB_QUERY_PARAM_PTR(session_pub),
1427 TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo),
1428 TALER_DB_QUERY_PARAM_END
1429 };
1430
1431 PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_melt", params);
1432
1433 if (PGRES_TUPLES_OK != PQresultStatus (result))
1434 {
1435 break_db_err (result);
1436 PQclear (result);
1437 return GNUNET_SYSERR;
1438 }
1439
1440 if (0 == PQntuples (result))
1441 {
1442 PQclear (result);
1443 return GNUNET_NO;
1444 }
1445
1446 GNUNET_assert (1 == PQntuples (result));
1447
1448 struct TALER_DB_ResultSpec rs[] = {
1449 TALER_DB_RESULT_SPEC("coin_pub", coin_pub),
1450 TALER_DB_RESULT_SPEC_END
1451 };
1452
1453 if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0))
1454 {
1455 PQclear (result);
1456 GNUNET_break (0);
1457 return GNUNET_SYSERR;
1458 }
1459
1460 PQclear (result);
1461 return GNUNET_OK;
1462}
1463
1464
1465int
1466TALER_db_get_link (PGconn *db_conn,
1467 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
1468 LinkIterator link_iter,
1469 void *cls)
1470{
1471 struct TALER_DB_QueryParam params[] = {
1472 TALER_DB_QUERY_PARAM_PTR(coin_pub),
1473 TALER_DB_QUERY_PARAM_END
1474 };
1475
1476 PGresult *result = TALER_DB_exec_prepared (db_conn, "get_link", params);
1477
1478 if (PGRES_TUPLES_OK != PQresultStatus (result))
1479 {
1480 break_db_err (result);
1481 PQclear (result);
1482 return GNUNET_SYSERR;
1483 }
1484
1485 if (0 == PQntuples (result))
1486 {
1487 PQclear (result);
1488 return GNUNET_NO;
1489 }
1490
1491
1492 int i = 0;
1493 int res;
1494
1495 for (i = 0; i < PQntuples (result); i++)
1496 {
1497 struct LinkDataEnc link_data_enc;
1498 struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
1499 struct TALER_RSA_Signature ev_sig;
1500 struct TALER_DB_ResultSpec rs[] = {
1501 TALER_DB_RESULT_SPEC("link_vector_enc", &link_data_enc),
1502 TALER_DB_RESULT_SPEC("denom_pub", &denom_pub),
1503 TALER_DB_RESULT_SPEC("ev_sig", &ev_sig),
1504 TALER_DB_RESULT_SPEC_END
1505 };
1506
1507 if (GNUNET_OK != TALER_DB_extract_result (result, rs, i))
1508 {
1509 PQclear (result);
1510 GNUNET_break (0);
1511 return GNUNET_SYSERR;
1512 }
1513
1514 if (GNUNET_OK != (res = link_iter (cls, &link_data_enc, &denom_pub, &ev_sig)))
1515 {
1516 GNUNET_assert (GNUNET_SYSERR != res);
1517 PQclear (result);
1518 return res;
1519 }
1520 }
1521
1522 PQclear (result);
1523 return GNUNET_OK;
1524}
1525
1526
1527int
1528TALER_db_get_transfer (PGconn *db_conn,
1529 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
1530 struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub,
1531 struct SharedSecretEnc *shared_secret_enc)
1532{
1533 struct TALER_DB_QueryParam params[] = {
1534 TALER_DB_QUERY_PARAM_PTR(coin_pub),
1535 TALER_DB_QUERY_PARAM_END
1536 };
1537
1538 PGresult *result = TALER_DB_exec_prepared (db_conn, "get_transfer", params);
1539
1540 if (PGRES_TUPLES_OK != PQresultStatus (result))
1541 {
1542 break_db_err (result);
1543 PQclear (result);
1544 return GNUNET_SYSERR;
1545 }
1546
1547 if (0 == PQntuples (result))
1548 {
1549 PQclear (result);
1550 return GNUNET_NO;
1551 }
1552
1553 if (1 != PQntuples (result))
1554 {
1555 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "got %d tuples for get_transfer\n", PQntuples (result));
1556 GNUNET_break (0);
1557 return GNUNET_SYSERR;
1558 }
1559
1560 struct TALER_DB_ResultSpec rs[] = {
1561 TALER_DB_RESULT_SPEC("transfer_pub", transfer_pub),
1562 TALER_DB_RESULT_SPEC("link_secret_enc", shared_secret_enc),
1563 TALER_DB_RESULT_SPEC_END
1564 };
1565
1566 if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0))
1567 {
1568 PQclear (result);
1569 GNUNET_break (0);
1570 return GNUNET_SYSERR;
1571 }
1572
1573 PQclear (result);
1574 return GNUNET_OK;
1575}
1576
1577
1578int
1579TALER_MINT_DB_init_deposits (PGconn *conn, int tmp)
1580{
1581 const char *tmp_str = (1 == tmp) ? "TEMPORARY" : "";
1582 char *sql;
1583 PGresult *res;
1584 int ret;
1585
1586 res = NULL;
1587 (void) GNUNET_asprintf (&sql,
1588 "CREATE %1$s TABLE IF NOT EXISTS deposits ("
1589 " coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (length(coin_pub)=32)"
1590 ",denom_pub BYTEA NOT NULL CHECK (length(denom_pub)=32)"
1591 ",transaction_id INT8 NOT NULL"
1592 ",amount_value INT4 NOT NULL"
1593 ",amount_fraction INT4 NOT NULL"
1594 ",amount_currency VARCHAR(4) NOT NULL"
1595 ",merchant_pub BYTEA NOT NULL"
1596 ",h_contract BYTEA NOT NULL CHECK (length(h_contract)=64)"
1597 ",h_wire BYTEA NOT NULL CHECK (length(h_wire)=64)"
1598 ",coin_sig BYTEA NOT NULL CHECK (length(coin_sig)=64)"
1599 ",wire TEXT NOT NULL"
1600 ")",
1601 tmp_str);
1602 res = PQexec (conn, sql);
1603 GNUNET_free (sql);
1604 if (PGRES_COMMAND_OK != PQresultStatus (res))
1605 {
1606 break_db_err (res);
1607 ret = GNUNET_SYSERR;
1608 }
1609 else
1610 ret = GNUNET_OK;
1611 PQclear (res);
1612 return ret;
1613}
1614
1615int
1616TALER_MINT_DB_prepare_deposits (PGconn *db_conn)
1617{
1618 PGresult *result;
1619
1620 result = PQprepare (db_conn, "insert_deposit",
1621 "INSERT INTO deposits ("
1622 "coin_pub,"
1623 "denom_pub,"
1624 "transaction_id,"
1625 "amount_value,"
1626 "amount_fraction,"
1627 "amount_currency,"
1628 "merchant_pub,"
1629 "h_contract,"
1630 "h_wire,"
1631 "coin_sig,"
1632 "wire"
1633 ") VALUES ("
1634 "$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11"
1635 ")",
1636 11, NULL);
1637 EXITIF (PGRES_COMMAND_OK != PQresultStatus(result));
1638 PQclear (result);
1639
1640 result = PQprepare (db_conn, "get_deposit",
1641 "SELECT "
1642 "coin_pub,"
1643 "denom_pub,"
1644 "transaction_id,"
1645 "amount_value,"
1646 "amount_fraction,"
1647 "amount_currency,"
1648 "merchant_pub,"
1649 "h_contract,"
1650 "h_wire,"
1651 "coin_sig"
1652 " FROM deposits WHERE ("
1653 "coin_pub = $1"
1654 ")",
1655 1, NULL);
1656 EXITIF (PGRES_COMMAND_OK != PQresultStatus(result));
1657 PQclear (result);
1658
1659 return GNUNET_OK;
1660
1661 EXITIF_exit:
1662 break_db_err (result);
1663 PQclear (result);
1664 return GNUNET_SYSERR;
1665}
1666
1667
1668int
1669TALER_MINT_DB_insert_deposit (PGconn *db_conn,
1670 const struct Deposit *deposit)
1671{
1672 struct TALER_DB_QueryParam params[]= {
1673 TALER_DB_QUERY_PARAM_PTR (&deposit->coin_pub),
1674 TALER_DB_QUERY_PARAM_PTR (&deposit->denom_pub),
1675 TALER_DB_QUERY_PARAM_PTR (&deposit->transaction_id),
1676 TALER_DB_QUERY_PARAM_PTR (&deposit->amount.value),
1677 TALER_DB_QUERY_PARAM_PTR (&deposit->amount.fraction),
1678 TALER_DB_QUERY_PARAM_PTR_SIZED (deposit->amount.currency, strlen (deposit->amount.currency)),
1679 TALER_DB_QUERY_PARAM_PTR (&deposit->merchant_pub),
1680 TALER_DB_QUERY_PARAM_PTR (&deposit->h_contract),
1681 TALER_DB_QUERY_PARAM_PTR (&deposit->h_wire),
1682 TALER_DB_QUERY_PARAM_PTR (&deposit->coin_sig),
1683 TALER_DB_QUERY_PARAM_PTR_SIZED (deposit->wire, strlen(deposit->wire)),
1684 TALER_DB_QUERY_PARAM_END
1685 };
1686 PGresult *result;
1687
1688 result = TALER_DB_exec_prepared (db_conn, "insert_deposit", params);
1689 if (PGRES_COMMAND_OK != PQresultStatus (result))
1690 {
1691 break_db_err (result);
1692 PQclear (result);
1693 return GNUNET_SYSERR;
1694 }
1695 PQclear (result);
1696 return GNUNET_OK;
1697}
1698
1699int
1700TALER_MINT_DB_get_deposit (PGconn *db_conn,
1701 const struct GNUNET_CRYPTO_EddsaPublicKey *coin_pub,
1702 struct Deposit **r_deposit)
1703{
1704 struct TALER_DB_QueryParam params[] = {
1705 TALER_DB_QUERY_PARAM_PTR (coin_pub),
1706 TALER_DB_QUERY_PARAM_END
1707 };
1708 PGresult *result;
1709 struct Deposit *deposit;
1710
1711 deposit = NULL;
1712 result = TALER_DB_exec_prepared (db_conn, "get_deposit", params);
1713 if (PGRES_TUPLES_OK != PQresultStatus (result))
1714 {
1715 break_db_err (result);
1716 goto EXITIF_exit;
1717 }
1718
1719 if (0 == PQntuples (result))
1720 {
1721 PQclear (result);
1722 return GNUNET_NO;
1723 }
1724
1725 if (1 != PQntuples (result))
1726 {
1727 GNUNET_break (0);
1728 goto EXITIF_exit;
1729 }
1730
1731 {
1732 deposit = GNUNET_malloc (sizeof (struct Deposit)); /* Without wire data */
1733 struct TALER_DB_ResultSpec rs[] = {
1734 TALER_DB_RESULT_SPEC ("coin_pub", &deposit->coin_pub),
1735 TALER_DB_RESULT_SPEC ("denom_pub", &deposit->denom_pub),
1736 TALER_DB_RESULT_SPEC ("coin_sig", &deposit->coin_sig),
1737 TALER_DB_RESULT_SPEC ("transaction_id", &deposit->transaction_id),
1738 TALER_DB_RESULT_SPEC ("merchant_pub", &deposit->merchant_pub),
1739 TALER_DB_RESULT_SPEC ("h_contract", &deposit->h_contract),
1740 TALER_DB_RESULT_SPEC ("h_wire", &deposit->h_wire),
1741 TALER_DB_RESULT_SPEC_END
1742 };
1743 EXITIF (GNUNET_OK != TALER_DB_extract_result (result, rs, 0));
1744 EXITIF (GNUNET_OK != TALER_DB_extract_amount_nbo (result, 0,
1745 "amount_value",
1746 "amount_fraction",
1747 "amount_currency",
1748 &deposit->amount));
1749 deposit->purpose.purpose = htonl (TALER_SIGNATURE_DEPOSIT);
1750 deposit->purpose.size = htonl (sizeof (struct Deposit)
1751 - offsetof (struct Deposit, purpose));
1752 }
1753
1754 PQclear (result);
1755 *r_deposit = deposit;
1756 return GNUNET_OK;
1757
1758EXITIF_exit:
1759 PQclear (result);
1760 GNUNET_free_non_null (deposit);
1761 deposit = NULL;
1762 return GNUNET_SYSERR;
1763}
1764
1765
1766
1767/**
1768 * Get the thread-local database-handle.
1769 * Connect to the db if the connection does not exist yet.
1770 *
1771 * @param the database connection, or NULL on error
1772 */
1773PGconn *
1774TALER_MINT_DB_get_connection (void)
1775{
1776 PGconn *db_conn;
1777
1778 if (NULL != (db_conn = pthread_getspecific (db_conn_threadlocal)))
1779 return db_conn;
1780
1781 db_conn = PQconnectdb (TALER_MINT_db_connection_cfg_str);
1782
1783 if (CONNECTION_OK != PQstatus (db_conn))
1784 {
1785 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1786 "db connection failed: %s\n",
1787 PQerrorMessage (db_conn));
1788 GNUNET_break (0);
1789 return NULL;
1790 }
1791
1792 if (GNUNET_OK != TALER_MINT_DB_prepare (db_conn))
1793 {
1794 GNUNET_break (0);
1795 return NULL;
1796 }
1797 if (0 != pthread_setspecific (db_conn_threadlocal, db_conn))
1798 {
1799 GNUNET_break (0);
1800 return NULL;
1801 }
1802 return db_conn;
1803}
1804
1805
1806/**
1807 * Close thread-local database connection when a thread is destroyed.
1808 *
1809 * @param closure we get from pthreads (the db handle)
1810 */
1811static void
1812db_conn_destroy (void *cls)
1813{
1814 PGconn *db_conn = cls;
1815 if (NULL != db_conn)
1816 PQfinish (db_conn);
1817}
1818
1819
1820/**
1821 * Initialize database subsystem.
1822 *
1823 * @param connection_cfg configuration to use to talk to DB
1824 * @return GNUNET_OK on success
1825 */
1826int
1827TALER_MINT_DB_init (const char *connection_cfg)
1828{
1829
1830 if (0 != pthread_key_create (&db_conn_threadlocal, &db_conn_destroy))
1831 {
1832 fprintf (stderr,
1833 "Can't create pthread key.\n");
1834 return GNUNET_SYSERR;
1835 }
1836 TALER_MINT_db_connection_cfg_str = GNUNET_strdup (connection_cfg);
1837 return GNUNET_OK;
1838}
diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h
new file mode 100644
index 000000000..4f47aac1c
--- /dev/null
+++ b/src/mint/mint_db.h
@@ -0,0 +1,344 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file mint/mint_db.h
19 * @brief Mint-specific database access
20 * @author Florian Dold
21 */
22
23#ifndef _NEURO_MINT_DB_H
24#define _NEURO_MINT_DB_H
25
26#include <libpq-fe.h>
27#include <gnunet/gnunet_util_lib.h>
28#include "taler_util.h"
29#include "taler_types.h"
30#include "taler_rsa.h"
31
32
33/**
34 * Reserve row. Corresponds to table 'reserves' in
35 * the mint's database.
36 */
37struct Reserve
38{
39 /**
40 * Signature over the purse.
41 * Only valid if (blind_session_missing==GNUNET_YES).
42 */
43 struct GNUNET_CRYPTO_EddsaSignature status_sig;
44 /**
45 * Signature with purpose TALER_SIGNATURE_PURSE.
46 * Only valid if (blind_session_missing==GNUNET_YES).
47 */
48 struct GNUNET_CRYPTO_EccSignaturePurpose status_sig_purpose;
49 /**
50 * Signing key used to sign the purse.
51 * Only valid if (blind_session_missing==GNUNET_YES).
52 */
53 struct GNUNET_CRYPTO_EddsaPublicKey status_sign_pub;
54 /**
55 * Withdraw public key, identifies the purse.
56 * Only the customer knows the corresponding private key.
57 */
58 struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
59 /**
60 * Remaining balance in the purse.
61 */
62 struct TALER_AmountNBO balance;
63
64 /**
65 * Expiration date for the purse.
66 */
67 struct GNUNET_TIME_AbsoluteNBO expiration;
68};
69
70
71struct CollectableBlindcoin
72{
73 struct TALER_RSA_BlindedSignaturePurpose ev;
74 struct TALER_RSA_Signature ev_sig;
75 struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
76 struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
77 struct GNUNET_CRYPTO_EddsaSignature reserve_sig;
78};
79
80
81struct RefreshSession
82{
83 int has_commit_sig;
84 struct GNUNET_CRYPTO_EddsaSignature commit_sig;
85 struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
86 uint16_t num_oldcoins;
87 uint16_t num_newcoins;
88 uint16_t kappa;
89 uint16_t noreveal_index;
90 uint8_t reveal_ok;
91};
92
93
94#define TALER_REFRESH_SHARED_SECRET_LENGTH (sizeof (struct GNUNET_HashCode))
95#define TALER_REFRESH_LINK_LENGTH (sizeof (struct LinkData))
96
97struct RefreshCommitLink
98{
99 struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
100 struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub;
101 uint16_t cnc_index;
102 uint16_t oldcoin_index;
103 char shared_secret_enc[sizeof (struct GNUNET_HashCode)];
104};
105
106struct LinkData
107{
108 struct GNUNET_CRYPTO_EcdsaPrivateKey coin_priv;
109 struct TALER_RSA_BlindingKeyBinaryEncoded bkey_enc;
110};
111
112
113GNUNET_NETWORK_STRUCT_BEGIN
114
115struct SharedSecretEnc
116{
117 char data[TALER_REFRESH_SHARED_SECRET_LENGTH];
118};
119
120
121struct LinkDataEnc
122{
123 char data[sizeof (struct LinkData)];
124};
125
126GNUNET_NETWORK_STRUCT_END
127
128struct RefreshCommitCoin
129{
130 struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
131 struct TALER_RSA_BlindedSignaturePurpose coin_ev;
132 uint16_t cnc_index;
133 uint16_t newcoin_index;
134 char link_enc[sizeof (struct LinkData)];
135};
136
137
138struct KnownCoin
139{
140 struct TALER_CoinPublicInfo public_info;
141 struct TALER_Amount expended_balance;
142 int is_refreshed;
143 /**
144 * Refreshing session, only valid if
145 * is_refreshed==1.
146 */
147 struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub;
148};
149
150GNUNET_NETWORK_STRUCT_BEGIN
151
152struct Deposit
153{
154 /* FIXME: should be TALER_CoinPublicInfo */
155 struct GNUNET_CRYPTO_EddsaPublicKey coin_pub;
156 struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
157 struct TALER_RSA_Signature coin_sig;
158 struct TALER_RSA_SignaturePurpose purpose;
159 uint64_t transaction_id;
160 struct TALER_AmountNBO amount;
161 struct GNUNET_CRYPTO_EddsaPublicKey merchant_pub;
162 struct GNUNET_HashCode h_contract;
163 struct GNUNET_HashCode h_wire;
164 /* TODO: uint16_t wire_size */
165 char wire[]; /* string encoded wire JSON object */
166};
167
168GNUNET_NETWORK_STRUCT_END
169
170int
171TALER_MINT_DB_prepare (PGconn *db_conn);
172
173int
174TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn,
175 struct TALER_RSA_BlindedSignaturePurpose *blind_ev,
176 struct CollectableBlindcoin *collectable);
177
178int
179TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn,
180 const struct CollectableBlindcoin *collectable);
181
182
183int
184TALER_MINT_DB_rollback (PGconn *db_conn);
185
186
187int
188TALER_MINT_DB_transaction (PGconn *db_conn);
189
190
191int
192TALER_MINT_DB_commit (PGconn *db_conn);
193
194
195int
196TALER_MINT_DB_get_reserve (PGconn *db_conn,
197 const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub,
198 struct Reserve *reserve_res);
199
200int
201TALER_MINT_DB_update_reserve (PGconn *db_conn,
202 const struct Reserve *reserve,
203 int fresh);
204
205
206int
207TALER_MINT_DB_insert_refresh_order (PGconn *db_conn,
208 uint16_t newcoin_index,
209 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
210 const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub);
211
212int
213TALER_MINT_DB_get_refresh_session (PGconn *db_conn,
214 const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
215 struct RefreshSession *r_session);
216
217
218int
219TALER_MINT_DB_get_known_coin (PGconn *db_conn, struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
220 struct KnownCoin *known_coin);
221
222
223int
224TALER_MINT_DB_upsert_known_coin (PGconn *db_conn, struct KnownCoin *known_coin);
225
226
227int
228TALER_MINT_DB_insert_refresh_commit_link (PGconn *db_conn, struct RefreshCommitLink *commit_link);
229
230int
231TALER_MINT_DB_insert_refresh_commit_coin (PGconn *db_conn, struct RefreshCommitCoin *commit_coin);
232
233
234int
235TALER_MINT_DB_get_refresh_commit_link (PGconn *db_conn,
236 const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
237 int i, int j,
238 struct RefreshCommitLink *commit_link);
239
240
241int
242TALER_MINT_DB_get_refresh_commit_coin (PGconn *db_conn,
243 const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
244 int i, int j,
245 struct RefreshCommitCoin *commit_coin);
246
247
248int
249TALER_MINT_DB_create_refresh_session (PGconn *db_conn,
250 const struct GNUNET_CRYPTO_EddsaPublicKey
251 *session_pub);
252
253
254int
255TALER_MINT_DB_get_refresh_order (PGconn *db_conn,
256 uint16_t newcoin_index,
257 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
258 struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub);
259
260
261int
262TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn,
263 uint16_t newcoin_index,
264 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
265 const struct TALER_RSA_Signature *ev_sig);
266int
267TALER_MINT_DB_get_refresh_collectable (PGconn *db_conn,
268 uint16_t newcoin_index,
269 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
270 struct TALER_RSA_Signature *ev_sig);
271int
272TALER_MINT_DB_set_reveal_ok (PGconn *db_conn,
273 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub);
274
275int
276TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn,
277 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
278 uint16_t oldcoin_index,
279 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
280 const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub);
281
282
283int
284TALER_MINT_DB_get_refresh_melt (PGconn *db_conn,
285 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
286 uint16_t oldcoin_index,
287 struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub);
288
289
290typedef
291int (*LinkIterator) (void *cls,
292 const struct LinkDataEnc *link_data_enc,
293 const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub,
294 const struct TALER_RSA_Signature *ev_sig);
295
296int
297TALER_db_get_link (PGconn *db_conn,
298 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
299 LinkIterator link_iter,
300 void *cls);
301
302
303int
304TALER_db_get_transfer (PGconn *db_conn,
305 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
306 struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub,
307 struct SharedSecretEnc *shared_secret_enc);
308
309int
310TALER_MINT_DB_init_deposits (PGconn *db_conn, int temporary);
311
312int
313TALER_MINT_DB_prepare_deposits (PGconn *db_conn);
314
315int
316TALER_MINT_DB_insert_deposit (PGconn *db_conn,
317 const struct Deposit *deposit);
318
319int
320TALER_MINT_DB_get_deposit (PGconn *db_conn,
321 const struct GNUNET_CRYPTO_EddsaPublicKey *coin_pub,
322 struct Deposit **r_deposit);
323int
324TALER_MINT_DB_insert_known_coin (PGconn *db_conn,
325 const struct KnownCoin *known_coin);
326
327
328
329/**
330 * Get the thread-local database-handle.
331 * Connect to the db if the connection does not exist yet.
332 *
333 * @param the database connection, or NULL on error
334 */
335PGconn *
336TALER_MINT_DB_get_connection (void);
337
338
339int
340TALER_MINT_DB_init (const char *connection_cfg);
341
342
343
344#endif /* _NEURO_MINT_DB_H */
diff --git a/src/mint/taler-mint-dbinit.c b/src/mint/taler-mint-dbinit.c
new file mode 100644
index 000000000..d877f62c6
--- /dev/null
+++ b/src/mint/taler-mint-dbinit.c
@@ -0,0 +1,285 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file taler-mint-dbinit.c
19 * @brief Create tables for the mint database.
20 * @author Florian Dold
21 */
22
23#include "platform.h"
24#include <gnunet/gnunet_util_lib.h>
25#include <libpq-fe.h>
26#include "mint.h"
27
28
29#define break_db_err(result) do { \
30 GNUNET_break(0); \
31 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Database failure: %s\n", PQresultErrorMessage (result)); \
32 PQclear (result); \
33 } while (0)
34
35
36static char *mint_base_dir;
37static struct GNUNET_CONFIGURATION_Handle *cfg;
38static PGconn *db_conn;
39static char *TALER_MINT_db_connection_cfg_str;
40
41
42int
43TALER_MINT_init_withdraw_tables (PGconn *conn)
44{
45 PGresult *result;
46 result = PQexec (conn,
47 "CREATE TABLE IF NOT EXISTS reserves"
48 "("
49 " reserve_pub BYTEA PRIMARY KEY"
50 ",balance_value INT4 NOT NULL"
51 ",balance_fraction INT4 NOT NULL"
52 ",balance_currency VARCHAR(4) NOT NULL"
53 ",status_sig BYTEA"
54 ",status_sign_pub BYTEA"
55 ",expiration_date INT8 NOT NULL"
56 ")");
57 if (PGRES_COMMAND_OK != PQresultStatus(result))
58 {
59 break_db_err (result);
60 return GNUNET_SYSERR;
61 }
62 PQclear (result);
63
64 result = PQexec (conn,
65 "CREATE TABLE IF NOT EXISTS collectable_blindcoins"
66 "("
67 "blind_ev BYTEA PRIMARY KEY"
68 ",blind_ev_sig BYTEA NOT NULL"
69 ",denom_pub BYTEA NOT NULL"
70 ",reserve_sig BYTEA NOT NULL"
71 ",reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub)"
72 ")");
73 if (PGRES_COMMAND_OK != PQresultStatus(result))
74 {
75 break_db_err (result);
76 return GNUNET_SYSERR;
77 }
78 PQclear (result);
79
80 result = PQexec (conn,
81 "CREATE TABLE IF NOT EXISTS known_coins "
82 "("
83 " coin_pub BYTEA NOT NULL PRIMARY KEY"
84 ",denom_pub BYTEA NOT NULL"
85 ",denom_sig BYTEA NOT NULL"
86 ",expended_value INT4 NOT NULL"
87 ",expended_fraction INT4 NOT NULL"
88 ",expended_currency VARCHAR(4) NOT NULL"
89 ",refresh_session_pub BYTEA"
90 ")");
91 if (PGRES_COMMAND_OK != PQresultStatus(result))
92 {
93 break_db_err (result);
94 return GNUNET_SYSERR;
95 }
96 PQclear (result);
97
98 result = PQexec (conn,
99 "CREATE TABLE IF NOT EXISTS refresh_sessions "
100 "("
101 " session_pub BYTEA PRIMARY KEY CHECK (length(session_pub) = 32)"
102 ",session_melt_sig BYTEA"
103 ",session_commit_sig BYTEA"
104 ",noreveal_index INT2 NOT NULL"
105 // non-zero if all reveals were ok
106 // and the new coin signatures are ready
107 ",reveal_ok BOOLEAN NOT NULL DEFAULT false"
108 ") ");
109 if (PGRES_COMMAND_OK != PQresultStatus(result))
110 {
111 break_db_err (result);
112 return GNUNET_SYSERR;
113 }
114 PQclear (result);
115
116 result = PQexec (conn,
117 "CREATE TABLE IF NOT EXISTS refresh_order "
118 "( "
119 " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub)"
120 ",newcoin_index INT2 NOT NULL "
121 ",denom_pub BYTEA NOT NULL "
122 ",PRIMARY KEY (session_pub, newcoin_index)"
123 ") ");
124
125 if (PGRES_COMMAND_OK != PQresultStatus(result))
126 {
127 break_db_err (result);
128 return GNUNET_SYSERR;
129 }
130 PQclear (result);
131
132
133 result = PQexec (conn,
134 "CREATE TABLE IF NOT EXISTS refresh_commit_link"
135 "("
136 " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub)"
137 ",transfer_pub BYTEA NOT NULL"
138 ",link_secret_enc BYTEA NOT NULL"
139 // index of the old coin in the customer's request
140 ",oldcoin_index INT2 NOT NULL"
141 // index for cut and choose,
142 // ranges from 0 to kappa-1
143 ",cnc_index INT2 NOT NULL"
144 ")");
145
146 if (PGRES_COMMAND_OK != PQresultStatus(result))
147 {
148 break_db_err (result);
149 return GNUNET_SYSERR;
150 }
151 PQclear (result);
152
153 result = PQexec (conn,
154 "CREATE TABLE IF NOT EXISTS refresh_commit_coin"
155 "("
156 " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) "
157 ",link_vector_enc BYTEA NOT NULL"
158 // index of the new coin in the customer's request
159 ",newcoin_index INT2 NOT NULL"
160 // index for cut and choose,
161 ",cnc_index INT2 NOT NULL"
162 ",coin_ev BYTEA NOT NULL"
163 ")");
164
165 if (PGRES_COMMAND_OK != PQresultStatus(result))
166 {
167 break_db_err (result);
168 return GNUNET_SYSERR;
169 }
170 PQclear (result);
171
172 result = PQexec (conn,
173 "CREATE TABLE IF NOT EXISTS refresh_melt"
174 "("
175 " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) "
176 ",coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) "
177 ",denom_pub BYTEA NOT NULL "
178 ",oldcoin_index INT2 NOT NULL"
179 ")");
180
181 if (PGRES_COMMAND_OK != PQresultStatus(result))
182 {
183 break_db_err (result);
184 return GNUNET_SYSERR;
185 }
186 PQclear (result);
187
188 result = PQexec (conn,
189 "CREATE TABLE IF NOT EXISTS refresh_collectable"
190 "("
191 " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) "
192 ",ev_sig BYTEA NOT NULL"
193 ",newcoin_index INT2 NOT NULL"
194 ")");
195
196 if (PGRES_COMMAND_OK != PQresultStatus(result))
197 {
198 break_db_err (result);
199 return GNUNET_SYSERR;
200 }
201 PQclear (result);
202
203 result = PQexec (conn,
204 "CREATE TABLE IF NOT EXISTS deposits "
205 "( "
206 " coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (length(coin_pub)=32)"
207 ",denom_pub BYTEA NOT NULL CHECK (length(denom_pub)=32)"
208 ",transaction_id INT8 NOT NULL"
209 ",amount_currency VARCHAR(4) NOT NULL"
210 ",amount_value INT4 NOT NULL"
211 ",amount_fraction INT4 NOT NULL"
212 ",merchant_pub BYTEA NOT NULL"
213 ",h_contract BYTEA NOT NULL CHECK (length(h_contract)=64)"
214 ",h_wire BYTEA NOT NULL CHECK (length(h_wire)=64)"
215 ",coin_sig BYTEA NOT NULL CHECK (length(coin_sig)=64)"
216 ",wire TEXT NOT NULL"
217 ")");
218
219 if (PGRES_COMMAND_OK != PQresultStatus(result))
220 {
221 break_db_err (result);
222 return GNUNET_SYSERR;
223 }
224 PQclear (result);
225
226 return GNUNET_OK;
227}
228
229
230/**
231 * The main function of the serve tool
232 *
233 * @param argc number of arguments from the command line
234 * @param argv command line arguments
235 * @return 0 ok, 1 on error
236 */
237int
238main (int argc, char *const *argv)
239{
240 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
241 GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keyup OPTIONS"),
242 {'d', "mint-dir", "DIR",
243 "mint directory", 1,
244 &GNUNET_GETOPT_set_filename, &mint_base_dir},
245 GNUNET_GETOPT_OPTION_END
246 };
247
248 if (GNUNET_GETOPT_run ("taler-mint-serve", options, argc, argv) < 0)
249 return 1;
250
251 GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-dbinit", "INFO", NULL));
252
253 if (NULL == mint_base_dir)
254 {
255 fprintf (stderr, "Mint base directory not given.\n");
256 return 1;
257 }
258
259 cfg = TALER_MINT_config_load (mint_base_dir);
260 if (NULL == cfg)
261 {
262 fprintf (stderr, "Can't load mint configuration.\n");
263 return 1;
264 }
265 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "mint", "db", &TALER_MINT_db_connection_cfg_str))
266 {
267 fprintf (stderr, "Configuration 'mint.db' not found.\n");
268 return 42;
269 }
270 db_conn = PQconnectdb (TALER_MINT_db_connection_cfg_str);
271 if (CONNECTION_OK != PQstatus (db_conn))
272 {
273 fprintf (stderr, "Database connection failed: %s\n", PQerrorMessage (db_conn));
274 return 1;
275 }
276
277 if (GNUNET_OK != TALER_MINT_init_withdraw_tables (db_conn))
278 {
279 fprintf (stderr, "Failed to initialize database.\n");
280 return 1;
281 }
282
283 return 0;
284}
285
diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c
new file mode 100644
index 000000000..6d69813c0
--- /dev/null
+++ b/src/mint/taler-mint-httpd.c
@@ -0,0 +1,376 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file taler-mint-httpd.c
19 * @brief Serve the HTTP interface of the mint
20 * @author Florian Dold
21 * @author Benedikt Mueller
22 * @author Christian Grothoff
23 */
24#include "platform.h"
25#include <gnunet/gnunet_util_lib.h>
26#include <jansson.h>
27#include <microhttpd.h>
28#include <libpq-fe.h>
29#include <pthread.h>
30#include "mint.h"
31#include "mint_db.h"
32#include "taler_types.h"
33#include "taler_signatures.h"
34#include "taler_rsa.h"
35#include "taler_json_lib.h"
36#include "taler_microhttpd_lib.h"
37#include "taler-mint-httpd_mhd.h"
38#include "taler-mint-httpd_keys.h"
39#include "taler-mint-httpd_deposit.h"
40#include "taler-mint-httpd_withdraw.h"
41#include "taler-mint-httpd_refresh.h"
42
43
44/**
45 * Base directory of the mint (global)
46 */
47char *mintdir;
48
49/**
50 * The mint's configuration (global)
51 */
52struct GNUNET_CONFIGURATION_Handle *cfg;
53
54/**
55 * Master public key (according to the
56 * configuration in the mint directory).
57 */
58struct GNUNET_CRYPTO_EddsaPublicKey master_pub;
59
60/**
61 * The HTTP Daemon.
62 */
63static struct MHD_Daemon *mydaemon;
64
65/**
66 * The kappa value for refreshing.
67 */
68static unsigned int refresh_security_parameter;
69
70/**
71 * Port to run the daemon on.
72 */
73static uint16_t serve_port;
74
75
76/**
77 * Convert a string representing an EdDSA signature to an EdDSA
78 * signature.
79 *
80 * FIXME: this should be in GNUnet.
81 * FIXME: why? this code is dead, even here!
82 *
83 * @param enc encoded EdDSA signature
84 * @param enclen number of bytes in @a enc (without 0-terminator)
85 * @param pub where to store the EdDSA signature
86 * @return #GNUNET_OK on success
87 */
88int
89TALER_eddsa_signature_from_string (const char *enc,
90 size_t enclen,
91 struct GNUNET_CRYPTO_EddsaSignature *sig)
92{
93 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaSignature)) * 8;
94
95 if (keylen % 5 > 0)
96 keylen += 5 - keylen % 5;
97 keylen /= 5;
98 if (enclen != keylen)
99 return GNUNET_SYSERR;
100
101 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
102 sig,
103 sizeof (struct GNUNET_CRYPTO_EddsaSignature)))
104 return GNUNET_SYSERR;
105 return GNUNET_OK;
106}
107
108
109/**
110 * Handle a request coming from libmicrohttpd.
111 *
112 * @param cls closure for MHD daemon (unused)
113 * @param connection the connection
114 * @param url the requested url
115 * @param method the method (POST, GET, ...)
116 * @param upload_data request data
117 * @param upload_data_size size of @a upload_data in bytes
118 * @param con_cls closure for request (a `struct Buffer *`)
119 * @return MHD result code
120 */
121static int
122handle_mhd_request (void *cls,
123 struct MHD_Connection *connection,
124 const char *url,
125 const char *method,
126 const char *version,
127 const char *upload_data,
128 size_t *upload_data_size,
129 void **con_cls)
130{
131 static struct RequestHandler handlers[] =
132 {
133 { "/", MHD_HTTP_METHOD_GET, "text/plain",
134 "Hello, I'm the mint\n", 0,
135 &TALER_MINT_handler_static_response, MHD_HTTP_OK },
136 { "/agpl", MHD_HTTP_METHOD_GET, "text/plain",
137 NULL, 0,
138 &TALER_MINT_handler_agpl_redirect, MHD_HTTP_FOUND },
139 { "/keys", MHD_HTTP_METHOD_GET, "application/json",
140 NULL, 0,
141 &TALER_MINT_handler_keys, MHD_HTTP_OK },
142 { "/keys", NULL, "text/plain",
143 "Only GET is allowed", 0,
144 &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
145 { "/withdraw/status", MHD_HTTP_METHOD_GET, "application/json",
146 NULL, 0,
147 &TALER_MINT_handler_withdraw_status, MHD_HTTP_OK },
148 { "/withdraw/status", NULL, "text/plain",
149 "Only GET is allowed", 0,
150 &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
151 { "/withdraw/sign", MHD_HTTP_METHOD_GET, "application/json",
152 NULL, 0,
153 &TALER_MINT_handler_withdraw_sign, MHD_HTTP_OK },
154 { "/withdraw/sign", NULL, "text/plain",
155 "Only GET is allowed", 0,
156 &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
157 { "/refresh/melt", MHD_HTTP_METHOD_POST, "application/json",
158 NULL, 0,
159 &TALER_MINT_handler_refresh_melt, MHD_HTTP_OK },
160 { "/refresh/melt", NULL, "text/plain",
161 "Only POST is allowed", 0,
162 &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
163 { "/refresh/commit", MHD_HTTP_METHOD_POST, "application/json",
164 NULL, 0,
165 &TALER_MINT_handler_refresh_commit, MHD_HTTP_OK },
166 { "/refresh/commit", NULL, "text/plain",
167 "Only POST is allowed", 0,
168 &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
169 { "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json",
170 NULL, 0,
171 &TALER_MINT_handler_refresh_melt, MHD_HTTP_OK },
172 { "/refresh/reveal", NULL, "text/plain",
173 "Only POST is allowed", 0,
174 &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
175 { "/refresh/link", MHD_HTTP_METHOD_GET, "application/json",
176 NULL, 0,
177 &TALER_MINT_handler_refresh_link, MHD_HTTP_OK },
178 { "/refresh/link", NULL, "text/plain",
179 "Only GET is allowed", 0,
180 &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
181 { "/refresh/reveal", MHD_HTTP_METHOD_GET, "application/json",
182 NULL, 0,
183 &TALER_MINT_handler_refresh_reveal, MHD_HTTP_OK },
184 { "/refresh/reveal", NULL, "text/plain",
185 "Only GET is allowed", 0,
186 &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
187 { "/deposit", MHD_HTTP_METHOD_POST, "application/json",
188 NULL, 0,
189 &TALER_MINT_handler_deposit, MHD_HTTP_OK },
190 { "/deposit", NULL, "text/plain",
191 "Only POST is allowed", 0,
192 &TALER_MINT_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
193 { NULL, NULL, NULL, NULL, 0, 0 }
194 };
195 static struct RequestHandler h404 =
196 {
197 "", NULL, "text/html",
198 "<html><title>404: not found</title></html>", 0,
199 &TALER_MINT_handler_static_response, MHD_HTTP_NOT_FOUND
200 };
201 struct RequestHandler *rh;
202 unsigned int i;
203
204 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
205 "Handling request for URL '%s'\n",
206 url);
207 for (i=0;NULL != handlers[i].url;i++)
208 {
209 rh = &handlers[i];
210 if ( (0 == strcasecmp (url,
211 rh->url)) &&
212 ( (NULL == rh->method) ||
213 (0 == strcasecmp (method,
214 rh->method)) ) )
215 return rh->handler (rh,
216 connection,
217 con_cls,
218 upload_data,
219 upload_data_size);
220 }
221 return TALER_MINT_handler_static_response (&h404,
222 connection,
223 con_cls,
224 upload_data,
225 upload_data_size);
226}
227
228
229
230/**
231 * Load configuration parameters for the mint
232 * server into the corresponding global variables.
233 *
234 * @param param mint_directory the mint's directory
235 * @return GNUNET_OK on success
236 */
237static int
238mint_serve_process_config (const char *mint_directory)
239{
240 unsigned long long port;
241 unsigned long long kappa;
242 char *master_pub_str;
243 char *db_cfg;
244
245 cfg = TALER_MINT_config_load (mint_directory);
246 if (NULL == cfg)
247 {
248 fprintf (stderr,
249 "can't load mint configuration\n");
250 return 1;
251 }
252 if (GNUNET_OK !=
253 GNUNET_CONFIGURATION_get_value_string (cfg,
254 "mint", "master_pub",
255 &master_pub_str))
256 {
257 fprintf (stderr,
258 "No master public key given in mint configuration.");
259 return GNUNET_NO;
260 }
261 if (GNUNET_OK !=
262 GNUNET_CRYPTO_eddsa_public_key_from_string (master_pub_str,
263 strlen (master_pub_str),
264 &master_pub))
265 {
266 fprintf (stderr,
267 "Invalid master public key given in mint configuration.");
268 return GNUNET_NO;
269 }
270
271 if (GNUNET_OK !=
272 GNUNET_CONFIGURATION_get_value_string (cfg,
273 "mint", "db",
274 &db_cfg))
275 {
276 fprintf (stderr,
277 "invalid configuration: mint.db\n");
278 return GNUNET_NO;
279 }
280 if (GNUNET_OK !=
281 TALER_MINT_DB_init (db_cfg))
282 {
283 fprintf (stderr,
284 "failed to initialize DB subsystem\n");
285 return GNUNET_NO;
286 }
287
288 if (GNUNET_OK !=
289 GNUNET_CONFIGURATION_get_value_number (cfg,
290 "mint", "port",
291 &port))
292 {
293 fprintf (stderr,
294 "invalid configuration: mint.port\n");
295 return GNUNET_NO;
296 }
297
298 if ((port == 0) || (port > UINT16_MAX))
299 {
300 fprintf (stderr,
301 "invalid configuration (value out of range): mint.port\n");
302 return GNUNET_NO;
303 }
304 serve_port = port;
305
306 if (GNUNET_OK !=
307 GNUNET_CONFIGURATION_get_value_number (cfg,
308 "mint", "refresh_security_parameter",
309 &kappa))
310 {
311 fprintf (stderr,
312 "invalid configuration: mint.refresh_security_parameter\n");
313 return GNUNET_NO;
314 }
315 refresh_security_parameter = kappa;
316
317 return GNUNET_OK;
318}
319
320
321/**
322 * The main function of the serve tool
323 *
324 * @param argc number of arguments from the command line
325 * @param argv command line arguments
326 * @return 0 ok, 1 on error
327 */
328int
329main (int argc, char *const *argv)
330{
331 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
332 GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keyup OPTIONS"),
333 {'d', "mint-dir", "DIR",
334 "mint directory", 1,
335 &GNUNET_GETOPT_set_filename, &mintdir},
336 GNUNET_GETOPT_OPTION_END
337 };
338 int ret;
339
340 GNUNET_assert (GNUNET_OK ==
341 GNUNET_log_setup ("taler-mint-serve",
342 "INFO",
343 NULL));
344 if (GNUNET_GETOPT_run ("taler-mint-serve",
345 options,
346 argc, argv) < 0)
347 return 1;
348 if (NULL == mintdir)
349 {
350 fprintf (stderr,
351 "no mint dir given\n");
352 return 1;
353 }
354
355 if (GNUNET_OK != mint_serve_process_config (mintdir))
356 return 1;
357
358
359 mydaemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
360 serve_port,
361 NULL, NULL,
362 &handle_mhd_request, NULL,
363 MHD_OPTION_END);
364
365 if (NULL == mydaemon)
366 {
367 fprintf (stderr,
368 "Failed to start MHD.\n");
369 return 1;
370 }
371
372 ret = TALER_MINT_key_reload_loop ();
373 MHD_stop_daemon (mydaemon);
374 return (GNUNET_OK == ret) ? 0 : 1;
375}
376
diff --git a/src/mint/taler-mint-httpd.h b/src/mint/taler-mint-httpd.h
new file mode 100644
index 000000000..59f38aadb
--- /dev/null
+++ b/src/mint/taler-mint-httpd.h
@@ -0,0 +1,106 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file taler-mint-httpd.h
18 * @brief Global declarations for the mint
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#ifndef TALER_MINT_HTTPD_H
24#define TALER_MINT_HTTPD_H
25
26
27/**
28 * Cut-and-choose size for refreshing.
29 * FIXME: maybe make it a config option?
30 */
31#define KAPPA 3
32
33
34/**
35 * The mint's configuration.
36 */
37extern struct GNUNET_CONFIGURATION_Handle *cfg;
38
39/**
40 * Main directory with mint data.
41 */
42extern char *mintdir;
43
44/**
45 * Master public key (according to the
46 * configuration in the mint directory).
47 */
48extern struct GNUNET_CRYPTO_EddsaPublicKey master_pub;
49
50
51/**
52 * Struct describing an URL and the handler for it.
53 */
54struct RequestHandler
55{
56
57 /**
58 * URL the handler is for.
59 */
60 const char *url;
61
62 /**
63 * Method the handler is for, NULL for "all".
64 */
65 const char *method;
66
67 /**
68 * Mime type to use in reply (hint, can be NULL).
69 */
70 const char *mime_type;
71
72 /**
73 * Raw data for the @e handler
74 */
75 const void *data;
76
77 /**
78 * Number of bytes in @e data, 0 for 0-terminated.
79 */
80 size_t data_size;
81
82 /**
83 * Function to call to handle the request.
84 *
85 * @param rh this struct
86 * @param mime_type the @e mime_type for the reply (hint, can be NULL)
87 * @param connection the MHD connection to handle
88 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
89 * @param upload_data upload data
90 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
91 * @return MHD result code
92 */
93 int (*handler)(struct RequestHandler *rh,
94 struct MHD_Connection *connection,
95 void **connection_cls,
96 const char *upload_data,
97 size_t *upload_data_size);
98
99 /**
100 * Default response code.
101 */
102 int response_code;
103};
104
105
106#endif
diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c
new file mode 100644
index 000000000..ecbc5c13b
--- /dev/null
+++ b/src/mint/taler-mint-httpd_deposit.c
@@ -0,0 +1,270 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file taler-mint-httpd_deposit.c
18 * @brief Handle /deposit requests
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#include "platform.h"
24#include <gnunet/gnunet_util_lib.h>
25#include <jansson.h>
26#include <microhttpd.h>
27#include <libpq-fe.h>
28#include <pthread.h>
29#include "mint.h"
30#include "mint_db.h"
31#include "taler_types.h"
32#include "taler_signatures.h"
33#include "taler_rsa.h"
34#include "taler_json_lib.h"
35#include "taler_microhttpd_lib.h"
36#include "taler-mint-httpd_keys.h"
37#include "taler-mint-httpd_deposit.h"
38
39
40/**
41 * Send confirmation of deposit success to client.
42 *
43 * @param connection connection to the client
44 * @param deposit deposit request to confirm
45 * @return MHD result code
46 */
47static int
48helper_deposit_send_response_success (struct MHD_Connection *connection,
49 struct Deposit *deposit)
50{
51 // FIXME: return more information here
52 return request_send_json_pack (connection, MHD_HTTP_OK,
53 "{s:s}", "status", "DEPOSIT_OK");
54}
55
56
57/**
58 * Handle a "/deposit" request
59 *
60 * @param rh context of the handler
61 * @param connection the MHD connection to handle
62 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
63 * @param upload_data upload data
64 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
65 * @return MHD result code
66 */
67int
68TALER_MINT_handler_deposit (struct RequestHandler *rh,
69 struct MHD_Connection *connection,
70 void **connection_cls,
71 const char *upload_data,
72 size_t *upload_data_size)
73{
74 json_t *json;
75 struct Deposit *deposit;
76 json_t *wire;
77 json_t *resp;
78 char *wire_enc = NULL;
79 const char *deposit_type;
80 struct MintKeyState *key_state;
81 struct TALER_CoinPublicInfo coin_info;
82 struct TALER_RSA_Signature ubsig;
83 size_t len;
84 int resp_code;
85 PGconn *db_conn;
86 int res;
87
88 res = process_post_json (connection,
89 connection_cls,
90 upload_data, upload_data_size,
91 &json);
92 if (GNUNET_SYSERR == res)
93 {
94 // FIXME: return 'internal error'
95 GNUNET_break (0);
96 return MHD_NO;
97 }
98 if (GNUNET_NO == res)
99 return MHD_YES;
100 if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
101 {
102 GNUNET_break (0);
103 return GNUNET_SYSERR;
104 }
105
106 deposit = NULL;
107 wire = NULL;
108 resp = NULL;
109 if (-1 == json_unpack (json,
110 "{s:s s:o}",
111 "type", &deposit_type,
112 "wire", &wire))
113 {
114 GNUNET_break_op (0);
115 resp = json_pack ("{s:s}", "error", "Bad format");
116 resp_code = MHD_HTTP_BAD_REQUEST;
117 goto EXITIF_exit;
118 }
119 if (NULL == (wire_enc = json_dumps (wire, JSON_COMPACT|JSON_SORT_KEYS)))
120 {
121 GNUNET_break_op (0);
122 resp = json_pack ("{s:s}", "error", "Bad format");
123 resp_code = MHD_HTTP_BAD_REQUEST;
124 goto EXITIF_exit;
125 }
126 len = strlen (wire_enc) + 1;
127 deposit = GNUNET_malloc (sizeof (struct Deposit) + len);
128#define EXITIF(cond) \
129 do { \
130 if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
131 } while (0)
132#define PARSE_DATA(field, addr) \
133 EXITIF (GNUNET_OK != request_json_require_nav \
134 (connection, json, \
135 JNAV_FIELD, field, JNAV_RET_DATA, addr, sizeof (*addr)))
136 PARSE_DATA ("coin_pub", &deposit->coin_pub);
137 PARSE_DATA ("denom_pub", &deposit->denom_pub);
138 PARSE_DATA ("ubsig", &ubsig);
139 PARSE_DATA ("merchant_pub", &deposit->merchant_pub);
140 PARSE_DATA ("H_a", &deposit->h_contract);
141 PARSE_DATA ("H_wire", &deposit->h_wire);
142 PARSE_DATA ("csig", &deposit->coin_sig);
143 PARSE_DATA ("transaction_id", &deposit->transaction_id);
144#undef PARSE_DATA
145 if (0 == strcmp ("DIRECT_DEPOSIT", deposit_type))
146 deposit->purpose.purpose = htonl (TALER_SIGNATURE_DEPOSIT);
147 else if (0 == strcmp ("INCREMENTAL_DEPOSIT", deposit_type))
148 deposit->purpose.purpose = htonl (TALER_SIGNATURE_INCREMENTAL_DEPOSIT);
149 else
150 {
151 GNUNET_break_op (0);
152 resp = json_pack ("{s:s}", "error", "Bad format");
153 resp_code = MHD_HTTP_BAD_REQUEST;
154 goto EXITIF_exit;
155 }
156 deposit->purpose.size = htonl (sizeof (struct Deposit)
157 - offsetof (struct Deposit, purpose));
158 memcpy (&coin_info.coin_pub,
159 &deposit->coin_pub,
160 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
161 coin_info.denom_pub = deposit->denom_pub;
162 coin_info.denom_sig = ubsig;
163 key_state = TALER_MINT_key_state_acquire ();
164 if (GNUNET_YES != TALER_MINT_test_coin_valid (key_state,
165 &coin_info))
166 {
167 TALER_MINT_key_state_release (key_state);
168 resp = json_pack ("{s:s}", "error", "Coin is not valid");
169 resp_code = MHD_HTTP_NOT_FOUND;
170 goto EXITIF_exit;
171 }
172 TALER_MINT_key_state_release (key_state);
173 /*
174 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_DEPOSIT,
175 &deposit->purpose,
176 &deposit->coin_sig,
177 &deposit->coin_pub))
178 {
179 resp = json_pack ("{s:s}", "error", "Signature verfication failed");
180 resp_code = MHD_HTTP_NOT_FOUND;
181 goto EXITIF_exit;
182 }
183 */
184
185 /* Check if we already received the same deposit permission,
186 * or the coin was already deposited */
187
188 {
189 struct Deposit *existing_deposit;
190 int res;
191
192 res = TALER_MINT_DB_get_deposit (db_conn,
193 &deposit->coin_pub,
194 &existing_deposit);
195 if (GNUNET_YES == res)
196 {
197 // FIXME: memory leak
198 if (0 == memcmp (existing_deposit, deposit, sizeof (struct Deposit)))
199 return helper_deposit_send_response_success (connection, deposit);
200 // FIXME: in the future, check if there's enough credits
201 // left on the coin. For now: refuse
202 // FIXME: return more information here
203 return request_send_json_pack (connection, MHD_HTTP_FORBIDDEN,
204 "{s:s}",
205 "error", "double spending");
206 }
207
208 if (GNUNET_SYSERR == res)
209 {
210 GNUNET_break (0);
211 return GNUNET_SYSERR;
212 }
213 }
214
215 {
216 struct KnownCoin known_coin;
217 int res;
218
219 res = TALER_MINT_DB_get_known_coin (db_conn, &coin_info.coin_pub, &known_coin);
220 if (GNUNET_YES == res)
221 {
222 // coin must have been refreshed
223 // FIXME: check
224 // FIXME: return more information here
225 return request_send_json_pack (connection, MHD_HTTP_FORBIDDEN,
226 "{s:s}",
227 "error", "coin was refreshed");
228 }
229 if (GNUNET_SYSERR == res)
230 {
231 GNUNET_break (0);
232 return GNUNET_SYSERR;
233 }
234
235 /* coin valid but not known => insert into DB */
236 known_coin.is_refreshed = GNUNET_NO;
237 known_coin.expended_balance = TALER_amount_ntoh (deposit->amount);
238 known_coin.public_info = coin_info;
239
240 if (GNUNET_OK != TALER_MINT_DB_insert_known_coin (db_conn, &known_coin))
241 {
242 GNUNET_break (0);
243 return GNUNET_SYSERR;
244 }
245 }
246
247 if (GNUNET_OK != TALER_MINT_DB_insert_deposit (db_conn, deposit))
248 {
249 GNUNET_break (0);
250 return GNUNET_SYSERR;
251 }
252 return helper_deposit_send_response_success (connection, deposit);
253
254 EXITIF_exit:
255 if (NULL != resp)
256 res = send_response_json (connection, resp, resp_code);
257 else
258 res = MHD_NO;
259 if (NULL != wire)
260 json_decref (wire);
261 if (NULL != deposit)
262 GNUNET_free (deposit);
263 if (NULL != wire_enc)
264 GNUNET_free (wire_enc);
265 return res;
266#undef EXITIF
267#undef PARSE_DATA
268}
269
270/* end of taler-mint-httpd_deposit.c */
diff --git a/src/mint/taler-mint-httpd_deposit.h b/src/mint/taler-mint-httpd_deposit.h
new file mode 100644
index 000000000..dd7b8c133
--- /dev/null
+++ b/src/mint/taler-mint-httpd_deposit.h
@@ -0,0 +1,48 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file taler-mint-httpd_deposit.h
18 * @brief Handle /deposit requests
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#ifndef TALER_MINT_HTTPD_DEPOSIT_H
24#define TALER_MINT_HTTPD_DEPOSIT_H
25
26#include <gnunet/gnunet_util_lib.h>
27#include <microhttpd.h>
28#include "taler-mint-httpd.h"
29
30
31/**
32 * Handle a "/deposit" request
33 *
34 * @param rh context of the handler
35 * @param connection the MHD connection to handle
36 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
37 * @param upload_data upload data
38 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
39 * @return MHD result code
40 */
41int
42TALER_MINT_handler_deposit (struct RequestHandler *rh,
43 struct MHD_Connection *connection,
44 void **connection_cls,
45 const char *upload_data,
46 size_t *upload_data_size);
47
48#endif
diff --git a/src/mint/taler-mint-httpd_keys.c b/src/mint/taler-mint-httpd_keys.c
new file mode 100644
index 000000000..ba023fe69
--- /dev/null
+++ b/src/mint/taler-mint-httpd_keys.c
@@ -0,0 +1,512 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file taler-mint-httpd_keys.c
18 * @brief Handle /keys requests
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#include "platform.h"
24#include <gnunet/gnunet_util_lib.h>
25#include <jansson.h>
26#include <microhttpd.h>
27#include <libpq-fe.h>
28#include <pthread.h>
29#include "mint.h"
30#include "mint_db.h"
31#include "taler_types.h"
32#include "taler_signatures.h"
33#include "taler_rsa.h"
34#include "taler_json_lib.h"
35#include "taler_microhttpd_lib.h"
36#include "taler-mint-httpd_keys.h"
37
38
39/**
40 * Mint key state. Never use directly, instead access via
41 * #TALER_MINT_key_state_acquire and #TALER_MINT_key_state_release.
42 */
43static struct MintKeyState *internal_key_state;
44
45/**
46 * Mutex protecting access to #internal_key_state.
47 */
48static pthread_mutex_t internal_key_state_mutex = PTHREAD_MUTEX_INITIALIZER;
49
50/**
51 * Pipe used for signaling reloading of our key state.
52 */
53static int reload_pipe[2];
54
55
56/**
57 * Convert the public part of a denomination key
58 * issue to a JSON object.
59 *
60 * @param dki the denomination key issue
61 * @return a JSON object describing the denomination key isue (public part)
62 */
63static json_t *
64denom_key_issue_to_json (const struct TALER_MINT_DenomKeyIssue *dki)
65{
66 json_t *dk_json = json_object ();
67 json_object_set_new (dk_json, "master_sig",
68 TALER_JSON_from_data (&dki->signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature)));
69 json_object_set_new (dk_json, "stamp_start", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->start)));
70 json_object_set_new (dk_json, "stamp_expire_withdraw", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->expire_withdraw)));
71 json_object_set_new (dk_json, "stamp_expire_deposit", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->expire_spend)));
72 json_object_set_new (dk_json, "denom_pub",
73 TALER_JSON_from_data (&dki->denom_pub, sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)));
74 json_object_set_new (dk_json, "value",
75 TALER_JSON_from_amount (TALER_amount_ntoh (dki->value)));
76 json_object_set_new (dk_json,
77 "fee_withdraw",
78 TALER_JSON_from_amount(TALER_amount_ntoh (dki->fee_withdraw)));
79 json_object_set_new (dk_json,
80 "fee_deposit",
81 TALER_JSON_from_amount(TALER_amount_ntoh (dki->fee_deposit)));
82 json_object_set_new (dk_json,
83 "fee_refresh",
84 TALER_JSON_from_amount(TALER_amount_ntoh (dki->fee_refresh)));
85 return dk_json;
86}
87
88
89/**
90 * Convert the public part of a sign key
91 * issue to a JSON object.
92 *
93 * @param ski the sign key issue
94 * @return a JSON object describing the sign key isue (public part)
95 */
96static json_t *
97sign_key_issue_to_json (const struct TALER_MINT_SignKeyIssue *ski)
98{
99 json_t *sk_json = json_object ();
100 json_object_set_new (sk_json, "stamp_start", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (ski->start)));
101 json_object_set_new (sk_json, "stamp_expire", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (ski->expire)));
102 json_object_set_new (sk_json, "master_sig",
103 TALER_JSON_from_data (&ski->signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature)));
104 json_object_set_new (sk_json, "key",
105 TALER_JSON_from_data (&ski->signkey_pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)));
106 return sk_json;
107}
108
109
110/**
111 * Get the relative time value that describes how
112 * far in the future do we want to provide coin keys.
113 *
114 * @return the provide duration
115 */
116static struct GNUNET_TIME_Relative
117TALER_MINT_conf_duration_provide ()
118{
119 struct GNUNET_TIME_Relative rel;
120
121 if (GNUNET_OK !=
122 GNUNET_CONFIGURATION_get_value_time (cfg,
123 "mint_keys",
124 "lookahead_provide",
125 &rel))
126 {
127 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
128 "mint_keys.lookahead_provide not valid or not given\n");
129 GNUNET_abort ();
130 }
131 return rel;
132}
133
134
135/**
136 * Iterator for denomination keys.
137 *
138 * @param cls closure
139 * @param dki the denomination key issue
140 * @param alias coin alias
141 * @return #GNUNET_OK to continue to iterate,
142 * #GNUNET_NO to stop iteration with no error,
143 * #GNUNET_SYSERR to abort iteration with error!
144 */
145static int
146reload_keys_denom_iter (void *cls,
147 const char *alias,
148 const struct TALER_MINT_DenomKeyIssue *dki)
149{
150 struct MintKeyState *ctx = cls;
151 struct GNUNET_TIME_Absolute stamp_provide;
152 struct GNUNET_HashCode denom_key_hash;
153 int res;
154
155 stamp_provide = GNUNET_TIME_absolute_add (ctx->reload_time,
156 TALER_MINT_conf_duration_provide ());
157
158 if (GNUNET_TIME_absolute_ntoh (dki->expire_spend).abs_value_us < ctx->reload_time.abs_value_us)
159 {
160 // this key is expired
161 return GNUNET_OK;
162 }
163 if (GNUNET_TIME_absolute_ntoh (dki->start).abs_value_us > stamp_provide.abs_value_us)
164 {
165 // we are to early for this key
166 return GNUNET_OK;
167 }
168
169 GNUNET_CRYPTO_hash (&dki->denom_pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey), &denom_key_hash);
170
171 res = GNUNET_CONTAINER_multihashmap_put (ctx->denomkey_map,
172 &denom_key_hash,
173 GNUNET_memdup (dki, sizeof (struct TALER_MINT_DenomKeyIssue)),
174 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
175 if (GNUNET_OK != res)
176 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Duplicate denomination key\n");
177
178 json_array_append_new (ctx->denom_keys_array,
179 denom_key_issue_to_json (dki));
180
181 return GNUNET_OK;
182}
183
184
185/**
186 * Iterator for sign keys.
187 *
188 * @param cls closure
189 * @param ski the sign key issue
190 * @return #GNUNET_OK to continue to iterate,
191 * #GNUNET_NO to stop iteration with no error,
192 * #GNUNET_SYSERR to abort iteration with error!
193 */
194static int
195reload_keys_sign_iter (void *cls,
196 const struct TALER_MINT_SignKeyIssue *ski)
197{
198 struct MintKeyState *ctx = cls;
199 struct GNUNET_TIME_Absolute stamp_provide;
200
201 stamp_provide = GNUNET_TIME_absolute_add (ctx->reload_time, TALER_MINT_conf_duration_provide (cfg));
202
203 if (GNUNET_TIME_absolute_ntoh (ski->expire).abs_value_us < ctx->reload_time.abs_value_us)
204 {
205 // this key is expired
206 return GNUNET_OK;
207 }
208
209 if (GNUNET_TIME_absolute_ntoh (ski->start).abs_value_us > stamp_provide.abs_value_us)
210 {
211 // we are to early for this key
212 return GNUNET_OK;
213 }
214
215 // the signkey is valid for now, check
216 // if it's more recent than the current one!
217 if (GNUNET_TIME_absolute_ntoh (ctx->current_sign_key_issue.start).abs_value_us >
218 GNUNET_TIME_absolute_ntoh (ski->start).abs_value_us)
219 ctx->current_sign_key_issue = *ski;
220
221
222 ctx->next_reload = GNUNET_TIME_absolute_min (ctx->next_reload,
223 GNUNET_TIME_absolute_ntoh (ski->expire));
224
225 json_array_append_new (ctx->sign_keys_array,
226 sign_key_issue_to_json (ski));
227
228 return GNUNET_OK;
229}
230
231
232/**
233 * Load the mint's key state from disk.
234 *
235 * @return fresh key state (with reference count 1)
236 */
237static struct MintKeyState *
238reload_keys ()
239{
240 struct MintKeyState *key_state;
241 json_t *keys;
242
243 key_state = GNUNET_new (struct MintKeyState);
244 key_state->refcnt = 1;
245
246 key_state->next_reload = GNUNET_TIME_UNIT_FOREVER_ABS;
247
248 key_state->denom_keys_array = json_array ();
249 GNUNET_assert (NULL != key_state->denom_keys_array);
250
251 key_state->sign_keys_array = json_array ();
252 GNUNET_assert (NULL != key_state->sign_keys_array);
253
254 key_state->denomkey_map = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
255 GNUNET_assert (NULL != key_state->denomkey_map);
256
257 key_state->reload_time = GNUNET_TIME_absolute_get ();
258
259 TALER_MINT_denomkeys_iterate (mintdir, &reload_keys_denom_iter, key_state);
260 TALER_MINT_signkeys_iterate (mintdir, &reload_keys_sign_iter, key_state);
261
262 keys = json_pack ("{s:o, s:o, s:o, s:o}",
263 "master_pub", TALER_JSON_from_data (&master_pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)),
264 "signkeys", key_state->sign_keys_array,
265 "denoms", key_state->denom_keys_array,
266 "list_issue_date", TALER_JSON_from_abs (key_state->reload_time));
267
268 key_state->keys_json = json_dumps (keys, JSON_INDENT(2));
269
270 return key_state;
271}
272
273
274/**
275 * Release key state, free if necessary (if reference count gets to zero).
276 *
277 * @param key_state the key state to release
278 */
279void
280TALER_MINT_key_state_release (struct MintKeyState *key_state)
281{
282 GNUNET_assert (0 == pthread_mutex_lock (&internal_key_state_mutex));
283 GNUNET_assert (0 != key_state->refcnt);
284 key_state->refcnt += 1;
285 if (key_state->refcnt == 0) {
286 GNUNET_free (key_state);
287 }
288 GNUNET_assert (0 == pthread_mutex_unlock (&internal_key_state_mutex));
289}
290
291
292/**
293 * Acquire the key state of the mint. Updates keys if necessary.
294 * For every call to #TALER_MINT_key_state_acquire, a matching call
295 * to #TALER_MINT_key_state_release must be made.
296 *
297 * @return the key state
298 */
299struct MintKeyState *
300TALER_MINT_key_state_acquire (void)
301{
302 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
303 struct MintKeyState *key_state;
304
305 // FIXME: the locking we have is very coarse-grained,
306 // using multiple locks might be nicer ...
307
308 GNUNET_assert (0 == pthread_mutex_lock (&internal_key_state_mutex));
309 if (NULL == internal_key_state)
310 {
311 internal_key_state = reload_keys ();
312 }
313 else if (internal_key_state->next_reload.abs_value_us <= now.abs_value_us)
314 {
315 GNUNET_assert (0 != internal_key_state->refcnt);
316 internal_key_state->refcnt--;
317 if (0 == internal_key_state->refcnt)
318 GNUNET_free (internal_key_state);
319 internal_key_state = reload_keys ();
320 }
321 key_state = internal_key_state;
322 key_state->refcnt += 1;
323 GNUNET_assert (0 == pthread_mutex_unlock (&internal_key_state_mutex));
324
325 return key_state;
326}
327
328
329/**
330 * Look up the issue for a denom public key.
331 *
332 * @param key state to look in
333 * @param denom_pub denomination public key
334 * @return the denomination key issue,
335 * or NULL if denom_pub could not be found
336 */
337struct TALER_MINT_DenomKeyIssue *
338TALER_MINT_get_denom_key (const struct MintKeyState *key_state,
339 const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub)
340{
341 struct TALER_MINT_DenomKeyIssue *issue;
342 struct GNUNET_HashCode hash;
343
344 GNUNET_CRYPTO_hash (denom_pub, sizeof (struct TALER_RSA_PublicKeyBinaryEncoded), &hash);
345 issue = GNUNET_CONTAINER_multihashmap_get (key_state->denomkey_map, &hash);
346 return issue;
347}
348
349
350/**
351 * Check if a coin is valid; that is, whether the denomination key exists,
352 * is not expired, and the signature is correct.
353 *
354 * @param key_state the key state to use for checking the coin's validity
355 * @param coin_public_info the coin public info to check for validity
356 * @return GNUNET_YES if the coin is valid,
357 * GNUNET_NO if it is invalid
358 * GNUNET_SYSERROR if an internal error occured
359 */
360int
361TALER_MINT_test_coin_valid (const struct MintKeyState *key_state,
362 struct TALER_CoinPublicInfo *coin_public_info)
363{
364 struct TALER_MINT_DenomKeyIssue *dki;
365
366 dki = TALER_MINT_get_denom_key (key_state, &coin_public_info->denom_pub);
367 if (NULL == dki)
368 return GNUNET_NO;
369 if (GNUNET_OK != TALER_RSA_verify (&coin_public_info->coin_pub,
370 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
371 &coin_public_info->denom_sig,
372 &dki->denom_pub))
373 {
374 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
375 "coin signature is invalid\n");
376 return GNUNET_NO;
377 }
378 return GNUNET_YES;
379}
380
381
382/**
383 * Function to call to handle the request by sending
384 * back static data from the @a rh.
385 *
386 * @param rh context of the handler
387 * @param connection the MHD connection to handle
388 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
389 * @param upload_data upload data
390 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
391 * @return MHD result code
392 */
393int
394TALER_MINT_handler_keys (struct RequestHandler *rh,
395 struct MHD_Connection *connection,
396 void **connection_cls,
397 const char *upload_data,
398 size_t *upload_data_size)
399{
400 struct MintKeyState *key_state;
401 struct MHD_Response *response;
402 int ret;
403
404 key_state = TALER_MINT_key_state_acquire ();
405 response = MHD_create_response_from_buffer (strlen (key_state->keys_json),
406 key_state->keys_json,
407 MHD_RESPMEM_MUST_COPY);
408 TALER_MINT_key_state_release (key_state);
409 if (NULL == response)
410 {
411 GNUNET_break (0);
412 return MHD_NO;
413 }
414 (void) MHD_add_response_header (response,
415 "Content-Type",
416 rh->mime_type);
417 ret = MHD_queue_response (connection,
418 rh->response_code,
419 response);
420 MHD_destroy_response (response);
421 return ret;
422}
423
424
425/**
426 * Handle a signal, writing relevant signal numbers
427 * (currently just SIGUSR1) to a pipe.
428 *
429 * @param signal_number the signal number
430 */
431static void
432handle_signal (int signal_number)
433{
434 size_t res;
435 char c = signal_number;
436
437 if (SIGUSR1 == signal_number)
438 {
439 errno = 0;
440 res = write (reload_pipe[1], &c, 1);
441 if ((res < 0) && (EINTR != errno))
442 {
443 GNUNET_break (0);
444 return;
445 }
446 if (0 == res)
447 {
448 GNUNET_break (0);
449 return;
450 }
451 }
452}
453
454
455/**
456 * Read signals from a pipe in a loop, and reload keys from disk if
457 * SIGUSR1 is read from the pipe.
458 */
459int
460TALER_MINT_key_reload_loop (void)
461{
462 struct sigaction act;
463
464 if (0 != pipe (reload_pipe))
465 {
466 fprintf (stderr,
467 "Failed to create pipe.\n");
468 return GNUNET_SYSERR;
469 }
470 memset (&act, 0, sizeof (struct sigaction));
471 act.sa_handler = &handle_signal;
472
473 if (0 != sigaction (SIGUSR1, &act, NULL))
474 {
475 fprintf (stderr,
476 "Failed to set signal handler.\n");
477 return GNUNET_SYSERR;
478 }
479
480 while (1)
481 {
482 char c;
483 ssize_t res;
484
485 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
486 "(re-)loading keys\n");
487 GNUNET_assert (0 == pthread_mutex_lock (&internal_key_state_mutex));
488 if (NULL != internal_key_state)
489 {
490 GNUNET_assert (0 != internal_key_state->refcnt);
491 internal_key_state->refcnt -= 1;
492 if (0 == internal_key_state->refcnt)
493 GNUNET_free (internal_key_state);
494 }
495 internal_key_state = reload_keys ();
496 GNUNET_assert (0 == pthread_mutex_unlock (&internal_key_state_mutex));
497read_again:
498 errno = 0;
499 res = read (reload_pipe[0], &c, 1);
500 if ((res < 0) && (EINTR != errno))
501 {
502 GNUNET_break (0);
503 return GNUNET_SYSERR;
504 }
505 if (EINTR == errno)
506 goto read_again;
507 }
508 return GNUNET_OK;
509}
510
511
512/* end of taler-mint-httpd_keys.c */
diff --git a/src/mint/taler-mint-httpd_keys.h b/src/mint/taler-mint-httpd_keys.h
new file mode 100644
index 000000000..640a9c916
--- /dev/null
+++ b/src/mint/taler-mint-httpd_keys.h
@@ -0,0 +1,155 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file taler-mint-httpd_keys.h
18 * @brief Handle /keys requests and manage key state
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#ifndef TALER_MINT_HTTPD_KEYS_H
24#define TALER_MINT_HTTPD_KEYS_H
25
26#include <gnunet/gnunet_util_lib.h>
27#include <microhttpd.h>
28#include "taler-mint-httpd.h"
29
30
31/**
32 * Snapshot of the (coin and signing)
33 * keys (including private keys) of the mint.
34 */
35struct MintKeyState
36{
37 /**
38 * When did we initiate the key reloading?
39 */
40 struct GNUNET_TIME_Absolute reload_time;
41
42 /**
43 * JSON array with denomination keys.
44 */
45 json_t *denom_keys_array;
46
47 /**
48 * JSON array with signing keys.
49 */
50 json_t *sign_keys_array;
51
52 /**
53 * Mapping from denomination keys to denomination key issue struct.
54 */
55 struct GNUNET_CONTAINER_MultiHashMap *denomkey_map;
56
57 /**
58 * When is the next key invalid and we have to reload?
59 */
60 struct GNUNET_TIME_Absolute next_reload;
61
62 /**
63 * Mint signing key that should be used currently.
64 */
65 struct TALER_MINT_SignKeyIssue current_sign_key_issue;
66
67 /**
68 * Cached JSON text that the mint will send for
69 * a /keys request.
70 */
71 char *keys_json;
72
73 /**
74 * Reference count.
75 */
76 unsigned int refcnt;
77};
78
79
80/**
81 * Release key state, free if necessary (if reference count gets to zero).
82 *
83 * @param key_state the key state to release
84 */
85void
86TALER_MINT_key_state_release (struct MintKeyState *key_state);
87
88
89/**
90 * Acquire the key state of the mint. Updates keys if necessary.
91 * For every call to #TALER_MINT_key_state_acquire, a matching call
92 * to #TALER_MINT_key_state_release must be made.
93 *
94 * @return the key state
95 */
96struct MintKeyState *
97TALER_MINT_key_state_acquire (void);
98
99
100/**
101 * Look up the issue for a denom public key.
102 *
103 * @param key state to look in
104 * @param denom_pub denomination public key
105 * @return the denomination key issue,
106 * or NULL if denom_pub could not be found
107 */
108struct TALER_MINT_DenomKeyIssue *
109TALER_MINT_get_denom_key (const struct MintKeyState *key_state,
110 const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub);
111
112
113/**
114 * Check if a coin is valid; that is, whether the denomination key exists,
115 * is not expired, and the signature is correct.
116 *
117 * @param key_state the key state to use for checking the coin's validity
118 * @param coin_public_info the coin public info to check for validity
119 * @return GNUNET_YES if the coin is valid,
120 * GNUNET_NO if it is invalid
121 * GNUNET_SYSERROR if an internal error occured
122 */
123int
124TALER_MINT_test_coin_valid (const struct MintKeyState *key_state,
125 struct TALER_CoinPublicInfo *coin_public_info);
126
127
128/**
129 * Read signals from a pipe in a loop, and reload keys from disk if
130 * SIGUSR1 is read from the pipe.
131 *
132 * @return GNUNET_OK if we terminated normally, GNUNET_SYSERR on error
133 */
134int
135TALER_MINT_key_reload_loop (void);
136
137
138/**
139 * Handle a "/keys" request
140 *
141 * @param rh context of the handler
142 * @param connection the MHD connection to handle
143 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
144 * @param upload_data upload data
145 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
146 * @return MHD result code
147 */
148int
149TALER_MINT_handler_keys (struct RequestHandler *rh,
150 struct MHD_Connection *connection,
151 void **connection_cls,
152 const char *upload_data,
153 size_t *upload_data_size);
154
155#endif
diff --git a/src/mint/taler-mint-httpd_mhd.c b/src/mint/taler-mint-httpd_mhd.c
new file mode 100644
index 000000000..09f3025b8
--- /dev/null
+++ b/src/mint/taler-mint-httpd_mhd.c
@@ -0,0 +1,300 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file taler-mint-httpd_mhd.c
19 * @brief helpers for MHD interaction
20 * @author Florian Dold
21 * @author Benedikt Mueller
22 * @author Christian Grothoff
23 */
24#include "platform.h"
25#include <gnunet/gnunet_util_lib.h>
26#include <jansson.h>
27#include <microhttpd.h>
28#include <libpq-fe.h>
29#include <pthread.h>
30#include "taler_microhttpd_lib.h"
31#include "taler-mint-httpd.h"
32#include "taler-mint-httpd_mhd.h"
33
34
35/**
36 * Function to call to handle the request by sending
37 * back static data from the @a rh.
38 *
39 * @param rh context of the handler
40 * @param connection the MHD connection to handle
41 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
42 * @param upload_data upload data
43 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
44 * @return MHD result code
45 */
46int
47TALER_MINT_handler_static_response (struct RequestHandler *rh,
48 struct MHD_Connection *connection,
49 void **connection_cls,
50 const char *upload_data,
51 size_t *upload_data_size)
52{
53 struct MHD_Response *response;
54 int ret;
55
56 if (0 == rh->data_size)
57 rh->data_size = strlen ((const char *) rh->data);
58 response = MHD_create_response_from_buffer (rh->data_size,
59 (void *) rh->data,
60 MHD_RESPMEM_PERSISTENT);
61 if (NULL == response)
62 {
63 GNUNET_break (0);
64 return MHD_NO;
65 }
66 if (NULL != rh->mime_type)
67 (void) MHD_add_response_header (response,
68 MHD_HTTP_HEADER_CONTENT_TYPE,
69 rh->mime_type);
70 ret = MHD_queue_response (connection,
71 rh->response_code,
72 response);
73 MHD_destroy_response (response);
74 return ret;
75}
76
77
78/**
79 * Function to call to handle the request by sending
80 * back a redirect to the AGPL source code.
81 *
82 * @param rh context of the handler
83 * @param connection the MHD connection to handle
84 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
85 * @param upload_data upload data
86 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
87 * @return MHD result code
88 */
89int
90TALER_MINT_handler_agpl_redirect (struct RequestHandler *rh,
91 struct MHD_Connection *connection,
92 void **connection_cls,
93 const char *upload_data,
94 size_t *upload_data_size)
95{
96 const char *agpl =
97 "This server is licensed under the Affero GPL. You will now be redirected to the source code.";
98 struct MHD_Response *response;
99 int ret;
100
101 response = MHD_create_response_from_buffer (strlen (agpl),
102 (void *) agpl,
103 MHD_RESPMEM_PERSISTENT);
104 if (NULL == response)
105 {
106 GNUNET_break (0);
107 return MHD_NO;
108 }
109 if (NULL != rh->mime_type)
110 (void) MHD_add_response_header (response,
111 MHD_HTTP_HEADER_CONTENT_TYPE,
112 rh->mime_type);
113 MHD_add_response_header (response,
114 MHD_HTTP_HEADER_LOCATION,
115 "http://www.git.taler.net/?p=mint.git");
116 ret = MHD_queue_response (connection,
117 rh->response_code,
118 response);
119 MHD_destroy_response (response);
120 return ret;
121}
122
123
124/**
125 * Function to call to handle the request by building a JSON
126 * reply from varargs.
127 *
128 * @param rh context of the handler
129 * @param connection the MHD connection to handle
130 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
131 * @param response_code HTTP response code to use
132 * @param do_cache can the response be cached? (0: no, 1: yes)
133 * @param fmt format string for pack
134 * @param ... varargs
135 * @return MHD result code
136 */
137int
138TALER_MINT_helper_send_json_pack (struct RequestHandler *rh,
139 struct MHD_Connection *connection,
140 void *connection_cls,
141 int response_code,
142 int do_cache,
143 const char *fmt,
144 ...)
145{
146 int ret;
147 json_t *json;
148 va_list argp;
149 char *json_str;
150 struct MHD_Response *response;
151
152 va_start (argp, fmt);
153 json = json_vpack_ex (NULL, 0, fmt, argp);
154 va_end (argp);
155 if (NULL == json)
156 return MHD_NO;
157 json_str = json_dumps (json, JSON_INDENT(2));
158 json_decref (json);
159 if (NULL == json_str)
160 return MHD_NO;
161 response = MHD_create_response_from_buffer (strlen (json_str),
162 json_str,
163 MHD_RESPMEM_MUST_FREE);
164 if (NULL == response)
165 {
166 free (json_str);
167 return MHD_NO;
168 }
169 if (NULL != rh->mime_type)
170 (void) MHD_add_response_header (response,
171 MHD_HTTP_HEADER_CONTENT_TYPE,
172 rh->mime_type);
173 ret = MHD_queue_response (connection,
174 response_code,
175 response);
176 MHD_destroy_response (response);
177 return ret;
178}
179
180
181/**
182 * Function to call to handle the request by building a JSON
183 * reply with an error message from @a rh.
184 *
185 * @param rh context of the handler
186 * @param connection the MHD connection to handle
187 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
188 * @param upload_data upload data
189 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
190 * @return MHD result code
191 */
192int
193TALER_MINT_handler_send_json_pack_error (struct RequestHandler *rh,
194 struct MHD_Connection *connection,
195 void **connection_cls,
196 const char *upload_data,
197 size_t *upload_data_size)
198{
199 return TALER_MINT_helper_send_json_pack (rh,
200 connection,
201 connection_cls,
202 1, /* caching enabled */
203 rh->response_code,
204 "{s:s}",
205 "error",
206 rh->data);
207}
208
209
210/**
211 * Send a response for an invalid argument.
212 *
213 * @param connection the MHD connection to use
214 * @param param_name the parameter that is missing
215 * @return a GNUnet result code
216 */
217static int
218request_arg_invalid (struct MHD_Connection *connection,
219 const char *param_name)
220{
221 json_t *json;
222 json = json_pack ("{ s:s, s:s }",
223 "error", "invalid parameter",
224 "parameter", param_name);
225 if (MHD_YES != send_response_json (connection, json, MHD_HTTP_BAD_REQUEST))
226 {
227 GNUNET_break (0);
228 return GNUNET_SYSERR;
229 }
230 return GNUNET_NO;
231}
232
233
234/**
235 * Get a GET paramater that is a string,
236 * or send an error response if the parameter is missing.
237 *
238 * @param connection the connection to get the parameter from /
239 * send the error response to
240 * @param param_name the parameter name
241 * @param str pointer to store the parameter string,
242 * must be freed by the caller
243 * @return GNUNET_YES if the parameter is present and valid,
244 * GNUNET_NO if the parameter is missing
245 * GNUNET_SYSERR on internal error
246 */
247static int
248request_arg_require_string (struct MHD_Connection *connection,
249 const char *param_name,
250 const char **str)
251{
252 *str = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, param_name);
253 if (NULL == *str)
254 {
255 if (MHD_NO ==
256 request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
257 "{ s:s, s:s }",
258 "error", "missing parameter",
259 "parameter", param_name))
260 return GNUNET_SYSERR;
261 return GNUNET_NO;
262 }
263 return GNUNET_OK;
264}
265
266
267/**
268 * Extraxt base32crockford encoded data from request.
269 *
270 * Queues an error response to the connection if the parameter is missing or
271 * invalid.
272 *
273 * @param connection the MHD connection
274 * @param param_name the name of the parameter with the key
275 * @param[out] out_data pointer to store the result
276 * @param out_size expected size of data
277 * @return
278 * GNUNET_YES if the the argument is present
279 * GNUNET_NO if the argument is absent or malformed
280 * GNUNET_SYSERR on internal error (error response could not be sent)
281 */
282int
283TALER_MINT_mhd_request_arg_data (struct MHD_Connection *connection,
284 const char *param_name,
285 void *out_data,
286 size_t out_size)
287{
288 const char *str;
289 int ret;
290
291 if (GNUNET_OK != (ret = request_arg_require_string (connection, param_name, &str)))
292 return ret;
293 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (str, strlen (str), out_data, out_size))
294 return request_arg_invalid (connection, param_name);
295 return GNUNET_OK;
296}
297
298
299
300/* end of taler-mint-httpd_mhd.c */
diff --git a/src/mint/taler-mint-httpd_mhd.h b/src/mint/taler-mint-httpd_mhd.h
new file mode 100644
index 000000000..29ab7f64b
--- /dev/null
+++ b/src/mint/taler-mint-httpd_mhd.h
@@ -0,0 +1,132 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file taler-mint-httpd_mhd.h
19 * @brief helpers for MHD interaction
20 * @author Florian Dold
21 * @author Benedikt Mueller
22 * @author Christian Grothoff
23 */
24#ifndef TALER_MINT_HTTPD_MHD_H
25#define TALER_MINT_HTTPD_MHD_H
26#include <gnunet/gnunet_util_lib.h>
27#include <microhttpd.h>
28#include "taler-mint-httpd.h"
29
30
31/**
32 * Function to call to handle the request by sending
33 * back static data from the @a rh.
34 *
35 * @param rh context of the handler
36 * @param connection the MHD connection to handle
37 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
38 * @param upload_data upload data
39 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
40 * @return MHD result code
41 */
42int
43TALER_MINT_handler_static_response (struct RequestHandler *rh,
44 struct MHD_Connection *connection,
45 void **connection_cls,
46 const char *upload_data,
47 size_t *upload_data_size);
48
49
50/**
51 * Function to call to handle the request by sending
52 * back a redirect to the AGPL source code.
53 *
54 * @param rh context of the handler
55 * @param connection the MHD connection to handle
56 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
57 * @param upload_data upload data
58 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
59 * @return MHD result code
60 */
61int
62TALER_MINT_handler_agpl_redirect (struct RequestHandler *rh,
63 struct MHD_Connection *connection,
64 void **connection_cls,
65 const char *upload_data,
66 size_t *upload_data_size);
67
68
69/**
70 * Function to call to handle the request by building a JSON
71 * reply from varargs.
72 *
73 * @param rh context of the handler
74 * @param connection the MHD connection to handle
75 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
76 * @param response_code HTTP response code to use
77 * @param do_cache can the response be cached? (0: no, 1: yes)
78 * @param fmt format string for pack
79 * @param ... varargs
80 * @return MHD result code
81 */
82int
83TALER_MINT_helper_send_json_pack (struct RequestHandler *rh,
84 struct MHD_Connection *connection,
85 void *connection_cls,
86 int response_code,
87 int do_cache,
88 const char *fmt,
89 ...);
90
91
92/**
93 * Function to call to handle the request by building a JSON
94 * reply with an error message from @a rh.
95 *
96 * @param rh context of the handler
97 * @param connection the MHD connection to handle
98 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
99 * @param upload_data upload data
100 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
101 * @return MHD result code
102 */
103int
104TALER_MINT_handler_send_json_pack_error (struct RequestHandler *rh,
105 struct MHD_Connection *connection,
106 void **connection_cls,
107 const char *upload_data,
108 size_t *upload_data_size);
109
110
111/**
112 * Extraxt base32crockford encoded data from request.
113 *
114 * Queues an error response to the connection if the parameter is missing or
115 * invalid.
116 *
117 * @param connection the MHD connection
118 * @param param_name the name of the parameter with the key
119 * @param[out] out_data pointer to store the result
120 * @param out_size expected size of data
121 * @return
122 * GNUNET_YES if the the argument is present
123 * GNUNET_NO if the argument is absent or malformed
124 * GNUNET_SYSERR on internal error (error response could not be sent)
125 */
126int
127TALER_MINT_mhd_request_arg_data (struct MHD_Connection *connection,
128 const char *param_name,
129 void *out_data,
130 size_t out_size);
131
132#endif
diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c
new file mode 100644
index 000000000..8121bb234
--- /dev/null
+++ b/src/mint/taler-mint-httpd_refresh.c
@@ -0,0 +1,1497 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file taler-mint-httpd_refresh.c
18 * @brief Handle /refresh/ requests
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#include "platform.h"
24#include <gnunet/gnunet_util_lib.h>
25#include <jansson.h>
26#include <microhttpd.h>
27#include <libpq-fe.h>
28#include <pthread.h>
29#include "mint.h"
30#include "mint_db.h"
31#include "taler_types.h"
32#include "taler_signatures.h"
33#include "taler_rsa.h"
34#include "taler_json_lib.h"
35#include "taler_microhttpd_lib.h"
36#include "taler-mint-httpd_keys.h"
37#include "taler-mint-httpd_mhd.h"
38#include "taler-mint-httpd_refresh.h"
39
40
41/**
42 * Sign the message in @a purpose with the mint's signing
43 * key and encode the signature as a JSON object.
44 *
45 * @param purpose the message to sign
46 * @return signature as JSON object
47 */
48static json_t *
49sign_as_json (struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
50{
51 json_t *sig_json;
52 struct GNUNET_CRYPTO_EddsaSignature sig;
53 struct MintKeyState *key_state;
54
55 key_state = TALER_MINT_key_state_acquire ();
56
57 sig_json = json_object ();
58
59 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (&key_state->current_sign_key_issue.signkey_priv,
60 purpose,
61 &sig));
62
63 TALER_MINT_key_state_release (key_state);
64
65 json_object_set (sig_json, "sig", TALER_JSON_from_data (&sig, sizeof (struct GNUNET_CRYPTO_EddsaSignature)));
66 json_object_set (sig_json, "purpose", json_integer (ntohl (purpose->purpose)));
67 json_object_set (sig_json, "size", json_integer (ntohl (purpose->size)));
68
69 return sig_json;
70}
71
72
73static int
74link_iter (void *cls,
75 const struct LinkDataEnc *link_data_enc,
76 const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub,
77 const struct TALER_RSA_Signature *ev_sig)
78{
79 json_t *list = cls;
80 json_t *obj = json_object ();
81
82 json_array_append_new (list, obj);
83
84 json_object_set_new (obj, "link_enc",
85 TALER_JSON_from_data (link_data_enc,
86 sizeof (struct LinkDataEnc)));
87
88 json_object_set_new (obj, "denom_pub",
89 TALER_JSON_from_data (denom_pub,
90 sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)));
91
92 json_object_set_new (obj, "ev_sig",
93 TALER_JSON_from_data (ev_sig,
94 sizeof (struct TALER_RSA_Signature)));
95
96 return GNUNET_OK;
97}
98
99
100/**
101 * Insert all requested denominations into the db, and compute the
102 * required cost of the denominations, including fees.
103 *
104 * @param connection the connection to send an error response to
105 * @param db_conn the database connection
106 * @param key_state the mint's key state to use
107 * @param session_pub the refresh session public key
108 * @param root the request JSON object
109 * @param hash_context the hash context where accepted
110 * denominations will be hased into
111 * @param r_amount the sum of the cost (value+fee) for
112 * all requested coins
113 * @return FIXME!
114 */
115static int
116refresh_accept_denoms (struct MHD_Connection *connection,
117 PGconn *db_conn,
118 const struct MintKeyState *key_state,
119 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
120 const json_t *root,
121 struct TALER_HashContext *hash_context,
122 struct TALER_Amount *r_amount)
123{
124 unsigned i;
125 int res;
126 json_t *new_denoms;
127
128 res = request_json_require_nav (connection, root,
129 JNAV_FIELD, "new_denoms",
130 JNAV_RET_TYPED_JSON,
131 JSON_ARRAY,
132 &new_denoms);
133 if (GNUNET_OK != res)
134 return res;
135
136 memset (r_amount, 0, sizeof (struct TALER_Amount));
137
138 for (i = 0; i < json_array_size (new_denoms); i++)
139 {
140 struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
141 int res;
142 struct TALER_MINT_DenomKeyIssue *dki;
143 struct TALER_Amount cost;
144
145 res = request_json_require_nav (connection, root,
146 JNAV_FIELD, "new_denoms",
147 JNAV_INDEX, (int) i,
148 JNAV_RET_DATA,
149 &denom_pub,
150 sizeof (struct TALER_RSA_PublicKeyBinaryEncoded));
151
152 if (GNUNET_OK != res)
153 return res;
154
155 dki = TALER_MINT_get_denom_key (key_state, &denom_pub);
156
157 TALER_hash_context_read (hash_context,
158 &denom_pub, sizeof (struct TALER_RSA_PublicKeyBinaryEncoded));
159
160 cost = TALER_amount_add (TALER_amount_ntoh (dki->value),
161 TALER_amount_ntoh (dki->fee_withdraw));
162
163 *r_amount = TALER_amount_add (cost, *r_amount);
164
165 /* Insert the requested coin into the DB, so we'll know later
166 * what denomination the request had */
167
168 if (GNUNET_OK !=
169 TALER_MINT_DB_insert_refresh_order (db_conn,
170 i,
171 session_pub,
172 &denom_pub))
173 return res; // ???
174 }
175 return GNUNET_OK;
176}
177
178
179/**
180 * Get an amount in the mint's currency
181 * that is zero.
182 *
183 * @return zero amount in the mint's currency
184 */
185static struct TALER_Amount
186mint_amount_native_zero ()
187{
188 struct TALER_Amount amount;
189
190 memset (&amount, 0, sizeof (amount));
191 // FIXME: load from config
192 memcpy (amount.currency, "EUR", 3);
193
194 return amount;
195}
196
197
198static int
199check_confirm_signature (struct MHD_Connection *connection,
200 json_t *coin_info,
201 const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub,
202 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub)
203{
204 struct RefreshMeltConfirmSignRequestBody body;
205 struct GNUNET_CRYPTO_EcdsaSignature sig;
206 int res;
207
208 body.purpose.size = htonl (sizeof (struct RefreshMeltConfirmSignRequestBody));
209 body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_CONFIRM);
210 body.session_pub = *session_pub;
211
212 res = request_json_require_nav (connection, coin_info,
213 JNAV_FIELD, "confirm_sig",
214 JNAV_RET_DATA,
215 &sig,
216 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
217
218 if (GNUNET_OK != res)
219 {
220 GNUNET_break (GNUNET_SYSERR != res);
221 return res;
222 }
223
224 if (GNUNET_OK !=
225 GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_REFRESH_MELT_CONFIRM,
226 &body.purpose,
227 &sig,
228 coin_pub))
229 {
230 if (MHD_YES !=
231 request_send_json_pack (connection,
232 MHD_HTTP_UNAUTHORIZED,
233 "{s:s}",
234 "error", "signature invalid"))
235 return GNUNET_SYSERR;
236 return GNUNET_NO;
237 }
238
239 return GNUNET_OK;
240}
241
242
243/**
244 * Extract public coin information from a JSON object.
245 *
246 * @param connection the connection to send error responses to
247 * @param root the JSON object to extract the coin info from
248 * @return GNUNET_YES if coin public info in JSON was valid
249 * GNUNET_NO otherwise
250 * GNUNET_SYSERR on internal error
251 */
252static int
253request_json_require_coin_public_info (struct MHD_Connection *connection,
254 json_t *root,
255 struct TALER_CoinPublicInfo *r_public_info)
256{
257 int ret;
258
259 GNUNET_assert (NULL != root);
260
261 ret = request_json_require_nav (connection, root,
262 JNAV_FIELD, "coin_pub",
263 JNAV_RET_DATA,
264 &r_public_info->coin_pub,
265 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
266 if (GNUNET_OK != ret)
267 return ret;
268
269 ret = request_json_require_nav (connection, root,
270 JNAV_FIELD, "denom_sig",
271 JNAV_RET_DATA,
272 &r_public_info->denom_sig,
273 sizeof (struct TALER_RSA_Signature));
274 if (GNUNET_OK != ret)
275 return ret;
276
277 ret = request_json_require_nav (connection, root,
278 JNAV_FIELD, "denom_pub",
279 JNAV_RET_DATA,
280 &r_public_info->denom_pub,
281 sizeof (struct TALER_RSA_PublicKeyBinaryEncoded));
282 if (GNUNET_OK != ret)
283 return ret;
284
285 return GNUNET_OK;
286}
287
288
289/**
290 * Parse coin melt requests from a JSON object and write them to
291 * the database.
292 *
293 * @param connection the connection to send errors to
294 * @param db_conn the database connection
295 * @param key_state the mint's key state
296 * @param session_pub the refresh session's public key
297 * @param root the JSON object
298 * @param hash_context the hash context that will receive
299 * the coin public keys of the melted coin
300 * @return a GNUnet result code, GNUNET_OK on success,
301 * GNUNET_NO if an error message was generated,
302 * GNUNET_SYSERR on internal errors (no response generated)
303 */
304static int
305refresh_accept_melts (struct MHD_Connection *connection,
306 PGconn *db_conn,
307 const struct MintKeyState *key_state,
308 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
309 json_t *root,
310 struct TALER_HashContext *hash_context,
311 struct TALER_Amount *r_melt_balance)
312{
313 size_t i;
314 int res;
315 json_t *melt_coins;
316
317 res = request_json_require_nav (connection, root,
318 JNAV_FIELD, "melt_coins",
319 JNAV_RET_TYPED_JSON,
320 JSON_ARRAY,
321 &melt_coins);
322 if (GNUNET_OK != res)
323 return res;
324
325 memset (r_melt_balance, 0, sizeof (struct TALER_Amount));
326
327 for (i = 0; i < json_array_size (melt_coins); i++)
328 {
329 struct TALER_CoinPublicInfo coin_public_info;
330 struct TALER_MINT_DenomKeyIssue *dki;
331 struct KnownCoin known_coin;
332 // money the customer gets by melting the current coin
333 struct TALER_Amount coin_gain;
334
335 res = request_json_require_coin_public_info (connection,
336 json_array_get (melt_coins, i),
337 &coin_public_info);
338 if (GNUNET_OK != res)
339 {
340 GNUNET_break (GNUNET_SYSERR != res);
341 return res;
342 }
343
344 if (GNUNET_OK != (res = check_confirm_signature (connection,
345 json_array_get (melt_coins, i),
346 &coin_public_info.coin_pub,
347 session_pub)))
348 {
349 GNUNET_break (GNUNET_SYSERR != res);
350 return res;
351 }
352
353 TALER_hash_context_read (hash_context,
354 &coin_public_info.coin_pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
355
356 dki = TALER_MINT_get_denom_key (key_state, &coin_public_info.denom_pub);
357
358 if (NULL == dki)
359 return (MHD_YES == request_send_json_pack (connection, MHD_HTTP_NOT_FOUND,
360 "{s:s}",
361 "error", "denom not found"))
362 ? GNUNET_NO : GNUNET_SYSERR;
363
364 if (GNUNET_OK != TALER_MINT_test_coin_valid (key_state, &coin_public_info))
365 return (MHD_YES == request_send_json_pack (connection, MHD_HTTP_NOT_FOUND,
366 "{s:s}",
367 "error", "coin invalid"))
368 ? GNUNET_NO : GNUNET_SYSERR;
369
370 res = TALER_MINT_DB_get_known_coin (db_conn, &coin_public_info.coin_pub,
371 &known_coin);
372
373 if (GNUNET_SYSERR == res)
374 {
375 GNUNET_break (0);
376 return GNUNET_SYSERR;
377 }
378
379 if (GNUNET_YES == res)
380 {
381 if (GNUNET_YES == known_coin.is_refreshed)
382 return (MHD_YES == request_send_json_pack (connection, MHD_HTTP_NOT_FOUND,
383 "{s:s}",
384 "error", "coin already refreshed")) ? GNUNET_NO : GNUNET_SYSERR;
385 }
386 else
387 {
388 known_coin.expended_balance = mint_amount_native_zero ();
389 known_coin.public_info = coin_public_info;
390 }
391
392 known_coin.is_refreshed = GNUNET_YES;
393 known_coin.refresh_session_pub = *session_pub;
394
395 if (GNUNET_OK != TALER_MINT_DB_upsert_known_coin (db_conn, &known_coin))
396 {
397 GNUNET_break (0);
398 return GNUNET_SYSERR;
399 }
400
401 if (GNUNET_OK != TALER_MINT_DB_insert_refresh_melt (db_conn, session_pub, i,
402 &coin_public_info.coin_pub,
403 &coin_public_info.denom_pub))
404 {
405 GNUNET_break (0);
406 return GNUNET_SYSERR;
407 }
408
409 coin_gain = TALER_amount_ntoh (dki->value);
410 coin_gain = TALER_amount_subtract (coin_gain, known_coin.expended_balance);
411
412 /* Refuse to refresh when the coin does not have enough money left to
413 * pay the refreshing fees of the coin. */
414
415 if (TALER_amount_cmp (coin_gain, TALER_amount_ntoh (dki->fee_refresh)) < 0)
416 return (MHD_YES == request_send_json_pack (connection, MHD_HTTP_NOT_FOUND,
417 "{s:s}",
418 "error", "depleted")) ? GNUNET_NO : GNUNET_SYSERR;
419
420 coin_gain = TALER_amount_subtract (coin_gain, TALER_amount_ntoh (dki->fee_refresh));
421
422 *r_melt_balance = TALER_amount_add (*r_melt_balance, coin_gain);
423 }
424 return GNUNET_OK;
425}
426
427
428/**
429 * Send a response for "/refresh/melt".
430 *
431 * @param connection the connection to send the response to
432 * @param db_conn the database connection to fetch values from
433 * @param session_pub the refresh session public key.
434 * @return a MHD result code
435 */
436static int
437helper_refresh_send_melt_response (struct MHD_Connection *connection,
438 PGconn *db_conn,
439 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub)
440{
441 struct RefreshSession session;
442 int res;
443 json_t *root;
444 json_t *list;
445 struct TALER_HashContext hash_context;
446
447 if (GNUNET_OK !=
448 (res = TALER_MINT_DB_get_refresh_session (db_conn,
449 session_pub,
450 &session)))
451 {
452 // FIXME: send internal error
453 GNUNET_break (0);
454 return MHD_NO;
455 }
456
457 root = json_object ();
458 list = json_array ();
459 json_object_set_new (root, "blind_session_pubs", list);
460
461 TALER_hash_context_start (&hash_context);
462
463 {
464 struct RefreshMeltResponseSignatureBody body;
465 json_t *sig_json;
466
467 body.purpose.size = htonl (sizeof (struct RefreshMeltResponseSignatureBody));
468 body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_RESPONSE);
469 TALER_hash_context_finish (&hash_context, &body.melt_response_hash);
470 sig_json = sign_as_json (&body.purpose);
471 GNUNET_assert (NULL != sig_json);
472 json_object_set (root, "signature", sig_json);
473 }
474
475 return send_response_json (connection,
476 root,
477 MHD_HTTP_OK);
478}
479
480
481/**
482 * Verify a signature that is encoded in a JSON object
483 *
484 * @param connection the connection to send errors to
485 * @param root the JSON object with the signature
486 * @param the public key that the signature was created with
487 * @param purpose the signed message
488 * @return GNUNET_YES if the signature was valid
489 * GNUNET_NO if the signature was invalid
490 * GNUNET_SYSERR on internal error
491 */
492static int
493request_json_check_signature (struct MHD_Connection *connection,
494 json_t *root,
495 struct GNUNET_CRYPTO_EddsaPublicKey *pub,
496 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
497{
498 struct GNUNET_CRYPTO_EddsaSignature signature;
499 int size;
500 uint32_t purpose_num;
501 int res;
502 json_t *el;
503
504 res = request_json_require_nav (connection, root,
505 JNAV_FIELD, "sig",
506 JNAV_RET_DATA,
507 &signature,
508 sizeof (struct GNUNET_CRYPTO_EddsaSignature));
509
510 if (GNUNET_OK != res)
511 return res;
512
513 res = request_json_require_nav (connection, root,
514 JNAV_FIELD, "purpose",
515 JNAV_RET_TYPED_JSON,
516 JSON_INTEGER,
517 &el);
518
519 if (GNUNET_OK != res)
520 return res;
521
522 purpose_num = json_integer_value (el);
523
524 if (purpose_num != ntohl (purpose->purpose))
525 {
526 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "signature invalid (purpose wrong)\n");
527 return request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
528 "{s:s}",
529 "error", "signature invalid (purpose)");
530 }
531
532 res = request_json_require_nav (connection, root,
533 JNAV_FIELD, "size",
534 JNAV_RET_TYPED_JSON,
535 JSON_INTEGER,
536 &el);
537
538 if (GNUNET_OK != res)
539 return res;
540
541 size = json_integer_value (el);
542
543 if (size != ntohl (purpose->size))
544 {
545 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "signature invalid (size wrong)\n");
546 return request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
547 GNUNET_NO, GNUNET_SYSERR,
548 "{s:s}",
549 "error", "signature invalid (size)");
550 }
551
552 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (purpose_num,
553 purpose,
554 &signature,
555 pub))
556 {
557 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "signature invalid (did not verify)\n");
558 return request_send_json_pack (connection, MHD_HTTP_UNAUTHORIZED,
559 "{s:s}",
560 "error", "invalid signature (verification)");
561 }
562
563 return GNUNET_OK;
564}
565
566
567/**
568 * Handle a "/refresh/melt" request
569 *
570 * @param rh context of the handler
571 * @param connection the MHD connection to handle
572 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
573 * @param upload_data upload data
574 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
575 * @return MHD result code
576 */
577int
578TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
579 struct MHD_Connection *connection,
580 void **connection_cls,
581 const char *upload_data,
582 size_t *upload_data_size)
583{
584 json_t *root;
585 PGconn *db_conn;
586 struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub;
587 int res;
588 struct MintKeyState *key_state;
589 struct TALER_Amount requested_cost;
590 struct TALER_Amount melt_balance;
591 struct TALER_HashContext hash_context;
592 struct GNUNET_HashCode melt_hash;
593
594 res = process_post_json (connection,
595 connection_cls,
596 upload_data,
597 upload_data_size, &root);
598 if (GNUNET_SYSERR == res)
599 {
600 // FIXME: return 'internal error'?
601 GNUNET_break (0);
602 return MHD_NO;
603 }
604 if (GNUNET_NO == res)
605 return MHD_YES;
606
607 if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
608 return GNUNET_SYSERR;
609
610 /* session_pub field must always be present */
611 res = request_json_require_nav (connection, root,
612 JNAV_FIELD, "session_pub",
613 JNAV_RET_DATA,
614 &refresh_session_pub,
615 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
616 if (GNUNET_OK != res)
617 {
618 // FIXME: return 'internal error'?
619 GNUNET_break (0);
620 return MHD_NO;
621 }
622 if (GNUNET_NO == res)
623 return MHD_YES;
624
625 /* Send response immediately if we already know the session.
626 * Do _not_ care about fields other than session_pub in this case. */
627
628 res = TALER_MINT_DB_get_refresh_session (db_conn,
629 &refresh_session_pub,
630 NULL);
631 if (GNUNET_YES == res)
632 return helper_refresh_send_melt_response (connection,
633 db_conn,
634 &refresh_session_pub);
635 if (GNUNET_SYSERR == res)
636 {
637 // FIXME: return 'internal error'?
638 GNUNET_break (0);
639 return MHD_NO;
640 }
641
642 /* We incrementally update the db with other parameters in a transaction.
643 * The transaction is aborted if some parameter does not validate. */
644
645 if (GNUNET_OK != TALER_MINT_DB_transaction (db_conn))
646 {
647 // FIXME: return 'internal error'?
648 GNUNET_break (0);
649 return MHD_NO;
650 }
651
652 if (GNUNET_OK != TALER_MINT_DB_create_refresh_session (db_conn,
653 &refresh_session_pub))
654 {
655 // FIXME: return 'internal error'?
656 GNUNET_break (0);
657 TALER_MINT_DB_rollback (db_conn);
658 return MHD_NO;
659 }
660
661 /* The next two operations must see the same key state,
662 * thus we acquire it here. */
663
664 key_state = TALER_MINT_key_state_acquire ();
665
666 /* Write requested denominations to the DB,
667 * and sum the costs (value plus fees) */
668
669 TALER_hash_context_start (&hash_context);
670
671 if (GNUNET_OK != (res = refresh_accept_denoms (connection, db_conn, key_state,
672 &refresh_session_pub, root,
673 &hash_context,
674 &requested_cost)))
675 {
676 TALER_MINT_key_state_release (key_state);
677 TALER_MINT_DB_rollback (db_conn);
678 // FIXME: hash_context_end?
679 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
680 }
681
682 /* Write old coins to db and sum their value */
683
684 if (GNUNET_OK != (res = refresh_accept_melts (connection, db_conn, key_state,
685 &refresh_session_pub, root,
686 &hash_context,
687 &melt_balance)))
688 {
689 TALER_MINT_key_state_release (key_state);
690 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
691 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
692 }
693
694 TALER_hash_context_finish (&hash_context, &melt_hash);
695
696 TALER_MINT_key_state_release (key_state);
697
698 /* check that signature from the session public key is ok */
699 {
700 struct RefreshMeltSignatureBody body;
701 json_t *melt_sig_json;
702
703 melt_sig_json = json_object_get (root, "melt_signature");
704 if (NULL == melt_sig_json)
705 {
706 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
707 return request_send_json_pack (connection,
708 MHD_HTTP_BAD_REQUEST,
709 "{s:s}",
710 "error", "melt_signature missing");
711 }
712
713 body.melt_hash = melt_hash;
714 body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT);
715 body.purpose.size = htonl (sizeof (struct RefreshMeltSignatureBody));
716
717 if (GNUNET_OK != (res = request_json_check_signature (connection,
718 melt_sig_json,
719 &refresh_session_pub,
720 &body.purpose)))
721 {
722 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
723 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
724 }
725 }
726
727
728 /* Request is only ok if cost of requested coins
729 * does not exceed value of melted coins. */
730
731 // FIXME: also, consider fees?
732 if (TALER_amount_cmp (melt_balance, requested_cost) < 0)
733 {
734 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
735
736 return request_send_json_pack (connection, MHD_HTTP_FORBIDDEN,
737 "{s:s}",
738 "error", "not enough coins melted");
739 }
740
741 if (GNUNET_OK != TALER_MINT_DB_commit (db_conn))
742 {
743 GNUNET_break (0);
744 return MHD_NO;
745 }
746 return helper_refresh_send_melt_response (connection,
747 db_conn,
748 &refresh_session_pub);
749}
750
751
752/**
753 * Send a response to a "/refresh/commit" request.
754 *
755 * @param connection the connection to send the response to
756 * @param db_conn the mint database
757 * @param refresh_session the refresh session
758 * @return a MHD status code
759 */
760static int
761refresh_send_commit_response (struct MHD_Connection *connection,
762 PGconn *db_conn,
763 struct RefreshSession *refresh_session)
764{
765 struct RefreshCommitResponseSignatureBody body;
766 json_t *sig_json;
767
768 body.purpose.size = htonl (sizeof (struct RefreshCommitResponseSignatureBody));
769 body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_COMMIT_RESPONSE);
770 body.noreveal_index = htons (refresh_session->noreveal_index);
771 sig_json = sign_as_json (&body.purpose);
772 GNUNET_assert (NULL != sig_json);
773 return request_send_json_pack (connection, MHD_HTTP_OK,
774 "{s:i, s:o}",
775 "noreveal_index", (int) refresh_session->noreveal_index,
776 "signature", sig_json);
777}
778
779
780/**
781 * Handle a "/refresh/commit" request
782 *
783 * @param rh context of the handler
784 * @param connection the MHD connection to handle
785 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
786 * @param upload_data upload data
787 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
788 * @return MHD result code
789 */
790int
791TALER_MINT_handler_refresh_commit (struct RequestHandler *rh,
792 struct MHD_Connection *connection,
793 void **connection_cls,
794 const char *upload_data,
795 size_t *upload_data_size)
796{
797 struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub;
798 int res;
799 PGconn *db_conn;
800 struct RefreshSession refresh_session;
801 int i;
802 struct GNUNET_HashCode commit_hash;
803 struct TALER_HashContext hash_context;
804 json_t *root;
805
806 res = process_post_json (connection,
807 connection_cls,
808 upload_data,
809 upload_data_size, &root);
810 if (GNUNET_SYSERR == res)
811 {
812 // FIXME: return 'internal error'?
813 GNUNET_break (0);
814 return MHD_NO;
815 }
816 if (GNUNET_NO == res)
817 return MHD_YES;
818
819
820 res = request_json_require_nav (connection, root,
821 JNAV_FIELD, "session_pub",
822 JNAV_RET_DATA,
823 &refresh_session_pub,
824 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
825 if (GNUNET_OK != res)
826 {
827 GNUNET_break (GNUNET_SYSERR != res);
828 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
829 }
830
831 if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
832 {
833 // FIXME: return 'internal error'?
834 GNUNET_break (0);
835 return MHD_NO;
836 }
837
838 /* Send response immediately if we already know the session.
839 * Do _not_ care about fields other than session_pub in this case. */
840
841 res = TALER_MINT_DB_get_refresh_session (db_conn,
842 &refresh_session_pub,
843 &refresh_session);
844 if ( (GNUNET_YES == res) &&
845 (GNUNET_YES == refresh_session.has_commit_sig) )
846 {
847 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
848 "sending cached commit response\n");
849 res = refresh_send_commit_response (connection,
850 db_conn,
851 &refresh_session);
852 GNUNET_break (res != GNUNET_SYSERR);
853 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
854 }
855 if (GNUNET_SYSERR == res)
856 {
857 // FIXME: return 'internal error'?
858 GNUNET_break (0);
859 return MHD_NO;
860 }
861
862 if (GNUNET_OK != TALER_MINT_DB_transaction (db_conn))
863 {
864 // FIXME: return 'internal error'?
865 GNUNET_break (0);
866 return MHD_NO;
867 }
868
869 /* Re-fetch the session information from the database,
870 * in case a concurrent transaction modified it. */
871
872 res = TALER_MINT_DB_get_refresh_session (db_conn,
873 &refresh_session_pub,
874 &refresh_session);
875 if (GNUNET_OK != res)
876 {
877 // FIXME: return 'internal error'?
878 GNUNET_break (GNUNET_SYSERR != res);
879 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
880 return MHD_NO;
881 }
882
883 TALER_hash_context_start (&hash_context);
884
885 for (i = 0; i < refresh_session.kappa; i++)
886 {
887 unsigned int j;
888
889 for (j = 0; j < refresh_session.num_newcoins; j++)
890 {
891 struct RefreshCommitCoin commit_coin;
892
893 res = request_json_require_nav (connection, root,
894 JNAV_FIELD, "coin_evs",
895 JNAV_INDEX, (int) i,
896 JNAV_INDEX, (int) j,
897 JNAV_RET_DATA,
898 &commit_coin.coin_ev,
899 sizeof (struct TALER_RSA_BlindedSignaturePurpose));
900
901 if (GNUNET_OK != res)
902 {
903 // FIXME: return 'internal error'?
904 GNUNET_break (0);
905 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
906 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
907 }
908
909 TALER_hash_context_read (&hash_context,
910 &commit_coin.coin_ev,
911 sizeof (struct TALER_RSA_BlindedSignaturePurpose));
912
913 res = request_json_require_nav (connection, root,
914 JNAV_FIELD, "link_encs",
915 JNAV_INDEX, (int) i,
916 JNAV_INDEX, (int) j,
917 JNAV_RET_DATA,
918 commit_coin.link_enc,
919 TALER_REFRESH_LINK_LENGTH);
920 if (GNUNET_OK != res)
921 {
922 // FIXME: return 'internal error'?
923 GNUNET_break (0);
924 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
925 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
926 }
927
928 TALER_hash_context_read (&hash_context,
929 commit_coin.link_enc,
930 TALER_REFRESH_LINK_LENGTH);
931
932 commit_coin.cnc_index = i;
933 commit_coin.newcoin_index = j;
934 commit_coin.session_pub = refresh_session_pub;
935
936 if (GNUNET_OK !=
937 TALER_MINT_DB_insert_refresh_commit_coin (db_conn,
938 &commit_coin))
939 {
940 // FIXME: return 'internal error'?
941 GNUNET_break (0);
942 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
943 return MHD_NO;
944 }
945 }
946 }
947
948 for (i = 0; i < refresh_session.kappa; i++)
949 {
950 unsigned int j;
951 for (j = 0; j < refresh_session.num_oldcoins; j++)
952 {
953 struct RefreshCommitLink commit_link;
954
955 res = request_json_require_nav (connection, root,
956 JNAV_FIELD, "transfer_pubs",
957 JNAV_INDEX, (int) i,
958 JNAV_INDEX, (int) j,
959 JNAV_RET_DATA,
960 &commit_link.transfer_pub,
961 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
962
963 if (GNUNET_OK != res)
964 {
965 GNUNET_break (GNUNET_SYSERR != res);
966 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
967 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
968 }
969
970 TALER_hash_context_read (&hash_context,
971 &commit_link.transfer_pub,
972 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
973
974 res = request_json_require_nav (connection, root,
975 JNAV_FIELD, "secret_encs",
976 JNAV_INDEX, (int) i,
977 JNAV_INDEX, (int) j,
978 JNAV_RET_DATA,
979 commit_link.shared_secret_enc,
980 TALER_REFRESH_SHARED_SECRET_LENGTH);
981
982 if (GNUNET_OK != res)
983 {
984 GNUNET_break (GNUNET_SYSERR != res);
985 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
986 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
987 }
988
989 TALER_hash_context_read (&hash_context,
990 commit_link.shared_secret_enc,
991 TALER_REFRESH_SHARED_SECRET_LENGTH);
992
993 commit_link.cnc_index = i;
994 commit_link.oldcoin_index = j;
995 commit_link.session_pub = refresh_session_pub;
996
997 if (GNUNET_OK != TALER_MINT_DB_insert_refresh_commit_link (db_conn, &commit_link))
998 {
999 // FIXME: return 'internal error'?
1000 GNUNET_break (0);
1001 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
1002 return MHD_NO;
1003 }
1004 }
1005 }
1006
1007 TALER_hash_context_finish (&hash_context, &commit_hash);
1008
1009 {
1010 struct RefreshCommitSignatureBody body;
1011 json_t *commit_sig_json;
1012
1013 commit_sig_json = json_object_get (root, "commit_signature");
1014 if (NULL == commit_sig_json)
1015 {
1016 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
1017 return request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
1018 "{s:s}",
1019 "error", "commit_signature missing");
1020 }
1021
1022 body.commit_hash = commit_hash;
1023
1024 body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_COMMIT);
1025 body.purpose.size = htonl (sizeof (struct RefreshCommitSignatureBody));
1026
1027 if (GNUNET_OK != (res = request_json_check_signature (connection,
1028 commit_sig_json,
1029 &refresh_session_pub,
1030 &body.purpose)))
1031 {
1032 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
1033 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
1034 }
1035 }
1036
1037 if (GNUNET_OK != TALER_MINT_DB_commit (db_conn))
1038 {
1039 // FIXME: return 'internal error'?
1040 GNUNET_break (0);
1041 return MHD_NO;
1042 }
1043
1044 return refresh_send_commit_response (connection, db_conn, &refresh_session);
1045}
1046
1047
1048/**
1049 * Send response for "/refresh/reveal".
1050 *
1051 * @param connection the MHD connection
1052 * @param db_conn the connection to the mint's db
1053 * @param refresh_session_pub the refresh session's public key
1054 * @return a MHD result code
1055 */
1056static int
1057helper_refresh_reveal_send_response (struct MHD_Connection *connection,
1058 PGconn *db_conn,
1059 struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub)
1060{
1061 int res;
1062 int newcoin_index;
1063 struct RefreshSession refresh_session;
1064 json_t *root;
1065 json_t *list;
1066
1067 res = TALER_MINT_DB_get_refresh_session (db_conn,
1068 refresh_session_pub,
1069 &refresh_session);
1070 if (GNUNET_OK != res)
1071 {
1072 // FIXME: return 'internal error'
1073 GNUNET_break (0);
1074 return MHD_NO;
1075 }
1076
1077 GNUNET_assert (0 != refresh_session.reveal_ok);
1078
1079 root = json_object ();
1080 list = json_array ();
1081 json_object_set_new (root, "ev_sigs", list);
1082
1083 for (newcoin_index = 0; newcoin_index < refresh_session.num_newcoins; newcoin_index++)
1084 {
1085 struct TALER_RSA_Signature ev_sig;
1086
1087 res = TALER_MINT_DB_get_refresh_collectable (db_conn,
1088 newcoin_index,
1089 refresh_session_pub,
1090 &ev_sig);
1091 if (GNUNET_OK != res)
1092 {
1093 // FIXME: return 'internal error'
1094 GNUNET_break (0);
1095 return MHD_NO;
1096 }
1097 json_array_append_new (list,
1098 TALER_JSON_from_data (&ev_sig,
1099 sizeof (struct TALER_RSA_Signature)));
1100 }
1101 return send_response_json (connection,
1102 root,
1103 MHD_HTTP_OK);
1104}
1105
1106
1107/**
1108 * Handle a "/refresh/reveal" request
1109 *
1110 * @param rh context of the handler
1111 * @param connection the MHD connection to handle
1112 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
1113 * @param upload_data upload data
1114 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
1115 * @return MHD result code
1116 */
1117int
1118TALER_MINT_handler_refresh_reveal (struct RequestHandler *rh,
1119 struct MHD_Connection *connection,
1120 void **connection_cls,
1121 const char *upload_data,
1122 size_t *upload_data_size)
1123{
1124 struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub;
1125 int res;
1126 PGconn *db_conn;
1127 struct RefreshSession refresh_session;
1128 struct MintKeyState *key_state;
1129 int i;
1130 int j;
1131 json_t *root;
1132
1133 res = process_post_json (connection,
1134 connection_cls,
1135 upload_data, upload_data_size,
1136 &root);
1137 if (GNUNET_SYSERR == res)
1138 {
1139 // FIXME: return 'internal error'?
1140 GNUNET_break (0);
1141 return MHD_NO;
1142 }
1143 if (GNUNET_NO == res)
1144 return MHD_YES;
1145
1146 res = request_json_require_nav (connection, root,
1147 JNAV_FIELD, "session_pub",
1148 JNAV_RET_DATA,
1149 &refresh_session_pub,
1150 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
1151 if (GNUNET_OK != res)
1152 {
1153 GNUNET_break (GNUNET_SYSERR != res);
1154 return res;
1155 }
1156
1157 if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
1158 {
1159 GNUNET_break (0);
1160 return MHD_NO;
1161 }
1162
1163 /* Send response immediately if we already know the session,
1164 * and the session commited already.
1165 * Do _not_ care about fields other than session_pub in this case. */
1166
1167 res = TALER_MINT_DB_get_refresh_session (db_conn, &refresh_session_pub, &refresh_session);
1168 if (GNUNET_YES == res && 0 != refresh_session.reveal_ok)
1169 return helper_refresh_reveal_send_response (connection, db_conn, &refresh_session_pub);
1170 if (GNUNET_SYSERR == res)
1171 {
1172 GNUNET_break (0);
1173 return MHD_NO;
1174 }
1175
1176 /* Check that the transfer private keys match their commitments.
1177 * Then derive the shared secret for each kappa, and check that they match. */
1178
1179 for (i = 0; i < refresh_session.kappa; i++)
1180 {
1181 struct GNUNET_HashCode last_shared_secret;
1182 int secret_initialized = GNUNET_NO;
1183
1184 if (i == (refresh_session.noreveal_index % refresh_session.kappa))
1185 continue;
1186
1187 for (j = 0; j < refresh_session.num_oldcoins; j++)
1188 {
1189 struct GNUNET_CRYPTO_EcdsaPrivateKey transfer_priv;
1190 struct RefreshCommitLink commit_link;
1191 struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
1192 struct GNUNET_HashCode transfer_secret;
1193 struct GNUNET_HashCode shared_secret;
1194
1195 res = request_json_require_nav (connection, root,
1196 JNAV_FIELD, "transfer_privs",
1197 JNAV_INDEX, (int) i,
1198 JNAV_INDEX, (int) j,
1199 JNAV_RET_DATA,
1200 &transfer_priv,
1201 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
1202
1203 if (GNUNET_OK != res)
1204 {
1205 GNUNET_break (GNUNET_SYSERR != res);
1206 return res;
1207 }
1208
1209 res = TALER_MINT_DB_get_refresh_commit_link (db_conn,
1210 &refresh_session_pub,
1211 i, j,
1212 &commit_link);
1213 if (GNUNET_OK != res)
1214 {
1215 GNUNET_break (0);
1216 return GNUNET_SYSERR;
1217 }
1218
1219 res = TALER_MINT_DB_get_refresh_melt (db_conn, &refresh_session_pub, j, &coin_pub);
1220 if (GNUNET_OK != res)
1221 {
1222 GNUNET_break (0);
1223 return GNUNET_SYSERR;
1224 }
1225
1226 /* We're converting key types here, which is not very nice
1227 * but necessary and harmless (keys will be thrown away later). */
1228 if (GNUNET_OK != GNUNET_CRYPTO_ecc_ecdh ((struct GNUNET_CRYPTO_EcdhePrivateKey *) &transfer_priv,
1229 (struct GNUNET_CRYPTO_EcdhePublicKey *) &coin_pub,
1230 &transfer_secret))
1231 {
1232 GNUNET_break (0);
1233 return GNUNET_SYSERR;
1234 }
1235
1236 if (0 >= TALER_refresh_decrypt (commit_link.shared_secret_enc, TALER_REFRESH_SHARED_SECRET_LENGTH,
1237 &transfer_secret, &shared_secret))
1238 {
1239 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n");
1240 return GNUNET_SYSERR;
1241 }
1242
1243 if (GNUNET_NO == secret_initialized)
1244 {
1245 secret_initialized = GNUNET_YES;
1246 last_shared_secret = shared_secret;
1247 }
1248 else if (0 != memcmp (&shared_secret, &last_shared_secret, sizeof (struct GNUNET_HashCode)))
1249 {
1250 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "shared secrets do not match\n");
1251 return GNUNET_SYSERR;
1252 }
1253
1254 {
1255 struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub_check;
1256 GNUNET_CRYPTO_ecdsa_key_get_public (&transfer_priv, &transfer_pub_check);
1257 if (0 != memcmp (&transfer_pub_check, &commit_link.transfer_pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
1258 {
1259 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "transfer keys do not match\n");
1260 return GNUNET_SYSERR;
1261 }
1262 }
1263 }
1264
1265 /* Check that the commitments for all new coins were correct */
1266
1267 for (j = 0; j < refresh_session.num_newcoins; j++)
1268 {
1269 struct RefreshCommitCoin commit_coin;
1270 struct LinkData link_data;
1271 struct TALER_RSA_BlindedSignaturePurpose *coin_ev_check;
1272 struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
1273 struct TALER_RSA_BlindingKey *bkey;
1274 struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
1275
1276 bkey = NULL;
1277 res = TALER_MINT_DB_get_refresh_commit_coin (db_conn,
1278 &refresh_session_pub,
1279 i, j,
1280 &commit_coin);
1281 if (GNUNET_OK != res)
1282 {
1283 GNUNET_break (0);
1284 return GNUNET_SYSERR;
1285 }
1286
1287
1288 if (0 >= TALER_refresh_decrypt (commit_coin.link_enc, sizeof (struct LinkData),
1289 &last_shared_secret, &link_data))
1290 {
1291 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n");
1292 return GNUNET_SYSERR;
1293 }
1294
1295 GNUNET_CRYPTO_ecdsa_key_get_public (&link_data.coin_priv, &coin_pub);
1296 if (NULL == (bkey = TALER_RSA_blinding_key_decode (&link_data.bkey_enc)))
1297 {
1298 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid blinding key\n");
1299 return GNUNET_SYSERR;
1300 }
1301 res = TALER_MINT_DB_get_refresh_order (db_conn, j, &refresh_session_pub, &denom_pub);
1302 if (GNUNET_OK != res)
1303 {
1304 GNUNET_break (0);
1305 return GNUNET_SYSERR;
1306 }
1307 if (NULL == (coin_ev_check =
1308 TALER_RSA_message_blind (&coin_pub,
1309 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
1310 bkey,
1311 &denom_pub)))
1312 {
1313 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "blind failed\n");
1314 return GNUNET_SYSERR;
1315 }
1316
1317 if (0 != memcmp (&coin_ev_check,
1318 &commit_coin.coin_ev,
1319 sizeof (struct TALER_RSA_BlindedSignaturePurpose)))
1320 {
1321 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "blind envelope does not match for kappa=%d, old=%d\n",
1322 (int) i, (int) j);
1323 return GNUNET_SYSERR;
1324 }
1325 }
1326 }
1327
1328
1329 if (GNUNET_OK != TALER_MINT_DB_transaction (db_conn))
1330 {
1331 GNUNET_break (0);
1332 return MHD_NO;
1333 }
1334
1335 for (j = 0; j < refresh_session.num_newcoins; j++)
1336 {
1337 struct RefreshCommitCoin commit_coin;
1338 struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
1339 struct TALER_MINT_DenomKeyIssue *dki;
1340 struct TALER_RSA_Signature ev_sig;
1341
1342 res = TALER_MINT_DB_get_refresh_commit_coin (db_conn,
1343 &refresh_session_pub,
1344 refresh_session.noreveal_index % refresh_session.kappa,
1345 j,
1346 &commit_coin);
1347 if (GNUNET_OK != res)
1348 {
1349 GNUNET_break (0);
1350 return GNUNET_SYSERR;
1351 }
1352 res = TALER_MINT_DB_get_refresh_order (db_conn, j, &refresh_session_pub, &denom_pub);
1353 if (GNUNET_OK != res)
1354 {
1355 GNUNET_break (0);
1356 return GNUNET_SYSERR;
1357 }
1358
1359
1360 key_state = TALER_MINT_key_state_acquire ();
1361 dki = TALER_MINT_get_denom_key (key_state, &denom_pub);
1362 TALER_MINT_key_state_release (key_state);
1363 if (NULL == dki)
1364 {
1365 GNUNET_break (0);
1366 return GNUNET_SYSERR;
1367 }
1368 if (GNUNET_OK !=
1369 TALER_RSA_sign (dki->denom_priv,
1370 &commit_coin.coin_ev,
1371 sizeof (struct TALER_RSA_BlindedSignaturePurpose),
1372 &ev_sig))
1373 {
1374 GNUNET_break (0);
1375 return GNUNET_SYSERR;
1376 }
1377
1378 res = TALER_MINT_DB_insert_refresh_collectable (db_conn,
1379 j,
1380 &refresh_session_pub,
1381 &ev_sig);
1382 if (GNUNET_OK != res)
1383 {
1384 GNUNET_break (0);
1385 return GNUNET_SYSERR;
1386 }
1387 }
1388 /* mark that reveal was successful */
1389
1390 res = TALER_MINT_DB_set_reveal_ok (db_conn, &refresh_session_pub);
1391 if (GNUNET_OK != res)
1392 {
1393 GNUNET_break (0);
1394 return GNUNET_SYSERR;
1395 }
1396
1397 if (GNUNET_OK != TALER_MINT_DB_commit (db_conn))
1398 {
1399 GNUNET_break (0);
1400 return MHD_NO;
1401 }
1402
1403 return helper_refresh_reveal_send_response (connection, db_conn, &refresh_session_pub);
1404}
1405
1406
1407/**
1408 * Handle a "/refresh/link" request
1409 *
1410 * @param rh context of the handler
1411 * @param connection the MHD connection to handle
1412 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
1413 * @param upload_data upload data
1414 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
1415 * @return MHD result code
1416 */
1417int
1418TALER_MINT_handler_refresh_link (struct RequestHandler *rh,
1419 struct MHD_Connection *connection,
1420 void **connection_cls,
1421 const char *upload_data,
1422 size_t *upload_data_size)
1423{
1424 struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
1425 int res;
1426 json_t *root;
1427 json_t *list;
1428 PGconn *db_conn;
1429 struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub;
1430 struct SharedSecretEnc shared_secret_enc;
1431
1432 res = TALER_MINT_mhd_request_arg_data (connection,
1433 "coin_pub",
1434 &coin_pub,
1435 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1436 if (GNUNET_SYSERR == res)
1437 {
1438 // FIXME: return 'internal error'
1439 GNUNET_break (0);
1440 return MHD_NO;
1441 }
1442 if (GNUNET_OK != res)
1443 return MHD_YES;
1444
1445 if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
1446 {
1447 GNUNET_break (0);
1448 return GNUNET_SYSERR;
1449 }
1450
1451 list = json_array ();
1452 root = json_object ();
1453 json_object_set_new (root, "new_coins", list);
1454
1455 res = TALER_db_get_transfer (db_conn,
1456 &coin_pub,
1457 &transfer_pub,
1458 &shared_secret_enc);
1459 if (GNUNET_SYSERR == res)
1460 {
1461 GNUNET_break (0);
1462 return MHD_NO;
1463 }
1464 if (GNUNET_NO == res)
1465 {
1466 return request_send_json_pack (connection,
1467 MHD_HTTP_NOT_FOUND,
1468 "{s:s}",
1469 "error", "link data not found (transfer)");
1470 }
1471 GNUNET_assert (GNUNET_OK == res);
1472
1473 res = TALER_db_get_link (db_conn, &coin_pub, link_iter, list);
1474 if (GNUNET_SYSERR == res)
1475 {
1476 GNUNET_break (0);
1477 return MHD_NO;
1478 }
1479 if (GNUNET_NO == res)
1480 {
1481 return request_send_json_pack (connection,
1482 MHD_HTTP_NOT_FOUND,
1483 "{s:s}",
1484 "error", "link data not found (link)");
1485 }
1486 GNUNET_assert (GNUNET_OK == res);
1487 json_object_set_new (root, "transfer_pub",
1488 TALER_JSON_from_data (&transfer_pub,
1489 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)));
1490 json_object_set_new (root, "secret_enc",
1491 TALER_JSON_from_data (&shared_secret_enc,
1492 sizeof (struct SharedSecretEnc)));
1493 return send_response_json (connection, root, MHD_HTTP_OK);
1494}
1495
1496
1497/* end of taler-mint-httpd_refresh.c */
diff --git a/src/mint/taler-mint-httpd_refresh.h b/src/mint/taler-mint-httpd_refresh.h
new file mode 100644
index 000000000..20e7d97c2
--- /dev/null
+++ b/src/mint/taler-mint-httpd_refresh.h
@@ -0,0 +1,103 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file taler-mint-httpd_refresh.h
18 * @brief Handle /refresh/ requests
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#ifndef TALER_MINT_HTTPD_REFRESH_H
24#define TALER_MINT_HTTPD_REFRESH_H
25
26#include <gnunet/gnunet_util_lib.h>
27#include <microhttpd.h>
28#include "taler-mint-httpd.h"
29
30
31/**
32 * Handle a "/refresh/melt" request
33 *
34 * @param rh context of the handler
35 * @param connection the MHD connection to handle
36 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
37 * @param upload_data upload data
38 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
39 * @return MHD result code
40 */
41int
42TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
43 struct MHD_Connection *connection,
44 void **connection_cls,
45 const char *upload_data,
46 size_t *upload_data_size);
47
48
49/**
50 * Handle a "/refresh/commit" request
51 *
52 * @param rh context of the handler
53 * @param connection the MHD connection to handle
54 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
55 * @param upload_data upload data
56 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
57 * @return MHD result code
58 */
59int
60TALER_MINT_handler_refresh_commit (struct RequestHandler *rh,
61 struct MHD_Connection *connection,
62 void **connection_cls,
63 const char *upload_data,
64 size_t *upload_data_size);
65
66
67/**
68 * Handle a "/refresh/link" request
69 *
70 * @param rh context of the handler
71 * @param connection the MHD connection to handle
72 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
73 * @param upload_data upload data
74 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
75 * @return MHD result code
76 */
77int
78TALER_MINT_handler_refresh_link (struct RequestHandler *rh,
79 struct MHD_Connection *connection,
80 void **connection_cls,
81 const char *upload_data,
82 size_t *upload_data_size);
83
84
85/**
86 * Handle a "/refresh/reveal" request
87 *
88 * @param rh context of the handler
89 * @param connection the MHD connection to handle
90 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
91 * @param upload_data upload data
92 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
93 * @return MHD result code
94 */
95int
96TALER_MINT_handler_refresh_reveal (struct RequestHandler *rh,
97 struct MHD_Connection *connection,
98 void **connection_cls,
99 const char *upload_data,
100 size_t *upload_data_size);
101
102
103#endif
diff --git a/src/mint/taler-mint-httpd_withdraw.c b/src/mint/taler-mint-httpd_withdraw.c
new file mode 100644
index 000000000..7ffa45706
--- /dev/null
+++ b/src/mint/taler-mint-httpd_withdraw.c
@@ -0,0 +1,400 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file taler-mint-httpd_withdraw.c
18 * @brief Handle /withdraw/ requests
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#include "platform.h"
24#include <gnunet/gnunet_util_lib.h>
25#include <jansson.h>
26#include <microhttpd.h>
27#include <libpq-fe.h>
28#include <pthread.h>
29#include "mint.h"
30#include "mint_db.h"
31#include "taler_types.h"
32#include "taler_signatures.h"
33#include "taler_rsa.h"
34#include "taler_json_lib.h"
35#include "taler_microhttpd_lib.h"
36#include "taler-mint-httpd_keys.h"
37#include "taler-mint-httpd_mhd.h"
38#include "taler-mint-httpd_withdraw.h"
39
40
41/**
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 */
49static json_t *
50sig_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 */
78static void
79sign_reserve (struct Reserve *reserve,
80 struct MintKeyState *key_state)
81{
82 reserve->status_sign_pub = key_state->current_sign_key_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
94 *
95 * @param rh context of the handler
96 * @param connection the MHD connection to handle
97 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
98 * @param upload_data upload data
99 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
100 * @return MHD result code
101 */
102int
103TALER_MINT_handler_withdraw_status (struct RequestHandler *rh,
104 struct MHD_Connection *connection,
105 void **connection_cls,
106 const char *upload_data,
107 size_t *upload_data_size)
108{
109 struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
110 PGconn *db_conn;
111 int res;
112 struct Reserve reserve;
113 struct MintKeyState *key_state;
114 int must_update = GNUNET_NO;
115 json_t *json;
116
117 res = TALER_MINT_mhd_request_arg_data (connection,
118 "reserve_pub",
119 &reserve_pub,
120 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)
139 return TALER_MINT_helper_send_json_pack (rh,
140 connection,
141 connection_cls,
142 0 /* no caching */,
143 MHD_HTTP_NOT_FOUND,
144 "{s:s}",
145 "error",
146 "Reserve not found");
147 if (GNUNET_OK != res)
148 {
149 // FIXME: return 'internal error'?
150 GNUNET_break (0);
151 return MHD_NO;
152 }
153 key_state = TALER_MINT_key_state_acquire ();
154 if (0 != memcmp (&key_state->current_sign_key_issue.signkey_pub,
155 &reserve.status_sign_pub,
156 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
157 {
158 sign_reserve (&reserve, key_state);
159 must_update = GNUNET_YES;
160 }
161 if ((GNUNET_YES == must_update) &&
162 (GNUNET_OK != TALER_MINT_DB_update_reserve (db_conn, &reserve, !must_update)))
163 {
164 GNUNET_break (0);
165 return MHD_YES;
166 }
167
168 /* Convert the public information of a reserve (i.e.
169 excluding private key) to a JSON object. */
170 json = json_object ();
171 json_object_set_new (json,
172 "balance",
173 TALER_JSON_from_amount (TALER_amount_ntoh (reserve.balance)));
174 json_object_set_new (json,
175 "expiration",
176 TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (reserve.expiration)));
177 json_object_set_new (json,
178 "signature",
179 sig_to_json (&reserve.status_sig_purpose,
180 &reserve.status_sig));
181
182 return send_response_json (connection,
183 json,
184 MHD_HTTP_OK);
185}
186
187
188/**
189 * Send positive, normal response for "/withdraw/sign".
190 *
191 * @param connection the connection to send the response to
192 * @param collectable the collectable blindcoin (i.e. the blindly signed coin)
193 * @return a MHD result code
194 */
195static int
196helper_withdraw_sign_send_reply (struct MHD_Connection *connection,
197 const struct CollectableBlindcoin *collectable)
198{
199 json_t *root = json_object ();
200
201 json_object_set_new (root, "ev_sig",
202 TALER_JSON_from_data (&collectable->ev_sig,
203 sizeof (struct TALER_RSA_Signature)));
204 return send_response_json (connection,
205 root,
206 MHD_HTTP_OK);
207}
208
209
210/**
211 * Handle a "/withdraw/sign" request
212 *
213 * @param rh context of the handler
214 * @param connection the MHD connection to handle
215 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
216 * @param upload_data upload data
217 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
218 * @return MHD result code
219 */
220int
221TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh,
222 struct MHD_Connection *connection,
223 void **connection_cls,
224 const char *upload_data,
225 size_t *upload_data_size)
226{
227 struct TALER_WithdrawRequest wsrd;
228 int res;
229 PGconn *db_conn;
230 struct Reserve reserve;
231 struct MintKeyState *key_state;
232 struct CollectableBlindcoin collectable;
233 struct TALER_MINT_DenomKeyIssue *dki;
234 struct TALER_RSA_Signature ev_sig;
235 struct TALER_Amount amount_required;
236
237 memset (&wsrd,
238 0,
239 sizeof (struct TALER_WithdrawRequest));
240 res = TALER_MINT_mhd_request_arg_data (connection,
241 "reserve_pub",
242 &wsrd.reserve_pub,
243 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
244 if (GNUNET_SYSERR == res)
245 {
246 // FIXME: return 'internal error'?
247 GNUNET_break (0);
248 return MHD_NO;
249 }
250 if (GNUNET_OK != res)
251 return MHD_YES;
252 res = TALER_MINT_mhd_request_arg_data (connection,
253 "denom_pub",
254 &wsrd.denomination_pub,
255 sizeof (struct TALER_RSA_PublicKeyBinaryEncoded));
256 if (GNUNET_SYSERR == res)
257 {
258 // FIXME: return 'internal error'?
259 GNUNET_break (0);
260 return MHD_NO;
261 }
262 if (GNUNET_OK != res)
263 return MHD_YES;
264 res = TALER_MINT_mhd_request_arg_data (connection,
265 "coin_ev",
266 &wsrd.coin_envelope,
267 sizeof (struct TALER_RSA_Signature));
268 if (GNUNET_SYSERR == res)
269 {
270 // FIXME: return 'internal error'?
271 GNUNET_break (0);
272 return MHD_NO;
273 }
274 if (GNUNET_OK != res)
275 return MHD_YES;
276 res = TALER_MINT_mhd_request_arg_data (connection,
277 "reserve_sig",
278 &wsrd.sig,
279 sizeof (struct GNUNET_CRYPTO_EddsaSignature));
280 if (GNUNET_SYSERR == res)
281 {
282 // FIXME: return 'internal error'?
283 GNUNET_break (0);
284 return MHD_NO;
285 }
286 if (GNUNET_OK != res)
287 return MHD_YES;
288
289 if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
290 {
291 // FIXME: return 'internal error'?
292 GNUNET_break (0);
293 return MHD_NO;
294 }
295
296 res = TALER_MINT_DB_get_collectable_blindcoin (db_conn,
297 &wsrd.coin_envelope,
298 &collectable);
299 if (GNUNET_SYSERR == res)
300 {
301 // FIXME: return 'internal error'
302 GNUNET_break (0);
303 return MHD_NO;
304 }
305
306 /* Don't sign again if we have already signed the coin */
307 if (GNUNET_YES == res)
308 return helper_withdraw_sign_send_reply (connection,
309 &collectable);
310 GNUNET_assert (GNUNET_NO == res);
311 res = TALER_MINT_DB_get_reserve (db_conn,
312 &wsrd.reserve_pub,
313 &reserve);
314 if (GNUNET_SYSERR == res)
315 {
316 // FIXME: return 'internal error'
317 GNUNET_break (0);
318 return MHD_NO;
319 }
320 if (GNUNET_NO == res)
321 return request_send_json_pack (connection,
322 MHD_HTTP_NOT_FOUND,
323 "{s:s}",
324 "error", "Reserve not found");
325
326 // fill out all the missing info in the request before
327 // we can check the signature on the request
328
329 wsrd.purpose.purpose = htonl (TALER_SIGNATURE_WITHDRAW);
330 wsrd.purpose.size = htonl (sizeof (struct TALER_WithdrawRequest) -
331 offsetof (struct TALER_WithdrawRequest, purpose));
332
333 if (GNUNET_OK !=
334 GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WITHDRAW,
335 &wsrd.purpose,
336 &wsrd.sig,
337 &wsrd.reserve_pub))
338 return request_send_json_pack (connection,
339 MHD_HTTP_UNAUTHORIZED,
340 "{s:s}",
341 "error", "Invalid Signature");
342
343 key_state = TALER_MINT_key_state_acquire ();
344 dki = TALER_MINT_get_denom_key (key_state,
345 &wsrd.denomination_pub);
346 TALER_MINT_key_state_release (key_state);
347 if (NULL == dki)
348 return request_send_json_pack (connection, MHD_HTTP_NOT_FOUND,
349 "{s:s}",
350 "error", "Denomination not found");
351
352 amount_required = TALER_amount_ntoh (dki->value);
353 amount_required = TALER_amount_add (amount_required,
354 TALER_amount_ntoh (dki->fee_withdraw));
355
356 if (0 < TALER_amount_cmp (amount_required,
357 TALER_amount_ntoh (reserve.balance)))
358 return request_send_json_pack (connection,
359 MHD_HTTP_PAYMENT_REQUIRED,
360 "{s:s}",
361 "error", "Insufficient funds");
362 if (GNUNET_OK != TALER_RSA_sign (dki->denom_priv,
363 &wsrd.coin_envelope,
364 sizeof (struct TALER_RSA_BlindedSignaturePurpose),
365 &ev_sig))
366 {
367 // FIXME: return 'internal error'
368 GNUNET_break (0);
369 return MHD_NO;
370 }
371
372 reserve.balance = TALER_amount_hton (TALER_amount_subtract (TALER_amount_ntoh (reserve.balance),
373 amount_required));
374 if (GNUNET_OK !=
375 TALER_MINT_DB_update_reserve (db_conn,
376 &reserve,
377 GNUNET_YES))
378 {
379 // FIXME: return 'internal error'
380 GNUNET_break (0);
381 return MHD_NO;
382 }
383
384 collectable.ev = wsrd.coin_envelope;
385 collectable.ev_sig = ev_sig;
386 collectable.reserve_pub = wsrd.reserve_pub;
387 collectable.reserve_sig = wsrd.sig;
388 if (GNUNET_OK !=
389 TALER_MINT_DB_insert_collectable_blindcoin (db_conn,
390 &collectable))
391 {
392 // FIXME: return 'internal error'
393 GNUNET_break (0);
394 return GNUNET_NO;;
395 }
396 return helper_withdraw_sign_send_reply (connection,
397 &collectable);
398}
399
400/* end of taler-mint-httpd_withdraw.c */
diff --git a/src/mint/taler-mint-httpd_withdraw.h b/src/mint/taler-mint-httpd_withdraw.h
new file mode 100644
index 000000000..1d292ebd9
--- /dev/null
+++ b/src/mint/taler-mint-httpd_withdraw.h
@@ -0,0 +1,65 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file taler-mint-httpd_withdraw.h
18 * @brief Handle /withdraw/ requests
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#ifndef TALER_MINT_HTTPD_WITHDRAW_H
24#define TALER_MINT_HTTPD_WITHDRAW_H
25
26#include <gnunet/gnunet_util_lib.h>
27#include <microhttpd.h>
28#include "taler-mint-httpd.h"
29
30/**
31 * Handle a "/withdraw/status" request
32 *
33 * @param rh context of the handler
34 * @param connection the MHD connection to handle
35 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
36 * @param upload_data upload data
37 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
38 * @return MHD result code
39 */
40int
41TALER_MINT_handler_withdraw_status (struct RequestHandler *rh,
42 struct MHD_Connection *connection,
43 void **connection_cls,
44 const char *upload_data,
45 size_t *upload_data_size);
46
47
48/**
49 * Handle a "/withdraw/sign" request
50 *
51 * @param rh context of the handler
52 * @param connection the MHD connection to handle
53 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
54 * @param upload_data upload data
55 * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data
56 * @return MHD result code
57 */
58int
59TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh,
60 struct MHD_Connection *connection,
61 void **connection_cls,
62 const char *upload_data,
63 size_t *upload_data_size);
64
65#endif
diff --git a/src/mint/taler-mint-keycheck.c b/src/mint/taler-mint-keycheck.c
new file mode 100644
index 000000000..c6186859c
--- /dev/null
+++ b/src/mint/taler-mint-keycheck.c
@@ -0,0 +1,169 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file taler-mint-keycheck.c
19 * @brief Check mint keys for validity.
20 * @author Florian Dold
21 * @author Benedikt Mueller
22 */
23
24#include <platform.h>
25#include <gnunet/gnunet_util_lib.h>
26#include "mint.h"
27#include "taler_signatures.h"
28
29
30static char *mintdir;
31static struct GNUNET_CONFIGURATION_Handle *kcfg;
32
33
34static int
35signkeys_iter (void *cls, const struct TALER_MINT_SignKeyIssue *ski)
36{
37 struct GNUNET_TIME_Absolute start;
38
39 printf ("iterating over key for start time %s\n",
40 GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (ski->start)));
41
42 start = GNUNET_TIME_absolute_ntoh (ski->start);
43
44 if (ntohl (ski->purpose.size) !=
45 (sizeof (struct TALER_MINT_SignKeyIssue) - offsetof (struct TALER_MINT_SignKeyIssue, purpose)))
46 {
47 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signkey with start %s has invalid purpose field (timestamp: %llu)\n",
48 GNUNET_STRINGS_absolute_time_to_string (start),
49 (long long) start.abs_value_us);
50 return GNUNET_SYSERR;
51 }
52
53
54 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNKEY,
55 &ski->purpose,
56 &ski->signature,
57 &ski->master_pub))
58 {
59 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signkey with start %s has invalid signature (timestamp: %llu)\n",
60 GNUNET_STRINGS_absolute_time_to_string (start),
61 (long long) start.abs_value_us);
62 return GNUNET_SYSERR;
63 }
64 printf ("key valid\n");
65 return GNUNET_OK;
66}
67
68
69static int
70mint_signkeys_check ()
71{
72 if (0 > TALER_MINT_signkeys_iterate (mintdir, signkeys_iter, NULL))
73 return GNUNET_NO;
74 return GNUNET_OK;
75}
76
77
78static int denomkeys_iter (void *cls,
79 const char *alias,
80 const struct TALER_MINT_DenomKeyIssue *dki)
81{
82 struct GNUNET_TIME_Absolute start;
83
84 start = GNUNET_TIME_absolute_ntoh (dki->start);
85
86 if (ntohl (dki->purpose.size) !=
87 (sizeof (struct TALER_MINT_DenomKeyIssue) - offsetof (struct TALER_MINT_DenomKeyIssue, purpose)))
88 {
89 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Denomkey for '%s' with start %s has invalid purpose field (timestamp: %llu)\n",
90 alias,
91 GNUNET_STRINGS_absolute_time_to_string (start),
92 (long long) start.abs_value_us);
93 return GNUNET_SYSERR;
94 }
95
96 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_DENOM,
97 &dki->purpose,
98 &dki->signature,
99 &dki->master))
100 {
101 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Denomkey for '%s'with start %s has invalid signature (timestamp: %llu)\n",
102 alias,
103 GNUNET_STRINGS_absolute_time_to_string (start),
104 (long long) start.abs_value_us);
105 return GNUNET_SYSERR;
106 }
107 printf ("denom key valid\n");
108
109 return GNUNET_OK;
110}
111
112
113static int
114mint_denomkeys_check ()
115{
116 if (0 > TALER_MINT_denomkeys_iterate (mintdir, denomkeys_iter, NULL))
117 return GNUNET_NO;
118 return GNUNET_OK;
119}
120
121
122static int
123mint_keys_check (void)
124{
125 if (GNUNET_OK != mint_signkeys_check ())
126 return GNUNET_NO;
127 return mint_denomkeys_check ();
128}
129
130
131/**
132 * The main function of the keyup tool
133 *
134 * @param argc number of arguments from the command line
135 * @param argv command line arguments
136 * @return 0 ok, 1 on error
137 */
138int
139main (int argc, char *const *argv)
140{
141 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
142 GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keyup OPTIONS"),
143 {'d', "mint-dir", "DIR",
144 "mint directory with keys to update", 1,
145 &GNUNET_GETOPT_set_filename, &mintdir},
146 GNUNET_GETOPT_OPTION_END
147 };
148
149 GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-keycheck", "WARNING", NULL));
150
151 if (GNUNET_GETOPT_run ("taler-mint-keyup", options, argc, argv) < 0)
152 return 1;
153 if (NULL == mintdir)
154 {
155 fprintf (stderr, "mint directory not given\n");
156 return 1;
157 }
158
159 kcfg = TALER_MINT_config_load (mintdir);
160 if (NULL == kcfg)
161 {
162 fprintf (stderr, "can't load mint configuration\n");
163 return 1;
164 }
165 if (GNUNET_OK != mint_keys_check ())
166 return 1;
167 return 0;
168}
169
diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c
new file mode 100644
index 000000000..8a1a77882
--- /dev/null
+++ b/src/mint/taler-mint-keyup.c
@@ -0,0 +1,657 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file taler-mint-keyup.c
19 * @brief Update the mint's keys for coins and signatures,
20 * using the mint's offline master key.
21 * @author Florian Dold
22 * @author Benedikt Mueller
23 */
24
25#include <platform.h>
26#include <gnunet/gnunet_util_lib.h>
27#include "taler_util.h"
28#include "taler_signatures.h"
29#include "mint.h"
30
31#define HASH_CUTOFF 20
32
33/**
34 * Macro to round microseconds to seconds in GNUNET_TIME_* structs.
35 */
36#define ROUND_TO_SECS(name,us_field) name.us_field -= name.us_field % (1000 * 1000);
37
38
39GNUNET_NETWORK_STRUCT_BEGIN
40
41struct CoinTypeNBO
42{
43 struct GNUNET_TIME_RelativeNBO duration_spend;
44 struct GNUNET_TIME_RelativeNBO duration_withdraw;
45 struct TALER_AmountNBO value;
46 struct TALER_AmountNBO fee_withdraw;
47 struct TALER_AmountNBO fee_deposit;
48 struct TALER_AmountNBO fee_refresh;
49};
50
51GNUNET_NETWORK_STRUCT_END
52
53struct CoinTypeParams
54{
55 struct GNUNET_TIME_Relative duration_spend;
56 struct GNUNET_TIME_Relative duration_withdraw;
57 struct GNUNET_TIME_Relative duration_overlap;
58 struct TALER_Amount value;
59 struct TALER_Amount fee_withdraw;
60 struct TALER_Amount fee_deposit;
61 struct TALER_Amount fee_refresh;
62 struct GNUNET_TIME_Absolute anchor;
63};
64
65
66/**
67 * Filename of the master private key.
68 */
69static char *masterkeyfile;
70
71/**
72 * Director of the mint, containing the keys.
73 */
74static char *mintdir;
75
76/**
77 * Time to pretend when the key update is executed.
78 */
79static char *pretend_time_str;
80
81/**
82 * Handle to the mint's configuration
83 */
84static struct GNUNET_CONFIGURATION_Handle *kcfg;
85
86/**
87 * Time when the key update is executed. Either the actual current time, or a
88 * pretended time.
89 */
90static struct GNUNET_TIME_Absolute now;
91
92/**
93 * Master private key of the mint.
94 */
95static struct GNUNET_CRYPTO_EddsaPrivateKey *master_priv;
96
97/**
98 * Master public key of the mint.
99 */
100static struct GNUNET_CRYPTO_EddsaPublicKey *master_pub;
101
102/**
103 * Until what time do we provide keys?
104 */
105static struct GNUNET_TIME_Absolute lookahead_sign_stamp;
106
107
108int
109config_get_denom (const char *section, const char *option, struct TALER_Amount *denom)
110{
111 char *str;
112 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (kcfg, section, option, &str))
113 return GNUNET_NO;
114 if (GNUNET_OK != TALER_string_to_amount (str, denom))
115 return GNUNET_SYSERR;
116 return GNUNET_OK;
117}
118
119
120char *
121get_signkey_dir ()
122{
123 char *dir;
124 size_t len;
125 len = GNUNET_asprintf (&dir, ("%s" DIR_SEPARATOR_STR DIR_SIGNKEYS), mintdir);
126 GNUNET_assert (len > 0);
127 return dir;
128}
129
130
131char *
132get_signkey_file (struct GNUNET_TIME_Absolute start)
133{
134 char *dir;
135 size_t len;
136 len = GNUNET_asprintf (&dir, ("%s" DIR_SEPARATOR_STR DIR_SIGNKEYS DIR_SEPARATOR_STR "%llu"),
137 mintdir, (long long) start.abs_value_us);
138 GNUNET_assert (len > 0);
139 return dir;
140}
141
142
143
144/**
145 * Hash the data defining the coin type.
146 * Exclude information that may not be the same for all
147 * instances of the coin type (i.e. the anchor, overlap).
148 */
149void
150hash_coin_type (const struct CoinTypeParams *p, struct GNUNET_HashCode *hash)
151{
152 struct CoinTypeNBO p_nbo;
153
154 memset (&p_nbo, 0, sizeof (struct CoinTypeNBO));
155
156 p_nbo.duration_spend = GNUNET_TIME_relative_hton (p->duration_spend);
157 p_nbo.duration_withdraw = GNUNET_TIME_relative_hton (p->duration_withdraw);
158 p_nbo.value = TALER_amount_hton (p->value);
159 p_nbo.fee_withdraw = TALER_amount_hton (p->fee_withdraw);
160 p_nbo.fee_deposit = TALER_amount_hton (p->fee_deposit);
161 p_nbo.fee_refresh = TALER_amount_hton (p->fee_refresh);
162
163 GNUNET_CRYPTO_hash (&p_nbo, sizeof (struct CoinTypeNBO), hash);
164}
165
166
167static const char *
168get_cointype_dir (const struct CoinTypeParams *p)
169{
170 static char dir[4096];
171 size_t len;
172 struct GNUNET_HashCode hash;
173 char *hash_str;
174 char *val_str;
175 unsigned int i;
176
177 hash_coin_type (p, &hash);
178 hash_str = TALER_data_to_string_alloc (&hash, sizeof (struct GNUNET_HashCode));
179 GNUNET_assert (HASH_CUTOFF <= strlen (hash_str) + 1);
180 GNUNET_assert (NULL != hash_str);
181 hash_str[HASH_CUTOFF] = 0;
182
183 val_str = TALER_amount_to_string (p->value);
184 for (i = 0; i < strlen (val_str); i++)
185 if (':' == val_str[i] || '.' == val_str[i])
186 val_str[i] = '_';
187
188 len = GNUNET_snprintf (dir, sizeof (dir),
189 ("%s" DIR_SEPARATOR_STR DIR_DENOMKEYS DIR_SEPARATOR_STR "%s-%s"),
190 mintdir, val_str, hash_str);
191 GNUNET_assert (len > 0);
192 GNUNET_free (hash_str);
193 return dir;
194}
195
196
197static const char *
198get_cointype_file (struct CoinTypeParams *p,
199 struct GNUNET_TIME_Absolute start)
200{
201 const char *dir;
202 static char filename[4096];
203 size_t len;
204 dir = get_cointype_dir (p);
205 len = GNUNET_snprintf (filename, sizeof (filename), ("%s" DIR_SEPARATOR_STR "%llu"),
206 dir, (unsigned long long) start.abs_value_us);
207 GNUNET_assert (len > 0);
208 return filename;
209}
210
211
212/**
213 * Get the latest key file from the past.
214 *
215 * @param cls closure
216 * @param filename complete filename (absolute path)
217 * @return #GNUNET_OK to continue to iterate,
218 * #GNUNET_NO to stop iteration with no error,
219 * #GNUNET_SYSERR to abort iteration with error!
220 */
221static int
222get_anchor_iter (void *cls,
223 const char *filename)
224{
225 struct GNUNET_TIME_Absolute stamp;
226 struct GNUNET_TIME_Absolute *anchor = cls;
227 const char *base;
228 char *end = NULL;
229
230 base = GNUNET_STRINGS_get_short_name (filename);
231 stamp.abs_value_us = strtol (base, &end, 10);
232
233 if ((NULL == end) || (0 != *end))
234 {
235 fprintf(stderr, "Ignoring unexpected file '%s'.\n", filename);
236 return GNUNET_OK;
237 }
238
239 // TODO: check if it's actually a valid key file
240
241 if ((stamp.abs_value_us <= now.abs_value_us) && (stamp.abs_value_us > anchor->abs_value_us))
242 *anchor = stamp;
243
244 return GNUNET_OK;
245}
246
247
248/**
249 * Get the timestamp where the first new key should be generated.
250 * Relies on correctly named key files.
251 *
252 * @param dir directory with the signed stuff
253 * @param duration how long is one key valid?
254 * @param overlap what's the overlap between the keys validity period?
255 * @param[out] anchor the timestamp where the first new key should be generated
256 */
257void
258get_anchor (const char *dir,
259 struct GNUNET_TIME_Relative duration,
260 struct GNUNET_TIME_Relative overlap,
261 struct GNUNET_TIME_Absolute *anchor)
262{
263 GNUNET_assert (0 == duration.rel_value_us % 1000000);
264 GNUNET_assert (0 == overlap.rel_value_us % 1000000);
265 if (GNUNET_YES != GNUNET_DISK_directory_test (dir, GNUNET_YES))
266 {
267 *anchor = now;
268 printf ("Can't look for anchor (%s)\n", dir);
269 return;
270 }
271
272 *anchor = GNUNET_TIME_UNIT_ZERO_ABS;
273 if (-1 == GNUNET_DISK_directory_scan (dir, &get_anchor_iter, anchor))
274 {
275 *anchor = now;
276 return;
277 }
278
279 if ((GNUNET_TIME_absolute_add (*anchor, duration)).abs_value_us < now.abs_value_us)
280 {
281 // there's no good anchor, start from now
282 // (existing keys are too old)
283 *anchor = now;
284 }
285 else if (anchor->abs_value_us != now.abs_value_us)
286 {
287 // we have a good anchor
288 *anchor = GNUNET_TIME_absolute_add (*anchor, duration);
289 *anchor = GNUNET_TIME_absolute_subtract (*anchor, overlap);
290 }
291 // anchor is now the stamp where we need to create a new key
292}
293
294static void
295create_signkey_issue (struct GNUNET_TIME_Absolute start,
296 struct GNUNET_TIME_Relative duration,
297 struct TALER_MINT_SignKeyIssue *issue)
298{
299 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
300
301 priv = GNUNET_CRYPTO_eddsa_key_create ();
302 GNUNET_assert (NULL != priv);
303 issue->signkey_priv = *priv;
304 GNUNET_free (priv);
305 issue->master_pub = *master_pub;
306 issue->start = GNUNET_TIME_absolute_hton (start);
307 issue->expire = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (start, duration));
308
309 GNUNET_CRYPTO_eddsa_key_get_public (&issue->signkey_priv, &issue->signkey_pub);
310
311 issue->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNKEY);
312 issue->purpose.size = htonl (sizeof (struct TALER_MINT_SignKeyIssue) - offsetof (struct TALER_MINT_SignKeyIssue, purpose));
313
314 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (master_priv, &issue->purpose, &issue->signature))
315 {
316 GNUNET_abort ();
317 }
318}
319
320
321static int
322check_signkey_valid (const char *signkey_filename)
323{
324 // FIXME: do real checks
325 return GNUNET_OK;
326}
327
328
329int
330mint_keys_update_signkeys ()
331{
332 struct GNUNET_TIME_Relative signkey_duration;
333 struct GNUNET_TIME_Absolute anchor;
334 char *signkey_dir;
335
336 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_keys", "signkey_duration", &signkey_duration))
337 {
338 fprintf (stderr, "Can't read config value mint_keys.signkey_duration\n");
339 return GNUNET_SYSERR;
340 }
341 ROUND_TO_SECS (signkey_duration, rel_value_us);
342 signkey_dir = get_signkey_dir ();
343 // make sure the directory exists
344 if (GNUNET_OK != GNUNET_DISK_directory_create (signkey_dir))
345 {
346 fprintf (stderr, "Cant create signkey dir\n");
347 return GNUNET_SYSERR;
348 }
349
350 get_anchor (signkey_dir, signkey_duration, GNUNET_TIME_UNIT_ZERO, &anchor);
351
352 while (anchor.abs_value_us < lookahead_sign_stamp.abs_value_us) {
353 char *skf;
354 skf = get_signkey_file (anchor);
355 if (GNUNET_YES != GNUNET_DISK_file_test (skf))
356 {
357 struct TALER_MINT_SignKeyIssue signkey_issue;
358 ssize_t nwrite;
359 printf ("Generating signing key for %s.\n", GNUNET_STRINGS_absolute_time_to_string (anchor));
360 create_signkey_issue (anchor, signkey_duration, &signkey_issue);
361 nwrite = GNUNET_DISK_fn_write (skf, &signkey_issue, sizeof (struct TALER_MINT_SignKeyIssue),
362 (GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_USER_READ));
363 if (nwrite != sizeof (struct TALER_MINT_SignKeyIssue))
364 {
365 fprintf (stderr, "Can't write to file '%s'\n", skf);
366 return GNUNET_SYSERR;
367 }
368 }
369 else if (GNUNET_OK != check_signkey_valid (skf))
370 {
371 return GNUNET_SYSERR;
372 }
373 anchor = GNUNET_TIME_absolute_add (anchor, signkey_duration);
374 }
375 return GNUNET_OK;
376}
377
378
379int
380get_cointype_params (const char *ct, struct CoinTypeParams *params)
381{
382 const char *dir;
383 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_denom_duration_withdraw", ct, &params->duration_withdraw))
384 {
385 fprintf (stderr, "Withdraw duration not given for coin type '%s'\n", ct);
386 return GNUNET_SYSERR;
387 }
388 ROUND_TO_SECS (params->duration_withdraw, rel_value_us);
389 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_denom_duration_spend", ct, &params->duration_spend))
390 {
391 fprintf (stderr, "Spend duration not given for coin type '%s'\n", ct);
392 return GNUNET_SYSERR;
393 }
394 ROUND_TO_SECS (params->duration_spend, rel_value_us);
395 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_denom_duration_overlap", ct, &params->duration_overlap))
396 {
397 fprintf (stderr, "Overlap duration not given for coin type '%s'\n", ct);
398 return GNUNET_SYSERR;
399 }
400 ROUND_TO_SECS (params->duration_overlap, rel_value_us);
401
402 if (GNUNET_OK != config_get_denom ("mint_denom_value", ct, &params->value))
403 {
404 fprintf (stderr, "Value not given for coin type '%s'\n", ct);
405 return GNUNET_SYSERR;
406 }
407
408 if (GNUNET_OK != config_get_denom ("mint_denom_fee_withdraw", ct, &params->fee_withdraw))
409 {
410 fprintf (stderr, "Withdraw fee not given for coin type '%s'\n", ct);
411 return GNUNET_SYSERR;
412 }
413
414 if (GNUNET_OK != config_get_denom ("mint_denom_fee_deposit", ct, &params->fee_deposit))
415 {
416 fprintf (stderr, "Deposit fee not given for coin type '%s'\n", ct);
417 return GNUNET_SYSERR;
418 }
419
420 if (GNUNET_OK != config_get_denom ("mint_denom_fee_refresh", ct, &params->fee_refresh))
421 {
422 fprintf (stderr, "Deposit fee not given for coin type '%s'\n", ct);
423 return GNUNET_SYSERR;
424 }
425
426 dir = get_cointype_dir (params);
427 get_anchor (dir, params->duration_spend, params->duration_overlap, &params->anchor);
428 return GNUNET_OK;
429}
430
431
432static void
433create_denomkey_issue (struct CoinTypeParams *params, struct TALER_MINT_DenomKeyIssue *dki)
434{
435 GNUNET_assert (NULL != (dki->denom_priv = TALER_RSA_key_create ()));
436 TALER_RSA_key_get_public (dki->denom_priv, &dki->denom_pub);
437 dki->master = *master_pub;
438 dki->start = GNUNET_TIME_absolute_hton (params->anchor);
439 dki->expire_withdraw =
440 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor,
441 params->duration_withdraw));
442 dki->expire_spend =
443 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor,
444 params->duration_spend));
445 dki->value = TALER_amount_hton (params->value);
446 dki->fee_withdraw = TALER_amount_hton (params->fee_withdraw);
447 dki->fee_deposit = TALER_amount_hton (params->fee_deposit);
448 dki->fee_refresh = TALER_amount_hton (params->fee_refresh);
449
450 dki->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOM);
451 dki->purpose.size = htonl (sizeof (struct TALER_MINT_DenomKeyIssue) - offsetof (struct TALER_MINT_DenomKeyIssue, purpose));
452
453 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (master_priv, &dki->purpose, &dki->signature))
454 {
455 GNUNET_abort ();
456 }
457}
458
459
460static int
461check_cointype_valid (const char *filename, struct CoinTypeParams *params)
462{
463 // FIXME: add real checks
464 return GNUNET_OK;
465}
466
467
468int
469mint_keys_update_cointype (const char *coin_alias)
470{
471 struct CoinTypeParams p;
472 const char *cointype_dir;
473
474 if (GNUNET_OK != get_cointype_params (coin_alias, &p))
475 return GNUNET_SYSERR;
476
477 cointype_dir = get_cointype_dir (&p);
478 if (GNUNET_OK != GNUNET_DISK_directory_create (cointype_dir))
479 return GNUNET_SYSERR;
480
481 while (p.anchor.abs_value_us < lookahead_sign_stamp.abs_value_us) {
482 const char *dkf;
483 dkf = get_cointype_file (&p, p.anchor);
484
485 if (GNUNET_YES != GNUNET_DISK_file_test (dkf))
486 {
487 struct TALER_MINT_DenomKeyIssue denomkey_issue;
488 int ret;
489 printf ("Generating denomination key for type '%s', start %s.\n",
490 coin_alias, GNUNET_STRINGS_absolute_time_to_string (p.anchor));
491 printf ("Target path: %s\n", dkf);
492 create_denomkey_issue (&p, &denomkey_issue);
493 ret = TALER_MINT_write_denom_key (dkf, &denomkey_issue);
494 TALER_RSA_key_free (denomkey_issue.denom_priv);
495 if (GNUNET_OK != ret)
496 {
497 fprintf (stderr, "Can't write to file '%s'\n", dkf);
498 return GNUNET_SYSERR;
499 }
500 }
501 else if (GNUNET_OK != check_cointype_valid (dkf, &p))
502 {
503 return GNUNET_SYSERR;
504 }
505 p.anchor = GNUNET_TIME_absolute_add (p.anchor, p.duration_spend);
506 p.anchor = GNUNET_TIME_absolute_subtract (p.anchor, p.duration_overlap);
507 }
508 return GNUNET_OK;
509}
510
511
512int
513mint_keys_update_denomkeys ()
514{
515 char *coin_types;
516 char *ct;
517 char *tok_ctx;
518
519 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (kcfg, "mint_keys", "coin_types", &coin_types))
520 {
521 fprintf (stderr, "mint_keys.coin_types not in configuration\n");
522 return GNUNET_SYSERR;
523 }
524
525 for (ct = strtok_r (coin_types, " ", &tok_ctx);
526 ct != NULL;
527 ct = strtok_r (NULL, " ", &tok_ctx))
528 {
529 if (GNUNET_OK != mint_keys_update_cointype (ct))
530 {
531 GNUNET_free (coin_types);
532 return GNUNET_SYSERR;
533 }
534 }
535 GNUNET_free (coin_types);
536 return GNUNET_OK;
537}
538
539
540static int
541mint_keys_update ()
542{
543 int ret;
544 struct GNUNET_TIME_Relative lookahead_sign;
545 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_keys", "lookahead_sign", &lookahead_sign))
546 {
547 fprintf (stderr, "mint_keys.lookahead_sign not found\n");
548 return GNUNET_SYSERR;
549 }
550 if (lookahead_sign.rel_value_us == 0)
551 {
552 fprintf (stderr, "mint_keys.lookahead_sign must not be zero\n");
553 return GNUNET_SYSERR;
554 }
555 ROUND_TO_SECS (lookahead_sign, rel_value_us);
556 lookahead_sign_stamp = GNUNET_TIME_absolute_add (now, lookahead_sign);
557
558 ret = mint_keys_update_signkeys ();
559 if (GNUNET_OK != ret)
560 return GNUNET_SYSERR;
561
562 return mint_keys_update_denomkeys ();
563}
564
565
566/**
567 * The main function of the keyup tool
568 *
569 * @param argc number of arguments from the command line
570 * @param argv command line arguments
571 * @return 0 ok, 1 on error
572 */
573int
574main (int argc, char *const *argv)
575{
576 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
577 GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keyup OPTIONS"),
578 {'m', "master-key", "FILE",
579 "master key file (private key)", 1,
580 &GNUNET_GETOPT_set_filename, &masterkeyfile},
581 {'d', "mint-dir", "DIR",
582 "mint directory with keys to update", 1,
583 &GNUNET_GETOPT_set_filename, &mintdir},
584 {'t', "time", "TIMESTAMP",
585 "pretend it is a different time for the update", 0,
586 &GNUNET_GETOPT_set_string, &pretend_time_str},
587 GNUNET_GETOPT_OPTION_END
588 };
589
590 GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-keyup", "WARNING", NULL));
591
592 if (GNUNET_GETOPT_run ("taler-mint-keyup", options, argc, argv) < 0)
593 return 1;
594 if (NULL == mintdir)
595 {
596 fprintf (stderr, "mint directory not given\n");
597 return 1;
598 }
599
600 if (NULL != pretend_time_str)
601 {
602 if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (pretend_time_str, &now))
603 {
604 fprintf (stderr, "timestamp invalid\n");
605 return 1;
606 }
607 }
608 else
609 {
610 now = GNUNET_TIME_absolute_get ();
611 }
612 ROUND_TO_SECS (now, abs_value_us);
613
614 kcfg = TALER_MINT_config_load (mintdir);
615 if (NULL == kcfg)
616 {
617 fprintf (stderr, "can't load mint configuration\n");
618 return 1;
619 }
620
621 if (NULL == masterkeyfile)
622 {
623 fprintf (stderr, "master key file not given\n");
624 return 1;
625 }
626 master_priv = GNUNET_CRYPTO_eddsa_key_create_from_file (masterkeyfile);
627 if (NULL == master_priv)
628 {
629 fprintf (stderr, "master key invalid\n");
630 return 1;
631 }
632
633 master_pub = GNUNET_new (struct GNUNET_CRYPTO_EddsaPublicKey);
634 GNUNET_CRYPTO_eddsa_key_get_public (master_priv, master_pub);
635
636 // check if key from file matches the one from the configuration
637 {
638 struct GNUNET_CRYPTO_EddsaPublicKey master_pub_from_cfg;
639 if (GNUNET_OK != TALER_configuration_get_data (kcfg, "mint", "master_pub",
640 &master_pub_from_cfg,
641 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
642 {
643 fprintf (stderr, "master key missing in configuration (mint.master_pub)\n");
644 return 1;
645 }
646 if (0 != memcmp (master_pub, &master_pub_from_cfg, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
647 {
648 fprintf (stderr, "Mismatch between key from mint configuration and master private key file from command line.\n");
649 return 1;
650 }
651 }
652
653 if (GNUNET_OK != mint_keys_update ())
654 return 1;
655 return 0;
656}
657
diff --git a/src/mint/taler-mint-reservemod.c b/src/mint/taler-mint-reservemod.c
new file mode 100644
index 000000000..3dd94f84b
--- /dev/null
+++ b/src/mint/taler-mint-reservemod.c
@@ -0,0 +1,215 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file taler-mint-reservemod.c
19 * @brief Modify reserves.
20 * @author Florian Dold
21 * @author Benedikt Mueller
22 */
23
24#include "platform.h"
25#include <gnunet/gnunet_util_lib.h>
26#include <libpq-fe.h>
27#include "taler_util.h"
28#include "taler_signatures.h"
29#include "mint.h"
30
31static char *mintdir;
32static struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub;
33static struct GNUNET_CONFIGURATION_Handle *kcfg;
34static PGconn *db_conn;
35
36
37
38/**
39 * Create a new or add to existing reserve.
40 * Fails if currencies do not match.
41 *
42 * @param denom denomination to add
43 *
44 * @return ...
45 */
46int
47reservemod_add (struct TALER_Amount denom)
48{
49 PGresult *result;
50 {
51 const void *param_values[] = { reserve_pub };
52 int param_lengths[] = {sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)};
53 int param_formats[] = {1};
54 result = PQexecParams (db_conn,
55 "select balance_value, balance_fraction, balance_currency from reserves where reserve_pub=$1 limit 1;",
56 1, NULL, (const char * const *) param_values, param_lengths, param_formats, 1);
57 }
58
59 if (PGRES_TUPLES_OK != PQresultStatus (result))
60 {
61 fprintf (stderr, "Select failed: %s\n", PQresultErrorMessage (result));
62 return GNUNET_SYSERR;
63 }
64 if (0 == PQntuples (result))
65 {
66 struct GNUNET_TIME_AbsoluteNBO exnbo;
67 exnbo = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add ( GNUNET_TIME_absolute_get (), GNUNET_TIME_UNIT_YEARS));
68
69 uint32_t value = htonl (denom.value);
70 uint32_t fraction = htonl (denom.fraction);
71 const void *param_values[] = {
72 reserve_pub,
73 &value,
74 &fraction,
75 denom.currency,
76 &exnbo};
77 int param_lengths[] = {32, 4, 4, strlen(denom.currency), 8};
78 int param_formats[] = {1, 1, 1, 1, 1};
79 result = PQexecParams (db_conn,
80 "insert into reserves (reserve_pub, balance_value, balance_fraction, balance_currency, "
81 " expiration_date )"
82 "values ($1,$2,$3,$4,$5);",
83 5, NULL, (const char **) param_values, param_lengths, param_formats, 1);
84
85 if (PGRES_COMMAND_OK != PQresultStatus (result))
86 {
87 fprintf (stderr, "Insert failed: %s\n", PQresultErrorMessage (result));
88 return GNUNET_SYSERR;
89 }
90 }
91 else
92 {
93 struct TALER_Amount old_denom;
94 struct TALER_Amount new_denom;
95 struct TALER_AmountNBO new_denom_nbo;
96 int denom_indices[] = {0, 1, 2};
97 int param_lengths[] = {4, 4, 32};
98 int param_formats[] = {1, 1, 1};
99 const void *param_values[] = {
100 &new_denom_nbo.value,
101 &new_denom_nbo.fraction,
102 reserve_pub
103 };
104
105 GNUNET_assert (GNUNET_OK == TALER_TALER_DB_extract_amount (result, 0, denom_indices, &old_denom));
106 new_denom = TALER_amount_add (old_denom, denom);
107 new_denom_nbo = TALER_amount_hton (new_denom);
108 result = PQexecParams (db_conn,
109 "UPDATE reserves "
110 "SET balance_value = $1, balance_fraction = $2, "
111 " status_sig = NULL, status_sign_pub = NULL "
112 "WHERE reserve_pub = $3 ",
113 3, NULL, (const char **) param_values, param_lengths, param_formats, 1);
114
115 if (PGRES_COMMAND_OK != PQresultStatus (result))
116 {
117 fprintf (stderr, "Update failed: %s\n", PQresultErrorMessage (result));
118 return GNUNET_SYSERR;
119 }
120
121 if (0 != strcmp ("1", PQcmdTuples (result)))
122 {
123 fprintf (stderr, "Update failed (updated '%s' tupes instead of '1')\n",
124 PQcmdTuples (result));
125 return GNUNET_SYSERR;
126 }
127
128 }
129 return GNUNET_OK;
130}
131
132
133/**
134 * The main function of the reservemod tool
135 *
136 * @param argc number of arguments from the command line
137 * @param argv command line arguments
138 * @return 0 ok, 1 on error
139 */
140int
141main (int argc, char *const *argv)
142{
143 static char *reserve_pub_str;
144 static char *add_str;
145 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
146 GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keyup OPTIONS"),
147 {'d', "mint-dir", "DIR",
148 "mint directory with keys to update", 1,
149 &GNUNET_GETOPT_set_filename, &mintdir},
150 {'R', "reserve", "KEY",
151 "reserve (public key) to modify", 1,
152 &GNUNET_GETOPT_set_string, &reserve_pub_str},
153 {'a', "add", "DENOM",
154 "value to add", 1,
155 &GNUNET_GETOPT_set_string, &add_str},
156 GNUNET_GETOPT_OPTION_END
157 };
158 char *TALER_MINT_db_connection_cfg_str;
159
160 GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-keycheck", "WARNING", NULL));
161
162 if (GNUNET_GETOPT_run ("taler-mint-keyup", options, argc, argv) < 0)
163 return 1;
164 if (NULL == mintdir)
165 {
166 fprintf (stderr, "mint directory not given\n");
167 return 1;
168 }
169
170 reserve_pub = GNUNET_new (struct GNUNET_CRYPTO_EddsaPublicKey);
171 if ((NULL == reserve_pub_str) ||
172 (GNUNET_OK != GNUNET_STRINGS_string_to_data (reserve_pub_str,
173 strlen (reserve_pub_str),
174 reserve_pub,
175 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))))
176 {
177 fprintf (stderr, "reserve key invalid\n");
178 return 1;
179 }
180
181 kcfg = TALER_MINT_config_load (mintdir);
182 if (NULL == kcfg)
183 {
184 fprintf (stderr, "can't load mint configuration\n");
185 return 1;
186 }
187 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (kcfg, "mint", "db", &TALER_MINT_db_connection_cfg_str))
188 {
189 fprintf (stderr, "db configuration string not found\n");
190 return 42;
191 }
192 db_conn = PQconnectdb (TALER_MINT_db_connection_cfg_str);
193 if (CONNECTION_OK != PQstatus (db_conn))
194 {
195 fprintf (stderr, "db connection failed: %s\n", PQerrorMessage (db_conn));
196 return 1;
197 }
198
199 if (NULL != add_str)
200 {
201 struct TALER_Amount add_value;
202 if (GNUNET_OK != TALER_string_to_amount (add_str, &add_value))
203 {
204 fprintf (stderr, "could not read value\n");
205 return 1;
206 }
207 if (GNUNET_OK != reservemod_add (add_value))
208 {
209 fprintf (stderr, "adding value failed\n");
210 return 1;
211 }
212 }
213 return 0;
214}
215
diff --git a/src/mint/test_mint_api.c b/src/mint/test_mint_api.c
new file mode 100644
index 000000000..965d607f5
--- /dev/null
+++ b/src/mint/test_mint_api.c
@@ -0,0 +1,211 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file mint/test_mint_api.c
19 * @brief testcase to test mint's HTTP API interface
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */
22
23#include "platform.h"
24#include "taler_util.h"
25#include "taler_mint_service.h"
26
27struct TALER_MINT_Context *ctx;
28
29struct TALER_MINT_Handle *mint;
30
31struct TALER_MINT_KeysGetHandle *dkey_get;
32
33struct TALER_MINT_DepositHandle *dh;
34
35static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
36
37static int result;
38
39
40static void
41do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
42{
43 shutdown_task = GNUNET_SCHEDULER_NO_TASK;
44 if (NULL != dkey_get)
45 TALER_MINT_keys_get_cancel (dkey_get);
46 dkey_get = NULL;
47 if (NULL != dh)
48 TALER_MINT_deposit_submit_cancel (dh);
49 dh = NULL;
50 TALER_MINT_disconnect (mint);
51 mint = NULL;
52 TALER_MINT_cleanup (ctx);
53 ctx = NULL;
54}
55
56
57/**
58 * Callbacks of this type are used to serve the result of submitting a deposit
59 * permission object to a mint
60 *
61 * @param cls closure
62 * @param status 1 for successful deposit, 2 for retry, 0 for failure
63 * @param obj the received JSON object; can be NULL if it cannot be constructed
64 * from the reply
65 * @param emsg in case of unsuccessful deposit, this contains a human readable
66 * explanation.
67 */
68static void
69deposit_status (void *cls,
70 int status,
71 json_t *obj,
72 char *emsg)
73{
74 char *json_enc;
75
76 dh = NULL;
77 json_enc = NULL;
78 if (NULL != obj)
79 {
80 json_enc = json_dumps (obj, JSON_INDENT(2));
81 fprintf (stderr, "%s", json_enc);
82 }
83 if (1 == status)
84 result = GNUNET_OK;
85 else
86 GNUNET_break (0);
87 if (NULL != emsg)
88 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Deposit failed: %s\n", emsg);
89 GNUNET_SCHEDULER_shutdown ();
90}
91/**
92 * Functions of this type are called to signal completion of an asynchronous call.
93 *
94 * @param cls closure
95 * @param emsg if the asynchronous call could not be completed due to an error,
96 * this parameter contains a human readable error message
97 */
98static void
99cont (void *cls, const char *emsg)
100{
101 json_t *dp;
102 char rnd_32[32];
103 char rnd_64[64];
104 char *enc_32;
105 char *enc_64;
106
107 GNUNET_assert (NULL == cls);
108 dkey_get = NULL;
109 if (NULL != emsg)
110 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
111
112 enc_32 = TALER_data_to_string_alloc (rnd_32, sizeof (rnd_32));
113 enc_64 = TALER_data_to_string_alloc (rnd_64, sizeof (rnd_64));
114 dp = json_pack ("{s:s s:o s:s s:s s:s s:s s:s s:s s:s s:s}",
115 "type", "DIRECT_DEPOSIT",
116 "wire", json_pack ("{s:s}", "type", "SEPA"),
117 "C", enc_32,
118 "K", enc_32,
119 "ubsig", enc_64,
120 "M", enc_32,
121 "H_a", enc_64,
122 "H_wire", enc_64,
123 "csig", enc_64,
124 "m", "B1C5GP2RB1C5G");
125 GNUNET_free (enc_32);
126 GNUNET_free (enc_64);
127 dh = TALER_MINT_deposit_submit_json (mint,
128 deposit_status,
129 NULL,
130 dp);
131 json_decref (dp);
132}
133
134
135/**
136 * Functions of this type are called to provide the retrieved signing and
137 * denomination keys of the mint. No TALER_MINT_*() functions should be called
138 * in this callback.
139 *
140 * @param cls closure passed to TALER_MINT_keys_get()
141 * @param sign_keys NULL-terminated array of pointers to the mint's signing
142 * keys. NULL if no signing keys are retrieved.
143 * @param denom_keys NULL-terminated array of pointers to the mint's
144 * denomination keys; will be NULL if no signing keys are retrieved.
145 */
146static void
147read_denom_key (void *cls,
148 struct TALER_MINT_SigningPublicKey **sign_keys,
149 struct TALER_MINT_DenomPublicKey **denom_keys)
150{
151 unsigned int cnt;
152 GNUNET_assert (NULL == cls);
153#define ERR(cond) do { if(!(cond)) break; GNUNET_break (0); return; } while (0)
154 ERR (NULL == sign_keys);
155 ERR (NULL == denom_keys);
156 for (cnt = 0; NULL != sign_keys[cnt]; cnt++)
157 GNUNET_free (sign_keys[cnt]);
158 ERR (0 == cnt);
159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Read %u signing keys\n", cnt);
160 GNUNET_free (sign_keys);
161 for (cnt = 0; NULL != denom_keys[cnt]; cnt++)
162 GNUNET_free (denom_keys[cnt]);
163 ERR (0 == cnt);
164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Read %u denomination keys\n", cnt);
165 GNUNET_free (denom_keys);
166#undef ERR
167 return;
168}
169
170
171/**
172 * Main function that will be run by the scheduler.
173 *
174 * @param cls closure
175 * @param args remaining command-line arguments
176 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
177 * @param config configuration
178 */
179static void
180run (void *cls, char *const *args, const char *cfgfile,
181 const struct GNUNET_CONFIGURATION_Handle *config)
182{
183 ctx = TALER_MINT_init ();
184 mint = TALER_MINT_connect (ctx, "localhost", 4241, NULL);
185 GNUNET_assert (NULL != mint);
186 dkey_get = TALER_MINT_keys_get (mint,
187 &read_denom_key, NULL,
188 &cont, NULL);
189 GNUNET_assert (NULL != dkey_get);
190 shutdown_task =
191 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
192 (GNUNET_TIME_UNIT_SECONDS, 5),
193 &do_shutdown, NULL);
194}
195
196int
197main (int argc, char * const *argv)
198{
199 static struct GNUNET_GETOPT_CommandLineOption options[] = {
200 GNUNET_GETOPT_OPTION_END
201 };
202
203 result = GNUNET_SYSERR;
204 if (GNUNET_OK !=
205 GNUNET_PROGRAM_run (argc, argv, "test-mint-api",
206 gettext_noop
207 ("Testcase to test mint's HTTP API interface"),
208 options, &run, NULL))
209 return 3;
210 return (GNUNET_OK == result) ? 0 : 1;
211}
diff --git a/src/mint/test_mint_common.c b/src/mint/test_mint_common.c
new file mode 100644
index 000000000..b7cad3ea4
--- /dev/null
+++ b/src/mint/test_mint_common.c
@@ -0,0 +1,83 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e. V. (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file mint/test_mint_common.c
19 * @brief test cases for some functions in mint/mint_common.c
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */
22
23#include "platform.h"
24#include "gnunet/gnunet_util_lib.h"
25#include "taler_rsa.h"
26#include "mint.h"
27
28#define EXITIF(cond) \
29 do { \
30 if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
31 } while (0)
32
33int
34main (int argc, const char *const argv[])
35{
36 struct TALER_MINT_DenomKeyIssue dki;
37 struct TALER_RSA_PrivateKeyBinaryEncoded *enc;
38 struct TALER_MINT_DenomKeyIssue dki_read;
39 struct TALER_RSA_PrivateKeyBinaryEncoded *enc_read;
40 char *tmpfile;
41
42 int ret;
43
44 ret = 1;
45 enc = NULL;
46 enc_read = NULL;
47 tmpfile = NULL;
48 dki.denom_priv = NULL;
49 dki_read.denom_priv = NULL;
50 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
51 &dki.signature,
52 sizeof (dki) - offsetof (struct TALER_MINT_DenomKeyIssue,
53 signature));
54 dki.denom_priv = TALER_RSA_key_create ();
55 EXITIF (NULL == (enc = TALER_RSA_encode_key (dki.denom_priv)));
56 EXITIF (NULL == (tmpfile = GNUNET_DISK_mktemp ("test_mint_common")));
57 EXITIF (GNUNET_OK != TALER_MINT_write_denom_key (tmpfile, &dki));
58 EXITIF (GNUNET_OK != TALER_MINT_read_denom_key (tmpfile, &dki_read));
59 EXITIF (NULL == (enc_read = TALER_RSA_encode_key (dki_read.denom_priv)));
60 EXITIF (enc->len != enc_read->len);
61 EXITIF (0 != memcmp (enc,
62 enc_read,
63 ntohs(enc->len)));
64 EXITIF (0 != memcmp (&dki.signature,
65 &dki_read.signature,
66 sizeof (dki) - offsetof (struct TALER_MINT_DenomKeyIssue,
67 signature)));
68 ret = 0;
69
70 EXITIF_exit:
71 GNUNET_free_non_null (enc);
72 if (NULL != tmpfile)
73 {
74 (void) unlink (tmpfile);
75 GNUNET_free (tmpfile);
76 }
77 GNUNET_free_non_null (enc_read);
78 if (NULL != dki.denom_priv)
79 TALER_RSA_key_free (dki.denom_priv);
80 if (NULL != dki_read.denom_priv)
81 TALER_RSA_key_free (dki_read.denom_priv);
82 return ret;
83}
diff --git a/src/mint/test_mint_deposits.c b/src/mint/test_mint_deposits.c
new file mode 100644
index 000000000..776bc15d2
--- /dev/null
+++ b/src/mint/test_mint_deposits.c
@@ -0,0 +1,149 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file mint/test_mint_deposits.c
19 * @brief testcase for mint deposits
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */
22
23#include "platform.h"
24#include <libpq-fe.h>
25#include <gnunet/gnunet_util_lib.h>
26#include "mint_db.h"
27
28#define DB_URI "postgres:///taler"
29
30/**
31 * Shorthand for exit jumps.
32 */
33#define EXITIF(cond) \
34 do { \
35 if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
36 } while (0)
37
38
39/**
40 * DB connection handle
41 */
42static PGconn *conn;
43
44/**
45 * Should we not interact with a temporary table?
46 */
47static int persistent;
48
49/**
50 * Testcase result
51 */
52static int result;
53
54
55static void
56do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
57{
58 if (NULL != conn)
59 PQfinish (conn);
60 conn = NULL;
61}
62
63
64/**
65 * Main function that will be run by the scheduler.
66 *
67 * @param cls closure
68 * @param args remaining command-line arguments
69 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
70 * @param config configuration
71 */
72static void
73run (void *cls, char *const *args, const char *cfgfile,
74 const struct GNUNET_CONFIGURATION_Handle *config)
75{
76 static const char wire[] = "{"
77 "\"type\":\"SEPA\","
78 "\"IBAN\":\"DE67830654080004822650\","
79 "\"NAME\":\"GNUNET E.V\","
80 "\"BIC\":\"GENODEF1SRL\""
81 "}";
82 struct Deposit *deposit;
83 struct Deposit *q_deposit;
84 uint64_t transaction_id;
85
86 deposit = NULL;
87 q_deposit = NULL;
88 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
89 &do_shutdown, NULL);
90 EXITIF (NULL == (conn = PQconnectdb(DB_URI)));
91 EXITIF (GNUNET_OK != TALER_MINT_DB_init_deposits (conn, !persistent));
92 EXITIF (GNUNET_OK != TALER_MINT_DB_prepare_deposits (conn));
93 deposit = GNUNET_malloc (sizeof (struct Deposit) + sizeof (wire));
94 /* Makeup a random coin public key */
95 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
96 deposit,
97 sizeof (struct Deposit));
98 /* Makeup a random 64bit transaction ID */
99 transaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
100 UINT64_MAX);
101 deposit->transaction_id = GNUNET_htonll (transaction_id);
102 /* Random amount */
103 deposit->amount.value =
104 htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX));
105 deposit->amount.fraction =
106 htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX));
107 strcpy (deposit->amount.currency, "EUR");
108 /* Copy wireformat */
109 (void) memcpy (deposit->wire, wire, sizeof (wire));
110 EXITIF (GNUNET_OK != TALER_MINT_DB_insert_deposit (conn,
111 deposit));
112 EXITIF (GNUNET_OK != TALER_MINT_DB_get_deposit (conn,
113 &deposit->coin_pub,
114 &q_deposit));
115 EXITIF (0 != memcmp (deposit,
116 q_deposit,
117 sizeof (struct Deposit) - offsetof(struct Deposit,
118 wire)));
119 EXITIF (transaction_id != GNUNET_ntohll (q_deposit->transaction_id));
120 result = GNUNET_OK;
121
122 EXITIF_exit:
123 GNUNET_free_non_null (deposit);
124 GNUNET_free_non_null (q_deposit);
125 GNUNET_SCHEDULER_shutdown ();
126 return;
127}
128
129
130int main(int argc, char *const argv[])
131{
132 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
133 {'T', "persist", NULL,
134 gettext_noop ("Use a persistent database table instead of a temporary one"),
135 GNUNET_NO, &GNUNET_GETOPT_set_one, &persistent},
136 GNUNET_GETOPT_OPTION_END
137 };
138
139
140 persistent = GNUNET_NO;
141 result = GNUNET_SYSERR;
142 if (GNUNET_OK !=
143 GNUNET_PROGRAM_run (argc, argv,
144 "test-mint-deposits",
145 "testcase for mint deposits",
146 options, &run, NULL))
147 return 3;
148 return (GNUNET_OK == result) ? 0 : 1;
149}
diff --git a/src/mint/test_mint_nayapaisa.ecc b/src/mint/test_mint_nayapaisa.ecc
new file mode 100644
index 000000000..942110b5c
--- /dev/null
+++ b/src/mint/test_mint_nayapaisa.ecc
Binary files differ
diff --git a/src/mint/test_mint_nayapaisa/README b/src/mint/test_mint_nayapaisa/README
new file mode 100644
index 000000000..fce5e0180
--- /dev/null
+++ b/src/mint/test_mint_nayapaisa/README
@@ -0,0 +1 @@
This directory is a template for the mint directory.
diff --git a/src/mint/test_mint_nayapaisa/config/mint-common.conf b/src/mint/test_mint_nayapaisa/config/mint-common.conf
new file mode 100644
index 000000000..c1fede7a2
--- /dev/null
+++ b/src/mint/test_mint_nayapaisa/config/mint-common.conf
@@ -0,0 +1,6 @@
1[mint]
2db = postgres:///taler
3port = 4241
4master_pub = 6ZE0HEY2M0FWP61M0470HYBF4K6RRD5DP54372PD2TN9N9VX2VJG
5refresh_security_parameter = 3
6
diff --git a/src/mint/test_mint_nayapaisa/config/mint-keyup.conf b/src/mint/test_mint_nayapaisa/config/mint-keyup.conf
new file mode 100644
index 000000000..1542d1a63
--- /dev/null
+++ b/src/mint/test_mint_nayapaisa/config/mint-keyup.conf
@@ -0,0 +1,79 @@
1[mint_keys]
2
3# how long is one signkey valid?
4signkey_duration = 4 weeks
5
6# how long do we generate denomination and signing keys
7# ahead of time?
8lookahead_sign = 32 weeks 1 day
9
10# how long do we provide to clients denomination and signing keys
11# ahead of time?
12lookahead_provide = 4 weeks 1 day
13
14# what coin types do we have available?
15coin_types = default_eur_ct_10 default_eur_5 default_eur_10 default_eur_1000
16
17
18
19[mint_denom_duration_overlap]
20default_eur_ct_10 = 5 minutes
21default_eur_5 = 5 minutes
22default_eur_10 = 5 minutes
23default_eur_1000 = 5 minutes
24
25
26
27[mint_denom_value]
28default_eur_ct_10 = EUR:0.10
29default_eur_5 = EUR:5
30default_eur_10 = EUR:10
31default_eur_1000 = EUR:1000
32
33
34
35[mint_denom_duration_withdraw]
36default_eur_ct_10 = 7 days
37default_eur_5 = 7 days
38default_eur_10 = 7 days
39default_eur_1000 = 1 day
40
41
42
43[mint_denom_duration_spend]
44default_eur_ct_10 = 30 days
45default_eur_5 = 30 days
46default_eur_10 = 30 days
47default_eur_1000 = 30 day
48
49
50
51[mint_denom_fee_withdraw]
52default_eur_ct_10 = EUR:0.01
53default_eur_5 = EUR:0.01
54default_eur_10 = EUR:0.01
55default_eur_1000 = EUR:0.01
56
57
58[mint_denom_fee_deposit]
59default_eur_ct_10 = EUR:0.01
60default_eur_5 = EUR:0.01
61default_eur_10 = EUR:0.01
62default_eur_1000 = EUR:0.01
63
64
65
66[mint_denom_fee_refresh]
67default_eur_ct_10 = EUR:0.01
68default_eur_5 = EUR:0.01
69default_eur_10 = EUR:0.01
70default_eur_1000 = EUR:0.01
71
72
73
74[mint_denom_kappa]
75default_eur_ct_10 = 3
76default_eur_5 = 3
77default_eur_10 = 3
78default_eur_1000 = 5
79
diff --git a/src/mint/test_mint_nyadirahim.ecc b/src/mint/test_mint_nyadirahim.ecc
new file mode 100644
index 000000000..9db920894
--- /dev/null
+++ b/src/mint/test_mint_nyadirahim.ecc
@@ -0,0 +1 @@
WBf r񷕊Ќ:Vj \ No newline at end of file
diff --git a/src/mint/test_mint_nyadirahim/README b/src/mint/test_mint_nyadirahim/README
new file mode 100644
index 000000000..fce5e0180
--- /dev/null
+++ b/src/mint/test_mint_nyadirahim/README
@@ -0,0 +1 @@
This directory is a template for the mint directory.
diff --git a/src/mint/test_mint_nyadirahim/config/mint-common.conf b/src/mint/test_mint_nyadirahim/config/mint-common.conf
new file mode 100644
index 000000000..c4d528634
--- /dev/null
+++ b/src/mint/test_mint_nyadirahim/config/mint-common.conf
@@ -0,0 +1,6 @@
1[mint]
2db = postgres:///taler
3port = 4241
4master_pub = 7995WKK71KPKTBBMA5BHNBSZFGNRZPYNXDJMQ8EK86V9598H03TG
5refresh_security_parameter = 3
6
diff --git a/src/mint/test_mint_nyadirahim/config/mint-keyup.conf b/src/mint/test_mint_nyadirahim/config/mint-keyup.conf
new file mode 100644
index 000000000..1542d1a63
--- /dev/null
+++ b/src/mint/test_mint_nyadirahim/config/mint-keyup.conf
@@ -0,0 +1,79 @@
1[mint_keys]
2
3# how long is one signkey valid?
4signkey_duration = 4 weeks
5
6# how long do we generate denomination and signing keys
7# ahead of time?
8lookahead_sign = 32 weeks 1 day
9
10# how long do we provide to clients denomination and signing keys
11# ahead of time?
12lookahead_provide = 4 weeks 1 day
13
14# what coin types do we have available?
15coin_types = default_eur_ct_10 default_eur_5 default_eur_10 default_eur_1000
16
17
18
19[mint_denom_duration_overlap]
20default_eur_ct_10 = 5 minutes
21default_eur_5 = 5 minutes
22default_eur_10 = 5 minutes
23default_eur_1000 = 5 minutes
24
25
26
27[mint_denom_value]
28default_eur_ct_10 = EUR:0.10
29default_eur_5 = EUR:5
30default_eur_10 = EUR:10
31default_eur_1000 = EUR:1000
32
33
34
35[mint_denom_duration_withdraw]
36default_eur_ct_10 = 7 days
37default_eur_5 = 7 days
38default_eur_10 = 7 days
39default_eur_1000 = 1 day
40
41
42
43[mint_denom_duration_spend]
44default_eur_ct_10 = 30 days
45default_eur_5 = 30 days
46default_eur_10 = 30 days
47default_eur_1000 = 30 day
48
49
50
51[mint_denom_fee_withdraw]
52default_eur_ct_10 = EUR:0.01
53default_eur_5 = EUR:0.01
54default_eur_10 = EUR:0.01
55default_eur_1000 = EUR:0.01
56
57
58[mint_denom_fee_deposit]
59default_eur_ct_10 = EUR:0.01
60default_eur_5 = EUR:0.01
61default_eur_10 = EUR:0.01
62default_eur_1000 = EUR:0.01
63
64
65
66[mint_denom_fee_refresh]
67default_eur_ct_10 = EUR:0.01
68default_eur_5 = EUR:0.01
69default_eur_10 = EUR:0.01
70default_eur_1000 = EUR:0.01
71
72
73
74[mint_denom_kappa]
75default_eur_ct_10 = 3
76default_eur_5 = 3
77default_eur_10 = 3
78default_eur_1000 = 5
79
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
new file mode 100644
index 000000000..f935802a6
--- /dev/null
+++ b/src/util/Makefile.am
@@ -0,0 +1,39 @@
1AM_CPPFLAGS = -I$(top_srcdir)/src/include $(LIBGCRYPT_CFLAGS) $(POSTGRESQL_CPPFLAGS)
2
3lib_LTLIBRARIES = \
4 libtalerutil.la
5
6libtalerutil_la_SOURCES = \
7 util.c \
8 json.c \
9 db.c \
10 microhttpd.c \
11 rsa.c
12
13libtalerutil_la_LIBADD = \
14 -lgnunetutil \
15 $(LIBGCRYPT_LIBS) \
16 -ljansson \
17 -lmicrohttpd \
18 -lpq
19
20libtalerutil_la_LDFLAGS = \
21 $(POSTGRESQL_LDFLAGS) \
22 -version-info 0:0:0 \
23 -export-dynamic -no-undefined
24
25check_PROGRAMS = \
26 test-hash-context \
27 test-rsa
28
29TESTS = \
30 $(check_PROGRAMS)
31
32test_hash_context_SOURCES = test_hash_context.c
33test_hash_context_CPPFLAGS = $(AM_CPPFLAGS) $(LIBGCRYPT_CFLAGS)
34test_hash_context_LDADD = libtalerutil.la \
35 -lgnunetutil $(LIBGCRYPT_LIBS)
36
37test_rsa_SOURCES = test_rsa.c
38test_rsa_LDADD = libtalerutil.la \
39 -lgnunetutil $(LIBGCRYPT_LIBS)
diff --git a/src/util/db.c b/src/util/db.c
new file mode 100644
index 000000000..a0b234a06
--- /dev/null
+++ b/src/util/db.c
@@ -0,0 +1,196 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17
18/**
19 * @file util/db.c
20 * @brief helper functions for DB interactions
21 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
22 * @author Florian Dold
23 */
24
25#include "platform.h"
26#include <gnunet/gnunet_util_lib.h>
27#include "taler_db_lib.h"
28
29
30/**
31 * Execute a prepared statement.
32 */
33PGresult *
34TALER_DB_exec_prepared (PGconn *db_conn,
35 const char *name,
36 const struct TALER_DB_QueryParam *params)
37{
38 unsigned len;
39 unsigned i;
40
41 /* count the number of parameters */
42
43 {
44 const struct TALER_DB_QueryParam *x;
45 for (len = 0, x = params;
46 x->more;
47 len +=1, x += 1);
48 }
49
50 /* new scope to allow stack allocation without alloca */
51
52 {
53 void *param_values[len];
54 int param_lengths[len];
55 int param_formats[len];
56
57 for (i = 0; i < len; i += 1)
58 {
59 param_values[i] = (void *) params[i].data;
60 param_lengths[i] = params[i].size;
61 param_formats[i] = 1;
62 }
63 return PQexecPrepared (db_conn, name, len,
64 (const char **) param_values, param_lengths, param_formats, 1);
65 }
66}
67
68
69/**
70 * Extract results from a query result according to the given specification.
71 * If colums are NULL, the destination is not modified, and GNUNET_NO
72 * is returned.
73 *
74 * @return
75 * GNUNET_YES if all results could be extracted
76 * GNUNET_NO if at least one result was NULL
77 * GNUNET_SYSERR if a result was invalid (non-existing field)
78 */
79int
80TALER_DB_extract_result (PGresult *result,
81 struct TALER_DB_ResultSpec *rs,
82 int row)
83{
84 int had_null = GNUNET_NO;
85
86 for (; NULL != rs->fname; rs += 1)
87 {
88 int fnum;
89 fnum = PQfnumber (result, rs->fname);
90 if (fnum < 0)
91 {
92 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "field '%s' does not exist in result\n", rs->fname);
93 return GNUNET_SYSERR;
94 }
95
96 /* if a field is null, continue but
97 * remember that we now return a different result */
98
99 if (PQgetisnull (result, row, fnum))
100 {
101 had_null = GNUNET_YES;
102 continue;
103 }
104 const char *res;
105 if (rs->dst_size != PQgetlength (result, row, fnum))
106 {
107 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "field '%s' has wrong size (got %u, expected %u)\n",
108 rs->fname, (int) PQgetlength (result, row, fnum), (int) rs->dst_size);
109 return GNUNET_SYSERR;
110 }
111 res = PQgetvalue (result, row, fnum);
112 GNUNET_assert (NULL != res);
113 memcpy (rs->dst, res, rs->dst_size);
114 }
115 if (GNUNET_YES == had_null)
116 return GNUNET_NO;
117 return GNUNET_YES;
118}
119
120
121int
122TALER_DB_field_isnull (PGresult *result,
123 int row,
124 const char *fname)
125{
126 int fnum;
127 fnum = PQfnumber (result, fname);
128 GNUNET_assert (fnum >= 0);
129 if (PQgetisnull (result, row, fnum))
130 return GNUNET_YES;
131 return GNUNET_NO;
132}
133
134
135int
136TALER_DB_extract_amount_nbo (PGresult *result,
137 int row,
138 const char *val_name,
139 const char *frac_name,
140 const char *curr_name,
141 struct TALER_AmountNBO *r_amount_nbo)
142{
143 int val_num;
144 int frac_num;
145 int curr_num;
146 int len;
147
148 GNUNET_assert (NULL != strstr (val_name, "_val"));
149 GNUNET_assert (NULL != strstr (frac_name, "_frac"));
150 GNUNET_assert (NULL != strstr (curr_name, "_curr"));
151
152 val_num = PQfnumber (result, val_name);
153 GNUNET_assert (val_num >= 0);
154 frac_num = PQfnumber (result, frac_name);
155 GNUNET_assert (frac_num >= 0);
156 curr_num = PQfnumber (result, curr_name);
157 GNUNET_assert (curr_num >= 0);
158
159 r_amount_nbo->value = *(uint32_t *) PQgetvalue (result, row, val_num);
160 r_amount_nbo->fraction = *(uint32_t *) PQgetvalue (result, row, frac_num);
161 memset (r_amount_nbo->currency, 0, TALER_CURRENCY_LEN);
162 // FIXME: overflow?
163 len = PQgetlength (result, row, curr_num);
164 len = GNUNET_MIN (TALER_CURRENCY_LEN, len);
165 memcpy (r_amount_nbo->currency, PQgetvalue (result, row, curr_num), len);
166 r_amount_nbo->currency[TALER_CURRENCY_LEN - 1] = '\0';
167
168 return GNUNET_OK;
169}
170
171
172int
173TALER_DB_extract_amount (PGresult *result,
174 int row,
175 const char *val_name,
176 const char *frac_name,
177 const char *curr_name,
178 struct TALER_Amount *r_amount)
179{
180 struct TALER_AmountNBO amount_nbo;
181
182 (void)
183 TALER_DB_extract_amount_nbo (result,
184 row,
185 val_name,
186 frac_name,
187 curr_name,
188 &amount_nbo);
189 r_amount->value = ntohl (amount_nbo.value);
190 r_amount->fraction = ntohl (amount_nbo.fraction);
191 (void) strncpy (r_amount->currency, amount_nbo.currency, TALER_CURRENCY_LEN);
192
193 return GNUNET_OK;
194}
195
196/* end of util/db.c */
diff --git a/src/util/json.c b/src/util/json.c
new file mode 100644
index 000000000..269e6cf26
--- /dev/null
+++ b/src/util/json.c
@@ -0,0 +1,194 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file util/json.c
19 * @brief helper functions for JSON processing using libjansson
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */
22
23#include "platform.h"
24#include <gnunet/gnunet_util_lib.h>
25#include "taler_util.h"
26#include "taler_json_lib.h"
27
28/**
29 * Shorthand for exit jumps.
30 */
31#define EXITIF(cond) \
32 do { \
33 if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
34 } while (0)
35
36/**
37 * Print JSON parsing related error information
38 */
39#define WARN_JSON(error) \
40 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
41 "JSON parsing failed at %s:%u: %s (%s)", \
42 __FILE__, __LINE__, error.text, error.source)
43
44/**
45 * Shorthand for JSON parsing related exit jumps.
46 */
47#define UNPACK_EXITIF(cond) \
48 do { \
49 if (cond) { WARN_JSON(error); goto EXITIF_exit; } \
50 } while (0)
51
52/**
53 * Convert a TALER amount to a JSON
54 * object.
55 *
56 * @param amount the amount
57 * @return a json object describing the amount
58 */
59json_t *
60TALER_JSON_from_amount (struct TALER_Amount amount)
61{
62 json_t *j;
63 j = json_pack ("{s: s, s:I, s:I}",
64 "currency", amount.currency,
65 "value", (json_int_t) amount.value,
66 "fraction", (json_int_t) amount.fraction);
67 GNUNET_assert (NULL != j);
68 return j;
69}
70
71
72/**
73 * Convert absolute timestamp to a json string.
74 *
75 * @param the time stamp
76 * @return a json string with the timestamp in @a stamp
77 */
78json_t *
79TALER_JSON_from_abs (struct GNUNET_TIME_Absolute stamp)
80{
81 json_t *j;
82 char *mystr;
83 int ret;
84 ret = GNUNET_asprintf (&mystr, "%llu",
85 (long long) (stamp.abs_value_us / (1000 * 1000)));
86 GNUNET_assert (ret > 0);
87 j = json_string (mystr);
88 GNUNET_free (mystr);
89 return j;
90}
91
92
93
94/**
95 * Convert binary data to a JSON string
96 * with the base32crockford encoding.
97 *
98 * @param data binary data
99 * @param size size of @a data in bytes
100 * @return json string that encodes @a data
101 */
102json_t *
103TALER_JSON_from_data (const void *data, size_t size)
104{
105 char *buf;
106 json_t *json;
107 buf = TALER_data_to_string_alloc (data, size);
108 json = json_string (buf);
109 GNUNET_free (buf);
110 return json;
111}
112
113
114/**
115 * Parse given JSON object to Amount
116 *
117 * @param json the json object representing Amount
118 * @param r_amount where the amount has to be written
119 * @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
120 */
121int
122TALER_JSON_to_amount (json_t *json,
123 struct TALER_Amount *r_amount)
124{
125 char *currency;
126 json_int_t value;
127 json_int_t fraction;
128 json_error_t error;
129
130 UNPACK_EXITIF (0 != json_unpack_ex (json, &error, JSON_STRICT,
131 "{s:s, s:I, s:I}",
132 "curreny", &currency,
133 "value", &value,
134 "fraction", &fraction));
135 EXITIF (3 < strlen (currency));
136 r_amount->value = (uint32_t) value;
137 r_amount->fraction = (uint32_t) fraction;
138 return GNUNET_OK;
139
140 EXITIF_exit:
141 return GNUNET_SYSERR;
142}
143
144
145/**
146 * Parse given JSON object to Amount
147 *
148 * @param json the json object representing Amount
149 * @param r_amount where the amount has to be written
150 * @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
151 */
152int
153TALER_JSON_to_abs (json_t *json,
154 struct GNUNET_TIME_Absolute *abs)
155{
156 const char *str;
157 unsigned long long abs_value_s;
158
159 GNUNET_assert (NULL != abs);
160 EXITIF (NULL == (str = json_string_value (json)));
161 EXITIF (1 > sscanf (str, "%llu", &abs_value_s));
162 abs->abs_value_us = abs_value_s * 1000 * 1000;
163 return GNUNET_OK;
164
165 EXITIF_exit:
166 return GNUNET_SYSERR;
167}
168
169/**
170 * Parse given JSON object to data
171 *
172 * @param json the json object representing data
173 * @param out the pointer to hold the parsed data.
174 * @param out_size the size of r_data.
175 * @return GNUNET_OK upon successful parsing; GNUNET_SYSERR upon error
176 */
177int
178TALER_JSON_to_data (json_t *json,
179 void *out,
180 size_t out_size)
181{
182 const char *enc;
183 unsigned int len;
184
185 EXITIF (NULL == (enc = json_string_value (json)));
186 len = strlen (enc);
187 EXITIF ((((len * 5) / 8) + ((((len * 5) % 8) == 0) ? 0 : 1)) == out_size);
188 EXITIF (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, len, out, out_size));
189 return GNUNET_OK;
190 EXITIF_exit:
191 return GNUNET_SYSERR;
192}
193
194/* End of util/json.c */
diff --git a/src/util/microhttpd.c b/src/util/microhttpd.c
new file mode 100644
index 000000000..f3bea74f8
--- /dev/null
+++ b/src/util/microhttpd.c
@@ -0,0 +1,417 @@
1#include "platform.h"
2#include <gnunet/gnunet_util_lib.h>
3#include "taler_microhttpd_lib.h"
4
5
6
7/**
8 * Initial size for POST
9 * request buffer.
10 */
11#define REQUEST_BUFFER_INITIAL 1024
12
13/**
14 * Maximum POST request size
15 */
16#define REQUEST_BUFFER_MAX (1024*1024)
17
18
19/**
20 * Buffer for POST requests.
21 */
22struct Buffer
23{
24 /**
25 * Allocated memory
26 */
27 char *data;
28
29 /**
30 * Number of valid bytes in buffer.
31 */
32 size_t fill;
33
34 /**
35 * Number of allocated bytes in buffer.
36 */
37 size_t alloc;
38};
39
40
41/**
42 * Initialize a buffer.
43 *
44 * @param buf the buffer to initialize
45 * @param data the initial data
46 * @param data_size size of the initial data
47 * @param alloc_size size of the buffer
48 * @param max_size maximum size that the buffer can grow to
49 * @return a GNUnet result code
50 */
51static int
52buffer_init (struct Buffer *buf, const void *data, size_t data_size, size_t alloc_size, size_t max_size)
53{
54 if (data_size > max_size || alloc_size > max_size)
55 return GNUNET_SYSERR;
56 if (data_size > alloc_size)
57 alloc_size = data_size;
58 buf->data = GNUNET_malloc (alloc_size);
59 memcpy (buf->data, data, data_size);
60 return GNUNET_OK;
61}
62
63
64/**
65 * Free the data in a buffer. Does *not* free
66 * the buffer object itself.
67 *
68 * @param buf buffer to de-initialize
69 */
70static void
71buffer_deinit (struct Buffer *buf)
72{
73 GNUNET_free (buf->data);
74 buf->data = NULL;
75}
76
77
78/**
79 * Append data to a buffer, growing the buffer if necessary.
80 *
81 * @param buf the buffer to append to
82 * @param data the data to append
83 * @param size the size of @a data
84 * @param max_size maximum size that the buffer can grow to
85 * @return GNUNET_OK on success,
86 * GNUNET_NO if the buffer can't accomodate for the new data
87 * GNUNET_SYSERR on fatal error (out of memory?)
88 */
89static int
90buffer_append (struct Buffer *buf, const void *data, size_t data_size, size_t max_size)
91{
92 if (buf->fill + data_size > max_size)
93 return GNUNET_NO;
94 if (data_size + buf->fill > buf->alloc)
95 {
96 char *new_buf;
97 size_t new_size = buf->alloc;
98 while (new_size < buf->fill + data_size)
99 new_size += 2;
100 if (new_size > max_size)
101 return GNUNET_NO;
102 new_buf = GNUNET_malloc (new_size);
103 memcpy (new_buf, buf->data, buf->fill);
104 buf->data = new_buf;
105 buf->alloc = new_size;
106 }
107 memcpy (buf->data + buf->fill, data, data_size);
108 buf->fill += data_size;
109 return GNUNET_OK;
110}
111
112
113/**
114 * Send JSON object as response. Decreases the reference count of the
115 * JSON object.
116 *
117 * @param connection the MHD connection
118 * @param json the json object
119 * @param status_code the http status code
120 * @return MHD result code
121 */
122int
123send_response_json (struct MHD_Connection *connection,
124 json_t *json,
125 unsigned int status_code)
126{
127 struct MHD_Response *resp;
128 char *json_str;
129
130 json_str = json_dumps (json, JSON_INDENT(2));
131 json_decref (json);
132 resp = MHD_create_response_from_buffer (strlen (json_str), json_str,
133 MHD_RESPMEM_MUST_FREE);
134 if (NULL == resp)
135 return MHD_NO;
136 return MHD_queue_response (connection, status_code, resp);
137}
138
139
140/**
141 * Send a JSON object via an MHD connection,
142 * specified with the JANSSON pack syntax (see json_pack).
143 *
144 * @param connection connection to send the JSON over
145 * @param http_code HTTP status for the response
146 * @param fmt format string for pack
147 * @param ... varargs
148 * @return MHD_YES on success or MHD_NO on error
149 */
150int
151request_send_json_pack (struct MHD_Connection *connection,
152 unsigned int http_code,
153 const char *fmt, ...)
154{
155 json_t *msg;
156 va_list argp;
157 int ret;
158
159 va_start(argp, fmt);
160 msg = json_vpack_ex (NULL, 0, fmt, argp);
161 va_end(argp);
162 if (NULL == msg)
163 return MHD_NO;
164 ret = send_response_json (connection, msg, http_code);
165 json_decref (msg);
166 return ret;
167}
168
169
170/**
171 * Process a POST request containing a JSON object.
172 *
173 * @param connection the MHD connection
174 * @param con_cs the closure (contains a 'struct Buffer *')
175 * @param upload_data the POST data
176 * @param upload_data_size the POST data size
177 * @param json the JSON object for a completed request
178 *
179 * @returns
180 * GNUNET_YES if json object was parsed
181 * GNUNET_NO is request incomplete or invalid
182 * GNUNET_SYSERR on internal error
183 */
184int
185process_post_json (struct MHD_Connection *connection,
186 void **con_cls,
187 const char *upload_data,
188 size_t *upload_data_size,
189 json_t **json)
190{
191 struct Buffer *r = *con_cls;
192
193 if (NULL == *con_cls)
194 {
195 /* We are seeing a fresh POST request. */
196
197 r = GNUNET_new (struct Buffer);
198 if (GNUNET_OK != buffer_init (r, upload_data, *upload_data_size,
199 REQUEST_BUFFER_INITIAL, REQUEST_BUFFER_MAX))
200 {
201 *con_cls = NULL;
202 buffer_deinit (r);
203 GNUNET_free (r);
204 return GNUNET_SYSERR;
205 }
206 *upload_data_size = 0;
207 *con_cls = r;
208 return GNUNET_NO;
209 }
210 if (0 != *upload_data_size)
211 {
212 /* We are seeing an old request with more data available. */
213
214 if (GNUNET_OK != buffer_append (r, upload_data, *upload_data_size,
215 REQUEST_BUFFER_MAX))
216 {
217 /* Request too long or we're out of memory. */
218
219 *con_cls = NULL;
220 buffer_deinit (r);
221 GNUNET_free (r);
222 return GNUNET_SYSERR;
223 }
224 *upload_data_size = 0;
225 return GNUNET_NO;
226 }
227
228 /* We have seen the whole request. */
229
230 *json = json_loadb (r->data, r->fill, 0, NULL);
231 buffer_deinit (r);
232 GNUNET_free (r);
233 if (NULL == *json)
234 {
235 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Can't parse JSON request body\n");
236 return request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
237 GNUNET_NO, GNUNET_SYSERR,
238 "{s:s}",
239 "error", "invalid json");
240 }
241 *con_cls = NULL;
242
243 return GNUNET_YES;
244}
245
246
247/**
248 * Navigate through a JSON tree.
249 *
250 * Sends an error response if navigation is impossible (i.e.
251 * the JSON object is invalid)
252 *
253 * @param connection the connection to send an error response to
254 * @param root the JSON node to start the navigation at.
255 * @param ... navigation specification (see JNAV_*)
256 * @return GNUNET_YES if navigation was successful
257 * GNUNET_NO if json is malformed, error response was generated
258 * GNUNET_SYSERR on internal error
259 */
260int
261request_json_require_nav (struct MHD_Connection *connection,
262 const json_t *root, ...)
263{
264 va_list argp;
265 int ignore = GNUNET_NO;
266 // what's our current path from 'root'?
267 json_t *path;
268
269 path = json_array ();
270
271 va_start(argp, root);
272
273 while (1)
274 {
275 int command = va_arg(argp, int);
276 switch (command)
277 {
278 case JNAV_FIELD:
279 {
280 const char *fname = va_arg(argp, const char *);
281 if (GNUNET_YES == ignore)
282 break;
283 json_array_append_new (path, json_string (fname));
284 root = json_object_get (root, fname);
285 if (NULL == root)
286 {
287
288 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
289 0, 0,
290 "{s:s,s:o}",
291 "error", "missing field in JSON",
292 "path", path);
293 ignore = GNUNET_YES;
294 break;
295 }
296 }
297 break;
298 case JNAV_INDEX:
299 {
300 int fnum = va_arg(argp, int);
301 if (GNUNET_YES == ignore)
302 break;
303 json_array_append_new (path, json_integer (fnum));
304 root = json_array_get (root, fnum);
305 if (NULL == root)
306 {
307 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
308 0, 0,
309 "{s:s, s:o}",
310 "error", "missing index in JSON",
311 "path", path);
312 ignore = GNUNET_YES;
313 break;
314 }
315 }
316 break;
317 case JNAV_RET_DATA:
318 {
319 void *where = va_arg (argp, void *);
320 size_t len = va_arg (argp, size_t);
321 const char *str;
322 int res;
323
324 va_end(argp);
325 if (GNUNET_YES == ignore)
326 return GNUNET_NO;
327 str = json_string_value (root);
328 if (NULL == str)
329 {
330 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
331 0, 0,
332 "{s:s, s:o}",
333 "error", "string expected",
334 "path", path);
335 return GNUNET_NO;
336 }
337 res = GNUNET_STRINGS_string_to_data (str, strlen (str),
338 where, len);
339 if (GNUNET_OK != res)
340 {
341 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
342 0, 0,
343 "{s:s,s:o}",
344 "error", "malformed binary data in JSON",
345 "path", path);
346 return GNUNET_NO;
347 }
348 return GNUNET_YES;
349 }
350 break;
351 case JNAV_RET_DATA_VAR:
352 {
353 void **where = va_arg (argp, void **);
354 size_t *len = va_arg (argp, size_t *);
355 const char *str;
356
357 va_end(argp);
358 if (GNUNET_YES == ignore)
359 return GNUNET_NO;
360 str = json_string_value (root);
361 if (NULL == str)
362 {
363 GNUNET_break (0);
364 return GNUNET_SYSERR;
365 }
366 *len = (strlen (str) * 5) / 8;
367 if (where != NULL)
368 {
369 int res;
370 *where = GNUNET_malloc (*len);
371 res = GNUNET_STRINGS_string_to_data (str, strlen (str),
372 *where, *len);
373 if (GNUNET_OK != res)
374 {
375 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
376 0, 0,
377 "{s:s, s:o}",
378 "error", "malformed binary data in JSON",
379 "path", path);
380 return GNUNET_NO;
381 }
382 }
383 return GNUNET_OK;
384 }
385 break;
386 case JNAV_RET_TYPED_JSON:
387 {
388 int typ = va_arg (argp, int);
389 const json_t **r_json = va_arg (argp, const json_t **);
390
391 va_end(argp);
392 if (GNUNET_YES == ignore)
393 return GNUNET_NO;
394 if (typ != -1 && json_typeof (root) != typ)
395 {
396 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
397 0, 0,
398 "{s:s, s:i, s:i s:o}",
399 "error", "wrong JSON field type",
400 "type_expected", typ,
401 "type_actual", json_typeof (root),
402 "path", path);
403 return GNUNET_NO;
404 }
405 *r_json = root;
406 return GNUNET_OK;
407 }
408 break;
409 default:
410 GNUNET_assert (0);
411 }
412 }
413 GNUNET_assert (0);
414}
415
416
417
diff --git a/src/util/misc.supp b/src/util/misc.supp
new file mode 100644
index 000000000..afcac6128
--- /dev/null
+++ b/src/util/misc.supp
@@ -0,0 +1,28 @@
1{
2 <gnunet_gcrypt_init>
3 Memcheck:Leak
4 match-leak-kinds:reachable
5 ...
6 fun:GNUNET_CRYPTO_random_init
7 fun:call_init.part.0
8 ...
9}
10
11{
12 <mpi_ec_new>
13 Memcheck:Leak
14 match-leak-kinds:reachable
15 ...
16 fun:point_from_keyparam
17 fun:_gcry_mpi_ec_new
18 ...
19}
20
21{
22 <gnunet_log_setup>
23 Memcheck:Leak
24 match-leak-kinds:reachable
25 ...
26 fun:GNUNET_log_setup
27 ...
28} \ No newline at end of file
diff --git a/src/util/rsa.c b/src/util/rsa.c
new file mode 100644
index 000000000..cde56be9e
--- /dev/null
+++ b/src/util/rsa.c
@@ -0,0 +1,925 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file util/rsa.c
19 * @brief RSA key management utilities. Most of the code here is taken from
20 * gnunet-0.9.5a
21 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
22 *
23 * Authors of the gnunet code:
24 * Christian Grothoff
25 * Krista Bennett
26 * Gerd Knorr <kraxel@bytesex.org>
27 * Ioana Patrascu
28 * Tzvetan Horozov
29 */
30
31#include "platform.h"
32#include "gcrypt.h"
33#include "gnunet/gnunet_util_lib.h"
34#include "taler_rsa.h"
35
36
37
38#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
39
40#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
41
42#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
43
44/**
45 * Log an error message at log-level 'level' that indicates
46 * a failure of the command 'cmd' with the message given
47 * by gcry_strerror(rc).
48 */
49#define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
50
51/**
52 * Shorthand to cleanup non null mpi data types
53 */
54#define mpi_release_non_null(mpi) \
55 if (NULL != mpi) gcry_mpi_release (mpi);
56
57/**
58 * The private information of an RSA key pair.
59 * NOTE: this must match the definition in crypto_ksk.c and gnunet-rsa.c!
60 */
61struct TALER_RSA_PrivateKey
62{
63 /**
64 * Libgcrypt S-expression for the ECC key.
65 */
66 gcry_sexp_t sexp;
67};
68
69
70/**
71 * Extract values from an S-expression.
72 *
73 * @param array where to store the result(s)
74 * @param sexp S-expression to parse
75 * @param topname top-level name in the S-expression that is of interest
76 * @param elems names of the elements to extract
77 * @return 0 on success
78 */
79static int
80key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname,
81 const char *elems)
82{
83 gcry_sexp_t list;
84 gcry_sexp_t l2;
85 const char *s;
86 unsigned int i;
87 unsigned int idx;
88
89 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
90 return 1;
91 l2 = gcry_sexp_cadr (list);
92 gcry_sexp_release (list);
93 list = l2;
94 if (! list)
95 return 2;
96 idx = 0;
97 for (s = elems; *s; s++, idx++)
98 {
99 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
100 {
101 for (i = 0; i < idx; i++)
102 {
103 gcry_free (array[i]);
104 array[i] = NULL;
105 }
106 gcry_sexp_release (list);
107 return 3; /* required parameter not found */
108 }
109 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
110 gcry_sexp_release (l2);
111 if (! array[idx])
112 {
113 for (i = 0; i < idx; i++)
114 {
115 gcry_free (array[i]);
116 array[i] = NULL;
117 }
118 gcry_sexp_release (list);
119 return 4; /* required parameter is invalid */
120 }
121 }
122 gcry_sexp_release (list);
123 return 0;
124}
125
126/**
127 * If target != size, move target bytes to the
128 * end of the size-sized buffer and zero out the
129 * first target-size bytes.
130 *
131 * @param buf original buffer
132 * @param size number of bytes in the buffer
133 * @param target target size of the buffer
134 */
135static void
136adjust (unsigned char *buf, size_t size, size_t target)
137{
138 if (size < target)
139 {
140 memmove (&buf[target - size], buf, size);
141 memset (buf, 0, target - size);
142 }
143}
144
145
146/**
147 * Create a new private key. Caller must free return value.
148 *
149 * @return fresh private key
150 */
151struct TALER_RSA_PrivateKey *
152TALER_RSA_key_create ()
153{
154 struct TALER_RSA_PrivateKey *ret;
155 gcry_sexp_t s_key;
156 gcry_sexp_t s_keyparam;
157
158 GNUNET_assert (0 ==
159 gcry_sexp_build (&s_keyparam, NULL,
160 "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))",
161 2048));
162 GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam));
163 gcry_sexp_release (s_keyparam);
164#if EXTRA_CHECKS
165 GNUNET_assert (0 == gcry_pk_testkey (s_key));
166#endif
167 ret = GNUNET_malloc (sizeof (struct TALER_RSA_PrivateKey));
168 ret->sexp = s_key;
169 return ret;
170}
171
172
173/**
174 * Free memory occupied by the private key.
175 *
176 * @param key pointer to the memory to free
177 */
178void
179TALER_RSA_key_free (struct TALER_RSA_PrivateKey *key)
180{
181 gcry_sexp_release (key->sexp);
182 GNUNET_free (key);
183}
184
185
186/**
187 * Encode the private key in a format suitable for
188 * storing it into a file.
189 * @return encoding of the private key
190 */
191struct TALER_RSA_PrivateKeyBinaryEncoded *
192TALER_RSA_encode_key (const struct TALER_RSA_PrivateKey *hostkey)
193{
194 struct TALER_RSA_PrivateKeyBinaryEncoded *retval;
195 gcry_mpi_t pkv[6];
196 void *pbu[6];
197 size_t sizes[6];
198 int rc;
199 int i;
200 int size;
201
202#if EXTRA_CHECKS
203 if (gcry_pk_testkey (hostkey->sexp))
204 {
205 GNUNET_break (0);
206 return NULL;
207 }
208#endif
209
210 memset (pkv, 0, sizeof (gcry_mpi_t) * 6);
211 rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "nedpqu");
212 if (rc)
213 rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "nedpqu");
214 if (rc)
215 rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "nedpq");
216 if (rc)
217 rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "nedpq");
218 if (rc)
219 rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "ned");
220 if (rc)
221 rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "ned");
222 GNUNET_assert (0 == rc);
223 size = sizeof (struct TALER_RSA_PrivateKeyBinaryEncoded);
224 for (i = 0; i < 6; i++)
225 {
226 if (NULL != pkv[i])
227 {
228 GNUNET_assert (0 ==
229 gcry_mpi_aprint (GCRYMPI_FMT_USG,
230 (unsigned char **) &pbu[i], &sizes[i],
231 pkv[i]));
232 size += sizes[i];
233 }
234 else
235 {
236 pbu[i] = NULL;
237 sizes[i] = 0;
238 }
239 }
240 GNUNET_assert (size < 65536);
241 retval = GNUNET_malloc (size);
242 retval->len = htons (size);
243 i = 0;
244 retval->sizen = htons (sizes[0]);
245 memcpy (&((char *) (&retval[1]))[i], pbu[0], sizes[0]);
246 i += sizes[0];
247 retval->sizee = htons (sizes[1]);
248 memcpy (&((char *) (&retval[1]))[i], pbu[1], sizes[1]);
249 i += sizes[1];
250 retval->sized = htons (sizes[2]);
251 memcpy (&((char *) (&retval[1]))[i], pbu[2], sizes[2]);
252 i += sizes[2];
253 /* swap p and q! */
254 retval->sizep = htons (sizes[4]);
255 memcpy (&((char *) (&retval[1]))[i], pbu[4], sizes[4]);
256 i += sizes[4];
257 retval->sizeq = htons (sizes[3]);
258 memcpy (&((char *) (&retval[1]))[i], pbu[3], sizes[3]);
259 i += sizes[3];
260 retval->sizedmp1 = htons (0);
261 retval->sizedmq1 = htons (0);
262 memcpy (&((char *) (&retval[1]))[i], pbu[5], sizes[5]);
263 for (i = 0; i < 6; i++)
264 {
265 if (pkv[i] != NULL)
266 gcry_mpi_release (pkv[i]);
267 if (pbu[i] != NULL)
268 free (pbu[i]);
269 }
270 return retval;
271}
272
273
274/**
275 * Extract the public key of the given private key.
276 *
277 * @param priv the private key
278 * @param pub where to write the public key
279 */
280void
281TALER_RSA_key_get_public (const struct TALER_RSA_PrivateKey *priv,
282 struct TALER_RSA_PublicKeyBinaryEncoded *pub)
283{
284 gcry_mpi_t skey[2];
285 size_t size;
286 int rc;
287
288 rc = key_from_sexp (skey, priv->sexp, "public-key", "ne");
289 if (0 != rc)
290 rc = key_from_sexp (skey, priv->sexp, "private-key", "ne");
291 if (0 != rc)
292 rc = key_from_sexp (skey, priv->sexp, "rsa", "ne");
293 GNUNET_assert (0 == rc);
294 pub->len =
295 htons (sizeof (struct TALER_RSA_PublicKeyBinaryEncoded) -
296 sizeof (pub->padding));
297 pub->sizen = htons (TALER_RSA_DATA_ENCODING_LENGTH);
298 pub->padding = 0;
299 size = TALER_RSA_DATA_ENCODING_LENGTH;
300 GNUNET_assert (0 ==
301 gcry_mpi_print (GCRYMPI_FMT_USG, &pub->key[0], size, &size,
302 skey[0]));
303 adjust (&pub->key[0], size, TALER_RSA_DATA_ENCODING_LENGTH);
304 size = TALER_RSA_KEY_LENGTH - TALER_RSA_DATA_ENCODING_LENGTH;
305 GNUNET_assert (0 ==
306 gcry_mpi_print (GCRYMPI_FMT_USG,
307 &pub->key
308 [TALER_RSA_DATA_ENCODING_LENGTH], size,
309 &size, skey[1]));
310 adjust (&pub->key[TALER_RSA_DATA_ENCODING_LENGTH], size,
311 TALER_RSA_KEY_LENGTH -
312 TALER_RSA_DATA_ENCODING_LENGTH);
313 gcry_mpi_release (skey[0]);
314 gcry_mpi_release (skey[1]);
315}
316
317
318/**
319 * Decode the private key from the data-format back
320 * to the "normal", internal format.
321 *
322 * @param buf the buffer where the private key data is stored
323 * @param len the length of the data in 'buffer'
324 * @return NULL on error
325 */
326struct TALER_RSA_PrivateKey *
327TALER_RSA_decode_key (const char *buf, uint16_t len)
328{
329 struct TALER_RSA_PrivateKey *ret;
330 const struct TALER_RSA_PrivateKeyBinaryEncoded *encoding =
331 (const struct TALER_RSA_PrivateKeyBinaryEncoded *) buf;
332 gcry_sexp_t res;
333 gcry_mpi_t n;
334 gcry_mpi_t e;
335 gcry_mpi_t d;
336 gcry_mpi_t p;
337 gcry_mpi_t q;
338 gcry_mpi_t u;
339 int rc;
340 size_t size;
341 size_t pos;
342 uint16_t enc_len;
343 size_t erroff;
344
345 enc_len = ntohs (encoding->len);
346 if (len != enc_len)
347 return NULL;
348
349 pos = 0;
350 size = ntohs (encoding->sizen);
351 rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG,
352 &((const unsigned char *) (&encoding[1]))[pos], size,
353 &size);
354 pos += ntohs (encoding->sizen);
355 if (0 != rc)
356 {
357 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
358 return NULL;
359 }
360 size = ntohs (encoding->sizee);
361 rc = gcry_mpi_scan (&e, GCRYMPI_FMT_USG,
362 &((const unsigned char *) (&encoding[1]))[pos], size,
363 &size);
364 pos += ntohs (encoding->sizee);
365 if (0 != rc)
366 {
367 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
368 gcry_mpi_release (n);
369 return NULL;
370 }
371 size = ntohs (encoding->sized);
372 rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG,
373 &((const unsigned char *) (&encoding[1]))[pos], size,
374 &size);
375 pos += ntohs (encoding->sized);
376 if (0 != rc)
377 {
378 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
379 gcry_mpi_release (n);
380 gcry_mpi_release (e);
381 return NULL;
382 }
383 /* swap p and q! */
384 size = ntohs (encoding->sizep);
385 if (size > 0)
386 {
387 rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG,
388 &((const unsigned char *) (&encoding[1]))[pos], size,
389 &size);
390 pos += ntohs (encoding->sizep);
391 if (0 != rc)
392 {
393 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
394 gcry_mpi_release (n);
395 gcry_mpi_release (e);
396 gcry_mpi_release (d);
397 return NULL;
398 }
399 }
400 else
401 q = NULL;
402 size = ntohs (encoding->sizeq);
403 if (size > 0)
404 {
405 rc = gcry_mpi_scan (&p, GCRYMPI_FMT_USG,
406 &((const unsigned char *) (&encoding[1]))[pos], size,
407 &size);
408 pos += ntohs (encoding->sizeq);
409 if (0 != rc)
410 {
411 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
412 gcry_mpi_release (n);
413 gcry_mpi_release (e);
414 gcry_mpi_release (d);
415 if (NULL != q)
416 gcry_mpi_release (q);
417 return NULL;
418 }
419 }
420 else
421 p = NULL;
422 pos += ntohs (encoding->sizedmp1);
423 pos += ntohs (encoding->sizedmq1);
424 size =
425 ntohs (encoding->len) - sizeof (struct TALER_RSA_PrivateKeyBinaryEncoded) - pos;
426 if (size > 0)
427 {
428 rc = gcry_mpi_scan (&u, GCRYMPI_FMT_USG,
429 &((const unsigned char *) (&encoding[1]))[pos], size,
430 &size);
431 if (0 != rc)
432 {
433 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
434 gcry_mpi_release (n);
435 gcry_mpi_release (e);
436 gcry_mpi_release (d);
437 if (NULL != p)
438 gcry_mpi_release (p);
439 if (NULL != q)
440 gcry_mpi_release (q);
441 return NULL;
442 }
443 }
444 else
445 u = NULL;
446
447 if ((NULL != p) && (NULL != q) && (NULL != u))
448 {
449 rc = gcry_sexp_build (&res, &erroff,
450 "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)(u %m)))",
451 n, e, d, p, q, u);
452 }
453 else
454 {
455 if ((NULL != p) && (NULL != q))
456 {
457 rc = gcry_sexp_build (&res, &erroff,
458 "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)))",
459 n, e, d, p, q);
460 }
461 else
462 {
463 rc = gcry_sexp_build (&res, &erroff,
464 "(private-key(rsa(n %m)(e %m)(d %m)))", n, e, d);
465 }
466 }
467 gcry_mpi_release (n);
468 gcry_mpi_release (e);
469 gcry_mpi_release (d);
470 if (NULL != p)
471 gcry_mpi_release (p);
472 if (NULL != q)
473 gcry_mpi_release (q);
474 if (NULL != u)
475 gcry_mpi_release (u);
476
477 if (0 != rc)
478 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
479 if (0 != (rc = gcry_pk_testkey (res)))
480 {
481 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
482 return NULL;
483 }
484 ret = GNUNET_malloc (sizeof (struct TALER_RSA_PrivateKey));
485 ret->sexp = res;
486 return ret;
487}
488
489
490/**
491 * Convert a public key to a string.
492 *
493 * @param pub key to convert
494 * @return string representing 'pub'
495 */
496char *
497TALER_RSA_public_key_to_string (const struct TALER_RSA_PublicKeyBinaryEncoded *pub)
498{
499 char *pubkeybuf;
500 size_t keylen = (sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)) * 8;
501 char *end;
502
503 if (keylen % 5 > 0)
504 keylen += 5 - keylen % 5;
505 keylen /= 5;
506 pubkeybuf = GNUNET_malloc (keylen + 1);
507 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
508 sizeof (struct TALER_RSA_PublicKeyBinaryEncoded),
509 pubkeybuf,
510 keylen);
511 if (NULL == end)
512 {
513 GNUNET_free (pubkeybuf);
514 return NULL;
515 }
516 *end = '\0';
517 return pubkeybuf;
518}
519
520
521/**
522 * Convert a string representing a public key to a public key.
523 *
524 * @param enc encoded public key
525 * @param enclen number of bytes in enc (without 0-terminator)
526 * @param pub where to store the public key
527 * @return GNUNET_OK on success
528 */
529int
530TALER_RSA_public_key_from_string (const char *enc,
531 size_t enclen,
532 struct TALER_RSA_PublicKeyBinaryEncoded *pub)
533{
534 size_t keylen = (sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)) * 8;
535
536 if (keylen % 5 > 0)
537 keylen += 5 - keylen % 5;
538 keylen /= 5;
539 if (enclen != keylen)
540 return GNUNET_SYSERR;
541
542 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
543 (unsigned char*) pub,
544 sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)))
545 return GNUNET_SYSERR;
546 if ( (ntohs (pub->len) != sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)) ||
547 (ntohs (pub->padding) != 0) ||
548 (ntohs (pub->sizen) != TALER_RSA_DATA_ENCODING_LENGTH) )
549 return GNUNET_SYSERR;
550 return GNUNET_OK;
551}
552
553
554/**
555 * Convert the data specified in the given purpose argument to an
556 * S-expression suitable for signature operations.
557 *
558 * @param ptr pointer to the data to convert
559 * @param size the size of the data
560 * @return converted s-expression
561 */
562static gcry_sexp_t
563data_to_sexp (const void *ptr, size_t size)
564{
565 gcry_mpi_t value;
566 gcry_sexp_t data;
567
568 value = NULL;
569 data = NULL;
570 GNUNET_assert (0 == gcry_mpi_scan (&value, GCRYMPI_FMT_USG, ptr, size, NULL));
571 GNUNET_assert (0 == gcry_sexp_build (&data, NULL, "(data (flags raw) (value %M))", value));
572 gcry_mpi_release (value);
573 return data;
574}
575
576
577/**
578 * Sign the given hash block.
579 *
580 * @param key private key to use for the signing
581 * @param hash the block containing the hash of the message to sign
582 * @param hash_size the size of the hash block
583 * @param sig where to write the signature
584 * @return GNUNET_SYSERR on error, GNUNET_OK on success
585 */
586int
587TALER_RSA_sign (const struct TALER_RSA_PrivateKey *key,
588 const void *hash,
589 size_t hash_size,
590 struct TALER_RSA_Signature *sig)
591{
592 gcry_sexp_t result;
593 gcry_sexp_t data;
594 size_t ssize;
595 gcry_mpi_t rval;
596
597 data = data_to_sexp (hash, hash_size);
598 GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp));
599 gcry_sexp_release (data);
600 GNUNET_assert (0 == key_from_sexp (&rval, result, "rsa", "s"));
601 gcry_sexp_release (result);
602 ssize = sizeof (struct TALER_RSA_Signature);
603 GNUNET_assert (0 ==
604 gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) sig, ssize,
605 &ssize, rval));
606 gcry_mpi_release (rval);
607 adjust (sig->sig, ssize, sizeof (struct TALER_RSA_Signature));
608 return GNUNET_OK;
609}
610
611
612/**
613 * Convert the given public key from the network format to the
614 * S-expression that can be used by libgcrypt.
615 *
616 * @param publicKey public key to decode
617 * @return NULL on error
618 */
619static gcry_sexp_t
620decode_public_key (const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey)
621{
622 gcry_sexp_t result;
623 gcry_mpi_t n;
624 gcry_mpi_t e;
625 size_t size;
626 size_t erroff;
627 int rc;
628
629 if ((ntohs (publicKey->sizen) != TALER_RSA_DATA_ENCODING_LENGTH) ||
630 (ntohs (publicKey->len) !=
631 sizeof (struct TALER_RSA_PublicKeyBinaryEncoded) -
632 sizeof (publicKey->padding)))
633 {
634 GNUNET_break (0);
635 return NULL;
636 }
637 size = TALER_RSA_DATA_ENCODING_LENGTH;
638 if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG, &publicKey->key[0], size, &size)))
639 {
640 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
641 return NULL;
642 }
643 size = TALER_RSA_KEY_LENGTH - TALER_RSA_DATA_ENCODING_LENGTH;
644 if (0 != (rc = gcry_mpi_scan (&e, GCRYMPI_FMT_USG,
645 &publicKey->key[TALER_RSA_DATA_ENCODING_LENGTH],
646 size, &size)))
647 {
648 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
649 gcry_mpi_release (n);
650 return NULL;
651 }
652 rc = gcry_sexp_build (&result, &erroff, "(public-key(rsa(n %m)(e %m)))", n,
653 e);
654 gcry_mpi_release (n);
655 gcry_mpi_release (e);
656 if (0 != rc)
657 {
658 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */
659 return NULL;
660 }
661 return result;
662}
663
664
665/**
666 * Verify signature with the given hash.
667 *
668 * @param hash the hash code to verify against the signature
669 * @param sig signature that is being validated
670 * @param publicKey public key of the signer
671 * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid
672 */
673int
674TALER_RSA_hash_verify (const struct GNUNET_HashCode *hash,
675 const struct TALER_RSA_Signature *sig,
676 const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey)
677{
678 gcry_sexp_t data;
679 gcry_sexp_t sigdata;
680 size_t size;
681 gcry_mpi_t val;
682 gcry_sexp_t psexp;
683 size_t erroff;
684 int rc;
685
686 size = sizeof (struct TALER_RSA_Signature);
687 GNUNET_assert (0 ==
688 gcry_mpi_scan (&val, GCRYMPI_FMT_USG,
689 (const unsigned char *) sig, size, &size));
690 GNUNET_assert (0 ==
691 gcry_sexp_build (&sigdata, &erroff, "(sig-val(rsa(s %m)))",
692 val));
693 gcry_mpi_release (val);
694 data = data_to_sexp (hash, sizeof (struct GNUNET_HashCode));
695 if (! (psexp = decode_public_key (publicKey)))
696 {
697 gcry_sexp_release (data);
698 gcry_sexp_release (sigdata);
699 return GNUNET_SYSERR;
700 }
701 rc = gcry_pk_verify (sigdata, data, psexp);
702 gcry_sexp_release (psexp);
703 gcry_sexp_release (data);
704 gcry_sexp_release (sigdata);
705 if (rc)
706 {
707 LOG (GNUNET_ERROR_TYPE_WARNING,
708 _("RSA signature verification failed at %s:%d: %s\n"), __FILE__,
709 __LINE__, gcry_strerror (rc));
710 return GNUNET_SYSERR;
711 }
712 return GNUNET_OK;
713}
714
715
716/**
717 * Verify signature on the given message
718 *
719 * @param msg the message
720 * @param size the size of the message
721 * @param sig signature that is being validated
722 * @param publicKey public key of the signer
723 * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid
724 */
725int
726TALER_RSA_verify (const void *msg, size_t size,
727 const struct TALER_RSA_Signature *sig,
728 const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey)
729{
730 struct GNUNET_HashCode hash;
731
732 GNUNET_CRYPTO_hash (msg, size, &hash);
733 return TALER_RSA_hash_verify (&hash, sig, publicKey);
734}
735
736/**
737 * The blinding key is equal in length to the RSA modulus
738 */
739#define TALER_RSA_BLINDING_KEY_LEN TALER_RSA_DATA_ENCODING_LENGTH
740
741struct TALER_RSA_BlindingKey
742{
743 /**
744 * The blinding factor
745 */
746 gcry_mpi_t r;
747};
748
749struct TALER_RSA_BlindingKey *
750TALER_RSA_blinding_key_create ()
751{
752 struct TALER_RSA_BlindingKey *blind;
753
754 blind = GNUNET_new (struct TALER_RSA_BlindingKey);
755 blind->r = gcry_mpi_new (TALER_RSA_BLINDING_KEY_LEN * 8);
756 gcry_mpi_randomize (blind->r, TALER_RSA_BLINDING_KEY_LEN * 8, GCRY_STRONG_RANDOM);
757 return blind;
758}
759
760
761void
762TALER_RSA_blinding_key_destroy (struct TALER_RSA_BlindingKey *bkey)
763{
764 gcry_mpi_release (bkey->r);
765 GNUNET_free (bkey);
766}
767
768
769struct TALER_RSA_BlindedSignaturePurpose *
770TALER_RSA_message_blind (const void *msg, size_t size,
771 struct TALER_RSA_BlindingKey *bkey,
772 struct TALER_RSA_PublicKeyBinaryEncoded *pkey)
773{
774 struct TALER_RSA_BlindedSignaturePurpose *bsp;
775 struct GNUNET_HashCode hash;
776 gcry_sexp_t psexp;
777 gcry_mpi_t data;
778 gcry_mpi_t skey[2];
779 gcry_mpi_t r_e;
780 gcry_mpi_t data_r_e;
781 size_t rsize;
782 gcry_error_t rc;
783 int ret;
784
785 bsp = NULL;
786 psexp = NULL;
787 data = NULL;
788 skey[0] = skey[1] = NULL;
789 r_e = NULL;
790 data_r_e = NULL;
791 rsize = 0;
792 rc = 0;
793 ret = 0;
794 if (! (psexp = decode_public_key (pkey)))
795 return NULL;
796 ret = key_from_sexp (skey, psexp, "public-key", "ne");
797 if (0 != ret)
798 ret = key_from_sexp (skey, psexp, "rsa", "ne");
799 gcry_sexp_release (psexp);
800 psexp = NULL;
801 GNUNET_assert (0 == ret);
802 GNUNET_CRYPTO_hash (msg, size, &hash);
803 if (0 != (rc=gcry_mpi_scan (&data, GCRYMPI_FMT_USG,
804 (const unsigned char *) msg, size, &rsize)))
805 {
806 LOG_GCRY (GNUNET_ERROR_TYPE_WARNING, "gcry_mpi_scan", rc);
807 goto cleanup;
808 }
809 r_e = gcry_mpi_new (0);
810 gcry_mpi_powm (r_e, bkey->r,
811 skey[1], /* e */
812 skey[0]); /* n */
813
814 data_r_e = gcry_mpi_new (0);
815 gcry_mpi_mulm (data_r_e, data, r_e, skey[0]);
816
817 bsp = GNUNET_new (struct TALER_RSA_BlindedSignaturePurpose);
818 rc = gcry_mpi_print (GCRYMPI_FMT_USG,
819 (unsigned char *) bsp,
820 sizeof (struct TALER_RSA_BlindedSignaturePurpose),
821 &rsize,
822 data_r_e);
823 GNUNET_assert (0 == rc);
824 adjust ((unsigned char *) bsp, rsize,
825 sizeof (struct TALER_RSA_BlindedSignaturePurpose));
826
827 cleanup:
828 if (NULL != psexp) gcry_sexp_release (psexp);
829 mpi_release_non_null (skey[0]);
830 mpi_release_non_null (skey[1]);
831 mpi_release_non_null (data);
832 mpi_release_non_null (r_e);
833 mpi_release_non_null (data_r_e);
834 return bsp;
835}
836
837
838int
839TALER_RSA_unblind (struct TALER_RSA_Signature *sig,
840 struct TALER_RSA_BlindingKey *bkey,
841 struct TALER_RSA_PublicKeyBinaryEncoded *pkey)
842{
843 gcry_sexp_t psexp;
844 gcry_mpi_t skey;
845 gcry_mpi_t sigval;
846 gcry_mpi_t r_inv;
847 gcry_mpi_t ubsig;
848 size_t rsize;
849 gcry_error_t rc;
850 int ret;
851
852 psexp = NULL;
853 skey = NULL;
854 sigval = NULL;
855 r_inv = NULL;
856 ubsig = NULL;
857 rsize = 0;
858 rc = 0;
859 ret = GNUNET_SYSERR;
860 if (! (psexp = decode_public_key (pkey)))
861 return GNUNET_SYSERR;
862 ret = key_from_sexp (&skey, psexp, "public-key", "n");
863 if (0 != ret)
864 ret = key_from_sexp (&skey, psexp, "rsa", "n");
865 gcry_sexp_release (psexp);
866 psexp = NULL;
867 if (0 != (rc = gcry_mpi_scan (&sigval, GCRYMPI_FMT_USG,
868 (const unsigned char *) sig,
869 sizeof (struct TALER_RSA_Signature),
870 &rsize)))
871 {
872 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
873 goto cleanup;
874 }
875 r_inv = gcry_mpi_new (0);
876 GNUNET_assert (1 == gcry_mpi_invm (r_inv, bkey->r, skey)); /* n: skey */
877 ubsig = gcry_mpi_new (0);
878 gcry_mpi_mulm (ubsig, sigval, r_inv, skey);
879 rc = gcry_mpi_print (GCRYMPI_FMT_USG,
880 (unsigned char *) sig,
881 sizeof (struct TALER_RSA_Signature),
882 &rsize,
883 ubsig);
884 GNUNET_assert (0 == rc);
885 adjust ((unsigned char *) sig, rsize, sizeof (struct TALER_RSA_Signature));
886 ret = GNUNET_OK;
887
888 cleanup:
889 if (NULL != psexp) gcry_sexp_release (psexp);
890 mpi_release_non_null (skey);
891 mpi_release_non_null (sigval);
892 mpi_release_non_null (r_inv);
893 mpi_release_non_null (ubsig);
894 return ret;
895}
896
897
898/**
899 * Encode a blinding key
900 *
901 * @param bkey the blinding key to encode
902 * @param bkey_enc where to store the encoded binary key
903 * @return #GNUNET_OK upon successful encoding; #GNUNET_SYSERR upon failure
904 */
905int
906TALER_RSA_blinding_key_encode (struct TALER_RSA_BlindingKey *bkey,
907 struct TALER_RSA_BlindingKeyBinaryEncoded *bkey_enc)
908{
909 GNUNET_abort (); /* FIXME: not implemented */
910}
911
912
913/**
914 * Decode a blinding key from its encoded form
915 *
916 * @param bkey_enc the encoded blinding key
917 * @return the decoded blinding key; NULL upon error
918 */
919struct TALER_RSA_BlindingKey *
920TALER_RSA_blinding_key_decode (struct TALER_RSA_BlindingKeyBinaryEncoded *bkey_enc)
921{
922 GNUNET_abort (); /* FIXME: not implemented */
923}
924
925/* end of util/rsa.c */
diff --git a/src/util/test_hash_context.c b/src/util/test_hash_context.c
new file mode 100644
index 000000000..e5110f212
--- /dev/null
+++ b/src/util/test_hash_context.c
@@ -0,0 +1,48 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file util/test_hash_context.c
19 * @brief test case for incremental hashing
20 * @author Florian Dold
21 */
22
23#include "platform.h"
24#include "taler_util.h"
25#include <gcrypt.h>
26
27#define LEN 1234
28
29int main()
30{
31 char data[1234];
32 struct GNUNET_HashCode hc1;
33 struct GNUNET_HashCode hc2;
34 struct TALER_HashContext hctx;
35
36 memset (data, 42, LEN);
37
38 TALER_hash_context_start (&hctx);
39 TALER_hash_context_read (&hctx, data, LEN);
40 TALER_hash_context_finish (&hctx, &hc1);
41
42 GNUNET_CRYPTO_hash (data, LEN, &hc2);
43
44 if (0 == memcmp (&hc1, &hc2, sizeof (struct GNUNET_HashCode)))
45 return 0;
46 return 1;
47}
48
diff --git a/src/util/test_rsa.c b/src/util/test_rsa.c
new file mode 100644
index 000000000..ac3ae2cd4
--- /dev/null
+++ b/src/util/test_rsa.c
@@ -0,0 +1,112 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file util/test_rsa.c
19 * @brief testcase for utility functions for RSA cryptography
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */
22#include "platform.h"
23#include "taler_rsa.h"
24#include <gnunet/gnunet_util_lib.h>
25
26#define TEST_PURPOSE UINT32_MAX
27
28
29#define EXITIF(cond) \
30 do { \
31 if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
32 } while (0)
33
34int
35main (int argc, char *argv[])
36{
37#define RND_BLK_SIZE 4096
38 unsigned char rnd_blk[RND_BLK_SIZE];
39 struct TALER_RSA_PrivateKey *priv;
40 struct TALER_RSA_PrivateKeyBinaryEncoded *priv_enc;
41 struct TALER_RSA_PublicKeyBinaryEncoded pubkey;
42 struct TALER_RSA_BlindingKey *bkey;
43 struct TALER_RSA_BlindedSignaturePurpose *bsp;
44 struct TALER_RSA_Signature sig;
45 struct GNUNET_HashCode hash;
46 int ret;
47
48 priv = NULL;
49 bsp = NULL;
50 bkey = NULL;
51 ret = 1;
52 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, rnd_blk,
53 RND_BLK_SIZE);
54 GNUNET_CRYPTO_hash (rnd_blk, RND_BLK_SIZE, &hash);
55 priv = TALER_RSA_key_create ();
56 GNUNET_assert (NULL != priv);
57 EXITIF (GNUNET_OK != TALER_RSA_sign (priv,
58 &hash, sizeof (hash),
59 &sig));
60 TALER_RSA_key_get_public (priv, &pubkey);
61 EXITIF (NULL == (priv_enc = TALER_RSA_encode_key (priv)));
62 TALER_RSA_key_free (priv);
63 priv = NULL;
64 EXITIF (NULL == (priv = TALER_RSA_decode_key ((const char *) priv_enc,
65 ntohs (priv_enc->len))));
66 GNUNET_free (priv_enc);
67 priv_enc = NULL;
68 EXITIF (GNUNET_OK != TALER_RSA_hash_verify (&hash,
69 &sig,
70 &pubkey));
71 EXITIF (GNUNET_OK != TALER_RSA_verify (rnd_blk,
72 RND_BLK_SIZE,
73 &sig,
74 &pubkey));
75
76 /* test blind signing */
77 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, rnd_blk,
78 RND_BLK_SIZE);
79 GNUNET_CRYPTO_hash (rnd_blk, RND_BLK_SIZE, &hash);
80 (void) memset (&sig, 0, sizeof (struct TALER_RSA_Signature));
81 EXITIF (NULL == (bkey = TALER_RSA_blinding_key_create ()));
82 EXITIF (NULL == (bsp =
83 TALER_RSA_message_blind (&hash, sizeof (hash),
84 bkey, &pubkey)));
85 EXITIF (GNUNET_OK != TALER_RSA_sign (priv,
86 bsp,
87 sizeof (struct TALER_RSA_BlindedSignaturePurpose),
88 &sig));
89 EXITIF (GNUNET_OK != TALER_RSA_unblind (&sig,
90 bkey,
91 &pubkey));
92 EXITIF (GNUNET_OK != TALER_RSA_hash_verify (&hash,
93 &sig,
94 &pubkey));
95 ret = 0; /* all OK */
96
97 EXITIF_exit:
98 if (NULL != priv)
99 {
100 TALER_RSA_key_free (priv);
101 priv = NULL;
102 }
103 if (NULL != priv_enc)
104 {
105 GNUNET_free (priv_enc);
106 priv_enc = NULL;
107 }
108 if (NULL != bkey)
109 TALER_RSA_blinding_key_destroy (bkey);
110 GNUNET_free_non_null (bsp);
111 return ret;
112}
diff --git a/src/util/util.c b/src/util/util.c
new file mode 100644
index 000000000..3677bcbde
--- /dev/null
+++ b/src/util/util.c
@@ -0,0 +1,528 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
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/>
15*/
16
17/**
18 * @file util.c
19 * @brief Common utility functions
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 * @author Florian Dold
22 * @author Benedikt Mueller
23 */
24
25#include "platform.h"
26#include "taler_util.h"
27#include <gnunet/gnunet_common.h>
28#include <gnunet/gnunet_util_lib.h>
29#include <gcrypt.h>
30
31#define CURVE "Ed25519"
32
33#define AMOUNT_FRAC_BASE 1000000
34#define AMOUNT_FRAC_LEN 6
35
36
37
38static void
39fatal_error_handler (void *cls, int wtf, const char *msg)
40{
41 LOG_ERROR("Fatal error in Gcrypt: %s\n", msg);
42 abort();
43}
44
45
46/**
47 * Initialize Gcrypt library.
48 */
49void
50TALER_gcrypt_init()
51{
52 gcry_set_fatalerror_handler (&fatal_error_handler, NULL);
53 TALER_assert_as(gcry_check_version(NEED_LIBGCRYPT_VERSION),
54 "libgcrypt version mismatch");
55 /* Disable secure memory. */
56 gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
57 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
58}
59
60
61/**
62 * Generate a ECC private key.
63 *
64 * @return the s-expression representing the generated ECC private key; NULL
65 * upon error
66 */
67gcry_sexp_t
68TALER_genkey ()
69{
70 gcry_sexp_t priv_sexp;
71 gcry_sexp_t s_keyparam;
72 int rc;
73
74 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
75 "(genkey(ecc(curve \"" CURVE "\")"
76 "(flags eddsa)))")))
77 {
78 LOG_GCRY_ERROR ("gcry_sexp_build", rc);
79 return NULL;
80 }
81 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
82 {
83 LOG_GCRY_ERROR ("gcry_pk_genkey", rc);
84 gcry_sexp_release (s_keyparam);
85 return NULL;
86 }
87 gcry_sexp_release (s_keyparam);
88 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
89 {
90 LOG_GCRY_ERROR("gcry_pk_testkey", rc);
91 gcry_sexp_release (priv_sexp);
92 return NULL;
93 }
94 return priv_sexp;
95}
96
97
98/**
99 * Parse money amount description, in the format "A:B.C".
100 *
101 * @param str amount description
102 * @param denom amount to write the result to
103 * @return GNUNET_OK if the string is a valid amount specification,
104 * GNUNET_SYSERR if it is invalid.
105 */
106int
107TALER_string_to_amount (const char *str, struct TALER_Amount *denom)
108{
109 unsigned int i; // pos in str
110 int n; // number tmp
111 unsigned int c; // currency pos
112 uint32_t b; // base for suffix
113
114 memset (denom, 0, sizeof (struct TALER_Amount));
115
116 i = n = c = 0;
117
118 while (isspace(str[i]))
119 i++;
120
121 if (0 == str[i])
122 {
123 printf("null before currency\n");
124 return GNUNET_SYSERR;
125 }
126
127 while (str[i] != ':')
128 {
129 if (0 == str[i])
130 {
131 printf("null before colon");
132 return GNUNET_SYSERR;
133 }
134 if (c > 3)
135 {
136 printf("currency too long\n");
137 return GNUNET_SYSERR;
138 }
139 denom->currency[c] = str[i];
140 c++;
141 i++;
142 }
143
144 // skip colon
145 i++;
146
147 if (0 == str[i])
148 {
149 printf("null before value\n");
150 return GNUNET_SYSERR;
151 }
152
153 while (str[i] != '.')
154 {
155 if (0 == str[i])
156 {
157 return GNUNET_OK;
158 }
159 n = str[i] - '0';
160 if (n < 0 || n > 9)
161 {
162 printf("invalid character '%c' before comma at %u\n", (char) n, i);
163 return GNUNET_SYSERR;
164 }
165 denom->value = (denom->value * 10) + n;
166 i++;
167 }
168
169 // skip the dot
170 i++;
171
172 if (0 == str[i])
173 {
174 printf("null after dot");
175 return GNUNET_SYSERR;
176 }
177
178 b = 100000;
179
180 while (0 != str[i])
181 {
182 n = str[i] - '0';
183 if (b == 0 || n < 0 || n > 9)
184 {
185 printf("error after comma");
186 return GNUNET_SYSERR;
187 }
188 denom->fraction += n * b;
189 b /= 10;
190 i++;
191 }
192
193 return GNUNET_OK;
194}
195
196
197/**
198 * FIXME
199 */
200struct TALER_AmountNBO
201TALER_amount_hton (struct TALER_Amount d)
202{
203 struct TALER_AmountNBO dn;
204 dn.value = htonl (d.value);
205 dn.fraction = htonl (d.fraction);
206 memcpy (dn.currency, d.currency, TALER_CURRENCY_LEN);
207
208 return dn;
209}
210
211
212/**
213 * FIXME
214 */
215struct TALER_Amount
216TALER_amount_ntoh (struct TALER_AmountNBO dn)
217{
218 struct TALER_Amount d;
219 d.value = ntohl (dn.value);
220 d.fraction = ntohl (dn.fraction);
221 memcpy (d.currency, dn.currency, sizeof(dn.currency));
222
223 return d;
224}
225
226
227/**
228 * Compare the value/fraction of two amounts. Does not compare the currency,
229 * i.e. comparing amounts with the same value and fraction but different
230 * currency would return 0.
231 *
232 * @param a1 first amount
233 * @param a2 second amount
234 * @return result of the comparison
235 */
236int
237TALER_amount_cmp (struct TALER_Amount a1, struct TALER_Amount a2)
238{
239 a1 = TALER_amount_normalize (a1);
240 a2 = TALER_amount_normalize (a2);
241 if (a1.value == a2.value)
242 {
243 if (a1.fraction < a2.fraction)
244 return -1;
245 if (a1.fraction > a2.fraction)
246 return 1;
247 return 0;
248 }
249 if (a1.value < a2.value)
250 return -1;
251 return 1;
252}
253
254
255/**
256 * Perform saturating subtraction of amounts.
257 *
258 * @param a1 amount to subtract from
259 * @param a2 amount to subtract
260 * @return (a1-a2) or 0 if a2>=a1
261 */
262struct TALER_Amount
263TALER_amount_subtract (struct TALER_Amount a1, struct TALER_Amount a2)
264{
265 a1 = TALER_amount_normalize (a1);
266 a2 = TALER_amount_normalize (a2);
267
268 if (a1.value < a2.value)
269 {
270 a1.value = 0;
271 a1.fraction = 0;
272 return a1;
273 }
274
275 if (a1.fraction < a2.fraction)
276 {
277 if (0 == a1.value)
278 {
279 a1.fraction = 0;
280 return a1;
281 }
282