taler-developer-manual.rst (73954B)
1 .. 2 This file is part of GNU TALER. 3 4 Copyright (C) 2014-2025 Taler Systems SA 5 6 TALER is free software; you can redistribute it and/or modify it under the 7 terms of the GNU Affero General Public License as published by the Free Software 8 Foundation; either version 2.1, or (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 13 14 You should have received a copy of the GNU Affero General Public License along with 15 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 16 17 @author Christian Grothoff 18 19 General Developer Manual 20 ######################## 21 22 .. note:: 23 24 This manual contains information for developers working on GNU Taler 25 and related components. It is not intended for a general audience. 26 27 28 Project Overview 29 ================ 30 31 GNU Taler consists of a large (and growing) number of components 32 in various Git repositories. The following list gives a first 33 overview: 34 35 * exchange: core payment processing logic with a REST API, plus various 36 helper processes for interaction with banks and cryptographic 37 computations. Also includes the logic for the auditor and an 38 in-memory "bank" API implementation for testing. 39 40 * libeufin: implementation of the "bank" API using the EBICS protocol 41 used by banks in the EU. Allows an exchange to interact with 42 European banks. 43 44 * taler-magnet-bank: implementation of the "bank" API using the Magnet Bank 45 API.Allows an exchange to interact with Magnet Bank. 46 47 * taler-cyclos: implementation of the "bank" API using the Cyclos API. Allows an exchange to interact with a Cyclos network. 48 49 * depolymerization: implementation of the "bank" API on top of 50 blockchains, specifically Bitcoin and Ethereum. Allows an exchange 51 to interact with crypto-currencies. 52 53 * merchant: payment processing backend to be run by merchants, 54 offering a REST API. 55 56 * wallet-core: platform-independent implementation of a wallet to be run by 57 normal users. Includes also the WebExtension for various browsers. 58 Furthermore, includes various single-page apps used by other 59 components (especially as libeufin and merchant). Also includes 60 command-line wallet and tools for testing. 61 62 * taler-android: Android Apps including the Android wallet, the 63 Android point-of-sale App and the Android casher app. 64 65 * taler-ios: iOS wallet App. 66 67 * sync: backup service, provides a simple REST API to allow users to 68 make encrypted backups of their wallet state. 69 70 * anastasis: key escrow service, provides a simple REST API to allow 71 users to distribute encryption keys across multiple providers and 72 define authorization policies for key recovery. 73 74 * taler-mdb: integration of Taler with the multi-drop-bus (MDB) API 75 used by vending machines. Allows Taler payments to be integrated 76 with vending machines. 77 78 * gnu-taler-payment-for-woocommerce: payment plugin for the 79 woocommerce (wordpress) E-commerce solution. 80 81 * twister: man-in-the-middle proxy for tests that require fuzzing a 82 REST/JSON protocol. Used for some of our testing. 83 84 * challenger: implementation of an OAuth 2.0 provider that can be used 85 to verify that a user can receive SMS or E-mail at particular addresses. 86 Used as part of KYC processes of the exchange. 87 88 * taler-mailbox: messaging service used to store and forward payment 89 messages to Taler wallets. 90 91 * taldir: directory service used to lookup Taler wallet addresses for 92 sending invoices or payments to other wallets. 93 94 * taler-merchant-demos: various demonstration services operated at 95 'demo.taler.net', including a simple shop and a donation page. 96 97 There are other important repositories without code, including: 98 99 * gana: Hosted on git.gnunet.org, this repository defines various 100 constants used in the GNU Taler project. 101 102 * docs: documentation, including this very document. 103 104 * marketing: various presentations, papers and other resources for 105 outreach. 106 107 * large-media: very large data objects, such as videos. 108 109 * www: the taler.net website. 110 111 Fundamentals 112 ============ 113 114 Versioning 115 ---------- 116 117 A central rule is to never break anything for any dependency. To accomplish 118 this, we use versioning, of the APIs, database schema and the protocol. The 119 database versioning approach is described in the :ref:`Database schema 120 versioning <DatabaseVersioning>` section. Here, we will focus on API and 121 protocol versioning. 122 123 The key issue we need to solve with protocols and APIs (and that does not 124 apply to database versioning) is being able to introduce and remove features 125 without requiring a flag day where all components must update at the same 126 time. For this, we use GNU libtool style versioning with MAJOR:REVISION:AGE 127 and *not* semantic versioning (SEMVER). With GNU libtool style versioning, 128 first the REVISION should be increased on every change to the respective code. 129 Then, each time a feature is introduced or deprecated, the MAJOR and AGE 130 numbers are increased. Whenever an API is actually removed the AGE number is 131 reduced to match the distance since the removed API was deprecated. Thus, if 132 some client implements version X of the protocol (including not using any APIs 133 that have been deprecated), it is compatible for any implementation where 134 MAJOR is larger or equal to X, and MAJOR minus AGE is smaller or equal to X. 135 REVISION is not used for expected compatibility issues and merely serves to 136 uniquely identify each version (in combination with MAJOR). 137 138 To evolve any implementation, it is thus critical to first of all never 139 just break an existing API or endpoint. The only acceptable modifications 140 are to return additional information (being aware of binary compatibility!) 141 or to accept additional optional arguments (again, in a way that does not 142 break existing users). Thus, the most common way to introduce changes will 143 be the addition of new endpoints. Breaking existing endpoints is only ever 144 at best acceptable while in the process of introducing it and if you are 145 absolutely sure that there are zero users in other components. 146 147 When removing endpoints (or fields being returned), you must first deprecate 148 the existing API (incrementing MAJOR and AGE) and then wait for all clients, 149 including all clients in operation (e.g. Android and iOS Apps, e-commerce 150 integrations, etc.) to upgrade to a protocol implementation above the 151 deprecated MAJOR revision. Only then you should remove the endpoint and reduce 152 AGE. 153 154 To document these changes, please try to use ``@since`` annotations in the API 155 specifications to explain the MAJOR revision when a feature became available, 156 but most importantly use ``@deprecated X`` annotations to indicate that an API 157 was deprecated and will be removed once MAJOR minus AGE is above X. When using 158 an API, use the ``/config`` endpoints to check for compatibility and show a 159 warning if the version(s) you support and the version(s) offered by the server 160 are incompatible. 161 162 163 Tagging and Package Versioning 164 ------------------------------ 165 166 Release tags are of the form ``v${major}.${minor}.${patch}``. Release tags *should* be 167 annotated git tags. 168 169 We usually consider Debian packaging files (in ``debian/``) to be part of a release. 170 When only the Debian packaging files need to be changed, there are two options: 171 172 * Make a new patch release (``v${major}.${minor}.${patch+1}``) 173 * Make a Debian release: 174 175 * Debian version now includes a revision: ``${major}.${minor}.${patch}-${debrevision}`` 176 * The tag is Debian-specific: ``debian-${major}.${minor}.${patch}-${debrevision}`` 177 178 All source repos *should* include a ``contrib/bump`` script that automates bumping the\ 179 version in all relevant source and packaging files. 180 In the future, we might add an option to the script to only release a packaging bump. 181 Right now, that process is manual. 182 183 We support tagged and published pre-release versions via tags of the form ``v${major}.${minor}.${patch}-dev.${n}``. 184 The corresponding Debian version must be ``${major}.${minor}.${patch}~dev${n}``. 185 186 Nightly Debian packages should follow the `Debian conventions <https://wiki.debian.org/Versioning>`__ of ``{upcoming_version}~git{date}.{hash}-{revision}``. 187 188 Testing Tools 189 ------------- 190 191 For full ``make check`` support, install these programs: 192 193 - `jq <https://github.com/stedolan/jq>`__ 194 - `curl <http://curl.haxx.se>`__ 195 - `faketime <https://github.com/wolfcw/libfaketime>`__ 196 197 The ``make check`` should be able to function without them, but 198 their presence permits some tests to run that would otherwise be skipped. 199 200 Manual Testing Database Reset 201 ----------------------------- 202 203 Sometimes ``make check`` will fail with some kind of database (SQL) 204 error, perhaps with a message like ``OBJECT does not exist`` in the 205 ``test-suite.log`` file, where ``OBJECT`` is the name of a table or function. 206 In that case, it may be necessary to reset the ``talercheck`` database 207 with the commands: 208 209 .. code-block:: console 210 211 $ dropdb talercheck 212 $ createdb talercheck 213 214 This is because, at the moment, there is no support for 215 doing these steps automatically in the ``make check`` flow. 216 217 (If ``make check`` still fails after the reset, file a bug report as usual.) 218 219 Bug Tracking 220 ------------ 221 222 Bug tracking is done with Mantis (https://www.mantisbt.org/). The bug tracker 223 is available at `<https://bugs.taler.net>`_. A registration on the Web site is 224 needed in order to use the bug tracker, only read access is granted without a 225 login. 226 227 We use the following conventions for the bug states: 228 229 * NEW: Incoming bugs are in 'new' so that management (or developers) 230 can easily identify those that need to be checked (report correct? 231 something we want to fix?), prioritized and targeted for releases. 232 "NEW" bugs are never assigned to a developer. 233 234 * FEEDBACK: When blocked on feedback from reporter or other developer. 235 Assigned to other developer (but cannot be assigned to reporter, 236 in this case MAY remain associated with the developer who expects 237 the feedback). 238 239 * ACKNOWLEDGED: The bug has been reviewed, but no decision about 240 what action to take has been made yet. Should not be worked on 241 until management (or a developer) comes up with a plan. 242 "ACKNOWLEDGED" bugs should NOT be assigned to a developer. 243 244 * CONFIRMED: This is a real issue that should be worked on, but 245 is not yet actively worked on. If working on this bug requires 246 other bugs to be fixed first, they should be added as 247 child-bugs (via relationships). Developers are always welcome 248 to self-assign bugs that are "CONFIRMED" if they start to work 249 on a bug. "CONFIRMED" bugs should NOT be assigned to a developer. 250 251 * ASSIGNED: The specific developer the bug is assigned to is 252 **actively** working on the issue. Developers should strive to 253 not have more than 5-10 bugs assigned to them at any time. 254 Only having one assigned to you is totally OK! 255 Developers should aggressively un-assign bugs that they are 256 blocked on, cannot make progress on, or are no longer actively 257 working on (but of course, better *resolve* them before 258 moving on if possible). If the bug remains open, it probably 259 should go back to "CONFIRMED" or "ACKNOWLEDGED". 260 261 * RESOLVED: The bug has been fixed in Git. 262 263 * CLOSED: An official release was made with the fix in it. 264 265 When developers want to keep an eye on certain bugs, they should 266 **monitor** them. Multiple developers can be monitoring a bug, but 267 it can only be assigned to one. Developers should also keep an 268 eye on the roadmap (by release), bug categories they care about, 269 and of course priorities / severities. 270 271 We use **tags** to categorize bugs. Common tags that also imply 272 some urgency include (in alphabetical order): 273 274 * accounting: issues required for accounting (such as taxes by merchants) 275 * compliance: issues related to regulatory compliance 276 * $CUSTOMER: issues requested by a particular customer 277 * performance: performance problems or ideas for improvement 278 * security: security issues (including planned improvements to security) 279 * UX: user experience issues 280 281 These tags **should** be attached to "NEW" bugs if they apply. 282 283 284 Code Repositories 285 ----------------- 286 287 Taler code is versioned with Git. For those users without write access, all the 288 codebases are found at the following URL: 289 290 .. code-block:: none 291 292 git://git.taler.net/<repository> 293 294 A complete list of all the existing repositories is currently found at 295 `<https://git.taler.net/>`_. 296 297 298 Committing code 299 --------------- 300 301 Before you can obtain Git write access, you must sign the copyright 302 agreement. As we collaborate closely with GNUnet, we use their 303 copyright agreement -- with the understanding that your contributions 304 to GNU Taler are included in the assignment. You can find the 305 agreement on the `GNUnet site <https://gnunet.org/en/copyright.html>`_. 306 Please sign and mail it to Christian Grothoff as he currently collects 307 all the documents for GNUnet e.V. 308 309 To obtain Git access, you need to send us your SSH public key. Most core 310 team members have administrative Git access, so simply contact whoever 311 is your primary point of contact so far. You can 312 find instructions on how to generate an SSH key 313 in the `Git book <https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key>`_. 314 If you have been granted write access, you first of all must change the URL of 315 the respective repository to: 316 317 .. code-block:: none 318 319 ssh://git@git.taler.net/<repository> 320 321 For an existing checkout, this can be done by editing the ``.git/config`` file. 322 323 The server is configured to reject all commits that have not been signed with 324 GnuPG. If you do not yet have a GnuPG key, you must create one, as explained 325 in the `GNU Privacy Handbook <https://www.gnupg.org/gph/en/manual/c14.html>`_. 326 You do not need to share the respective public key with us to make commits. 327 However, we recommend that you upload it to key servers, put it on your 328 business card and personally meet with other GNU hackers to have it signed 329 such that others can verify your commits later. 330 331 To sign all commits, you should run 332 333 .. code-block:: console 334 335 $ git config --global commit.gpgsign true 336 337 You can also sign individual commits only by adding the ``-S`` option to the 338 ``git commit`` command. If you accidentally already made commits but forgot 339 to sign them, you can retroactively add signatures using: 340 341 .. code-block:: console 342 343 $ git rebase -S 344 345 346 Whether you commit to a personal branch (recommended: ``dev/$USER/...``), 347 a feature branch or to ``master`` should 348 depend on your level of comfort and the nature of the change. As a general 349 rule, the code in ``master`` must always build and tests should always pass, at 350 least on your own system. However, we all make mistakes and you should expect 351 to receive friendly reminders if your change did not live up to this simple 352 standard. We plan to move to a system where the CI guarantees this invariant 353 in the future. 354 355 In order to keep a linear and clean commits history, we advise to avoid 356 merge commits and instead always rebase your changes before pushing to 357 the ``master`` branch. If you commit and later find out that new commits were 358 pushed, the following command will pull the new commits and rebase yours 359 on top of them. 360 361 .. code-block:: console 362 363 # -S instructs Git to (re)sign your commits 364 $ git pull --rebase -S 365 366 367 368 Observing changes 369 ----------------- 370 371 Every commit to the ``master`` branch of any of our public repositories 372 (and almost all are public) is automatically sent to the 373 gnunet-svn@gnu.org mailinglist. That list is for Git commits only, 374 and must not be used for discussions. It also carries commits from 375 our main dependencies, namely GNUnet and GNU libmicrohttpd. While 376 it can be high volume, the lists is a good way to follow overall 377 development. 378 379 380 Code generator usage policy 381 --------------------------- 382 383 We do neither encourage nor discourage the use of tools for code generation. 384 It is up to the individual developer to decide if a tool is acceptable for 385 a particular task. But of course, we do encourage you to use FLOSS tools 386 and we MUST NOT become dependend on non-free software! That said, if you 387 use tools, you must document their use and in particular satisfy the 388 `NLnet policy on the use of "AI" <https://nlnet.nl/news/2025/20250829-policy-on-use-of-AI.html>`__. 389 390 Specifically, we ask developers to always put generated code into a *separate* 391 Git commit and to include the full prompt in the commit message. Naturally, 392 you may clean up the code generator's output, but then you should do so in 393 separate Git commits (and of course only merge into master/stable after the 394 clean up is complete). But do preserve (not squash!) the commit with the 395 generated code so that it remains documented what the prompts were and which 396 code is generated. This will go a long way to keep code auditors sane! 397 398 399 Communication 400 ------------- 401 402 For public discussions we use the taler@gnu.org mailinglist. All developers 403 should subscribe to the low-volume Taler mailinglist. There are separate 404 low-volume mailinglists for gnunet-developers (@gnu.org) and for libmicrohttpd 405 (@gnu.org). For internal discussions we use https://mattermost.taler.net/ 406 (invitation only, but also achieved). 407 408 409 What to put in bootstrap 410 ------------------------ 411 412 Each repository has a ``bootstrap`` script, which contains commands for the 413 developer to run after a repository checkout (i.e., after ``git clone`` or 414 ``git pull``). 415 Typically, this updates and initializes submodules, prepares the tool chain, 416 and runs ``autoreconf``. 417 The last step generates the ``configure`` script, whether for immediate use or 418 for inclusion in the distribution tarball. 419 420 One common submodule is ``contrib/gana``, which pulls from the 421 `GNUnet GANA repository <https://git.gnunet.org/gana.git/>`__. 422 For example, in the 423 `Taler exchange repository <https://git.taler.net/exchange.git>`__, 424 the bootstrap script eventually runs the ``git submodule update --init`` command 425 early on, and later runs script ``./contrib/gana-generate.sh``, which 426 generates files such as ``src/include/taler_signatures.h``. 427 428 Thus, to update that file, you need to: 429 430 - (in GANA repo) Find a suitable (unused) name and number for the Signature 431 Purposes database. 432 433 - Add it to GANA, in ``gnunet-signatures/registry.rec``. 434 (You can check for uniqueness with the ``recfix`` utility.) 435 436 - Commit the change, and push it to the GANA Git repo. 437 438 - (in Taler Repo) Run the ``contrib/gana-latest.sh`` script. 439 440 - Bootstrap, configure, do ``make install``, ``make check``, etc. 441 (Basically, make sure the change does not break anything.) 442 443 - Commit the submodule change, and push it to the Taler exchange Git repo. 444 445 A similar procedure is required for other databases in GANA. 446 See file ``README`` in the various directories for specific instructions. 447 448 449 Debian and Ubuntu Repositories 450 ============================== 451 452 We package our software for Debian and Ubuntu. 453 454 Nightly Repositories 455 -------------------- 456 457 To try the latest, unstable and untested versions of packages, 458 you can add the nightly package sources. 459 460 .. code-block:: shell-session 461 462 # For Debian (trixie) 463 $ curl -sS https://deb.taler.net/apt-nightly/taler-trixie-ci.sources \ 464 | tee /etc/apt/sources.list.d/taler-trixie-nightly.sources 465 466 467 Taler Deployment on gv.taler.net 468 ================================ 469 470 This section describes the GNU Taler deployment on ``gv.taler.net``. ``gv`` 471 is our server at BFH. It hosts the Git repositories, Web sites, CI and other 472 services. Developers can receive an SSH account and e-mail alias for the 473 system, you should contact Javier, Christian or Florian. As with Git, ask 474 your primary team contact for shell access if you think you need it. 475 476 477 DNS 478 --- 479 480 DNS records for taler.net are controlled by the GNU Taler maintainers, 481 specifically Christian and Florian, and our system administrator, Javier. If 482 you need a sub-domain to be added, please contact one of them. 483 484 485 User Acccounts 486 -------------- 487 488 On ``gv.taler.net``, there are three system users that are set up to 489 serve Taler on the Internet: 490 491 - ``head``: serves ``*.head.taler.net`` and gets automatically 492 built by Buildbot every 2 hours from the ``sandcastle-ng.git``. 493 Master key may be reset occasionally 494 495 - ``taler-test``: serves ``*.test.taler.net`` and does *NOT* get 496 automatically built, and runs more recent tags and/or unreleased 497 versions of Taler components. Master key may be reset 498 occasionally. 499 500 - ``demo``: serves ``*.demo.taler.net``. Never automatically built. 501 Master key is retained. 502 503 Demo Upgrade Procedure 504 ====================== 505 506 #. Login as the ``demo`` user on ``gv.taler.net``. 507 #. Pull the latest ``sandcastle-ng.git`` code in checkout at ``$HOME/sandcastle-ng``. 508 #. Run ``systemctl --user restart container-taler-sandcastle-demo.service`` 509 #. Refer to the sandcastle-ng README (https://git.taler.net/sandcastle-ng.git/about/) 510 for more info. 511 512 513 Upgrading the ``demo`` environment should be done with care, and ideally be 514 coordinated on the mailing list before. It is our goal for ``demo`` to always 515 run a "working version" that is compatible with various published wallets. 516 Please use the :doc:`demo upgrade checklist <../checklists/checklist-demo-upgrade>` to make 517 sure everything is working. 518 Nginx is already configured to reach the services as exported by the user unit. 519 520 521 Tagging components 522 ------------------ 523 524 All Taler components must be tagged with git before they are deployed on the 525 ``demo`` environment, using a tag of the following form: 526 527 .. code-block:: none 528 529 demo-YYYY-MM-DD-SS 530 YYYY = year 531 MM = month 532 DD = day 533 SS = serial 534 535 Environments and Builders on taler.net 536 ====================================== 537 538 Buildbot implementation 539 ----------------------- 540 541 GNU Taler uses a buildbot implementation (front end at https://buildbot.taler.net) to manage continuous integration. Buildbot documentation is at https://docs.buildbot.net/. 542 543 Here are some highlights: 544 545 - The WORKER is the config that that lives on a shell account on a localhost (taler.net), where this host has buildbot-worker installed. The WORKER executes the commands that perform all end-functions of buildbot. 546 547 - The WORKER running buildbot-worker receives these commands by authenticating and communicating with the buildbot server using parameters that were specified when the worker was created in that shell account with the ``buildbot-worker`` command. 548 549 - The buildbot server's master.cfg file contains FACTORY declarations which specify the commands that the WORKER will run on localhost. 550 551 - The FACTORY is tied to the WORKER in master.cfg by a BUILDER. 552 553 - The master.cfg also allows for SCHEDULER that defines how and when the BUILDER is executed. 554 555 - Our master.cfg file is checked into git, and then periodically updated on a particular account on taler.net (ask Christian for access if needed). Do not edit this file directly/locally on taler.net, but check changes into Git. 556 557 558 Best Practices: 559 560 - When creating a new WORKER in the ``master.cfg`` file, leave a comment specifying the server and user account that this WORKER is called from. (At this time, taler.net is the only server used by this implementation, but it's still good practice.) 561 562 - Create a worker from a shell account with this command: ``buildbot-worker create-worker <workername> localhost <username> <password>`` 563 564 Then make sure there is a WORKER defined in master.cfg like: ``worker.Worker("<username>", "<password>")`` 565 566 Test builder 567 ------------ 568 569 This builder (``test-builder``) compiles and starts every Taler component. 570 The associated worker is run by the ``taler-test`` Gv user, via the SystemD 571 unit ``buildbot-worker-taler``. The following commands start/stop/restart 572 the worker: 573 574 .. code-block:: 575 576 systemctl --user start buildbot-worker-taler 577 systemctl --user stop buildbot-worker-taler 578 systemctl --user restart buildbot-worker-taler 579 580 .. note:: 581 the mentioned unit file can be found at ``deployment.git/systemd-services/`` 582 583 Wallet builder 584 -------------- 585 586 This builder (``wallet-builder``) compiles every Taler component 587 and runs the wallet integration tests. The associated worker is 588 run by the ``walletbuilder`` Gv user, via the SystemD unit ``buildbot-worker-wallet``. 589 The following commands start/stop/restart the worker: 590 591 .. code-block:: 592 593 systemctl --user start buildbot-worker-wallet 594 systemctl --user stop buildbot-worker-wallet 595 systemctl --user restart buildbot-worker-wallet 596 597 .. note:: 598 the mentioned unit file can be found at ``deployment.git/systemd-services/`` 599 600 Documentation Builder 601 --------------------- 602 603 All the Taler documentation is built by the user ``docbuilder`` that 604 runs a Buildbot worker. The following commands set the ``docbuilder`` up, 605 starting with an empty home directory. 606 607 .. code-block:: console 608 609 # Log-in as the 'docbuilder' user. 610 611 $ cd $HOME 612 $ git clone git://git.taler.net/deployment 613 $ ./deployment/bootstrap-docbuilder 614 615 # If the previous step worked, the setup is 616 # complete and the Buildbot worker can be started. 617 618 $ buildbot-worker start worker/ 619 620 621 Website Builder 622 --------------- 623 624 625 Taler Websites, ``www.taler.net`` and ``stage.taler.net``, are built by the 626 user ``taler-websites`` by the means of a Buildbot worker. The following 627 commands set the ``taler-websites`` up, starting with an empty home directory. 628 629 .. code-block:: console 630 631 # Log-in as the 'taler-websites' user. 632 633 $ cd $HOME 634 $ git clone git://git.taler.net/deployment 635 $ ./deployment/bootstrap-sitesbuilder 636 637 # If the previous step worked, the setup is 638 # complete and the Buildbot worker can be started. 639 640 $ buildbot-worker start worker/ 641 642 643 Code coverage 644 ------------- 645 646 Code coverage tests are run by the ``lcovworker`` user, and are also driven 647 by Buildbot. 648 649 .. code-block:: console 650 651 # Log-in as the 'lcovworker' user. 652 653 $ cd $HOME 654 $ git clone git://git.taler.net/deployment 655 $ ./deployment/bootstrap-taler lcov 656 657 # If the previous step worked, the setup is 658 # complete and the Buildbot worker can be started. 659 660 $ buildbot-worker start worker/ 661 662 The results are then published at ``https://lcov.taler.net/``. 663 664 Producing auditor reports 665 ------------------------- 666 667 Both 'test' and 'demo' setups get their auditor reports compiled 668 by a Buildbot worker. The following steps get the reports compiler 669 prepared. 670 671 .. code-block:: console 672 673 # Log-in as <env>-auditor, with <env> being either 'test' or 'demo' 674 675 $ git clone git://git.taler.net/deployment 676 $ ./deployment/buildbot/bootstrap-scripts/prepare-auditorreporter <env> 677 678 # If the previous steps worked, then it should suffice to start 679 # the worker, with: 680 681 $ buildbot-worker start worker/ 682 683 684 .. _DatabaseVersioning: 685 686 Database schema versioning 687 -------------------------- 688 689 The PostgreSQL databases of the exchange and the auditor are versioned. 690 See the ``versioning.sql`` file in the respective directory for documentation. 691 692 Every set of changes to the database schema must be stored in a new 693 versioned SQL script. The scripts must have contiguous numbers. After 694 any release (or version being deployed to a production or staging 695 environment), existing scripts MUST be immutable. 696 697 Developers and operators MUST NOT make changes to database schema 698 outside of this versioning. All tables of a GNU Taler component should live in their own schema. 699 700 701 QA Plans 702 ======== 703 704 .. include:: ../checklists/qa-1.0.rst 705 706 707 Releases 708 ======== 709 710 .. include:: ../checklists/checklist-release.rst 711 712 Release Process 713 --------------- 714 715 This document describes the process for releasing a new version of the 716 various Taler components to the official GNU mirrors. 717 718 The following components are published on the GNU mirrors 719 720 - taler-exchange (exchange.git) 721 - taler-merchant (merchant.git) 722 - sync (sync.git) 723 - taler-mdb (taler-mdb.git) 724 - libeufin (libeufin.git) 725 - challenger (challenger.git) 726 - wallet-core (wallet-core.git) 727 728 Tagging 729 ------- 730 731 Tag releases with an **annotated** commit, like 732 733 .. code-block:: console 734 735 $ git tag -a v0.1.0 -m "Official release v0.1.0" 736 $ git push origin v0.1.0 737 738 739 Database for tests 740 ------------------ 741 742 For tests in the exchange and merchant to run, make sure that a database 743 *talercheck* is accessible by *$USER*. Otherwise tests involving the 744 database logic are skipped. 745 746 .. include:: ../frags/db-stores-sensitive-data.rst 747 748 Exchange, merchant 749 ------------------ 750 751 Set the version in ``configure.ac``. The commit being tagged should be 752 the change of the version. 753 754 Tag the current GANA version that works with the exchange and merchant and 755 checkout that tag of gana.git (instead of master). Otherwise, if there are 756 incompatible changes in GANA (like removed symbols), old builds could break. 757 758 Update the Texinfo documentation using the files from docs.git: 759 760 .. code-block:: console 761 762 # Get the latest documentation repository 763 $ cd $GIT/docs 764 $ git pull 765 $ make texinfo 766 # The *.texi files are now in _build/texinfo 767 # 768 # This checks out the prebuilt branch in the prebuilt directory 769 $ git worktree add prebuilt prebuilt 770 $ cd prebuilt 771 # Copy the pre-built documentation into the prebuilt directory 772 $ cp -r ../_build/texinfo . 773 # Push and commit to branch 774 $ git commit -a -S -m "updating texinfo" 775 $ git status 776 # Verify that all files that should be tracked are tracked, 777 # new files will have to be added to the Makefile.am in 778 # exchange.git as well! 779 $ git push 780 # Remember $REVISION of commit 781 # 782 # Go to exchange 783 $ cd $GIT/exchange/doc/prebuilt 784 # Update submodule to point to latest commit 785 $ git checkout $REVISION 786 787 Finally, the Automake ``Makefile.am`` files may have to be adjusted to 788 include new ``*.texi`` files or images. 789 790 For bootstrap, you will need to install 791 `GNU Recutils <https://www.gnu.org/software/recutils/>`_. 792 793 For the exchange test cases to pass, ``make install`` must be run first. 794 Without it, test cases will fail because plugins can't be located. 795 796 .. code-block:: console 797 798 $ ./bootstrap 799 $ ./configure # add required options for your system 800 $ make dist 801 $ tar -xf taler-$COMPONENT-$VERSION.tar.gz 802 $ cd taler-$COMPONENT-$VERSION 803 $ make install check 804 805 Wallet WebExtension 806 ------------------- 807 808 The version of the wallet is in *manifest.json*. The ``version_name`` 809 should be adjusted, and *version* should be increased independently on 810 every upload to the WebStore. 811 812 .. code-block:: console 813 814 $ ./configure 815 $ make dist 816 817 Upload to GNU mirrors 818 --------------------- 819 820 See https://www.gnu.org/prep/maintain/maintain.html#Automated-FTP-Uploads 821 822 Directive file: 823 824 .. code-block:: none 825 826 version: 1.2 827 directory: taler 828 filename: taler-exchange-0.1.0.tar.gz 829 symlink: taler-exchange-0.1.0.tar.gz taler-exchange-latest.tar.gz 830 831 Upload the files in **binary mode** to the ftp servers. 832 833 834 Creating Debian packages 835 ------------------------ 836 837 Our general setup is based on 838 https://wiki.debian.org/DebianRepository/SetupWithReprepro 839 840 First, update at least the version of the Debian package in 841 debian/changelog, and then run: 842 843 .. code-block:: bash 844 845 $ dpkg-buildpackage -rfakeroot -b -uc -us 846 847 in the respective source directory (GNUnet, exchange, merchant) to create the 848 ``.deb`` files. Note that they will be created in the parent directory. This 849 can be done on gv.taler.net, or on another (secure) machine. 850 Actual release builds should be done via the Docker images 851 that can be found in ``deployment.git`` under packaging. 852 853 On ``gv``, we use the ``aptbuilder`` user to manage the reprepro repository. 854 855 Next, the ``*.deb`` files should be copied to gv.taler.net, say to 856 ``/home/aptbuilder/incoming``. Then, run 857 858 .. code-block:: bash 859 860 # cd /home/aptbuilder/apt 861 # reprepro includedeb bullseye ~/incoming/*.deb 862 863 to import all Debian files from ``~/incoming/`` into the ``bullseye`` 864 distribution. If Debian packages were build against other distributions, 865 reprepro may need to be first configured for those and the import command 866 updated accordingly. 867 868 Finally, make sure to clean up ``~/incoming/`` (by deleting the 869 now imported ``*.deb`` files). 870 871 872 873 Continuous integration 874 ====================== 875 876 CI is done with Buildbot (https://buildbot.net/), and builds are 877 triggered by the means of Git hooks. The results are published at 878 https://buildbot.taler.net/ . 879 880 In order to avoid downtimes, CI uses a "blue/green" deployment 881 technique. In detail, there are two users building code on the system, 882 the "green" and the "blue" user; and at any given time, one is running 883 Taler services and the other one is either building the code or waiting 884 for that. 885 886 There is also the possibility to trigger builds manually, but this is 887 only reserved to "admin" users. 888 889 890 Internationalisation 891 ==================== 892 893 Internationalisation (a.k.a "translation") is handled with Weblate (https://weblate.org) via our instance at https://weblate.taler.net/ organised as so-called *strings* in a bunch of Git repositories. 894 895 Who can register 896 ---------------- 897 898 At this time, anyone can register an account at https://weblate.taler.net/ to create translations. Registered users default to the **Users** and **Viewers** privilege levels. 899 900 About privilege levels 901 ---------------------- 902 903 This is the breakdown of privilege levels in Weblate: 904 905 * **Viewers** = Have access to translations and can view them but are not entitled to translate 906 907 * **Users** = Can log in and perform translations (*applies to new users*) 908 909 * **Reviewers** = Can contribute translations to existing *components* and review translations 910 911 * **Managers** = Can create new *components* of existing *projects* 912 913 * **Superusers** = Can create new *projects*, moreover they manage Weblate's settings and repository maintenance, can edit all user accounts, deactivate users, trigger commits from Weblate's local repositories with pushes to Git and perform backups of language files 914 915 How to contribute with your translation 916 --------------------------------------- 917 918 1 - Log into https://weblate.taler.net 919 920 2 - Navigate to *Projects* and *Browse all projects* 921 922 3 - Choose the *project* you wish to contribute to 923 924 4 - Choose the *component* you wish to contribute to 925 926 5 - Find the language you want to translate into 927 928 6 - Find a phrase and translate it 929 930 7 - While translating, take into consideration at each string to translate 931 932 * the comments 933 934 * the context 935 936 * the string location in the source code 937 938 * the "nearby strings" in Weblate as one of the sorting options on the translation form 939 940 * "other languages" as another sorting option to compare strings in a way translatologists would do 941 942 * if applicable, the history of string changes and the message ID or key of a string 943 944 8 - **Always test your translations in the actual apps** after they have been pushed by the platform to the apps 945 946 9 - Be aware of ambiguities and immediately **report inconsistencies or bugs** by using Mantis bug tickets 947 948 10 - If you want to contribute your translation in a language which does not yet exist in a Taler component, navigate to the *component* you want to translate for and click "Start new translation" to begin. In case you require a privilege upgrade, please contact a *Superuser* with your request. Currently, *Superusers* are Christian, Florian, Martin, and Stefan. 949 950 Translation standards and practices 951 ----------------------------------- 952 953 1 - *Developers*, Weblate *reviewers* and *managers* MUST look into **design documents** for the specific component or software project, like e.g. for the Taler wallets DD53 https://docs.taler.net/design-documents/053-wallet-ui.html and stick close to the documentation, especially the **text to use** and **text to avoid** 954 955 2 - To every ambiguous string *developers* MUST add **context** or **comments** to the strings on Weblate 956 957 3 - *Developers*, Weblate *reviewers* and *managers* SHOULD add **screenshots** where needed to the strings on Weblate 958 959 4 - Weblate *managers* MUST take care of **checks** in the translations overview and keep the repositories consistent and up-to-date, t.i. to perform regularly **synchronisation** between Git and Weblate repositories and vice-versa 960 961 5 - *Weblate admins* MUST set the **commit and push rules** to *manual* only, and when asked, set the license to *GPLv3 or later* 962 963 6 - You MAY also wish to refer to https://docs.weblate.org/ and to the ``README files`` in components like web pages to find out more specific variables if prompted 964 965 How to create a project 966 ----------------------- 967 968 The *GNU Taler* project is probably the correct project for most Weblate components and Taler-related translations. Please contact a *Superuser* if you need another project created. 969 970 How to create a component 971 ------------------------- 972 973 Reference: https://docs.weblate.org/en/weblate-5.13.2/admin/projects.html#component-configuration 974 975 In Weblate, a *component* is a subset of a *project* and each component contains N translations. A component is generally associated with a Git repository. 976 977 To create a component, log into https://weblate.taler.net/ with your credentials for a *Manager* privilege level (or higher) and choose **+ Add** from the upper-right corner. 978 979 What follows is a sort of Wizard. You can find detailed docs at https://docs.weblate.org/. Here are some important notes about connecting your component to the Taler Git repository: 980 981 On the component level, choose *Operations* from the menu bar, select *Settings*, then add at the tab *Basic* these settings: 982 983 * **Component name** - The distinctive name of the software project, e.g. ``Main web site`` 984 985 * **Translation license** - Choose *GNU Affero General Public License v3.0 or Later* 986 987 * **Contributor license agreement** - left empty as the *Translation license* defaults 988 989 * **Source string bug reporting address** - This requires an email address of the Weblate admin or *Superuser* in charge or just ``languages@taler.net`` 990 991 * **Priority** - Generally ``Medium`` 992 993 * **Restricted component** - ``deactivated`` 994 995 * **Share in projects** - ``deactivated`` 996 997 * **Use as a glossary** - ``deactivated`` 998 999 At the tab *Translation* settings are generally: 1000 1001 * **Turn on suggestions** - ``activated`` 1002 1003 * **Allow translation propagation** - ``activated`` 1004 1005 * **Contribute to project translation memory** - ``activated`` 1006 1007 * **Secondary language** - Leave empty (respectively ``--------`` ) 1008 1009 At the tab *Version control* ( *https://weblate.taler.net/create/component/vcs/* ) settings require variables as follows: 1010 1011 * **Version Control System** - Generally ``Git`` 1012 1013 * **Source code repository** - Generally ``git+ssh://git@git.taler.net/<repositoryname>.git``, check with ``git remote -v`` 1014 1015 * **Repository branch** - Choose the correct branch to draw from and commit to which is generally ``master`` 1016 1017 * **Repository push URL** - Generally ``git+ssh://git@git.taler.net/<repositoryname>.git``, check with ``git remote -v`` 1018 1019 * **Push branch** - Choose the correct branch to push to, this is generally ``master`` 1020 1021 * **Repository browser** - Normally, this field is left empty. If you are required to have this field pointing to the www URL of the Git repo's file browser, it could be filled with ``https://git.taler.net/<repositoryname>.git/tree/{{filename}}?h={{branch}}#n{{line}}`` where ``<repositoryname>`` gets replaced but ``{{filename}}`` and other items in braces are actual variables in the string 1022 1023 * **Push on commit** - ``deactivated`` 1024 1025 * **Age of changes to commit** - 24 (hours after which any pending changes will be committed to the VCS) 1026 1027 * **Merge style** - Generally ``Rebase``, in line with GNU Taler development procedures 1028 1029 * **Lock on error** - ``activated`` 1030 1031 At the tab *Commit messages* you can leave the defaults: 1032 1033 * **Commit message when translating** has the most important message: 1034 1035 Translated using Weblate ({{ language_name }}) 1036 Currently translated at {{ stats.translated_percent }}% ({{ stats.translated }} of {{ stats.all }} strings) 1037 Translation: {{ project_name }}/{{ component_name }} 1038 Translate-URL: {{ url }} 1039 1040 At the tab *Files* 1041 1042 * **File format** - Mostly ``gettext PO file`` for web pages, ``Android String Resource`` for Android app strings, ``XLIFF 1.2 translation file`` for iOS apps, or ``TermBase eXchange file`` for some of the glossaries 1043 1044 * **Language filter** - Dependent on the respective folder structure of the project, for structures used with gettext PO files mostly ``locale/*/LC_MESSAGES/messages.po`` 1045 1046 * **Language filter** - Generally ``^[^.]+$`` 1047 1048 * **Source language** - ``English`` 1049 1050 * **Monolingual translations / Monolingual base language file** - Leave empty 1051 1052 * **Edit base file** - ``deactivated`` 1053 1054 * **Intermediate language file** - Leave empty 1055 1056 * **Template for new translations** - Dependent on the respective folder structure of the project, for structures used with gettext PO files ``locale/messages.pot`` 1057 1058 * **Adding new translation** - Generally ``Create new language file`` 1059 1060 * **Language code style** - Generally ``Default based on the file format`` 1061 1062 * **Screenshot file mask** - Leave empty (unless we do not dispose of a dedicated screenshot folder with a path relative to repository root) 1063 1064 GPG signing of translations 1065 --------------------------- 1066 1067 Weblate signs its GPG commits with the GPG key CD33CE35801462FA5EB0B695F2664BF474BFE502, and the corresponding public key can be found at https://weblate.taler.net/keys/. 1068 1069 This means that contributions made through Weblate will not be signed with the individual contributor's key when they are checked into the Git repository but with Weblate's public key. 1070 1071 1072 1073 iOS Apps 1074 ======== 1075 1076 .. _Build-iOS-from-source: 1077 1078 Building Taler Wallet for iOS from source 1079 ----------------------------------------- 1080 1081 The GNU Taler Wallet iOS app is in 1082 `the official Git repository <https://git.taler.net/taler-ios.git>`__. 1083 1084 Compatibility 1085 ^^^^^^^^^^^^^ 1086 1087 The minimum version of iOS supported is 15.0. 1088 This app runs on all iPhone models at least as new as the iPhone 6S. 1089 1090 1091 Building 1092 ^^^^^^^^ 1093 1094 Before building the iOS wallet, you must first checkout the 1095 `quickjs-tart repo <https://git.taler.net/quickjs-tart.git>`__ 1096 and the 1097 `wallet-core repo <https://git.taler.net/wallet-core.git>`__. 1098 1099 Have all 3 local repos (wallet-core, quickjs-tart, and this one) adjacent at 1100 the same level (e.g. in a "GNU_Taler" folder) 1101 Taler.xcworkspace expects the QuickJS framework sub-project to be at 1102 ``../quickjs-tart/QuickJS-rt.xcodeproj``. 1103 1104 Build wallet-core first: 1105 1106 .. code-block:: shell-session 1107 1108 $ cd wallet-core 1109 $ make embedded 1110 $ open packages/taler-wallet-embedded/dist 1111 1112 then drag or move its product "taler-wallet-core-qjs.mjs" 1113 into your quickjs-tart folder right at the top level. 1114 1115 Open Taler.xcworkspace, and set scheme / target to Taler_Wallet. Build&run... 1116 1117 Don't open QuickJS-rt.xcodeproj or TalerWallet.xcodeproj and build anything 1118 there - all needed libraries and frameworks will be built automatically from 1119 Taler.xcworkspace. 1120 1121 1122 Android Apps 1123 ============ 1124 1125 Android App Nightly Builds 1126 -------------------------- 1127 1128 There are currently three Android apps in 1129 `the official Git repository <https://git.taler.net/taler-android.git>`__: 1130 1131 * Wallet 1132 [`CI <https://git.taler.net/taler-android.git/tree/wallet/.gitlab-ci.yml>`__] 1133 * Merchant PoS Terminal 1134 [`CI <https://git.taler.net/taler-android.git/tree/merchant-terminal/.gitlab-ci.yml>`__] 1135 * Cashier 1136 [`CI <https://git.taler.net/taler-android.git/tree/cashier/.gitlab-ci.yml>`__] 1137 1138 Their git repositories are `mirrored at Gitlab <https://gitlab.com/gnu-taler/taler-android>`__ 1139 to utilize their CI 1140 and `F-Droid <https://f-droid.org>`_'s Gitlab integration 1141 to `publish automatic nightly builds <https://f-droid.org/docs/Publishing_Nightly_Builds/>`_ 1142 for each change on the ``master`` branch. 1143 1144 All three apps publish their builds to the same F-Droid nightly repository 1145 (which is stored as a git repository): 1146 https://gitlab.com/gnu-taler/fdroid-repo-nightly 1147 1148 You can download the APK files directly from that repository 1149 or add it to the F-Droid app for automatic updates 1150 by clicking the following link (on the phone that has F-Droid installed). 1151 1152 `GNU Taler Nightly F-Droid Repository <fdroidrepos://gnu-taler.gitlab.io/fdroid-repo-nightly/fdroid/repo?fingerprint=55F8A24F97FAB7B0960016AF393B7E57E7A0B13C2D2D36BAC50E1205923A7843>`_ 1153 1154 .. note:: 1155 Nightly apps can be installed alongside official releases 1156 and thus are meant **only for testing purposes**. 1157 Use at your own risk! 1158 1159 .. _Build-apps-from-source: 1160 1161 Building apps from source 1162 ------------------------- 1163 1164 Note that this guide is different from other guides for building Android apps, 1165 because it does not require you to run non-free software. 1166 It uses the Merchant PoS Terminal as an example, but works as well for the other apps 1167 if you replace ``merchant-terminal`` with ``wallet`` or ``cashier``. 1168 1169 First, ensure that you have the required dependencies installed: 1170 1171 * Java Development Kit 8 or higher (default-jdk-headless) 1172 * git 1173 * unzip 1174 1175 Then you can get the app's source code using git: 1176 1177 .. code-block:: console 1178 1179 # Start by cloning the Android git repository 1180 $ git clone https://git.taler.net/taler-android.git 1181 1182 # Change into the directory of the cloned repository 1183 $ cd taler-android 1184 1185 # Find out which Android SDK version you will need 1186 $ grep -i compileSdkVersion merchant-terminal/build.gradle 1187 1188 The last command will return something like ``compileSdkVersion 29``. 1189 So visit the `Android Rebuilds <http://android-rebuilds.beuc.net/>`_ project 1190 and look for that version of the Android SDK there. 1191 If the SDK version is not yet available as a free rebuild, 1192 you can try to lower the ``compileSdkVersion`` in the app's ``merchant-terminal/build.gradle`` file. 1193 Note that this might break things 1194 or require you to also lower other versions such as ``targetSdkVersion``. 1195 1196 In our example, the version is ``29`` which is available, 1197 so download the "SDK Platform" package of "Android 10.0.0 (API 29)" 1198 and unpack it: 1199 1200 .. code-block:: console 1201 1202 # Change into the directory that contains your downloaded SDK 1203 $ cd $HOME 1204 1205 # Unpack/extract the Android SDK 1206 $ unzip android-sdk_eng.10.0.0_r14_linux-x86.zip 1207 1208 # Tell the build system where to find the SDK 1209 $ export ANDROID_SDK_ROOT="$HOME/android-sdk_eng.10.0.0_r14_linux-x86" 1210 1211 # Change into the directory of the cloned repository 1212 $ cd taler-android 1213 1214 # Build the merchant-terminal app 1215 $ ./gradlew :merchant-terminal:assembleRelease 1216 1217 If you get an error message complaining about build-tools 1218 1219 > Failed to install the following Android SDK packages as some licences have not been accepted. 1220 build-tools;29.0.3 Android SDK Build-Tools 29.0.3 1221 1222 you can try changing the ``buildToolsVersion`` in the app's ``merchant-terminal/build.gradle`` file 1223 to the latest "Android SDK build tools" version supported by the Android Rebuilds project. 1224 1225 After the build finished successfully, 1226 you will find your APK in ``merchant-terminal/build/outputs/apk/release/``. 1227 1228 Update translations 1229 ------------------- 1230 1231 Translations are managed with Taler's weblate instance: 1232 https://weblate.taler.net/projects/gnu-taler/ 1233 1234 To update translations, enter the taler-android git repository 1235 and ensure that the weblate remote exists: 1236 1237 .. code-block:: console 1238 1239 $ git config -l | grep weblate 1240 1241 If it does not yet exist (empty output), you can add it like this: 1242 1243 .. code-block:: console 1244 1245 $ git remote add weblate https://weblate.taler.net/git/gnu-taler/wallet-android/ 1246 1247 Then you can merge in translations commit from the weblate remote: 1248 1249 .. code-block:: console 1250 1251 # ensure you have latest version 1252 $ git fetch weblate 1253 1254 # merge in translation commits 1255 $ git merge weblate/master 1256 1257 Afterwards, build the entire project from source and test the UI 1258 to ensure that no erroneous translations (missing placeholders) are breaking things. 1259 1260 Release process 1261 --------------- 1262 1263 After extensive testing, the code making up a new release should get a signed git tag. 1264 The current tag format is: 1265 1266 * cashier-$VERSION 1267 * pos-$VERSION 1268 * wallet-$VERSION (where $VERSION has a v prefix) 1269 1270 .. code-block:: console 1271 1272 $ git tag -s $APP-$VERSION 1273 1274 F-Droid 1275 ^^^^^^^ 1276 Nightly builds get published automatically (see above) after pushing code to the official repo. 1277 Actual releases get picked up by F-Droid's official repository via git tags. 1278 So ensure that all releases get tagged properly. 1279 1280 Some information for F-Droid official repository debugging: 1281 1282 * Wallet: [`metadata <https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/net.taler.wallet.fdroid.yml>`__] [`build log <https://f-droid.org/wiki/page/net.taler.wallet.fdroid/lastbuild>`__] 1283 * Cashier: [`metadata <https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/net.taler.cashier.yml>`__] [`build log <https://f-droid.org/wiki/page/net.taler.cashier/lastbuild>`__] 1284 * PoS: [`metadata <https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/net.taler.merchantpos.yml>`__] [`build log <https://f-droid.org/wiki/page/net.taler.merchantpos/lastbuild>`__] 1285 1286 Google Play 1287 ^^^^^^^^^^^ 1288 Google Play uploads are managed via `Fastlane <https://docs.fastlane.tools/getting-started/android/setup/>`__. 1289 Before proceeding, ensure that this is properly set up 1290 and that you have access to the Google Play API. 1291 1292 It is important to have access to the signing keys and Google Play access keys 1293 (JSON) and to ensure that the following environment variables are set 1294 correctly and made available to Fastlane: 1295 1296 .. code-block:: bash 1297 1298 TALER_KEYSTORE_PATH= 1299 TALER_KEYSTORE_PASS= 1300 TALER_KEYSTORE_WALLET_ALIAS= 1301 TALER_KEYSTORE_WALLET_PASS= 1302 TALER_KEYSTORE_POS_ALIAS= 1303 TALER_KEYSTORE_POS_PASS= 1304 TALER_KEYSTORE_CASHIER_ALIAS= 1305 TALER_KEYSTORE_CASHIER_PASS= 1306 TALER_JSON_KEY_FILE= 1307 1308 To release an app, enter into its respective folder and run fastlane: 1309 1310 .. code-block:: console 1311 1312 $ bundle exec fastlane 1313 1314 Then select the deploy option. 1315 1316 All uploads are going to the beta track by default. These can be promoted to 1317 production later or immediately after upload if you feel daring. It is also 1318 important to bump the version and build code with every release. 1319 1320 .. _Code-coverage: 1321 1322 Code Coverage 1323 ============= 1324 1325 Code coverage is done with the Gcov / Lcov 1326 (http://ltp.sourceforge.net/coverage/lcov.php) combo, and it is run 1327 nightly (once a day) by a Buildbot worker. The coverage results are 1328 then published at https://lcov.taler.net/ . 1329 1330 1331 Coding Conventions 1332 ================== 1333 1334 GNU Taler is developed primarily in C, Kotlin, Python, Swift and TypeScript. 1335 1336 Components written in C 1337 ----------------------- 1338 1339 These are the general coding style rules for Taler. 1340 1341 * Baseline rules are to follow GNU guidelines, modified or extended 1342 by the GNUnet style: https://docs.gnunet.org/handbook/gnunet.html#Coding-style 1343 1344 Naming conventions 1345 ^^^^^^^^^^^^^^^^^^ 1346 1347 * include files (very similar to GNUnet): 1348 1349 * if installed, must start with "``taler_``" (exception: platform.h), 1350 and MUST live in src/include/ 1351 * if NOT installed, must NOT start with "``taler_``" and 1352 MUST NOT live in src/include/ and 1353 SHOULD NOT be included from outside of their own directory 1354 * end in "_lib" for "simple" libraries 1355 * end in "_plugin" for plugins 1356 * end in "_service" for libraries accessing a service, i.e. the exchange 1357 1358 * binaries: 1359 1360 * taler-exchange-xxx: exchange programs 1361 * taler-merchant-xxx: merchant programs (demos) 1362 * taler-wallet-xxx: wallet programs 1363 * plugins should be libtaler_plugin_xxx_yyy.so: plugin yyy for API xxx 1364 * libtalerxxx: library for API xxx 1365 1366 * logging 1367 1368 * tools use their full name in GNUNET_log_setup 1369 (i.e. 'taler-exchange-offline') and log using plain 'GNUNET_log'. 1370 * pure libraries (without associated service) use 'GNUNET_log_from' 1371 with the component set to their library name (without lib or '.so'), 1372 which should also be their directory name (i.e. 'util') 1373 * plugin libraries (without associated service) use 'GNUNET_log_from' 1374 with the component set to their type and plugin name (without lib or '.so'), 1375 which should also be their directory name (i.e. 'exchangedb-postgres') 1376 * libraries with associated service) use 'GNUNET_log_from' 1377 with the name of the service, which should also be their 1378 directory name (i.e. 'exchange') 1379 * for tools with ``-l LOGFILE``, its absence means write logs to stderr 1380 1381 * configuration 1382 1383 * same rules as for GNUnet 1384 1385 * exported symbols 1386 1387 * must start with TALER_[SUBSYSTEMNAME]_ where SUBSYSTEMNAME 1388 MUST match the subdirectory of src/ in which the symbol is defined 1389 * from libtalerutil start just with ``TALER_``, without subsystemname 1390 * if scope is ONE binary and symbols are not in a shared library, 1391 use binary-specific prefix (such as TMH = taler-exchange-httpd) for 1392 globals, possibly followed by the subsystem (TMH_DB_xxx). 1393 1394 * structs: 1395 1396 * structs that are 'packed' and do not contain pointers and are 1397 thus suitable for hashing or similar operations are distinguished 1398 by adding a "P" at the end of the name. (NEW) Note that this 1399 convention does not hold for the GNUnet-structs (yet). 1400 * structs that are used with a purpose for signatures, additionally 1401 get an "S" at the end of the name. 1402 1403 * private (library-internal) symbols (including structs and macros) 1404 1405 * must not start with ``TALER_`` or any other prefix 1406 1407 * testcases 1408 1409 * must be called "test_module-under-test_case-description.c" 1410 1411 * performance tests 1412 1413 * must be called "perf_module-under-test_case-description.c" 1414 1415 Shell Scripts 1416 ------------- 1417 1418 Shell scripts should be avoided if at all possible. The only permissible uses of shell scripts 1419 in GNU Taler are: 1420 1421 * Trivial invocation of other commands. 1422 * Scripts for compatibility (e.g. ``./configure``) that must run on 1423 as many systems as possible. 1424 1425 When shell scripts are used, they ``MUST`` begin with the following ``set`` command: 1426 1427 .. code-block:: console 1428 1429 # Make the shell fail on undefined variables and 1430 # commands with non-zero exit status. 1431 $ set -eu 1432 1433 Kotlin 1434 ------ 1435 1436 We so far have no specific guidelines, please follow best practices 1437 for the language. 1438 1439 1440 Python 1441 ------ 1442 1443 Supported Python Versions 1444 ^^^^^^^^^^^^^^^^^^^^^^^^^ 1445 1446 Python code should be written and build against version 3.7 of Python. 1447 1448 Style 1449 ^^^^^ 1450 1451 We use `yapf <https://github.com/google/yapf>`_ to reformat the 1452 code to conform to our style instructions. 1453 A reusable yapf style file can be found in ``build-common``, 1454 which is intended to be used as a git submodule. 1455 1456 Python for Scripting 1457 ^^^^^^^^^^^^^^^^^^^^ 1458 1459 When using Python for writing small utilities, the following libraries 1460 are useful: 1461 1462 * ``click`` for argument parsing (should be preferred over argparse) 1463 * ``pathlib`` for path manipulation (part of the standard library) 1464 * ``subprocess`` for "shelling out" to other programs. Prefer ``subprocess.run`` 1465 over the older APIs. 1466 1467 1468 Swift 1469 ----- 1470 1471 Please follow best practices for the language. 1472 1473 1474 TypeScript 1475 ---------- 1476 1477 Please follow best practices for the language. 1478 1479 1480 Testing library 1481 =============== 1482 1483 This chapter is a VERY ABSTRACT description of how testing is 1484 implemented in Taler, and in NO WAY wants to substitute the reading of 1485 the actual source code by the user. 1486 1487 In Taler, a test case is an array of ``struct TALER_TESTING_Command``, 1488 informally referred to as ``CMD``, that is iteratively executed by the 1489 testing interpreter. This latter is transparently initiated by the 1490 testing library. 1491 1492 However, the developer does not have to defined CMDs manually, but 1493 rather call the proper constructor provided by the library. For example, 1494 if a CMD is supposed to test feature ``x``, then the library would 1495 provide the ``TALER_TESTING_cmd_x ()`` constructor for it. Obviously, 1496 each constructor has its own particular arguments that make sense to 1497 test ``x``, and all constructor are thoroughly commented within the 1498 source code. 1499 1500 Internally, each CMD has two methods: ``run ()`` and ``cleanup ()``. The 1501 former contains the main logic to test feature ``x``, whereas the latter 1502 cleans the memory up after execution. 1503 1504 In a test life, each CMD needs some internal state, made by values it 1505 keeps in memory. Often, the test has to *share* those values with other 1506 CMDs: for example, CMD1 may create some key material and CMD2 needs this 1507 key material to encrypt data. 1508 1509 The offering of internal values from CMD1 to CMD2 is made by *traits*. A 1510 trait is a ``struct TALER_TESTING_Trait``, and each CMD contains an array 1511 of traits, that it offers via the public trait interface to other 1512 commands. The definition and filling of such array happens transparently 1513 to the test developer. 1514 1515 For example, the following example shows how CMD2 takes an amount object 1516 offered by CMD1 via the trait interface. 1517 1518 Note: the main interpreter and the most part of CMDs and traits are 1519 hosted inside the exchange codebase, but nothing prevents the developer 1520 from implementing new CMDs and traits within other codebases. 1521 1522 .. code-block:: c 1523 1524 /* Without loss of generality, let's consider the 1525 * following logic to exist inside the run() method of CMD1 */ 1526 ... 1527 1528 struct TALER_Amount *a; 1529 /** 1530 * the second argument (0) points to the first amount object offered, 1531 * in case multiple are available. 1532 */ 1533 if (GNUNET_OK != TALER_TESTING_get_trait_amount_obj (cmd2, 0, &a)) 1534 return GNUNET_SYSERR; 1535 ... 1536 1537 use(a); /* 'a' points straight into the internal state of CMD2 */ 1538 1539 In the Taler realm, there is also the possibility to alter the behaviour 1540 of supposedly well-behaved components. This is needed when, for example, 1541 we want the exchange to return some corrupted signature in order to 1542 check if the merchant backend detects it. 1543 1544 This alteration is accomplished by another service called *twister*. The 1545 twister acts as a proxy between service A and B, and can be programmed 1546 to tamper with the data exchanged by A and B. 1547 1548 Please refer to the Twister codebase (under the ``test`` directory) in 1549 order to see how to configure it. 1550 1551 1552 User-Facing Terminology 1553 ======================= 1554 1555 This section contains terminology that should be used and that should not be 1556 used in the user interface and help materials. 1557 1558 Terms to Avoid 1559 -------------- 1560 1561 Refreshing 1562 Refreshing is the internal technical terminology for the protocol to 1563 give change for partially spent coins 1564 1565 **Use instead**: "Obtaining change" 1566 1567 Charge 1568 Charge has two opposite meanings (charge to a credit card vs. charge a battery). 1569 This can confuse users. 1570 1571 **Use instead**: "Obtain", "Credit", "Debit", "Withdraw", "Top up" 1572 1573 Coin 1574 Coins are an internal construct, the user should never be aware that their balance 1575 is represented by coins of different denominations. 1576 1577 **Use instead**: "(Digital) Cash" or "(Wallet) Balance" 1578 1579 Consumer 1580 Has bad connotation of consumption. 1581 1582 **Use instead**: Customer or user. 1583 1584 Proposal 1585 The term used to describe the process of the merchant facilitating the download 1586 of the signed contract terms for an order. 1587 1588 **Avoid**. Generally events that relate to proposal downloads 1589 should not be shown to normal users, only developers. Instead, use 1590 "communication with mechant failed" if a proposed order can't be downloaded. 1591 1592 Anonymous E-Cash 1593 Should be generally avoided, since Taler is only anonymous for 1594 the customer. Also some people are scared of anonymity (which as 1595 a term is also way too absolute, as anonymity is hardly ever perfect). 1596 1597 **Use instead**: "Privacy-preserving", "Privacy-friendly" 1598 1599 Payment Replay 1600 The process of proving to the merchant that the customer is entitled 1601 to view a digital product again, as they already paid for it. 1602 1603 **Use instead**: In the event history, "re-activated digital content purchase" 1604 could be used. (FIXME: this is still not nice.) 1605 1606 Session ID 1607 See Payment Replay. 1608 1609 Order 1610 Too ambiguous in the wallet. 1611 1612 **Use instead**: Purchase 1613 1614 Fulfillment URL 1615 URL that the serves the digital content that the user purchased 1616 with their payment. Can also be something like a donation receipt. 1617 1618 Donau 1619 Developer-internal name for the tax authority component. 1620 1621 **Use instead**: Tax authority 1622 1623 Terms to Use 1624 ------------ 1625 1626 Auditor 1627 Regulatory entity that certifies exchanges and oversees their operation. 1628 1629 Exchange Operator 1630 The entity/service that gives out digital cash in exchange for some 1631 other means of payment. 1632 1633 In some contexts, using "Issuer" could also be appropriate. 1634 When showing a balance breakdown, 1635 we can say "100 Eur (issued by exchange.euro.taler.net)". 1636 Sometimes we may also use the more generic term "Payment Service Provider" 1637 when the concept of an "Exchange" is still unclear to the reader. 1638 1639 Refund 1640 A refund is given by a merchant to the customer (rather the customer's wallet) 1641 and "undoes" a previous payment operation. 1642 1643 Payment 1644 The act of sending digital cash to a merchant to pay for an order. 1645 1646 Purchase 1647 Used to refer to the "result" of a payment, as in "view purchase". 1648 Use sparsingly, as the word doesn't fit for all payments, such as donations. 1649 1650 Contract Terms 1651 Partially machine-readable representation of the merchant's obligation after the 1652 customer makes a payment. 1653 1654 Merchant 1655 Party that receives a payment. 1656 1657 Wallet 1658 Also "Taler Wallet". Software component that manages the user's digital cash 1659 and payments. 1660 1661 1662 Developer Glossary 1663 ================== 1664 1665 This glossary is meant for developers. It contains some terms that we usually do not 1666 use when talking to end users or even system administrators. 1667 1668 .. glossary:: 1669 :sorted: 1670 1671 absolute time 1672 method of keeping time in :term:`GNUnet` where the time is represented 1673 as the number of microseconds since 1.1.1970 (UNIX epoch). Called 1674 absolute time in contrast to :term:`relative time`. 1675 1676 aggregate 1677 the :term:`exchange` combines multiple payments received by the 1678 same :term:`merchant` into one larger :term:`wire transfer` to 1679 the respective merchant's :term:`bank` account 1680 1681 auditor 1682 trusted third party that verifies that the :term:`exchange` is operating correctly 1683 1684 bank 1685 traditional financial service provider who offers 1686 :term:`wire transfers <wire transfer>` between accounts 1687 1688 buyer 1689 individual in control of a Taler :term:`wallet`, usually using it to 1690 :term:`spend` the :term:`coins <coin>` on :term:`contracts <contract>` (see also :term:`customer`). 1691 1692 close 1693 operation an :term:`exchange` performs on a :term:`reserve` that has not been 1694 :term:`emptied <empty>` by :term:`withdraw` operations. When closing a reserve, the 1695 exchange wires the remaining funds back to the customer, minus a :term:`fee` 1696 for closing 1697 1698 customer 1699 individual that directs the buyer (perhaps the same individual) to make a purchase 1700 1701 coin 1702 coins are individual token representing a certain amount of value, also known as the :term:`denomination` of the coin 1703 1704 refresh commitment 1705 data that the wallet commits to during the :term:`melt` stage of the 1706 :term:`refresh` protocol where it 1707 has to prove to the :term:`exchange` that it is deriving the :term:`fresh` 1708 coins as specified by the Taler protocol. The commitment is verified 1709 probabilistically (see: :term:`kappa`) during the :term:`reveal` stage. 1710 1711 contract 1712 formal agreement between :term:`merchant` and :term:`customer` specifying the 1713 :term:`contract terms` and signed by the merchant and the :term:`coins <coin>` of the 1714 customer 1715 1716 contract terms 1717 the individual clauses specifying what the buyer is purchasing from the 1718 :term:`merchant` 1719 1720 denomination 1721 unit of currency, specifies both the currency and the face value of a :term:`coin`, 1722 as well as associated fees and validity periods 1723 1724 denomination key 1725 (RSA) key used by the exchange to certify that a given :term:`coin` is valid and of a 1726 particular :term:`denomination` 1727 1728 deposit 1729 operation by which a merchant passes coins to an exchange, expecting the 1730 exchange to credit his bank account in the future using an 1731 :term:`aggregate` :term:`wire transfer` 1732 1733 drain 1734 process by which an exchange operator takes the profits 1735 (from :term:`fees <fee>`) out of the escrow account and moves them into 1736 their regular business account 1737 1738 dirty 1739 a :term:`coin` is dirty if its public key may be known to an entity other than 1740 the customer, thereby creating the danger of some entity being able to 1741 link multiple transactions of coin's owner if the coin is not refreshed 1742 1743 empty 1744 a :term:`reserve` is being emptied when a :term:`wallet` is using the 1745 reserve's private key to :term:`withdraw` coins from it. This reduces 1746 the balance of the reserve. Once the balance reaches zero, we say that 1747 the reserve has been (fully) emptied. Reserves that are not emptied 1748 (which is the normal process) are :term:`closed <close>` by the exchange. 1749 1750 exchange 1751 Taler's payment service operator. Issues electronic coins during 1752 withdrawal and redeems them when they are deposited by merchants 1753 1754 expired 1755 Various operations come with time limits. In particular, denomination keys 1756 come with strict time limits for the various operations involving the 1757 coin issued under the denomination. The most important limit is the 1758 deposit expiration, which specifies until when wallets are allowed to 1759 use the coin in deposit or refreshing operations. There is also a "legal" 1760 expiration, which specifies how long the exchange keeps records beyond the 1761 deposit expiration time. This latter expiration matters for legal disputes 1762 in courts and also creates an upper limit for refreshing operations on 1763 special zombie coin 1764 1765 GNUnet 1766 Codebase of various libraries for a better Internet, some of which 1767 GNU Taler depends upon. 1768 1769 fakebank 1770 implementation of the :term:`bank` API in memory to be used only for test 1771 cases. 1772 1773 fee 1774 an :term:`exchange` charges various fees for its service. The different 1775 fees are specified in the protocol. There are fees per coin for 1776 :term:`withdrawing <withdraw>`, :term:`depositing <deposit>`, :term:`melting <melt>`, and 1777 :term:`refunding <refund>`. Furthermore, there are fees per wire transfer 1778 when a :term:`reserve` is :term:`closed <close>` 1779 and for :term:`aggregate` :term:`wire transfers <wire transfer>` 1780 to the :term:`merchant`. 1781 1782 fresh 1783 a :term:`coin` is fresh if its public key is only known to the customer 1784 1785 JSON 1786 JavaScript Object Notation (JSON) is a 1787 serialization format derived from the JavaScript language which is 1788 commonly used in the Taler protocol as the payload of HTTP requests 1789 and responses. 1790 1791 kappa 1792 security parameter used in the :term:`refresh` protocol. Defined to be 3. 1793 The probability of successfully evading the income transparency with the 1794 refresh protocol is 1:kappa. 1795 1796 libeufin 1797 Kotlin component that implements a regional currency bank and an 1798 adapter to communicate via EBICS with European core banking systems. 1799 1800 link 1801 specific step in the :term:`refresh` protocol that an exchange must offer 1802 to prevent abuse of the :term:`refresh` mechanism. The link step is 1803 not needed in normal operation, it just must be offered. 1804 1805 master key 1806 offline key used by the exchange to certify denomination keys and 1807 message signing keys 1808 1809 melt 1810 step of the :term:`refresh` protocol where a :term:`dirty` :term:`coin` 1811 is invalidated to be reborn :term:`fresh` in a subsequent 1812 :term:`reveal` step. 1813 1814 merchant 1815 party receiving payments (usually in return for goods or services) 1816 1817 message signing key 1818 key used by the exchange to sign online messages, other than coins 1819 1820 order 1821 offer made by the merchant to a wallet; pre-cursor to 1822 a contract where the wallet is not yet fixed. Turns 1823 into a :term:`contract` when a wallet claims the order. 1824 1825 owner 1826 a coin is owned by the entity that knows the private key of the coin 1827 1828 relative time 1829 method of keeping time in :term:`GNUnet` where the time is represented 1830 as a relative number of microseconds. Thus, a relative time specifies 1831 an offset or a duration, but not a date. Called relative time in 1832 contrast to :term:`absolute time`. 1833 1834 recoup 1835 Operation by which an exchange returns the value of coins affected 1836 by a :term:`revocation <revoke>` to their :term:`owner`, either by allowing the owner to 1837 withdraw new coins or wiring funds back to the bank account of the :term:`owner`. 1838 1839 planchet 1840 precursor data for a :term:`coin`. A planchet includes the coin's internal 1841 secrets (coin private key, blinding factor), but lacks the RSA signature 1842 of the :term:`exchange`. When :term:`withdrawing <withdraw>`, a :term:`wallet` 1843 creates and persists a planchet before asking the exchange to sign it to 1844 get the coin. 1845 1846 purchase 1847 Refers to the overall process of negotiating a :term:`contract` and then 1848 making a payment with :term:`coins <coin>` to a :term:`merchant`. 1849 1850 privacy policy 1851 Statement of an operator how they will protect the privacy of users. 1852 1853 proof 1854 Message that cryptographically demonstrates that a particular claim is correct. 1855 1856 proposal 1857 a list of :term:`contract terms` that has been completed and signed by the 1858 merchant backend. 1859 1860 refresh 1861 operation by which a :term:`dirty` :term:`coin` is converted into one or more 1862 :term:`fresh` coins. Involves :term:`melting <melt>` the :term:`dirty` coins and 1863 then :term:`revealing <reveal>` so-called :term:`transfer keys <transfer key>`. 1864 1865 refund 1866 operation by which a merchant steps back from the right to funds that he 1867 obtained from a :term:`deposit` operation, giving the right to the funds back 1868 to the customer 1869 1870 refund transaction id 1871 unique number by which a merchant identifies a :term:`refund`. Needed 1872 as refunds can be partial and thus there could be multiple refunds for 1873 the same :term:`purchase`. 1874 1875 reserve 1876 accounting mechanism used by the exchange to track customer funds 1877 from incoming :term:`wire transfers <wire transfer>`. A reserve is created whenever 1878 a customer wires money to the exchange using a well-formed public key 1879 in the subject. The exchange then allows the customer's :term:`wallet` 1880 to :term:`withdraw` up to the amount received in :term:`fresh` 1881 :term:`coins <coin>` from the reserve, thereby emptying the reserve. If a 1882 reserve is not emptied, the exchange will eventually :term:`close` it. 1883 1884 Other definition: Funds set aside for future use; either the balance of a customer at the 1885 exchange ready for withdrawal, or the funds kept in the exchange;s bank 1886 account to cover obligations from coins in circulation. 1887 1888 reveal 1889 step in the :term:`refresh` protocol where some of the transfer private 1890 keys are revealed to prove honest behavior on the part of the wallet. 1891 In the reveal step, the exchange returns the signed :term:`fresh` coins. 1892 1893 revoke 1894 exceptional operation by which an exchange withdraws a denomination from 1895 circulation, either because the signing key was compromised or because 1896 the exchange is going out of operation; unspent coins of a revoked 1897 denomination are subjected to recoup. 1898 1899 sharing 1900 users can share ownership of a :term:`coin` by sharing access to the coin's 1901 private key, thereby allowing all co-owners to spend the coin at any 1902 time. 1903 1904 spend 1905 operation by which a customer gives a merchant the right to deposit 1906 coins in return for merchandise 1907 1908 transfer key 1909 special cryptographic key used in the :term:`refresh` protocol, some of which 1910 are revealed during the :term:`reveal` step. Note that transfer keys have, 1911 despite the name, no relationship to :term:`wire transfers <wire transfer>`. They merely 1912 help to transfer the value from a :term:`dirty` coin to a :term:`fresh` coin 1913 1914 terms 1915 the general terms of service of an operator, possibly including 1916 the :term:`privacy policy`. Not to be confused with the 1917 :term:`contract terms` which are about the specific purchase. 1918 1919 transaction 1920 method by which ownership is exclusively transferred from one entity 1921 1922 user 1923 any individual using the Taler payment system 1924 (see :term:`customer`, :term:`buyer`, :term:`merchant`). 1925 1926 version 1927 Taler uses various forms of versioning. There is a database 1928 schema version (stored itself in the database, see \*-0000.sql) describing 1929 the state of the table structure in the database of an :term:`exchange`, 1930 :term:`auditor` or :term:`merchant`. There is a protocol 1931 version (CURRENT:REVISION:AGE, see GNU libtool) which specifies 1932 the network protocol spoken by an :term:`exchange` or :term:`merchant` 1933 including backwards-compatibility. And finally there is the software 1934 release version (MAJOR.MINOR.PATCH, see https://semver.org/) of 1935 the respective code base. 1936 1937 wallet 1938 software running on a customer's computer; withdraws, stores and 1939 spends coins 1940 1941 WebExtension 1942 Cross-browser API used to implement the GNU Taler wallet browser extension. 1943 1944 wire gateway 1945 API used by the exchange to talk with some real-time gross settlement system 1946 (core banking system, blockchain) to notice inbound credits wire transfers 1947 (during withdraw) and to trigger outbound debit wire transfers (primarily 1948 for deposits). 1949 1950 wire transfer 1951 a wire transfer is a method of sending funds between :term:`bank` accounts 1952 1953 wire transfer identifier 1954 Subject of a wire transfer from the exchange to a merchant; 1955 set by the aggregator to a random nonce which uniquely 1956 identifies the transfer. 1957 1958 withdraw 1959 operation by which a :term:`wallet` can convert funds from a :term:`reserve` to 1960 fresh coins 1961 1962 zombie 1963 :term:`coin` where the respective :term:`denomination key` is past its 1964 :term:`deposit` :term:`expiration <expired>` time, but which is still (again) valid 1965 for an operation because it was :term:`melted <melt>` while it was still 1966 valid, and then later again credited during a :term:`recoup` process 1967 1968 1969 1970 Developer Tools 1971 =============== 1972 1973 This section describes various internal programs to make life easier for the 1974 developer. 1975 1976 1977 taler-harness 1978 ------------- 1979 1980 **taler-harness deployment gen-coin-config** is a tool to simplify Taler configuration generation. 1981 1982 1983 **taler-harness deployment gen-coin-config** 1984 [**-min-amount**=**\ \ *VALUE*] 1985 [**-max-amount**=**\ \ *VALUE*]