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