summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-04-26 17:07:25 +0200
committerChristian Grothoff <christian@grothoff.org>2021-04-26 17:07:25 +0200
commitc9d78ec0f5c5935616cb12206bd616a0966ab0af (patch)
tree59f86c35e376184855cbb0967cafd2dd9bea21ba
parent488608716fcd0fa90013f7136cb4bee4822f972d (diff)
downloaddocs-c9d78ec0f5c5935616cb12206bd616a0966ab0af.tar.gz
docs-c9d78ec0f5c5935616cb12206bd616a0966ab0af.tar.bz2
docs-c9d78ec0f5c5935616cb12206bd616a0966ab0af.zip
update prebuild docs
-rw-r--r--man/taler-auditor-dbinit.14
-rw-r--r--man/taler-auditor-exchange.14
-rw-r--r--man/taler-auditor-httpd.14
-rw-r--r--man/taler-auditor-offline.1131
-rw-r--r--man/taler-auditor.16
-rw-r--r--man/taler-exchange-aggregator.14
-rw-r--r--man/taler-exchange-benchmark.14
-rw-r--r--man/taler-exchange-closer.14
-rw-r--r--man/taler-exchange-dbinit.14
-rw-r--r--man/taler-exchange-httpd.14
-rw-r--r--man/taler-exchange-offline.156
-rw-r--r--man/taler-exchange-secmod-eddsa.14
-rw-r--r--man/taler-exchange-secmod-rsa.14
-rw-r--r--man/taler-exchange-transfer.14
-rw-r--r--man/taler-exchange-wirewatch.14
-rw-r--r--man/taler-helper-auditor-aggregation.14
-rw-r--r--man/taler-helper-auditor-coins.14
-rw-r--r--man/taler-helper-auditor-deposits.14
-rw-r--r--man/taler-helper-auditor-reserves.14
-rw-r--r--man/taler-helper-auditor-wire.16
-rw-r--r--man/taler-merchant-benchmark.110
-rw-r--r--man/taler-merchant-dbinit.14
-rw-r--r--man/taler-merchant-httpd.124
-rw-r--r--man/taler-merchant-setup-reserve.16
-rw-r--r--man/taler-wire-gateway-client.14
-rw-r--r--man/taler.conf.531
-rw-r--r--texinfo/anastasis-figures/anastasis-db.pngbin0 -> 38801 bytes
-rw-r--r--texinfo/anastasis-figures/anastasis_challenge_payment.pngbin0 -> 20331 bytes
-rw-r--r--texinfo/anastasis-figures/anastasis_challengecode.pngbin0 -> 17678 bytes
-rw-r--r--texinfo/anastasis-figures/anastasis_reducer_backup.pngbin0 -> 47081 bytes
-rw-r--r--texinfo/anastasis-figures/anastasis_reducer_recovery.pngbin0 -> 48943 bytes
-rw-r--r--texinfo/anastasis-figures/anastasis_truth.pngbin0 -> 19493 bytes
-rw-r--r--texinfo/anastasis-figures/anastasis_truth_payment.pngbin0 -> 13430 bytes
-rw-r--r--texinfo/anastasis.texi2792
-rw-r--r--texinfo/taler-auditor-figures/anastasis-db.pngbin0 -> 38801 bytes
-rw-r--r--texinfo/taler-auditor-figures/anastasis_challenge_payment.pngbin0 -> 20331 bytes
-rw-r--r--texinfo/taler-auditor-figures/anastasis_challengecode.pngbin0 -> 17678 bytes
-rw-r--r--texinfo/taler-auditor-figures/anastasis_reducer_backup.pngbin0 -> 47081 bytes
-rw-r--r--texinfo/taler-auditor-figures/anastasis_reducer_recovery.pngbin0 -> 48943 bytes
-rw-r--r--texinfo/taler-auditor-figures/anastasis_truth.pngbin0 -> 19493 bytes
-rw-r--r--texinfo/taler-auditor-figures/anastasis_truth_payment.pngbin0 -> 13430 bytes
-rw-r--r--texinfo/taler-auditor.texi140
-rw-r--r--texinfo/taler-bank-figures/anastasis-db.pngbin0 -> 38801 bytes
-rw-r--r--texinfo/taler-bank-figures/anastasis_challenge_payment.pngbin0 -> 20331 bytes
-rw-r--r--texinfo/taler-bank-figures/anastasis_challengecode.pngbin0 -> 17678 bytes
-rw-r--r--texinfo/taler-bank-figures/anastasis_reducer_backup.pngbin0 -> 47081 bytes
-rw-r--r--texinfo/taler-bank-figures/anastasis_reducer_recovery.pngbin0 -> 48943 bytes
-rw-r--r--texinfo/taler-bank-figures/anastasis_truth.pngbin0 -> 19493 bytes
-rw-r--r--texinfo/taler-bank-figures/anastasis_truth_payment.pngbin0 -> 13430 bytes
-rw-r--r--texinfo/taler-bank.texi6
-rw-r--r--texinfo/taler-developer-manual-figures/anastasis-db.pngbin0 -> 38801 bytes
-rw-r--r--texinfo/taler-developer-manual-figures/anastasis_challenge_payment.pngbin0 -> 20331 bytes
-rw-r--r--texinfo/taler-developer-manual-figures/anastasis_challengecode.pngbin0 -> 17678 bytes
-rw-r--r--texinfo/taler-developer-manual-figures/anastasis_reducer_backup.pngbin0 -> 47081 bytes
-rw-r--r--texinfo/taler-developer-manual-figures/anastasis_reducer_recovery.pngbin0 -> 48943 bytes
-rw-r--r--texinfo/taler-developer-manual-figures/anastasis_truth.pngbin0 -> 19493 bytes
-rw-r--r--texinfo/taler-developer-manual-figures/anastasis_truth_payment.pngbin0 -> 13430 bytes
-rw-r--r--texinfo/taler-developer-manual-figures/arch-api.pngbin0 -> 59189 bytes
-rw-r--r--texinfo/taler-developer-manual-figures/auditor-db.pngbin0 -> 397630 bytes
-rw-r--r--texinfo/taler-developer-manual-figures/exchange-db.pngbin0 -> 352589 bytes
-rw-r--r--texinfo/taler-developer-manual-figures/merchant-db.pngbin0 -> 459305 bytes
-rw-r--r--texinfo/taler-developer-manual-figures/replication.pngbin0 -> 46376 bytes
-rw-r--r--texinfo/taler-developer-manual.texi2731
-rw-r--r--texinfo/taler-exchange-figures/anastasis-db.pngbin0 -> 38801 bytes
-rw-r--r--texinfo/taler-exchange-figures/anastasis_challenge_payment.pngbin0 -> 20331 bytes
-rw-r--r--texinfo/taler-exchange-figures/anastasis_challengecode.pngbin0 -> 17678 bytes
-rw-r--r--texinfo/taler-exchange-figures/anastasis_reducer_backup.pngbin0 -> 47081 bytes
-rw-r--r--texinfo/taler-exchange-figures/anastasis_reducer_recovery.pngbin0 -> 48943 bytes
-rw-r--r--texinfo/taler-exchange-figures/anastasis_truth.pngbin0 -> 19493 bytes
-rw-r--r--texinfo/taler-exchange-figures/anastasis_truth_payment.pngbin0 -> 13430 bytes
-rw-r--r--texinfo/taler-exchange.texi55
-rw-r--r--texinfo/taler-merchant-api-tutorial-figures/anastasis-db.pngbin0 -> 38801 bytes
-rw-r--r--texinfo/taler-merchant-api-tutorial-figures/anastasis_challenge_payment.pngbin0 -> 20331 bytes
-rw-r--r--texinfo/taler-merchant-api-tutorial-figures/anastasis_challengecode.pngbin0 -> 17678 bytes
-rw-r--r--texinfo/taler-merchant-api-tutorial-figures/anastasis_reducer_backup.pngbin0 -> 47081 bytes
-rw-r--r--texinfo/taler-merchant-api-tutorial-figures/anastasis_reducer_recovery.pngbin0 -> 48943 bytes
-rw-r--r--texinfo/taler-merchant-api-tutorial-figures/anastasis_truth.pngbin0 -> 19493 bytes
-rw-r--r--texinfo/taler-merchant-api-tutorial-figures/anastasis_truth_payment.pngbin0 -> 13430 bytes
-rw-r--r--texinfo/taler-merchant-api-tutorial.texi75
-rw-r--r--texinfo/taler-merchant-figures/anastasis-db.pngbin0 -> 38801 bytes
-rw-r--r--texinfo/taler-merchant-figures/anastasis_challenge_payment.pngbin0 -> 20331 bytes
-rw-r--r--texinfo/taler-merchant-figures/anastasis_challengecode.pngbin0 -> 17678 bytes
-rw-r--r--texinfo/taler-merchant-figures/anastasis_reducer_backup.pngbin0 -> 47081 bytes
-rw-r--r--texinfo/taler-merchant-figures/anastasis_reducer_recovery.pngbin0 -> 48943 bytes
-rw-r--r--texinfo/taler-merchant-figures/anastasis_truth.pngbin0 -> 19493 bytes
-rw-r--r--texinfo/taler-merchant-figures/anastasis_truth_payment.pngbin0 -> 13430 bytes
-rw-r--r--texinfo/taler-merchant.texi175
87 files changed, 5880 insertions, 436 deletions
diff --git a/man/taler-auditor-dbinit.1 b/man/taler-auditor-dbinit.1
index 60401fe6..a442eaff 100644
--- a/man/taler-auditor-dbinit.1
+++ b/man/taler-auditor-dbinit.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-AUDITOR-DBINIT" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-AUDITOR-DBINIT" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-auditor-dbinit \- setup auditor database
.
@@ -88,6 +88,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-auditor-exchange.1 b/man/taler-auditor-exchange.1
index ecb49c4d..56baf361 100644
--- a/man/taler-auditor-exchange.1
+++ b/man/taler-auditor-exchange.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-AUDITOR-EXCHANGE" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-AUDITOR-EXCHANGE" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-auditor-exchange \- add or remove exchange from auditor’s list
.
@@ -92,6 +92,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-auditor-httpd.1 b/man/taler-auditor-httpd.1
index 84b9c36a..f97415fd 100644
--- a/man/taler-auditor-httpd.1
+++ b/man/taler-auditor-httpd.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-AUDITOR-HTTPD" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-AUDITOR-HTTPD" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-auditor-httpd \- HTTP server providing a RESTful API to access a Taler auditor
.
@@ -91,6 +91,6 @@ electronic mail to <\fI\%taler@gnu.org\fP>
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-auditor-offline.1 b/man/taler-auditor-offline.1
index cd06e750..59c473b9 100644
--- a/man/taler-auditor-offline.1
+++ b/man/taler-auditor-offline.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-AUDITOR-OFFLINE" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-AUDITOR-OFFLINE" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-auditor-offline \- Taler auditor certifies that it audits a Taler exchange
.
@@ -38,7 +38,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
[\fB\-L\fP\ \fILOGLEVEL\fP\ |\ \fB––loglevel=\fP‌\fILOGLEVEL\fP]
[\fB\-l\fP\ \fIFILENAME\fP\ |\ \fB––logfile=\fP‌\fIFILENAME\fP]
[\fB\-v\fP\ |\ \fB––version\fP]
-[subcommand …]
+[subcommand ...]
.SH DESCRIPTION
.sp
\fBtaler\-auditor\-offline\fP is a command\-line tool to be used by an auditor to
@@ -47,7 +47,7 @@ signature, the auditor affirms that he will verify that the exchange is
properly accounting for coins of those denominations. The tool takes a list
of subcommands as arguments which are then processed sequentially.
.sp
-The tool includes two subcommands to interact \fIonline\fP with the exchange’s
+The tool includes two subcommands to interact \fIonline\fP with the exchange\(aqs
REST APIs. The \fBdownload\fP subcommand downloads current public keys from the
running exchange. Note that this only includes keys that the exchange
operator has previously validated using the \fBtaler\-exchange\-offline\fP tool.
@@ -55,10 +55,10 @@ The resulting data serves as input to the \fBsign\fP and \fBshow\fP subcommands.
.sp
The \fBupload\fP subcommand uploads the signatures created with the private key to
the exchange. It handles the output of all subcommands (except \fBdownload\fP).
-The \fBdownload\fP and \fBupload\fP subcommands must naturally be run “online” and do not
-require access to the auditor’s private key, which should be kept offline.
+The \fBdownload\fP and \fBupload\fP subcommands must naturally be run "online" and do not
+require access to the auditor\(aqs private key, which should be kept offline.
.sp
-All other subcommands are intended to be run “offline”. However, especially
+All other subcommands are intended to be run "offline". However, especially
when testing, it is of course possible to run the subcommands online as well.
Generally, subcommands read inputs (beyond command\-line arguments)
from \fBstdin\fP\&. However, they may also consume outputs of previous
@@ -88,8 +88,8 @@ Print version information.
.SH CONFIGURATION
.sp
The exchange and the \fBtaler\-auditor\-httpd\fP must both be provided with
-the auditor’s public key, such that they can validate messages signed
-by the auditor. To obtain the auditor’s public key, use:
+the auditor\(aqs public key, such that they can validate messages signed
+by the auditor. To obtain the auditor\(aqs public key, use:
.INDENT 0.0
.INDENT 3.5
.sp
@@ -102,13 +102,13 @@ $ taler\-auditor\-offline setup
.UNINDENT
.sp
Note that if the private key file already exists, the above will simply output
-the existing key. Passing additional arguments after setup (including “\-“)
+the existing key. Passing additional arguments after setup (including "\-")
will cause the output to be encapsulated in JSON.
.sp
Relevant configuration options for \fBtaler\-auditor\-offline\fP are:
.INDENT 0.0
.IP \(bu 2
-\fB[auditor/AUDITOR_PRIV_FILE]\fP — where to store the private key
+\fB[auditor/AUDITOR_PRIV_FILE]\fP \-\-\- where to store the private key
.UNINDENT
.SH SUBCOMMANDS
.SS setup
@@ -143,115 +143,6 @@ directly.
.sp
It outputs the signatures over \fIall\fP denomination and signing keys
present in the input, in a format suitable for the \fBupload\fP subcommand.
-.SS revoke\-denomination
-.sp
-This subcommand signs a revocation message for a denomination key.
-.sp
-The hash of the denomination public key must be given in the usual
-base32\-encoding as the first and only argument to the subcommand.
-.sp
-It outputs the signature affirming the revocation of the denomination key,
-in a format suitable for the \fBupload\fP subcommand.
-.SS revoke\-signkey
-.sp
-This subcommand signs a revocation message for an exchange online signing key.
-.sp
-The online signing public key must be given in the usual
-base32\-encoding as the first and only argument to the subcommand.
-.sp
-It outputs the signature affirming the revocation of the online signing key,
-in a format suitable for the \fBupload\fP subcommand.
-.SS enable\-auditor
-.sp
-This subcommand
-informs an exchange that an auditor is to be activated. Afterwards, the
-exchange will accept inputs from that auditor’s \fBtaler\-auditor\-offline\fP
-tool. Note that the auditor also must add the exchange to the list of
-exchanges that it audits via \fBtaler\-auditor\-exchange\fP\&. Furthermore, the
-exchange’s database will need to be provided to the auditor. This subcommand
-only informs the exchange about the auditor, but does not perform those
-additional mandatory steps for a working auditor.
-.sp
-The auditor’s public key must be given in the usual base32\-encoding as the
-first argument.
-.sp
-The auditor’s REST API base URL must be given as the second argument. The tool
-performs a minimal sanity check, namely that the URL begins with “http”
-(this also allows “https”), but as it runs offline does not perform any further
-validation!
-.sp
-The third argument must be a human\-readable name for the auditor. This may
-be shown to users and should identify the auditor’s business entity. If
-the name includes spaces, the argument should be quoted.
-.sp
-The subcommand takes no inputs from \fBstdin\fP or other subcommands.
-.sp
-It outputs the signature affirming the addition of the auditor,
-in a format suitable for the \fBupload\fP subcommand.
-.SS disable\-auditor
-.sp
-This subcommand
-informs an exchange that an auditor is to be deactivated. Afterwards, the
-exchange will refuse inputs from that auditor’s \fBtaler\-auditor\-offline\fP
-tool.
-.sp
-The auditor’s public key must be given in the usual base32\-encoding as the
-first argument.
-.sp
-The subcommand takes no inputs from \fBstdin\fP or other subcommands.
-.sp
-It outputs the signature affirming the removal of the auditor,
-in a format suitable for the \fBupload\fP subcommand.
-.SS enable\-account
-.sp
-This subcommand
-informs an exchange that it should advertise a bank account as belonging to
-the exchange on its \fB/wire\fP endpoint. Note that this does \fInot\fP ensure that
-the exchange will use this bank account for incoming or outgoing wire
-transfers! For this, the \fBtaler\-exchange\-transfer\fP and
-\fBtaler\-exchange\-wirewatch\fP tools must be configured. Furthermore, the bank
-account information advertised could theoretically differ from that which
-these tool actually use, for example if the public bank account is only a
-front for the actual internal business acounts.
-.sp
-The \fBpayto://\fP URI (RFC 8905) of the exchange’s bank account must be given
-as the first argument to the subcommand.
-.sp
-The subcommand takes no inputs from \fBstdin\fP or other subcommands.
-.sp
-It outputs the signature affirming the addition of the wire account,
-in a format suitable for the \fBupload\fP subcommand.
-.SS disable\-account
-.sp
-This subcommand
-informs an exchange that it should stop advertising a bank account as
-belonging to the exchange on its \fB/wire\fP endpoint.
-.sp
-The \fBpayto://\fP URI (RFC 8905) of the exchange’s (former) bank account must be
-given as the first argument to the subcommand.
-.sp
-The subcommand takes no inputs from \fBstdin\fP or other subcommands.
-.sp
-It outputs the signature affirming the deletion of the wire account, in a
-format suitable for the \fBupload\fP subcommand.
-.SS wire\-fee
-.sp
-This subcommand informs an exchange about the desired wire fee (and closing fee)
-structure for particular wire method and a calendar year (!). The tool does not
-permit changing wire fees during a calendar year. Also, once the wire fee has been
-set for a calendar year, it cannot be changed.
-.sp
-The subcommand takes the year, wire\-method (see RFC 8905, examples include
-\fBx\-taler\-bank\fP or \fBiban\fP), wire fee and closing fee as arguments.
-Instead of a year, the string \fBnow\fP can be given for the current year
-(this is mostly useful for test cases). The wire\-method should follow the
-GANA registry as given in RFC 8905. The fees must be given in the usual
-Taler format of \fBCURRENCY:NUMBER.FRACTION\fP\&.
-.sp
-The subcommand takes no inputs from \fBstdin\fP or other subcommands.
-.sp
-It outputs the signature affirming the wire fees, in a format suitable for the
-\fBupload\fP subcommand.
.SS upload
.sp
This subcommand uploads outputs from other subcommands (except \fBdownload\fP and \fBshow\fP)
@@ -342,6 +233,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-auditor.1 b/man/taler-auditor.1
index dca283cf..ac9b3d0b 100644
--- a/man/taler-auditor.1
+++ b/man/taler-auditor.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-AUDITOR" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-AUDITOR" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-auditor \- audit exchange
.
@@ -63,7 +63,7 @@ Print short help on options.
.TP
\fB\-i\fP | \fB––internal\fP
Run additional checks that can only performed on the exchange\-internal
-database and not the “safe” replicated database at the auditor.
+database and not the "safe" replicated database at the auditor.
.TP
\fB\-L\fP \fILOGLEVEL\fP | \fB––loglevel=\fP‌\fILOGLEVEL\fP
Specifies the log level to use. Accepted values are: \fBDEBUG\fP, \fBINFO\fP,
@@ -96,6 +96,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-exchange-aggregator.1 b/man/taler-exchange-aggregator.1
index 26d9ef18..2662ec5a 100644
--- a/man/taler-exchange-aggregator.1
+++ b/man/taler-exchange-aggregator.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-EXCHANGE-AGGREGATOR" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-EXCHANGE-AGGREGATOR" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-exchange-aggregator \- aggregate deposits into wire transfers
.
@@ -83,6 +83,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-exchange-benchmark.1 b/man/taler-exchange-benchmark.1
index 0a84f14a..7ee6104a 100644
--- a/man/taler-exchange-benchmark.1
+++ b/man/taler-exchange-benchmark.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-EXCHANGE-BENCHMARK" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-EXCHANGE-BENCHMARK" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-exchange-benchmark \- measure exchange performance
.
@@ -113,6 +113,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-exchange-closer.1 b/man/taler-exchange-closer.1
index f8d44d82..4c3a1130 100644
--- a/man/taler-exchange-closer.1
+++ b/man/taler-exchange-closer.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-EXCHANGE-CLOSER" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-EXCHANGE-CLOSER" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-exchange-closer \- close idle reserves
.
@@ -82,6 +82,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-exchange-dbinit.1 b/man/taler-exchange-dbinit.1
index 123e9c8c..166a7f11 100644
--- a/man/taler-exchange-dbinit.1
+++ b/man/taler-exchange-dbinit.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-EXCHANGE-DBINIT" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-EXCHANGE-DBINIT" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-exchange-dbinit \- initialize Taler exchange database
.
@@ -85,6 +85,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-exchange-httpd.1 b/man/taler-exchange-httpd.1
index 334a6fe7..027d75c0 100644
--- a/man/taler-exchange-httpd.1
+++ b/man/taler-exchange-httpd.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-EXCHANGE-HTTPD" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-EXCHANGE-HTTPD" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-exchange-httpd \- run Taler exchange (with RESTful API)
.
@@ -142,6 +142,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-exchange-offline.1 b/man/taler-exchange-offline.1
index 656ce1d6..d38871b5 100644
--- a/man/taler-exchange-offline.1
+++ b/man/taler-exchange-offline.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-EXCHANGE-OFFLINE" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-EXCHANGE-OFFLINE" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-exchange-offline \- operations using the offline key of a Taler exchange
.
@@ -38,24 +38,24 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
[\fB\-L\fP\ \fILOGLEVEL\fP\ |\ \fB––loglevel=\fP‌\fILOGLEVEL\fP]
[\fB\-l\fP\ \fIFILENAME\fP\ |\ \fB––logfile=\fP‌\fIFILENAME\fP]
[\fB\-v\fP\ |\ \fB––version\fP]
-[subcommand …]
+[subcommand ...]
.SH DESCRIPTION
.sp
\fBtaler\-exchange\-offline\fP is a command\-line tool to interact with the Taler
-exchange’s master private key. Most operations of this tool require access to
+exchange\(aqs master private key. Most operations of this tool require access to
the exchange’s long\-term offline signing key and should be run in a secure
(offline) environment under strict controls. The tool takes a list of
subcommands as arguments which are then processed sequentially.
.sp
-The tool includes two subcommands to interact \fIonline\fP with the exchange’s
+The tool includes two subcommands to interact \fIonline\fP with the exchange\(aqs
REST APIs. The \fBdownload\fP subcommand downloads the future public keys from the
running exchange. The resulting data serves as input to the \fBsign\fP and \fBshow\fP
subcommands. The \fBupload\fP subcommand uploads the signatures created with the
private master key to the exchange. It handles the output of all subcommands
(except \fBdownload\fP). The \fBdownload\fP and \fBupload\fP subcommands must naturally be
-run “online” and do not require access to the offline key.
+run "online" and do not require access to the offline key.
.sp
-All other subcommands are intended to be run “offline”. However, especially
+All other subcommands are intended to be run "offline". However, especially
when testing, it is of course possible to run the subcommands online as well.
Generally, subcommands read inputs (beyond command\-line arguments)
from \fBstdin\fP\&. However, they may also consume outputs of previous
@@ -99,17 +99,17 @@ $ taler\-exchange\-offline setup
.UNINDENT
.sp
Note that if the private key file already exists, the above will simply output
-the existing key. Passing additional arguments after setup (including “\-“)
+the existing key. Passing additional arguments after setup (including "\-")
will cause the output to be encapsulated in JSON.
.sp
Relevant configuration options for \fBtaler\-exchange\-offline\fP are:
.INDENT 0.0
.IP \(bu 2
-\fB[exchange/BASE_URL]\fP — how to reach the exchange (for download/upload)
+\fB[exchange/BASE_URL]\fP \-\-\- how to reach the exchange (for download/upload)
.IP \(bu 2
-\fB[exchange\-offline/MASTER_PRIV_FILE]\fP — where to store the private keys
+\fB[exchange\-offline/MASTER_PRIV_FILE]\fP \-\-\- where to store the private keys
.IP \(bu 2
-\fB[exchange\-offline/SECM_TOFU_FILE]\fP — where to store TOFU data
+\fB[exchange\-offline/SECM_TOFU_FILE]\fP \-\-\- where to store TOFU data
.UNINDENT
.SH SUBCOMMANDS
.SS setup
@@ -169,23 +169,23 @@ in a format suitable for the \fBupload\fP subcommand.
.sp
This subcommand
informs an exchange that an auditor is to be activated. Afterwards, the
-exchange will accept inputs from that auditor’s \fBtaler\-auditor\-offline\fP
+exchange will accept inputs from that auditor\(aqs \fBtaler\-auditor\-offline\fP
tool. Note that the auditor also must add the exchange to the list of
exchanges that it audits via \fBtaler\-auditor\-exchange\fP\&. Furthermore, the
-exchange’s database will need to be provided to the auditor. This subcommand
+exchange\(aqs database will need to be provided to the auditor. This subcommand
only informs the exchange about the auditor, but does not perform those
additional mandatory steps for a working auditor.
.sp
-The auditor’s public key must be given in the usual base32\-encoding as the
+The auditor\(aqs public key must be given in the usual base32\-encoding as the
first argument.
.sp
-The auditor’s REST API base URL must be given as the second argument. The tool
-performs a minimal sanity check, namely that the URL begins with “http”
-(this also allows “https”), but as it runs offline does not perform any further
+The auditor\(aqs REST API base URL must be given as the second argument. The tool
+performs a minimal sanity check, namely that the URL begins with "http"
+(this also allows "https"), but as it runs offline does not perform any further
validation!
.sp
The third argument must be a human\-readable name for the auditor. This may
-be shown to users and should identify the auditor’s business entity. If
+be shown to users and should identify the auditor\(aqs business entity. If
the name includes spaces, the argument should be quoted.
.sp
The subcommand takes no inputs from \fBstdin\fP or other subcommands.
@@ -196,10 +196,10 @@ in a format suitable for the \fBupload\fP subcommand.
.sp
This subcommand
informs an exchange that an auditor is to be deactivated. Afterwards, the
-exchange will refuse inputs from that auditor’s \fBtaler\-auditor\-offline\fP
+exchange will refuse inputs from that auditor\(aqs \fBtaler\-auditor\-offline\fP
tool.
.sp
-The auditor’s public key must be given in the usual base32\-encoding as the
+The auditor\(aqs public key must be given in the usual base32\-encoding as the
first argument.
.sp
The subcommand takes no inputs from \fBstdin\fP or other subcommands.
@@ -216,9 +216,9 @@ transfers! For this, the \fBtaler\-exchange\-transfer\fP and
\fBtaler\-exchange\-wirewatch\fP tools must be configured. Furthermore, the bank
account information advertised could theoretically differ from that which
these tool actually use, for example if the public bank account is only a
-front for the actual internal business acounts.
+front for the actual internal business accounts.
.sp
-The \fBpayto://\fP URI (RFC 8905) of the exchange’s bank account must be given
+The \fBpayto://\fP URI (RFC 8905) of the exchange\(aqs bank account must be given
as the first argument to the subcommand.
.sp
The subcommand takes no inputs from \fBstdin\fP or other subcommands.
@@ -231,7 +231,7 @@ This subcommand
informs an exchange that it should stop advertising a bank account as
belonging to the exchange on its \fB/wire\fP endpoint.
.sp
-The \fBpayto://\fP URI (RFC 8905) of the exchange’s (former) bank account must be
+The \fBpayto://\fP URI (RFC 8905) of the exchange\(aqs (former) bank account must be
given as the first argument to the subcommand.
.sp
The subcommand takes no inputs from \fBstdin\fP or other subcommands.
@@ -396,7 +396,7 @@ $ taler\-exchange\-offline revoke\-signkey $SK revoke\-denomkey $DKH > mix.json
.UNINDENT
.UNINDENT
.sp
-The outputs (“revoke.json”, “mix.json”) must be uploaded using the \fBupload\fP
+The outputs ("revoke.json", "mix.json") must be uploaded using the \fBupload\fP
subcommand to the exchange to actually revoke the keys.
.SH SECURITY CONSIDERATIONS
.sp
@@ -405,18 +405,18 @@ system with \fImonotonic time\fP\&. The time does not have to precisely match th
of the exchange, but it must be monotonic across tool invocations. The clock
of the offline system is used in the enable/disable signatures to communicate
an order of the events to the exchange. This prevents someone from replaying
-an older “enable” (or “disable”) message after a more recent “disable” (or
-“enable”) message has been provided to the exchange. Thus, there is no need
+an older "enable" (or "disable") message after a more recent "disable" (or
+"enable") message has been provided to the exchange. Thus, there is no need
to keep the actual files exchanged with the offline tool secret.
.sp
The \fBtaler\-exchange\-offline\fP tool tries to make sure that the online signing
-keys of the the exchange are always created by the same two security modules.
+keys of the exchange are always created by the same two security modules.
The goal here is to prevent an attacker who compromised \fBtaler\-exchange\-httpd\fP
but \fInot\fP the security modules from providing attacker\-controlled keys to the
offline signing process.
.sp
For this, the \fBtaler\-exchange\-offline\fP signing subcommand always
-automatically learns the security module’s public signing key and \fItrusts it
+automatically learns the security module\(aqs public signing key and \fItrusts it
on first use\fP (TOFU), but stores it to disk (see the \fBSECM_TOFU_FILE\fP option
in the \fB[exchange\-offline]\fP section of the configuration). If the keys
change subsequently, the tool will refuse to sign.
@@ -430,6 +430,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-exchange-secmod-eddsa.1 b/man/taler-exchange-secmod-eddsa.1
index e49f6959..dbaa35c7 100644
--- a/man/taler-exchange-secmod-eddsa.1
+++ b/man/taler-exchange-secmod-eddsa.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-EXCHANGE-SECMOD-EDDSA" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-EXCHANGE-SECMOD-EDDSA" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-exchange-secmod-eddsa \- handle private EDDSA key operations for a Taler exchange
.
@@ -90,6 +90,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-exchange-secmod-rsa.1 b/man/taler-exchange-secmod-rsa.1
index 25965f0d..3edcce2a 100644
--- a/man/taler-exchange-secmod-rsa.1
+++ b/man/taler-exchange-secmod-rsa.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-EXCHANGE-SECMOD-RSA" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-EXCHANGE-SECMOD-RSA" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-exchange-secmod-rsa \- handle private RSA key operations for a Taler exchange
.
@@ -90,6 +90,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-exchange-transfer.1 b/man/taler-exchange-transfer.1
index f86ffc14..890dd341 100644
--- a/man/taler-exchange-transfer.1
+++ b/man/taler-exchange-transfer.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-EXCHANGE-TRANSFER" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-EXCHANGE-TRANSFER" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-exchange-transfer \- execute wire transfers
.
@@ -82,6 +82,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-exchange-wirewatch.1 b/man/taler-exchange-wirewatch.1
index d53d3a1a..4840e714 100644
--- a/man/taler-exchange-wirewatch.1
+++ b/man/taler-exchange-wirewatch.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-EXCHANGE-WIREWATCH" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-EXCHANGE-WIREWATCH" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-exchange-wirewatch \- watch for incoming wire transfers
.
@@ -88,6 +88,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-helper-auditor-aggregation.1 b/man/taler-helper-auditor-aggregation.1
index 66acfaf1..272ed200 100644
--- a/man/taler-helper-auditor-aggregation.1
+++ b/man/taler-helper-auditor-aggregation.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-HELPER-AUDITOR-AGGREGATION" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-HELPER-AUDITOR-AGGREGATION" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-helper-auditor-aggregation \- audit Taler exchange aggregation activity
.
@@ -89,6 +89,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-helper-auditor-coins.1 b/man/taler-helper-auditor-coins.1
index 328804a6..54b9edc1 100644
--- a/man/taler-helper-auditor-coins.1
+++ b/man/taler-helper-auditor-coins.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-HELPER-AUDITOR-COINS" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-HELPER-AUDITOR-COINS" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-helper-auditor-coins \- audit Taler coin processing
.
@@ -89,6 +89,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-helper-auditor-deposits.1 b/man/taler-helper-auditor-deposits.1
index d8a1a381..a09fb23c 100644
--- a/man/taler-helper-auditor-deposits.1
+++ b/man/taler-helper-auditor-deposits.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-HELPER-AUDITOR-DEPOSITS" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-HELPER-AUDITOR-DEPOSITS" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-helper-auditor-deposits \- audit Taler exchange database for deposit confirmation consistency
.
@@ -89,6 +89,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-helper-auditor-reserves.1 b/man/taler-helper-auditor-reserves.1
index 37964afe..a411d1df 100644
--- a/man/taler-helper-auditor-reserves.1
+++ b/man/taler-helper-auditor-reserves.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-HELPER-AUDITOR-RESERVES" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-HELPER-AUDITOR-RESERVES" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-helper-auditor-reserves \- audit Taler exchange reserve handling
.
@@ -89,6 +89,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-helper-auditor-wire.1 b/man/taler-helper-auditor-wire.1
index d55d3665..e4315e7c 100644
--- a/man/taler-helper-auditor-wire.1
+++ b/man/taler-helper-auditor-wire.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-HELPER-AUDITOR-WIRE" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-HELPER-AUDITOR-WIRE" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-helper-auditor-wire \- audit exchange database for consistency with the bank's wire transfers
.
@@ -44,7 +44,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.SH DESCRIPTION
.sp
\fBtaler\-helper\-auditor\-wire\fP is a command\-line tool to
-audit exchange database for consistency with the bank’s wire transfers.
+audit exchange database for consistency with the bank\(aqs wire transfers.
.sp
FIXME: More detail.
.sp
@@ -89,6 +89,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-merchant-benchmark.1 b/man/taler-merchant-benchmark.1
index 839403e7..a37ace4c 100644
--- a/man/taler-merchant-benchmark.1
+++ b/man/taler-merchant-benchmark.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-MERCHANT-BENCHMARK" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-MERCHANT-BENCHMARK" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-merchant-benchmark \- generate Taler-style benchmarking payments
.
@@ -72,14 +72,14 @@ unaggregated payments and actually aggregated them.
.SH COMMON OPTIONS
.INDENT 0.0
.TP
-\fB\-a\fP \fIAPIKEY\fP | \fB–apikey=\fP\fIAPIKEY\fP
-HTTP ‘Authorization’ header to send to the merchant.
+\fB\-a\fP \fIAPIKEY\fP | \fB\-\-apikey=\fP\fIAPIKEY\fP
+HTTP \(aqAuthorization\(aq header to send to the merchant.
.TP
\fB\-c\fP \fIFILENAME\fP | \fB––config=\fP\fIFILENAME\fP
Use the configuration and other resources for the merchant to
operate from FILENAME.
.TP
-\fB\-e\fP \fISECTION\fP | \fB–exchange\-account=\fP\fISECTION\fP
+\fB\-e\fP \fISECTION\fP | \fB\-\-exchange\-account=\fP\fISECTION\fP
Mandatory.
Configuration \fISECTION\fP specifying the exchange account to use.
.TP
@@ -106,6 +106,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-merchant-dbinit.1 b/man/taler-merchant-dbinit.1
index e3de3d68..8327f7d2 100644
--- a/man/taler-merchant-dbinit.1
+++ b/man/taler-merchant-dbinit.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-MERCHANT-DBINIT" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-MERCHANT-DBINIT" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-merchant-dbinit \- initialize Taler merchant database
.
@@ -79,6 +79,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-merchant-httpd.1 b/man/taler-merchant-httpd.1
index 922b2b37..eadc6ee9 100644
--- a/man/taler-merchant-httpd.1
+++ b/man/taler-merchant-httpd.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-MERCHANT-HTTPD" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-MERCHANT-HTTPD" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-merchant-httpd \- run Taler merchant backend (with RESTful API)
.
@@ -48,6 +48,19 @@ before running this command.
.SH OPTIONS
.INDENT 0.0
.TP
+\fB\-a\fP \fITOKEN\fP | \fB––auth=\fP\fITOKEN\fP
+Use TOKEN for initial access control to the merchant backend. The value
+given in TOKEN must appear in backoffice requests to the default instance
+of the merchant, i.e. "Authorization: secret\-token:TOKEN" to obtain
+access to the merchant backend. Note that setting a passphrase for the
+default instance by any means will block future access via TOKEN. This
+is basically a way to reset the passphrase protecting access. TOKEN
+should be a "pchar" as per RFC 8959, but this is NOT checked. Note that
+TOKEN will only grant access to the \(aqdefault\(aq instance, not other instances.
+Instead of using the command\-line, which exposes TOKEN to users on the
+system, you may want to consider setting the
+TALER_MERCHANT_TOKEN environment variable instead.
+.TP
\fB\-C\fP | \fB––connection\-close\fP
Force each HTTP connection to be closed after each request
(useful in combination with \-f to avoid having to wait for nc to
@@ -82,6 +95,13 @@ Print version information.
Sending a SIGTERM to the process will cause it to shutdown
cleanly.
.UNINDENT
+.SH ENVIRONMENT VARIABLES
+.INDENT 0.0
+.TP
+.B TALER_MERCHANT_TOKEN
+Like the "\-a" option, resets the access token for the default
+instance to the given value.
+.UNINDENT
.SH SEE ALSO
.sp
taler\-merchant\-dbinit(1), taler\-merchant\-tip\-enable(1), taler.conf(5)
@@ -92,6 +112,6 @@ electronic mail to <\fI\%taler@gnu.org\fP>
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-merchant-setup-reserve.1 b/man/taler-merchant-setup-reserve.1
index 14494c56..dceb1cf2 100644
--- a/man/taler-merchant-setup-reserve.1
+++ b/man/taler-merchant-setup-reserve.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-MERCHANT-SETUP-RESERVE" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-MERCHANT-SETUP-RESERVE" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-merchant-setup-reserve \- setup reserve for tipping at a Taler merchant backend
.
@@ -57,7 +57,7 @@ from the exchange needed to fill the reserve.
.TP
\fB\-A\fP \fIUSERNAME:PASSWORD\fP | \fB––auth=\fP\fIUSERNAME:PASSWORD\fP
Use \fBUSERNAME\fP and \fBPASSWORD\fP for HTTP client authentication.
-The “:” must be present as a separator.
+The ":" must be present as a separator.
Note that this form of authentication has nothing to do with the TLS client
certificate authentication supported with the \fB\-C\fP, \fB\-k\fP and \fB\-p\fP options.
The \fBPASSWORD\fP given to this option is given to the server!
@@ -129,6 +129,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler-wire-gateway-client.1 b/man/taler-wire-gateway-client.1
index 00ce678c..28bb7aad 100644
--- a/man/taler-wire-gateway-client.1
+++ b/man/taler-wire-gateway-client.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER-WIRE-GATEWAY-CLIENT" "1" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER-WIRE-GATEWAY-CLIENT" "1" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler-wire-gateway-client \- trigger a transfer at the bank
.
@@ -141,6 +141,6 @@ mail to <\fI\%taler@gnu.org\fP>
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/man/taler.conf.5 b/man/taler.conf.5
index aee0a7c6..48911c7f 100644
--- a/man/taler.conf.5
+++ b/man/taler.conf.5
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "TALER.CONF" "5" "Jan 27, 2021" "0.8pre0" "GNU Taler"
+.TH "TALER.CONF" "5" "Apr 26, 2021" "0.8" "GNU Taler"
.SH NAME
taler.conf \- Taler configuration file
.
@@ -62,6 +62,7 @@ more \fBNUMBER UNIT\fP pairs, e.g. \fB60 s\fP, \fB4 weeks 1 day\fP, \fB5 years 2
.sp
Values that represent an amount are in the usual amount syntax:
\fBCURRENCY:VALUE.FRACTION\fP, e.g. \fBEUR:1.50\fP\&.
+The \fBFRACTION\fP portion may extend up to 8 places.
.sp
Files containing default values for many of the options described below
are installed under \fB$TALER_PREFIX/share/taler/config.d/\fP\&.
@@ -121,7 +122,7 @@ Port on which the HTTP server listens, e.g.\ 8080.
.TP
.B MASTER_PUBLIC_KEY
Crockford Base32\-encoded master public key, public version of the
-exchange’s long\-time offline signing key.
+exchange\(aqs long\-time offline signing key.
.TP
.B MASTER_PRIV_FILE
Location of the master private key on disk. Only used by tools that
@@ -144,12 +145,12 @@ For how long should clients cache \fB/keys\fP responses at most?
.B TERMS_DIR
Directory where the terms of service of the exchange operator can be fund.
The directory must contain sub\-directories for every supported language,
-using the two\-character language code in lower case, e.g. “en/” or “fr/”.
+using the two\-character language code in lower case, e.g. "en/" or "fr/".
Each subdirectory must then contain files with the terms of service in
various formats. The basename of the file of the current policy must be
specified under \fBTERMS_ETAG\fP\&. The extension defines the mime type.
-Supported extensions include “html”, “htm”, “txt”, “pdf”, “jpg”, “jpeg”,
-“png” and “gif”. For example, using a \fBTERMS_ETAG\fP of “0”, the structure
+Supported extensions include "html", "htm", "txt", "pdf", "jpg", "jpeg",
+"png" and "gif". For example, using a \fBTERMS_ETAG\fP of "0", the structure
could be the following:
.INDENT 7.0
.IP \(bu 2
@@ -168,7 +169,7 @@ $TERMS_DIR/de/0.txt
.TP
.B TERMS_ETAG
Basename of the file(s) in the \fBTERMS_DIR\fP with the current terms of service.
-The value is also used for the “Etag” in the HTTP request to control
+The value is also used for the "Etag" in the HTTP request to control
caching. Whenever the terms of service change, the \fBTERMS_ETAG\fP MUST also
change, and old values MUST NOT be repeated. For example, the date or
version number of the terms of service SHOULD be used for the Etag. If
@@ -184,7 +185,7 @@ Works the same as \fBTERMS_ETAG\fP, just for the privacy policy.
.UNINDENT
.SS EXCHANGE OFFLINE SIGNING OPTIONS
.sp
-The following options must be in the section “[exchange\-offline]”.
+The following options must be in the section "[exchange\-offline]".
.INDENT 0.0
.TP
.B MASTER_PRIV_FILE
@@ -210,7 +211,7 @@ this option will also be ignored.
.UNINDENT
.SS EXCHANGE RSA CRYPTO HELPER OPTIONS
.sp
-The following options must be in the section “[taler\-exchange\-secmod\-rsa]”.
+The following options must be in the section "[taler\-exchange\-secmod\-rsa]".
.INDENT 0.0
.TP
.B LOOKAHEAD_SIGN
@@ -237,7 +238,7 @@ Note that the \fBtaler\-exchange\-secmod\-rsa\fP also evaluates the \fB[coin_*]\
configuration sections described below.
.SS EXCHANGE EDDSA CRYPTO HELPER OPTIONS
.sp
-The following options must be in the section “[taler\-exchange\-secmod\-eddsa]”.
+The following options must be in the section "[taler\-exchange\-secmod\-eddsa]".
.INDENT 0.0
.TP
.B LOOKAHEAD_SIGN
@@ -264,7 +265,7 @@ On which path should the security module listen for signing requests?
.UNINDENT
.SS EXCHANGE DATABASE OPTIONS
.sp
-The following options must be in the section “[exchangedb]”.
+The following options must be in the section "[exchangedb]".
.INDENT 0.0
.TP
.B IDLE_RESERVE_EXPIRATION_TIME
@@ -305,7 +306,7 @@ URL of the wire gateway. Typically of the form
\fBhttps://$HOSTNAME[:$PORT]/taler\-wire\-gateway/$USERNAME/\fP
where $HOSTNAME is the hostname of the system running the bank
(such as the Taler Python bank or the Nexus) and \fB$USERNAME\fP is
-the username of the exchange’s bank account (usually matching
+the username of the exchange\(aqs bank account (usually matching
the \fBUSERNAME\fP option used for authentication). Example:
\fBhttps://bank.demo.taler.net/taler\-wire\-gateway/Exchange/\fP\&.
.TP
@@ -416,7 +417,7 @@ Base URL of the exchange, e.g.\ “\fI\%https://exchange.demo.taler.net/\fP”
.TP
.B MASTER_KEY
Crockford Base32 encoded master public key, public version of the
-exchange’s long\-time offline signing key. Can be omitted, in that
+exchange\(aqs long\-time offline signing key. Can be omitted, in that
case the exchange will NOT be trusted unless it is audited by
a known auditor.
Omitting \fBMASTER_KEY\fP can be useful if we do not trust the exchange
@@ -475,8 +476,8 @@ The following options must be in section “[auditordb\-postgres]” if the
.INDENT 0.0
.TP
.B CONFIG
-How to access the database, e.g.\ “postgres:///taler” to use the
-“taler” database. Testcases use “talercheck”.
+How to access the database, e.g.\ "postgres:///taler" to use the
+"taler" database. Testcases use “talercheck”.
.UNINDENT
.SH SEE ALSO
.sp
@@ -489,6 +490,6 @@ mail to <\fI\%taler@gnu.org\fP>.
.SH AUTHOR
GNU Taler contributors
.SH COPYRIGHT
-2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
.\" Generated by docutils manpage writer.
.
diff --git a/texinfo/anastasis-figures/anastasis-db.png b/texinfo/anastasis-figures/anastasis-db.png
new file mode 100644
index 00000000..03eed9da
--- /dev/null
+++ b/texinfo/anastasis-figures/anastasis-db.png
Binary files differ
diff --git a/texinfo/anastasis-figures/anastasis_challenge_payment.png b/texinfo/anastasis-figures/anastasis_challenge_payment.png
new file mode 100644
index 00000000..a0593eba
--- /dev/null
+++ b/texinfo/anastasis-figures/anastasis_challenge_payment.png
Binary files differ
diff --git a/texinfo/anastasis-figures/anastasis_challengecode.png b/texinfo/anastasis-figures/anastasis_challengecode.png
new file mode 100644
index 00000000..fc30f4fe
--- /dev/null
+++ b/texinfo/anastasis-figures/anastasis_challengecode.png
Binary files differ
diff --git a/texinfo/anastasis-figures/anastasis_reducer_backup.png b/texinfo/anastasis-figures/anastasis_reducer_backup.png
new file mode 100644
index 00000000..87b0a9b4
--- /dev/null
+++ b/texinfo/anastasis-figures/anastasis_reducer_backup.png
Binary files differ
diff --git a/texinfo/anastasis-figures/anastasis_reducer_recovery.png b/texinfo/anastasis-figures/anastasis_reducer_recovery.png
new file mode 100644
index 00000000..7d3cc9ae
--- /dev/null
+++ b/texinfo/anastasis-figures/anastasis_reducer_recovery.png
Binary files differ
diff --git a/texinfo/anastasis-figures/anastasis_truth.png b/texinfo/anastasis-figures/anastasis_truth.png
new file mode 100644
index 00000000..7f23fa21
--- /dev/null
+++ b/texinfo/anastasis-figures/anastasis_truth.png
Binary files differ
diff --git a/texinfo/anastasis-figures/anastasis_truth_payment.png b/texinfo/anastasis-figures/anastasis_truth_payment.png
new file mode 100644
index 00000000..70a6b3df
--- /dev/null
+++ b/texinfo/anastasis-figures/anastasis_truth_payment.png
Binary files differ
diff --git a/texinfo/anastasis.texi b/texinfo/anastasis.texi
new file mode 100644
index 00000000..cd9938f2
--- /dev/null
+++ b/texinfo/anastasis.texi
@@ -0,0 +1,2792 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename anastasis.info
+@documentencoding UTF-8
+@ifinfo
+@*Generated by Sphinx 3.4.3.@*
+@end ifinfo
+@settitle Anastasis Manual
+@defindex ge
+@paragraphindent 0
+@exampleindent 4
+@finalout
+@dircategory CATEGORY
+@direntry
+* MENU ENTRY: (anastasis.info). DESCRIPTION
+@end direntry
+
+@definfoenclose strong,`,'
+@definfoenclose emph,`,'
+@c %**end of header
+
+@copying
+@quotation
+GNU Taler 0.8.0pre0, Apr 26, 2021
+
+Anastasis team
+
+Copyright @copyright{} 2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+@end quotation
+
+@end copying
+
+@titlepage
+@title Anastasis Manual
+@insertcopying
+@end titlepage
+@contents
+
+@c %** start of user preamble
+
+@c %** end of user preamble
+
+@ifnottex
+@node Top
+@top Anastasis Manual
+@insertcopying
+@end ifnottex
+
+@c %**start of body
+@anchor{anastasis doc}@anchor{0}
+@c This file is part of Anastasis
+@c Copyright (C) 2019. 2021 Anastasis SARL
+@c
+@c Anastasis is free software; you can redistribute it and/or modify it under the
+@c terms of the GNU General Public License as published by the Free Software
+@c Foundation; either version 2.1, or (at your option) any later version.
+@c
+@c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
+@c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+@c A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+@c
+@c You should have received a copy of the GNU Lesser General Public License along with
+@c Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+@c
+@c @author Christian Grothoff
+@c @author Dominik Meister
+@c @author Dennis Neufeld
+
+Anastasis is a service that allows the user to securely deposit a
+@strong{core secret} with an open set of escrow providers and recover it if the secret is
+lost. The @strong{core secret} itself is protected from the escrow providers by
+encrypting it with a @strong{master key}. The main objective of Anastasis is to
+ensure that the user can reliably recover the @strong{core secret}, while making
+this difficult for everyone else. Furthermore, it is assumed that the user is
+unable to reliably remember any secret with sufficiently high entropy, so we
+cannot simply encrypt using some other key material in possession of the user.
+
+To uniquely identify users, an "unforgettable" @strong{identifier} is used. This
+identifier should be difficult to guess for anybody but the user. However, the
+@strong{identifier} is not expected to have sufficient entropy or secrecy to be
+cryptographically secure. Examples for such identifier would be a
+concatenation of the full name of the user and their social security or
+passport number(s). For Swiss citizens, the AHV number could also be used.
+
+The adversary model of Anastasis has two types of adversaries: weak
+adversaries which do not know the user's @strong{identifier}, and strong
+adversaries which somehow do know a user's @strong{identifier}. For weak
+adversaries the system guarantees full confidentiality. For strong
+adversaries, breaking confidentiality additionally requires that Anastasis
+escrow providers must have colluded. The user is able to specify a set of
+@strong{policies} which determine which Anastasis escrow providers would need to
+collude to break confidentiality. These policies also set the bar for the user
+to recover their core secret.
+
+A @strong{recovery document} includes all of the information a user needs to
+recover access to their core secret. It specifies a set of @strong{escrow
+methods}, which specify how the user should convince the Anastasis server
+that they are "real". Escrow methods can for example include SMS-based
+verification, video identification or a security question. For each escrow
+method, the Anastasis server is provided with @strong{truth}, that is data the
+Anastasis operator may learn during the recovery process to authenticate the
+user. Examples for truth would be a phone number (for SMS), a picture of the
+user (for video identification), or the (hash of) a security answer. A strong
+adversary is assumed to be able to learn the truth, while weak adversaries
+must not. In addition to a set of escrow methods and associated Anastasis
+server operators, the @strong{recovery document} also specifies @strong{policies}, which
+describe the combination(s) of the escrow methods that suffice to obtain
+access to the core secret. For example, a @strong{policy} could say that the
+escrow methods (A and B) suffice, and a second policy may permit (A and C). A
+different user may choose to use the policy that (A and B and C) are all
+required. Anastasis imposes no limit on the number of policies in a
+@strong{recovery document}, or the set of providers or escrow methods involved in
+guarding a user's secret. Weak adversaries must not be able to deduce
+information about a user's @strong{recovery document} (except for its length, which
+may be exposed to an adversary which monitors the user's network traffic).
+
+@menu
+* Anastasis DB Schema::
+* Anastasis Cryptography::
+* Anastasis REST API::
+* Anastasis Reducer API::
+* Authentication Methods::
+
+@end menu
+
+@node Anastasis DB Schema,Anastasis Cryptography,Top,Top
+@anchor{anastasis anastasis}@anchor{1}@anchor{anastasis anastasis-db-schema}@anchor{2}
+@chapter Anastasis DB Schema
+
+
+@image{anastasis-figures/anastasis-db,,,,png}
+
+@image{anastasis-figures/anastasis_challengecode,,,,png}
+
+@image{anastasis-figures/anastasis_challenge_payment,,,,png}
+
+@image{anastasis-figures/anastasis_truth,,,,png}
+
+@image{anastasis-figures/anastasis_truth_payment,,,,png}
+
+@node Anastasis Cryptography,Anastasis REST API,Anastasis DB Schema,Top
+@anchor{anastasis anastasis-cryptography}@anchor{3}
+@chapter Anastasis Cryptography
+
+
+When a user needs to interact with Anastasis, the system first derives some key
+material, but not the master secret, from the user's @strong{identifier} using
+different HKDFs. These HKDFs are salted using the respective escrow
+provider's @strong{server salt}, which ensures that the accounts for the same user
+cannot be easily correlated across the various Anastasis servers.
+
+Each Anastasis server uses an EdDSA @strong{account key} to identify the account of
+the user. The account private key is derived from the user's @strong{identifier} using
+a computationally expensive cryptographic hash function. Using an
+expensive hash algorithm is assumed to make it infeasible for a weak adversary to
+determine account keys by brute force (without knowing the user's identifier).
+However, it is assumed that a strong adversary performing a targeted attack can
+compute the account key pair.
+
+The public account key is Crockford base32-encoded in the URI to identify the
+account, and used to sign requests. These signatures are also provided in
+base32-encoding and transmitted using the HTTP header
+@code{Anastasis-Account-Signature}.
+
+When confidential data is uploaded to an Anastasis server, the respective
+payload is encrypted using AES-GCM with a symmetric key and initialization
+vector derived from the @strong{identifier} and a high-entropy @strong{nonce}. The
+nonce and the GCM tag are prepended to the ciphertext before being uploaded to
+the Anastasis server. This is done whenever confidential data is stored with
+the server.
+
+The @strong{core secret} of the user is (AES) encrypted using a symmetric @strong{master
+key}. Recovering this master key requires the user to satisfy a particular
+@strong{policy}. Policies specify a set of @strong{escrow methods}, each of which leads
+the user to a @strong{key share}. Combining those key shares (by hashing) allows
+the user to obtain a @strong{policy key}, which can be used to decrypt the @strong{master
+key}. There can be many policies, satisfying any of these will allow the
+user to recover the master key. A @strong{recovery document} contains the
+encrypted @strong{core secret}, a set of escrow methods and a set of policies.
+
+@menu
+* Key derivations::
+* Key Usage::
+* Availability Considerations::
+
+@end menu
+
+@node Key derivations,Key Usage,,Anastasis Cryptography
+@anchor{anastasis key-derivations}@anchor{4}
+@section Key derivations
+
+
+EdDSA and ECDHE public keys are always points on Curve25519 and represented
+using the standard 256 bit Ed25519 compact format. The binary representation
+is converted to Crockford Base32 when transmitted inside JSON or as part of
+URLs.
+
+To start, a user provides their private, unique and unforgettable
+@strong{identifier} as a seed to identify their account. For example, this could
+be a social security number together with their full name. Specifics may
+depend on the cultural context, in this document we will simply refer to this
+information as the @strong{identifier}.
+
+This identifier will be first hashed with Argon2, to provide a @strong{kdf_id}
+which will be used to derive other keys later. The Hash must also include the
+respective @strong{server_salt}. This also ensures that the @strong{kdf_id} is different
+on each server. The use of Argon2 and the respective @strong{server_salt} is intended
+to make it difficult to brute-force @strong{kdf_id} values and help protect the user's
+privacy. Also this ensures that the @strong{kdf_id}s on every server differs. However,
+we do not assume that the @strong{identifier} or the @strong{kdf_id} cannot be
+determined by an adversary performing a targeted attack, as a user's
+@strong{identifier} is likely to always be known to state actors and may
+likely also be available to other actors.
+
+@example
+kdf_id := Argon2( identifier, server_salt, keysize )
+@end example
+
+@strong{identifier}: The secret defined from the user beforehand.
+
+@strong{server_salt}: The salt from the Server.
+
+@strong{keysize}: The desired output size of the KDF, here 32 bytes.
+
+@menu
+* Verification::
+* Encryption::
+
+@end menu
+
+@node Verification,Encryption,,Key derivations
+@anchor{anastasis verification}@anchor{5}
+@subsection Verification
+
+
+For users to authorize "policy" operations we need an EdDSA key pair. As we
+cannot assure that the corresponding private key is truly secret, such policy
+operations must never be destructive: Should an adversary learn the private
+key, they could access (and with the @strong{kdf_id}, decrypt) the user's policy (but
+not the core secret), or upload a new version of the
+@strong{encrypted recovery document} (but not delete an existing version).
+
+For the generation of the private key we use the @strong{kdf_id} as the entropy source,
+hash it to derive a base secret which will then be processed to fit the
+requirements for EdDSA private keys. From the private key we can then
+generate the corresponding public key. Here, "ver" is used as a salt for the
+HKDF to ensure that the result differs from other cases where we hash
+@strong{kdf_id}.
+
+@example
+ver_secret := HKDF(kdf_id, "ver", keysize)
+eddsa_priv := eddsa_d_to_a(ver_secret)
+eddsa_pub := get_EdDSA_Pub(eddsa_priv)
+@end example
+
+@strong{HKDF()}: The HKDF-function uses two phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase.
+
+@strong{kdf_id}: Hashed identifier.
+
+@strong{key_size}: Size of the output, here 32 bytes.
+
+@strong{ver_secret}: Derived key from the @code{kdf_id}, serves as intermediate step for the generation of the private key.
+
+@strong{eddsa_d_to_a()}: Function which converts the ver_key to a valid EdDSA private key. Specifically, assuming the value @code{eddsa_priv} is in a 32-byte array "digest", the function clears and sets certain bits as follows:
+
+@example
+digest[0] = (digest[0] & 0x7f) | 0x40;
+digest[31] &= 0xf8;
+@end example
+
+@strong{eddsa_priv}: The generated EdDSA private key.
+
+@strong{eddsa_pub}: The generated EdDSA public key.
+
+@node Encryption,,Verification,Key derivations
+@anchor{anastasis encryption}@anchor{6}
+@subsection Encryption
+
+
+For symmetric encryption of data we use AES256-GCM. For this we need a
+symmetric key and an initialization vector (IV). To ensure that the
+symmetric key changes for each encryption operation, we compute the
+key material using an HKDF over a @code{nonce} and the @code{kdf_id}.
+
+@example
+(iv,key) := HKDF(kdf_id, nonce, keysize + ivsize)
+@end example
+
+@strong{HKDF()}: The HKDF-function uses two phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase.
+
+@strong{kdf_id}: Hashed identifier.
+
+@strong{keysize}: Size of the AES symmetric key, here 32 bytes.
+
+@strong{ivsize}: Size of the AES GCM IV, here 12 bytes.
+
+@strong{prekey}: Original key material.
+
+@strong{nonce}: 32-byte nonce, must never match "ver" (which it cannot as the length is different). Of course, we must
+avoid key reuse. So, we have to use different nonces to get different keys and IVs (see below).
+
+@strong{key}: Symmetric key which is later used to encrypt the documents with AES256-GCM.
+
+@strong{iv}: IV which will be used for AES-GCM.
+
+@node Key Usage,Availability Considerations,Key derivations,Anastasis Cryptography
+@anchor{anastasis key-usage}@anchor{7}
+@section Key Usage
+
+
+The keys we have generated are then used to encrypt the @strong{recovery document} and
+the @strong{key_share} of the user.
+
+@menu
+* Encryption: Encryption<2>.
+* Signatures::
+
+@end menu
+
+@node Encryption<2>,Signatures,,Key Usage
+@anchor{anastasis id1}@anchor{8}
+@subsection Encryption
+
+
+Before every encryption a 32-byte nonce is generated.
+From this the symmetric key is computed as described above.
+We use AES256-GCM for the encryption of the @strong{recovery document} and
+the @strong{key_share}. To ensure that the key derivation for the encryption
+of the @strong{recovery document} differs fundamentally from that of an
+individual @strong{key share}, we use different salts ("erd" and "eks", respectively).
+
+@example
+(iv0, key0) := HKDF(key_id, nonce0, "erd", keysize + ivsize)
+(encrypted_recovery_document, aes_gcm_tag) := AES256_GCM(recovery_document, key0, iv0)
+(iv_i, key_i) := HKDF(key_id, nonce_i, "eks", [optional data], keysize + ivsize)
+(encrypted_key_share_i, aes_gcm_tag_i) := AES256_GCM(key_share_i, key_i, iv_i)
+@end example
+
+@strong{encrypted_recovery_document}: The encrypted @strong{recovery document} which contains the escrow methods, policies
+and the encrypted @strong{core secret}.
+
+@strong{nonce0}: Nonce which is used to generate @emph{key0} and @emph{iv0} which are used for the encryption of the @emph{recovery document}.
+Nonce must contain the string "ERD".
+
+@strong{optional data}: Key material that optionally is contributed from the authentication method to further obfuscate the key share from the escrow provider.
+
+@strong{encrypted_key_share_i}: The encrypted @strong{key_share} which the escrow provider must release upon successful authentication.
+Here, @strong{i} must be a positive number used to iterate over the various @strong{key shares} used for the various @strong{escrow methods}
+at the various providers.
+
+@strong{nonce_i}: Nonce which is used to generate @emph{key_i} and @emph{iv_i} which are used for the encryption of the @strong{key share}. @strong{i} must be
+the same number as specified above for @emph{encrypted_key_share_i}. Nonce must contain the string "EKS" plus the according @emph{i}.
+
+As a special rule, when a @strong{security question} is used to authorize access to an
+@strong{encrypted_key_share_i}, then the salt "eks" is replaced with an (expensive) hash
+of the answer to the security question as an additional way to make the key share
+inaccessible to those who do not have the answer:
+
+@example
+powh := POW_HASH (qsalt, answer)
+ekss := HKDF("Anastasis-secure-question-uuid-salting",
+ powh,
+ uuid);
+(iv_i, key_i) := HKDF(key_id, nonce_i, ekss, [optional data], keysize + ivsize)
+@end example
+
+@strong{qsalt}: Salt value used to hash answer to satisfy the challenge to prevent the provider from determining the answer via guessing.
+
+@strong{answer}: Answer to the security question, in UTF-8, as entered by the user.
+
+@strong{powh}: Result of the (expensive, proof-of-work) hash algorithm.
+
+@strong{uuid}: UUID of the challenge associated with the security question and the encrypted key share.
+
+@strong{ekss}: Replacement salt to be used instead of "eks" when deriving the key to encrypt/decrypt the key share.
+
+@node Signatures,,Encryption<2>,Key Usage
+@anchor{anastasis signatures}@anchor{9}
+@subsection Signatures
+
+
+The EdDSA keys are used to sign the data sent from the client to the
+server. Everything the client sends to server is signed. The following
+algorithm is equivalent for @strong{Anastasis-Policy-Signature}.
+
+@example
+(anastasis-account-signature) := eddsa_sign(h_body, eddsa_priv)
+ver_res := eddsa_verifiy(h_body, anastasis-account-signature, eddsa_pub)
+@end example
+
+@strong{anastasis-account-signature}: Signature over the SHA-512 hash of the body using the purpose code @code{TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD} (1400) (see GNUnet EdDSA signature API for the use of purpose).
+
+@strong{h_body}: The hashed body.
+
+@strong{ver_res}: A boolean value. True: Signature verification passed, False: Signature verification failed.
+
+When requesting policy downloads, the client must also provide a signature:
+
+@example
+(anastasis-account-signature) := eddsa_sign(version, eddsa_priv)
+ver_res := eddsa_verifiy(version, anastasis-account-signature, eddsa_pub)
+@end example
+
+@strong{anastasis-account-signature}: Signature over the SHA-512 hash of the body using the purpose code @code{TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD} (1401) (see GNUnet EdDSA signature API for the use of purpose).
+
+@strong{version}: The version requested as a 64-bit integer, 2^64-1 for the "latest version".
+
+@strong{ver_res}: A boolean value. True: Signature verification passed, False: Signature verification failed.
+
+@node Availability Considerations,,Key Usage,Anastasis Cryptography
+@anchor{anastasis availability-considerations}@anchor{a}
+@section Availability Considerations
+
+
+Anastasis considers two main threats against availability. First, the
+Anastasis server operators must be protected against denial-of-service attacks
+where an adversary attempts to exhaust the operator's resources. The API protects
+against these attacks by allowing operators to set fees for all
+operations. Furthermore, all data stored comes with an expiration logic, so an
+attacker cannot force servers to store data indefinitely.
+
+A second availability issue arises from strong adversaries that may be able to
+compute the account keys of some user. While we assume that such an adversary
+cannot successfully authenticate against the truth, the account key does
+inherently enable these adversaries to upload a new policy for the account.
+This cannot be prevented, as the legitimate user must be able to set or change
+a policy using only the account key. To ensure that an adversary cannot
+exploit this, policy uploads first of all never delete existing policies, but
+merely create another version. This way, even if an adversary uploads a
+malicious policy, a user can still retrieve an older version of the policy to
+recover access to their data. This append-only storage for policies still
+leaves a strong adversary with the option of uploading many policies to
+exhaust the Anastasis server's capacity. We limit this attack by requiring a
+policy upload to include a reference to a @strong{payment identifier} from a payment
+made by the user. Thus, a policy upload requires both knowledge of the
+@strong{identity} and making a payment. This effectively prevents an adversary
+from using the append-only policy storage from exhausting Anastasis server
+capacity.
+
+@node Anastasis REST API,Anastasis Reducer API,Anastasis Cryptography,Top
+@anchor{anastasis anastasis-rest-api}@anchor{b}
+@chapter Anastasis REST API
+
+@anchor{anastasis salt}@anchor{c}
+@menu
+* Receiving Configuration::
+* Receiving Terms of Service::
+* Manage policy::
+* Managing truth::
+
+@end menu
+
+@node Receiving Configuration,Receiving Terms of Service,,Anastasis REST API
+@anchor{anastasis config}@anchor{d}@anchor{anastasis receiving-configuration}@anchor{e}
+@section Receiving Configuration
+
+
+@anchor{anastasis get--config}@anchor{f}
+@deffn {HTTP Get} GET /config
+
+Obtain the configuration details of the escrow provider.
+
+@strong{Response:}
+
+Returns an @ref{10,,EscrowConfigurationResponse}.
+@anchor{anastasis escrowconfigurationresponse}@anchor{10}
+@example
+interface EscrowConfigurationResponse @{
+
+ // Protocol identifier, clarifies that this is an Anastasis provider.
+ name: "anastasis";
+
+ // libtool-style representation of the Exchange protocol version, see
+ // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
+ // The format is "current:revision:age".
+ version: string;
+
+ // Currency in which this provider processes payments.
+ currency: string;
+
+ // Supported authorization methods.
+ methods: AuthorizationMethodConfig[];
+
+ // Maximum policy upload size supported.
+ storage_limit_in_megabytes: number;
+
+ // Payment required to maintain an account to store policy documents for a year.
+ // Users can pay more, in which case the storage time will go up proportionally.
+ annual_fee: Amount;
+
+ // Payment required to upload truth. To be paid per upload.
+ truth_upload_fee: Amount;
+
+ // How long until the service expires deposited truth
+ // (unless refreshed via another POST)?
+ truth_lifetime: RelativeTime;
+
+ // Limit on the liability that the provider is offering with
+ // respect to the services provided.
+ liability_limit: Amount;
+
+ // Salt value with 128 bits of entropy.
+ // Different providers
+ // will use different high-entropy salt values. The resulting
+ // **provider salt** is then used in various operations to ensure
+ // cryptographic operations differ by provider. A provider must
+ // never change its salt value.
+ server_salt: string;
+
+@}
+@end example
+@anchor{anastasis authorizationmethodconfig}@anchor{11}
+@example
+interface AuthorizationMethodConfig @{
+ // Name of the authorization method.
+ type: string;
+
+ // Fee for accessing key share using this method.
+ cost: Amount;
+
+@}
+@end example
+@end deffn
+
+@node Receiving Terms of Service,Manage policy,Receiving Configuration,Anastasis REST API
+@anchor{anastasis receiving-terms-of-service}@anchor{12}@anchor{anastasis terms}@anchor{13}
+@section Receiving Terms of Service
+
+
+@anchor{anastasis get--terms}@anchor{14}
+@deffn {HTTP Get} GET /terms
+
+Obtain the terms of service provided by the escrow provider.
+
+@strong{Response:}
+
+Returns the terms of service of the provider, in the best language
+and format available based on the client's request.
+@end deffn
+
+@anchor{anastasis get--privacy}@anchor{15}
+@deffn {HTTP Get} GET /privacy
+
+Obtain the privacy policy of the service provided by the escrow provider.
+
+@strong{Response:}
+
+Returns the privacy policy of the provider, in the best language
+and format available based on the client's request.
+@end deffn
+
+@node Manage policy,Managing truth,Receiving Terms of Service,Anastasis REST API
+@anchor{anastasis id2}@anchor{16}@anchor{anastasis manage-policy}@anchor{17}
+@section Manage policy
+
+
+This API is used by the Anastasis client to deposit or request encrypted
+recovery documents with the escrow provider. Generally, a client will deposit
+the same encrypted recovery document with each escrow provider, but provide
+a different truth to each escrow provider.
+
+Operations by the client are identified and authorized by @code{$ACCOUNT_PUB}, which
+should be kept secret from third parties. @code{$ACCOUNT_PUB} should be an account
+public key using the Crockford base32-encoding.
+
+In the following, UUID is always defined and used according to RFC 4122@footnote{https://tools.ietf.org/html/rfc4122}.
+
+@anchor{anastasis get--policy-$ACCOUNT_PUB[?version=$NUMBER]}@anchor{18}
+@deffn {HTTP Get} GET /policy/$ACCOUNT_PUB[?version=$NUMBER]
+
+Get the customer's encrypted recovery document. If @code{version}
+is not specified, the server returns the latest available version. If
+@code{version} is specified, returns the policy with the respective
+@code{version}. The response must begin with the nonce and
+an AES-GCM tag and continue with the ciphertext. Once decrypted, the
+plaintext is expected to contain:
+
+
+@itemize *
+
+@item
+the escrow policy
+
+@item
+the separately encrypted master public key
+@end itemize
+
+Note that the key shares required to decrypt the master public key are
+not included, as for this the client needs to obtain authorization.
+The policy does provide sufficient information for the client to determine
+how to authorize requests for @strong{truth}.
+
+The client MAY provide an @code{If-None-Match} header with an Etag.
+In that case, the server MUST additionally respond with an @code{304} status
+code in case the resource matches the provided Etag.
+
+@strong{Response}:
+
+
+@table @asis
+
+@item 200 OK@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1}:
+
+The escrow provider responds with an @ref{19,,EncryptedRecoveryDocument} object.
+
+@item 304 Not modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}:
+
+The client requested the same resource it already knows.
+
+@item 400 Bad request@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}:
+
+The @code{$ACCOUNT_PUB} is not an EdDSA public key.
+
+@item 402 Payment Required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
+
+The account's balance is too low for the specified operation.
+See the Taler payment protocol specification for how to pay.
+
+@item 403 Forbidden@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4}:
+
+The required account signature was invalid.
+
+@item 404 Not found@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5}:
+
+The requested resource was not found.
+@end table
+
+@emph{Anastasis-Version}: $NUMBER --- The server must return actual version of the encrypted recovery document via this header.
+If the client specified a version number in the header of the request, the server must return that version. If the client
+did not specify a version in the request, the server returns latest version of the @ref{19,,EncryptedRecoveryDocument}.
+
+@emph{Etag}: Set by the server to the Base32-encoded SHA512 hash of the body. Used for caching and to prevent redundancies. The server MUST send the Etag if the status code is @code{200 OK}.
+
+@emph{If-None-Match}: If this is not the very first request of the client, this contains the Etag-value which the client has received before from the server.
+The client SHOULD send this header with every request (except for the first request) to avoid unnecessary downloads.
+
+@emph{Anastasis-Account-Signature}: The client must provide Base-32 encoded EdDSA signature over hash of body with @code{$ACCOUNT_PRIV}, affirming desire to download the requested encrypted recovery document. The purpose used MUST be @code{TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD} (1401).
+@end deffn
+
+@anchor{anastasis post--policy-$ACCOUNT_PUB}@anchor{1a}
+@deffn {HTTP Post} POST /policy/$ACCOUNT_PUB
+
+Upload a new version of the customer's encrypted recovery document.
+While the document's structure is described in JSON below, the upload
+should just be the bytestream of the raw data (i.e. 32-byte nonce followed
+by 16-byte tag followed by the encrypted document).
+If the request has been seen before, the server should do nothing, and otherwise store the new version.
+The body must begin with a nonce, an AES-GCM tag and continue with the ciphertext. The format
+is the same as specified for the response of the GET method. The
+Anastasis server cannot fully validate the format, but MAY impose
+minimum and maximum size limits.
+
+@strong{Request}:
+
+@*Query Parameters:
+
+@itemize *
+
+@item
+@code{pay} -- Optional argument, any non-empty value will do,
+suggested is @code{y} for @code{yes}.
+The client insists on making a payment for the respective
+account, even if this is not yet required. The server
+will respond with a @code{402 Payment required}, but only
+if the rest of the request is well-formed (account
+signature must match). Clients that do not actually
+intend to make a new upload but that only want to pay
+may attempt to upload the latest backup again, as this
+option will be checked before the @code{304 Not modified}
+case.
+
+@item
+@code{timeout_ms=NUMBER} -- @emph{Optional.} If specified, the Anastasis server will
+wait up to @code{timeout_ms} milliseconds for completion of the payment before
+sending the HTTP response. A client must never rely on this behavior, as the
+backend may return a response immediately.
+@end itemize
+
+
+@emph{If-None-Match}: This header MUST be present and set to the SHA512 hash (Etag) of the body by the client.
+The client SHOULD also set the @code{Expect: 100-Continue} header and wait for @code{100 continue}
+before uploading the body. The server MUST
+use the Etag to check whether it already knows the encrypted recovery document that is about to be uploaded.
+The server MUST refuse the upload with a @code{304} status code if the Etag matches
+the latest version already known to the server.
+
+@emph{Anastasis-Policy-Signature}: The client must provide Base-32 encoded EdDSA signature over hash of body with @code{$ACCOUNT_PRIV}, affirming desire to upload an encrypted recovery document.
+
+@emph{Payment-Identifier}: Base-32 encoded 32-byte payment identifier that was included in a previous payment (see @code{402} status code). Used to allow the server to check that the client paid for the upload (to protect the server against DoS attacks) and that the client knows a real secret of financial value (as the @strong{kdf_id} might be known to an attacker). If this header is missing in the client's request (or the associated payment has exceeded the upload limit), the server must return a @code{402} response. When making payments, the server must include a fresh, randomly-generated payment-identifier in the payment request.
+
+@strong{Response}:
+
+
+@table @asis
+
+@item 204 No content@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5}:
+
+The encrypted recovery document was accepted and stored. @code{Anastasis-Version} and @code{Anastasis-UUID} headers
+indicate what version and UUID was assigned to this encrypted recovery document upload by the server.
+
+@item 304 Not modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}:
+
+The same encrypted recovery document was previously accepted and stored. @code{Anastasis-Version} header
+indicates what version was previously assigned to this encrypted recovery document.
+
+@item 400 Bad request@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}:
+
+The @code{$ACCOUNT_PUB} is not an EdDSA public key or mandatory headers are missing.
+The response body MUST elaborate on the error using a Taler error code in the typical JSON encoding.
+
+@item 402 Payment required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
+
+The account's balance is too low for the specified operation.
+See the Taler payment protocol specification for how to pay.
+The response body MAY provide alternative means for payment.
+
+@item 403 Forbidden@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4}:
+
+The required account signature was invalid. The response body may elaborate on the error.
+
+@item 413 Request entity too large@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.14}:
+
+The upload is too large @emph{or} too small. The response body may elaborate on the error.
+@end table
+
+@strong{Details:}
+@anchor{anastasis encryptedrecoverydocument}@anchor{19}
+@example
+interface EncryptedRecoveryDocument @{
+ // Nonce used to compute the (iv,key) pair for encryption of the
+ // encrypted_compressed_recovery_document.
+ nonce: [32]; //bytearray
+
+ // Authentication tag.
+ aes_gcm_tag: [16]; //bytearray
+
+ // Variable-size encrypted recovery document. After decryption,
+ // this contains a gzip compressed JSON-encoded `RecoveryDocument`.
+ // The nonce of the HKDF for this encryption must include the
+ // string "ERD".
+ encrypted_compressed_recovery_document: []; //bytearray of undefined length
+
+@}
+@end example
+@anchor{anastasis recoverydocument}@anchor{1b}
+@example
+interface RecoveryDocument @{
+ // Account identifier at backup provider, AES-encrypted with
+ // the (symmetric) master_key, i.e. an URL
+ // https://sync.taler.net/$BACKUP_ID and
+ // a private key to decrypt the backup. Anastasis is oblivious
+ // to the details of how this is ultimately encoded.
+ backup_account: []; //bytearray of undefined length
+
+ // List of escrow providers and selected authentication method.
+ methods: EscrowMethod[];
+
+ // List of possible decryption policies.
+ policy: DecryptionPolicy[];
+
+@}
+@end example
+@anchor{anastasis escrowmethod}@anchor{1c}
+@example
+interface EscrowMethod @{
+ // URL of the escrow provider (including possibly this Anastasis server).
+ provider_url : string;
+
+ // Type of the escrow method (e.g. security question, SMS etc.).
+ escrow_type: string;
+
+ // UUID of the escrow method (see /truth/ API below).
+ uuid: string;
+
+ // Key used to encrypt the `Truth` this `EscrowMethod` is related to.
+ // Client has to provide this key to the server when using `@w{`}/truth/`@w{`}.
+ truth_encryption_key: [32]; //bytearray
+
+ // Salt used to encrypt the truth on the Anastasis server.
+ truth_salt: [32]; //bytearray
+
+ // The challenge to give to the user (i.e. the security question
+ // if this is challenge-response).
+ // (Q: as string in base32 encoding?)
+ // (Q: what is the mime-type of this value?)
+ //
+ // For some methods, this value may be absent.
+ //
+ // The plaintext challenge is not revealed to the
+ // Anastasis server.
+ challenge: []; //bytearray of undefined length
+
+@}
+@end example
+@anchor{anastasis decryptionpolicy}@anchor{1d}
+@example
+interface DecryptionPolicy @{
+ // Salt included to encrypt master key share when
+ // using this decryption policy.
+ policy_salt: [32]; //bytearray
+
+ // Master key, AES-encrypted with key derived from
+ // salt and keyshares revealed by the following list of
+ // escrow methods identified by UUID.
+ encrypted_master_key: [32]; //bytearray
+
+ // List of escrow methods identified by their UUID.
+ uuid: string[];
+
+@}
+@end example
+@end deffn
+
+@node Managing truth,,Manage policy,Anastasis REST API
+@anchor{anastasis managing-truth}@anchor{1e}@anchor{anastasis truth}@anchor{1f}
+@section Managing truth
+
+
+This API is used by the Anastasis client to deposit @strong{truth} or request a (encrypted) @strong{key share} with
+the escrow provider.
+
+An @strong{escrow method} specifies an Anastasis provider and how the user should
+authorize themself. The @strong{truth} API allows the user to provide the
+(encrypted) key share to the respective escrow provider, as well as auxiliary
+data required for such a respective escrow method.
+
+An Anastasis-server may store truth for free for a certain time period, or
+charge per truth operation using GNU Taler.
+
+@anchor{anastasis post--truth-$UUID}@anchor{20}
+@deffn {HTTP Post} POST /truth/$UUID
+
+Upload a @ref{21,,TruthUploadRequest}-Object according to the policy the client created before (see @ref{1b,,RecoveryDocument}).
+If request has been seen before, the server should do nothing, and otherwise store the new object.
+
+@strong{Request:}
+
+@*Query Parameters:
+
+@itemize *
+
+@item
+@code{timeout_ms=NUMBER} -- @emph{Optional.} If specified, the Anastasis server will
+wait up to @code{timeout_ms} milliseconds for completion of the payment before
+sending the HTTP response. A client must never rely on this behavior, as the
+backend may return a response immediately.
+@end itemize
+
+
+@strong{Response:}
+
+
+@table @asis
+
+@item 204 No content@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5}:
+
+Truth stored successfully.
+
+@item 304 Not modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}:
+
+The same truth was previously accepted and stored under this UUID. The
+Anastasis server must still update the expiration time for the truth when returning
+this response code.
+
+@item 402 Payment required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
+
+This server requires payment to store truth per item.
+See the Taler payment protocol specification for how to pay.
+The response body MAY provide alternative means for payment.
+
+@item 409 Conflict@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10}:
+
+The server already has some truth stored under this UUID. The client should check that it
+is generating UUIDs with enough entropy.
+
+@item 412 Precondition failed@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.13}:
+
+The selected authentication method is not supported on this provider.
+@end table
+
+@strong{Details:}
+@anchor{anastasis truthuploadrequest}@anchor{21}
+@example
+interface TruthUploadRequest @{
+ // Contains the information of an interface `EncryptedKeyShare`, but simply
+ // as one binary block (in Crockford Base32 encoding for JSON).
+ key_share_data: []; //bytearray
+
+ // Key share method, i.e. "security question", "SMS", "e-mail", ...
+ type: string;
+
+ // Nonce used to compute the (iv,key) pair for encryption of the
+ // encrypted_truth.
+ nonce: [32]; //bytearray
+
+ // Authentication tag of `@w{`}encrypted_truth`@w{`}.
+ aes_gcm_tag: [16]; //bytearray
+
+ // Variable-size truth. After decryption,
+ // this contains the ground truth, i.e. H(challenge answer),
+ // phone number, e-mail address, picture, fingerprint, ...
+ // **base32 encoded**.
+ //
+ // The nonce of the HKDF for this encryption must include the
+ // string "ECT".
+ encrypted_truth: [80]; //bytearray
+
+ // MIME type of truth, i.e. text/ascii, image/jpeg, etc.
+ truth_mime: string;
+
+@}
+@end example
+@end deffn
+
+@anchor{anastasis get--truth-$UUID[?response=$H_RESPONSE]}@anchor{22}
+@deffn {HTTP Get} GET /truth/$UUID[?response=$H_RESPONSE]
+
+Get the stored encrypted key share. If @code{$H_RESPONSE} is specified by the client, the server checks
+if @code{$H_RESPONSE} matches the expected response specified before within the @ref{21,,TruthUploadRequest} (see @code{encrypted_truth}).
+Also, the user has to provide the correct @emph{truth_encryption_key} with every get request (see below).
+When @code{$H_RESPONSE} is correct, the server responds with the encrypted key share.
+The encrypted key share is returned simply as a byte array and not in JSON format.
+
+@strong{Response}:
+
+
+@table @asis
+
+@item 200 OK@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1}:
+
+@ref{23,,EncryptedKeyShare} is returned in body (in binary).
+
+@item 202 Accepted@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.3}:
+
+The escrow provider will respond out-of-band (i.e. SMS).
+The body may contain human-readable instructions on next steps.
+
+@item >>208 Already Reported<<:
+
+An authentication challenge was recently send, client should
+simply respond to the pending challenge.
+
+@item 303 See other@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4}:
+
+The provider redirects for authentication (i.e. video identification/WebRTC).
+If the client is not a browser, it should launch a browser at the URL
+given in the @code{Location} header and allow the user to re-try the operation
+after successful authorization.
+
+@item 402 Payment required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
+
+The service requires payment for access to truth.
+See the Taler payment protocol specification for how to pay.
+The response body MAY provide alternative means for payment.
+
+@item 403 Forbidden@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4}:
+
+The server requires a valid "response" to the challenge associated with the UUID.
+
+@item 404 Not found@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5}:
+
+The server does not know any truth under the given UUID.
+
+@item 410 Gone@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.11}:
+
+The server has not (recently) issued a challenge under the given UUID,
+but a reply was provided. (This does not apply for secure question.)
+
+@item 417 Expectation Failed@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.18}:
+
+The decrypted @code{truth} does not match the expectations of the authentication
+backend, i.e. a phone number for sending an SMS is not a number, or
+an e-mail address for sending an E-mail is not a valid e-mail address.
+
+@item 503 Service Unavailable@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4}:
+
+Server is out of Service.
+@end table
+
+@emph{Truth-Decryption-Key}: Key used to encrypt the @strong{truth} (see encrypted_truth within @ref{21,,TruthUploadRequest}) and which has to provided by the user. The key is stored with
+the according @ref{1c,,EscrowMethod}. The server needs this key to get the info out of @ref{21,,TruthUploadRequest} needed to verify the @code{$RESPONSE}.
+
+@strong{Details:}
+@anchor{anastasis encryptedkeyshare}@anchor{23}
+@example
+interface EncryptedKeyShare @{
+ // Nonce used to compute the decryption (iv,key) pair.
+ nonce_i: [32]; //bytearray
+
+ // Authentication tag.
+ aes_gcm_tag_i: [16]; //bytearray
+
+ // Encrypted key-share in base32 encoding.
+ // After decryption, this yields a `KeyShare`. Note that
+ // the `KeyShare` MUST be encoded as a fixed-size binary
+ // block (instead of in JSON encoding).
+ //
+ // HKDF for the key generation must include the
+ // string "eks" as salt.
+ // Depending on the method,
+ // the HKDF may additionally include
+ // bits from the response (i.e. some hash over the
+ // answer to the security question).
+ encrypted_key_share_i: [32]; //bytearray
+
+@}
+@end example
+@anchor{anastasis keyshare}@anchor{24}
+@example
+interface KeyShare @{
+ // Key material to concatenate with policy_salt and KDF to derive
+ // the key to decrypt the master key.
+ key_share: [32]; //bytearray
+
+ // Signature over method, UUID, and `@w{`}key_share`@w{`}.
+ account_sig: EddsaSignature;
+
+@}
+@end example
+@end deffn
+
+@node Anastasis Reducer API,Authentication Methods,Anastasis REST API,Top
+@anchor{anastasis anastasis-reducer-api}@anchor{25}
+@chapter Anastasis Reducer API
+
+
+This section describes the Anastasis Reducer API which is used by client applications
+to store or load the different states the client application can have.
+The reducer takes a @ref{26,,state} in JSON syntax and returns the new state in JSON syntax.
+
+For example a @strong{state} may take the following structure:
+
+@example
+@{
+ "backup_state": "CONTINENT_SELECTING",
+ "continents": [
+ "Europe",
+ "North_America"
+ ]
+@}
+@end example
+
+The new state depends on the previous one and on the transition @ref{27,,action} with its
+arguments given to the reducer. A @strong{transition argument} also is a statement in JSON syntax:
+
+@example
+@{
+ "continent": "Europe"
+@}
+@end example
+
+The new state returned by the reducer with the state and transition argument defined
+above would look like following for the transition @ref{27,,action} @code{select_continent}:
+
+@example
+@{
+ "backup_state": "COUNTRY_SELECTING",
+ "continents": [
+ "Europe",
+ "North_America"
+ ],
+ "selected_continent": "Europe",
+ "countries": [
+ @{
+ "code": "ch",
+ "name": "Switzerland",
+ "continent": "Europe",
+ "name_i18n": @{
+ "de_DE": "Schweiz",
+ "de_CH": "Schwiiz",
+ "fr": "Suisse",
+ "en": "Swiss"
+ @},
+ "currency": "CHF"
+ @},
+ @{
+ "code": "de",
+ "name": "Germany",
+ "continent": "Europe",
+ "continent_i18n": @{
+ "de": "Europa"
+ @},
+ "name_i18n": @{
+ "de_DE": "Deutschland",
+ "de_CH": "Deutschland",
+ "fr": "Allemagne",
+ "en": "Germany"
+ @},
+ "currency": "EUR"
+ @}
+ ]
+@}
+@end example
+
+@menu
+* States::
+* Backup Reducer::
+* Recovery Reducer::
+* Reducer transitions::
+
+@end menu
+
+@node States,Backup Reducer,,Anastasis Reducer API
+@anchor{anastasis states}@anchor{28}
+@section States
+
+
+Overall, the reducer knows the following states:
+
+@quotation
+
+
+@itemize -
+
+@item
+
+@table @asis
+
+@item @strong{ERROR}: The transition led to an error. No further transitions are possible from
+
+this state, but the client may want to continue from a previous state.
+@end table
+
+@item
+
+@table @asis
+
+@item @strong{CONTINENT_SELECTING}: The user should specify the continent where they are living,
+
+so that we can show a list of countries to choose from.
+@end table
+
+@item
+
+@table @asis
+
+@item @strong{COUNTRY_SELECTING}: The user should specify the country where they are living,
+
+so that we can determine appropriate attributes, currencies and Anastasis
+providers.
+@end table
+
+@item
+
+@table @asis
+
+@item @strong{USER_ATTRIBUTES_COLLECTING}: The user should provide the country-specific personal
+
+attributes.
+@end table
+
+@item
+
+@table @asis
+
+@item @strong{AUTHENTICATIONS_EDITING}: The user should add authentication methods to be used
+
+during recovery.
+@end table
+
+@item
+@strong{POLICIES_REVIEWING}: The user should review the recovery policies.
+
+@item
+@strong{SECRET_EDITING}: The user should edit the secret to be backed up.
+
+@item
+
+@table @asis
+
+@item @strong{TRUTHS_PAYING}: The user needs to pay for one or more uploads of data associated
+
+with an authentication method.
+@end table
+
+@item
+@strong{POLICIES_PAYING}: The user needs to pay for storing the recovery policy document.
+
+@item
+@strong{BACKUP_FINISHED}: A backup has been successfully generated.
+
+@item
+
+@table @asis
+
+@item @strong{CHALLENGE_SELECTING}: The user needs to select an authorization challenge to
+
+proceed with recovery.
+@end table
+
+@item
+@strong{CHALLENGE_PAYING}: The user needs to pay to proceed with the authorization challenge.
+
+@item
+@strong{CHALLENGE_SOLVING}: The user needs to solve the authorization challenge.
+
+@item
+@strong{RECOVERY_FINISHED}: The secret of the user has been recovered.
+@end itemize
+@end quotation
+
+State names:
+
+@quotation
+
+
+@itemize -
+
+@item
+In SELECTING-states, the user has to choose one value out of a predefined set of values (for example a continent out of a set of continents).
+
+@item
+In COLLECTING-states, the user has to give certain values.
+
+@item
+In EDITING-states, the user is free to choose which values he wants to give.
+
+@item
+In REVEIWING-states, the user may make a few choices, but primarily is expected to affirm something.
+
+@item
+in PAYING-states, the user must make a payment.
+
+@item
+in FINISHED-states, the operation has definitively concluded.
+@end itemize
+@end quotation
+
+@node Backup Reducer,Recovery Reducer,States,Anastasis Reducer API
+@anchor{anastasis backup-reducer}@anchor{29}
+@section Backup Reducer
+
+@anchor{anastasis state}@anchor{26}@anchor{anastasis action}@anchor{27}
+
+@float Figure
+
+@image{anastasis-figures/anastasis_reducer_backup,,,fig-anastasis_reducer_backup,png}
+
+@caption{Backup states and their transitions.}
+
+@end float
+
+
+The illustration above shows the different states the reducer can have during a backup
+process.
+
+@node Recovery Reducer,Reducer transitions,Backup Reducer,Anastasis Reducer API
+@anchor{anastasis recovery-reducer}@anchor{2a}
+@section Recovery Reducer
+
+
+
+@float Figure
+
+@image{anastasis-figures/anastasis_reducer_recovery,,,fig-anastasis_reducer_recovery,png}
+
+@caption{Recovery states and their transitions.}
+
+@end float
+
+
+The illustration above shows the different states the reducer can have during a recovery
+process.
+
+@node Reducer transitions,,Recovery Reducer,Anastasis Reducer API
+@anchor{anastasis reducer-transitions}@anchor{2b}
+@section Reducer transitions
+
+
+In the following, the individual transitions will be specified in more detail.
+Note that we only show fields added by the reducer, typically the previous
+state is preserved to enable "back" transitions to function smoothly.
+
+@menu
+* Initial state::
+* Common transitions::
+* Backup transitions::
+* Recovery transitions::
+
+@end menu
+
+@node Initial state,Common transitions,,Reducer transitions
+@anchor{anastasis initial-state}@anchor{2c}
+@subsection Initial state
+
+
+The initial states for backup and recovery processes are:
+
+@strong{Initial backup state:}
+
+@example
+@{
+ "backup_state": "CONTINENT_SELECTING",
+ "continents": [
+ "Europe",
+ "North America"
+ ]
+@}
+@end example
+
+@strong{Initial recovery state:}
+
+@example
+@{
+ "recovery_state": "CONTINENT_SELECTING",
+ "continents": [
+ "Europe",
+ "North America"
+ ]
+@}
+@end example
+
+Here, "continents" is an array of English strings with the names of the
+continents which contain countries for which Anastasis could function (based
+on having providers that are known to operate and rules being provided for
+user attributes from those countries).
+
+For internationalization, another field @code{continents_i18n} may be present.
+This field would be a map of language names to arrays of translated
+continent names:
+
+@example
+@{
+ "recovery_state": "CONTINENT_SELECTING",
+ "continents": [
+ "Europe",
+ "North America"
+ ]
+ "continents_i18n":
+ @{
+ "de_DE" : [
+ "Europa",
+ "Nordamerika"
+ ],
+ "de_CH" : [
+ "Europa",
+ "Nordamerika"
+ ]
+ @}
+@}
+@end example
+
+Translations must be given in the same order as the main English array.
+
+@node Common transitions,Backup transitions,Initial state,Reducer transitions
+@anchor{anastasis common-transitions}@anchor{2d}
+@subsection Common transitions
+
+
+@strong{select_continent:}
+
+Here the user specifies the continent they live on. Arguments (example):
+
+@example
+@{
+ "continent": "Europe"
+@}
+@end example
+
+The continent must be given using the English name from the @code{continents} array.
+Using a translated continent name is invalid and may result in failure.
+
+The reducer returns an updated state with a list of countries to choose from,
+for example:
+
+@example
+@{
+ "backup_state": "COUNTRY_SELECTING",
+ "selected_continent": "Europe",
+ "countries": [
+ @{
+ "code": "ch",
+ "name": "Switzerland",
+ "continent": "Europe",
+ "name_i18n": @{
+ "de_DE": "Schweiz",
+ "de_CH": "Schwiiz",
+ "fr": "Suisse",
+ "en": "Swiss"
+ @},
+ "currency": "CHF"
+ @},
+ @{
+ "code": "de",
+ "name": "Germany",
+ "continent": "Europe",
+ "continent_i18n": @{
+ "de": "Europa"
+ @},
+ "name_i18n": @{
+ "de_DE": "Deutschland",
+ "de_CH": "Deutschland",
+ "fr": "Allemagne",
+ "en": "Germany"
+ @},
+ "currency": "EUR"
+ @}
+ ]
+@}
+@end example
+
+Here @code{countries} is an array of countries on the @code{selected_continent}. For
+each country, the @code{code} is the ISO 3166-1 alpha-2 country code. The
+@code{continent} is only present because some countries span continents, the
+information is redundant and will always match @code{selected_continent}. The
+@code{name} is the name of the country in English, internationalizations of the
+name may be provided in @code{name_i18n}. The @code{currency} is @strong{an} official
+currency of the country, if a country has multiple currencies, it may appear
+multiple times in the list. In this case, the user should select the entry
+with the currency they intend to pay with. It is also possible for users
+to select a currency that does not match their country, but user interfaces
+should by default try to use currencies that match the user's residence.
+
+@strong{select_country:}
+
+Selects the country (via the country code) and specifies the currency.
+The latter is needed as some countries have more than one currency,
+and some use-cases may also involve users insisting on paying with
+foreign currency.
+
+Arguments (example):
+
+@example
+@{
+ "country_code": "de",
+ "currency": "EUR"
+@}
+@end example
+
+The @code{country_code} must be an ISO 3166-1 alpha-2 country code from
+the array of @code{countries} of the reducer's state. The @code{currency}
+field must be a valid currency accepted by the Taler payment system.
+
+The reducer returns a new state with the list of attributes the
+user is expected to provide, as well as possible authentication
+providers that accept payments in the selected currency:
+
+@example
+@{
+ "backup_state": "USER_ATTRIBUTES_COLLECTING",
+ "selected_country": "de",
+ "currency": "EUR",
+ "required_attributes": [
+ @{
+ "type": "string",
+ "name": "full_name",
+ "label": "Full name",
+ "label_i18n": @{
+ "de_DE": "Vollstaendiger Name",
+ "de_CH": "Vollstaendiger. Name",
+ "fr": "Nom complet",
+ "en": "Full name"
+ @},
+ "widget": "anastasis_gtk_ia_full_name",
+ "uuid" : "9e8f463f-575f-42cb-85f3-759559997331"
+ @},
+ @{
+ "type": "date",
+ "name": "birthdate",
+ "label": "Birthdate",
+ "label_i18n": @{
+ "de_DE": "Geburtsdatum",
+ "de_CH": "Geburtsdatum",
+ "fr": "Date de naissance",
+ "en": "Birthdate"
+ @},
+ "uuid" : "83d655c7-bdb6-484d-904e-80c1058c8854"
+ "widget": "anastasis_gtk_ia_birthdate"
+ @},
+ @{
+ "type": "string",
+ "name": "tax_number",
+ "label": "Taxpayer identification number",
+ "label_i18n":@{
+ "de_DE": "Steuerliche Identifikationsnummer",
+ "de_CH": "Steuerliche Identifikationsnummer",
+ "en": "German taxpayer identification number"
+ @},
+ "widget": "anastasis_gtk_ia_tax_de",
+ "uuid": "dae48f85-e3ff-47a4-a4a3-ed981ed8c3c6",
+ "validation-regex": "^[0-9]@{11@}$",
+ "validation-logic": "DE_TIN_check"
+ @},
+ @{
+ "type": "string",
+ "name": "social_security_number",
+ "label": "Social security number",
+ "label_i18n": @{
+ "de_DE": "Sozialversicherungsnummer",
+ "de_CH": "Sozialversicherungsnummer",
+ "fr": "Numéro de sécurité sociale",
+ "en": "Social security number"
+ @},
+ "widget": "anastasis_gtk_ia_ssn",
+ "validation-regex": "^[0-9]@{8@}[[:upper:]][0-9]@{3@}$",
+ "validation-logic": "DE_SVN_check"
+ "optional" : true
+ @}
+ ],
+ "authentication_providers": @{
+ "http://localhost:8089/": @{
+ "http_status": 200,
+ "methods": [
+ @{ "type" : "question",
+ "usage_fee" : "EUR:0.0" @},
+ @{ "type" : "sms",
+ "usage_fee" : "EUR:0.5" @}
+ ],
+ "annual_fee": "EUR:4.99",
+ "truth_upload_fee": "EUR:4.99",
+ "liability_limit": "EUR:1",
+ "currency": "EUR",
+ "truth_lifetime": @{ "d_ms" : 50000000 @},
+ "storage_limit_in_megabytes": 1,
+ "provider_name": "Anastasis 4",
+ "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
+ @},
+ "http://localhost:8088/": @{
+ "http_status": 200,
+ "methods": [
+ @{ "type" : "question",
+ "usage_fee" : "EUR:0.01" @},
+ @{ "type" : "sms",
+ "usage_fee" : "EUR:0.55" @}
+ ],
+ "annual_fee": "EUR:0.99",
+ "truth_upload_fee": "EUR:3.99",
+ "liability_limit": "EUR:1",
+ "currency": "EUR",
+ "truth_lifetime": @{ "d_ms" : 50000000 @},
+ "storage_limit_in_megabytes": 1,
+ "provider_name": "Anastasis 4",
+ "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
+ @}
+ @}
+@}
+@end example
+
+The array of @code{required_attributes} contains attributes about the user
+that must be provided includes:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{type}: The type of the attribute, for now only @code{string} and @code{date} are
+supported.
+
+@item
+@strong{name}: The name of the attribute, this is the key under which the
+attribute value must be provided later. The name must be unique per response.
+
+@item
+@strong{label}: A human-readable description of the attribute in English.
+Translated descriptions may be provided under @strong{label_i18n}.
+
+@item
+@strong{uuid}: A UUID that uniquely identifies identical attributes across
+different countries. Useful to preserve values should the user enter
+some attributes, and then switch to another country. Note that
+attributes must not be preserved if they merely have the same @strong{name},
+only the @strong{uuid} will be identical if the semantics is identicial.
+
+@item
+@strong{widget}: An optional name of a widget that is known to nicely render
+the attribute entry in user interfaces where named widgets are
+supported.
+
+@item
+@strong{validation-regex}: An optional extended POSIX regular expression
+that is to be used to validate (string) inputs to ensure they are
+well-formed.
+
+@item
+@strong{validation-logic}: Optional name of a function that should be called
+to validate the input. If the function is not known to the particular
+client, the respective validation can be skipped (at the expense of
+typos by users not being detected, possibly rendering secrets
+irrecoverable).
+
+@item
+@strong{optional}: Optional boolean field that, if @code{true}, indicates that
+this attribute is not actually required but optional and users MAY leave
+it blank in case they do not have the requested information. Used for
+common fields that apply to some large part of the population but are
+not sufficiently universal to be actually required.
+@end itemize
+@end quotation
+
+The authentication providers are listed under a key that is the
+base URL of the service. For each provider, the following
+information is provided if the provider was successfully contacted:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{http_status}: HTTP status code, always @code{200} on success.
+
+@item
+@strong{methods}: Array of authentication methods supported by this
+provider. Includes the @strong{type} of the authentication method
+and the @strong{usage_fee} (how much the user must pay for authorization
+using this method during recovery).
+
+@item
+@strong{annual_fee}: Fee the provider charges to store the recovery
+policy for one year.
+
+@item
+@strong{truth_upload_fee}: Fee the provider charges to store a key share.
+
+@item
+@strong{truth_lifetime}: Taler-style relative time that specifies how
+long the provider will store truth data (key shares) after an upload.
+
+@item
+@strong{liability_limit}: Amount the provider can be held liable for in
+case a key share or recovery document cannot be recovered due to
+provider failures.
+
+@item
+@strong{currency}: Currency in which the provider wants to be paid,
+will match all of the fees.
+
+@item
+@strong{storage_limit_in_megabytes}: Maximum size of an upload (for
+both recovery document and truth data) in megabytes.
+
+@item
+@strong{provider_name}: Human-readable name of the provider's business.
+
+@item
+@strong{salt}: Salt value used by the provider, used to derive the
+user's identity at this provider. Should be unique per provider,
+and must never change for a given provider. The salt is
+base32 encoded.
+@end itemize
+@end quotation
+
+If contacting the provider failed, the information returned is:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{http_status}: HTTP status code (if available, possibly 0 if
+we did not even obtain an HTTP response).
+
+@item
+@strong{error_code}: Taler error code, never 0.
+@end itemize
+@end quotation
+
+@strong{add_provider}:
+
+This operation can be performed in state @code{USER_ATTRIBUTES_COLLECTING}. It
+adds one or more Anastasis providers to the list of providers the reducer
+should henceforth consider. Note that removing providers is not possible at
+this time.
+
+Here, the client must provide an array with the base URLs of the
+providers to add, for example:
+
+@example
+@{
+ "urls": [
+ "http://localhost:8888/",
+ "http://localhost:8089/"
+ ]
+@}
+@end example
+
+Note that existing providers will remain in the state. The following is an
+example for an expected new state where the service on port 8089 is
+unreachable, the service on port 8088 was previously known, and service on
+port 8888 was now added:
+
+@example
+@{
+ "backup_state": "USER_ATTRIBUTES_COLLECTING",
+ "authentication_providers": @{
+ "http://localhost:8089/": @{
+ "error_code": 11,
+ "http_status": 0
+ @},
+ "http://localhost:8088/": @{
+ "http_status": 200,
+ "methods": [
+ @{ "type" : "question",
+ "usage_fee" : "EUR:0.01" @},
+ @{ "type" : "sms",
+ "usage_fee" : "EUR:0.55" @}
+ ],
+ "annual_fee": "EUR:0.99",
+ "truth_upload_fee": "EUR:3.99",
+ "liability_limit": "EUR:1",
+ "currency": "EUR",
+ "truth_lifetime": @{ "d_ms" : 50000000 @},
+ "storage_limit_in_megabytes": 1,
+ "provider_name": "Anastasis 4",
+ "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
+ @}
+ "http://localhost:8888/": @{
+ "methods": [
+ @{ "type" : "question",
+ "usage_fee" : "EUR:0.01" @},
+ @{ "type" : "sms",
+ "usage_fee" : "EUR:0.55" @}
+ ],
+ "annual_fee": "EUR:0.99",
+ "truth_upload_fee": "EUR:3.99",
+ "liability_limit": "EUR:1",
+ "currency": "EUR",
+ "truth_lifetime": @{ "d_ms" : 50000000 @},
+ "storage_limit_in_megabytes": 1,
+ "provider_name": "Anastasis 42",
+ "salt": "BXAPCKSH9D3MYJTS9536RHJHCX"
+ @}
+ @}
+@}
+@end example
+
+@node Backup transitions,Recovery transitions,Common transitions,Reducer transitions
+@anchor{anastasis backup-transitions}@anchor{2e}
+@subsection Backup transitions
+
+
+@strong{enter_user_attributes:}
+
+This transition provides the user's personal attributes. The specific set of
+attributes required depends on the country of residence of the user. Some
+attributes may be optional, in which case they should be omitted entirely
+(that is, not simply be set to @code{null} or an empty string). Example
+arguments would be:
+
+@example
+@{
+ "identity_attributes": @{
+ "full_name": "Max Musterman",
+ "social_security_number": "123456789",
+ "birthdate": "2000-01-01",
+ "birthplace": "Earth"
+ @}
+@}
+@end example
+
+Note that at this stage, the state machines between backup and
+recovery diverge and the @code{recovery_state} will begin to look
+very different from the @code{backup_state}.
+
+For backups, if all required attributes are present, the reducer will
+transition to an @code{AUTHENTICATIONS_EDITING} state with the attributes added
+to it:
+
+@example
+@{
+ "backup_state": "AUTHENTICATIONS_EDITING",
+ "identity_attributes": @{
+ "full_name": "Max Musterman",
+ "social_security_number": "123456789",
+ "birthdate": "2000-01-01",
+ "birthplace": "Earth"
+ @}
+@}
+@end example
+
+If required attributes are missing, do not match the required regular
+expression, or fail the custom validation logic, the reducer SHOULD transition
+to an error state indicating what was wrong about the input. A reducer that
+does not support some specific validation logic MAY accept the invalid input
+and proceed anyway. The error state will include a Taler error code that
+is specific to the failure, and optional details. Example:
+
+@example
+@{
+ "backup_state": "ERROR",
+ "code": 8404,
+ "hint": "An input did not match the regular expression.",
+ "detail": "social_security_number"
+@}
+@end example
+
+Clients may safely repeat this transition to validate the user's inputs
+until they satisfy all of the constraints. This way, the user interface
+does not have to perform the input validation directly.
+
+@strong{add_authentication}:
+
+This transition adds an authentication method. The method must be supported
+by one or more providers that are included in the current state. Adding an
+authentication method requires specifying the @code{type} and @code{instructions} to
+be given to the user. The @code{challenge} is encrypted and stored at the
+Anastasis provider. The specific semantics of the value depend on the
+@code{type}. Typical challenges values are a phone number (to send an SMS to),
+an e-mail address (to send a PIN code to) or the answer to a security
+question. Note that these challenge values will still be encrypted (and
+possibly hashed) before being given to the Anastasis providers.
+
+Note that the @code{challenge} must be given in Crockford Base32 encoding, as it
+MAY include binary data (such as a photograph of the user). In the latter
+case, the optional @code{mime_type} field must be provided to give the MIME type
+of the value encoded in @code{challenge}.
+
+@example
+@{
+ "authentication_method":
+ @{
+ "type": "question",
+ "mime_type" : "text/plain",
+ "instructions" : "What is your favorite GNU package?",
+ "challenge" : "E1QPPS8A",
+ @}
+@}
+@end example
+
+If the information provided is valid, the reducer will add the new
+authentication method to the array of authentication methods:
+
+@example
+@{
+ "backup_state": "AUTHENTICATIONS_EDITING",
+ "authentication_methods": [
+ @{
+ "type": "question",
+ "mime_type" : "text/plain",
+ "instructions" : "What is your favorite GNU package?",
+ "challenge" : "E1QPPS8A",
+ @},
+ @{
+ "type": "email",
+ "instructions" : "E-mail to user@@*le.com",
+ "challenge": "ENSPAWJ0CNW62VBGDHJJWRVFDM50"
+ @}
+ ]
+@}
+@end example
+
+@strong{delete_authentication}:
+
+This transition can be used to remove an authentication method from the
+array of authentication methods. It simply requires the index of the
+authentication method to remove. Note that the array is 0-indexed:
+
+@example
+@{
+ "auth_method_index": 1
+@}
+@end example
+
+Assuming we begin with the state from the example above, this would
+remove the @code{email} authentication method, resulting in the following
+response:
+
+@example
+@{
+ "backup_state": "AUTHENTICATIONS_EDITING",
+ "authentication_methods": [
+ @{
+ "type": "question",
+ "mime_type" : "text/plain",
+ "instructions" : "What is your favorite GNU package?",
+ "challenge" : "gdb",
+ @}
+ ]
+@}
+@end example
+
+If the index is invalid, the reducer will instead
+transition into an @code{ERROR} state.
+
+@strong{next} (from @code{AUTHENTICATIONS_EDITING}):
+
+This transition confirms that the user has finished adding (or removing)
+authentication methods, and that the system should now automatically compute
+a set of reasonable recovery policies.
+
+This transition does not take any mandatory arguments. Optional arguments can
+be provided to upload the recovery document only to a specific subset of the
+providers:
+
+@example
+@{
+ "providers": [
+ "http://localhost:8088/",
+ "http://localhost:8089/"
+ ]
+@}
+@end example
+
+The resulting state provides the suggested recovery policies in a way suitable
+for presentation to the user:
+
+@example
+@{
+ "backup_state": "POLICIES_REVIEWING",
+ "policy_providers" : [
+ @{ "provider_url" : "http://localhost:8088/" @},
+ @{ "provider_url" : "http://localhost:8089/" @}
+ ],
+ "policies": [
+ @{
+ "methods": [
+ @{
+ "authentication_method": 0,
+ "provider": "http://localhost:8088/"
+ @},
+ @{
+ "authentication_method": 1,
+ "provider": "http://localhost:8089/"
+ @},
+ @{
+ "authentication_method": 2,
+ "provider": "http://localhost:8087/"
+ @}
+ ]
+ @},
+ @{
+ "methods": [
+ @{
+ "authentication_method": 0,
+ "provider": "http://localhost:8088/"
+ @},
+ @{
+ "authentication_method": 1,
+ "provider": "http://localhost:8089/"
+ @},
+ @{
+ "authentication_method": 3,
+ "provider": "http://localhost:8089/"
+ @}
+ ]
+ @}
+ ]
+@}
+@end example
+
+For each recovery policy, the state includes the specific details of which
+authentication @code{methods} must be solved to recovery the secret using this
+policy. The @code{methods} array specifies the index of the
+@code{authentication_method} in the @code{authentication_methods} array, as well as
+the provider that was selected to supervise this authentication.
+
+If no authentication method was provided, the reducer will transition into an
+@code{ERROR} state instead of suggesting policies.
+
+@strong{add_policy}:
+
+Using this transition, the user can add an additional recovery policy to the
+state. The argument format is the same that is used in the existing state.
+An example for a possible argument would thus be:
+
+@example
+@{
+ "policy": [
+ @{
+ "auth_method_index": 1,
+ "provider": "http://localhost:8088/"
+ @},
+ @{
+ "auth_method_index": 3,
+ "provider": "http://localhost:8089/"
+ @}
+ ]
+@}
+@end example
+
+Note that the specified providers must already be in the
+@code{authentication_providers} of the state. You cannot add new providers at
+this stage. The reducer will simply attempt to append the suggested policy to
+the "policies" array, returning an updated state:
+
+@example
+@{
+ "backup_state": "POLICIES_REVIEWING",
+ "policies": [
+ @{
+ "methods": [
+ @{
+ "authentication_method": 0,
+ "provider": "http://localhost:8089/"
+ @},
+ @{
+ "authentication_method": 1,
+ "provider": "http://localhost:8088/"
+ @}
+ ]
+ @},
+ @{
+ "methods": [
+ @{
+ "authentication_method": 0,
+ "provider": "http://localhost:8089/"
+ @},
+ @{
+ "authentication_method": 2,
+ "provider": "http://localhost:8088/"
+ @}
+ ]
+ @},
+ @{
+ "methods": [
+ @{
+ "authentication_method": 1,
+ "provider": "http://localhost:8089/"
+ @},
+ @{
+ "authentication_method": 2,
+ "provider": "http://localhost:8088/"
+ @}
+ ]
+ @},
+ @{
+ "methods": [
+ @{
+ "authentication_method": 1,
+ "provider": "http://localhost:8088/"
+ @},
+ @{
+ "authentication_method": 3,
+ "provider": "http://localhost:8089/"
+ @}
+ ]
+ @}
+ ]
+@}
+@end example
+
+If the new policy is invalid, for example because it adds an unknown
+authentication method, or the selected provider does not support the type of
+authentication, the reducer will transition into an @code{ERROR} state instead of
+adding the new policy.
+
+@strong{delete_policy:}
+
+This transition allows the deletion of a recovery policy. The argument
+simply specifies the index of the policy to delete, for example:
+
+@example
+@{
+ "policy_index": 3
+@}
+@end example
+
+Given as input the state from the example above, the expected new state would
+be:
+
+@example
+@{
+ "backup_state": "POLICIES_REVIEWING",
+ "policies": [
+ @{
+ "methods": [
+ @{
+ "authentication_method": 0,
+ "provider": "http://localhost:8089/"
+ @},
+ @{
+ "authentication_method": 1,
+ "provider": "http://localhost:8088/"
+ @}
+ ]
+ @},
+ @{
+ "methods": [
+ @{
+ "authentication_method": 0,
+ "provider": "http://localhost:8089/"
+ @},
+ @{
+ "authentication_method": 2,
+ "provider": "http://localhost:8088/"
+ @}
+ ]
+ @},
+ @{
+ "methods": [
+ @{
+ "authentication_method": 1,
+ "provider": "http://localhost:8089/"
+ @},
+ @{
+ "authentication_method": 2,
+ "provider": "http://localhost:8088/"
+ @}
+ ]
+ @}
+ ]
+@}
+@end example
+
+If the index given is invalid, the reducer will transition into an @code{ERROR} state
+instead of deleting a policy.
+
+@strong{next} (from @code{POLICIES_REVIEWING}):
+
+Using this transition, the user confirms that the policies in the current
+state are acceptable. The transition does not take any arguments.
+
+The reducer will simply transition to the @code{SECRET_EDITING} state:
+
+@example
+@{
+ "backup_state": "SECRET_EDITING",
+@}
+@end example
+
+If the array of @code{policies} is currently empty, the reducer will transition
+into an @code{ERROR} state instead of allowing the user to continue.
+
+@strong{enter_secret:}
+
+This transition provides the reducer with the actual core @code{secret} of the user
+that Anastasis is supposed to backup (and possibly recover). The argument is
+simply the Crockford-Base32 encoded @code{value} together with its @code{mime} type,
+for example:
+
+@example
+@{
+ "secret": @{
+ "value": "EDJP6WK5EG50",
+ "mime" : "text/plain"
+ @}
+@}
+@end example
+
+If the application is unaware of the format, it set the @code{mime} field to @code{null}.
+
+After adding a secret, the reducer may transition into different states
+depending on whether payment(s) are necessary. If payments are needed, the
+@code{secret} will be stored in the state under @code{core_secret}. Applications
+should be careful when persisting the resulting state, as the @code{core_secret}
+is not protected in the @code{PAYING} states. The @code{PAYING} states only differ
+in terms of what the payments are for (key shares or the recovery document),
+in all cases the state simply includes an array of Taler URIs that refer to
+payments that need to be made with the Taler wallet.
+
+If all payments are complete, the reducer will transition into the
+@code{BACKUP_FINISHED} state and (if applicable) delete the @code{core_secret} as an
+additional safety measure.
+
+Example results are thus:
+
+@example
+@{
+ "backup_state": "TRUTHS_PAYING",
+ "core_secret" : "DATA",
+ "payments": [
+ "taler://pay/...",
+ "taler://pay/..."
+ ]
+@}
+@end example
+
+@example
+@{
+ "backup_state": "POLICIES_PAYING",
+ "core_secret" : "DATA",
+ "payments": [
+ "taler://pay/...",
+ "taler://pay/..."
+ ]
+@}
+@end example
+
+@example
+@{
+ "backup_state": "BACKUP_FINISHED",
+@}
+@end example
+
+@strong{pay:}
+
+This transition suggests to the reducer that a payment may have been made or
+is immanent, and that the reducer should check with the Anastasis service
+provider to see if the operation is now possible. The operation takes one
+optional argument, which is a @code{timeout} value that specifies how long the
+reducer may wait (in long polling) for the payment to complete:
+
+@example
+@{
+ "timeout": @{ "d_ms" : 5000 @},
+@}
+@end example
+
+The specified timeout is passed on to the Anastasis service provider(s), which
+will wait this long before giving up. If no timeout is given, the check is
+done as quickly as possible without additional delays. The reducer will continue
+to either an updated state with the remaining payment requests, to the
+@code{BACKUP_FINISHED} state (if all payments have been completed and the backup
+finished), or into an @code{ERROR} state in case there was an irrecoverable error,
+indicating the specific provider and how it failed. An example for this
+final error state would be:
+
+@example
+@{
+ "backup_state": "ERROR",
+ "http_status" : 500,
+ "upload_status" : 52,
+ "provider_url" : "https://bad.example.com/",
+@}
+@end example
+
+Here, the fields have the following meaning:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{http_status} is the HTTP status returned by the Anastasis provider.
+
+@item
+@strong{upload_status} is the Taler error code return by the provider.
+
+@item
+@strong{provider_url} is the base URL of the failing provider.
+@end itemize
+@end quotation
+
+In the above example, 52 would thus imply that the Anastasis provider failed to
+store information into its database.
+
+@node Recovery transitions,,Backup transitions,Reducer transitions
+@anchor{anastasis recovery-transitions}@anchor{2f}
+@subsection Recovery transitions
+
+
+@strong{enter_user_attributes:}
+
+This transition provides the user's personal attributes. The specific set of
+attributes required depends on the country of residence of the user. Some
+attributes may be optional, in which case they should be omitted entirely
+(that is, not simply be set to @code{null} or an empty string). The
+arguments are identical to the @strong{enter_user_attributes} transition from
+the backup process. Example arguments would thus be:
+
+@example
+@{
+ "identity_attributes": @{
+ "full_name": "Max Musterman",
+ "social_security_number": "123456789",
+ "birthdate": "2000-01-01",
+ "birthplace": "Earth"
+ @}
+@}
+@end example
+
+However, in contrast to the backup process, the reducer will attempt to
+retrieve the latest recovery document from all known providers for the
+selected currency given the above inputs. If a recovery document was found
+by any provider, the reducer will attempt to load it and transition to
+a state where the user can choose which challenges to satisfy:
+
+@example
+@{
+ "recovery_state": "CHALLENGE_SELECTING",
+ "recovery_information": @{
+ "challenges": [
+ @{
+ "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G",
+ "cost": "TESTKUDOS:0",
+ "type": "question",
+ "instructions": "q1"
+ @},
+ @{
+ "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+ "cost": "TESTKUDOS:0",
+ "type": "email",
+ "instructions": "e-mail address m?il@@f*.bar"
+ @}
+ ],
+ "policies": [
+ [
+ @{
+ "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G"
+ @},
+ @{
+ "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0"
+ @}
+ ]
+ ],
+ "provider_url": "http://localhost:8088/",
+ "version": 1
+ @},
+ "recovery_document": @{
+ ...
+ @}
+@}
+@end example
+
+The @code{recovery_document} is an internal representation of the recovery
+information and of no concern to the user interface. The pertinent information
+is in the @code{recovery_information}. Here, the @code{challenges} array is a list
+of possible challenges the user could attempt to solve next, while @code{policies}
+is an array of policies, with each policy being an array of challenges.
+Satisfying all of the challenges of one of the policies will enable the secret
+to be recovered. The @code{provider_url} from where the recovery document was
+obtained and its @code{version} are also provided. Each challenge comes with
+four mandatory fields:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{uuid}: A unique identifier of the challenge; this is what the
+UUIDs in the policies array refer to, but also this UUID may be
+included in messages sent to the user. They allow the user to
+distinguish different PIN/TANs should say the same phone number be
+used for SMS-authentication with different providers.
+
+@item
+@strong{cost}: This is the amount the Anastasis provider will charge
+to allow the user to pass the challenge.
+
+@item
+@strong{type}: This is the type of the challenge, as a string.
+
+@item
+@strong{instructions}: Contains additional important hints for the user
+to allow the user to satisfy the challenge. It typically includes
+an abbreviated form of the contact information or the security
+question. Details depend on @code{type}.
+@end itemize
+@end quotation
+
+If a recovery document was not found, either the user never performed
+a backup, entered incorrect attributes, or used a provider not yet in
+the list of Anastasis providers. Hence, the user must now either
+select a different provider, or go @code{back} and update the identity
+attributes. In the case a recovery document was not found, the
+transition fails, returning the error code and a human-readable error
+message together with a transition failure:
+
+@example
+@{
+ "recovery_state": "ERROR",
+ "error_message": "account unknown to Anastasis server",
+ "error_code": 9,
+@}
+@end example
+
+Here, the @code{error_code} is from the @code{enum ANASTASIS_RecoveryStatus}
+and describes precisely what failed about the download, while the
+@code{error_message} is a human-readable (English) explanation of the code.
+Applications may want to translate the message using GNU gettext;
+translations should be available in the @code{anastasis} text domain.
+However, in general it should be sufficient to display the slightly
+more generic Taler error code that is returned with the new state.
+
+@strong{change_version:}
+
+Even if a recovery document was found, it is possible that the user
+intended to recover a different version, or recover a backup where
+the recovery document is stored at a different provider. Thus, the
+reducer allows the user to explicitly switch to a different provider
+or recovery document version using the @code{change_version} transition,
+which takes a provider URL and policy version as arguments:
+
+@example
+@{
+ "provider_url": "https://localhost:8080/",
+ "version": 2
+@}
+@end example
+
+Note that using a version of 0 implies fetching "the latest version". The
+resulting states are the same as those of the @code{enter_user_attributes}
+transition, except that the recovery document version is not necessarily the
+latest available version at the provider.
+
+@strong{select_challenge:}
+
+Selecting a challenge takes different, depending on the state of the payment.
+A comprehensive example for @code{select_challenge} would be:
+
+@example
+@{
+ "uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
+ "timeout" : @{ "d_ms" : 5000 @},
+ "payment_secret": "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
+@}
+@end example
+
+The @code{uuid} field is mandatory and specifies the selected challenge.
+The other fields are optional, and are needed in case the user has
+previously been requested to pay for the challenge. In this case,
+the @code{payment_secret} identifies the previous payment request, and
+@code{timeout} says how long the Anastasis service should wait for the
+payment to be completed before giving up (long polling).
+
+Depending on the type of the challenge and the need for payment, the
+reducer may transition into @code{CHALLENGE_SOLVING} or @code{CHALLENGE_PAYING}
+states. In @code{CHALLENGE_SOLVING}, the new state will primarily specify
+the selected challenge:
+
+@example
+@{
+ "backup_state": "CHALLENGE_SOLVING",
+ "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
+@}
+@end example
+
+In @code{CHALLENGE_PAYING}, the new state will include instructions for payment
+in the @code{challenge_feedback}. In general, @code{challenge_feedback} includes
+information about attempted challenges, with the final state being @code{solved}:
+
+@example
+@{
+ "recovery_state": "CHALLENGE_SELECTING",
+ "recovery_information": @{
+ // ...
+ @}
+ "challenge_feedback": @{
+ "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : @{
+ "state" : "solved"
+ @}
+ @}
+@}
+@end example
+
+Challenges feedback for a challenge can have many different @code{state} values
+that applications must all handle. States other than @code{solved} are:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{payment}: Here, the user must pay for a challenge. An example would be:
+
+@example
+@{
+ "backup_state": "CHALLENGE_PAYING",
+ "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30",
+ "challenge_feedback": @{
+ "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : @{
+ "state" : "payment",
+ "taler_pay_uri" : "taler://pay/...",
+ "provider" : "https://localhost:8080/",
+ "payment_secret" : "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
+ @}
+ @}
+@}
+@end example
+@end itemize
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{body}: Here, the server provided an HTTP reply for
+how to solve the challenge, but the reducer could not parse
+them into a known format. A mime-type may be provided and may
+help parse the details.
+
+@example
+@{
+ "recovery_state": "CHALLENGE_SOLVING",
+ "recovery_information": @{
+ // ...
+ @}
+ "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+ "challenge_feedback": @{
+ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+ "state": "body",
+ "body": "CROCKFORDBASE32ENCODEDBODY",
+ "http_status": 403,
+ "mime_type" : "anything/possible"
+ @}
+ @}
+@}
+@end example
+
+@item
+@strong{hint}: Here, the server provided human-readable hint for
+how to solve the challenge. Note that the @code{hint} provided this
+time is from the Anastasis provider and may differ from the @code{instructions}
+for the challenge under @code{recovery_information}:
+
+@example
+@{
+ "recovery_state": "CHALLENGE_SOLVING",
+ "recovery_information": @{
+ // ...
+ @}
+ "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+ "challenge_feedback": @{
+ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+ "state": "hint",
+ "hint": "Recovery TAN send to email mail@@DOMAIN",
+ "http_status": 403
+ @}
+ @}
+@}
+@end example
+
+@item
+@strong{details}: Here, the server provided a detailed JSON status response
+related to solving the challenge:
+
+@example
+@{
+ "recovery_state": "CHALLENGE_SOLVING",
+ "recovery_information": @{
+ // ...
+ @}
+ "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+ "challenge_feedback": @{
+ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+ "state": "details",
+ "details": @{
+ "code": 8111,
+ "hint": "The client's response to the challenge was invalid.",
+ "detail" : null
+ @},
+ "http_status": 403
+ @}
+ @}
+@}
+@end example
+@end itemize
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{redirect}: To solve the challenge, the user must visit the indicated
+Web site at @code{redirect_url}, for example to perform video authentication:
+@end itemize
+
+@quotation
+
+@example
+@{
+ "recovery_state": "CHALLENGE_SOLVING",
+ "recovery_information": @{
+ // ...
+ @}
+ "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+ "challenge_feedback": @{
+ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+ "state": "redirect",
+ "redirect_url": "https://videoconf.example.com/",
+ "http_status": 303
+ @}
+ @}
+@}
+@end example
+
+
+@itemize -
+
+@item
+@strong{server-failure}: This indicates that the Anastasis provider encountered
+a failure and recovery using this challenge cannot proceed at this time.
+Examples for failures might be that the provider is unable to send SMS
+messages at this time due to an outage. The body includes details about
+the failure. The user may try again later or continue with other challenges.
+@end itemize
+
+@example
+@{
+ "recovery_state": "CHALLENGE_SELECTING",
+ "recovery_information": @{
+ // ...
+ @}
+ "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+ "challenge_feedback": @{
+ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+ "state": "server-failure",
+ "http_status": "500",
+ "error_code": 52
+ @}
+ @}
+@}
+@end example
+
+
+@itemize -
+
+@item
+@strong{truth-unknown}: This indicates that the Anastasis provider is unaware of
+the specified challenge. This is typically a permanent failure, and user
+interfaces should not allow users to re-try this challenge.
+@end itemize
+
+@example
+@{
+ "recovery_state": "CHALLENGE_SELECTING",
+ "recovery_information": @{
+ // ...
+ @}
+ "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+ "challenge_feedback": @{
+ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+ "state": "truth-unknown",
+ "error_code": 8108
+ @}
+ @}
+@}
+@end example
+
+
+@itemize -
+
+@item
+@strong{rate-limit-exceeded}:
+@end itemize
+
+@example
+@{
+ "recovery_state": "CHALLENGE_SELECTING",
+ "recovery_information": @{
+ // ...
+ @}
+ "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+ "challenge_feedback": @{
+ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+ "state": "rate-limit-exceeded",
+ "error_code": 8121
+ @}
+ @}
+@}
+@end example
+@end quotation
+@end quotation
+@end quotation
+@end quotation
+
+@strong{pay:}
+
+With a @code{pay} transition, the application indicates to the reducer that
+a payment may have been made. Here, it is again possible to specify an
+optional @code{timeout} argument for long-polling, for example:
+
+@example
+@{
+ "payment_secret": "ABCDADF242525AABASD52525235ABABFDABABANALASDAAKASDAS"
+ "timeout" : @{ "d_ms" : 5000 @},
+@}
+@end example
+
+Depending on the type of the challenge and the result of the operation, the
+new state may be @code{CHALLENGE_SOLVING} (if say the SMS was now sent to the
+user), @code{CHALLENGE_SELECTING} (if the answer to the security question was
+correct), @code{RECOVERY_FINISHED} (if this was the last challenge that needed to
+be solved) or still @code{CHALLENGE_PAYING} (if the challenge was not actually
+paid for). For sample messages, see the different types of
+@code{challenge_feedback} in the section about @code{select_challenge}.
+
+@strong{solve_challenge:}
+
+Solving a challenge takes various formats, depending on the type of the
+challenge and what is known about the answer. The different supported
+formats are:
+
+@example
+@{
+ "answer": "answer to security question"
+@}
+@end example
+
+@example
+@{
+ "pin": 1234
+@}
+@end example
+
+@example
+@{
+ "hash": "SOMEBASE32ENCODEDHASHVALUE"
+@}
+@end example
+
+@node Authentication Methods,,Anastasis Reducer API,Top
+@anchor{anastasis anastasis-auth-methods}@anchor{30}@anchor{anastasis authentication-methods}@anchor{31}
+@chapter Authentication Methods
+
+
+This section describes the supported authentication methods in detail. We
+note that the server implements rate limiting for all authentication methods
+to ensure that malicious strong attackers cannot guess the values by
+brute-force. Typically, a user is given three attempts per hour to enter the
+correct code from 2^63 possible values. Transmitted codes also come with an
+expiration date. If the user re-requests a challenge to be sent, the same
+challenge may be transmitted (with the three attempts counter not increasing!)
+for a limited period of time (depending on the authentication method) before
+the service eventually rotates to a fresh random code with a fresh retry
+counter. Given the default value range and time intervals (which providers are
+at liberty to adjust), brute-force attacks against this are expected to
+succeed with a 50% probability after about 200000 years of attempts at the
+maximum permissible frequency.
+
+@menu
+* SMS (sms): SMS sms.
+* Email verification (email): Email verification email.
+* Video identification (vid): Video identification vid.
+* Security question (qa): Security question qa.
+* Snail mail verification (post): Snail mail verification post.
+
+@end menu
+
+@node SMS sms,Email verification email,,Authentication Methods
+@anchor{anastasis sms-sms}@anchor{32}
+@section SMS (sms)
+
+
+Sends an SMS with a code (prefixed with @code{A-}) to the user's phone, including
+a UUID which identifies the challenge the code is for. The user must send
+this code back with his request (see @code{$RESPONSE} under @ref{1e,,Managing truth}).
+If the transmitted code is correct, the server responses with the requested
+encrypted key share.
+
+@node Email verification email,Video identification vid,SMS sms,Authentication Methods
+@anchor{anastasis email-verification-email}@anchor{33}
+@section Email verification (email)
+
+
+Sends an email with a code (prefixed with @code{A-}) to the user's mail address,
+including a UUID which identifies the challenge the code is for. The user
+must send this code back with his request (see @code{$RESPONSE} under @ref{1e,,Managing truth}). If the transmitted code is correct, the server responses with the
+requested encrypted key share.
+
+@node Video identification vid,Security question qa,Email verification email,Authentication Methods
+@anchor{anastasis video-identification-vid}@anchor{34}
+@section Video identification (vid)
+
+
+Requires the user to identify via video-call. In the video-call, the
+user is told the code (prefixed with @code{A-}) needed to authenticate.
+
+The user is expected to delete all metadata revealing personal information
+from the images before uploading them. Since the respective images must be
+passed on to the video identification service in the event of password
+recovery, it should be ensured that no further information about the user can
+be derived from them.
+
+Video identification will typically result in the Anastasis provider
+requesting the user to be redirected to a Web site (or other URL) for the
+video-call.
+
+@node Security question qa,Snail mail verification post,Video identification vid,Authentication Methods
+@anchor{anastasis security-question-qa}@anchor{35}
+@section Security question (qa)
+
+
+Asks the user a security question. The user sends back a @strong{salted}
+hash over the answer. The @strong{question-salt} is stored encrypted as
+part of the recovery document and never revealed to the providers. This
+ensures that providers cannot derive the answer from the hash value.
+Furthermore, the security question itself is also only in the recovery
+document and never given to the Anastasis provider. A moderately expensive
+hash function is used to further limit strong attackers that have obtained
+the recovery document from brute-forcing the answer.
+
+If the hash value matches with the one the server is expecting, the server
+answers with the requested encrypted key share. However, unlike other
+encrypted key shares, the encrypted key share of a security question uses a
+special variation of the Anastasis encryption: Here, a different hash function
+over the security answer is used to provide an additional @strong{key-salt} for the
+decryption of the (encrypted) @strong{key share}. This ensures that the key share
+remains irrecoverable without the answer even if the Anastasis provider
+storing the security question is malicious.
+
+@node Snail mail verification post,,Security question qa,Authentication Methods
+@anchor{anastasis snail-mail-verification-post}@anchor{36}
+@section Snail mail verification (post)
+
+
+Sends physical mail (snail mail) with a code (prefixed with @code{A-}) to the
+user's mail address, including a UUID which identifies the challenge the code
+is for. The user must send this code back with their request (see
+@code{$RESPONSE} under @ref{1e,,Managing truth}). If the transmitted code is correct,
+the server responds with the requested encrypted key share.
+
+@c %**end of body
+@bye
diff --git a/texinfo/taler-auditor-figures/anastasis-db.png b/texinfo/taler-auditor-figures/anastasis-db.png
new file mode 100644
index 00000000..03eed9da
--- /dev/null
+++ b/texinfo/taler-auditor-figures/anastasis-db.png
Binary files differ
diff --git a/texinfo/taler-auditor-figures/anastasis_challenge_payment.png b/texinfo/taler-auditor-figures/anastasis_challenge_payment.png
new file mode 100644
index 00000000..a0593eba
--- /dev/null
+++ b/texinfo/taler-auditor-figures/anastasis_challenge_payment.png
Binary files differ
diff --git a/texinfo/taler-auditor-figures/anastasis_challengecode.png b/texinfo/taler-auditor-figures/anastasis_challengecode.png
new file mode 100644
index 00000000..fc30f4fe
--- /dev/null
+++ b/texinfo/taler-auditor-figures/anastasis_challengecode.png
Binary files differ
diff --git a/texinfo/taler-auditor-figures/anastasis_reducer_backup.png b/texinfo/taler-auditor-figures/anastasis_reducer_backup.png
new file mode 100644
index 00000000..87b0a9b4
--- /dev/null
+++ b/texinfo/taler-auditor-figures/anastasis_reducer_backup.png
Binary files differ
diff --git a/texinfo/taler-auditor-figures/anastasis_reducer_recovery.png b/texinfo/taler-auditor-figures/anastasis_reducer_recovery.png
new file mode 100644
index 00000000..7d3cc9ae
--- /dev/null
+++ b/texinfo/taler-auditor-figures/anastasis_reducer_recovery.png
Binary files differ
diff --git a/texinfo/taler-auditor-figures/anastasis_truth.png b/texinfo/taler-auditor-figures/anastasis_truth.png
new file mode 100644
index 00000000..7f23fa21
--- /dev/null
+++ b/texinfo/taler-auditor-figures/anastasis_truth.png
Binary files differ
diff --git a/texinfo/taler-auditor-figures/anastasis_truth_payment.png b/texinfo/taler-auditor-figures/anastasis_truth_payment.png
new file mode 100644
index 00000000..70a6b3df
--- /dev/null
+++ b/texinfo/taler-auditor-figures/anastasis_truth_payment.png
Binary files differ
diff --git a/texinfo/taler-auditor.texi b/texinfo/taler-auditor.texi
index 1d769051..442afdb7 100644
--- a/texinfo/taler-auditor.texi
+++ b/texinfo/taler-auditor.texi
@@ -21,11 +21,11 @@
@copying
@quotation
-GNU Taler 0.8.0pre0, Jan 27, 2021
+GNU Taler 0.8.0pre0, Apr 26, 2021
GNU Taler team
-Copyright @copyright{} 2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+Copyright @copyright{} 2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
@end quotation
@end copying
@@ -121,7 +121,7 @@ Operation
Auditor implementation guide
-* The auditor’s database::
+* The auditor's database::
* Invariants checked by the auditor::
* Testing the auditor::
@@ -189,7 +189,7 @@ to other parties.
To perform this duty, you will need at least (read-only) access to the bank
transactions of the exchange, as well as a continuously synchronized replica
-of the exchange’s database. The general assumption for running the auditor
+of the exchange's database. The general assumption for running the auditor
is that this is done on a separate system controlled by the auditor. After
all, the goal is to detect nerfarious activity of the exchange operator,
which cannot be effectively done on a machine controlled by the exchange
@@ -201,9 +201,9 @@ withdrawals made by consumers and income received by merchants. As a result,
the auditor is expected to provide high confidentiality for the database. In
general, the auditor does not have to offer high-availability: the exchange
operator can continue operations without the auditor, and the auditor can
-catch up with it later when the auditor’s systems are restored. However, of
+catch up with it later when the auditor's systems are restored. However, of
course any downtime would provide a window of opportunity for fraud and should
-thus be minimized. Finally, the auditor’s copy of the exchange’s database can
+thus be minimized. Finally, the auditor's copy of the exchange's database can
be useful as a backup to the exchange in case the exchange experiences a loss
of its own copies. Thus, business agreements between auditor and exchanges may
include availability requirements as well.
@@ -211,7 +211,7 @@ include availability requirements as well.
Then, with the software provided, auditors can verify the cryptographic proofs
collected by the exchange and detect if any improper bank transactions have been
made. There are additional tasks which an auditor should perform. While this
-manual only focuses on the audit of the exchange’s database and wire transfers
+manual only focuses on the audit of the exchange's database and wire transfers
with the existing tools, a proper auditor should also perform the following
tasks:
@@ -237,7 +237,7 @@ verification that the exchange properly implements the @code{/link} protocol
@item
verification that the exchange properly reports coins issued during
the refresh protocol (by irregularly refreshing coins withdrawn by
-the auditor and comparing against the exchange’s database — the
+the auditor and comparing against the exchange's database --- the
code required to support this is not yet implemented)
@end itemize
@@ -258,8 +258,8 @@ oversight function.
Auditors should generally be independent third parties that verify that the
exchange operates correctly. However, an exchange is likely to also run the
auditing logic, as it is also used to calculate the exchange’s profits, risk
-and liabilities. Furthermore, it’s usually a good idea to not only rely on
-third parties to verify one’s own work.
+and liabilities. Furthermore, it's usually a good idea to not only rely on
+third parties to verify one's own work.
The Taler software stack for an auditor consists of the following
components:
@@ -291,7 +291,7 @@ the auditor to detect if an exchange is underreporting deposits.
In the future, the Web service should be extended to allow customers and
merchants to automatically upload cryptographic proof of other violations
of the specification by the exchange. However, for now it is assumed that
-the respective cryptographic proofs are reported and verified manually —
+the respective cryptographic proofs are reported and verified manually ---
as with a well-behaved exchange this should obviously be a rare event.
The main binary of this component is the @code{taler-auditor-httpd}.
@@ -311,7 +311,7 @@ needs access to the wire gateway).
The @code{taler-helper-auditor-wire} auditor verifies that the bank
transactions performed by the exchange
were done properly. This component must have access to the bank account
-of the exchange, as well as to a copy of the exchange’s database.
+of the exchange, as well as to a copy of the exchange's database.
The @code{taler-auditor} script invokes the various helpers, each generating
a JSON report. It then invokes the @code{taler-helper-auditor-render.py}
@@ -509,7 +509,7 @@ Sample configuration files for the HTTP reverse proxy can be found in
@chapter Configuration
-The auditor’s configuration works the same way as the configuration of other
+The auditor's configuration works the same way as the configuration of other
Taler components.
This section discusses configuration options related to the auditor.
@@ -657,8 +657,8 @@ option.
The auditor works with one signing key to certify that it is auditing
-a particular exchange’s denomination keys. This key can and should
-be kept @emph{offline} (and backed up adequately). As with the exchange’s
+a particular exchange's denomination keys. This key can and should
+be kept @emph{offline} (and backed up adequately). As with the exchange's
offline key, it is only used for a few cryptographic signatures and
thus the respective code can be run on modest hardware, like a
Raspberry Pi.
@@ -747,14 +747,14 @@ CONFIG = postgres:///auditordemo
If an exchange runs its own auditor, it may use the same database for
the auditor and the exchange itself.
-The @code{taler-auditor-dbinit} tool is used to initialize the auditor’s
+The @code{taler-auditor-dbinit} tool is used to initialize the auditor's
tables. After running this tool, the rights to CREATE or DROP tables
are no longer required and should be removed.
Both the @code{taler-auditor-httpd} and the @code{taler-auditor} (and its helpers)
also need (read-only) access to a (recent, current, synchronized) copy of the
-exchange’s database. The configuration options are the same that are also
-used when configuring the exchange’ database:
+exchange's database. The configuration options are the same that are also
+used when configuring the exchange' database:
@quotation
@@ -775,14 +775,14 @@ CONFIG = postgres:///exchangedemo
@anchor{taler-auditor-manual wallets}@anchor{17}
Before GNU Taler wallets will happily interact with an exchange,
-the respective auditor’s public key (to be obtained via @code{taler-auditor-offline setup})
+the respective auditor's public key (to be obtained via @code{taler-auditor-offline setup})
must be added under the respective currency to the wallet. This
is usually expected to be hard-coded into the Taler wallet.
Users can also manually add auditors for a particular currency via a
Web page offering the respective pairing.
-FIXME-DOLD: explain how that Web page works, once it works…
+FIXME-DOLD: explain how that Web page works, once it works...
@menu
* Exchange::
@@ -796,13 +796,13 @@ FIXME-DOLD: explain how that Web page works, once it works…
@section Exchange
-The next step is to add the exchange’s master public key and the base
+The next step is to add the exchange's master public key and the base
URL of the exchange to the list of exchanges audited by the auditor.
This is done using the @code{taler-auditor-exchange} tool. The tool
-basically creates the respective record in the auditor’s database.
+basically creates the respective record in the auditor's database.
If this step is skipped, the auditor will malfunction at all future
-stages with a foreign key violation, as it doesn’t know the exchange’s
+stages with a foreign key violation, as it doesn't know the exchange's
master public key.
@example
@@ -811,7 +811,7 @@ $ taler-auditor-exchange -m $MASTER_PUB -u $EXCHANGE_BASE_URL
The equivalent step must be performed by the exchange operator.
Here, the exchange operator must use the @code{taler-exchange-offline}
-tool to add the auditor’s public key, base URL and (business) name
+tool to add the auditor's public key, base URL and (business) name
to the list of approved auditors of the exchange. For details,
see Auditor-configuration in the exchange operator manual.
@@ -847,7 +847,7 @@ process that is outside of the scope of this document.
Note that the @code{input.json} does not contain any confidential data. However,
signing the wrong keys would be fatal in that it may allow an illegitimate
exchange to convince users that it is a trustworthy operator and subsequently
-betray the user’s trust that is anchored in the existence of a trustworthy
+betray the user's trust that is anchored in the existence of a trustworthy
auditor.
Given the verified JSON input, the auditor can then sign it (typically
@@ -880,21 +880,21 @@ command-line option, send logging output to standard error by default.
The next key step for the auditor is to configure replication of the
-@emph{exchange}’s database in-house. This should be performed in two steps
+@emph{exchange}'s database in-house. This should be performed in two steps
as illustrated in the following figure:
@image{taler-auditor-figures/replication,,,,png}
First, the exchange should use standard Postgres replication features to
-enable the auditor to obtain a full copy of the exchange’s database.
-Second, the auditor should make a “trusted” local copy, ensuring that it
+enable the auditor to obtain a full copy of the exchange's database.
+Second, the auditor should make a "trusted" local copy, ensuring that it
never replicates malicious changes using @code{taler-auditor-sync}. Both
of these steps are described in more detail below.
We note that as a result of these steps, the auditor will have three
databases: its own production primary database (as configured in
-@code{auditordb-postgres}), its on production copy of the exchange’s database
-(@code{exchangedb-postgress}), and a third, untrusted “ingres” copy of the
+@code{auditordb-postgres}), its on production copy of the exchange's database
+(@code{exchangedb-postgress}), and a third, untrusted "ingres" copy of the
exchange database. The untrusted database should run as a separate Postgres
instance and is only accessed via @code{taler-auditor-sync} and the replication
mechanism driven by the exchange operator.
@@ -919,10 +919,10 @@ that asynchronous replication should suffice.
The resulting auditor database should be treated as read-only on the auditor
side. The @code{taler-exchange-dbinit} tool can be used to setup the schema, or
-the schema can be replicated using Postgres’s standard mechanisms. The same
+the schema can be replicated using Postgres's standard mechanisms. The same
applies for schema upgrades: if logical replication is used (which does not
replicate schema changes), @code{taler-exchange-dbinit} can be used to migrate
-the schema(s) in both the ingres and production copies of the exchange’s
+the schema(s) in both the ingres and production copies of the exchange's
database as well.
For details, we refer to the Postgres manual.
@@ -932,7 +932,7 @@ For details, we refer to the Postgres manual.
Depending on the replication method used, the exchange may perform
unexpected changes to the schema or perform @code{UPDATE}, @code{DELETE} or
@code{DROP} operations on the tables. Hence, the auditor cannot rely upon the
-exchange’s primary copy to respect schema constraints, especially as we
+exchange's primary copy to respect schema constraints, especially as we
have to presume that the exchange could act maliciously. Furthermore, it
is unclear to what degree Postgres database replication mechanisms are
robust against a malicious master database. Thus, the auditor should
@@ -946,20 +946,20 @@ process, from its actual operational data.
@subsection Safe replication of the ingres database into the auditor production database
-Using @code{taler-auditor-sync}, the auditor should make a second “safe” copy of
-the exchange’s ingres database. @code{taler-auditor-sync} basically reads from one
+Using @code{taler-auditor-sync}, the auditor should make a second "safe" copy of
+the exchange's ingres database. @code{taler-auditor-sync} basically reads from one
exchange database and inserts all records found into a second exchange
database. If the source database violates invariants, the tool halts with an
error. This way, records violating invariants are never even copied, and in
particular schema changes and deletions or updates are not propagated into the
-auditor’s production database.
+auditor's production database.
While @code{taler-auditor-sync} could in theory be run directly against the
-exchange’s production system, this is likely a bad idea due to the high
+exchange's production system, this is likely a bad idea due to the high
latency from the network between auditor and exchange operator. Thus, we
-recommend first making an “untrusted” ingress copy of the exchange’s
+recommend first making an "untrusted" ingress copy of the exchange's
production database using standard Postgres tooling, and then using
-@code{taler-auditor-sync} to create a second “safe” copy. The “safe” copy used
+@code{taler-auditor-sync} to create a second "safe" copy. The "safe" copy used
by the production system should also run under a different UID.
Before @code{taler-auditor-sync} can be used, the target database must be
@@ -972,11 +972,11 @@ needs to be changed.
When the exchange performs garbage collection to @code{DELETE} obsolete records,
this change should be automatically replicated to the auditors untrusted
-ingress database. However, as @code{taler-auditor-sync} tries to be “safe”,
-it will not replicate those deletions to the auditor’s production database.
+ingress database. However, as @code{taler-auditor-sync} tries to be "safe",
+it will not replicate those deletions to the auditor's production database.
Thus, it is necessary to (occasonally) run @code{taler-exchange-dbinit -g} on
-the auditor’s production database to garbage collect old data in the
-auditor’s production copy. We note that this does not have to be done
+the auditor's production database to garbage collect old data in the
+auditor's production copy. We note that this does not have to be done
at the same time when the exchange runs its garbage collection.
@node Operation,Auditor implementation guide,Deployment,Top
@@ -1002,7 +1002,7 @@ at the same time when the exchange runs its garbage collection.
The @code{taler-auditor-httpd} runs the required REST API for the auditor. The
service must have @code{INSERT} (and @code{SELECT}) rights on the
-@code{deposit_confirmations} table in the auditor’s database. We expect that in
+@code{deposit_confirmations} table in the auditor's database. We expect that in
future versions additional rights may be required.
As the @code{taler-auditor-httpd} does not include HTTPS-support, it is
@@ -1045,7 +1045,7 @@ anymore), this is not recommended in a production setup.
@section Reading the report
-The auditor’s report needs to be read carefully, as it includes
+The auditor's report needs to be read carefully, as it includes
several categories of failures of different severity:
@@ -1111,14 +1111,14 @@ completing a @code{taler-audit} run against the old schema
@item
migrating the exchange schema (@code{taler-exchange-dbinit}) of
the master database, possibly the ingres database and the
-auditor’s production copy
+auditor's production copy
@item
migrating the auditor database (@code{taler-auditor-dbinit})
@item
-resuming database replication between the exchange’s master
-database and the auditor’s ingres copy
+resuming database replication between the exchange's master
+database and the auditor's ingres copy
@item
resuming @code{taler-auditor-sync}
@@ -1163,7 +1163,7 @@ For more information, see Revocations in the exchange operator manual.
If all denominations of an exchange are revoked, the exchange includes logic
to wire back all returned funds to the bank accounts from which they
originate. If some denominations remain operational, wallets will generally
-exchange old coins of revoked denominations for new coins – while providing
+exchange old coins of revoked denominations for new coins -- while providing
additional information to demonstrate that these coins were not forged from
the compromised private key but obtained via a legitimate withdraw operation.
@@ -1172,12 +1172,12 @@ the compromised private key but obtained via a legitimate withdraw operation.
@section Failures
-Most audit failures are handled by the auditor’s regular reporting functionality,
+Most audit failures are handled by the auditor's regular reporting functionality,
creating a (hopefully descriptive) PDF report detailing the problems found.
However, there is one category of errors where this is not possible, which
-concerns arithmetic overflows for amounts. Taler’s specification limits amount
-values to at most 2^52. If, during the auditor’s calculations, amounts are
+concerns arithmetic overflows for amounts. Taler's specification limits amount
+values to at most 2^52. If, during the auditor's calculations, amounts are
encountered that exceed this threshold, the auditor will not generate a regular
report, but instead write a log statement explaining where the problem happened
and exit with a status code of @emph{42}.
@@ -1209,15 +1209,15 @@ The auditor implementation is split into five main processes, called
@code{taler-helper-auditor-XXX}. The split was done to realize the principle of
least privilege and to enable independent logic to be possibly run in
parallel. Only the taler-wire-auditor must have (read-only) access to the
-exchange’s bank account, the other components only need access to the
+exchange's bank account, the other components only need access to the
database.
All auditor subsystems basically start their audit from a certain transaction
index (@code{BIG SERIAL}) in the auditor database which identifies where the last
audit concluded. They then check that the transactions claimed in the
-exchange’s database match up internally, including the cryptographic
+exchange's database match up internally, including the cryptographic
signatures and also with respect to amounts adding up. The auditor also
-calculates the exchange’s profits and expected bank balances. Once all
+calculates the exchange's profits and expected bank balances. Once all
existing transactions are processed, the auditor processes store the current
checkpoint in its database and generate a JSON report.
@@ -1226,22 +1226,22 @@ uses Jinja2 with a TeX template to convert the five individual
JSON reports into LaTeX and then into PDF.
@menu
-* The auditor’s database::
+* The auditor's database::
* Invariants checked by the auditor::
* Testing the auditor::
@end menu
-@node The auditor’s database,Invariants checked by the auditor,,Auditor implementation guide
+@node The auditor's database,Invariants checked by the auditor,,Auditor implementation guide
@anchor{taler-auditor-manual the-auditor-s-database}@anchor{2e}
-@section The auditor’s database
+@section The auditor's database
The database scheme used by the exchange looks as follows:
@image{taler-auditor-figures/auditor-db,,,,png}
-@node Invariants checked by the auditor,Testing the auditor,The auditor’s database,Auditor implementation guide
+@node Invariants checked by the auditor,Testing the auditor,The auditor's database,Auditor implementation guide
@anchor{taler-auditor-manual invariants-checked-by-the-auditor}@anchor{2f}
@section Invariants checked by the auditor
@@ -1266,7 +1266,7 @@ pass where it might seem applicable.
@subsection Invariants checked by the taler-helper-auditor-aggregation
-This is from CodeBlau’s analysis. A proper write-up is pending.
+This is from CodeBlau's analysis. A proper write-up is pending.
CodeBlau reports the following checks:
@@ -1378,7 +1378,7 @@ wire fee unavailable for given time
@subsection Invariants checked by the taler-helper-auditor-coins
-This is from CodeBlau’s analysis. A proper write-up is pending.
+This is from CodeBlau's analysis. A proper write-up is pending.
CodeBlau reports the following checks:
@@ -1386,9 +1386,9 @@ CodeBlau reports the following checks:
@item
check that all denominations used by the exchange have been signed using
-this auditor’s key. All denominations encountered in the database that
+this auditor's key. All denominations encountered in the database that
this auditor did not officially sign for are reported (but still included
-in the audit as they obviously may impact the exchange’s bank balance).
+in the audit as they obviously may impact the exchange's bank balance).
Depending on the business situation, this may be normal (say if an exchange
is changing auditors and newer denominations are no longer supported until
their end-of-life by the current auditor).
@@ -1484,7 +1484,7 @@ merchants by simply not reporting deposits to the auditor.
@subsection Invariants checked by the taler-helper-auditor-reserves
-This is from CodeBlau’s analysis. A proper write-up is pending.
+This is from CodeBlau's analysis. A proper write-up is pending.
CodeBlau reports the following checks:
@@ -1546,11 +1546,11 @@ target account does not match origin account
This auditor is special in that it is the only pass that is required to have
-@emph{read-only} access to the exchange’s bank account (privilege separation). Its
-main role is to verify that the wire transfers in the exchange’s database and
+@emph{read-only} access to the exchange's bank account (privilege separation). Its
+main role is to verify that the wire transfers in the exchange's database and
those reported by the bank are identical.
-This is from CodeBlau’s analysis. A proper write-up is pending.
+This is from CodeBlau's analysis. A proper write-up is pending.
CodeBlau reports the following checks:
@@ -1612,7 +1612,7 @@ closing fee above total amount
The main objective of the auditor is to detect inconsistencies. Thus, the
@code{test-auditor.sh} script deliberately introduces various inconsistencies into
-a synthetic exchange database. For this, an “normal” exchange database is
+a synthetic exchange database. For this, an "normal" exchange database is
first generated using the @code{taler-wallet-cli}. Then, various fields or rows
of that database are manipulated, and the auditor is let loose on the modified
database. Afterwards, the test verifies that the JSON contains values
@@ -1625,13 +1625,13 @@ cover as many code paths as possible in both the exchange and the auditor. It
should also ideally create all interesting possible variations of the exchange
database fields (within the constraints of the database schema).
-In general, @code{test-auditor.sh} runs the tests against an “old” database where
+In general, @code{test-auditor.sh} runs the tests against an "old" database where
some transactions are past the due-date (and hence the aggregator would trigger
wire transfers), as well as a freshly generated exchange database where the
auditor would not perform any transfers. Auditor interactions can be made
before or after the aggregator, depending on what is being tested.
-The current script also rudimentarily tests the auditor’s resume logic,
+The current script also rudimentarily tests the auditor's resume logic,
by re-starting the auditor once against a database that the auditor has
already seen.
diff --git a/texinfo/taler-bank-figures/anastasis-db.png b/texinfo/taler-bank-figures/anastasis-db.png
new file mode 100644
index 00000000..03eed9da
--- /dev/null
+++ b/texinfo/taler-bank-figures/anastasis-db.png
Binary files differ
diff --git a/texinfo/taler-bank-figures/anastasis_challenge_payment.png b/texinfo/taler-bank-figures/anastasis_challenge_payment.png
new file mode 100644
index 00000000..a0593eba
--- /dev/null
+++ b/texinfo/taler-bank-figures/anastasis_challenge_payment.png
Binary files differ
diff --git a/texinfo/taler-bank-figures/anastasis_challengecode.png b/texinfo/taler-bank-figures/anastasis_challengecode.png
new file mode 100644
index 00000000..fc30f4fe
--- /dev/null
+++ b/texinfo/taler-bank-figures/anastasis_challengecode.png
Binary files differ
diff --git a/texinfo/taler-bank-figures/anastasis_reducer_backup.png b/texinfo/taler-bank-figures/anastasis_reducer_backup.png
new file mode 100644
index 00000000..87b0a9b4
--- /dev/null
+++ b/texinfo/taler-bank-figures/anastasis_reducer_backup.png
Binary files differ
diff --git a/texinfo/taler-bank-figures/anastasis_reducer_recovery.png b/texinfo/taler-bank-figures/anastasis_reducer_recovery.png
new file mode 100644
index 00000000..7d3cc9ae
--- /dev/null
+++ b/texinfo/taler-bank-figures/anastasis_reducer_recovery.png
Binary files differ
diff --git a/texinfo/taler-bank-figures/anastasis_truth.png b/texinfo/taler-bank-figures/anastasis_truth.png
new file mode 100644
index 00000000..7f23fa21
--- /dev/null
+++ b/texinfo/taler-bank-figures/anastasis_truth.png
Binary files differ
diff --git a/texinfo/taler-bank-figures/anastasis_truth_payment.png b/texinfo/taler-bank-figures/anastasis_truth_payment.png
new file mode 100644
index 00000000..70a6b3df
--- /dev/null
+++ b/texinfo/taler-bank-figures/anastasis_truth_payment.png
Binary files differ
diff --git a/texinfo/taler-bank.texi b/texinfo/taler-bank.texi
index 882303a8..53e89a41 100644
--- a/texinfo/taler-bank.texi
+++ b/texinfo/taler-bank.texi
@@ -21,11 +21,11 @@
@copying
@quotation
-GNU Taler 0.8.0pre0, Jan 27, 2021
+GNU Taler 0.8.0pre0, Apr 26, 2021
GNU Taler team
-Copyright @copyright{} 2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+Copyright @copyright{} 2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
@end quotation
@end copying
@@ -152,8 +152,8 @@ interface BankRegistrationRequest @{
password: string;
@}
@end example
-@anchor{8}@w{ }
@anchor{taler-bank-manual tsref-type-BankRegistrationRequest}@w{ }
+@anchor{8}@w{ }
@c %**end of body
@bye
diff --git a/texinfo/taler-developer-manual-figures/anastasis-db.png b/texinfo/taler-developer-manual-figures/anastasis-db.png
new file mode 100644
index 00000000..03eed9da
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/anastasis-db.png
Binary files differ
diff --git a/texinfo/taler-developer-manual-figures/anastasis_challenge_payment.png b/texinfo/taler-developer-manual-figures/anastasis_challenge_payment.png
new file mode 100644
index 00000000..a0593eba
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/anastasis_challenge_payment.png
Binary files differ
diff --git a/texinfo/taler-developer-manual-figures/anastasis_challengecode.png b/texinfo/taler-developer-manual-figures/anastasis_challengecode.png
new file mode 100644
index 00000000..fc30f4fe
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/anastasis_challengecode.png
Binary files differ
diff --git a/texinfo/taler-developer-manual-figures/anastasis_reducer_backup.png b/texinfo/taler-developer-manual-figures/anastasis_reducer_backup.png
new file mode 100644
index 00000000..87b0a9b4
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/anastasis_reducer_backup.png
Binary files differ
diff --git a/texinfo/taler-developer-manual-figures/anastasis_reducer_recovery.png b/texinfo/taler-developer-manual-figures/anastasis_reducer_recovery.png
new file mode 100644
index 00000000..7d3cc9ae
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/anastasis_reducer_recovery.png
Binary files differ
diff --git a/texinfo/taler-developer-manual-figures/anastasis_truth.png b/texinfo/taler-developer-manual-figures/anastasis_truth.png
new file mode 100644
index 00000000..7f23fa21
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/anastasis_truth.png
Binary files differ
diff --git a/texinfo/taler-developer-manual-figures/anastasis_truth_payment.png b/texinfo/taler-developer-manual-figures/anastasis_truth_payment.png
new file mode 100644
index 00000000..70a6b3df
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/anastasis_truth_payment.png
Binary files differ
diff --git a/texinfo/taler-developer-manual-figures/arch-api.png b/texinfo/taler-developer-manual-figures/arch-api.png
new file mode 100644
index 00000000..8004f790
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/arch-api.png
Binary files differ
diff --git a/texinfo/taler-developer-manual-figures/auditor-db.png b/texinfo/taler-developer-manual-figures/auditor-db.png
new file mode 100644
index 00000000..3f10f3ab
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/auditor-db.png
Binary files differ
diff --git a/texinfo/taler-developer-manual-figures/exchange-db.png b/texinfo/taler-developer-manual-figures/exchange-db.png
new file mode 100644
index 00000000..f99e2664
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/exchange-db.png
Binary files differ
diff --git a/texinfo/taler-developer-manual-figures/merchant-db.png b/texinfo/taler-developer-manual-figures/merchant-db.png
new file mode 100644
index 00000000..cd5f7bd6
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/merchant-db.png
Binary files differ
diff --git a/texinfo/taler-developer-manual-figures/replication.png b/texinfo/taler-developer-manual-figures/replication.png
new file mode 100644
index 00000000..855237fc
--- /dev/null
+++ b/texinfo/taler-developer-manual-figures/replication.png
Binary files differ
diff --git a/texinfo/taler-developer-manual.texi b/texinfo/taler-developer-manual.texi
new file mode 100644
index 00000000..5c7dbc73
--- /dev/null
+++ b/texinfo/taler-developer-manual.texi
@@ -0,0 +1,2731 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename taler-developer-manual.info
+@documentencoding UTF-8
+@ifinfo
+@*Generated by Sphinx 3.4.3.@*
+@end ifinfo
+@settitle Taler Developer Manual
+@defindex ge
+@paragraphindent 0
+@exampleindent 4
+@finalout
+@dircategory CATEGORY
+@direntry
+* MENU ENTRY: (taler-developer-manual.info). DESCRIPTION
+@end direntry
+
+@definfoenclose strong,`,'
+@definfoenclose emph,`,'
+@c %**end of header
+
+@copying
+@quotation
+GNU Taler 0.8.0pre0, Apr 26, 2021
+
+GNU Taler team
+
+Copyright @copyright{} 2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+@end quotation
+
+@end copying
+
+@titlepage
+@title Taler Developer Manual
+@insertcopying
+@end titlepage
+@contents
+
+@c %** start of user preamble
+
+@c %** end of user preamble
+
+@ifnottex
+@node Top
+@top Taler Developer Manual
+@insertcopying
+@end ifnottex
+
+@c %**start of body
+@anchor{taler-developer-manual doc}@anchor{0}
+@c This file is part of GNU TALER.
+@c
+@c Copyright (C) 2014-2021 Taler Systems SA
+@c
+@c TALER is free software; you can redistribute it and/or modify it under the
+@c terms of the GNU General Public License as published by the Free Software
+@c Foundation; either version 2.1, or (at your option) any later version.
+@c
+@c TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+@c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+@c A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+@c
+@c You should have received a copy of the GNU General Public License along with
+@c TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+@c
+@c @author Christian Grothoff
+
+@menu
+* GNU Taler Release Checklist::
+* GNU Taler Demo Upgrade Checklist::
+* Fundamentals::
+* Language-Specific Guidelines::
+* Taler Deployment on gv.taler.net: Taler Deployment on gv taler net.
+* Demo Upgrade Procedure::
+* Environments and Builders on taler.net: Environments and Builders on taler net.
+* Releases::
+* Continuous integration::
+* Internationalization::
+* Android Apps::
+* Code Coverage::
+* Coding Conventions::
+* Testing library::
+* User-Facing Terminology::
+* Developer Glossary::
+* Developer Tools::
+* Index::
+
+@end menu
+
+@node GNU Taler Release Checklist,GNU Taler Demo Upgrade Checklist,Top,Top
+@anchor{checklist-release doc}@anchor{1}@anchor{checklist-release developer-s-manual}@anchor{2}@anchor{checklist-release gnu-taler-release-checklist}@anchor{3}
+@chapter GNU Taler Release Checklist
+
+
+Release checklists for GNU Taler:
+
+Wallet:
+
+
+@itemize -
+
+@item
+[ ] build wallet
+
+@item
+[ ] verify wallet works against 'test.taler.net'
+
+@item
+[ ] tag repo.
+
+@item
+[ ] upgrade 'demo.taler.net' to 'test.taler.net'
+
+@item
+[ ] upload new wallet release to app store
+
+@item
+[ ] Update bug tracker (mark release, resolved -> closed)
+
+@item
+[ ] Send announcement to @email{taler@@gnu.org}
+
+@item
+[ ] Send announcement to @email{info-gnu@@gnu.org} (major releases only)
+
+@item
+[ ] Send announcement to @email{coordinator@@translationproject.org}
+@end itemize
+
+For exchange:
+
+
+@itemize -
+
+@item
+[ ] check no compiler warnings at "-Wall"
+
+@item
+[ ] ensure Coverity static analysis passes
+
+@item
+[ ] make check.
+
+@item
+[ ] upgrade 'demo.taler.net' to 'test.taler.net'
+
+@item
+[ ] make dist, make check on result of 'make dist'.
+
+@item
+[ ] Change version number in configure.ac.
+
+@item
+[ ] make dist for release.
+
+@item
+[ ] tag repo.
+
+@item
+[ ] Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+@item
+[ ] Update bug tracker (mark release, resolved -> closed)
+
+@item
+[ ] Send announcement to @email{taler@@gnu.org}
+
+@item
+[ ] Send announcement to @email{info-gnu@@gnu.org} (major releases only)
+
+@item
+[ ] Send announcement to @email{coordinator@@translationproject.org}
+@end itemize
+
+For merchant (C backend):
+
+
+@itemize -
+
+@item
+[ ] check no compiler warnings at "-Wall"
+
+@item
+[ ] ensure Coverity static analysis passes
+
+@item
+[ ] make check.
+
+@item
+[ ] upgrade 'demo.taler.net' to 'test.taler.net'
+
+@item
+[ ] make dist, make check on result of 'make dist'.
+
+@item
+[ ] Change version number in configure.ac.
+
+@item
+[ ] make dist for release.
+
+@item
+[ ] tag repo.
+
+@item
+[ ] Upload triplet to ftp-upload.gnu.org/incoming/ftp or /incoming/alpha
+
+@item
+[ ] Update bug tracker (mark release, resolved -> closed)
+
+@item
+[ ] Send announcement to @email{taler@@gnu.org}
+
+@item
+[ ] Send announcement to @email{info-gnu@@gnu.org} (major releases only)
+
+@item
+[ ] Send announcement to @email{coordinator@@translationproject.org}
+@end itemize
+
+For bank:
+
+
+@itemize -
+
+@item
+TBD
+@end itemize
+
+For Python merchant frontend:
+
+
+@itemize -
+
+@item
+TBD
+@end itemize
+
+For PHP merchant frontend:
+
+
+@itemize -
+
+@item
+TBD
+@end itemize
+
+For auditor:
+
+
+@itemize -
+
+@item
+TBD
+@end itemize
+
+For libebics:
+
+
+@itemize -
+
+@item
+TBD
+@end itemize
+
+@node GNU Taler Demo Upgrade Checklist,Fundamentals,GNU Taler Release Checklist,Top
+@anchor{checklist-demo-upgrade doc}@anchor{4}@anchor{checklist-demo-upgrade gnu-taler-demo-upgrade-checklist}@anchor{5}
+@chapter GNU Taler Demo Upgrade Checklist
+
+
+Post-upgrade checks:
+
+
+@itemize -
+
+@item
+ Run @code{taler-deployment-arm -I} to verify that all services are running.
+
+@item
+ Run the headless wallet to check that services are actually working:
+
+@example
+$ taler-wallet-cli integrationtest \
+ -e https://exchange.demo.taler.net/ \
+ -m https://backend.demo.taler.net/ \
+ -b https://bank.demo.taler.net \
+ -w "KUDOS:10" \
+ -s "KUDOS:5"
+@end example
+@end itemize
+
+Basics:
+
+
+@itemize -
+
+@item
+ Visit @indicateurl{https://demo.taler.net/} to see if the landing page is displayed correctly
+
+@item
+ Visit the wallet installation page, install the wallet, and see if the presence
+indicator is updated correctly.
+
+@item
+ Visit @indicateurl{https://bank.demo.taler.net/}, register a new user and withdraw coins into the
+browser wallet.
+@end itemize
+
+Blog demo:
+
+
+@itemize -
+
+@item
+ Visit @indicateurl{https://shop.demo.taler.net/} and purchase an article.
+
+@item
+ Verify that the balance in the wallet was updated correctly.
+
+@item
+ Go back to @indicateurl{https://shop.demo.taler.net/} and click on the same article
+link. Verify that the article is shown and @strong{no} repeated payment is
+requested.
+
+@item
+ Open the fulfillment page from the previous step in an anonymous browsing session
+(without the wallet installed) and verify that it requests a payment again.
+
+@item
+ Delete cookies on @indicateurl{https://shop.demo.taler.net/} and click on the same article again.
+Verify that the wallet detects that the article has already purchased and successfully
+redirects to the article without spending more money.
+@end itemize
+
+Donation demo:
+
+
+@itemize -
+
+@item
+ Make a donation on @indicateurl{https://donations.demo.taler.net}
+
+@item
+ Make another donation with the same parameters and verify
+that the payment is requested again, instead of showing the previous
+fulfillment page.
+@end itemize
+
+Survey/Tipping:
+
+
+@itemize -
+
+@item
+ Visit @indicateurl{https://survey.demo.taler.net/} and receive a tip.
+
+@item
+ Verify that the survey stats page (@indicateurl{https://survey.demo.taler.net/survey-stats}) is working,
+and that the survey reserve has sufficient funds.
+@end itemize
+
+@cartouche
+@quotation Note
+This manual contains information for developers working on GNU Taler
+and related components. It is not intended for a general audience.
+@end quotation
+@end cartouche
+
+@node Fundamentals,Language-Specific Guidelines,GNU Taler Demo Upgrade Checklist,Top
+@anchor{taler-developer-manual fundamentals}@anchor{6}
+@chapter Fundamentals
+
+
+@menu
+* Bug Tracking::
+* Code Repositories::
+* Committing code::
+* Observing changes::
+* Communication::
+
+@end menu
+
+@node Bug Tracking,Code Repositories,,Fundamentals
+@anchor{taler-developer-manual bug-tracking}@anchor{7}
+@section Bug Tracking
+
+
+Bug tracking is done with Mantis (@indicateurl{https://www.mantisbt.org/}). The bug tracker
+is available at @indicateurl{https://bugs.taler.net}. A registration on the Web site is
+needed in order to use the bug tracker, only read access is granted without a
+login.
+
+@node Code Repositories,Committing code,Bug Tracking,Fundamentals
+@anchor{taler-developer-manual code-repositories}@anchor{8}
+@section Code Repositories
+
+
+Taler code is versioned with Git. For those users without write access, all the
+codebases are found at the following URL:
+
+@example
+git://git.taler.net/<repository>
+@end example
+
+A complete list of all the existing repositories is currently found at
+@indicateurl{https://git.taler.net/}.
+
+@node Committing code,Observing changes,Code Repositories,Fundamentals
+@anchor{taler-developer-manual committing-code}@anchor{9}
+@section Committing code
+
+
+Before you can obtain Git write access, you must sign the copyright
+agreement. As we collaborate closely with GNUnet, we use their
+copyright agreement -- with the understanding that your contributions
+to GNU Taler are included in the assignment. You can find the
+agreement on the GNUnet site@footnote{https://gnunet.org/en/copyright.html}.
+Please sign and mail it to Christian Grothoff as he currently collects
+all the documents for GNUnet e.V.
+
+To obtain Git access, you need to send us your SSH public key. Most core
+team members have administrative Git access, so simply contact whoever
+is your primary point of contact so far. You can
+find instructions on how to generate an SSH key
+in the Git book@footnote{https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key}.
+If you have been granted write access, you first of all must change the URL of
+the respective repository to:
+
+@example
+ssh://git@@git.taler.net/<repository>
+@end example
+
+For an existing checkout, this can be done by editing the @code{.git/config} file.
+
+The server is configured to reject all commits that have not been signed with
+GnuPG. If you do not yet have a GnuPG key, you must create one, as explained
+in the GNU Privacy Handbook@footnote{https://www.gnupg.org/gph/en/manual/c14.html}.
+You do not need to share the respective public key with us to make commits.
+However, we recommend that you upload it to key servers, put it on your
+business card and personally meet with other GNU hackers to have it signed
+such that others can verify your commits later.
+
+To sign all commits, you should run
+
+@example
+$ git config --global commit.gpgsign true
+@end example
+
+You can also sign individual commits only by adding the @code{-S} option to the
+@code{git commit} command. If you accidentally already made commits but forgot
+to sign them, you can retroactively add signatures using:
+
+@example
+$ git rebase -S
+@end example
+
+Whether you commit to a personal branch (recommended: @code{dev/$USER/...}),
+a feature branch or to @code{master} should
+depend on your level of comfort and the nature of the change. As a general
+rule, the code in @code{master} must always build and tests should always pass, at
+least on your own system. However, we all make mistakes and you should expect
+to receive friendly reminders if your change did not live up to this simple
+standard. We plan to move to a system where the CI guarantees this invariant
+in the future.
+
+In order to keep a linear and clean commits history, we advise to avoid
+merge commits and instead always rebase your changes before pushing to
+the @code{master} branch. If you commit and later find out that new commits were
+pushed, the following command will pull the new commits and rebase yours
+on top of them.
+
+@example
+# -S instructs Git to (re)sign your commits
+$ git pull --rebase -S
+@end example
+
+@node Observing changes,Communication,Committing code,Fundamentals
+@anchor{taler-developer-manual observing-changes}@anchor{a}
+@section Observing changes
+
+
+Every commit to the @code{master} branch of any of our public repositories
+(and almost all are public) is automatically sent to the
+@email{gnunet-svn@@gnu.org} mailinglist. That list is for Git commits only,
+and must not be used for discussions. It also carries commits from
+our main dependencies, namely GNUnet and GNU libmicrohttpd. While
+it can be high volume, the lists is a good way to follow overall
+development.
+
+@node Communication,,Observing changes,Fundamentals
+@anchor{taler-developer-manual communication}@anchor{b}
+@section Communication
+
+
+We use the #taler channel on the Freenode IRC network and the @email{taler@@gnu.org}
+public mailinglist for discussions. Not all developers are active on IRC, but
+all developers should probably subscribe to the low-volume Taler mailinglist.
+There are separate low-volume mailinglists for gnunet-developers (@@gnu.org)
+and for libmicrohttpd (@@gnu.org).
+
+@node Language-Specific Guidelines,Taler Deployment on gv taler net,Fundamentals,Top
+@anchor{taler-developer-manual language-specific-guidelines}@anchor{c}
+@chapter Language-Specific Guidelines
+
+
+
+@itemize *
+
+@item
+Python Guidelines
+@end itemize
+
+@node Taler Deployment on gv taler net,Demo Upgrade Procedure,Language-Specific Guidelines,Top
+@anchor{taler-developer-manual taler-deployment-on-gv-taler-net}@anchor{d}
+@chapter Taler Deployment on gv.taler.net
+
+
+This section describes the GNU Taler deployment on @code{gv.taler.net}.
+@code{gv} is our server at BFH. It hosts the Git repositories, Web sites,
+CI and other services. Developers can receive an SSH account and
+e-mail alias for the system. As with Git, ask your primary team
+contact for shell access if you think you need it.
+
+Our old server, @code{tripwire}, is currently offline and will likely
+go back online to host @code{production} systems for operating real
+Taler payments at BFH in the future.
+
+@menu
+* DNS::
+* User Acccounts::
+
+@end menu
+
+@node DNS,User Acccounts,,Taler Deployment on gv taler net
+@anchor{taler-developer-manual dns}@anchor{e}
+@section DNS
+
+
+DNS records for taler.net are controlled by the GNU Taler
+maintainers, specifically Christian and Florian. If you
+need a sub-domain to be added, please contact one of them.
+
+@node User Acccounts,,DNS,Taler Deployment on gv taler net
+@anchor{taler-developer-manual user-acccounts}@anchor{f}
+@section User Acccounts
+
+
+On @code{gv.taler.net}, there are four system users that are set up to
+serve Taler on the Internet:
+
+
+@itemize -
+
+@item
+@code{taler-test}: serves @code{*.test.taler.net} and gets automatically
+built by Buildbot.
+
+@item
+@code{taler-internal}: serves @code{*.int.taler.net}, and does @emph{NOT} get
+automatically built.
+@end itemize
+
+The following two users are @emph{never} automatically built, and they both
+serve @code{*.demo.taler.net}. At any given time, only one is active and
+serves the HTTP requests from the outside; the other one can so be
+compiled without any downtime. If the compilation succeeds, the inactive
+user can be switched to become active (see next section), and vice versa.
+
+
+@itemize -
+
+@item
+@code{demo-blue}
+
+@item
+@code{demo-green}
+@end itemize
+
+@node Demo Upgrade Procedure,Environments and Builders on taler net,Taler Deployment on gv taler net,Top
+@anchor{taler-developer-manual demo-upgrade-procedure}@anchor{10}
+@chapter Demo Upgrade Procedure
+
+
+Upgrading the @code{demo} environment should be done with care, and ideally be
+coordinated on the mailing list before. It is our goal for @code{demo} to always
+run a "working version" that is compatible with various published wallets.
+
+Before deploying on @code{demo}, the same version of all components @strong{must}
+be deployed @emph{and} tested on @code{int}.
+
+Please use the @ref{4,,demo upgrade checklist} to make
+sure everything is working.
+
+@menu
+* Tagging components::
+* Environment Layout::
+* Using envcfg.py: Using envcfg py.
+* Bootstrapping an Environment::
+* Upgrading an Existing Environment::
+* Switching Demo Colors::
+
+@end menu
+
+@node Tagging components,Environment Layout,,Demo Upgrade Procedure
+@anchor{taler-developer-manual tagging-components}@anchor{11}
+@section Tagging components
+
+
+All Taler components must be tagged with git before they are deployed on the
+@code{demo} environment, using a tag of the following form:
+
+@example
+demo-YYYY-MM-DD-SS
+YYYY = year
+MM = month
+DD = day
+SS = serial
+@end example
+
+@node Environment Layout,Using envcfg py,Tagging components,Demo Upgrade Procedure
+@anchor{taler-developer-manual environment-layout}@anchor{12}
+@section Environment Layout
+
+
+Environments have the following layout:
+
+@example
+$HOME/
+ deployment (deployment.git checkout)
+ envcfg.py (configuration of the Taler environment)
+ activate (bash file, sourced to set environment variables)
+ logs/ (log files)
+ local/ (locally installed software)
+ sources/ (sources repos of locally build components)
+ sockets/ (unix domain sockets of running components)
+ taler-data (on-disk state, public and private keys)
+ .config/taler.conf (main Taler configuration file)
+@end example
+
+On @code{demo-blue} and @code{demo-green}, @code{taler-data} is a symlink pointing to @code{$HOME/demo/shared-data}
+instead of a directory.
+
+@node Using envcfg py,Bootstrapping an Environment,Environment Layout,Demo Upgrade Procedure
+@anchor{taler-developer-manual using-envcfg-py}@anchor{13}
+@section Using envcfg.py
+
+
+The @code{$HOME/envcfg.py} file contains (1) the name of the environment and (2) the version
+of all components we build (in the form of a git rev).
+
+The @code{envcfg.py} for demo looks like this:
+
+@example
+env = "demo"
+tag = "demo-2019-10-05-01:
+tag_gnunet = tag
+tag_libmicrohttpd = tag
+tag_exchange = tag
+tag_merchant = tag
+tag_bank = tag
+tag_twister = tag
+tag_landing = tag
+tag_donations = tag
+tag_blog = tag
+tag_survey = tag
+tag_backoffice = tag
+tag_sync = tag
+@end example
+
+Currently only the variables @code{env} and @code{tag_$@{component@}} are used.
+
+When deploying to @code{demo}, the @code{envcfg.py} should be committed to @code{deployment.git/envcfg/envcfg-demo-YYYY-MM-DD-SS.py}.
+
+@node Bootstrapping an Environment,Upgrading an Existing Environment,Using envcfg py,Demo Upgrade Procedure
+@anchor{taler-developer-manual bootstrapping-an-environment}@anchor{14}
+@section Bootstrapping an Environment
+
+
+@example
+$ git clone https://git.taler.net/deployment.git ~/deployment
+$ cp ~/deployment/envcfg/$ENVCFGFILE ~/envcfg.py
+$ ./deployment/bin/taler-deployment bootstrap
+$ source ~/activate
+$ taler-deployment build
+$ taler-deployment-prepare
+$ taler-deployment-start
+$ taler-deployment-arm -I # check everything works
+# The following command sets up the 'blog' and 'donations' instances.
+$ taler-config-instances
+@end example
+
+@node Upgrading an Existing Environment,Switching Demo Colors,Bootstrapping an Environment,Demo Upgrade Procedure
+@anchor{taler-developer-manual upgrading-an-existing-environment}@anchor{15}
+@section Upgrading an Existing Environment
+
+
+@example
+$ rm -rf ~/sources ~/local
+$ git -C ~/deployment pull
+$ cp ~/deployment/envcfg/$ENVCFGFILE ~/envcfg.py
+$ taler-deployment bootstrap
+$ taler-deployment build
+$ taler-deployment-prepare
+$ taler-deployment-restart
+$ taler-deployment-arm -I # check everything works
+@end example
+
+@node Switching Demo Colors,,Upgrading an Existing Environment,Demo Upgrade Procedure
+@anchor{taler-developer-manual switching-demo-colors}@anchor{16}
+@section Switching Demo Colors
+
+
+As the @code{demo} user, to switch to color @code{$@{COLOR@}},
+run the following script from @code{deployment/bin}:
+
+@example
+$ taler-deployment switch-demo
+@end example
+
+@node Environments and Builders on taler net,Releases,Demo Upgrade Procedure,Top
+@anchor{taler-developer-manual environments-and-builders-on-taler-net}@anchor{17}
+@chapter Environments and Builders on taler.net
+
+
+@menu
+* Buildbot implementation::
+* Documentation Builder::
+* Website Builder::
+* Code coverage::
+* Service Checker::
+* Tipping reserve top-up::
+* Producing auditor reports::
+* Database schema versioning::
+
+@end menu
+
+@node Buildbot implementation,Documentation Builder,,Environments and Builders on taler net
+@anchor{taler-developer-manual buildbot-implementation}@anchor{18}
+@section Buildbot implementation
+
+
+GNU Taler uses a buildbot implementation (front end at @indicateurl{https://buildbot.taler.net}) to manage continuous integration. Buildbot documentation is at @indicateurl{https://docs.buildbot.net/}.
+
+Here are some highlights:
+
+
+@itemize -
+
+@item
+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.
+
+@item
+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 @code{buildbot-worker} command.
+
+@item
+The buildbot server's master.cfg file contains FACTORY declarations which specify the commands that the WORKER will run on localhost.
+
+@item
+The FACTORY is tied to the WORKER in master.cfg by a BUILDER.
+
+@item
+The master.cfg also allows for SCHEDULER that defines how and when the BUILDER is executed.
+
+@item
+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.
+@end itemize
+
+Best Practices:
+
+
+@itemize -
+
+@item
+When creating a new WORKER in the @code{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.)
+
+@item
+Create a worker from a shell account with this command: @code{buildbot-worker create-worker <workername> localhost <username> <password>}
+@end itemize
+
+Then make sure there is a WORKER defined in master.cfg like: @code{worker.Worker("<username>", "<password>")}
+
+@node Documentation Builder,Website Builder,Buildbot implementation,Environments and Builders on taler net
+@anchor{taler-developer-manual documentation-builder}@anchor{19}
+@section Documentation Builder
+
+
+All the Taler documentation is built by the user @code{docbuilder} that
+runs a Buildbot worker. The following commands set the @code{docbuilder} up,
+starting with a empty home directory.
+
+@example
+# Log-in as the 'docbuilder' user.
+
+$ cd $HOME
+$ git clone git://git.taler.net/deployment
+$ ./deployment/bootstrap-docbuilder
+
+# If the previous step worked, the setup is
+# complete and the Buildbot worker can be started.
+
+$ buildbot-worker start worker/
+@end example
+
+@node Website Builder,Code coverage,Documentation Builder,Environments and Builders on taler net
+@anchor{taler-developer-manual website-builder}@anchor{1a}
+@section Website Builder
+
+
+Taler Websites, @code{www.taler.net} and @code{stage.taler.net}, are built by the
+user @code{taler-websites} by the means of a Buildbot worker. The following
+commands set the @code{taler-websites} up, starting with a empty home directory.
+
+@example
+# Log-in as the 'taler-websites' user.
+
+$ cd $HOME
+$ git clone git://git.taler.net/deployment
+$ ./deployment/bootstrap-sitesbuilder
+
+# If the previous step worked, the setup is
+# complete and the Buildbot worker can be started.
+
+$ buildbot-worker start worker/
+@end example
+
+@node Code coverage,Service Checker,Website Builder,Environments and Builders on taler net
+@anchor{taler-developer-manual code-coverage}@anchor{1b}
+@section Code coverage
+
+
+Code coverage tests are run by the @code{lcovworker} user, and are also driven
+by Buildbot.
+
+@example
+# Log-in as the 'lcovworker' user.
+
+$ cd $HOME
+$ git clone git://git.taler.net/deployment
+$ ./deployment/bootstrap-taler lcov
+
+# If the previous step worked, the setup is
+# complete and the Buildbot worker can be started.
+
+$ buildbot-worker start worker/
+@end example
+
+The results are then published at @code{https://lcov.taler.net/}.
+
+@node Service Checker,Tipping reserve top-up,Code coverage,Environments and Builders on taler net
+@anchor{taler-developer-manual service-checker}@anchor{1c}
+@section Service Checker
+
+
+The user @code{demo-checker} runs periodic checks to see if all the
+@code{*.demo.taler.net} services are up and running. It is driven by
+Buildbot, and can be bootstrapped as follows.
+
+@example
+# Log-in as the 'demo-checker' user
+
+$ cd $HOME
+$ git clone git://git.taler.net/deployment
+$ ./deployment/bootstrap-demochecker
+
+# If the previous step worked, the setup is
+# complete and the Buildbot worker can be started.
+
+$ buildbot-worker start worker/
+@end example
+
+@node Tipping reserve top-up,Producing auditor reports,Service Checker,Environments and Builders on taler net
+@anchor{taler-developer-manual tipping-reserve-top-up}@anchor{1d}
+@section Tipping reserve top-up
+
+
+Both 'test' and 'demo' setups get their tip reserve topped up
+by a Buildbot worker. The following steps get the reserve topper
+prepared.
+
+@example
+# Log-in as <env>-topper, with <env> being either 'test' or 'demo'
+
+$ git clone git://git.taler.net/deployment
+$ ./deployment/prepare-reservetopper <env>
+
+# If the previous steps worked, then it should suffice to start
+# the worker, with:
+
+$ buildbot-worker start worker/
+@end example
+
+@node Producing auditor reports,Database schema versioning,Tipping reserve top-up,Environments and Builders on taler net
+@anchor{taler-developer-manual producing-auditor-reports}@anchor{1e}
+@section Producing auditor reports
+
+
+Both 'test' and 'demo' setups get their auditor reports compiled
+by a Buildbot worker. The following steps get the reports compiler
+prepared.
+
+@example
+# Log-in as <env>-auditor, with <env> being either 'test' or 'demo'
+
+$ git clone git://git.taler.net/deployment
+$ ./deployment/prepare-auditorreporter <env>
+
+# If the previous steps worked, then it should suffice to start
+# the worker, with:
+
+$ buildbot-worker start worker/
+@end example
+
+@node Database schema versioning,,Producing auditor reports,Environments and Builders on taler net
+@anchor{taler-developer-manual database-schema-versioning}@anchor{1f}
+@section Database schema versioning
+
+
+The Postgres databases of the exchange and the auditor are versioned.
+See the 0000.sql file in the respective directory for documentation.
+
+Every set of changes to the database schema must be stored in a new
+versioned SQL script. The scripts must have contiguous numbers. After
+any release (or version being deployed to a production or staging
+environment), existing scripts MUST be immutable.
+
+Developers and operators MUST NOT make changes to database schema
+outside of this versioning.
+
+@node Releases,Continuous integration,Environments and Builders on taler net,Top
+@anchor{taler-developer-manual releases}@anchor{20}
+@chapter Releases
+
+
+@menu
+* Release Process and Checklists::
+* Tagging::
+* Database for tests::
+* Exchange@comma{} merchant: Exchange merchant.
+* Wallet WebExtension::
+* Upload to GNU mirrors::
+* Creating Debian packages::
+
+@end menu
+
+@node Release Process and Checklists,Tagging,,Releases
+@anchor{taler-developer-manual release-process-and-checklists}@anchor{21}
+@section Release Process and Checklists
+
+
+Please use the @ref{1,,release checklist}
+
+This document describes the process for releasing a new version of the
+various Taler components to the official GNU mirrors.
+
+The following components are published on the GNU mirrors
+
+
+@itemize -
+
+@item
+taler-exchange (exchange.git)
+
+@item
+taler-merchant (merchant.git)
+
+@item
+talerdonations (donations.git)
+
+@item
+talerblog (blog.git)
+
+@item
+taler-bank (bank.git)
+
+@item
+taler-wallet-webex (wallet-webex.git)
+@end itemize
+
+@node Tagging,Database for tests,Release Process and Checklists,Releases
+@anchor{taler-developer-manual tagging}@anchor{22}
+@section Tagging
+
+
+Tag releases with an @strong{annotated} commit, like
+
+@example
+$ git tag -a v0.1.0 -m "Official release v0.1.0"
+$ git push origin v0.1.0
+@end example
+
+@node Database for tests,Exchange merchant,Tagging,Releases
+@anchor{taler-developer-manual database-for-tests}@anchor{23}
+@section Database for tests
+
+
+For tests in the exchange and merchant to run, make sure that a database
+@emph{talercheck} is accessible by @emph{$USER}. Otherwise tests involving the
+database logic are skipped.
+
+@node Exchange merchant,Wallet WebExtension,Database for tests,Releases
+@anchor{taler-developer-manual exchange-merchant}@anchor{24}
+@section Exchange, merchant
+
+
+Set the version in @code{configure.ac}. The commit being tagged should be
+the change of the version.
+
+Tag the current GANA version that works with the exchange and merchant and
+checkout that tag of gana.git (instead of master). Otherwise, if there are
+incompatible changes in GANA (like removed symbols), old builds could break.
+
+Update the Texinfo documentation using the files from docs.git:
+
+@example
+# Get the latest documentation repository
+$ cd $GIT/docs
+$ git pull
+$ make texinfo
+# The *.texi files are now in _build/texinfo
+#
+# This checks out the prebuilt branch in the prebuilt directory
+$ git worktree add prebuilt prebuilt
+$ cd prebuilt
+# Copy the pre-built documentation into the prebuilt directory
+$ cp -r ../_build/texinfo .
+# Push and commit to branch
+$ git commit -a -S -m "updating texinfo"
+$ git status
+# Verify that all files that should be tracked are tracked,
+# new files will have to be added to the Makefile.am in
+# exchange.git as well!
+$ git push
+# Remember $REVISION of commit
+#
+# Go to exchange
+$ cd $GIT/exchange/doc/prebuilt
+# Update submodule to point to latest commit
+$ git checkout $REVISION
+@end example
+
+Finally, the Automake @code{Makefile.am} files may have to be adjusted to
+include new @code{*.texi} files or images.
+
+For bootstrap, you will need to install
+GNU Recutils@footnote{https://www.gnu.org/software/recutils/}.
+
+For the exchange test cases to pass, @code{make install} must be run first.
+Without it, test cases will fail because plugins can't be located.
+
+@example
+$ ./bootstrap
+$ ./configure # add required options for your system
+$ make dist
+$ tar -xf taler-$COMPONENT-$VERSION.tar.gz
+$ cd taler-$COMPONENT-$VERSION
+$ make install check
+@end example
+
+@node Wallet WebExtension,Upload to GNU mirrors,Exchange merchant,Releases
+@anchor{taler-developer-manual wallet-webextension}@anchor{25}
+@section Wallet WebExtension
+
+
+The version of the wallet is in @emph{manifest.json}. The @code{version_name}
+should be adjusted, and @emph{version} should be increased independently on
+every upload to the WebStore.
+
+@example
+$ ./configure
+$ make dist
+@end example
+
+@node Upload to GNU mirrors,Creating Debian packages,Wallet WebExtension,Releases
+@anchor{taler-developer-manual upload-to-gnu-mirrors}@anchor{26}
+@section Upload to GNU mirrors
+
+
+See @indicateurl{https://www.gnu.org/prep/maintain/maintain.html#Automated-FTP-Uploads}
+
+Directive file:
+
+@example
+version: 1.2
+directory: taler
+filename: taler-exchange-0.1.0.tar.gz
+@end example
+
+Upload the files in @strong{binary mode} to the ftp servers.
+
+@node Creating Debian packages,,Upload to GNU mirrors,Releases
+@anchor{taler-developer-manual creating-debian-packages}@anchor{27}
+@section Creating Debian packages
+
+
+Our general setup is based on
+@indicateurl{https://wiki.debian.org/DebianRepository/SetupWithReprepro}
+
+First, update at least the version of the Debian package in
+debian/changelog, and then run:
+
+@example
+$ dpkg-buildpackage -rfakeroot -b -uc -us
+@end example
+
+in the respective source directory (GNUnet, exchange, merchant) to create the
+@code{.deb} files. Note that they will be created in the parent directory. This
+can be done on gv.taler.net, or on another (secure) machine.
+
+Next, the @code{*.deb} files should be copied to gv.taler.net, say to
+@code{/root/incoming}. Then, run
+
+@example
+# cd /var/www/repos/apt/debian/
+# reprepro includedeb sid /root/incoming/*.deb
+@end example
+
+to import all Debian files from @code{/root/incoming/} into the @code{sid}
+distribution. If Debian packages were build against other distributions,
+reprepro may need to be first configured for those and the import command
+updated accordingly.
+
+Finally, make sure to clean up @code{/root/incoming/} (by deleting the
+now imported @code{*.deb} files).
+
+@node Continuous integration,Internationalization,Releases,Top
+@anchor{taler-developer-manual continuous-integration}@anchor{28}
+@chapter Continuous integration
+
+
+CI is done with Buildbot (@indicateurl{https://buildbot.net/}), and builds are
+triggered by the means of Git hooks. The results are published at
+@indicateurl{https://buildbot.taler.net/} .
+
+In order to avoid downtimes, CI uses a "blue/green" deployment
+technique. In detail, there are two users building code on the system,
+the "green" and the "blue" user; and at any given time, one is running
+Taler services and the other one is either building the code or waiting
+for that.
+
+There is also the possibility to trigger builds manually, but this is
+only reserved to "admin" users.
+
+@node Internationalization,Android Apps,Continuous integration,Top
+@anchor{taler-developer-manual internationalization}@anchor{29}
+@chapter Internationalization
+
+
+Internationalization (a.k.a "Translation") is handled with Weblate (@indicateurl{https://weblate.org}) via our instance at @indicateurl{https://weblate.taler.net/} .
+
+At this time, this system is still very new for Taler.net and this documentation may be incorrect and is certainly incomplete.
+
+@menu
+* Who can Register::
+* About Privilege Levels::
+* Upgrading Privileges::
+* How to Create a Project::
+* How to Create a Component::
+* How to Create a Translation::
+* Translation Standards and Practices::
+* GPG Signing of Translations::
+
+@end menu
+
+@node Who can Register,About Privilege Levels,,Internationalization
+@anchor{taler-developer-manual who-can-register}@anchor{2a}
+@section Who can Register
+
+
+At this time, anyone can register an account at @indicateurl{https://weblate.taler.net/} to create translations. Registered users default to the @strong{Users} and @strong{Viewers} privilege level.
+
+@node About Privilege Levels,Upgrading Privileges,Who can Register,Internationalization
+@anchor{taler-developer-manual about-privilege-levels}@anchor{2b}
+@section About Privilege Levels
+
+
+This is the breakdown of privilege levels in Weblate:
+
+
+@itemize *
+
+@item
+@strong{Users}/@strong{Viewers} = Can log in, view Translations (@emph{applies to new users})
+
+@item
+@strong{Reviewers} = Can contribute Translations to existing @emph{Components}
+
+@item
+@strong{Managers} = Can create new @emph{Components} of existing @emph{Projects}
+
+@item
+@strong{Superusers} = Can create new @emph{Projects}
+@end itemize
+
+@node Upgrading Privileges,How to Create a Project,About Privilege Levels,Internationalization
+@anchor{taler-developer-manual upgrading-privileges}@anchor{2c}
+@section Upgrading Privileges
+
+
+To upgrade from @strong{Users}/@strong{Viewers}, a superuser must manually augment your privileges. At this time, superusers are Christian, Florian, and Buck.
+
+@node How to Create a Project,How to Create a Component,Upgrading Privileges,Internationalization
+@anchor{taler-developer-manual how-to-create-a-project}@anchor{2d}
+@section How to Create a Project
+
+
+The @emph{GNU Taler} project is probably the correct project for most Components and Translations falling under this guide. Please contact a superuser if you need another Project created.
+
+@node How to Create a Component,How to Create a Translation,How to Create a Project,Internationalization
+@anchor{taler-developer-manual how-to-create-a-component}@anchor{2e}
+@section How to Create a Component
+
+
+Reference: @indicateurl{https://docs.weblate.org/en/weblate-4.0.3/admin/projects.html#component-configuration}
+
+In Weblate, a @emph{Component} is a subset of a @emph{Project} and each Component contains N translations. A Component is generally associated with a Git repo.
+
+To create a Component, log into @indicateurl{https://weblate.taler.net/} with your @emph{Manager} or higher credentials and choose @strong{+ Add} from the upper-right corner.
+
+What follows is a sort of Wizard. You can find detailed docs at @indicateurl{https://docs.weblate.org/}. Here are some important notes about connecting your Component to the Taler Git repository:
+
+Under @emph{https://weblate.taler.net/create/component/vcs/}:
+
+
+@itemize *
+
+@item
+@strong{Source code repository} - Generally @code{git+ssh://git@@git.taler.net/<reponame>`}. Check with @code{git remote -v}.
+
+@item
+@strong{Repository branch} - Choose the correct branch to draw from and commit to.
+
+@item
+@strong{Repository push URL} - This is generally @code{git+ssh://git@@git.taler.net/<reponame>`} Check with @code{git remote -v}.
+
+@item
+@strong{Repository browser} - This is the www URL of the Git repo's file browser. Example @code{https://git.taler.net/<repositoryname>.git/tree/@{@{filename@}@}?h=@{@{branch@}@}#n@{@{line@}@}} where @code{<repositoryname>} gets replaced but @code{@{@{filename@}@}} and other items in braces are actual variables in the string.
+
+@item
+@strong{Merge style} - @emph{Rebase}, in line with GNU Taler development procedures
+
+@item
+@strong{Translation license} - @emph{GNU General Public License v3.0 or Later}
+
+@item
+@strong{Adding new translation} - Decide how to handle adding new translations
+@end itemize
+
+@node How to Create a Translation,Translation Standards and Practices,How to Create a Component,Internationalization
+@anchor{taler-developer-manual how-to-create-a-translation}@anchor{2f}
+@section How to Create a Translation
+
+
+1 - Log into @indicateurl{https://weblate.taler.net}
+
+2 - Navigate to @emph{Projects} > @emph{Browse all projects}
+
+3 - Choose the @emph{Project} you wish to contribute to.
+
+4 - Choose the @emph{Component} you wish to contribute to.
+
+5 - Find the language you want to translate into. Click "Translate" on that line.
+
+6 - Find a phrase and translate it.
+
+You may also wish to refer to @indicateurl{https://docs.weblate.org/} .
+
+@node Translation Standards and Practices,GPG Signing of Translations,How to Create a Translation,Internationalization
+@anchor{taler-developer-manual translation-standards-and-practices}@anchor{30}
+@section Translation Standards and Practices
+
+
+By default, our Weblate instance is set to accept translations in English, French, German, Italian, Russian, Spanish, and Portuguese. If you want to contribute a translation in a different language, navigate to the @emph{Component} you want to translate for, and click "Start new translation" to begin. If you require a privilege upgrade, please contact a superuser with your request.
+
+When asked, set the license to GPLv3 or later.
+
+Set commit/push to manual only.
+
+@node GPG Signing of Translations,,Translation Standards and Practices,Internationalization
+@anchor{taler-developer-manual gpg-signing-of-translations}@anchor{31}
+@section GPG Signing of Translations
+
+
+weblate.taler.net signs GPG commits with the GPG key CD33CE35801462FA5EB0B695F2664BF474BFE502, and the corresponding public key can be found at @indicateurl{https://weblate.taler.net/keys/}.
+
+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 the weblate key.
+
+@node Android Apps,Code Coverage,Internationalization,Top
+@anchor{taler-developer-manual android-apps}@anchor{32}
+@chapter Android Apps
+
+
+@menu
+* Android App Nightly Builds::
+* Building apps from source::
+* Update translations::
+* Release process::
+
+@end menu
+
+@node Android App Nightly Builds,Building apps from source,,Android Apps
+@anchor{taler-developer-manual android-app-nightly-builds}@anchor{33}
+@section Android App Nightly Builds
+
+
+There are currently three Android apps in
+the official Git repository@footnote{https://git.taler.net/taler-android.git}:
+
+
+@itemize *
+
+@item
+Wallet
+[CI@footnote{https://git.taler.net/taler-android.git/tree/wallet/.gitlab-ci.yml}]
+
+@item
+Merchant PoS Terminal
+[CI@footnote{https://git.taler.net/taler-android.git/tree/merchant-terminal/.gitlab-ci.yml}]
+
+@item
+Cashier
+[CI@footnote{https://git.taler.net/taler-android.git/tree/cashier/.gitlab-ci.yml}]
+@end itemize
+
+Their git repositories are mirrored at Gitlab@footnote{https://gitlab.com/gnu-taler/taler-android}
+to utilize their CI
+and F-Droid@footnote{https://f-droid.org}'s Gitlab integration
+to publish automatic nightly builds@footnote{https://f-droid.org/docs/Publishing_Nightly_Builds/}
+for each change on the @code{master} branch.
+
+All three apps publish their builds to the same F-Droid nightly repository
+(which is stored as a git repository):
+@indicateurl{https://gitlab.com/gnu-taler/fdroid-repo-nightly}
+
+You can download the APK files directly from that repository
+or add it to the F-Droid app for automatic updates
+by clicking the following link (on the phone that has F-Droid installed).
+
+@quotation
+
+GNU Taler Nightly F-Droid Repository@footnote{fdroidrepos://gnu-taler.gitlab.io/fdroid-repo-nightly/fdroid/repo?fingerprint=55F8A24F97FAB7B0960016AF393B7E57E7A0B13C2D2D36BAC50E1205923A7843}
+@end quotation
+
+@cartouche
+@quotation Note
+Nightly apps can be installed alongside official releases
+and thus are meant @strong{only for testing purposes}.
+Use at your own risk!
+@end quotation
+@end cartouche
+
+@node Building apps from source,Update translations,Android App Nightly Builds,Android Apps
+@anchor{taler-developer-manual build-apps-from-source}@anchor{34}@anchor{taler-developer-manual building-apps-from-source}@anchor{35}
+@section Building apps from source
+
+
+Note that this guide is different from other guides for building Android apps,
+because it does not require you to run non-free software.
+It uses the Merchant PoS Terminal as an example, but works as well for the other apps
+if you replace @code{merchant-terminal} with @code{wallet} or @code{cashier}.
+
+First, ensure that you have the required dependencies installed:
+
+
+@itemize *
+
+@item
+Java Development Kit 8 or higher (default-jdk-headless)
+
+@item
+git
+
+@item
+unzip
+@end itemize
+
+Then you can get the app's source code using git:
+
+@example
+# Start by cloning the Android git repository
+$ git clone https://git.taler.net/taler-android.git
+
+# Change into the directory of the cloned repository
+$ cd taler-android
+
+# Find out which Android SDK version you will need
+$ grep -i compileSdkVersion merchant-terminal/build.gradle
+@end example
+
+The last command will return something like @code{compileSdkVersion 29}.
+So visit the Android Rebuilds@footnote{http://android-rebuilds.beuc.net/} project
+and look for that version of the Android SDK there.
+If the SDK version is not yet available as a free rebuild,
+you can try to lower the @code{compileSdkVersion} in the app's @code{merchant-terminal/build.gradle} file.
+Note that this might break things
+or require you to also lower other versions such as @code{targetSdkVersion}.
+
+In our example, the version is @code{29} which is available,
+so download the "SDK Platform" package of "Android 10.0.0 (API 29)"
+and unpack it:
+
+@example
+# Change into the directory that contains your downloaded SDK
+$ cd $HOME
+
+# Unpack/extract the Android SDK
+$ unzip android-sdk_eng.10.0.0_r14_linux-x86.zip
+
+# Tell the build system where to find the SDK
+$ export ANDROID_SDK_ROOT="$HOME/android-sdk_eng.10.0.0_r14_linux-x86"
+
+# Change into the directory of the cloned repository
+$ cd taler-android
+
+# Build the merchant-terminal app
+$ ./gradlew :merchant-terminal:assembleRelease
+@end example
+
+If you get an error message complaining about build-tools
+
+@quotation
+
+
+@table @asis
+
+@item > Failed to install the following Android SDK packages as some licences have not been accepted.
+
+build-tools;29.0.3 Android SDK Build-Tools 29.0.3
+@end table
+@end quotation
+
+you can try changing the @code{buildToolsVersion} in the app's @code{merchant-terminal/build.gradle} file
+to the latest "Android SDK build tools" version supported by the Android Rebuilds project.
+
+After the build finished successfully,
+you will find your APK in @code{merchant-terminal/build/outputs/apk/release/}.
+
+@node Update translations,Release process,Building apps from source,Android Apps
+@anchor{taler-developer-manual update-translations}@anchor{36}
+@section Update translations
+
+
+Translations are managed with Taler's weblate instance:
+@indicateurl{https://weblate.taler.net/projects/gnu-taler/}
+
+To update translations, enter the taler-android git repository
+and ensure that the weblate remote exists:
+
+@example
+$ git config -l | grep weblate
+@end example
+
+If it does not yet exist (empty output), you can add it like this:
+
+@example
+$ git remote add weblate https://weblate.taler.net/git/gnu-taler/wallet-android/
+@end example
+
+Then you can merge in translations commit from the weblate remote:
+
+@example
+# ensure you have latest version
+$ git fetch weblate
+
+# merge in translation commits
+$ git merge weblate/master
+@end example
+
+Afterwards, build the entire project from source and test the UI
+to ensure that no erroneous translations (missing placeholders) are breaking things.
+
+@node Release process,,Update translations,Android Apps
+@anchor{taler-developer-manual release-process}@anchor{37}
+@section Release process
+
+
+After extensive testing, the code making up a new release should get a signed git tag.
+The current tag format is:
+
+
+@itemize *
+
+@item
+cashier-$VERSION
+
+@item
+pos-$VERSION
+
+@item
+wallet-$VERSION (where $VERSION has a v prefix)
+@end itemize
+
+@example
+$ git tag -s $APP-$VERSION
+@end example
+
+@menu
+* F-Droid::
+* Google Play::
+
+@end menu
+
+@node F-Droid,Google Play,,Release process
+@anchor{taler-developer-manual id1}@anchor{38}
+@subsection F-Droid
+
+
+Nightly builds get published automatically (see above) after pushing code to the official repo.
+Actual releases get picked up by F-Droid's official repository via git tags.
+So ensure that all releases get tagged properly.
+
+Some information for F-Droid official repository debugging:
+
+
+@itemize *
+
+@item
+Wallet: [metadata@footnote{https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/net.taler.wallet.fdroid.yml}] [build log@footnote{https://f-droid.org/wiki/page/net.taler.wallet.fdroid/lastbuild}]
+
+@item
+Cashier: [metadata@footnote{https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/net.taler.cashier.yml}] [build log@footnote{https://f-droid.org/wiki/page/net.taler.cashier/lastbuild}]
+
+@item
+PoS: [metadata@footnote{https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/net.taler.merchantpos.yml}] [build log@footnote{https://f-droid.org/wiki/page/net.taler.merchantpos/lastbuild}]
+@end itemize
+
+@node Google Play,,F-Droid,Release process
+@anchor{taler-developer-manual google-play}@anchor{39}
+@subsection Google Play
+
+
+Google Play uploads are managed via Fastlane@footnote{https://docs.fastlane.tools/getting-started/android/setup/}.
+Before proceeding, ensure that this is properly set up
+and that you have access to the Google Play API.
+
+To release an app, enter into its respective folder and run fastlane:
+
+@example
+$ bundle exec fastlane
+@end example
+
+Then select the deploy option.
+Note this requires access to the Google Play upload signing key
+set via the various environment variables in $app/fastlane/Fastfile.
+
+All uploads are going to the beta track by default.
+These can be promoted to production later or immediately after upload if you feel daring.
+
+@node Code Coverage,Coding Conventions,Android Apps,Top
+@anchor{taler-developer-manual id2}@anchor{3a}@anchor{taler-developer-manual id3}@anchor{3b}
+@chapter Code Coverage
+
+
+Code coverage is done with the Gcov / Lcov
+(@indicateurl{http://ltp.sourceforge.net/coverage/lcov.php}) combo, and it is run
+nightly (once a day) by a Buildbot worker. The coverage results are
+then published at @indicateurl{https://lcov.taler.net/} .
+
+@node Coding Conventions,Testing library,Code Coverage,Top
+@anchor{taler-developer-manual coding-conventions}@anchor{3c}
+@chapter Coding Conventions
+
+
+GNU Taler is developed primarily in C, Kotlin, Python and TypeScript.
+
+@menu
+* Components written in C::
+* Shell Scripts::
+* Kotlin::
+* Python::
+
+@end menu
+
+@node Components written in C,Shell Scripts,,Coding Conventions
+@anchor{taler-developer-manual components-written-in-c}@anchor{3d}
+@section Components written in C
+
+
+These are the general coding style rules for Taler.
+
+
+@itemize *
+
+@item
+Baseline rules are to follow GNU guidelines, modified or extended
+by the GNUnet style: @indicateurl{https://docs.gnunet.org/handbook/gnunet.html#Coding-style}
+@end itemize
+
+@menu
+* Naming conventions::
+
+@end menu
+
+@node Naming conventions,,,Components written in C
+@anchor{taler-developer-manual naming-conventions}@anchor{3e}
+@subsection Naming conventions
+
+
+
+@itemize *
+
+@item
+include files (very similar to GNUnet):
+
+
+@itemize *
+
+@item
+if installed, must start with "@code{taler_}" (exception: platform.h),
+and MUST live in src/include/
+
+@item
+if NOT installed, must NOT start with "@code{taler_}" and
+MUST NOT live in src/include/ and
+SHOULD NOT be included from outside of their own directory
+
+@item
+end in "_lib" for "simple" libraries
+
+@item
+end in "_plugin" for plugins
+
+@item
+end in "_service" for libraries accessing a service, i.e. the exchange
+@end itemize
+
+@item
+binaries:
+
+
+@itemize *
+
+@item
+taler-exchange-xxx: exchange programs
+
+@item
+taler-merchant-xxx: merchant programs (demos)
+
+@item
+taler-wallet-xxx: wallet programs
+
+@item
+plugins should be libtaler_plugin_xxx_yyy.so: plugin yyy for API xxx
+
+@item
+libtalerxxx: library for API xxx
+@end itemize
+
+@item
+logging
+
+
+@itemize *
+
+@item
+tools use their full name in GNUNET_log_setup
+(i.e. 'taler-exchange-offline') and log using plain 'GNUNET_log'.
+
+@item
+pure libraries (without associated service) use 'GNUNET_log_from'
+with the component set to their library name (without lib or '.so'),
+which should also be their directory name (i.e. 'util')
+
+@item
+plugin libraries (without associated service) use 'GNUNET_log_from'
+with the component set to their type and plugin name (without lib or '.so'),
+which should also be their directory name (i.e. 'exchangedb-postgres')
+
+@item
+libraries with associated service) use 'GNUNET_log_from'
+with the name of the service, which should also be their
+directory name (i.e. 'exchange')
+
+@item
+for tools with @code{-l LOGFILE}, its absence means write logs to stderr
+@end itemize
+
+@item
+configuration
+
+
+@itemize *
+
+@item
+same rules as for GNUnet
+@end itemize
+
+@item
+exported symbols
+
+
+@itemize *
+
+@item
+must start with TALER_[SUBSYSTEMNAME]_ where SUBSYSTEMNAME
+MUST match the subdirectory of src/ in which the symbol is defined
+
+@item
+from libtalerutil start just with @code{TALER_}, without subsystemname
+
+@item
+if scope is ONE binary and symbols are not in a shared library,
+use binary-specific prefix (such as TMH = taler-exchange-httpd) for
+globals, possibly followed by the subsystem (TMH_DB_xxx).
+@end itemize
+
+@item
+structs:
+
+
+@itemize *
+
+@item
+structs that are 'packed' and do not contain pointers and are
+thus suitable for hashing or similar operations are distinguished
+by adding a "P" at the end of the name. (NEW) Note that this
+convention does not hold for the GNUnet-structs (yet).
+
+@item
+structs that are used with a purpose for signatures, additionally
+get an "S" at the end of the name.
+@end itemize
+
+@item
+private (library-internal) symbols (including structs and macros)
+
+
+@itemize *
+
+@item
+must not start with @code{TALER_} or any other prefix
+@end itemize
+
+@item
+testcases
+
+
+@itemize *
+
+@item
+must be called "test_module-under-test_case-description.c"
+@end itemize
+
+@item
+performance tests
+
+
+@itemize *
+
+@item
+must be called "perf_module-under-test_case-description.c"
+@end itemize
+@end itemize
+
+@node Shell Scripts,Kotlin,Components written in C,Coding Conventions
+@anchor{taler-developer-manual shell-scripts}@anchor{3f}
+@section Shell Scripts
+
+
+Shell scripts should be avoided if at all possible. The only permissible uses of shell scripts
+in GNU Taler are:
+
+
+@itemize *
+
+@item
+Trivial invocation of other commands.
+
+@item
+Scripts for compatibility (e.g. @code{./configure}) that must run on
+as many systems as possible.
+@end itemize
+
+When shell scripts are used, they @code{MUST} begin with the following @code{set} command:
+
+@example
+# Make the shell fail on undefined variables and
+# commands with non-zero exit status.
+$ set -eu
+@end example
+
+@node Kotlin,Python,Shell Scripts,Coding Conventions
+@anchor{taler-developer-manual kotlin}@anchor{40}
+@section Kotlin
+
+
+We so far have no specific guidelines, please follow best practices
+for the language.
+
+@node Python,,Kotlin,Coding Conventions
+@anchor{taler-developer-manual python}@anchor{41}
+@section Python
+
+
+@menu
+* Supported Python Versions::
+* Style::
+* Python for Scripting::
+
+@end menu
+
+@node Supported Python Versions,Style,,Python
+@anchor{taler-developer-manual supported-python-versions}@anchor{42}
+@subsection Supported Python Versions
+
+
+Python code should be written and build against version 3.7 of Python.
+
+@node Style,Python for Scripting,Supported Python Versions,Python
+@anchor{taler-developer-manual style}@anchor{43}
+@subsection Style
+
+
+We use yapf@footnote{https://github.com/google/yapf} to reformat the
+code to conform to our style instructions.
+A reusable yapf style file can be found in @code{build-common},
+which is intended to be used as a git submodule.
+
+@node Python for Scripting,,Style,Python
+@anchor{taler-developer-manual python-for-scripting}@anchor{44}
+@subsection Python for Scripting
+
+
+When using Python for writing small utilities, the following libraries
+are useful:
+
+
+@itemize *
+
+@item
+@code{click} for argument parsing (should be preferred over argparse)
+
+@item
+@code{pathlib} for path manipulation (part of the standard library)
+
+@item
+@code{subprocess} for "shelling out" to other programs. Prefer @code{subprocess.run}
+over the older APIs.
+@end itemize
+
+@node Testing library,User-Facing Terminology,Coding Conventions,Top
+@anchor{taler-developer-manual testing-library}@anchor{45}
+@chapter Testing library
+
+
+This chapter is a VERY ABSTRACT description of how testing is
+implemented in Taler, and in NO WAY wants to substitute the reading of
+the actual source code by the user.
+
+In Taler, a test case is a array of @code{struct TALER_TESTING_Command},
+informally referred to as @code{CMD}, that is iteratively executed by the
+testing interpreter. This latter is transparently initiated by the
+testing library.
+
+However, the developer does not have to defined CMDs manually, but
+rather call the proper constructor provided by the library. For example,
+if a CMD is supposed to test feature @code{x}, then the library would
+provide the @code{TALER_TESTING_cmd_x ()} constructor for it. Obviously,
+each constructor has its own particular arguments that make sense to
+test @code{x}, and all constructor are thoroughly commented within the
+source code.
+
+Internally, each CMD has two methods: @code{run ()} and @code{cleanup ()}. The
+former contains the main logic to test feature @code{x}, whereas the latter
+cleans the memory up after execution.
+
+In a test life, each CMD needs some internal state, made by values it
+keeps in memory. Often, the test has to @emph{share} those values with other
+CMDs: for example, CMD1 may create some key material and CMD2 needs this
+key material to encrypt data.
+
+The offering of internal values from CMD1 to CMD2 is made by @emph{traits}. A
+trait is a @code{struct TALER_TESTING_Trait}, and each CMD contains a array
+of traits, that it offers via the public trait interface to other
+commands. The definition and filling of such array happens transparently
+to the test developer.
+
+For example, the following example shows how CMD2 takes an amount object
+offered by CMD1 via the trait interface.
+
+Note: the main interpreter and the most part of CMDs and traits are
+hosted inside the exchange codebase, but nothing prevents the developer
+from implementing new CMDs and traits within other codebases.
+
+@example
+/* Without loss of generality, let's consider the
+ * following logic to exist inside the run() method of CMD1 */
+...
+
+struct TALER_Amount *a;
+/**
+ * the second argument (0) points to the first amount object offered,
+ * in case multiple are available.
+ */
+if (GNUNET_OK != TALER_TESTING_get_trait_amount_obj (cmd2, 0, &a))
+ return GNUNET_SYSERR;
+...
+
+use(a); /* 'a' points straight into the internal state of CMD2 */
+@end example
+
+In the Taler realm, there is also the possibility to alter the behaviour
+of supposedly well-behaved components. This is needed when, for example,
+we want the exchange to return some corrupted signature in order to
+check if the merchant backend detects it.
+
+This alteration is accomplished by another service called @emph{twister}. The
+twister acts as a proxy between service A and B, and can be programmed
+to tamper with the data exchanged by A and B.
+
+Please refer to the Twister codebase (under the @code{test} directory) in
+order to see how to configure it.
+
+@node User-Facing Terminology,Developer Glossary,Testing library,Top
+@anchor{taler-developer-manual user-facing-terminology}@anchor{46}
+@chapter User-Facing Terminology
+
+
+This section contains terminology that should be used and that should not be
+used in the user interface and help materials.
+
+@menu
+* Terms to Avoid::
+* Terms to Use::
+
+@end menu
+
+@node Terms to Avoid,Terms to Use,,User-Facing Terminology
+@anchor{taler-developer-manual terms-to-avoid}@anchor{47}
+@section Terms to Avoid
+
+
+
+@table @asis
+
+@item Refreshing
+
+Refreshing is the internal technical terminology for the protocol to
+give change for partially spent coins
+
+@strong{Use instead}: "Obtaining change"
+
+@item Coin
+
+Coins are an internal construct, the user should never be aware that their balance
+is represented by coins if different denominations.
+
+@strong{Use instead}: "(Digital) Cash" or "(Wallet) Balance"
+
+@item Consumer
+
+Has bad connotation of consumption.
+
+@strong{Use instead}: Customer or user.
+
+@item Proposal
+
+The term used to describe the process of the merchant facilitating the download
+of the signed contract terms for an order.
+
+@strong{Avoid}. Generally events that relate to proposal downloads
+should not be shown to normal users, only developers. Instead, use
+"communication with mechant failed" if a proposed order can't be downloaded.
+
+@item Anonymous E-Cash
+
+Should be generally avoided, since Taler is only anonymous for
+the customer. Also some people are scared of anonymity (which as
+a term is also way too absolute, as anonymity is hardly ever perfect).
+
+@strong{Use instead}: "Privacy-preserving", "Privacy-friendly"
+
+@item Payment Replay
+
+The process of proving to the merchant that the customer is entitled
+to view a digital product again, as they already paid for it.
+
+@strong{Use instead}: In the event history, "re-activated digital content purchase"
+could be used. (FIXME: this is still not nice.)
+
+@item Session ID
+
+See Payment Replay.
+
+@item Order
+
+Too ambiguous in the wallet.
+
+@strong{Use instead}: Purchase
+
+@item Fulfillment URL
+
+URL that the serves the digital content that the user purchased
+with their payment. Can also be something like a donation receipt.
+@end table
+
+@node Terms to Use,,Terms to Avoid,User-Facing Terminology
+@anchor{taler-developer-manual terms-to-use}@anchor{48}
+@section Terms to Use
+
+
+
+@table @asis
+
+@item Auditor
+
+Regulatory entity that certifies exchanges and oversees their operation.
+
+@item Exchange Operator
+
+The entity/service that gives out digital cash in exchange for some
+other means of payment.
+
+In some contexts, using "Issuer" could also be appropriate.
+When showing a balance breakdown,
+we can say "100 Eur (issued by exchange.euro.taler.net)".
+Sometimes we may also use the more generic term "Payment Service Provider"
+when the concept of an "Exchange" is still unclear to the reader.
+
+@item Refund
+
+A refund is given by a merchant to the customer (rather the customer's wallet)
+and "undoes" a previous payment operation.
+
+@item Payment
+
+The act of sending digital cash to a merchant to pay for an order.
+
+@item Purchase
+
+Used to refer to the "result" of a payment, as in "view purchase".
+Use sparsingly, as the word doesn't fit for all payments, such as donations.
+
+@item Contract Terms
+
+Partially machine-readable representation of the merchant's obligation after the
+customer makes a payment.
+
+@item Merchant
+
+Party that receives a payment.
+
+@item Wallet
+
+Also "Taler Wallet". Software component that manages the user's digital cash
+and payments.
+@end table
+
+@node Developer Glossary,Developer Tools,User-Facing Terminology,Top
+@anchor{taler-developer-manual developer-glossary}@anchor{49}
+@chapter Developer Glossary
+
+
+This glossary is meant for developers. It contains some terms that we usually do not
+use when talking to end users or even system administrators.
+
+
+@table @asis
+@anchor{taler-developer-manual term-absolute-time}@anchor{4a}
+@geindex absolute time
+
+@item absolute time
+
+method of keeping time in @ref{4b,,GNUnet} where the time is represented
+as the number of microseconds since 1.1.1970 (UNIX epoch). Called
+absolute time in contrast to @ref{4c,,relative time}.
+@anchor{taler-developer-manual term-aggregate}@anchor{4d}
+@geindex aggregate
+
+@item aggregate
+
+the @ref{4e,,exchange} combines multiple payments received by the
+same @ref{4f,,merchant} into one larger @ref{50,,wire transfer} to
+the respective merchant's @ref{51,,bank} account
+@anchor{taler-developer-manual term-auditor}@anchor{52}
+@geindex auditor
+
+@item auditor
+
+trusted third party that verifies that the @ref{4e,,exchange} is operating correctly
+@anchor{taler-developer-manual term-bank}@anchor{51}
+@geindex bank
+
+@item bank
+
+traditional financial service provider who offers wire @ref{53,,transfers} between accounts
+@anchor{taler-developer-manual term-buyer}@anchor{54}
+@geindex buyer
+
+@item buyer
+
+individual in control of a Taler @ref{55,,wallet}, usually using it to
+@ref{56,,spend} the @ref{57,,coins} on @ref{58,,contracts} (see also @ref{59,,customer}).
+@anchor{taler-developer-manual term-close}@anchor{5a}
+@geindex close
+
+@item close@anchor{taler-developer-manual term-closes}@anchor{5b}
+@geindex closes
+
+@itemx closes@anchor{taler-developer-manual term-closed}@anchor{5c}
+@geindex closed
+
+@itemx closed@anchor{taler-developer-manual term-closing}@anchor{5d}
+@geindex closing
+
+@itemx closing
+
+operation an @ref{4e,,exchange} performs on a @ref{5e,,reserve} that has not been
+@ref{5f,,drained} by @ref{60,,withdraw} operations. When closing a reserve, the
+exchange wires the remaining funds back to the customer, minus a @ref{61,,fee}
+for closing
+@anchor{taler-developer-manual term-coin}@anchor{62}
+@geindex coin
+
+@item coin@anchor{taler-developer-manual term-coins}@anchor{57}
+@geindex coins
+
+@itemx coins
+
+coins are individual token representing a certain amount of value, also known as the @ref{63,,denomination} of the coin
+@anchor{taler-developer-manual term-commitment}@anchor{64}
+@geindex commitment
+
+@item commitment@anchor{taler-developer-manual term-refresh-commitment}@anchor{65}
+@geindex refresh commitment
+
+@itemx refresh commitment
+
+data that the wallet commits to during the @ref{66,,melt} stage of the
+@ref{67,,refresh} protocol where it
+has to prove to the @ref{4e,,exchange} that it is deriving the @ref{68,,fresh}
+coins as specified by the Taler protocol. The commitment is verified
+probabilistically (see: @ref{69,,kappa}) during the @ref{6a,,reveal} stage.
+@anchor{taler-developer-manual term-contract}@anchor{6b}
+@geindex contract
+
+@item contract@anchor{taler-developer-manual term-contracts}@anchor{58}
+@geindex contracts
+
+@itemx contracts
+
+formal agreement between @ref{4f,,merchant} and @ref{59,,customer} specifying the
+@ref{6c,,contract terms} and signed by the merchant and the @ref{57,,coins} of the
+customer
+@anchor{taler-developer-manual term-contract-terms}@anchor{6c}
+@geindex contract terms
+
+@item contract terms
+
+the individual clauses specifying what the buyer is purchasing from the
+@ref{4f,,merchant}
+@anchor{taler-developer-manual term-customer}@anchor{59}
+@geindex customer
+
+@item customer
+
+individual that directs the buyer (perhaps the same individual) to make a purchase
+@anchor{taler-developer-manual term-denomination}@anchor{63}
+@geindex denomination
+
+@item denomination
+
+unit of currency, specifies both the currency and the face value of a @ref{62,,coin},
+as well as associated fees and validity periods
+@anchor{taler-developer-manual term-denomination-key}@anchor{6d}
+@geindex denomination key
+
+@item denomination key
+
+(RSA) key used by the exchange to certify that a given @ref{62,,coin} is valid and of a
+particular @ref{63,,denomination}
+@anchor{taler-developer-manual term-deposit}@anchor{6e}
+@geindex deposit
+
+@item deposit@anchor{taler-developer-manual term-deposits}@anchor{6f}
+@geindex deposits
+
+@itemx deposits@anchor{taler-developer-manual term-depositing}@anchor{70}
+@geindex depositing
+
+@itemx depositing
+
+operation by which a merchant passes coins to an exchange, expecting the
+exchange to credit his bank account in the future using an
+@ref{4d,,aggregate} @ref{50,,wire transfer}
+@anchor{taler-developer-manual term-dirty}@anchor{71}
+@geindex dirty
+
+@item dirty@anchor{taler-developer-manual term-dirty-coin}@anchor{72}
+@geindex dirty coin
+
+@itemx dirty coin
+
+a coin is dirty if its public key may be known to an entity other than
+the customer, thereby creating the danger of some entity being able to
+link multiple transactions of coin's owner if the coin is not refreshed
+@anchor{taler-developer-manual term-drain}@anchor{73}
+@geindex drain
+
+@item drain@anchor{taler-developer-manual term-drained}@anchor{5f}
+@geindex drained
+
+@itemx drained
+
+a @ref{5e,,reserve} is being drained when a @ref{55,,wallet} is using the
+reserve's private key to @ref{60,,withdraw} coins from it. This reduces
+the balance of the reserve. Once the balance reaches zero, we say that
+the reserve has been (fully) drained. Reserves that are not drained
+(which is the normal process) are @ref{5c,,closed} by the exchange.
+@anchor{taler-developer-manual term-exchange}@anchor{4e}
+@geindex exchange
+
+@item exchange
+
+Taler's payment service operator. Issues electronic coins during
+withdrawal and redeems them when they are deposited by merchants
+@anchor{taler-developer-manual term-expired}@anchor{74}
+@geindex expired
+
+@item expired@anchor{taler-developer-manual term-expiration}@anchor{75}
+@geindex expiration
+
+@itemx expiration
+
+Various operations come with time limits. In particular, denomination keys
+come with strict time limits for the various operations involving the
+coin issued under the denomination. The most important limit is the
+deposit expiration, which specifies until when wallets are allowed to
+use the coin in deposit or refreshing operations. There is also a "legal"
+expiration, which specifies how long the exchange keeps records beyond the
+deposit expiration time. This latter expiration matters for legal disputes
+in courts and also creates an upper limit for refreshing operations on
+special zombie coin
+@anchor{taler-developer-manual term-fakebank}@anchor{76}
+@geindex fakebank
+
+@item fakebank
+
+implementation of the @ref{51,,bank} API in memory to be used only for test
+cases.
+@anchor{taler-developer-manual term-fee}@anchor{61}
+@geindex fee
+
+@item fee
+
+an @ref{4e,,exchange} charges various fees for its service. The different
+fees are specified in the protocol. There are fees per coin for
+@ref{77,,withdrawing}, @ref{70,,depositing}, @ref{78,,melting}, and
+@ref{79,,refunding}. Furthermore, there are fees per wire transfer
+for @ref{5d,,closing} a @ref{5e,,reserve}: and for
+@ref{4d,,aggregate} @ref{7a,,wire transfers} to the @ref{4f,,merchant}.
+@anchor{taler-developer-manual term-fresh}@anchor{68}
+@geindex fresh
+
+@item fresh@anchor{taler-developer-manual term-fresh-coin}@anchor{7b}
+@geindex fresh coin
+
+@itemx fresh coin
+
+a coin is fresh if its public key is only known to the customer
+@anchor{taler-developer-manual term-GNUnet}@anchor{4b}
+@geindex GNUnet
+
+@item GNUnet
+
+Codebase of various libraries for a better Internet, some of which
+GNU Taler depends upon.
+@anchor{taler-developer-manual term-json}@anchor{7c}
+@geindex json
+
+@item json@anchor{taler-developer-manual term-JSON}@anchor{7d}
+@geindex JSON
+
+@itemx JSON@anchor{taler-developer-manual term-JavaScript-Object-Notation}@anchor{7e}
+@geindex JavaScript Object Notation
+
+@itemx JavaScript Object Notation
+
+serialization format derived from the JavaScript language which is
+commonly used in the Taler protocol as the payload of HTTP requests
+and responses.
+@anchor{taler-developer-manual term-kappa}@anchor{69}
+@geindex kappa
+
+@item kappa
+
+security parameter used in the @ref{67,,refresh} protocol. Defined to be 3.
+The probability of successfully evading the income transparency with the
+refresh protocol is 1:kappa.
+@anchor{taler-developer-manual term-LibEuFin}@anchor{7f}
+@geindex LibEuFin
+
+@item LibEuFin
+
+FIXME: explain
+@anchor{taler-developer-manual term-link}@anchor{80}
+@geindex link
+
+@item link@anchor{taler-developer-manual term-linking}@anchor{81}
+@geindex linking
+
+@itemx linking
+
+specific step in the @ref{67,,refresh} protocol that an exchange must offer
+to prevent abuse of the @ref{67,,refresh} mechanism. The link step is
+not needed in normal operation, it just must be offered.
+@anchor{taler-developer-manual term-master-key}@anchor{82}
+@geindex master key
+
+@item master key
+
+offline key used by the exchange to certify denomination keys and
+message signing keys
+@anchor{taler-developer-manual term-melt}@anchor{66}
+@geindex melt
+
+@item melt@anchor{taler-developer-manual term-melted}@anchor{83}
+@geindex melted
+
+@itemx melted@anchor{taler-developer-manual term-melting}@anchor{78}
+@geindex melting
+
+@itemx melting
+
+step of the @ref{67,,refresh} protocol where a @ref{72,,dirty coin}
+is invalidated to be reborn @ref{68,,fresh} in a subsequent
+@ref{6a,,reveal} step.
+@anchor{taler-developer-manual term-merchant}@anchor{4f}
+@geindex merchant
+
+@item merchant
+
+party receiving payments (usually in return for goods or services)
+@anchor{taler-developer-manual term-message-signing-key}@anchor{84}
+@geindex message signing key
+
+@item message signing key
+
+key used by the exchange to sign online messages, other than coins
+@anchor{taler-developer-manual term-order}@anchor{85}
+@geindex order
+
+@item order
+
+FIXME: to be written!
+@anchor{taler-developer-manual term-owner}@anchor{86}
+@geindex owner
+
+@item owner
+
+a coin is owned by the entity that knows the private key of the coin
+@anchor{taler-developer-manual term-planchet}@anchor{87}
+@geindex planchet
+
+@item planchet
+
+precursor data for a @ref{62,,coin}. A planchet includes the coin's internal
+secrets (coin private key, blinding factor), but lacks the RSA signature
+of the @ref{4e,,exchange}. When @ref{77,,withdrawing}, a @ref{55,,wallet}
+creates and persists a planchet before asking the exchange to sign it to
+get the coin.
+@anchor{taler-developer-manual term-privacy-policy}@anchor{88}
+@geindex privacy policy
+
+@item privacy policy
+
+Statement of an operator how they will protect the privacy of users.
+@anchor{taler-developer-manual term-proof}@anchor{89}
+@geindex proof
+
+@item proof
+
+Message that cryptographically demonstrates that a particular claim is correct.
+@anchor{taler-developer-manual term-proposal}@anchor{8a}
+@geindex proposal
+
+@item proposal
+
+a list of @ref{6c,,contract terms} that has been completed and signed by the
+merchant backend.
+@anchor{taler-developer-manual term-purchase}@anchor{8b}
+@geindex purchase
+
+@item purchase
+
+Refers to the overall process of negotiating a @ref{6b,,contract} and then
+making a payment with @ref{57,,coins} to a @ref{4f,,merchant}.
+@anchor{taler-developer-manual term-recoup}@anchor{8c}
+@geindex recoup
+
+@item recoup
+
+Operation by which an exchange returns the value of coins affected
+by a @ref{8d,,revocation} to their @ref{86,,owner}, either by allowing the owner to
+withdraw new coins or wiring funds back to the bank account of the @ref{86,,owner}.
+@anchor{taler-developer-manual term-refresh}@anchor{67}
+@geindex refresh
+
+@item refresh@anchor{taler-developer-manual term-refreshing}@anchor{8e}
+@geindex refreshing
+
+@itemx refreshing
+
+operation by which a @ref{72,,dirty coin} is converted into one or more
+@ref{68,,fresh} coins. Involves @ref{78,,melting} the @ref{72,,dirty coin} and
+then @ref{8f,,revealing} so-called @ref{90,,transfer keys}.
+@anchor{taler-developer-manual term-refund}@anchor{91}
+@geindex refund
+
+@item refund@anchor{taler-developer-manual term-refunding}@anchor{79}
+@geindex refunding
+
+@itemx refunding
+
+operation by which a merchant steps back from the right to funds that he
+obtained from a @ref{6e,,deposit} operation, giving the right to the funds back
+to the customer
+@anchor{taler-developer-manual term-refund-transaction-id}@anchor{92}
+@geindex refund transaction id
+
+@item refund transaction id
+
+unique number by which a merchant identifies a @ref{91,,refund}. Needed
+as refunds can be partial and thus there could be multiple refunds for
+the same @ref{8b,,purchase}.
+@anchor{taler-developer-manual term-relative-time}@anchor{4c}
+@geindex relative time
+
+@item relative time
+
+method of keeping time in @ref{4b,,GNUnet} where the time is represented
+as a relative number of microseconds. Thus, a relative time specifies
+an offset or a duration, but not a date. Called relative time in
+contrast to @ref{4a,,absolute time}.
+@anchor{taler-developer-manual term-reserve}@anchor{5e}
+@geindex reserve
+
+@item reserve
+
+accounting mechanism used by the exchange to track customer funds
+from incoming @ref{7a,,wire transfers}. A reserve is created whenever
+a customer wires money to the exchange using a well-formed public key
+in the subject. The exchange then allows the customer's @ref{55,,wallet}
+to @ref{60,,withdraw} up to the amount received in @ref{68,,fresh}
+@ref{57,,coins} from the reserve, thereby draining the reserve. If a
+reserve is not drained, the exchange eventually @ref{5b,,closes} it.
+
+Other definition: Funds set aside for future use; either the balance of a customer at the
+exchange ready for withdrawal, or the funds kept in the exchange;s bank
+account to cover obligations from coins in circulation.
+@anchor{taler-developer-manual term-reveal}@anchor{6a}
+@geindex reveal
+
+@item reveal@anchor{taler-developer-manual term-revealing}@anchor{8f}
+@geindex revealing
+
+@itemx revealing
+
+step in the @ref{67,,refresh} protocol where some of the transfer private
+keys are revealed to prove honest behavior on the part of the wallet.
+In the reveal step, the exchange returns the signed @ref{68,,fresh} coins.
+@anchor{taler-developer-manual term-revoke}@anchor{93}
+@geindex revoke
+
+@item revoke@anchor{taler-developer-manual term-revocation}@anchor{8d}
+@geindex revocation
+
+@itemx revocation
+
+exceptional operation by which an exchange withdraws a denomination from
+circulation, either because the signing key was compromised or because
+the exchange is going out of operation; unspent coins of a revoked
+denomination are subjected to recoup.
+@anchor{taler-developer-manual term-sharing}@anchor{94}
+@geindex sharing
+
+@item sharing
+
+users can share ownership of a @ref{62,,coin} by sharing access to the coin&#39;s
+private key, thereby allowing all co-owners to spend the coin at any
+time.
+@anchor{taler-developer-manual term-spend}@anchor{56}
+@geindex spend
+
+@item spend@anchor{taler-developer-manual term-spending}@anchor{95}
+@geindex spending
+
+@itemx spending
+
+operation by which a customer gives a merchant the right to deposit
+coins in return for merchandise
+@anchor{taler-developer-manual term-terms}@anchor{96}
+@geindex terms
+
+@item terms
+
+the general terms of service of an operator, possibly including
+the @ref{88,,privacy policy}. Not to be confused with the
+@ref{6c,,contract terms} which are about the specific purchase.
+@anchor{taler-developer-manual term-transaction}@anchor{97}
+@geindex transaction
+
+@item transaction
+
+method by which ownership is exclusively transferred from one entity
+@anchor{taler-developer-manual term-transfer}@anchor{53}
+@geindex transfer
+
+@item transfer@anchor{taler-developer-manual term-transfers}@anchor{98}
+@geindex transfers
+
+@itemx transfers@anchor{taler-developer-manual term-wire-transfer}@anchor{50}
+@geindex wire transfer
+
+@itemx wire transfer@anchor{taler-developer-manual term-wire-transfers}@anchor{7a}
+@geindex wire transfers
+
+@itemx wire transfers
+
+method of sending funds between @ref{51,,bank} accounts
+@anchor{taler-developer-manual term-transfer-key}@anchor{99}
+@geindex transfer key
+
+@item transfer key@anchor{taler-developer-manual term-transfer-keys}@anchor{90}
+@geindex transfer keys
+
+@itemx transfer keys
+
+special cryptographic key used in the @ref{67,,refresh} protocol, some of which
+are revealed during the @ref{6a,,reveal} step. Note that transfer keys have,
+despite the name, no relationship to @ref{7a,,wire transfers}. They merely
+help to transfer the value from a @ref{72,,dirty coin} to a @ref{7b,,fresh coin}
+@anchor{taler-developer-manual term-user}@anchor{9a}
+@geindex user
+
+@item user
+
+any individual using the Taler payment system
+(see @ref{59,,customer}, @ref{54,,buyer}, @ref{4f,,merchant}).
+@anchor{taler-developer-manual term-version}@anchor{9b}
+@geindex version
+
+@item version
+
+Taler uses various forms of versioning. There is a database
+schema version (stored itself in the database, see *-0000.sql) describing
+the state of the table structure in the database of an @ref{4e,,exchange},
+@ref{52,,auditor} or @ref{4f,,merchant}. There is a protocol
+version (CURRENT:REVISION:AGE, see GNU libtool) which specifies
+the network protocol spoken by an @ref{4e,,exchange} or @ref{4f,,merchant}
+including backwards-compatibility. And finally there is the software
+release version (MAJOR.MINOR.PATCH, see @indicateurl{https://semver.org/}) of
+the respective code base.
+@anchor{taler-developer-manual term-wallet}@anchor{55}
+@geindex wallet
+
+@item wallet
+
+software running on a customer's computer; withdraws, stores and
+spends coins
+@anchor{taler-developer-manual term-WebExtension}@anchor{9c}
+@geindex WebExtension
+
+@item WebExtension
+
+Cross-browser API used to implement the GNU Taler wallet browser extension.
+@anchor{taler-developer-manual term-wire-gateway}@anchor{9d}
+@geindex wire gateway
+
+@item wire gateway
+
+FIXME: explain
+@anchor{taler-developer-manual term-wire-transfer-identifier}@anchor{9e}
+@geindex wire transfer identifier
+
+@item wire transfer identifier@anchor{taler-developer-manual term-wtid}@anchor{9f}
+@geindex wtid
+
+@itemx wtid
+
+Subject of a wire transfer from the exchange to a merchant;
+set by the aggregator to a random nonce which uniquely
+identifies the transfer.
+@anchor{taler-developer-manual term-withdraw}@anchor{60}
+@geindex withdraw
+
+@item withdraw@anchor{taler-developer-manual term-withdrawing}@anchor{77}
+@geindex withdrawing
+
+@itemx withdrawing@anchor{taler-developer-manual term-withdrawal}@anchor{a0}
+@geindex withdrawal
+
+@itemx withdrawal
+
+operation by which a @ref{55,,wallet} can convert funds from a @ref{5e,,reserve} to
+fresh coins
+@anchor{taler-developer-manual term-zombie}@anchor{a1}
+@geindex zombie
+
+@item zombie@anchor{taler-developer-manual term-zombie-coin}@anchor{a2}
+@geindex zombie coin
+
+@itemx zombie coin
+
+coin where the respective @ref{6d,,denomination key} is past its
+@ref{6e,,deposit} @ref{75,,expiration} time, but which is still (again) valid
+for an operation because it was @ref{83,,melted} while it was still
+valid, and then later again credited during a @ref{8c,,recoup} process
+@end table
+
+@node Developer Tools,Index,Developer Glossary,Top
+@anchor{taler-developer-manual developer-tools}@anchor{a3}
+@chapter Developer Tools
+
+
+This section describes various internal programs to make life easier for the
+developer.
+
+@menu
+* taler-config-generate::
+
+@end menu
+
+@node taler-config-generate,,,Developer Tools
+@anchor{taler-developer-manual taler-config-generate}@anchor{a4}
+@section taler-config-generate
+
+
+@strong{taler-config-generate} - tool to simplify Taler configuration generation
+
+@strong{taler-config-generate}
+[@strong{-C} @emph{CURRENCY} | @strong{––currency=}‌@emph{CURRENCY}]
+[@strong{-c} @emph{FILENAME} | @strong{––config=}‌@emph{FILENAME}]
+[@strong{-e} | @strong{––exchange}]
+[@strong{-f} @emph{AMOUNT} | @emph{––wirefee=}‌@emph{AMOUNT}]
+[@strong{-h} | @strong{––help}]
+[@strong{-J} @emph{JSON} | @strong{––wire-json-exchange=}‌@emph{JSON}]
+[@strong{-j} @emph{JSON} | @strong{––wire-json-merchant=}‌@emph{JSON}]
+[@strong{-L} @emph{LOGLEVEL} | @strong{––loglevel=}‌@emph{LOGLEVEL}]
+[@strong{-m} | @strong{––merchant}]
+[@strong{-t} | @strong{––trusted}]
+[@strong{-v} | @strong{––version}]
+[@strong{-w} @emph{WIREFORMAT} | @strong{––wire} @emph{WIREFORMAT}]
+[@strong{––bank-uri}]
+[@strong{––exchange-bank-account}]
+[@strong{––merchant-bank-account}]
+
+@strong{taler-config-generate} can be used to generate configuration files
+for the Taler exchange or Taler merchants.
+
+
+@table @asis
+
+@item @strong{-C} @emph{CURRENCY} | @strong{––currency=}‌@emph{CURRENCY}
+
+Which currency should we use in the configuration.
+
+@item @strong{-c} @emph{FILENAME} | @strong{––config=}‌@emph{FILENAME}
+
+Location where to write the generated configuration. Existing file
+will be updated, not overwritten.
+
+@item @strong{-e} | @strong{––exchange}
+
+Generate configuration for a Taler exchange.
+
+@item @strong{-f} @emph{AMOUNT} | @emph{-wirefee=}‌@emph{AMOUNT}
+
+Setup wire transfer fees for the next 5 years for the exchange (for
+all wire methods).
+
+@item @strong{-h} | @strong{––help}
+
+Shows this man page.
+
+@item @strong{-J} @emph{JSON} | @strong{––wire-json-exchange=}‌@emph{JSON}
+
+Wire configuration to use for the exchange.
+
+@item @strong{-j} @emph{JSON} | @strong{––wire-json-merchant=}‌@emph{JSON}
+
+Wire configuration to use for the merchant.
+
+@item @strong{-L} @emph{LOGLEVEL} | @strong{––loglevel=}‌@emph{LOGLEVEL}
+
+Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and
+ERROR.
+
+@item @strong{-m} | @strong{––merchant}
+
+Generate configuration for a Taler merchant.
+
+@item @strong{-t} | @strong{––trusted}
+
+Setup current exchange as trusted with current merchant. Generally
+only useful when configuring for testcases.
+
+@item @strong{-v} | @strong{––version}
+
+Print version information.
+
+@item @strong{-w} @emph{WIREFORMAT} | @strong{––wire} @emph{WIREFORMAT}
+
+Specifies which wire format to use (i.e. “test” or “sepa”)
+
+@item @strong{––bank-uri}
+
+Alternative to specify wire configuration to use for the exchange and
+merchant for the “test” wire method. Only useful if WIREFORMAT was
+set to “test”. Specifies the URI of the bank.
+
+@item @strong{––exchange-bank-account}
+
+Alternative to specify wire configuration to use for the exchange for
+the “test” wire method. Only useful if WIREFORMAT was set to “test”.
+Specifies the bank account number of the exchange.
+
+@item @strong{––merchant-bank-account}
+
+Alternative to specify wire configuration to use for the merchant for
+the “test” wire method. Only useful if WIREFORMAT was set to “test”.
+Specifies the bank account number of the merchant.
+@end table
+
+@node Index,,Developer Tools,Top
+@unnumbered Index
+
+
+@printindex ge
+
+
+@c %**end of body
+@bye
diff --git a/texinfo/taler-exchange-figures/anastasis-db.png b/texinfo/taler-exchange-figures/anastasis-db.png
new file mode 100644
index 00000000..03eed9da
--- /dev/null
+++ b/texinfo/taler-exchange-figures/anastasis-db.png
Binary files differ
diff --git a/texinfo/taler-exchange-figures/anastasis_challenge_payment.png b/texinfo/taler-exchange-figures/anastasis_challenge_payment.png
new file mode 100644
index 00000000..a0593eba
--- /dev/null
+++ b/texinfo/taler-exchange-figures/anastasis_challenge_payment.png
Binary files differ
diff --git a/texinfo/taler-exchange-figures/anastasis_challengecode.png b/texinfo/taler-exchange-figures/anastasis_challengecode.png
new file mode 100644
index 00000000..fc30f4fe
--- /dev/null
+++ b/texinfo/taler-exchange-figures/anastasis_challengecode.png
Binary files differ
diff --git a/texinfo/taler-exchange-figures/anastasis_reducer_backup.png b/texinfo/taler-exchange-figures/anastasis_reducer_backup.png
new file mode 100644
index 00000000..87b0a9b4
--- /dev/null
+++ b/texinfo/taler-exchange-figures/anastasis_reducer_backup.png
Binary files differ
diff --git a/texinfo/taler-exchange-figures/anastasis_reducer_recovery.png b/texinfo/taler-exchange-figures/anastasis_reducer_recovery.png
new file mode 100644
index 00000000..7d3cc9ae
--- /dev/null
+++ b/texinfo/taler-exchange-figures/anastasis_reducer_recovery.png
Binary files differ
diff --git a/texinfo/taler-exchange-figures/anastasis_truth.png b/texinfo/taler-exchange-figures/anastasis_truth.png
new file mode 100644
index 00000000..7f23fa21
--- /dev/null
+++ b/texinfo/taler-exchange-figures/anastasis_truth.png
Binary files differ
diff --git a/texinfo/taler-exchange-figures/anastasis_truth_payment.png b/texinfo/taler-exchange-figures/anastasis_truth_payment.png
new file mode 100644
index 00000000..70a6b3df
--- /dev/null
+++ b/texinfo/taler-exchange-figures/anastasis_truth_payment.png
Binary files differ
diff --git a/texinfo/taler-exchange.texi b/texinfo/taler-exchange.texi
index ed44281e..4163e74f 100644
--- a/texinfo/taler-exchange.texi
+++ b/texinfo/taler-exchange.texi
@@ -21,11 +21,11 @@
@copying
@quotation
-GNU Taler 0.8.0pre0, Jan 27, 2021
+GNU Taler 0.8.0pre0, Apr 26, 2021
GNU Taler team
-Copyright @copyright{} 2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+Copyright @copyright{} 2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
@end quotation
@end copying
@@ -265,7 +265,7 @@ binary is the @code{taler-exchange-httpd}.
@item
Crypto-Helpers
The @code{taler-exchange-secmod-rsa} and @code{taler-exchange-secmod-eddsa}
-are two programs that are responsible for managing the exchange’s
+are two programs that are responsible for managing the exchange's
online signing keys. They must run on the same machine as the
@code{taler-exchange-httpd} as the HTTP frontend communicates with the
crypto helpers using UNIX Domain Sockets.
@@ -284,7 +284,7 @@ Closer
The @code{taler-exchange-closer} tool check that reserves are properly
closed. If a customer wires funds to an exchange and then fails
to withdraw them, the closer will (eventually) trigger a wire
-transfer that sends the customer’s funds back to the originating
+transfer that sends the customer's funds back to the originating
wire account.
@item
@@ -325,7 +325,7 @@ the Python bank provides a bank that directly provides
the wire adapter API.
@item
-For production, libeufin’s Nexus component implements a wire
+For production, libeufin's Nexus component implements a wire
adapter towards the traditional SEPA banking system with IBAN
accounts.
@end enumerate
@@ -362,7 +362,7 @@ copy of the database.
The exchange (and ideally also auditors) uses a long-term offline master
siging key that identifies the operator and is used to authenticate critical
-information, such as the exchange’s bank account and the actual keys the
+information, such as the exchange's bank account and the actual keys the
exchange uses online.
Interactions with the offline system are performed using the
@@ -407,7 +407,7 @@ integration support.
The UNIX domain sockets have mode 0620 (u+rw, g+w). The exchange process
-MUST be in the same group as the the crypto helper processes.
+MUST be in the same group as the crypto helper processes.
The two helper processes will create the required private keys, and allow
anyone with access to the UNIX domain socket to sign arbitrary messages with
@@ -421,7 +421,7 @@ expires or if they are informed about a key having been revoked.
From a security point of view, the helpers are designed to @emph{only} make it
-harder for an attacker who took control of the HTTP daemon’s account to
+harder for an attacker who took control of the HTTP daemon's account to
extract the private keys, limiting the attackers ability to creating
signatures to the duration of their control of that account.
@@ -441,8 +441,8 @@ The helper processes should be run under a user ID that is separate from that
of the user running the main @code{taler-exchange-httpd} service. For security,
it is important that helpers run under a different user ID than the main HTTP
frontend, in fact ideally each helper should run under its own user ID. The
-@code{taler-exchange-httpd} service’s will securely communicate with the helpers
-using UNIX domain sockets. To enable access to the keys, the service’s user
+@code{taler-exchange-httpd} service's will securely communicate with the helpers
+using UNIX domain sockets. To enable access to the keys, the service's user
must be in the group of the helper processes (and no other users should be in
that group).
@@ -884,9 +884,9 @@ denomination keys (signs electronic coins, see section Coins)
security module keys (signs sign keys and denomination keys)
@end itemize
-Additionally, the exchange is sometimes concerned with the auditor’s public
+Additionally, the exchange is sometimes concerned with the auditor's public
key (to verify messages signed by auditors approved by the exchange operator)
-and the merchant’s public key (to verify refunds are authorized by the
+and the merchant's public key (to verify refunds are authorized by the
merchant).
Key options include:
@@ -1003,7 +1003,7 @@ must then have the following options:
@item
@code{VALUE}: How much is the coin worth, the format is
-CURRENCY:VALUE.FRACTION. For example, a 10 cent piece is “EUR:0.10”.
+CURRENCY:VALUE.FRACTION. For example, a 10 cent piece is "EUR:0.10".
@item
@code{DURATION_WITHDRAW}: How long can a coin of this type be withdrawn?
@@ -1015,6 +1015,9 @@ key is compromised.
values result in lower storage costs for the exchange.
@item
+@code{DURATION_LEGAL}: How long is the coin of the given type legal?
+
+@item
@code{FEE_WITHDRAW}: What does it cost to withdraw this coin? Specified
using the same format as value.
@@ -1027,6 +1030,10 @@ the same format as value.
the same format as value.
@item
+@code{FEE_REFUND}: What does it cost to refund this coin?
+Specified using the same format as value.
+
+@item
@code{RSA_KEYSIZE}: How many bits should the RSA modulus (product of the two
primes) have for this type of coin.
@end itemize
@@ -1115,7 +1122,7 @@ delayed.
@section Terms of Service
-The exchange has an endpoint “/terms” to return the terms of service
+The exchange has an endpoint "/terms" to return the terms of service
(in legal language) of the exchange operator. The wallet will show
those terms of service to the user when the user is first withdrawing
coins. Terms of service are optional for experimental deployments,
@@ -1129,7 +1136,7 @@ in the @code{[exchange]} section:
@itemize -
@item
-@code{TERMS_ETAG}: The current “Etag” to return for the terms of service.
+@code{TERMS_ETAG}: The current "Etag" to return for the terms of service.
This value must be changed whenever the terms of service are
updated. A common value to use would be a version number.
Note that if you change the @code{TERMS_ETAG}, you MUST also provide
@@ -1143,7 +1150,7 @@ process.
The @code{TERMS_DIR} directory structure must follow a particular layout.
First, inside of @code{TERMS_DIR}, there should be sub-directories using
-two-letter language codes like “en”, “de”, or “jp”. Each of these
+two-letter language codes like "en", "de", or "jp". Each of these
directories would then hold translations of the current terms of
service into the respective language. Empty directories are
permitted in case translations are not available.
@@ -1165,7 +1172,7 @@ present, the exchange may show a warning on startup.
@subsection Example
-A sample file structure for a @code{TERMS_ETAG} of “v1” would be:
+A sample file structure for a @code{TERMS_ETAG} of "v1" would be:
@itemize -
@@ -1192,7 +1199,7 @@ TERMS_DIR/de/v1.pdf
TERMS_DIR/fr/v1.pdf
@end itemize
-If the user requests an HTML format with language preferences “fr” followed by “en”,
+If the user requests an HTML format with language preferences "fr" followed by "en",
the exchange would return @code{TERMS_DIR/en/v1.html} lacking an HTML version in
French.
@@ -1318,7 +1325,7 @@ The exchange must be informed about any auditor that is expected to provision
it with auditor signatures. This is also done using the
@code{taler-exchange-offline} tool on the offline system. First, the auditor
must be configured and provide the exchange operator with its public key and
-the URL of it’s REST API. The exchange operator also needs a human-readable
+the URL of it's REST API. The exchange operator also needs a human-readable
name that may be shown to users to identify the auditor. Given this
information, the exchange operator can enable the auditor:
@@ -1575,7 +1582,7 @@ helpful for diagnostics.
While an exchange should use an external auditor to attest to regulators that
-it is operating correctly, an exchange operator can also use the auditor’s
+it is operating correctly, an exchange operator can also use the auditor's
logic to perform internal checks. For this, an exchange opeator can generally
follow the auditor guide. However, instead of using @code{taler-auditor-sync},
an internal audit can and likely should be performed either directly against
@@ -1621,14 +1628,14 @@ The database scheme used by the exchange looks as follows:
This chapter describes how to run the Taler exchange benchmark. The benchmark
can be used to measure the performance of the exchange by running a (possibly
large) number of simulated clients against one Taler deployment with a bank,
-exchange and auditor. For the bank, both a “fakebank” (@code{-f}) and a
-“Pythonbank” deployment are currently supported. The
+exchange and auditor. For the bank, both a "fakebank" (@code{-f}) and a
+"Pythonbank" deployment are currently supported. The
@code{taler-exchange-benchmark} program can launch all required services and
clients, or only launch the parallel clients (@code{-m}), for example for
distributed testing over a network.
For each @emph{parallel} (@code{-p}) client, a number of @emph{reserves} (@code{-r}) is first established by
-@strong{transferring} money from a “user” account (42) to the Exchange’s account
+@strong{transferring} money from a "user" account (42) to the Exchange's account
with the respective reserve public key as wire subject. Next, the
client will @strong{withdraw} a @emph{number of coins} (@code{-n}) from the reserve and
@strong{deposit} them. Additionally, a @emph{fraction} (@code{-R}) of the dirty coins will then be
@@ -1648,7 +1655,7 @@ You can run a first simple benchmark using:
@cartouche
@quotation Note
FIXME-TTN/CG: these instructions are incomplete and untested for the
-current iteration of the code…
+current iteration of the code...
@end quotation
@end cartouche
diff --git a/texinfo/taler-merchant-api-tutorial-figures/anastasis-db.png b/texinfo/taler-merchant-api-tutorial-figures/anastasis-db.png
new file mode 100644
index 00000000..03eed9da
--- /dev/null
+++ b/texinfo/taler-merchant-api-tutorial-figures/anastasis-db.png
Binary files differ
diff --git a/texinfo/taler-merchant-api-tutorial-figures/anastasis_challenge_payment.png b/texinfo/taler-merchant-api-tutorial-figures/anastasis_challenge_payment.png
new file mode 100644
index 00000000..a0593eba
--- /dev/null
+++ b/texinfo/taler-merchant-api-tutorial-figures/anastasis_challenge_payment.png
Binary files differ
diff --git a/texinfo/taler-merchant-api-tutorial-figures/anastasis_challengecode.png b/texinfo/taler-merchant-api-tutorial-figures/anastasis_challengecode.png
new file mode 100644
index 00000000..fc30f4fe
--- /dev/null
+++ b/texinfo/taler-merchant-api-tutorial-figures/anastasis_challengecode.png
Binary files differ
diff --git a/texinfo/taler-merchant-api-tutorial-figures/anastasis_reducer_backup.png b/texinfo/taler-merchant-api-tutorial-figures/anastasis_reducer_backup.png
new file mode 100644
index 00000000..87b0a9b4
--- /dev/null
+++ b/texinfo/taler-merchant-api-tutorial-figures/anastasis_reducer_backup.png
Binary files differ
diff --git a/texinfo/taler-merchant-api-tutorial-figures/anastasis_reducer_recovery.png b/texinfo/taler-merchant-api-tutorial-figures/anastasis_reducer_recovery.png
new file mode 100644
index 00000000..7d3cc9ae
--- /dev/null
+++ b/texinfo/taler-merchant-api-tutorial-figures/anastasis_reducer_recovery.png
Binary files differ
diff --git a/texinfo/taler-merchant-api-tutorial-figures/anastasis_truth.png b/texinfo/taler-merchant-api-tutorial-figures/anastasis_truth.png
new file mode 100644
index 00000000..7f23fa21
--- /dev/null
+++ b/texinfo/taler-merchant-api-tutorial-figures/anastasis_truth.png
Binary files differ
diff --git a/texinfo/taler-merchant-api-tutorial-figures/anastasis_truth_payment.png b/texinfo/taler-merchant-api-tutorial-figures/anastasis_truth_payment.png
new file mode 100644
index 00000000..70a6b3df
--- /dev/null
+++ b/texinfo/taler-merchant-api-tutorial-figures/anastasis_truth_payment.png
Binary files differ
diff --git a/texinfo/taler-merchant-api-tutorial.texi b/texinfo/taler-merchant-api-tutorial.texi
index 35557ef0..bf5aaefa 100644
--- a/texinfo/taler-merchant-api-tutorial.texi
+++ b/texinfo/taler-merchant-api-tutorial.texi
@@ -21,11 +21,11 @@
@copying
@quotation
-GNU Taler 0.8.0pre0, Jan 27, 2021
+GNU Taler 0.8.0pre0, Apr 26, 2021
GNU Taler team
-Copyright @copyright{} 2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+Copyright @copyright{} 2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
@end quotation
@end copying
@@ -142,7 +142,7 @@ This chapter explains some basic concepts. In the
second chapter, you will learn how to do basic payments.
This version of the tutorial has examples for Python3. It uses the
-requests library for HTTP requests. Versions for other
+@code{requests} library for HTTP requests. Versions for other
languages/environments are available as well.
If you want to look at some simple, running examples, check out these:
@@ -293,7 +293,7 @@ not affiliated with or officially approved by the respective projects.
@end quotation
@end cartouche
-All endpoints for instances offer the same API. Thus, which instance is
+All endpoints for instances offer the same API. Thus, which instance
to be used is simply included in the base URL of the merchant backend.
@node Merchant Payment Processing,Giving Refunds,Introduction,Top
@@ -331,28 +331,28 @@ field:
@itemize -
@item
-amount: The amount to be paid, as a string in the format
+@code{amount}: The amount to be paid, as a string in the format
@code{CURRENCY:DECIMAL_VALUE}, for example @code{EUR:10} for 10 Euros or
@code{KUDOS:1.5} for 1.5 KUDOS.
@item
-summary: A human-readable summary for what the payment is about. The
+@code{summary}: A human-readable summary for what the payment is about. The
summary should be short enough to fit into titles, though no hard
limit is enforced.
@item
-fulfillment_url: A URL that will be displayed once the payment is
+@code{fulfillment_url}: A URL that will be displayed once the payment is
completed. For digital goods, this should be a page that displays the
product that was purchased. On successful payment, the wallet
automatically appends the @code{order_id} as a query parameter, as well
-as the @code{session_sig} for session-bound payments (discussed later).
+as the @code{session_sig} for session-bound payments (discussed below).
@end itemize
Orders can have many more fields, see @ref{c,,The Taler Order Format}. When POSTing an order,
you can also specify additional details such as an override
for the refund duration and instructions for inventory
management. These are rarely needed and not covered in this
-tutorial; please read the core/api-merchant reference
+tutorial; please see the core/api-merchant reference
manual for details.
A minimal Python snippet for creating an order would look like this:
@@ -436,14 +436,14 @@ payment status, including:
@itemize -
@item
-contract_terms: The full contract terms of the order.
+@code{contract_terms}: The full contract terms of the order.
@item
-refunded: @code{true} if a (possibly partial) refund was granted for
+@code{refunded}: @code{true} if a (possibly partial) refund was granted for
this purchase.
@item
-refunded_amount: Amount that was refunded
+@code{refunded_amount}: Amount that was refunded
@end itemize
Once the frontend has confirmed that the payment was successful, it
@@ -453,7 +453,7 @@ the merchant’s obligations under the contract.
@cartouche
@quotation Note
You do not need to keep querying to notice changes
-to the order’s transaction status. The endpoint
+to the order's transaction status. The endpoints
support long polling, simply specify a @code{timeout_ms}
query parameter with how long you want to wait at most
for the order status to change to @code{paid}.
@@ -485,13 +485,13 @@ The refund request JSON object has only two fields:
@itemize -
@item
-refund: Amount to be refunded. If a previous refund was authorized
+@code{refund}: Amount to be refunded. If a previous refund was authorized
for the same order, the new amount must be higher, otherwise the
operation has no effect. The value indicates the total amount to be
refunded, @emph{not} an increase in the refund.
@item
-reason: Human-readable justification for the refund. The reason is
+@code{reason}: Human-readable justification for the refund. The reason is
only used by the Back Office and is not exposed to the customer.
@end itemize
@@ -551,8 +551,8 @@ from the QR code).
The merchant backend then updates the session ID of the existing order to
the current session ID of the browser. When the payment status for the
-“new” unpaid order is checked (or already in long-polling), the backend
-detects that for the browser’s @emph{session ID} and @emph{fulfillment URL} there is an
+"new" unpaid order is checked (or already in long-polling), the backend
+detects that for the browser's @emph{session ID} and @emph{fulfillment URL} there is an
existing paid contract. It then tells the browser to immediately redirect to
the fulfillment URL where the already paid article is available.
@@ -566,7 +566,7 @@ Note that changing the session ID to a different device requires the
involvement of the wallet that made the payment, thus reasonably limiting the
possibility of broadly sharing the digital purchases. Repurchase detection is
also @emph{only} done for HTTP(S) fulfillment URLs. In particular, this means
-fulfillment URIs like “taler://fulfillment-success/$MESSAGE” are not
+fulfillment URIs like @code{taler://fulfillment-success/$MESSAGE} are not
considered to identify a resource you can pay for and thus do not have to be
unique.
@anchor{taler-merchant-api-tutorial giving-customers-tips}@anchor{12}
@@ -598,8 +598,7 @@ funds available for tipping, query the @code{/tip-query} endpoint:
... headers=@{"Authorization": "ApiKey sandbox"@})
<Response [200]>
@end example
-
-authorize tip
+@anchor{taler-merchant-api-tutorial authorize-tip}@anchor{14}
To authorize a tip, @code{POST} to @code{/tip-authorize}. The following fields
are recognized in the JSON request object:
@@ -607,25 +606,25 @@ are recognized in the JSON request object:
@itemize -
@item
-amount: Amount that should be given to the visitor as a tip.
+@code{amount}: Amount that should be given to the visitor as a tip.
@item
-instance: Merchant instance that grants the tip (each instance may
+@code{instance}: Merchant instance that grants the tip (each instance may
have its own independent tipping funds configured).
@item
-justification: Description of why the tip was granted. Human-readable
+@code{justification}: Description of why the tip was granted. Human-readable
text not exposed to the customer, but used by the Back Office.
@item
-next_url: The URL that the user’s browser should be redirected to by
+@code{next_url}: The URL that the user’s browser should be redirected to by
the wallet, once the tip has been processed.
@end itemize
The response from the backend contains a @code{tip_redirect_url}. The
customer’s browser must be redirected to this URL for the wallet to pick
-up the tip. pick up tip
-
+up the tip.
+@anchor{taler-merchant-api-tutorial pick-up-tip}@anchor{15}
This code snipped illustrates giving a tip:
@example
@@ -640,7 +639,7 @@ This code snipped illustrates giving a tip:
@end example
@node Advanced topics,Index,Giving Customers Tips,Top
-@anchor{taler-merchant-api-tutorial advanced-topics}@anchor{14}@anchor{taler-merchant-api-tutorial id6}@anchor{15}
+@anchor{taler-merchant-api-tutorial advanced-topics}@anchor{16}@anchor{taler-merchant-api-tutorial id6}@anchor{17}
@chapter Advanced topics
@@ -652,7 +651,7 @@ This code snipped illustrates giving a tip:
@end menu
@node Session-Bound Payments,Product Identification,,Advanced topics
-@anchor{taler-merchant-api-tutorial session-002dbound-payments}@anchor{16}@anchor{taler-merchant-api-tutorial session-bound-payments}@anchor{17}
+@anchor{taler-merchant-api-tutorial session-002dbound-payments}@anchor{18}@anchor{taler-merchant-api-tutorial session-bound-payments}@anchor{19}
@section Session-Bound Payments
@@ -689,7 +688,7 @@ receipt is in the user’s wallet is also available as @code{last_session_id}
in the response to @code{/check-payment}.
@node Product Identification,The Taler Order Format,Session-Bound Payments,Advanced topics
-@anchor{taler-merchant-api-tutorial id8}@anchor{18}@anchor{taler-merchant-api-tutorial product-identification}@anchor{19}
+@anchor{taler-merchant-api-tutorial id8}@anchor{1a}@anchor{taler-merchant-api-tutorial product-identification}@anchor{1b}
@section Product Identification
@@ -697,7 +696,7 @@ in the response to @code{/check-payment}.
In some situations the user may have paid for some digital good, but the
frontend does not know the exact order ID, and thus cannot instruct the
-wallet to reveil the existing payment receipt. This is common for simple
+wallet to reveal the existing payment receipt. This is common for simple
shops without a login system. In this case, the user would be prompted
for payment again, even though they already purchased the product.
@@ -710,7 +709,7 @@ contract with the same @code{resource_url} before, and if so replay the
previous payment.
@node The Taler Order Format,,Product Identification,Advanced topics
-@anchor{taler-merchant-api-tutorial id9}@anchor{1a}@anchor{taler-merchant-api-tutorial the-taler-order-format}@anchor{1b}
+@anchor{taler-merchant-api-tutorial id9}@anchor{1c}@anchor{taler-merchant-api-tutorial the-taler-order-format}@anchor{1d}
@section The Taler Order Format
@@ -743,7 +742,7 @@ customer.
This is the maximum total amount of deposit fees that the merchant is
willing to pay. If the deposit fees for the coins exceed this amount,
the customer has to include it in the payment total. The fee is
-specified using the same triplet used for @code{amount}.
+specified using the same format used for @code{amount}.
@end table
@geindex fees
@@ -885,7 +884,7 @@ or just the count.
@item price
-Price for quantity units of this product shipped to the given
+Price for @code{quantity} units of this product shipped to the given
@code{delivery_location}. Note that usually the sum of all of the prices
should add up to the total amount of the contract, but it may be
different due to discounts or because individual prices are
@@ -911,19 +910,19 @@ also likely to be used by tax audits of the merchant.
@item delivery_date
Time by which the product is to be delivered to the
-delivery_location.
+@code{delivery_location}.
@item delivery_location
-This should give a label in the locations map, specifying where
+This should give a label in the @code{locations} map, specifying where
the item is to be delivered.
@end table
Values can be omitted if they are not applicable. For example, if a
purchase is about a bundle of products that have no individual prices
-or product IDs, the product_id or price may not be specified in the
+or product IDs, the @code{product_id} or @code{price} may not be specified in the
contract. Similarly, for virtual products delivered directly via the
-fulfillment URI, there is no delivery location.
+fulfillment URI, there is no @code{delivery_location}.
@item merchant
@@ -1021,8 +1020,8 @@ render fields that they do not understand as a key-value list.
@printindex ge
-@anchor{c}@w{ }
@anchor{taler-merchant-api-tutorial The-Taler-Order-Format}@w{ }
+@anchor{c}@w{ }
@c %**end of body
@bye
diff --git a/texinfo/taler-merchant-figures/anastasis-db.png b/texinfo/taler-merchant-figures/anastasis-db.png
new file mode 100644
index 00000000..03eed9da
--- /dev/null
+++ b/texinfo/taler-merchant-figures/anastasis-db.png
Binary files differ
diff --git a/texinfo/taler-merchant-figures/anastasis_challenge_payment.png b/texinfo/taler-merchant-figures/anastasis_challenge_payment.png
new file mode 100644
index 00000000..a0593eba
--- /dev/null
+++ b/texinfo/taler-merchant-figures/anastasis_challenge_payment.png
Binary files differ
diff --git a/texinfo/taler-merchant-figures/anastasis_challengecode.png b/texinfo/taler-merchant-figures/anastasis_challengecode.png
new file mode 100644
index 00000000..fc30f4fe
--- /dev/null
+++ b/texinfo/taler-merchant-figures/anastasis_challengecode.png
Binary files differ
diff --git a/texinfo/taler-merchant-figures/anastasis_reducer_backup.png b/texinfo/taler-merchant-figures/anastasis_reducer_backup.png
new file mode 100644
index 00000000..87b0a9b4
--- /dev/null
+++ b/texinfo/taler-merchant-figures/anastasis_reducer_backup.png
Binary files differ
diff --git a/texinfo/taler-merchant-figures/anastasis_reducer_recovery.png b/texinfo/taler-merchant-figures/anastasis_reducer_recovery.png
new file mode 100644
index 00000000..7d3cc9ae
--- /dev/null
+++ b/texinfo/taler-merchant-figures/anastasis_reducer_recovery.png
Binary files differ
diff --git a/texinfo/taler-merchant-figures/anastasis_truth.png b/texinfo/taler-merchant-figures/anastasis_truth.png
new file mode 100644
index 00000000..7f23fa21
--- /dev/null
+++ b/texinfo/taler-merchant-figures/anastasis_truth.png
Binary files differ
diff --git a/texinfo/taler-merchant-figures/anastasis_truth_payment.png b/texinfo/taler-merchant-figures/anastasis_truth_payment.png
new file mode 100644
index 00000000..70a6b3df
--- /dev/null
+++ b/texinfo/taler-merchant-figures/anastasis_truth_payment.png
Binary files differ
diff --git a/texinfo/taler-merchant.texi b/texinfo/taler-merchant.texi
index af3159e5..738d7804 100644
--- a/texinfo/taler-merchant.texi
+++ b/texinfo/taler-merchant.texi
@@ -21,11 +21,11 @@
@copying
@quotation
-GNU Taler 0.8.0pre0, Jan 27, 2021
+GNU Taler 0.8.0pre0, Apr 26, 2021
GNU Taler team
-Copyright @copyright{} 2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)
+Copyright @copyright{} 2014-2021 Taler Systems SA (GPLv3+ or GFDL 1.3+)
@end quotation
@end copying
@@ -242,7 +242,7 @@ special currency “KUDOS” and includes its own special bank.
@geindex frontend
-@geindex back office
+@geindex back-office
@geindex backend
@@ -257,7 +257,7 @@ components:
@itemize -
@item
-A frontend which interacts with the customer’s browser. The frontend
+A @emph{frontend} which interacts with the customer’s browser. The frontend
enables the customer to build a shopping cart and place an order.
Upon payment, it triggers the respective business logic to satisfy
the order. This component is not included with Taler, but rather
@@ -266,21 +266,21 @@ The Merchant API Tutorial gives an
introduction for how to integrate Taler with Web shop frontends.
@item
-A back office application that enables the shop operators to view
+A @emph{back-office} application that enables the shop operators to view
customer orders, match them to financial transfers, and possibly
approve refunds if an order cannot be satisfied. This component is
not included with Taler, but rather assumed to exist at the
merchant. The Merchant Backend API provides
the API specification that should be reviewed to integrate such a
-back office with the Taler backend.
+back-office with the Taler backend.
@item
-A Taler-specific payment backend which makes it easy for the frontend
+A Taler-specific payment @emph{backend} which makes it easy for the frontend
to process financial transactions with Taler. This manual primarily
describes how to install and configure this backend.
@item
-A DBMS which stores the transaction history for the Taler backend.
+A @emph{DBMS} which stores the transaction history for the Taler backend.
For now, the GNU Taler reference implementation only supports
Postgres, but the code could be easily extended to support another
DBMS. Please review the Postgres documentation for details on
@@ -299,7 +299,7 @@ Taler-specific financial information in a DBMS and communicates with the GNU
Taler exchange over the Internet. The frontend accesses the backend via a
RESTful API. As a result, the frontend never has to directly communicate with
the exchange, and also does not deal with sensitive data. In particular, the
-merchant’s signing keys and bank account information is encapsulated within
+merchant’s signing keys and bank account information are encapsulated within
the Taler backend.
A typical deployment will additionally include a full-blown Web server (like
@@ -348,7 +348,7 @@ the main Taler configuration (accepted currency, exchanges and auditors).
To receive payments, an instance must have configured one or more bank
@emph{accounts}. The backend does not have accounts for users, and instances are
-also not really ‘accounts’. So whenever we use the term @emph{account}, it is about
+also not really 'accounts'. So whenever we use the term @emph{account}, it is about
a bank account of a merchant.
@node Inventory,Orders and Contracts,Accounts,Terminology
@@ -406,7 +406,7 @@ merchant, where the merchant specifies the specific terms of the order.
After an order is created, it is @emph{claimed} by a wallet. Once an order is
claimed by a specific wallet, only that wallet will be able to pay for this
order, to the exclusion of other wallets even if they see the same order URL.
-Sharing order URLs is explicitly allowed: if a user shares and order URL
+Sharing order URLs is explicitly allowed: if a user shares an order URL
with another user, that other user should be given the opportunity to
purchase the same product.
@@ -447,7 +447,7 @@ decade), contract information is deleted.
The Taler backend can be used to verify that the exchange correctly wired all
of the funds to the merchant. However, the backend does not have access to the
-incoming wire transfers of the merchant’s bank account. Thus, merchants must
+incoming wire transfers of the merchant's bank account. Thus, merchants must
manually provide the backend with wire @emph{transfer} data that specifies the wire
transfer subject and the amount that was received. Given this information, the
backend can detect and report any irregularities that might arise.
@@ -621,7 +621,7 @@ shared object libraries (@code{.so} files)
visible to the various installed programs.
There is no need to actually run a GNUnet peer to use the Taler merchant
-backend – all the merchant needs from GNUnet is a number of headers and
+backend -- all the merchant needs from GNUnet is a number of headers and
libraries!
@node Installing the GNU Taler exchange,Installing the GNU Taler merchant backend,Installing GNUnet,Generic instructions for installation from source
@@ -649,7 +649,7 @@ which requires you to run the last step as @code{root}. You have to specify
previous step.
There is no need to actually run a Taler exchange to use the Taler merchant
-backend – all the merchant needs from the Taler exchange is a few headers and
+backend -- all the merchant needs from the Taler exchange is a few headers and
libraries!
@node Installing the GNU Taler merchant backend,,Installing the GNU Taler exchange,Generic instructions for installation from source
@@ -1155,7 +1155,7 @@ $ taler-config -s TALER -o CURRENCY -V KUDOS
@subsection Database
-In principle is possible for the backend to support different DBMSs.
+In principle it is possible for the backend to support different DBMSs.
The option
@example
@@ -1163,7 +1163,7 @@ The option
@end example
specifies which DBMS is to be used. However, currently only the value
-“postgres” is supported. This is also the default.
+@code{postgres} is supported. This is also the default.
In addition to selecting the DBMS software, the backend requires
DBMS-specific options to access the database.
@@ -1178,7 +1178,7 @@ This option specifies a postgres access path using the format
@code{postgres:///$DBNAME}, where @code{$DBNAME} is the name of the
Postgres database you want to use. Suppose @code{$USER} is the name of
the user who will run the backend process. Then, you need to first
-run
+run:
@example
$ sudo -u postgres createuser -d $USER
@@ -1216,6 +1216,7 @@ the Postgres documentation.
Commands, like @code{taler-merchant-dbinit}, that support the @code{-l LOGFILE}
command-line option, send logging output to standard error by default.
+See manpages/taler-merchant-dbinit.1 for more information.
@c index: MASTER_KEY
@@ -1232,8 +1233,8 @@ section, the following options need to be configured:
@itemize -
@item
-The “EXCHANGE_BASE_URL” option specifies the exchange’s base URL. For example,
-to use the Taler demonstrator, specify:
+The @code{EXCHANGE_BASE_URL} option specifies the exchange’s base URL.
+For example, to use the Taler demonstrator, specify:
@example
$ taler-config -s MERCHANT-EXCHANGE-demo \
@@ -1242,17 +1243,17 @@ $ taler-config -s MERCHANT-EXCHANGE-demo \
@end example
@item
-The “MASTER_KEY” option specifies the exchange’s master public key
+The @code{MASTER_KEY} option specifies the exchange’s master public key
in base32 encoding. For the Taler demonstrator, use:
@example
$ taler-config -s MERCHANT-EXCHANGE-demo \
-o MASTER_KEY \
- -V CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00
+ -V FH1Y8ZMHCTPQ0YFSZECDH8C9407JR3YN0MF1706PTG24Q4NEWGV0
@end example
@item
-The “CURRENCY” option specifies the exchange’s currency.
+The @code{CURRENCY} option specifies the exchange’s currency.
For the Taler demonstrator, use:
@example
@@ -1263,9 +1264,9 @@ $ taler-config -s MERCHANT-EXCHANGE-demo \
@end itemize
Note that multiple exchanges can be added to the system by using different
-tokens in place of @code{demo} in the example above. Note that all of the
+tokens in place of @code{demo} in the examples above. Note that all of the
exchanges must use the same currency: If the currency does not match the main
-currency from the “TALER” section, the exchange is ignored. If you need to
+currency from the @code{TALER} section, the exchange is ignored. If you need to
support multiple currencies, you need to configure a backend per currency.
@node Auditor,,Exchange,Backend options
@@ -1282,8 +1283,8 @@ that section, the following options need to be configured:
@itemize -
@item
-The “AUDITOR_BASE_URL” option specifies the auditor’s base URL. For example,
-to use the Taler demonstrator’s auditor, specify:
+The @code{AUDITOR_BASE_URL} option specifies the auditor’s base URL.
+For example, to use the Taler demonstrator's auditor, specify:
@example
$ taler-config -s MERCHANT-AUDITOR-demo \
@@ -1292,17 +1293,17 @@ $ taler-config -s MERCHANT-AUDITOR-demo \
@end example
@item
-The “AUDITOR_KEY” option specifies the auditor’s public key
+The @code{AUDITOR_KEY} option specifies the auditor's public key
in base32 encoding. For the Taler demonstrator, use:
@example
$ taler-config -s MERCHANT-AUDITOR-demo \
-o AUDITOR_KEY \
- -V FIXMEBADVALUENEEDTOGETTHERIGHTVALUEHEREEVENTUALLY000
+ -V DSDASDXAMDAARMNAD53ZA4AFAHA2QADAMAHHASWDAWXN84SDAA11
@end example
@item
-The “CURRENCY” option specifies the auditor’s currency.
+The @code{CURRENCY} option specifies the auditor’s currency.
For the Taler demonstrator, use:
@example
@@ -1313,9 +1314,9 @@ $ taler-config -s MERCHANT-AUDITOR-demo \
@end itemize
Note that multiple auditors can be added to the system by using different
-tokens in place of @code{demo} in the example above. Note that all of the
+tokens in place of @code{demo} in the examples above. Note that all of the
auditors must use the same currency: If the currency does not match the main
-currency from the “TALER” section, the auditor is ignored. If you need to
+currency from the @code{TALER} section, the auditor is ignored. If you need to
support multiple currencies, you need to configure a backend per currency.
@node Sample backend configuration,Launching the backend,Backend options,How to configure the merchant’s backend
@@ -1359,7 +1360,7 @@ Given the above configuration, the backend will use a database named
The backend will deposit the coins it receives to the exchange at
@indicateurl{https://exchange.demo.taler.net/}, which has the master key
-“FH1Y8ZMHCTPQ0YFSZECDH8C9407JR3YN0MF1706PTG24Q4NEWGV0”.
+@code{FH1Y8ZMHCTPQ0YFSZECDH8C9407JR3YN0MF1706PTG24Q4NEWGV0}.
Please note that @code{doc/config.sh} will walk you through all
configuration steps, showing how to invoke @code{taler-config} for each of
@@ -1409,7 +1410,7 @@ and use TLS for improved network privacy, see @ref{9,,Secure setup}.
@chapter Instance setup
-Before using the backend, you must at least configure the “default” instance.
+Before using the backend, you must at least configure the "default" instance.
@menu
* KUDOS Accounts::
@@ -1430,12 +1431,13 @@ In order to receive payments, the merchant backend needs to
communicate bank account details to the exchange.
The bank account information is provided in the form of a @code{payto://}-URI.
-See RFC 8905 for the format of @code{payto://}-URIs.
+See RFC 8905@footnote{https://tools.ietf.org/html/rfc8905}
+for the format of @code{payto://}-URIs.
For first tests, you should sign up for a KUDOS bank
account at @indicateurl{https://bank.demo.taler.net/}.
-In this case, the payto://-URI will be of the form
-“payto://x-taler-bank/bank.demo.taler.net/$USERNAME” where “$USERNAME”
+In this case, the @code{payto://}-URI will be of the form
+@code{payto://x-taler-bank/bank.demo.taler.net/$USERNAME} where @code{$USERNAME}
must be replaced with the name of the account that was established
at @indicateurl{https://bank.demo.taler.net/}.
@@ -1446,17 +1448,17 @@ at @indicateurl{https://bank.demo.taler.net/}.
When deploying Taler with the real banking system, you primarily need to
change the currency of the configuration from KUDOS to the actual currency
-(such as EUR, USD, CHF) and provide a payto://-URI of your real bank
+(such as EUR, USD, CHF) and provide a @code{payto://}-URI of your real bank
account. In Europe, this will involve knowing your IBAN number. If you have an
-IBAN, the corresponding payto://-URI is simply “payto://iban/$IBAN” where
-“$IBAN” must be replaced with the actual IBAN number.
+IBAN, the corresponding @code{payto://}-URI is simply @code{payto://iban/$IBAN} where
+@code{$IBAN} must be replaced with the actual IBAN number.
@node Setup,,IBAN Accounts,Instance setup
@anchor{taler-merchant-manual setup}@anchor{33}
@section Setup
-With the knowledge of the payto://-URI, instances can be configured by POSTing
+With the knowledge of the @code{payto://}-URI, instances can be configured by POSTing
a request to @code{POST /private/instances}. To create a first instance,
create a file @code{instance.json} with an InstanceConfigurationMessage
@@ -1466,6 +1468,7 @@ create a file @code{instance.json} with an InstanceConfigurationMessage
"id" : "default",
"name": "example.com",
"address": @{ "country" : "zz" @},
+ "auth": @{ "method" : "external"@} ,
"jurisdiction": @{ "country" : "zz" @},
"default_max_wire_fee": "KUDOS:1",
"default_wire_fee_amortization": 100,
@@ -1475,10 +1478,10 @@ create a file @code{instance.json} with an InstanceConfigurationMessage
@}
@end example
-In the text above, you must replace “$PAYTO_URI” with your actual
-payto://-URI. Also, be sure to replace KUDOS with the fiat currency if the
-setup is for an actual bank. The “name” field will be shown as the name of
-your shop. The “address” field is expected to contain your shop’s physical
+In the text above, you must replace @code{$PAYTO_URI} with your actual
+@code{payto://}-URI. Also, be sure to replace @code{KUDOS} with the fiat currency if the
+setup is for an actual bank. The @code{name} field will be shown as the name of
+your shop. The @code{address} field is expected to contain your shop's physical
address. The various defaults specify defaults for transaction fees your shop
is willing to cover, how long offers made to the customer are valid, and how
long the exchange has before it must wire the funds to your bank
@@ -1493,7 +1496,7 @@ $ wget --post-file=instance.json http://localhost:8888/private/instances
The base URL for the instance will then be
@code{http://localhost:8888/instances/default}. You can create additional
-instances by changing the “id” value to identifies other than “default”.
+instances by changing the @code{id} value to identifies other than @code{default}.
Endpoints to modify (reconfigure), permanently disable (while keeping the data)
or purge (deleting all associated data) instances exist as well and are documented
@@ -1534,9 +1537,9 @@ $ taler-config -s MERCHANT -o SERVE -V UNIX
$ taler-config -s MERCHANT -o UNIXPATH -V /some/path/here.sock
@end example
-Do not use a UNIX domain socket path in “/tmp”: systemd (or other init
-systems) may give Web servers a private “/tmp” thereby hiding UNIX domain
-sockets created by other users/processes in “/tmp”.
+Do not use a UNIX domain socket path in "/tmp": systemd (or other init
+systems) may give Web servers a private "/tmp" thereby hiding UNIX domain
+sockets created by other users/processes in "/tmp".
If UNIX domain sockets are for some reason not possible, you @emph{may} use a
host-based firewall to block access to the TCP port of the merchant backend,
@@ -1579,8 +1582,8 @@ process after changing the @code{SERVE} configuration.
@subsection Apache
-In Apache, make sure you have “mod_proxy”, “mod_proxy_http” and
-“mod_headers” enabled:
+In Apache, make sure you have @code{mod_proxy}, @code{mod_proxy_http} and
+@code{mod_headers} enabled:
@example
$ a2enmod proxy
@@ -1599,7 +1602,7 @@ RequestHeader add "X-Forwarded-Proto" "https"
@end example
Note that the above again assumes your domain name is @code{example.com} and that
-you have TLS configured. Note that you must add the “https” header unless
+you have TLS configured. Note that you must add the @code{https} header unless
your site is not available via TLS.
The above configuration(s) are both incomplete. You must still additionally
@@ -1647,10 +1650,10 @@ location ~ /private/ @{
@}
@end example
-Here, “SECURITYTOKEN” should be replaced with the actual shared secret. Note
-that the “~” ensures that the above matches all endpoints that include the
-string “/private/”. If you only run a single instance, you could simply
-specify “/private/” without the “~” to only configure the access policy for
+Here, @code{SECURITYTOKEN} should be replaced with the actual shared secret. Note
+that the @code{~} ensures that the above matches all endpoints that include the
+string @code{/private/}. If you only run a single instance, you could simply
+specify @code{/private/} without the @code{~} to only configure the access policy for
the default instance.
If you are running different instances on the same backend, you
@@ -1662,22 +1665,22 @@ location ~ ^/instances/foo/private/ @{
if ($http_authorization !~ "(?i)ApiKey FOOTOKEN") @{
return 401;
@}
- proxy_pass ...; // as above
+ proxy_pass ...; # as above
@}
location ~ ^/instances/bar/private/ @{
if ($http_authorization !~ "(?i)ApiKey BARTOKEN") @{
return 401;
@}
- proxy_pass ...; // as above
+ proxy_pass ...; # as above
@}
location /private/ @{
if ($http_authorization !~ "(?i)ApiKey MASTERTOKEN") @{
return 401;
@}
- proxy_pass ...; // as above
+ proxy_pass ...; # as above
@}
location ~ /private/ @{
- return 401; // access to instances not explicitly configured is forbidden
+ return 401; # access to instances not explicitly configured is forbidden
@}
@end example
@@ -1686,7 +1689,7 @@ location ~ /private/ @{
@subsection Apache
-For Apache, you should first enable “mod_rewrite”:
+For Apache, you should first enable @code{mod_rewrite}:
@example
$ a2enmod rewrite
@@ -1704,10 +1707,10 @@ ProxyPass "unix:/some/path/here.sock|http://example.com/"
</Location>
@end example
-Here, “SECURITYTOKEN” should be replaced with the actual shared secret. Note
-that the “(.+)” ensures that the above matches all endpoints that include the
-string “/private/”. If you only run a single instance, you could simply
-specify “/private/” without the “~” to only configure the access policy for
+Here, @code{SECURITYTOKEN} should be replaced with the actual shared secret. Note
+that the @code{(.+)} ensures that the above matches all endpoints that include the
+string @code{/private/}. If you only run a single instance, you could simply
+specify @code{/private/} without the @code{~} to only configure the access policy for
the default instance.
If you are running different instances on the same backend, you
@@ -1807,10 +1810,10 @@ preferences indicated by the browser is returned.
All of the static files must fit into memory and it must be possible for the
process to hold open file handles for all of these files. You may want
-to increase the “ulimit” of the @code{taler-merchant-httpd} process if you have
+to increase the @code{ulimit} of the @code{taler-merchant-httpd} process if you have
templates for many languages.
-The backend determines the MIME type based on the file’s extension. The list
+The backend determines the MIME type based on the file's extension. The list
of supported extensions is hard-coded and includes common text and image
formats.
@@ -1881,7 +1884,7 @@ There are three basic steps that must happen to tip a visitor.
First, the reserve must be setup in the merchant backend. A reserve
is always tied to a particular instance. To create a reserve with
-10 KUDOS at instance “default” using the demo exchange, use:
+10 KUDOS at instance @code{default} using the demo exchange, use:
@example
$ taler-merchant-setup-reserve \
@@ -1891,11 +1894,11 @@ $ taler-merchant-setup-reserve \
@end example
The above command assumes that the merchant runs on localhost on
-port 8888. The current implementation of the tool does not yet support
-transmission of authentication information to the backend
-(see bug 6418@footnote{https://bugs.gnunet.org/view.php?id=6418}).
+port 8888.
+For more information, including how to transmit authentication information
+to the backend, see manpages/taler-merchant-setup-reserve.1.
-The command will output a payto:// URI which specifies where to
+The command will output a @code{payto://} URI which specifies where to
wire the funds and which wire transfer subject to use.
FIXME: add full example output.
@@ -1910,7 +1913,7 @@ You now need to make a wire transfer to the exchange’s bank account
using the given wire transfer subject.
Make your wire transfer and (optionally) check at
-“@indicateurl{https://exchange/reserves/QPE24X}…” whether your transfer has arrived at the
+“@indicateurl{https://exchange/reserves/QPE24X}...” whether your transfer has arrived at the
exchange.
Once the funds have arrived, you can start to use the reserve for
@@ -2092,7 +2095,7 @@ The tool @code{taler-config} can be used to extract or manipulate
configuration values; however, the configuration use the well-known INI
file format and can also be edited by hand.
-Run
+Run:
@example
$ taler-config -s $SECTION
@@ -2100,7 +2103,7 @@ $ taler-config -s $SECTION
to list all of the configuration values in section @code{$SECTION}.
-Run
+Run:
@example
$ taler-config -s $section -o $option
@@ -2109,7 +2112,7 @@ $ taler-config -s $section -o $option
to extract the respective configuration value for option @code{$option} in
section @code{$section}.
-Finally, to change a setting, run
+Finally, to change a setting, run:
@example
$ taler-config -s $section -o $option -V $value
@@ -2158,7 +2161,7 @@ need, or will not need initially.
The merchant codebase offers the @code{taler-merchant-benchmark} tool to
populate the database with fake payments. This tool is in charge of
-starting a merchant, exchange, and bank processes, and provide them all
+starting a merchant, exchange, and bank processes, and provides them all
the input to accomplish payments. Note that each component will use its
own configuration (as they would do in production).
@@ -2181,13 +2184,13 @@ start.
The @code{taler-merchant-benchmark} tool will automatically launch and configure the
exchange, (Python) bank and other tools required for the benchmark. However,
the configuration file must be provided and have consistent options set. The
-options that require special care include the exchange’s public key (which
+options that require special care include the exchange's public key (which
must match the private key in the file specified by the configuration), the
currency (which must be consistent across the file), the denomination
structure (which must enable payments in the range of 100ths of the unit
currency (often called cents)). Furthermore, the benchmark will set the
-Exchange bank account password to be “x”, so the configuration must also
-specify “x” for the passphrase. Finally, the bank must be configured to allow
+Exchange bank account password to be "x", so the configuration must also
+specify "x" for the passphrase. Finally, the bank must be configured to allow
for substantial debt least the transactions by the benchmark run out of
digital cash.
@@ -2319,11 +2322,11 @@ rsa_keysize = 1024
@end example
-Note that the public key must match the exchange’s
+Note that the public key must match the exchange's
private key and that the Postgres database must
exist before launching the benchmark. You also
-will need to ensure that the Exchange’s
-details are setup.
+will need to ensure that the Exchange's
+details are set up.
For details, see the Exchange Operator Manual.
@node Running the benchmark command,,Benchmark setup,Advanced experimental features
@@ -2342,7 +2345,7 @@ one of them being mandatory:
section specifies the bank account for the exchange that
should be used for the benchmark. For the example
configuration above, the SECTION value provided must be
-“exchange-account-exchange”.
+@code{exchange-account-exchange}.
@end itemize
The tool comes with two operation modes: @emph{ordinary}, and @emph{corner}.
@@ -2353,7 +2356,7 @@ use merchant instances other than the default (which is, actually, the
one used by default by the tool).
Note: the ability of driving the aggregation policy is useful for testing
-the backoffice facility.
+the back-office facility.
Any subcommand is also equipped with the canonical @code{--help} option, so
feel free to issue the following command in order to explore all the
@@ -2391,7 +2394,7 @@ options:
@item
@code{--tracks-number=TN} Instructs the tool to perform @emph{TN} tracking
operations. Note that the @strong{total} amount of operations will be two
-times @emph{TN}, since “one” tracking operation accounts for
+times @emph{TN}, since "one" tracking operation accounts for
@code{/track/transaction} and @code{/track/transfer}. This command should
only be used to see if the operation ends without problems, as no
actual measurement of performance is provided (despite of the
@@ -2459,7 +2462,7 @@ this stage of development, you should also ignore some (harmless) error
message from postresql about already existing roles and databases.
To test if everything worked as expected, it suffices to issue a simple
-request to the merchant, as:
+request to the merchant, for example:
@example
$ curl http://$(docker-machine ip)/