975 lines
30 KiB
Plaintext
975 lines
30 KiB
Plaintext
\input texinfo @c -*-texinfo-*-
|
|
@setfilename taler-exchange.info
|
|
@documentencoding UTF-8
|
|
@include version.texi
|
|
@settitle The GNU Taler Exchange Operator Manual
|
|
@paragraphindent 0
|
|
@exampleindent 4
|
|
|
|
@include syntax.texi
|
|
|
|
@copying
|
|
This manual is for the GNU Taler Exchange
|
|
(version @value{VERSION}, @value{UPDATED}),
|
|
a payment service provider for GNU Taler.
|
|
|
|
Copyright @copyright{} 2014-2018 Taler Systems SA
|
|
|
|
@quotation
|
|
Permission is granted to copy, distribute and/or modify this document
|
|
under the terms of the GNU Free Documentation License, Version 1.3
|
|
or any later version published by the Free Software Foundation;
|
|
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
|
|
Texts. A copy of the license is included in the section entitled "GNU
|
|
Free Documentation License".
|
|
@end quotation
|
|
@end copying
|
|
|
|
@dircategory Network applications
|
|
@direntry
|
|
* GNU Taler Exchange: (taler-exchange). Electronic payment system.
|
|
@end direntry
|
|
|
|
|
|
@titlepage
|
|
@title The GNU Taler Exchange Operator Manual
|
|
@subtitle Version @value{VERSION}
|
|
@subtitle @value{UPDATED}
|
|
@author Christian Grothoff (@email{grothoff@@taler.net})
|
|
@author Marcello Stanisci (@email{stanisci@@taler.net})
|
|
@page
|
|
@vskip 0pt plus 1filll
|
|
@insertcopying
|
|
@end titlepage
|
|
|
|
@summarycontents
|
|
@contents
|
|
|
|
@ifnottex
|
|
@node Top
|
|
@top The GNU Taler Exchange Operator Manual
|
|
@insertcopying
|
|
@end ifnottex
|
|
|
|
|
|
@menu
|
|
* Introduction::
|
|
* Installation::
|
|
* Configuration::
|
|
* Deployment::
|
|
* Diagnostics::
|
|
|
|
|
|
|
|
Appendices
|
|
|
|
* GNU-AGPL:: The GNU Affero General Public License says how you
|
|
can copy and share the code of the `GNU Taler Exchange'.
|
|
* GNU-FDL:: The GNU Free Documentation License says how you
|
|
can copy and share the documentation of `GNU Taler'.
|
|
|
|
Indices
|
|
|
|
* Concept Index:: Index of concepts and programs.
|
|
@end menu
|
|
|
|
@node Introduction
|
|
@chapter Introduction
|
|
|
|
This manual is an early draft that still needs significant editing
|
|
work to become readable.
|
|
|
|
|
|
@section About GNU Taler
|
|
|
|
GNU Taler is an open protocol for an electronic payment system with a
|
|
free software reference implementation. GNU Taler offers secure, fast
|
|
and easy payment processing using well understood cryptographic
|
|
techniques. GNU Taler allows customers to remain anonymous, while
|
|
ensuring that merchants can be held accountable by governments.
|
|
Hence, GNU Taler is compatible with anti-money-laundering (AML) and
|
|
know-your-customer (KYC) regulation, as well as data protection
|
|
regulation (such as GDPR).
|
|
|
|
GNU Taler is not yet production-ready, after following this manual
|
|
you will have a backend that can process payments in ``KUDOS'', but
|
|
not regular currencies. This is not so much because of limitations
|
|
in the backend, but because we are not aware of a Taler exchange
|
|
operator offering regular currencies today.
|
|
|
|
@section About this manual
|
|
|
|
This tutorial targets system administrators who want to install and
|
|
operate a GNU Taler exchange.
|
|
|
|
@section Organizational prerequisites
|
|
|
|
Operating a GNU Taler exchange means that you are operating a payment
|
|
service provider, which means that you will most likely need a bank
|
|
license and/or follow applicable financial regulation.
|
|
|
|
@cindex availability
|
|
@cindex backup
|
|
@cindex replication
|
|
GNU Taler payment service providers generally need to ensure high
|
|
availability and have @emph{really} good backups (synchronous
|
|
replication, asynchronous remote replication, off-site backup, 24/7
|
|
monitoring, etc.).@footnote{Naturally, you could operate a Taler
|
|
exchange for a toy currency without any real value on low-cost setups
|
|
like a Raspberry Pi, but we urge you to limit the use of such setups
|
|
to research and education as with GNU Taler data loss instantly
|
|
results in financial losses.} This manual will not cover these
|
|
aspects of operating a payment service provider.
|
|
|
|
@cindex HSM
|
|
@cindex offline
|
|
@cindex database
|
|
@cindex operational security
|
|
We will assume that you can operate a (high-availability,
|
|
high-assurance) Postgres database. Furthermore, we expect some
|
|
moderate familiarity with the compilation and installation of free
|
|
software packages. You need to understand the cryptographic concepts
|
|
of private and public keys and must be able to protect private keys
|
|
stored in files on disk. An exchange uses an @emph{offline} master
|
|
key as well as @emph{online} keys. You are advised to secure your
|
|
private master key and any copies on encrypted, always-offline
|
|
computers. Again, we assume that you are familiar with good best
|
|
practices in operational security, including securing key
|
|
material.@footnote{The current implementation does not make provisions
|
|
for secret splitting. Still, the use of a hardware security module
|
|
(HSM) for protecting private keys is adviseable, so please contact the
|
|
developers for HSM integration support.}
|
|
|
|
|
|
@section Architecture overview
|
|
|
|
@cindex crypto-currency
|
|
@cindex bank
|
|
@cindex escrow
|
|
@cindex coin
|
|
Taler is a pure payment system, not a new crypto-currency. As such, it
|
|
operates in a traditional banking context. In particular, this means
|
|
that in order to receive funds via Taler, the merchant must have a
|
|
regular bank account, and payments can be executed in ordinary
|
|
currencies such as USD or EUR. Similarly, the Taler exchange must
|
|
interact with a bank. The bank of the exchange holds the exchange's
|
|
funds in an escrow account.
|
|
|
|
@cindex reserve
|
|
@cindex fee
|
|
@cindex aggregator
|
|
@cindex deposit
|
|
When customers wire money to the escrow account, the bank notifies
|
|
the exchange about the incoming wire transfers. The exchange then
|
|
creates a @emph{reserve} based on the subject of the wire transfer.
|
|
The wallet which knows the secret key matching the wire transfer
|
|
subject can then withdraw coins from the reserve, thereby draining
|
|
it. The liability of the exchange against the reserve is thereby
|
|
converted into a liability against digital coins issued by the
|
|
exchange. When the customer later spends the coins at a merchant,
|
|
and the merchant @emph{deposits} the coins at the exchange, the
|
|
exchange first @emph{aggregates} the amount from multiple deposits
|
|
from the same merchant and then instructs its bank to make a
|
|
wire transfer to the merchant, thereby fulfilling its obligation
|
|
and eliminating the liability. The exchange charges @emph{fees}
|
|
for some or all of its operations to cover costs and possibly make
|
|
a profit.
|
|
|
|
@cindex auditor
|
|
@cindex accounting
|
|
@emph{Auditors} are third parties, for example financial regulators,
|
|
that verify that the exchange operates correctly. The same software
|
|
is also used to calculate the exchange's profits, risk and liabilities
|
|
by the accountants of the exchange.
|
|
|
|
The Taler software stack for an exchange consists of the
|
|
following components:
|
|
|
|
@itemize
|
|
@cindex HTTP frontend
|
|
@item The HTTP frontend interacts with Taler wallets and
|
|
merchant backends. It is used to withdraw coins, deposit
|
|
coins, refresh coins, issue refunds, map wire transfers to
|
|
Taler transactions, inquire about the exchange's bank account
|
|
details, signing keys and fee structure.
|
|
The binary is the @code{taler-exchange-httpd}.
|
|
@cindex Aggregator
|
|
@item The aggregator combines multiple deposits made by
|
|
the same merchant and (eventually) triggers wire transfers for the
|
|
aggregate amount. The merchant can control how quickly wire
|
|
transfers are made. The exchange may be charge a fee per wire transfer
|
|
to discourage excessively frequent transfers. The binary
|
|
is the @code{taler-exchange-aggregator}.
|
|
@cindex Auditor
|
|
@item The auditor verifies that the transactions performed by
|
|
the exchange were done properly. It checks the various signatures,
|
|
totals up the amounts and alerts the operator to any inconsistencies.
|
|
It also computes the expected bank balance, revenue and risk exposure
|
|
of the exchange operator. The main binary is the
|
|
@code{taler-auditor}.
|
|
@cindex Wire plugin
|
|
@item A wire plugin enables the HTTP frontend to talk to the
|
|
bank. Its role is to allow the exchange to validate bank
|
|
addresses (i.e. IBAN numbers), for the aggregator to execute
|
|
wire transfers and for the auditor to query bank transaction
|
|
histories. Wire plugins are @emph{plugins} as there can be
|
|
many different implementations to deal with different
|
|
banking standards. Wire plugins are automatically located
|
|
and used by the exchange, aggregator and auditor.
|
|
@cindex DBMS
|
|
@cindex Postgres
|
|
@item The exchange requires a DBMS to stores the transaction history for
|
|
the Taler exchange and aggregator, and a (typically separate) DBMS for
|
|
the Taler auditor.
|
|
For now, the GNU Taler reference implemenation only supports Postgres,
|
|
but the code could be easily extended to support another DBMS.
|
|
@end itemize
|
|
|
|
@c The following image illustrates the various interactions of these
|
|
@c key components:
|
|
|
|
@c @center @image{arch, 3in, 4in}
|
|
|
|
|
|
@node Installation
|
|
@chapter Installation
|
|
|
|
Please install the following packages before proceeding with the exchange compilation.
|
|
|
|
@itemize
|
|
|
|
@item
|
|
GNU autoconf @geq{} 2.69
|
|
|
|
@item
|
|
GNU automake @geq{} 1.14
|
|
|
|
@item
|
|
GNU libtool @geq{} 2.4
|
|
|
|
@item
|
|
GNU autopoint @geq{} 0.19
|
|
|
|
@item
|
|
GNU libltdl @geq{} 2.4
|
|
|
|
@item
|
|
GNU libunistring @geq{} 0.9.3
|
|
|
|
@item
|
|
libcurl @geq{} 7.26 (or libgnurl @geq{} 7.26)
|
|
|
|
@item
|
|
GNU libmicrohttpd @geq{} 0.9.59
|
|
|
|
@item
|
|
GNU libgcrypt @geq{} 1.6
|
|
|
|
@item
|
|
libjansson @geq{} 2.7
|
|
|
|
@item
|
|
Postgres @geq{} 9.6, including libpq
|
|
|
|
@item
|
|
libgnunetutil (from Git)
|
|
|
|
@item
|
|
GNU Taler exchange (from Git)
|
|
@end itemize
|
|
|
|
Except for the last two, these are available in most GNU/Linux
|
|
distributions and should just be installed using the respective
|
|
package manager.
|
|
|
|
The following instructions will show how to install libgnunetutil and
|
|
the GNU Taler exchange.
|
|
|
|
Before you install libgnunetutil, you must download and install the
|
|
dependencies mentioned above, otherwise the build may succeed but fail
|
|
to export some of the tooling required by Taler.
|
|
|
|
To download and install libgnunetutil, proceed as follows:
|
|
|
|
@example
|
|
$ git clone https://gnunet.org/git/gnunet/
|
|
$ cd gnunet/
|
|
$ ./bootstrap
|
|
$ ./configure [--prefix=GNUNETPFX]
|
|
$ # Each dependency can be fetched from non standard locations via
|
|
$ # the '--with-<LIBNAME>' option. See './configure --help'.
|
|
$ make
|
|
# make install
|
|
@end example
|
|
|
|
If you did not specify a prefix, GNUnet will install to
|
|
@code{/usr/local}, which requires you to run the last step as
|
|
@code{root}.
|
|
|
|
To download and install the GNU Taler exchange, proceeds as follows:
|
|
|
|
@setsyntax shell
|
|
@example
|
|
$ git clone git://taler.net/exchange
|
|
$ cd exchange
|
|
$ ./bootstrap
|
|
$ ./configure [--prefix=EXCHANGEPFX] \
|
|
[--with-gnunet=GNUNETPFX]
|
|
$ # Each dependency can be fetched from non standard locations via
|
|
$ # the '--with-<LIBNAME>' option. See './configure --help'.
|
|
$ make
|
|
# make install
|
|
@end example
|
|
|
|
If you did not specify a prefix, the exchange will install to
|
|
@code{/usr/local}, which requires you to run the last step as
|
|
@code{root}. Note that you have to specify @code{--with-gnunet=/usr/local}
|
|
if you installed GNUnet to @code{/usr/local} in the previous step.
|
|
|
|
|
|
|
|
|
|
@node Configuration
|
|
@chapter Configuration
|
|
|
|
@c In this document, we assume that @code{$HOME/.config/taler.conf} is being customized.
|
|
|
|
This chapter provides an overview of the exchange configuration. Or
|
|
at least eventually will do so, for now it is a somewhat wild
|
|
description of some of the options.
|
|
|
|
@menu
|
|
* Configuration format::
|
|
* Using taler-config::
|
|
* Keying::
|
|
* Serving::
|
|
* Currency::
|
|
* Bank account::
|
|
* Database::
|
|
* Coins (denomination keys): Coins denomination keys.
|
|
* Keys duration::
|
|
|
|
@end menu
|
|
|
|
@include configuration-format.texi
|
|
@include taler-config.texi
|
|
|
|
|
|
|
|
|
|
@node Keying
|
|
@section Keying
|
|
|
|
The exchange works with three types of keys:
|
|
|
|
@c FIXME: explain better!
|
|
|
|
@itemize
|
|
|
|
@item
|
|
@cite{master key}
|
|
|
|
@item
|
|
@cite{sign keys}
|
|
|
|
@item
|
|
@cite{denomination keys} (see section @cite{Coins})
|
|
@end itemize
|
|
|
|
@c FIXME: text here.
|
|
|
|
@itemize
|
|
@item
|
|
@cite{MASTER_PRIV_FILE}: Path to the exchange's master private file.
|
|
|
|
@item
|
|
@cite{MASTER_PUBLIC_KEY}: Must specify the exchange's master public key.
|
|
@end itemize
|
|
|
|
|
|
|
|
|
|
|
|
@node Serving
|
|
@section Serving
|
|
|
|
|
|
The exchange can serve HTTP over both TCP and UNIX domain socket.
|
|
|
|
The following values are to be configured in the section
|
|
@cite{[exchange]}:
|
|
|
|
|
|
@itemize
|
|
|
|
@item
|
|
@cite{serve}: must be set to @cite{tcp} to serve HTTP over TCP, or
|
|
@cite{unix} to serve HTTP over a UNIX domain socket
|
|
|
|
@item
|
|
@cite{port}: Set to the TCP port to listen on if @cite{serve} Is
|
|
@cite{tcp}.
|
|
|
|
@item
|
|
@cite{unixpath}: set to the UNIX domain socket path to listen on if
|
|
@cite{serve} Is @cite{unix}
|
|
|
|
@item
|
|
@cite{unixpath_mode}: number giving the mode with the access
|
|
permission MASK for the @cite{unixpath} (i.e. 660 = rw-rw----).
|
|
@end itemize
|
|
|
|
|
|
@node Currency
|
|
@section Currency
|
|
|
|
|
|
The exchange supports only one currency. This data is set under the respective
|
|
option @cite{currency} in section @cite{[taler]}.
|
|
|
|
@node Bank account
|
|
@section Bank account
|
|
|
|
To configure a bank account in Taler, we need to furnish four
|
|
pieces of information:
|
|
@itemize
|
|
@item
|
|
The @code{payto://} URL of the bank account, which uniquely idenfies
|
|
the account. Examples for such URLs include
|
|
@code{payto://sepa/CH9300762011623852957} for a bank account
|
|
in the single European payment area (SEPA) or
|
|
@code{payto://x-taler-bank/localhost:8080/2} for the 2nd bank
|
|
account a the Taler bank demonstrator running at @code{localhost}
|
|
on port 8080. The first part of the URL following @code{payto://}
|
|
(``sepa'' or ``x-taler-bank'') is called the wire method.
|
|
@item
|
|
A matching wire plugin that implements a protocol to interact
|
|
with the banking system. For example, the EBICS plugin can
|
|
be used for SEPA transfers, or the ``taler-bank'' plugin can
|
|
interact with the Taler bank demonstrator. A wire plugin
|
|
only supports one particular wire method. Thus, you must make
|
|
sure to pick a plugin that supports the wire method used in the
|
|
URL.
|
|
@item
|
|
A file containing the signed JSON-encoded bank account details
|
|
for the /wire API. This is necessary as Taler supports offline
|
|
signing for bank accounts for additional security.
|
|
@item
|
|
Finally, the plugin needs to be provided resources for
|
|
authentication to the respective banking service. The format
|
|
in which the authentication information must be provided
|
|
depends on the wire plugin.
|
|
@end itemize
|
|
|
|
You can configure multiple accounts for an exchange by creating
|
|
sections starting with ``account-'' for the section name. You can
|
|
ENABLE for each account whether it should be used, and for what
|
|
(incoming or outgoing wire transfers):
|
|
|
|
@setsyntax ini
|
|
@example
|
|
|
|
[account-1]
|
|
URL = "payto://sepa/CH9300762011623852957"
|
|
WIRE_RESPONSE = $@{TALER_CONFIG_HOME@}/account-1.json
|
|
|
|
# Currently, only the 'taler_bank' plugin is implemented.
|
|
PLUGIN = <plugin_name_here>
|
|
|
|
# Use for exchange-aggregator (outgoing transfers)
|
|
ENABLE_DEBIT = YES
|
|
# Use for exchange-wirewatch (and listed in /wire)
|
|
ENABLE_CREDIT = YES
|
|
|
|
# Authentication options for the chosen plugin go here.
|
|
# (Next sections have examples of authentication mechanisms)
|
|
@end example
|
|
|
|
The command line tool @cite{taler-exchange-wire} is used to create
|
|
the @code{account-1.json} file.
|
|
For example, the utility may be invoked as follows to create
|
|
all of the WIRE_RESPONSE files (in the locations specified by the configuration):
|
|
|
|
@example
|
|
$ taler-exchange-wire
|
|
@end example
|
|
|
|
The generated file will be echoed by the exchange when serving
|
|
/wire@footnote{https://api.taler.net/api-exchange.html#wire-req}
|
|
requests.
|
|
|
|
|
|
@menu
|
|
* Wire plugin ``taler_bank''::
|
|
* Wire plugin ``ebics''::
|
|
* Wire fee structure::
|
|
@end menu
|
|
|
|
@node Wire plugin ``taler_bank''
|
|
@subsection Wire plugin ``taler_bank''
|
|
@cindex x-taler-bank
|
|
@cindex taler_bank plugin
|
|
|
|
The @code{taler_bank} plugin implements the wire method ``x-taler-bank''.
|
|
|
|
The format of the @code{payto://} URL is @code{payto://x-taler-bank/HOSTNAME:PORT},
|
|
possibly followed by other parameters like the amount and wire transfer subject
|
|
as per the @code{payto://} standard.
|
|
|
|
For basic authentication, the @code{taler_bank} plugin only supports
|
|
simple password-based authentication. For this, the configuration
|
|
must contain the ``USERNAME'' and ``PASSWORD'' of the respective
|
|
account at the bank.
|
|
|
|
@setsyntax ini
|
|
@example
|
|
[account-1]
|
|
|
|
# Bank account details here..
|
|
# ..
|
|
|
|
# Authentication options for the taler_bank plugin below:
|
|
|
|
TALER_BANK_AUTH_METHOD = basic
|
|
USERNAME = exchange
|
|
PASSWORD = super-secure
|
|
@end example
|
|
|
|
|
|
@node Wire plugin ``ebics''
|
|
@subsection Wire plugin ``ebics''
|
|
|
|
The ``ebics'' wire plugin is not fully implemented and today
|
|
does not support actual wire transfers.
|
|
|
|
|
|
@cartouche
|
|
@quotation Note
|
|
The rationale behind having multiple bank accounts is that the exchange operator, as a security
|
|
measure, may want to instruct the bank that the incoming bank account is only supposed to
|
|
@emph{receive} money.
|
|
@end quotation
|
|
@end cartouche
|
|
|
|
|
|
@node Wire fee structure
|
|
@subsection Wire fee structure
|
|
@cindex wire fee
|
|
@cindex fee
|
|
|
|
For each wire method (``sepa'' or ``x-taler-wire'', but not per plugin!) the
|
|
exchange configuration must specify applicable wire fees. This is done
|
|
in configuration sections of the format @code{fee-METHOD}. There are two
|
|
types of fees, simple wire fees and closing fees. Wire fees apply whenever
|
|
the aggregator transfers funds to a merchant. Closing fees apply whenever
|
|
the exchange closes a reserve (sending back funds to the customer). The
|
|
fees must be constant for a full year, which is specified as part of the name
|
|
of the option.
|
|
|
|
@setsyntax ini
|
|
@example
|
|
[fee-iban]
|
|
WIRE-FEE-2018 = EUR:0.01
|
|
WIRE-FEE-2019 = EUR:0.01
|
|
CLOSING-FEE-2018 = EUR:0.01
|
|
CLOSING-FEE-2019 = EUR:0.01
|
|
|
|
[fee-x-taler-bank]
|
|
WIRE-FEE-2018 = KUDOS:0.01
|
|
WIRE-FEE-2019 = KUDOS:0.01
|
|
CLOSING-FEE-2018 = KUDOS:0.01
|
|
CLOSING-FEE-2019 = KUDOS:0.01
|
|
@end example
|
|
|
|
|
|
@node Database
|
|
@section Database
|
|
|
|
|
|
The option @cite{db} under section @cite{[exchange]} gets the DB backend's name the exchange
|
|
is going to use. So far, only @cite{db = postgres} is supported. After choosing the backend,
|
|
it is mandatory to supply the connection string (namely, the database name). This is
|
|
possible in two ways:
|
|
|
|
|
|
@itemize
|
|
|
|
@item
|
|
via an environment variable: @cite{TALER_EXCHANGEDB_POSTGRES_CONFIG}.
|
|
|
|
@item
|
|
via configuration option @cite{CONFIG}, under section @cite{[exchangedb-BACKEND]}. For example, the demo exchange is configured as follows:
|
|
@end itemize
|
|
|
|
@setsyntax ini
|
|
@example
|
|
[exchange]
|
|
...
|
|
DB = postgres
|
|
...
|
|
|
|
[exchangedb-postgres]
|
|
CONFIG = postgres:///talerdemo
|
|
@end example
|
|
|
|
@node Coins denomination keys
|
|
@section Coins (denomination keys)
|
|
|
|
|
|
Sections specifying denomination (coin) information start with
|
|
"coin_". By convention, the name continues with
|
|
"$CURRENCY_[$SUBUNIT]_$VALUE", i.e. @cite{[coin_eur_ct_10]} for a 10
|
|
cent piece. However, only the "coin_" prefix is mandatory. Each
|
|
"coin_"-section must then have the following options:
|
|
|
|
|
|
@itemize
|
|
|
|
@item
|
|
@cite{value}: How much is the coin worth, the format is
|
|
CURRENCY:VALUE.FRACTION. For example, a 10 cent piece is "EUR:0.10".
|
|
|
|
@item
|
|
@cite{duration_withdraw}: How long can a coin of this type be
|
|
withdrawn? This limits the losses incurred by the exchange when a
|
|
denomination key is compromised.
|
|
|
|
@item
|
|
@cite{duration_overlap}: What is the overlap of the withdrawal
|
|
timespan for this coin type?
|
|
|
|
@item
|
|
@cite{duration_spend}: How long is a coin of the given type valid?
|
|
Smaller values result in lower storage costs for the exchange.
|
|
|
|
@item
|
|
@cite{fee_withdraw}: What does it cost to withdraw this coin?
|
|
Specified using the same format as @cite{value}.
|
|
|
|
@item
|
|
@cite{fee_deposit}: What does it cost to deposit this coin? Specified
|
|
using the same format as @cite{value}.
|
|
|
|
@item
|
|
@cite{fee_refresh}: What does it cost to refresh this coin? Specified
|
|
using the same format as @cite{value}.
|
|
|
|
@item
|
|
@cite{rsa_keysize}: How many bits should the RSA modulus (product of
|
|
the two primes) have for this type of coin.
|
|
@end itemize
|
|
|
|
|
|
@node Keys duration
|
|
@section Keys duration
|
|
|
|
|
|
Both @cite{signkeys} and @cite{denom keys} have a starting date. The
|
|
option @cite{lookahead_provide}, under section @cite{[exchange_keys]},
|
|
is such that only keys whose starting date is younger than
|
|
@cite{lookahead_provide} will be issued by the exchange.
|
|
|
|
@cite{signkeys}. The option @cite{lookahead_sign} is such that, being
|
|
@cite{t} the time when @cite{taler-exchange-keyup} is run,
|
|
@cite{taler-exchange-keyup} will generate @cite{n} @cite{signkeys},
|
|
where @cite{t + (n * signkey_duration) = t + lookahead_sign}. In other
|
|
words, we generate a number of keys which is sufficient to cover a
|
|
period of @cite{lookahead_sign}. As for the starting date, the first
|
|
generated key will get a starting time of @cite{t}, and the
|
|
@cite{j}-th key will get a starting time of @cite{x +
|
|
signkey_duration}, where @cite{x} is the starting time of the
|
|
@cite{(j-1)}-th key.
|
|
|
|
@cite{denom keys}. The option @cite{lookahead_sign} is such that,
|
|
being @cite{t} the time when @cite{taler-exchange-keyup} is run,
|
|
@cite{taler-exchange-keyup} will generate @cite{n} @cite{denom keys}
|
|
for each denomination, where @cite{t + (n * duration_withdraw) = t +
|
|
lookahead_sign}. In other words, for each denomination, we generate a
|
|
number of keys which is sufficient to cover a period of
|
|
@cite{lookahead_sign}. As for the starting date, the first generated
|
|
key will get a starting time of @cite{t}, and the @cite{j}-th key will
|
|
get a starting time of @cite{x + duration_withdraw}, where @cite{x} is
|
|
the starting time of the @cite{(j-1)}-th key.
|
|
|
|
To change these settings, edit the following
|
|
values in section @cite{[exchange]}:
|
|
|
|
@itemize
|
|
@item
|
|
@cite{SIGNKEY_DURATION}: How long should one signing key be used?
|
|
|
|
@item
|
|
@cite{LOOKAHEAD_SIGN}: How much time we want to cover with our
|
|
signing keys? Note that if @cite{SIGNKEY_DURATION} is bigger than
|
|
@cite{LOOKAHEAD_SIGN}, @code{taler-exchange-keyup} will generate a
|
|
quantity of signing keys which is sufficient to cover all the
|
|
gap.
|
|
@end itemize
|
|
|
|
@c FIXME: LEGAL_DURATION not covered!
|
|
@c FIXME: LOOKAHEAD_PROVIDE not covered!
|
|
|
|
|
|
@node Deployment
|
|
@chapter Deployment
|
|
|
|
|
|
@menu
|
|
* Keys generation::
|
|
* Database upgrades::
|
|
@end menu
|
|
|
|
@node Keys generation
|
|
@section Keys generation
|
|
|
|
Once the configuration is properly set up, all the keys can be generated
|
|
by the tool @code{taler-exchange-keyup}. The following command generates denomkeys
|
|
and signkeys, plus the "blob" that is to be signed by the auditor.
|
|
|
|
@example
|
|
taler-exchange-keyup -o blob
|
|
@end example
|
|
|
|
@emph{blob} contains data about denomkeys that the exchange operator needs to
|
|
get signed by every auditor he wishes (or is forced to) work with.
|
|
|
|
In a normal scenario, an auditor must have some way of receiving the blob to
|
|
sign (Website, manual delivery, ..). Nonetheless, the exchange admin can fake
|
|
an auditor signature --- for testing purposes --- by running the following command
|
|
|
|
@example
|
|
taler-auditor-sign -m EXCHANGE_MASTER_PUB -r BLOB -u AUDITOR_URL -o OUTPUT_FILE
|
|
@end example
|
|
|
|
Those arguments are all mandatory.
|
|
|
|
@itemize
|
|
@item @code{EXCHANGE_MASTER_PUB} the base32 Crockford-encoded exchange's master
|
|
public key. Tipically, this value lies in the configuration option
|
|
@code{[exchange]/master_public_key}.
|
|
@item @code{BLOB} the blob generated in the previous step.
|
|
@item @code{AUDITOR_URL} the URL that identifies the auditor.
|
|
@item @code{OUTPUT_FILE} where on the disk the signed blob is to be saved.
|
|
@end itemize
|
|
|
|
@code{OUTPUT_FILE} must then be copied into the directory specified
|
|
by the option @code{AUDITOR_BASE_DIR} under the section @code{[exchangedb]}.
|
|
Assuming @code{AUDITOR_BASE_DIR = $@{HOME@}/.local/share/taler/auditors}, the
|
|
following command will "add" the auditor identified by @code{AUDITOR_URL} to
|
|
the exchange.
|
|
|
|
@example
|
|
cp OUTPUT_FILE $@{HOME@}/.local/share/taler/auditors
|
|
@end example
|
|
|
|
If the auditor has been correctly added, the exchange's @code{/keys} response
|
|
must contain an entry in the @code{auditors} array mentioning the auditor's URL.
|
|
|
|
|
|
@c FIXME: reference section about where keys are stored.
|
|
|
|
@node Database upgrades
|
|
@section Database upgrades
|
|
|
|
Currently, there is no way to upgrade the database between Taler versions.
|
|
|
|
The exchange database can be re-initialized using:
|
|
|
|
@example
|
|
$ taler-exchange-dbinit -r
|
|
@end example
|
|
|
|
However, running this command will result in all data in the database
|
|
being lost, which may result in significant financial liabilities as
|
|
the exchange can then not detect double-spending. Hence this
|
|
operation must not be performed in a production system.
|
|
|
|
@node Diagnostics
|
|
@chapter Diagnostics
|
|
|
|
This chapter includes various (very unpolished) sections on specific topics
|
|
that might be helpful to understand how the exchange operates, which files
|
|
should be backed up. The information may also be helpful for diagnostics.
|
|
|
|
@menu
|
|
* Reserve management::
|
|
* Database Scheme::
|
|
* Signing key storage::
|
|
* Denomination key storage::
|
|
* Auditor signature storage::
|
|
@end menu
|
|
|
|
|
|
@node Reserve management
|
|
@section Reserve management
|
|
|
|
|
|
Incoming transactions to the exchange's provider result in the
|
|
creation or update of reserves, identified by their reserve key. The
|
|
command line tool @cite{taler-exchange-reservemod} allows create and
|
|
add money to reserves in the exchange's database.
|
|
|
|
|
|
|
|
|
|
@node Database Scheme
|
|
@section Database Scheme
|
|
|
|
|
|
The exchange database must be initialized using @cite{taler-exchange-dbinit}. This
|
|
tool creates the tables required by the Taler exchange to operate. The
|
|
tool also allows you to reset the Taler exchange database, which is useful
|
|
for test cases but should never be used in production. Finally,
|
|
@cite{taler-exchange-dbinit} has a function to garbage collect a database,
|
|
allowing administrators to purge records that are no longer required.
|
|
|
|
The database scheme used by the exchange look as follows:
|
|
|
|
@image{exchange-db,5in,,,png}
|
|
|
|
|
|
@node Signing key storage
|
|
@section Signing key storage
|
|
|
|
|
|
The private online signing keys of the exchange are stored in a
|
|
subdirectory "signkeys/" of the "KEYDIR" which is an option in the
|
|
"[exchange]" section of the configuration file. The filename is the
|
|
starting time at which the signing key can be used in microseconds
|
|
since the Epoch. The file format is defined by the @cite{struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP}:
|
|
|
|
@example
|
|
struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP @{
|
|
struct TALER_ExchangePrivateKeyP signkey_priv;
|
|
struct TALER_ExchangeSigningKeyValidityPS issue;
|
|
@};
|
|
@end example
|
|
|
|
|
|
@node Denomination key storage
|
|
@section Denomination key storage
|
|
|
|
The private denomination keys of the exchange are store in a
|
|
subdirectory "denomkeys/" of the "KEYDIR" which is an option in the
|
|
"[exchange]" section of the configuration file. "denomkeys/" contains
|
|
further subdirectories, one per denomination. The specific name of
|
|
the subdirectory under "denomkeys/" is ignored by the exchange.
|
|
However, the name is important for the "taler-exchange-keyup" tool
|
|
that generates the keys. The tool combines a human-readable encoding
|
|
of the denomination (i.e. for EUR:1.50 the prefix would be
|
|
"EUR_1_5-", or for EUR:0.01 the name would be "EUR_0_01-") with a
|
|
postfix that is a truncated Crockford32 encoded hash of the various
|
|
attributes of the denomination key (relative validity periods, fee
|
|
structure and key size). Thus, if any attributes of a coin change,
|
|
the name of the subdirectory will also change, even if the
|
|
denomination remains the same.
|
|
|
|
Within this subdirectory, each file represents a particular
|
|
denomination key. The filename is the starting time at which the
|
|
signing key can be used in microseconds since the Epoch. The
|
|
format on disk begins with a
|
|
@cite{struct TALER_EXCHANGEDB_DenominationKeyInformationP} giving
|
|
the attributes of the denomination key and the associated
|
|
signature with the exchange's long-term offline key:
|
|
|
|
@example
|
|
struct TALER_EXCHANGEDB_DenominationKeyInformationP @{
|
|
struct TALER_MasterSignatureP signature;
|
|
struct TALER_DenominationKeyValidityPS properties;
|
|
@};
|
|
@end example
|
|
|
|
This is then followed by the variable-size RSA private key in
|
|
libgcrypt's S-expression format, which can be decoded using
|
|
@cite{GNUNET_CRYPTO_rsa_private_key_decode()}.
|
|
|
|
@menu
|
|
* Revocations::
|
|
@end menu
|
|
|
|
@node Revocations
|
|
@subsection Revocations
|
|
|
|
@cindex payback
|
|
@cindex revocation
|
|
When an exchange goes out of business or detects that the private
|
|
key of a denomination key pair has been compromised, it may revoke
|
|
some or all of its denomination keys. At this point, the hashes
|
|
of the revoked keys must be returned as part of the @code{/keys} response
|
|
under ``payback''. Wallets detect this, and then return unspent
|
|
coins of the respective denomination key using the @code{/payback}
|
|
API.
|
|
|
|
When a denomination key is revoked, a revocation file is placed
|
|
into the respective subdirectory of ``denomkeys/''. The file has the
|
|
same prefix as the file that stores the
|
|
@cite{struct TALER_EXCHANGEDB_DenominationKeyInformationP} information,
|
|
but is followed by the ``.rev'' suffix. It contains a 64-byte
|
|
EdDSA signature made with the master key of the exchange with purpose
|
|
@code{TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED}. If such a file
|
|
is present, the exchange must check the signature and if it is valid
|
|
treat the respective denomination key as revoked.
|
|
|
|
Revocation files can be generated using the
|
|
@code{taler-exchange-keyup} command-line tool using the @code{-r}
|
|
option. The Taler auditor will instruct operators to generate
|
|
revocations if it detects a key compromise (which is possible more
|
|
coins of a particular denomination were deposited than issued).
|
|
|
|
It should be noted that denomination key revocations should only happen
|
|
under highly unusual (``emergency'') conditions and not under normal
|
|
conditions.
|
|
|
|
|
|
@node Auditor signature storage
|
|
@section Auditor signature storage
|
|
|
|
|
|
Signatures from auditors are stored in the directory specified
|
|
in the exchange configuration section "exchangedb" under the
|
|
option "AUDITOR_BASE_DIR". The exchange does not care about
|
|
the specific names of the files in this directory.
|
|
|
|
Each file must contain a header with the public key information
|
|
of the auditor, the master public key of the exchange, and
|
|
the number of signed denomination keys:
|
|
|
|
@example
|
|
struct AuditorFileHeaderP @{
|
|
struct TALER_AuditorPublicKeyP apub;
|
|
struct TALER_MasterPublicKeyP mpub;
|
|
uint32_t dki_len;
|
|
@};
|
|
@end example
|
|
|
|
This is then followed by @cite{dki_len} signatures of the auditor of type
|
|
@cite{struct TALER_AuditorSignatureP}, which are then followed by another
|
|
@cite{dki_len} blocks of type @cite{struct TALER_DenominationKeyValidityPS}.
|
|
The auditor's signatures must be signatures over the information of
|
|
the corresponding denomination key validity structures embedded in a
|
|
@cite{struct TALER_ExchangeKeyValidityPS} structure using the
|
|
@cite{TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS} purpose.
|
|
|
|
|
|
|
|
@c **********************************************************
|
|
@c ******************* Appendices *************************
|
|
@c **********************************************************
|
|
|
|
@node GNU-AGPL
|
|
@chapter GNU Affero GPL
|
|
@cindex license
|
|
@include agpl.texi
|
|
|
|
@node GNU-FDL
|
|
@chapter GNU Free Documentation License
|
|
@cindex license
|
|
@include fdl-1.3.texi
|
|
|
|
@node Concept Index
|
|
@chapter Concept Index
|
|
|
|
@printindex cp
|
|
|
|
@bye
|