initial import of thesis-dold
24
doc/system/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
thesis.pdf
|
||||
thesis-*.pdf
|
||||
thesis.out
|
||||
summary/summary-english.pdf
|
||||
*-converted-to.pdf
|
||||
*.log
|
||||
*.toc
|
||||
*.run.xml
|
||||
*.ind
|
||||
*.ilg
|
||||
*.fls
|
||||
*.fdb_latexmk
|
||||
*.aux
|
||||
*.idx
|
||||
*.bbl
|
||||
*.bcf
|
||||
*.blg
|
||||
*.lof
|
||||
*.maf
|
||||
*.mt*
|
||||
|
||||
bench/results/
|
||||
bench/plots/
|
||||
bench/stats
|
52
doc/system/abstract.tex
Normal file
@ -0,0 +1,52 @@
|
||||
\chapter{Abstract}
|
||||
%As our society becomes more and more digitalized, an electronic version of cash
|
||||
%becomes inevitable. The design of payment systems is not just a technological
|
||||
%matter, but has far-reaching sociopolitical consequences.
|
||||
\begin{samepage}
|
||||
We describe the design and implementation of GNU Taler, an electronic payment
|
||||
system based on an extension of Chaumian online e-cash with efficient change.
|
||||
In addition to anonymity for customers, it provides the novel notion of
|
||||
\emph{income transparency}, which guarantees that merchants can reliably
|
||||
receive a payment from an untrusted payer only when their income from the
|
||||
payment is visible to tax authorities.
|
||||
|
||||
Income transparency is achieved by the introduction of a \emph{refresh
|
||||
protocol}, which gives anonymous change for a partially spent coin without
|
||||
introducing a tax evasion loophole. In addition to income transparency, the
|
||||
refresh protocol can be used to implement Camenisch-style \emph{atomic swaps}, and to
|
||||
preserve anonymity in the presence of protocol \emph{aborts} and crash faults with
|
||||
data loss by participants.
|
||||
|
||||
Furthermore, we show the provable security of our income-transparent anonymous
|
||||
e-cash, which, in addition to the usual \emph{anonymity} and
|
||||
\emph{unforgeability} properties of e-cash, also formally models
|
||||
\emph{conservation} of funds and income transparency.
|
||||
|
||||
Our implementation of GNU Taler is usable by non-expert users and integrates
|
||||
with the modern Web architecture. Our payment platform addresses a range of
|
||||
practical issues, such as tipping customers, providing refunds, integrating
|
||||
with banks and know-your-customer (KYC) checks, as well as Web platform
|
||||
security and reliability requirements. On a single machine, we achieve
|
||||
transaction rates that rival those of global, commercial credit card
|
||||
processors. We increase the robustness of the exchange---the component that
|
||||
keeps bank money in escrow in exchange for e-cash---by adding an auditor
|
||||
component, which verifies the correct operation of the system and allows to
|
||||
detect a compromise or misbehavior of the exchange early.
|
||||
|
||||
Just like bank accounts have reason to exist besides bank notes, e-cash only
|
||||
serves as part of a whole payment system stack. Distributed ledgers have
|
||||
recently gained immense popularity as potential replacement for parts of the
|
||||
traditional financial industry. While cryptocurrencies based on proof-of-work
|
||||
such as Bitcoin have yet to scale to be useful as a replacement for established
|
||||
payment systems, other more efficient systems based on blockchains with more
|
||||
classical consensus algorithms might still have promising applications in the
|
||||
financial industry.
|
||||
|
||||
We design, implement and analyze the performance of \emph{Byzantine Set Union
|
||||
Consensus} (BSC), a Byzantine consensus protocol that agrees on a (super-)set
|
||||
of elements at once, instead of sequentially agreeing on the individual
|
||||
elements of a set. While BSC is interesting in itself, it can also be used as
|
||||
a building block for permissioned blockchains, where---just like in
|
||||
Nakamoto-style consensus---whole blocks of transactions are agreed upon at once,
|
||||
increasing the transaction rate.
|
||||
\end{samepage}
|
27
doc/system/acknowledgements.tex
Normal file
@ -0,0 +1,27 @@
|
||||
\chapter*{Acknowledgements}
|
||||
|
||||
The book is based on Florian Dold's PhD thesis. We have removed the parts that
|
||||
are not crucial for GNU Taler. Also, unlike the thesis, the GNU Taler project
|
||||
continues to be updated, so this books is expected to be kept up-to-date with
|
||||
the latest developments. Nevertheless, Florian Dold's contribution to the
|
||||
text remains fundamental.
|
||||
|
||||
We would like to thank Moritz Bartl for helping with the funding for Florian's
|
||||
thesis and GNU Taler in general. Bruno Haible provided generous support for
|
||||
the GNU Taler team to visit meetings of the W3C's Web Payment Working Group.
|
||||
We also thank Ashoka, the Tor project and the Donaukurier for their support.
|
||||
|
||||
This work benefits from the financial support of the Brittany Region (ARED
|
||||
9174) and the Renewable Freedom Foundation (RFF).
|
||||
|
||||
We thank the Bern University of Applied Sciences for continuing to host the
|
||||
GNU Taler servers.
|
||||
|
||||
We thank to Cristina Onete and Jeff Burdges for their collaboration on the
|
||||
provable security of GNU Taler.
|
||||
|
||||
We are grateful to the GNU project, in particular Richard Stallman, for their
|
||||
support of this project. We also thank all GNUnet developers and GNU Guix
|
||||
developers, especially Hartmut Goebel, Nils Gillmann, Gabor Toth, Ludovic
|
||||
Courtès and Andreas Enge.
|
||||
|
247
doc/system/conclusions.tex
Normal file
@ -0,0 +1,247 @@
|
||||
\chapter{Future Work}\label{chapter:future-work}
|
||||
We now discuss future work that builds upon the results presented so far.
|
||||
|
||||
|
||||
\subsection*{Standard Model}
|
||||
Our current instantiation of the Taler protocol relies heavily on hash
|
||||
functions. Since the result by Canetti and others \cite{canetti2004random}
|
||||
about the theoretical impossibility of securely instantiating protocols that
|
||||
rely on the random oracle assumption for their security, a vast amount of
|
||||
literature has been devoted to find instantiations of interesting protocols in
|
||||
the standard model \cite{koblitz2015random}. The Taler protocol syntax could
|
||||
likely be also instantiated securely in the standard model, based existing on
|
||||
blind signature schemes in the standard model. The trade-off however is that
|
||||
while removing the random oracle assumption, typically other less well known
|
||||
assumptions must be made.
|
||||
|
||||
\subsection*{Post-Quantum security}
|
||||
The possibility of post-quantum computers breaking the security of established
|
||||
cryptographic primitives has lately received a lot of attention from
|
||||
cryptographers. While currently most schemes with post-quantum security are impractical,
|
||||
it might be worthwhile to further investigate their application to e-cash, based
|
||||
on existing work such as \cite{zhang2018new}.
|
||||
|
||||
\subsection*{Applications to network incentives}
|
||||
Some peer-to-peer networking protocols (such as onion routing
|
||||
\cite{dingledine2004tor}) do not have inherent incentives and rely on
|
||||
volunteers to provide infrastructure. In future work, we want to look at
|
||||
adding incentives in the form of Taler payments to a peer-to-peer networking
|
||||
platform such as GNUnet.
|
||||
|
||||
\subsection*{Smart(er) Contracts and Auctions}
|
||||
Contract terms in Taler are relatively limited. There are some interesting
|
||||
secure multiparty computations, such as privacy-preserving auctions
|
||||
\cite{brandt2006obtain} that could be offered by exchanges as a fixed smart
|
||||
contract. This would allow a full privacy-preserving auction platform, as
|
||||
current auction protocols only output the winner of a privacy-preserving
|
||||
auction but do not address the required anonymous payments.
|
||||
|
||||
|
||||
\subsection*{Backup and Sync}\label{sec:future-work-backup-sync}
|
||||
Synchronization of wallets between multiple devices is a useful feature, but a
|
||||
na\"ive implementation endangers privacy. A carefully designed protocol for
|
||||
backup and synchronization must make sure that the hosting service for the
|
||||
wallet's data cannot collaborate with the exchange and merchants to deanonymize
|
||||
users or transactions. Thus when spending coins for a payment, devices should
|
||||
not have to synchronously talk to their backup/sync provider. This creates the
|
||||
challenge of allocating the total available balance to individual devices in a
|
||||
way that fits the customer's spending pattern, and only require synchronous
|
||||
communication at fixed intervals or when really necessary to re-allocate coins.
|
||||
|
||||
Another possible approach might be to use Private Information Retrieval (PIR)
|
||||
\cite{goldberg2007improving} to access backup and synchronization information.
|
||||
|
||||
|
||||
\subsection*{Machine-Verified Proofs}
|
||||
We currently model only a subset of the GNU Taler protocol formally, and proofs
|
||||
are handwritten and verified by humans. A tool such as CryptoVerif
|
||||
\cite{blanchet2007cryptoverif} can allow a higher coverage and computer-checked
|
||||
proofs, and would allow protocol changes to be validated in shorter time.
|
||||
|
||||
\subsection*{Coin Restrictions / ``Taler for Children''}
|
||||
By designating certain denominations for different purposes, GNU Taler could be
|
||||
used to implement a very simple form of anonymous credentials
|
||||
\cite{paquin2011u,camenisch2004signature}, which then could be used to
|
||||
implement a Taler wallet specifically aimed at children, in order to teach them
|
||||
responsible and autonomous spending behavior, while granting them privacy and
|
||||
at the same time preventing them from making age-inappropriate purchases
|
||||
online, as the discretion of parents.
|
||||
|
||||
%\subsection*{gnunet-blockchain / deployment of the full stack payment system}
|
||||
%=> no, talk more about integration with real banks, KYC
|
||||
%
|
||||
%\subsection*{P2P payments}
|
||||
%
|
||||
%\subsection*{NFC Wallet}
|
||||
%
|
||||
%\subsection*{large, scaleable deployment}
|
||||
%I.e. sharding, db replication, load balancer(s)
|
||||
%
|
||||
%\subsection*{Hardware security module for exchange}
|
||||
%
|
||||
%\subsection*{Bitcoin/Blockchain integration}
|
||||
%
|
||||
%\subsection*{UX study and improvements}
|
||||
%(including tracking/planning of spending)
|
||||
%
|
||||
%\subsection*{News Distribution}
|
||||
|
||||
\chapter{Conclusion}\label{chapter:conclusion}
|
||||
|
||||
% sources and inspirations
|
||||
% https://www.bis.org/publ/arpdf/ar2018e5.pdf
|
||||
% https://www.bis.org/publ/qtrpdf/r_qt1709f.pdf
|
||||
% http://andolfatto.blogspot.com/2015/02/fedcoin-on-desirability-of-government.html
|
||||
|
||||
% mention eKrona/Riksbank
|
||||
|
||||
% bessere ueberleitung
|
||||
% effizienz!
|
||||
% freie software / commons
|
||||
% scalability of blockchains
|
||||
% expand on some ideas such as naiveity of blockchains
|
||||
% 3 areas for currencies
|
||||
|
||||
|
||||
% einleitung: we introduced two systems that solve/address core problems for
|
||||
% banking (consensus, transactions, ...) "geld ist kein selbstzweck"
|
||||
% reason for having money is: ...
|
||||
|
||||
% central banks are the only tool that we know that works
|
||||
|
||||
% geld ist politisch, macht, verantwortung, gesellschaften aufbauen oder ruinieren
|
||||
% apolitical solution impossible
|
||||
|
||||
This book presented GNU Taler, an efficient protocol for
|
||||
value-based electronic payment systems with focus on security and
|
||||
privacy. While we believe our approach to be socially and economically beneficial, a
|
||||
technological impact analysis is in order prior to adopting new
|
||||
systems that have broad economic and socio-political implications.
|
||||
|
||||
Currencies serve three key functions in society:~\cite{mankiw2010macroeconomics}
|
||||
\begin{enumerate}
|
||||
\item As a unit for measurement of value,
|
||||
\item a medium of exchange, and
|
||||
\item a store of value.
|
||||
\end{enumerate}
|
||||
How do the various methods measure up to these requirements?
|
||||
|
||||
\section{Cryptocurrencies vs. Central-Bank-Issued Currencies}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{diagrams/bitcoin-market-price.png}
|
||||
\caption[Historical market price of Bitcoin.]{Historical market price (in
|
||||
USD) of Bitcoin across major exchanges (Source:~\url{https://blockchain.com}).}
|
||||
\label{fig:volatility}
|
||||
\end{figure}
|
||||
|
||||
Cryptocurrencies generally fail to achieve the required stability to serve as a
|
||||
reasonable unit of measurement (Figure~\ref{fig:volatility}). The volatility
|
||||
of cyptocurrencies is caused by a combination of a lack of institutions that
|
||||
could intervene to dampen fluctuations and a comparatively limited liquidity
|
||||
in the respective
|
||||
markets. The latter is exacerbated by the limited ability of decentralized
|
||||
cryptocurrencies to handle large transaction volumes, despite their extreme
|
||||
levels of resource consumption. As a result, the utility of decentralized
|
||||
cryptocurrencies is limited to highly speculative investments and to the
|
||||
facilitation of criminal transactions.
|
||||
|
||||
With respect to privacy, completely decentralized cryptocurrencies
|
||||
provide either too much or too little anonymity. Transparent
|
||||
cryptocurrencies create the spectre of discriminatory pricing, while
|
||||
especially for privacy-enhanced cryptocurrencies the lack of
|
||||
regulation creates an attractive environment for fraud and criminal
|
||||
activity from tax evasion to financing of terrorism.
|
||||
|
||||
These problems are easily addressed by combining the register (or
|
||||
ledger) with a central bank providing a regulatory framework and
|
||||
monetary policy, including anti-money-laundering and
|
||||
know-your-customer enforcement.
|
||||
|
||||
\section{Electronic Payments}
|
||||
|
||||
Day-to-day payments using registers are expensive and inconvenient.
|
||||
Using a register requires users to {\em identify} themselves to {\em
|
||||
authorize} transactions, and the use of register-based banking
|
||||
systems tends to be more expensive than the direct exchange of
|
||||
physical cash. However, with the ongoing digitalization of daily life
|
||||
where a significant number of transactions is realized over networks,
|
||||
some form of electronic payments remain inevitable.
|
||||
|
||||
The current alternative to (centrally banked) electronic cash are a
|
||||
payment systems under full control of oligopoly companies such as
|
||||
Google, Apple, Facebook or Visa. The resulting oligopolies are
|
||||
anti-competitive. In addition to excessive fees, they sometimes even
|
||||
refuse to process payments with certain types of legal businesses,
|
||||
which then are often ruined due to lack of alternatives. Combining
|
||||
payment services with companies where the core business model is
|
||||
advertising is also particularly damaging for privacy. Finally, the
|
||||
sheer size of these companies creates systemic risks, just as their
|
||||
global scale creates challenges for regulation.
|
||||
|
||||
As GNU Taler is free software, even without backing by a central bank,
|
||||
Taler would not suffer from these drawbacks arising from the use of
|
||||
proprietary technology.
|
||||
|
||||
Furthermore, Taler-style electronic cash comes
|
||||
with some unique benefits:
|
||||
\begin{itemize}
|
||||
\item improved income transparency compared to cash and traditional
|
||||
Chaum-style e-cash,
|
||||
\item anonymity for payers,
|
||||
\item avoidance of enticement towards consumer debt --- especially
|
||||
compared to credit cards, and
|
||||
\item support of new business models and Internet security
|
||||
mechanisms which require (anonymous) micro-transactions.
|
||||
\end{itemize}
|
||||
|
||||
Central banks are carefully considering what might be the right
|
||||
technology to implement an electronic version of their centrally
|
||||
banked currency, and with Taler we hope to address most of their concerns.
|
||||
Nevertheless, all electronic payment systems, including Taler even
|
||||
when backed by central-bank-issued currencies, come with their own
|
||||
inherent set of risks:~\cite{riksbank2017riksbank}
|
||||
|
||||
\begin{itemize}
|
||||
\item increased risk of a bank run: in a banking crisis,
|
||||
as it is easier to withdraw large amounts of digital
|
||||
cash quickly --- even from remote locations;
|
||||
\item increased volatility due to foreign holdings that would
|
||||
not be as easily possible with physical cash;
|
||||
\item increased risk of theft and disruption: while physical
|
||||
cash can also be stolen (and likely with much less effort), it is
|
||||
difficult to transport in volume~\cite{force2015money}, the
|
||||
risk is increased with computers because attacks scale \cite{hammer2018billion}, and
|
||||
generally many small incidents are socially preferable over a
|
||||
tiny number of very large-scale incidents; and
|
||||
\item unavailability in crisis situations without electricity and Internet
|
||||
connectivity.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
We believe that in the case of Taler, some of the risks mentioned
|
||||
above can be mitigated:
|
||||
\begin{itemize}
|
||||
\item Volatility due to foreign holdings and the resulting increased
|
||||
risk of bank runs can be reduced by putting limits on the amount of
|
||||
electronic coins that customers can withdraw. Limiting the
|
||||
validity periods of coins is another method that can help
|
||||
disincentivize the use of Taler as a value store.
|
||||
\item The use of open standards and reference implementations enables
|
||||
white-hat security research around GNU Taler, which together with
|
||||
good operational security procedures and the possibility of
|
||||
competing providers should reduce the risks from attacks.
|
||||
\item GNU Taler can co-exist with physical cash, and might even
|
||||
help revive the use of cash if it succeeds in reducing credit
|
||||
card use online thereby eliminating a key reason for people to
|
||||
have credit cards.
|
||||
\end{itemize}
|
||||
|
||||
Unlike cryptocurrencies, Taler does not prescribe a solution for monetary
|
||||
policy or just taxation, as we believe these issues need to be subject to
|
||||
continuous political debate and cannot be ``solved'' by simplistic algorithms.
|
||||
What we offer to society is an open and free (as in free speech) system with
|
||||
mechanisms to audit merchants' income, instead of proprietary systems
|
||||
controlled by a few oligopoly companies.
|
||||
|
1813
doc/system/cryptocode.sty
Normal file
BIN
doc/system/diagrams/bitcoin-market-price.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
doc/system/diagrams/taler-diagram-denom-expiration.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
doc/system/diagrams/taler-diagram-exchange.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
doc/system/diagrams/taler-diagram-keyup.png
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
doc/system/diagrams/taler-diagram-merchant.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
doc/system/diagrams/taler-diagram-signatures.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
doc/system/diagrams/taler-diagram-wallet.png
Normal file
After Width: | Height: | Size: 38 KiB |
541
doc/system/introduction.tex
Normal file
@ -0,0 +1,541 @@
|
||||
\chapter{Introduction}\label{chapter:introduction}
|
||||
|
||||
New networking and cryptographic protocols can substantially improve
|
||||
electronic online payment systems. This book is about the design,
|
||||
implementation and security analysis of GNU
|
||||
Taler\footnote{\url{https://taler.net/}}, a privacy-friendly payment
|
||||
system that is designed to be practical for usage as an online
|
||||
(micro-)payment method, and at the same time socially and ethically
|
||||
responsible.
|
||||
|
||||
Payment systems can generally be divided into two types: Register-based
|
||||
and value-based~\cite{riksbank2017riksbank}. A register-based system
|
||||
associates value with identities (e.g., bank account balances with
|
||||
customers), while a value-based system associates value with typically
|
||||
anonymous, digital or physical tokens (such as cash or prepaid credit
|
||||
cards). In practice, these two types of systems are combined, as
|
||||
different layers have different (and often conflicting) requirements:
|
||||
the payment system used to pay for a cappuccino in a coffee shop is
|
||||
most likely not suitable to buy real estate. Value-based payment
|
||||
systems typically provide more anonymity and convenience but also more
|
||||
risk to consumers (as they are responsible to secure the values they
|
||||
hold), while register-based systems shift risks to the payment service
|
||||
provider who has to authenticate consumers and ensure the integrity of
|
||||
the register.
|
||||
|
||||
This book explains GNU Taler, a design and implementation of a value-based
|
||||
payment system, discussing in-depth how to create a practical,
|
||||
privacy-preserving and secure (micro-)payment protocol that integrates nicely
|
||||
with the modern web. Our value-based payment protocol can in principle
|
||||
operate on top of any existing register-based system.
|
||||
|
||||
GNU Taler is an official package of the GNU
|
||||
project\footnote{\url{https://gnu.org/}}. Our free software implementation is
|
||||
freely available from the GNU mirrors.
|
||||
|
||||
|
||||
\section{Design Goals for GNU Taler}
|
||||
|
||||
The design of payment systems shapes economies and societies
|
||||
\cite{zandi2013impact,dalebrant2016monetary}. Payment systems with high
|
||||
transaction costs create an economic burden. Predominantly cash-based
|
||||
societies provide some degree of anonymity for their citizens, but can fail to
|
||||
provide a sound foundation for taxation, facilitate corruption
|
||||
\cite{singh2017does} and thus risk creating weak governments. On the other
|
||||
hand, systems with too much surveillance eliminate personal freedom.
|
||||
|
||||
As the Internet has no standardized payment system, especially not one
|
||||
that is capable of quickly, efficiently and securely settling small
|
||||
transactions (so-called micropayments), the majority of content on the web is
|
||||
financed by advertisements. As a result, advertising (and by
|
||||
implication, collecting data on users) has been a dominant business
|
||||
model on the Internet. This has not only resulted in a loss of
|
||||
independence of publishers---who need to cater to the needs
|
||||
of advertisers---but also in a situation where micro-targeted ads
|
||||
are so wide-spread, that they have been suspected to have influenced
|
||||
multiple major elections~\cite{persily2017election}. Ads are also a
|
||||
vector for malware \cite{provos2007ghost}. Due to the prevalence of
|
||||
ad blockers, ads are also not guaranteed to be a sustainable business
|
||||
model.
|
||||
|
||||
In the world of online payments, credit cards and a sprawling number
|
||||
of smaller, proprietary payment processors are currently dominant, and
|
||||
market shares vary widely between different
|
||||
countries~\cite{adyen2016global,paypers2016ecommerce}. The resulting
|
||||
fragmentation again increases social costs: online shops can either
|
||||
choose to invest in implementing many proprietary protocols, or only
|
||||
implement the most popular ones, thereby reinforcing the dominance of
|
||||
a handful of proprietary payment systems.
|
||||
|
||||
Considering these and other social implications of payment systems, we
|
||||
started the development of GNU Taler with a set of high-level design
|
||||
goals that fit our social agenda. They are ranked by the importance
|
||||
we give to them, and when a trade-off must be made, the one that
|
||||
supports the more highly ranked goal is preferred:
|
||||
|
||||
% what about micropayments -> part of 'efficient'
|
||||
\begin{enumerate}
|
||||
\item \textbf{GNU Taler must be implemented as free software.}
|
||||
|
||||
Free refers to ``free as in free speech'', as opposed to ``free as in free beer''.
|
||||
More specifically, the four essential freedoms of free software
|
||||
\cite{stallman2002essays} must be respected, namely users must have the
|
||||
freedom to (1) run the software, (2) study and modify it, (3) redistribute
|
||||
copies, and (4) distribute copies of the modified version.
|
||||
|
||||
For merchants this prevents vendor lock-in, as another payment provider can
|
||||
take over, should the current one provide inadequate quality of service.
|
||||
As the software of
|
||||
the payment provider itself is free, smaller or disadvantaged countries or
|
||||
organizations can run the payment system without being controlled by a
|
||||
foreign company. Customers benefit from this freedom, as the wallet
|
||||
software can be made to run on a variety of platforms, and user-hostile
|
||||
features such as tracking or telemetry could easily be removed from
|
||||
wallet software.
|
||||
|
||||
This rules out the mandatory usage of specialized
|
||||
hardware such as smart cards or other hardware security modules, as the
|
||||
software they run cannot be modified by the user. These components can,
|
||||
however, be voluntarily used by merchants, customers or payment processors
|
||||
to increase their operational security.
|
||||
|
||||
\item \textbf{GNU Taler must protect the privacy of buyers.}\label{item:privacy}
|
||||
|
||||
Privacy should be guaranteed via technical measures, as opposed to mere
|
||||
policies. Especially with micropayments for online content, a
|
||||
disproportionate amount of rather private data about buyers would be revealed, if
|
||||
the payment system does not have privacy protections.
|
||||
|
||||
%Especially if a payment system is to be used for microtransactions for online
|
||||
%content, the privacy of buyers becomes important: if micropayments were more
|
||||
%commonplace, the transaction data could be used to collect extremely detailled
|
||||
%profiles of users. Unfortunately practically no commercially used payment
|
||||
%system has strong anonymity guarantees.
|
||||
|
||||
In legislations with data protection regulations (such as the recently introduced GDPR in Europe \cite{voigt2017eu}),
|
||||
merchants benefit from this as well, as no data breach of customers can happen if this information
|
||||
is, by design, not collected in the first place. Obviously some private data, such as the shipping
|
||||
address for a physical delivery, must still be collected according to business needs.
|
||||
|
||||
The security of the payment systems also benefits from this, as the model
|
||||
shifts from authentication of customers to mere authorization of payments.
|
||||
This approach rules out whole classes of attacks such as phishing \cite{garera2007framework} or credit
|
||||
card fraud \cite{sahin2010overview}.
|
||||
|
||||
\item \textbf{GNU Taler must enable the state to tax income and crack down on
|
||||
illegal business activities.}
|
||||
|
||||
% FIXME: provide broader ethical justification!
|
||||
As a payment system must still be legal to operate and use, it must comply
|
||||
with these requirements. Furthermore, we consider levying of taxes as
|
||||
beneficial to society.
|
||||
|
||||
\item \textbf{GNU Taler must prevent payment fraud.}
|
||||
|
||||
This imposes requirements on the security of the system, as well as on the
|
||||
general design, as payment fraud can also happen through misleading user
|
||||
interface design or the lack of cryptographic evidence for certain
|
||||
processes.
|
||||
|
||||
\item \textbf{GNU Taler must only disclose the minimal amount of information
|
||||
necessary.}
|
||||
|
||||
The reason behind this goal is similar to (\ref{item:privacy}). The
|
||||
privacy of buyers is given priority, but other parties such as merchants
|
||||
still benefit from it, for example, by keeping details about the merchant's financials
|
||||
hidden from competitors.
|
||||
|
||||
|
||||
\item \textbf{GNU Taler must be usable.}
|
||||
|
||||
Specifically it must be usable for non-expert customers. Usability also
|
||||
applies to the integration with merchants, and informs choices about the
|
||||
architecture, such as encapsulating procedures that require cryptographic
|
||||
operations into an isolated component with a simple API.
|
||||
|
||||
\item \textbf{GNU Taler must be efficient.}
|
||||
|
||||
% FIXME: provide broader ethical justification (environmental impact,
|
||||
% social cost, opportunity cost of lack of micropayments)
|
||||
Approaches such as proof-of-work are ruled out by this requirement. Efficiency is
|
||||
necessary for GNU Taler to be used for micropayments.
|
||||
|
||||
\item \textbf{GNU Taler must avoid single points of failure.}
|
||||
|
||||
While the design we present later is rather centralized, avoiding single
|
||||
points of failure is still a goal. This manifests in architectural choices such as
|
||||
the isolation of certain components, and auditing procedures.
|
||||
|
||||
\item \textbf{GNU Taler must foster competition.}
|
||||
|
||||
It must be relatively easy for competitors to join the systems. While the
|
||||
barriers for this in traditional financial systems are rather high, the
|
||||
technical burden for new competitors to join must be minimized. Another
|
||||
design choice that supports this is to split the whole system into smaller
|
||||
components that can be operated, developed and improved upon independently,
|
||||
instead of having one completely monolithic system.
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
|
||||
\section{Features of Value-based Payment Systems}\label{sec:intro:features}
|
||||
|
||||
There are many different possible features that have been proposed for
|
||||
value-based (sometimes called token-based) payment systems in the past. While we
|
||||
will discuss existing work on e-cash in more detail in
|
||||
Section~\ref{sec:related-work:e-cash}, we will begin by a brief
|
||||
summary of the possible features that value-based payment systems
|
||||
could provide, and clarify which high-level features we chose to adopt
|
||||
for GNU Taler.
|
||||
|
||||
% EXPLAIN: in traditional (online) e-cash, spending is never
|
||||
% bound to a contract identifier
|
||||
|
||||
%\subsubsection*{Different signature schemes and zero-knowledge proofs}
|
||||
%Since Chaum's original blind signature scheme based on RSA, many variations
|
||||
%using other cryptographic primitives have been developed. Some newer e-cash
|
||||
%schemes do not use blind signatures, but rely on zero-knowledge proofs instead.
|
||||
%
|
||||
%In GNU Taler, we opt for an RSA-based blind signature scheme, due to the low
|
||||
%complexity, relatively clear security assumptions and small number of
|
||||
%communication rounds compared to other protocols.
|
||||
|
||||
\subsection{Offline vs Online Payments}
|
||||
|
||||
Anonymous digital cash schemes since Chaum~\cite{chaum1983blind} were frequently designed to allow
|
||||
the merchant to be offline during the transaction, by providing a means to
|
||||
deanonymize customers involved in double-spending, typically by encoding the
|
||||
customer's identity into their coins in a way that makes it only possible to
|
||||
decode the identity with two spending transcripts.
|
||||
|
||||
This approach is problematic in practice, as customers that restore a wallet
|
||||
from backup might accidentally double-spend and would then face punishment for
|
||||
it. Enforcing punishment for double-spenders can be rather difficult as well,
|
||||
since the double-spender might have signed up with a false identity or might
|
||||
already have fled to another country, and a large number of merchants might already
|
||||
have been defrauded with the same coins.
|
||||
|
||||
Should the issuer of e-cash be compromised, an attacker could issue coins that
|
||||
fail to identify a culprit or even blame somebody else when they are
|
||||
double-spent. In an offline e-cash system, the detection of such an event is
|
||||
greatly delayed compared to systems with online spending, which can immediately
|
||||
detect when more coins are spent than were issued.
|
||||
|
||||
Thus, in GNU Taler, we decided that all coins must be immediately
|
||||
deposited online during a purchase. Only either a merchant or a customer
|
||||
needs to be online, since one of the two can forward messages to the
|
||||
payment service provider for the other.
|
||||
|
||||
\subsection{Change and Divisibility}
|
||||
|
||||
Customers do not always have the right set of coins available to exactly cover
|
||||
the amount to be paid to a merchant. With physical cash, the store would
|
||||
give the customer change. For e-cash, the situation is more complex, as
|
||||
the customer would have to make sure that the change has not already been
|
||||
spent, does not violate their anonymity and the merchant does not have a
|
||||
digital ``copy'' of the change tokens that the merchant can spend before the customer. Note
|
||||
that it would be unwise to always withdraw the correct amount of e-cash
|
||||
directly before a purchase, as it creates a temporal correlation between the
|
||||
non-anonymous withdrawal event and the spending event.
|
||||
|
||||
Most modern e-cash schemes instead deal with exact spending by providing
|
||||
\emph{divisibility} of coins, where the customer can decide to only spend part
|
||||
of a coin. A significant chunk of the e-cash literature has been concerned
|
||||
with developing schemes that allow the individual, divided parts of a coin to
|
||||
be unlinkable (thus preserving anonymity) and to optimize the storage costs for
|
||||
wallets and the communication cost of withdrawals.
|
||||
|
||||
The current state of the art for divisible e-cash~\cite{pointcheval2017cut}
|
||||
achieves constant-time withdrawal and wallet storage cost for coins that can be
|
||||
split into an arbitrary but fixed (as a system parameter) number of pieces. A
|
||||
continuous ``chunk'' of the smallest pieces of a coin can be spent with
|
||||
constant-time communication complexity.
|
||||
|
||||
While this sounds attractive in theory, these results are mostly of academic
|
||||
interest, as the storage and/or computational complexity for the party that is
|
||||
checking for double spending of coins remains enormous: each smallest piece of
|
||||
every coin needs to be recorded and checked individually. When paying
|
||||
$\$10.00$ with a coin that supports division into cent pieces, $1000$
|
||||
individual coin pieces must be checked for double spending and recorded,
|
||||
possibliy in compressed form to trade storage costs for more computation.
|
||||
|
||||
For GNU Taler, we use a rather simple and practical approach, made possible by
|
||||
requiring participants to be online during spending: coins can be fractionally
|
||||
spent without having divisible, unlinkable parts. The remaining value on a coin
|
||||
that was spend (and thus revealed) can be used to withdraw fresh, unlinkable
|
||||
coins. The protocol to obtain change takes additional measures to ensure that
|
||||
it cannot be misused to facilitate untaxed transactions. Giving change for
|
||||
e-cash has been proposed before \cite{brickell1995trustee,tracz2001fair}, but
|
||||
to the best of our knowledge, the idea of income-transparent change is novel.
|
||||
|
||||
\subsection{Anonymity Control}
|
||||
|
||||
Some proposed e-cash protocols contain mechanisms to allow selective
|
||||
deanonymization of transactions for scenarios involving crime
|
||||
\cite{sander1999escrow}, specifically blackmailing and tax evasion.
|
||||
|
||||
Unfortunately this does not really work as a countermeasure against
|
||||
blackmailing in practice. As noted in the paper that initially described such
|
||||
a mechanism for blind signatures \cite{stadler1995fair}, a blackmailer could
|
||||
simply request to be paid directly with plain, blindly signed coins, and
|
||||
thereby completely circumvent the threat of revocable anonymity.
|
||||
|
||||
GNU Taler provides \emph{income transparency} as a measure against tax evasion.
|
||||
We furthermore describe a different approach in a blackmailing scenario in
|
||||
Section~\ref{sec:design:blackmailing}, which we believe is more practical in
|
||||
dissuading blackmailers in practice.
|
||||
|
||||
\subsection{User Suspension}
|
||||
|
||||
Anonymous user suspension \cite{au2011electronic} has been proposed as
|
||||
another mechanism to punish users suspected in illicit activities by
|
||||
preventing then from making further transactions until the suspension is
|
||||
lifted. Anonymous suspension is based on transactions; the user
|
||||
involved in a particular transaction is suspended, but their identity is not
|
||||
revealed.
|
||||
|
||||
While the approach is interesting, it is not practical, as it requires
|
||||
a single permanent key pair to be associated with each user. If a
|
||||
user claims they lost their private key and requests a new key pair,
|
||||
their suspension would be effectively lifted. Suspending users from a
|
||||
dominant payment system is also socially problematic, as excluding
|
||||
them from most commercial activities would likely be a
|
||||
disproportionate and cruel punishment.
|
||||
|
||||
\subsection{Transferability}
|
||||
|
||||
Transferability is a feature of certain e-cash systems that allows
|
||||
transfer of e-cash between two parties without breaking anonymity
|
||||
properties \cite{fuchsbauer2009transferable}. Contemporary systems
|
||||
that offer this type of disintermediation attract criminal
|
||||
activity~\cite{richet2016extortion}.
|
||||
|
||||
GNU Taler specifically provides roughly the \emph{opposite} of this property,
|
||||
namely \emph{income transparency}, to guarantee that e-cash is not easily
|
||||
abused for tax evasion. Mutually trusting users, however, can share ownership
|
||||
of a coin.
|
||||
|
||||
\subsection{Atomic Swaps}
|
||||
|
||||
Atomic swaps (often called ``fair exchange'' in the e-cash literature) are a
|
||||
feature of some e-cash systems that allows e-cash
|
||||
to be exchanged against some service or (digital) product, with a trusted third
|
||||
party ensuring that the payee receives the payment if and only if they correctly
|
||||
provided the merchandise.
|
||||
|
||||
GNU Taler supports Camenisch-style atomic swaps~\cite{camenisch2007endorsed},
|
||||
as explained in Section~\ref{sec:security:atomic-swaps}.
|
||||
|
||||
\subsection{Refunds}
|
||||
|
||||
GNU Taler allows merchants to provide refunds to customers during a limited
|
||||
time after the coins for the payment were deposited. The merchant signs a
|
||||
statement that effectively allows the customer to reclaim a previously spent
|
||||
coin. Customers can request anonymous change for the reclaimed amount.
|
||||
|
||||
While this is a rather simple extension, we are not aware of any other e-cash
|
||||
system that supports refunds.
|
||||
|
||||
|
||||
\section{User Experience and Performance} \label{sec:intro:ux}
|
||||
|
||||
For adoption of a payment system, the user experience is critical. Thus,
|
||||
before diving into {\em how} GNU Taler is implemented, we begin by
|
||||
showing how GNU Taler {\em looks} from the perspective of an end user in the
|
||||
context of web payments, in a desktop browser (Chromium).
|
||||
|
||||
To use GNU Taler, the user must first install a browser extension
|
||||
(Figure~\ref{fig:ux:install-prompt}). Once installed, the user can
|
||||
open a pop-up window by clicking on the Taler logo, to see the
|
||||
initially empty wallet balance (Figure~\ref{fig:ux:installed}).
|
||||
|
||||
The customer logs into their online bank---a simple demo bank in our case--to
|
||||
withdraw digital cash from their bank account into their wallet (Figures~%
|
||||
\ref{fig:ux:bank-login} and~\ref{fig:ux:bank-profile}). Our demo uses
|
||||
\textsc{Kudos} as an imaginary currency. Before the user is asked to confirm,
|
||||
they are given the option to view details about or change the default exchange
|
||||
provider, the GNU Taler payment service provider (Figure~\ref{fig:ux:select-exchange}).
|
||||
|
||||
With a real bank, a second factor (such as a mobile TAN) would now be requested
|
||||
from the user. Our demo instead asks the user to solve a simple CAPTCHA
|
||||
(Figure~\ref{fig:ux:pin-tan}). The amount withdrawn---minus withdrawal
|
||||
fees---is now available as e-cash in the wallet (Figure~%
|
||||
\ref{fig:ux:withdraw-done}).
|
||||
|
||||
The customer can now go to an online shop to spend their digital cash. We've
|
||||
implemented a shop that sells single chapters from Richard Stallman's essay
|
||||
collection ``Free Software, Free Society'' \cite{stallman2002essays} (Figure~%
|
||||
\ref{fig:ux:essay-landing}). The user selects an essay, and is then
|
||||
immediately presented with a confirmation page rendered by the wallet (Figure~\ref{fig:ux:essay-pay}).
|
||||
After paying, the user can immediately read the article (Figure~\ref{fig:ux:essay-done}).
|
||||
|
||||
Our benchmarks, discussed in Chapter \ref{chapter:implementation} show that a
|
||||
single machine can support around 1000 payments per second, and our
|
||||
implementation is easily amenable to further scaling.
|
||||
|
||||
The extra computation required in the customer's wallet is in the order of a
|
||||
few hundred milliseconds even on typical mobile or tablet devices, and thus
|
||||
barely noticeable.
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{taler-screenshots/wallet-install-prompt.png}
|
||||
\caption{The user is prompted to install the wallet.}
|
||||
\label{fig:ux:install-prompt}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{taler-screenshots/wallet-installed.png}
|
||||
\caption{The wallet popup shows an empty balance.}
|
||||
\label{fig:ux:installed}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{taler-screenshots/bank-login.png}
|
||||
\caption{The bank asks for login details.}
|
||||
\label{fig:ux:bank-login}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{taler-screenshots/bank-profile.png}
|
||||
\caption{Account page of the demo bank.}
|
||||
\label{fig:ux:bank-profile}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{taler-screenshots/withdraw-confirm.png}
|
||||
\caption{Exchange selection dialog in the wallet.}
|
||||
\label{fig:ux:select-exchange}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{taler-screenshots/pin-tan.png}
|
||||
\caption{PIN/TAN dialog of the demo bank.}
|
||||
\label{fig:ux:pin-tan}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{taler-screenshots/withdraw-done.png}
|
||||
\caption{After a successful withdrawal, the balance is shown in the wallet.}
|
||||
\label{fig:ux:withdraw-done}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{taler-screenshots/essay-landing.png}
|
||||
\caption{Landing page of a store that sells essays.}
|
||||
\label{fig:ux:essay-landing}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{taler-screenshots/essay-pay.png}
|
||||
\caption[Payment prompt for an essay.]{Payment prompt for an essay. Rendered by the wallet.}
|
||||
\label{fig:ux:essay-pay}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{taler-screenshots/essay-done.png}
|
||||
\caption{Essay successfully purchased by the user.}
|
||||
\label{fig:ux:essay-done}
|
||||
\end{figure}
|
||||
|
||||
%\begin{figure}
|
||||
%\begin{subfigure}{.5\textwidth}
|
||||
% \centering
|
||||
% \includegraphics[width=.8\linewidth]{taler-screenshots/wallet-installed.png}
|
||||
% \caption{1a}
|
||||
% \label{fig:sfig1}
|
||||
%\end{subfigure}%
|
||||
%\begin{subfigure}{.5\textwidth}
|
||||
% \centering
|
||||
% \includegraphics[width=.8\linewidth]{taler-screenshots/bank-login.png}
|
||||
% \caption{1b}
|
||||
% \label{fig:sfig2}
|
||||
%\end{subfigure}
|
||||
%\caption{plots of....}
|
||||
%\label{fig:fig}
|
||||
%\end{figure}
|
||||
|
||||
% FIXME: perf results
|
||||
|
||||
\section{The Technical Foundation: Anonymous E-Cash} \label{sec:intro:ecash}
|
||||
GNU Taler is based on anonymous e-cash. Anonymous e-cash was invented by David
|
||||
Chaum in the 1980s \cite{chaum1983blind}. The idea behind Chaumian e-cash is
|
||||
both simple and ingenious, and can be best illustrated
|
||||
with the carbon paper\footnote{%
|
||||
Carbon paper is a paper coated with pigment (originally carbon) on one side.
|
||||
When put face-down between two sheets of normal paper, the pressure from
|
||||
writing with a pen or typewriter on the first layer causes pigment to be
|
||||
deposited on the paper beneath, allowing a copy to be made.
|
||||
} analogy: A long, random serial number is generated, for example, by throwing
|
||||
a die a few dozen times, and written on a piece of paper. A carbon paper is
|
||||
placed on top, with the pigmented side facing down, and both pieces of paper
|
||||
are put into an opaque envelope. The envelope is now sealed and brought to a
|
||||
bank. The bank draws a signature on the outside of the envelope, which presses
|
||||
through to the piece of paper with the serial number. In exchange for the
|
||||
signed envelope, the bank deducts a fixed amount (say five dollars) from the
|
||||
customer's bank account. Under the (admittedly rather strong) assumption that
|
||||
the bank's signature cannot be forged, the signed piece of paper with the serial
|
||||
number is now an untraceable bank note worth five dollars, as the bank signed
|
||||
it without seeing the serial number inside the envelope! Since the signed
|
||||
paper can be easily copied, merchants that accept it as payment must check the
|
||||
bank's signature, call the bank and transmit the serial number. The bank keeps
|
||||
a register of all serial numbers that have been used as payment before. If the
|
||||
serial number is already in the bank's register, the bank informs the merchant
|
||||
about the attempted double spending, and the merchant then rejects the payment.
|
||||
|
||||
The digital analogue of this process is called a \emph{blind signature}, where
|
||||
the signer knows that it gave a digital signature, but does not know the
|
||||
contents of the message that it signed.
|
||||
|
||||
In this document, we use \emph{coin} to refer to a token of value in an e-cash
|
||||
system. Note that the analogy of a coin does not always hold up, as certain
|
||||
types of operations possible in some e-cash schemes, such as partial spending,
|
||||
divisibility, etc., do not transfer to physical coins.
|
||||
|
||||
|
||||
%\subsection{Security Properties}\label{sec:intro:security}
|
||||
|
||||
We have the following security and correctness properties for GNU Taler
|
||||
(formally defined in Chapter~\ref{chapter:security}):
|
||||
\begin{itemize}
|
||||
\item \emph{Anonymity} guarantees that transactions cannot be correlated with withdrawals or
|
||||
other transactions made by the same customer.
|
||||
\item \emph{Unforgeability} guarantees that users cannot spend more e-cash than they withdrew.
|
||||
\item \emph{Conservation} guarantees that customers do not lose money due to
|
||||
interrupted protocols or malicious merchants; they can always obtain
|
||||
anonymous change or a proof of successful spending.
|
||||
\item \emph{Income transparency} guarantees that mutually distrusting parties
|
||||
are unable to reliably transfer e-cash between them without the income of
|
||||
participants being visible to tax auditors.
|
||||
\end{itemize}
|
||||
|
||||
While anonymity and unforgeability are common properties of e-cash, we are not
|
||||
aware of any other treatments of income transparency and conservation.
|
||||
|
||||
|
||||
\section{Roadmap}
|
||||
|
||||
Chapter \ref{chapter:design} describes the high-level design of GNU Taler, and
|
||||
compares it to payment systems found in the academic literature and real-world
|
||||
usage. Chapter \ref{chapter:security} first gives a gentle introduction to
|
||||
provable security (which can be skipped by readers with a background in
|
||||
cryptography), and then defines security properties for income-transparent,
|
||||
anonymous e-cash. The cryptographic protocols for GNU Taler are defined in
|
||||
detail, and proofs are given that our protocols satisfy the security
|
||||
properties defined earlier. In Chapter \ref{chapter:implementation}, the
|
||||
implementation of GNU Taler is described, and the performance and scalability
|
||||
is evaluated. Chapter \ref{chapter:future-work} discusses future work and
|
||||
missing pieces to deploy GNU Taler in production. Chapter
|
||||
\ref{chapter:conclusion} concludes with an outlook on the potential impact and
|
||||
practical relevance of this work.
|
||||
|
12
doc/system/plots/dbsize.sql
Normal file
@ -0,0 +1,12 @@
|
||||
create temporary view sizes as
|
||||
select table_name as n,
|
||||
pg_relation_size(quote_ident(table_name)) / 1024.0 / 1024.0 as s_tbl,
|
||||
pg_indexes_size(quote_ident(table_name)) / 1024.0 / 1024.0 as s_idx
|
||||
from information_schema.tables
|
||||
where table_schema = 'public';
|
||||
|
||||
|
||||
select n, s_tbl, s_idx, s_tbl + s_idx from sizes where (s_tbl) != 0
|
||||
order by (s_tbl + s_idx);
|
||||
|
||||
select sum(s_tbl), sum(s_idx), sum(s_tbl + s_idx) from sizes where s_tbl != 0;
|
20
doc/system/plots/eval-basic.bash
Normal file
@ -0,0 +1,20 @@
|
||||
#/usr/bin/env bash
|
||||
|
||||
for x in 1 $(seq 10 10 190) $(seq 200 100 2000); do
|
||||
cat results/stats-$x/stats/taler-exchange-* | awk -v n=$x '{ print n, int(($3 + $5) / 96) }'
|
||||
done | sort -n > plots/time_exchange_cpu.data
|
||||
|
||||
tail results/stats-*/benchmark.log | awk '/RAW/ { printf "%d %d\n", $4, $5 }' | sort -n > plots/time_real.data
|
||||
|
||||
tail results/stats-*/benchmark.log | awk '/RAW/ { printf "%d %f\n", $4, (($4 * 1000)/($5/1000/1000)) }' | sort -n > plots/speed.data
|
||||
|
||||
for x in 1 $(seq 10 10 190) $(seq 200 100 2000); do
|
||||
tail results/stats-$x/benchmark.log | awk -v n=$x '/cpu time/ { print n, int(($4 + $6) / 96) }'
|
||||
done | sort -n > plots/time_bench_cpu.data
|
||||
|
||||
|
||||
for x in 1 $(seq 10 10 190) $(seq 200 100 2000); do
|
||||
awk -f ~/code/gnunet/contrib/benchmark/collect.awk baseline.txt results/stats-$x/stats/gnunet-benchmark-ops-thread* \
|
||||
| grep total_ops_adjusted_ms \
|
||||
| awk -v n=$x '{ print n, int($2 / 96) }'
|
||||
done | sort -n > plots/time_bench_ops_only.data
|
35
doc/system/plots/eval-latency.bash
Normal file
@ -0,0 +1,35 @@
|
||||
#/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
mkdir -p plots
|
||||
|
||||
do_eval() {
|
||||
e=$1
|
||||
out=$2
|
||||
for x in 0 50 100 150 200; do
|
||||
awk -f ~/repos/gnunet/contrib/benchmark/collect.awk results/latency-$x/stats/gnunet-benchmark-urls-*.txt \
|
||||
| fgrep "$1" | fgrep "status 200" | awk -v x=$x '{ print x, $10/1000 }'
|
||||
done | sort -n > plots/latency-$out.data
|
||||
}
|
||||
|
||||
|
||||
awk -f ~/repos/gnunet/contrib/benchmark/collect.awk results/latency-0/stats/gnunet-benchmark-urls-*.txt \
|
||||
| fgrep "status 200" | awk '{ print $2, $10/1000 }' > plots/latency-summary-0.data
|
||||
|
||||
awk -f ~/repos/gnunet/contrib/benchmark/collect.awk results/latency-100/stats/gnunet-benchmark-urls-*.txt \
|
||||
| fgrep "status 200" | awk '{ print $2, $10/1000 }' > plots/latency-summary-100.data
|
||||
|
||||
do_eval '/refresh/melt' 'refresh-melt'
|
||||
do_eval '/refresh/reveal' 'refresh-reveal'
|
||||
do_eval '/deposit' 'deposit'
|
||||
do_eval '/reserve/withdraw' 'withdraw'
|
||||
do_eval '/keys' 'keys'
|
||||
|
||||
awk -f ~/repos/gnunet/contrib/benchmark/collect.awk results/latency-*/stats/gnunet-benchmark-urls-*.txt \
|
||||
| fgrep "status 200" | awk '{ print $2, $16/1000 }' \
|
||||
> plots/req-sent.data
|
||||
|
||||
awk -f ~/repos/gnunet/contrib/benchmark/collect.awk results/latency-*/stats/gnunet-benchmark-urls-*.txt \
|
||||
| fgrep "status 200" | awk '{ print $2, $18/1000 }' \
|
||||
> plots/req-received.data
|
5
doc/system/plots/latency-deposit.data
Normal file
@ -0,0 +1,5 @@
|
||||
0 22.3593
|
||||
50 122.833
|
||||
100 223.217
|
||||
150 323.787
|
||||
200 424.537
|
5
doc/system/plots/latency-keys.data
Normal file
@ -0,0 +1,5 @@
|
||||
0 1.139
|
||||
50 101.446
|
||||
100 201.251
|
||||
150 301.335
|
||||
200 401.399
|
5
doc/system/plots/latency-refresh-melt.data
Normal file
@ -0,0 +1,5 @@
|
||||
0 20.7065
|
||||
50 121.796
|
||||
100 223.9
|
||||
150 323.459
|
||||
200 422.474
|
5
doc/system/plots/latency-refresh-reveal.data
Normal file
@ -0,0 +1,5 @@
|
||||
0 63.6377
|
||||
50 264.969
|
||||
100 466.303
|
||||
150 665.626
|
||||
200 862.193
|
5
doc/system/plots/latency-withdraw.data
Normal file
@ -0,0 +1,5 @@
|
||||
0 22.675
|
||||
50 123.066
|
||||
100 222.458
|
||||
150 322.701
|
||||
200 423.749
|
35
doc/system/plots/plot.gnu
Normal file
@ -0,0 +1,35 @@
|
||||
set terminal pdf monochrome
|
||||
|
||||
set nokey
|
||||
set output 'speed.pdf'
|
||||
set ylabel "coins per second"
|
||||
set xlabel "parallel clients"
|
||||
plot "speed.data" with lines lw 1
|
||||
|
||||
set key top left Left reverse
|
||||
set output 'cpu.pdf'
|
||||
set ylabel "CPU time (us)"
|
||||
set xlabel "parallel clients"
|
||||
plot "time_real.data" with lines lw 1 title "wall clock", \
|
||||
"time_bench_cpu.data" with lines lw 1 title "benchmark CPU / 96", \
|
||||
"time_exchange_cpu.data" with lines lw 1 title "exchange CPU / 96", \
|
||||
"time_bench_ops_only.data" with lines lw 1 title "exchange crypto / 96"
|
||||
set nokey
|
||||
|
||||
|
||||
set output 'latencies.pdf'
|
||||
set multiplot layout 2, 3
|
||||
set xlabel "delay" font ",10"
|
||||
set ylabel "latency" font ",10"
|
||||
set xtics font ",10"
|
||||
set ytics font ",10"
|
||||
set title "/refresh/melt"
|
||||
plot "latency-refresh-melt.data" with lines lw 1
|
||||
set title "/refresh/reveal"
|
||||
plot "latency-refresh-reveal.data" with lines lw 1
|
||||
set title "/keys"
|
||||
plot "latency-keys.data" with lines lw 1
|
||||
set title "/reserve/withdraw"
|
||||
plot "latency-withdraw.data" with lines lw 1
|
||||
set title "/deposit"
|
||||
plot "latency-deposit.data" with lines lw 1
|
44
doc/system/plots/run-latency.bash
Normal file
@ -0,0 +1,44 @@
|
||||
#/usr/bin/env bash
|
||||
|
||||
# This is intended to be run with SSH agent forwarding,
|
||||
# so we can log in as root to adjust artificial delay.
|
||||
|
||||
set -eu
|
||||
|
||||
which taler-exchange-benchmark
|
||||
|
||||
# check that we can log in at least!
|
||||
ssh root@gv.taler.net true
|
||||
ssh root@firefly.gnunet.org true
|
||||
|
||||
ssh root@gv.taler.net tc qdisc delete dev enp4s0f0 root || true
|
||||
ssh root@firefly.gnunet.org tc qdisc delete dev eno2 root || true
|
||||
|
||||
ssh root@gv.taler.net "echo 3 > /proc/sys/net/ipv4/tcp_fastopen"
|
||||
ssh root@firefly.gnunet.org "echo 3 > /proc/sys/net/ipv4/tcp_fastopen"
|
||||
|
||||
# warm up TCP fast open cookies
|
||||
taler-exchange-benchmark -c benchmark-remote-gv.conf -m client -p 1 -n 5 >> benchmark-latency.log 2>&1
|
||||
|
||||
export GNUNET_BENCHMARK_DIR=$(readlink -f ./stats)
|
||||
|
||||
for x in 0 50 100 150 200; do
|
||||
echo running with one-sided delay of $x
|
||||
result_dir="results/latency-$x"
|
||||
if [[ -d "$result_dir" ]]; then
|
||||
echo "skipping because results exist"
|
||||
continue
|
||||
fi
|
||||
|
||||
ssh root@gv.taler.net tc qdisc add dev enp4s0f0 root netem delay "${x}ms"
|
||||
ssh root@firefly.gnunet.org tc qdisc add dev eno2 root netem delay "${x}ms"
|
||||
|
||||
rm -rf stats
|
||||
taler-exchange-benchmark -c benchmark-remote-gv.conf -m client -p 1 -n 200 >> benchmark-latency.log 2>&1
|
||||
echo "### Finished latency run for ${x}ms" >> benchmark-latency.log
|
||||
mkdir -p "$result_dir"
|
||||
cp -a stats "$result_dir/"
|
||||
|
||||
ssh root@gv.taler.net tc qdisc delete dev enp4s0f0 root
|
||||
ssh root@firefly.gnunet.org tc qdisc delete dev eno2 root
|
||||
done
|
10
doc/system/plots/run.bash
Normal file
@ -0,0 +1,10 @@
|
||||
#/usr/bin/env bash
|
||||
|
||||
for x in $(seq 10 10 190) $(seq 200 100 2000); do
|
||||
echo running with $x clients
|
||||
rm -rf stats
|
||||
taler-exchange-benchmark -c benchmark-local.conf -p $x -n 1000 >& /dev/shm/benchmark.log
|
||||
mkdir -p "results/stats-$x"
|
||||
cp -a stats "results/stats-$x"/
|
||||
cp /dev/shm/benchmark.log "results/stats-$x/"
|
||||
done
|
19
doc/system/plots/set-latency.bash
Normal file
@ -0,0 +1,19 @@
|
||||
#/usr/bin/env bash
|
||||
|
||||
# This is intended to be run with SSH agent forwarding,
|
||||
# so we can log in as root to adjust artificial delay.
|
||||
|
||||
set -eu
|
||||
|
||||
echo "setting latency to $1"
|
||||
|
||||
# check that we can log in at least!
|
||||
ssh root@gv.taler.net true
|
||||
ssh root@firefly.gnunet.org true
|
||||
|
||||
ssh root@gv.taler.net tc qdisc delete dev enp4s0f0 root || true
|
||||
ssh root@firefly.gnunet.org tc qdisc delete dev eno2 root || true
|
||||
|
||||
ssh root@gv.taler.net tc qdisc add dev enp4s0f0 root netem delay "${1}ms"
|
||||
ssh root@firefly.gnunet.org tc qdisc add dev eno2 root netem delay "${1}ms"
|
||||
|
37
doc/system/plots/speed.data
Normal file
@ -0,0 +1,37 @@
|
||||
1 1.104439
|
||||
10 92.290911
|
||||
20 180.087087
|
||||
30 255.700284
|
||||
40 344.687076
|
||||
50 438.485028
|
||||
60 515.618333
|
||||
70 568.431831
|
||||
80 639.706303
|
||||
100 673.724088
|
||||
110 676.973144
|
||||
120 671.559308
|
||||
130 694.295694
|
||||
140 664.765652
|
||||
150 638.751296
|
||||
160 673.683504
|
||||
170 674.329287
|
||||
180 669.691392
|
||||
190 638.637718
|
||||
200 699.212198
|
||||
300 675.841986
|
||||
400 656.455187
|
||||
500 714.911636
|
||||
600 738.661570
|
||||
700 699.990279
|
||||
800 708.218566
|
||||
1000 735.599016
|
||||
1100 700.423479
|
||||
1200 687.508367
|
||||
1300 696.931102
|
||||
1400 698.255900
|
||||
1500 696.575458
|
||||
1600 737.278906
|
||||
1700 718.587847
|
||||
1800 691.539112
|
||||
1900 736.039940
|
||||
2000 742.994853
|
39
doc/system/plots/time_bench_cpu.data
Normal file
@ -0,0 +1,39 @@
|
||||
1 9801666
|
||||
10 11386875
|
||||
20 23130250
|
||||
30 36564875
|
||||
40 47727458
|
||||
50 58359958
|
||||
60 70447500
|
||||
70 84446916
|
||||
80 93801750
|
||||
90 106124375
|
||||
100 119029750
|
||||
110 129536541
|
||||
120 147174791
|
||||
130 154257625
|
||||
140 174573916
|
||||
150 192325541
|
||||
160 194480625
|
||||
170 206233000
|
||||
180 214591541
|
||||
190 239929750
|
||||
200 236358375
|
||||
300 348233916
|
||||
400 495046791
|
||||
500 579896000
|
||||
600 689094875
|
||||
700 830684375
|
||||
800 957190833
|
||||
900 1058149291
|
||||
1000 1154518791
|
||||
1100 1325087916
|
||||
1200 1502792333
|
||||
1300 1610584958
|
||||
1400 1712165458
|
||||
1500 1838840458
|
||||
1600 1881089500
|
||||
1700 2023251583
|
||||
1800 2209685583
|
||||
1900 2241094458
|
||||
2000 2351564083
|
39
doc/system/plots/time_bench_ops_only.data
Normal file
@ -0,0 +1,39 @@
|
||||
1 2509331
|
||||
10 2564859
|
||||
20 5002341
|
||||
30 7865777
|
||||
40 10073982
|
||||
50 12128759
|
||||
60 14693754
|
||||
70 17792025
|
||||
80 19538636
|
||||
90 21980148
|
||||
100 24423023
|
||||
110 26545671
|
||||
120 30144030
|
||||
130 31522690
|
||||
140 35732386
|
||||
150 39585595
|
||||
160 39812006
|
||||
170 42203541
|
||||
180 44053474
|
||||
190 49793400
|
||||
200 48356499
|
||||
300 74601183
|
||||
400 105393510
|
||||
500 123044026
|
||||
600 145506335
|
||||
700 176345850
|
||||
800 200698466
|
||||
900 221478860
|
||||
1000 239238872
|
||||
1100 276518348
|
||||
1200 321194002
|
||||
1300 340475242
|
||||
1400 360182556
|
||||
1500 387822458
|
||||
1600 393044377
|
||||
1700 428264745
|
||||
1800 469067124
|
||||
1900 469026116
|
||||
2000 486510753
|
39
doc/system/plots/time_exchange_cpu.data
Normal file
@ -0,0 +1,39 @@
|
||||
1 4769125
|
||||
10 4958166
|
||||
20 9639333
|
||||
30 14984541
|
||||
40 19394166
|
||||
50 23851208
|
||||
60 28914708
|
||||
70 34698375
|
||||
80 38456250
|
||||
90 43448500
|
||||
100 48580291
|
||||
110 52942000
|
||||
120 59859458
|
||||
130 62778708
|
||||
140 70788500
|
||||
150 78093250
|
||||
160 78634750
|
||||
170 83169416
|
||||
180 86460000
|
||||
190 96958916
|
||||
200 94814958
|
||||
300 138324083
|
||||
400 194283541
|
||||
500 227209291
|
||||
600 267426291
|
||||
700 322986833
|
||||
800 368918208
|
||||
900 406839708
|
||||
1000 440552708
|
||||
1100 518428416
|
||||
1200 591421708
|
||||
1300 631228208
|
||||
1400 663142625
|
||||
1500 713897625
|
||||
1600 726439583
|
||||
1700 783727750
|
||||
1800 858787125
|
||||
1900 863532291
|
||||
2000 895376500
|
40
doc/system/plots/time_real.data
Normal file
@ -0,0 +1,40 @@
|
||||
0 0
|
||||
1 905437353
|
||||
10 108353032
|
||||
20 111057380
|
||||
30 117324860
|
||||
40 116047287
|
||||
50 114028979
|
||||
60 116365141
|
||||
70 123145813
|
||||
80 125057389
|
||||
90 136314756
|
||||
100 148428714
|
||||
110 162487982
|
||||
120 178688611
|
||||
130 187240107
|
||||
140 210600532
|
||||
150 234833183
|
||||
160 237500249
|
||||
170 252102353
|
||||
180 268780519
|
||||
190 297508266
|
||||
200 286036200
|
||||
300 443890741
|
||||
400 609333292
|
||||
500 699387134
|
||||
600 812279973
|
||||
700 1000013888
|
||||
800 1129594787
|
||||
900 1251266347
|
||||
1000 1359436294
|
||||
1100 1570478479
|
||||
1200 1745433303
|
||||
1300 1865320684
|
||||
1400 2004995589
|
||||
1500 2153391973
|
||||
1600 2170142109
|
||||
1700 2365751116
|
||||
1800 2602889653
|
||||
1900 2581381658
|
||||
2000 2691808686
|
2825
doc/system/ref.bib
Normal file
42
doc/system/snippets/donations.py
Normal file
@ -0,0 +1,42 @@
|
||||
@app.route("/donate")
|
||||
def donate():
|
||||
donation_amount = expect_parameter("donation_amount")
|
||||
donation_donor = expect_parameter("donation_donor")
|
||||
fulfillment_url = flask.url_for("fulfillment", _external=True)
|
||||
order = dict(
|
||||
amount=donation_amount,
|
||||
extra=dict(donor=donation_donor, amount=donation_amount),
|
||||
fulfillment_url=fulfillment_url,
|
||||
summary="Donation to the GNU Taler project",
|
||||
)
|
||||
# ask backend to create new order
|
||||
order_resp = backend_post("order", dict(order=order))
|
||||
order_id = order_resp["order_id"]
|
||||
return flask.redirect(flask.url_for("fulfillment", order_id=order_id))
|
||||
|
||||
|
||||
@app.route("/receipt")
|
||||
def fulfillment():
|
||||
order_id = expect_parameter("order_id")
|
||||
pay_params = dict(order_id=order_id)
|
||||
|
||||
# ask backend for status of payment
|
||||
pay_status = backend_get("check-payment", pay_params)
|
||||
|
||||
if pay_status.get("payment_redirect_url"):
|
||||
return flask.redirect(pay_status["payment_redirect_url"])
|
||||
|
||||
if pay_status.get("paid"):
|
||||
# The "extra" field in the contract terms can be used
|
||||
# by the merchant for free-form data, interpreted
|
||||
# by the merchant (avoids additional database access)
|
||||
extra = pay_status["contract_terms"]["extra"]
|
||||
return flask.render_template(
|
||||
"templates/fulfillment.html",
|
||||
donation_amount=extra["amount"],
|
||||
donation_donor=extra["donor"],
|
||||
order_id=order_id,
|
||||
currency=CURRENCY)
|
||||
|
||||
# no pay_redirect but article not paid, this should never happen!
|
||||
err_abort(500, message="Internal error, invariant failed", json=pay_status)
|
98
doc/system/system.tex
Normal file
@ -0,0 +1,98 @@
|
||||
\documentclass[10pt]{book}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage{titlesec}
|
||||
\usepackage{xspace}
|
||||
\usepackage{microtype}
|
||||
\usepackage{amssymb,amsmath,amsthm}
|
||||
\newtheorem{theorem}{Theorem}
|
||||
\newtheorem{lemma}{Lemma}
|
||||
\usepackage{url}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{caption}
|
||||
\usepackage{subcaption}
|
||||
\usepackage{enumitem}
|
||||
\usepackage{hyperref}
|
||||
% bold math
|
||||
\usepackage{bm}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{adjustbox}
|
||||
\usepackage{array}
|
||||
\usepackage{verbatim}
|
||||
\usepackage{listings}
|
||||
\usepackage{multicol}
|
||||
|
||||
|
||||
% stuff like \ding for symbols
|
||||
\usepackage{pifont}
|
||||
|
||||
\usepackage[
|
||||
natbib=true,
|
||||
style=alphabetic,
|
||||
backref=true,
|
||||
doi=false,
|
||||
isbn=false,
|
||||
maxbibnames=99,
|
||||
]{biblatex}
|
||||
\addbibresource{ref.bib}
|
||||
|
||||
\usepackage{epsfig}
|
||||
\usepackage{textpos}
|
||||
\usepackage{ifthen}
|
||||
\usepackage{makeidx}
|
||||
\usepackage{float}
|
||||
\usepackage{calc}
|
||||
\usepackage{vmargin}
|
||||
\usepackage{letterspace}
|
||||
\usepackage[pass]{geometry}
|
||||
|
||||
\usepackage{eurosym}
|
||||
\usepackage{bytefield}
|
||||
\usepackage[binary-units,detect-weight=true,detect-family=true]{siunitx}
|
||||
\usepackage[usenames,dvipsnames,svgnames,table]{xcolor}
|
||||
\usepackage{qrcode}
|
||||
\usepackage{cryptocode}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{shapes,arrows}
|
||||
\usetikzlibrary{positioning}
|
||||
\usetikzlibrary{calc}
|
||||
\usepackage{mdframed}
|
||||
% Typography
|
||||
\usepackage[sc,osf]{mathpazo}
|
||||
\linespread{1.05}
|
||||
\usepackage[scaled]{helvet} % ss
|
||||
\usepackage{courier} % tt
|
||||
\normalfont
|
||||
\usepackage[T1]{fontenc}
|
||||
|
||||
\usepackage{pdfpages}
|
||||
|
||||
\author{Florian Dold \and the GNU Taler Developers}
|
||||
\title{The GNU Taler System}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\newcommand{\astfootnote}[1]{
|
||||
\let\oldthefootnote=\thefootnote%
|
||||
\setcounter{footnote}{0}%
|
||||
\renewcommand{\thefootnote}{\fnsymbol{footnote}}%
|
||||
\footnote{#1}%
|
||||
\let\thefootnote=\oldthefootnote%
|
||||
}
|
||||
|
||||
\frontmatter
|
||||
\include{abstract}
|
||||
\include{acknowledgements}
|
||||
\tableofcontents
|
||||
\listoffigures
|
||||
\mainmatter
|
||||
|
||||
|
||||
\include{introduction}
|
||||
\include{taler/design}
|
||||
\include{taler/security}
|
||||
\include{taler/implementation}
|
||||
\include{conclusions}
|
||||
|
||||
\printbibliography[heading=bibintoc]
|
||||
|
||||
\end{document}
|
BIN
doc/system/taler-screenshots/bank-login.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
doc/system/taler-screenshots/bank-profile.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
doc/system/taler-screenshots/essay-done.png
Normal file
After Width: | Height: | Size: 135 KiB |
BIN
doc/system/taler-screenshots/essay-landing.png
Normal file
After Width: | Height: | Size: 163 KiB |
BIN
doc/system/taler-screenshots/essay-pay.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
doc/system/taler-screenshots/pin-tan.png
Normal file
After Width: | Height: | Size: 91 KiB |
BIN
doc/system/taler-screenshots/wallet-install-prompt.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
doc/system/taler-screenshots/wallet-installed.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
doc/system/taler-screenshots/withdraw-confirm.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
doc/system/taler-screenshots/withdraw-done.png
Normal file
After Width: | Height: | Size: 84 KiB |
1
doc/system/taler/blockchain-accountability.tex
Normal file
@ -0,0 +1 @@
|
||||
\chapter{Exchange-accountable e-cash}
|
1286
doc/system/taler/design.tex
Normal file
2198
doc/system/taler/implementation.tex
Normal file
1729
doc/system/taler/security.tex
Normal file
62
doc/system/taler/snippet-keys.txt
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"version": "2:0:0",
|
||||
"master_public_key": "CQQZ...",
|
||||
"reserve_closing_delay": "/Delay(2419200)/",
|
||||
"signkeys": [
|
||||
{
|
||||
"stamp_start": "/Date(1522223035)/",
|
||||
"stamp_expire": "/Date(1533109435)/",
|
||||
"stamp_end": "/Date(1585295035)/",
|
||||
"master_sig": "842D...",
|
||||
"key": "05XW..."
|
||||
}
|
||||
],
|
||||
"payback": [],
|
||||
"denoms": [
|
||||
{
|
||||
"master_sig": "BHG5...",
|
||||
"stamp_start": "/Date(1500450235)/",
|
||||
"stamp_expire_withdraw": "/Date(1595058235)/",
|
||||
"stamp_expire_deposit": "/Date(1658130235)/",
|
||||
"stamp_expire_legal": "/Date(1815810235)/",
|
||||
"denom_pub": "51RD...",
|
||||
"value": "TESTKUDOS:10",
|
||||
"fee_withdraw": "TESTKUDOS:0.01",
|
||||
"fee_deposit": "TESTKUDOS:0.01",
|
||||
"fee_refresh": "TESTKUDOS:0.01",
|
||||
"fee_refund": "TESTKUDOS:0.01"
|
||||
},
|
||||
{
|
||||
"master_sig": "QT0T...",
|
||||
"stamp_start": "/Date(1500450235)/",
|
||||
"stamp_expire_withdraw": "/Date(1595058235)/",
|
||||
"stamp_expire_deposit": "/Date(1658130235)/",
|
||||
"stamp_expire_legal": "/Date(1815810235)/",
|
||||
"denom_pub": "51R7",
|
||||
"value": "TESTKUDOS:0.1",
|
||||
"fee_withdraw": "TESTKUDOS:0.01",
|
||||
"fee_deposit": "TESTKUDOS:0.01",
|
||||
"fee_refresh": "TESTKUDOS:0.01",
|
||||
"fee_refund": "TESTKUDOS:0.01"
|
||||
},
|
||||
],
|
||||
"auditors": [
|
||||
{
|
||||
"denomination_keys": [
|
||||
{
|
||||
"denom_pub_h": "RNTQ...",
|
||||
"auditor_sig": "6SC2..."
|
||||
},
|
||||
{
|
||||
"denom_pub_h": "CP6B...",
|
||||
"auditor_sig": "0GSE..."
|
||||
}
|
||||
],
|
||||
"auditor_url": "https://auditor.test.taler.net/",
|
||||
"auditor_pub": "BW9DC..."
|
||||
}
|
||||
],
|
||||
"list_issue_date": "/Date(1530196508)/",
|
||||
"eddsa_pub": "05XW...",
|
||||
"eddsa_sig": "RXCD..."
|
||||
}
|