This commit is contained in:
Özgür Kesim 2022-10-29 20:12:16 +02:00
parent e72709a93c
commit bae905a842
18 changed files with 578 additions and 1 deletions

View File

@ -16,7 +16,7 @@
\usepackage{graphicx} \usepackage{graphicx}
\usepackage{listings} \usepackage{listings}
\usepackage{fontspec} \usepackage{fontspec}
\setmonofont[Path = fonts/, \setmonofont[Path = ../fonts/,
Extension = .ttf, Extension = .ttf,
UprightFont = *-Regular, UprightFont = *-Regular,
ItalicFont = *-Italic, ItalicFont = *-Italic,

View File

@ -0,0 +1,57 @@
Hi Stefan,
Vielen Dank!
Kannst du dazu ein paar Saetze fuer Oec's NGI POINTER Bericht auf
Englisch schreiben? Ich denke wichtig fuer POINTER sind:
- wir sind in Kontakt mit dieser Kommission
- die Sitzung ist erst am 7.12.2022, daher kann es vorher nichts
offizielles geben
- wir bereiten eine Eingabe vor
In Bezug auf den Vorgang selber denke ich, dass wir in unserer Eingabe
nicht nur das ESORICS-Paper haben sollten, sondern auch eine genauere
Darstellung was passieren soll mit Konten die Jugendlichen gehoeren (=>
wenn wir das per EBICS rausbekommen) und den Plan, unser KYC zur
Altersverifikation bei P2P Zahlungen zu nutzen und so jugendlichen
Empfaengern auch eine Altersrestriktion aufzuzwingen.
Hast du die Eingabe schon gemacht, oder "nur" einen Text vorbereitet?
Den sollten ich und Oec sicherlich deutlich vor dem 7.12. nochmal
gegenlesen / ueberarbeiten...
My 2 cents
Christian
On 10/19/22 20:57, Stefan Kügel wrote:
> Hallo Christian,
>
> die Kommission für Jugendmedienschutz hat mir in Aussicht gestellt, GNU
> Taler als übergreifendes Jugendschutzkonzept zu bewerten und mit
> einerPositivbewertung als empfehlenswert auf seine Webseite
> https://www.kjm-online.de/aufsicht/technischer-jugendmedienschutz/uebergreifende-konzepte zu setzen. Dies würde auch eine Listung imDokument https://www.kjm-online.de/fileadmin/user_upload/KJM/Aufsicht/Technischer_Jugendmedienschutz/Uebergreifende_Jugendschutzkonzepte.pdf bedeuten, das den Inhalt der oben genannten Webseite auf 4 Seiten wiederholt.
>
> Die KJM ist die zentrale Aufsichtsstelle für den Jugendschutz im
> privaten Rundfunk und den Telemedien. Sie hat eine gemeinsame
> Geschäftsstelle der Landesmedienanstalten in Berlin. Ihr Plenum trifft
> sich am 7.12.2022 in Berlin zu einer Sitzung, vor der wir eine
> Systembeschreibung und das NGI-Paper zu Taler-Token mit
> Altersbeschränkungen eingeben. Koordiniert wird dies durch meinen
> Gesprächspartner Henning Mellage, Referent Recht & Aufsicht, der in der
> Landesanstalt für Medien NRW in Düsseldorf arbeitet.
>
> Mir war es im Gespräch mit ihm wichtig zu betonen, dass GNU Taler ein
> sog. "übergreifendes Jugendschutzkonzept" ist und nicht etwa einer
> geschlossenen Benutzergruppe dient (Geschlossene Benutzergruppe heißt:
> Zugang zu Inhalten oder Gütern nur mit Altersverifikation durch
> Ausweisvorlage).
>
> Die Positivbewertung ist kostenfrei, da sonst die KJM den Vorwurf der
> Befangenheit durch Geldannahme gegen sich gelten hätte, und das dürfe
> eine Behörde nicht zulassen, meinte Herr Mellage.
>
> Falls noch Fragen zu dem Vorgang bestehen, stehe ich gern zur Auskunft.
>
> Herzliche Grüße
> Stefan

332
m4/ngi-ap3-m4-report.tex Normal file
View File

@ -0,0 +1,332 @@
\documentclass{scrartcl}
\usepackage[a4paper]{geometry}
\usepackage{hyperref}
\usepackage[dvipsnames]{xcolor}
\hypersetup{
colorlinks = true,
allcolors = {black},
linkcolor = DarkOrchid,
urlcolor = DarkOrchid,
}
\usepackage{url}
\usepackage[font=footnotesize]{caption}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{pdfpages}
\usepackage{graphicx}
\usepackage{listings}
\usepackage{fontspec}
\setmonofont[Path = ../fonts/,
Extension = .ttf,
UprightFont = *-Regular,
ItalicFont = *-Italic,
BoldFont = *-Bold,
Scale=0.85]{RobotoMono}
\lstdefinelanguage{typescript}{
keywords={typeof, new, true, false, catch, function, return, null, catch, switch, var, if, in, while, do, else, case, break, interface},
keywordstyle=\bfseries,
ndkeywords={class, export, boolean, number, Amount, string, Timestamp, RelativeTime, EddsaPublicKey, BrandtVickreyAuction, BrandtVickreyAuctionMessage, BrandtVickreyAuctionWinner, EddsaSignature, HashCode, throw, implements, import, this, BrandtVickreyReplayOutcome},
ndkeywordstyle=\bfseries,
identifierstyle=\color{black},
sensitive=false,
comment=[l]{//},
morecomment=[s]{/*}{*/},
commentstyle=\itshape,
%stringstyle=\color{red},
morestring=[b]',
morestring=[b]"
}
\lstset{
language=typescript,
%backgroundcolor=\color{lightgray},
extendedchars=true,
basicstyle=\footnotesize\color{NavyBlue}\ttfamily,
showstringspaces=false,
showspaces=false,
%numbers=left,
%numberstyle=\footnotesize,
%numbersep=9pt,
tabsize=2,
breaklines=true,
showtabs=false,
captionpos=b,
emphstyle=\bfseries
}
\newcommand{\TODO}[1]{{\color{orange}#1}\marginpar{{\color{orange}TODO}}}
\begin{document}
\title{AP³\\
Report for Milestone IV\\
NGI Pointer}
\author{Özgür Kesim\\
Christan Grothoff\\
Florian Dold\\
Stefan Kügel\\
Emmanuel Benoist\\[\bigskipamount]
\normalsize Mentor: Mirko Ross \href{mailto:m.ross@digital-worx.de}{<m.ross@digital-worx.de>}\\[\medskipamount]
}
\date{October 29, 2022}
\maketitle
\section*{Management summary}
\begin{abstract}
For the \textsc{NGI Pointer} programme, the AP³ project team extended GNU Taler with
\begin{itemize}
\item age-restricted payments,
\item peer-to-peer (P2P) payments and
\item a proof-of-concept escrow functionality for
privacy-preserving auctions.
\end{itemize}
This document provides the report for the final milestone IV with details on
the state of the implementation, the results of user experience studies
and projected future work.
\end{abstract}
\vfill
\hfill {\footnotesize Version: 1.0}
\thispagestyle{empty}
\newpage
\tableofcontents
\newpage
\section{Age Restriction}
\TODO{}
\subsection{Technical details}
\TODO{}
\subsection{Future Works}
\TODO{}
\subsection{Links}
\TODO{}
\newpage
\section{P2P Payments}
We implemented two styles of P2P payments: \textbf{push payments} where a
user sends money to another Taler wallet (which can then accept the
payment), and \textbf{pull payments} where a user sends an invoice to
another Taler wallet (which can then pay the invoice).
Both styles of payment only require one asynchronous uni-directional
secure communication between the wallets to make the payment. The
information that is exchanged is in both cases a short \texttt{taler://}-URI
which allows the wallet to obtain further details from the payment service
provider. These further details include the contract/invoice that the payment
is for. The contract/invoice is stored encrypted at the exchange and thus
cannot be learned by the exchange.
The actual P2P payment works by having the initiator wallet first
communicate with the Taler exchange to setup the payment. Then the
Taler URI is communicated to the other wallet, for now usually via
QR code or NFC transmission; however, users could also copy the URI
to the clipboard and exchange it via some (secure) messenger. Upon
receiving the URI, the other wallet then again interacts with the
exchange to obtain more details and complete the payment.
If the recipient of a push payment does not accept the payment
(say because the message was lost in transmission, or they do not
like the attached contract terms) the money is automatically refunded
to the payer after some expiration date is reached.
\subsection{Technical details}
P2P payments always work by establishing a \textbf{purse} at the
exchange. A purse has an expiration date, target amount, minimum age,
associated business contract (or invoice), an actual balance and two
public-private key pairs representing permissions to operate on the
purse. For a push payment, the wallet of the sending user creates a
purse (with contract and expiration time) and immediately ensures that
the balance of the purse is the target amount. The payer then sends
the merge-capability key of the purse to the payee. The payee can
then use the merge-capability key to merge (move) the balance of the
purse into a KYCed (i.e. know-your-customer ready) reserve of the receiving
wallet. A KYCed reserve basically is a long-term public-private key pair that
identifies a wallet and a user at an exchange, ensuring income transparency.
Once the money is in the reserve, the wallet can then use the reserve private
key to withdraw fresh coins.
When invoicing, the initiator again creates a purse, but this time
does not put any money into it and keeps the merge capability key
private. The initiator wallet instead immediately specifies its own
KYCed reserve as the one the purse should be merged into. The
initiator then shares a contract-download capability key with the
payer. The payer downloads the contract (including the purse public
key) and can then decide to put money into the purse. Once the purse
balance reaches the target amount, it is then automatically merged
with the initiator's reserve. The initiator's wallet (long) polls the
reserve and withdraws the funds as soon as they become available.
The protocol and implementation includes a few refinements, like fees
to be paid to the exchange for managing a purse and age-restrictions
on the coins used to pay an invoice.
\subsection{Future Work}
The following features (from tiny to major) have been discussed in
the team and ought to be implemented as part of future work.
\begin{itemize}
\item \textbf{Wallets:} The wallet UIs currently do not allow the user to actually specify
any age-restrictions on the payer when sending P2P pull payment requests
(invoicing). This mostly is about adding one more drop-down widget.
\item \textbf{Wallets:} The wallet UIs currently do not allow the user to actually specify
the expiration date for the purse. Instead, the duration is hard-coded
to a few hours (likely too short). This mostly is about adding one more
input field.
\item \textbf{Auditor:} The Taler auditor was extended to support P2P transactions in
its audits, but the code has not been adequately tested (no
fault injection).
\item \textbf{Exchange:} P2P payments currently only work if both wallets are using the
same exchange. If multiple exchanges operate in the same currency
domain and the recipient has made their (expensive) KYC process
at one exchange and the payer has withdrawn from the other, a
direct payment between the wallets is not possible right now. We
envision federation protocol using periodic aggregated
(``wad'') payments between exchanges should be added to support
P2P payments involing multiple exchanges in the future.
\item \textbf{Mailbox (NEW):} Currently, sending the payment URI is largely left to the user.
We would like to implement a ``mailbox'' service for Taler wallets
that would enable wallets to asynchronously exchange URIs over the
Internet. Once a wallet knows the mailbox address of another wallet
(which would include a public key to encrypt messages to), the user
would no longer be required to manually exchange the QR code.
\item \textbf{TalDir (NEW):} To lookup the mailbox address of another wallet, we would like
to implement a directory service that maps existing addresses like
e-mail addresses, phone numbers or accounts in messengers or social
media platforms to a mailbox. When establishing the directory service
entry, the directory service would validate that the user registering
the wallet has control over the respective address. Naturally, the
directory service would need to be trusted to return the correct
mapping.
\item Both the mailbox and the directory service operators could
themselves be paid via Taler for their service. That should help
ensure a high quality of service from those operators. Naturally,
using the mailbox or the directory service would be optional.
\item \textbf{Messaging:} In the long term, we would like to see more direct integration
of Taler payment functionality with messaging applications, especially
for spam prevention (``The recipient has configured its software to
demand a payment of 50 cents before displaying a message from an unknown
sender to the user. If they like your message, they promise they would
refund this attention fee. Do you want to pay to have your message
shown? (Y/N)'').
\end{itemize}
\subsection{Links}
\href{https://docs.taler.net/design-documents/013-peer-to-peer-payments.html}{Document
013} at \url{https://docs.taler.net/design-documents/} presents the design.
The main implementation parts for P2P are distributed over various code
locations under \url{https://git.taler.net/wallet-core.git/tree/packages/}
(wallet) and \url{https://git.taler.net/exchange.git/tree/src/exchange/}
(exchange):
\begin{description}
\item[Payment operations:] \href{https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-core/src/operations/pay-peer.ts}{taler-wallet-core/src/operations/pay-peer.ts}
\item[Database schema related:] \href{https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-core/src/db.ts#n2065}{taler-wallet-core/src/db.ts}
\item[Transaction list type declarations:] \href{https://git.taler.net/wallet-core.git/tree/packages/taler-util/src/transactions-types.ts#n251}{taler-util/src/transactions-types.ts}
\item[WebExtension UI:] \href{https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-webextension/src/cta/InvoiceCreate}{taler-wallet-webextension/src/cta/InvoiceCreate} and \href{https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-webextension/src/cta/InvoicePay}{InvoicePay}
\item[Exchange] \url{https://git.taler.net/exchange.git/tree/src/exchange/},
specifically:\\
\texttt{taler-exchange-httpd\_purses\_*.c}, \texttt{taler-exchange-httpd\_reserves\_purse\_*.c},
\texttt{taler-exchange-httpd\_contract.*},
\texttt{taler-exchange-expire.c} (plus related changes in the database, client libraries, history, auditor),
and the main test case at
\href{https://git.taler.net/exchange.git/tree/src/testing/test\_exchange\_p2p.c}{testing/test\_exchange\_p2p.c}
\end{description}
\newpage
\section{Brandt-Vickrey Auctions}
\TODO{}
\subsection{Technical details}
\TODO{}
\subsection{Future Works}
\TODO{}
\subsection{Links}
\TODO{}
\newpage
\section{User Experience Studies}
For the \textsc{NGI Pointer} programme, the AP³ project team performed a
usability study to gather feedback and inform further development of the
age-restricted and P2P payment functionalities.
The BFH ``Digitaltag'' is an annual day-long event where the
university presents itself to the public. It is held right next to the
central train station of Biel/Bienne, and is open to the general
public. It was attended by a mixture of prospective students, normal
adults, Swiss executives and retirees.
We used the opportunity to both present GNU Taler to the public, and
to conduct usability studies with interested volunteers.
\begin{figure}[h!]
\includegraphics[width=\textwidth]{pics/digitaltag-ux-setup.jpg}
\caption{Our booth, with GNU Taler publications (including on
age-restrictions), NGI stickers, and a Taler-enabled coffee machine.}
\end{figure}
\subsection{Preparation}
We prepared several notebooks with a browser running a Taler wallet as
well as several Android phones with the Taler Android wallet. We
set up the coffee machine and three Taler backends, one for CHF (used
by the coffee machine), one for KUDOS (used with age-restrictions in
the browser-based setup) and one for Bitcoin (used for P2P payments).
We also prepared a rough write-up describing what we would like users
to do. These intended user stories are included in the appendix. We
note that during the day, we permitted participants to deviate from
the script if they desired to do so, sometimes leading them to explore
other GNU Taler features (and us learning interesting lessons about
those).
For the UX study, we prepared four tables: two tables with the coffee
machine and information materials, and two tables with additional
chairs for guests for the actual UX experiment.
\begin{figure}[h!]
\includegraphics[width=\textwidth]{pics/digitaltag-ux-chairs.jpg}
\caption{Tables for the UX study with Prof. Benoist.}
\end{figure}
\subsection{Data collection}
We did not collect any PII on the participants.\footnote{Except for
one executive who had come just for our booth from Zug and who gave us
his business card as he hopes to collaborate with us in the future.}
Instead, each team member wrote down their observations. We
afterwards de-duplicated the observations and turned those that could
lead to improvements into over 20 new issues on the GNU Taler
bug-tracker (\#7334--\#7354).
\subsection{Key conclusions}
The day revealed the existence of several previously unknown bugs
(like refresh not working properly with the new features) as well
as quite a few surprising difficulties of users (not finding the
QR code button, not finding the account balance, not understanding
that the \texttt{shop.demo.taler.net} page is the shop where they should buy
things). We will try to rectify those as soon as possible.
\end{document}

188
m4/p2p-report.tex Normal file
View File

@ -0,0 +1,188 @@
%\documentclass{article}
\documentclass[a4paper,12pt]{article}
\usepackage[english]{babel}
%\usepackage[a4paper,top=20mm,bottom=20mm,left=20mm,right=20mm,marginparwidth=1.75cm]{geometry}
\usepackage[a4paper,top=20mm,bottom=20mm,left=20mm,right=20mm]{geometry}
\usepackage{array}
\usepackage[framemethod=tikz]{mdframed}
\usepackage{makecell}
\usepackage{enumitem}
\usepackage{xcolor}
\usepackage{parskip}
\newcolumntype{P}[1]{>{\centering\arraybackslash}p{#1}}
\newcolumntype{M}[1]{>{\centering\arraybackslash}m{#1}}
\newenvironment{changemargin}[2]{%
\begin{list}{}{%
\setlength{\topsep}{0pt}%
\setlength{\leftmargin}{#1}%
\setlength{\rightmargin}{#2}%
\setlength{\listparindent}{\parindent}%
\setlength{\itemindent}{\parindent}%
\setlength{\parsep}{\parskip}%
}%
\item[]}{\end{list}}
% Useful packages
\usepackage{amsmath}
\usepackage{graphicx}
\usepackage[colorlinks=true, allcolors=blue]{hyperref}
%\title{Your Paper}
%\author{You}
\begin{document}
%\maketitle
%\begin{abstract}
%Your abstract.
%\end{abstract}
\begin{center}
{\Huge \textsc{NGI POINTER: Peer-to-Peer Payments}}
\end{center}
\section{Context}
For the NGI POINTER programme, the GNU Taler team developed
age-restricted payments, peer-to-peer (P2P) payments and a proof-of-concept
ability to extend GNU Taler with escrow functionality for
privacy-preserving auctions. This document provides some
details on the state of the P2P payment functionality.
\section{Overview}
We implemented two styles of P2P payments: {\bf push payments} where a
user sends money to another Taler wallet (which can then accept the
payment), and {\bf pull payments} where a user sends an invoice to
another Taler wallet (which can then pay the invoice).
Both styles of payment only require one asynchronous uni-directional
secure communication between the wallets to make the payment. The
information that is exchanged is in both cases a short {\tt
taler://}-URI which allows the wallet to obtain further details from
the payment service provider. These further details include the
contract/invoice that the payment is for. The contract/invoice is
stored encrypted at the exchange and thus cannot be learned by the
exchange.
The actual P2P payment works by having the initiator wallet first
communicate with the Taler exchange to setup the payment. Then the
Taler URI is communicated to the other wallet, for now usually via
QR code or NFC transmission; however, users could also copy the URI
to the clipboard and exchange it via some (secure) messenger. Upon
receiving the URI, the other wallet then again interacts with the
exchange to obtain more details and complete the payment.
If the recipient of a push payment does not accept the payment
(say because the message was lost in transmission, or they do not
like the attached contract terms) the money is automatically refunded
to the payer after some expiration date is reached.
\section{Technical details}
P2P payments always work by establishing a {\bf purse} at the
exchange. A purse has an expiration date, target amount, minimum age,
associated business contract (or invoice), an actual balance and two
public-private key pairs representing permissions to operate on the
purse. For a push payment, the wallet of the sending user creates a
purse (with contract and expiration time) and immediately ensures that
the balance of the purse is the target amount. The payer then sends
the merge-capability key of the purse to the payee. The payee can
then use the merge-capability key to merge (move) the balance of the
purse into a KYCed reserve of the receiving wallet. A KYCed reserve
basically is a long-term public-private key pair that identifies a
wallet and a user at an exchange, ensuring income transparency. Once
the money is in the reserve, the wallet can then use the reserve
private key to withdraw fresh coins.
When invoicing, the initiator again creates a purse, but this time
does not put any money into it and keeps the merge capability key
private. The initiator wallet instead immediately specifies its own
KYCed reserve as the one the purse should be merged into. The
initiator then shares a contract-download capability key with the
payer. The payer downloads the contract (including the purse public
key) and can then decide to put money into the purse. Once the purse
balance reaches the target amount, it is then automatically merged
with the initiator's reserve. The initiator's wallet (long) polls the
reserve and withdraws the funds as soon as they become available.
The protocol and implementation includes a few refinements, like fees
to be paid to the exchange for managing a purse and age-restrictions
on the coins used to pay an invoice.
\section{Future Work}
The following features (from tiny to major) have been discussed in
the team and ought to be implemented as part of future work.
\begin{itemize}
\item {\bf Wallets:} The wallet UIs currently do not allow the user to actually specify
any age-restrictions on the payer when sending P2P pull payment requests
(invoicing). This mostly is about adding one more drop-down widget.
\item {\bf Wallets:} The wallet UIs currently do not allow the user to actually specify
the expiration date for the purse. Instead, the duration is hard-coded
to a few hours (likely too short). This mostly is about adding one more
input field.
\item {\bf Auditor:} The Taler auditor was extended to support P2P transactions in
its audits, but the code has not been adequately tested (no
fault injection).
\item {\bf Exchange:} P2P payments currently only work if both wallets are using the
same exchange. If multiple exchanges operate in the same currency
domain and the recipient has made their (expensive) KYC process
at one exchange and the payer has withdrawn from the other, a
direct payment between the wallets is not possible right now. We
envision federation protocol using periodic aggregated
(``wad'') payments between exchanges should be added to support
P2P payments involing multiple exchanges in the future.
\item {\bf Mailbox (NEW):} Currently, sending the payment URI is largely left to the user.
We would like to implement a ``mailbox'' service for Taler wallets
that would enable wallets to asynchronously exchange URIs over the
Internet. Once a wallet knows the mailbox address of another wallet
(which would include a public key to encrypt messages to), the user
would no longer be required to manually exchange the QR code.
\item {\bf TalDir (NEW):} To lookup the mailbox address of another wallet, we would like
to implement a directory service that maps existing addresses like
e-mail addresses, phone numbers or accounts in messengers or social
media platforms to a mailbox. When establishing the directory service
entry, the directory service would validate that the user registering
the wallet has control over the respective address. Naturally, the
directory service would need to be trusted to return the correct
mapping.
\item Both the mailbox and the directory service operators could
themselves be paid via Taler for their service. That should help
ensure a high quality of service from those operators. Naturally,
using the mailbox or the directory service would be optional.
\item {\bf Messaging:} In the long term, we would like to see more direct integration
of Taler payment functionality with messaging applications, especially
for spam prevention (``The recipient has configured its software to
demand a payment of 50 cents before displaying a message from an unknown
sender to the user. If they like your message, they promise they would
refund this attention fee. Do you want to pay to have your message
shown? (Y/N)'').
\end{itemize}
\section{Links}
The design is documented at
\url{https://docs.taler.net/design-documents/013-peer-to-peer-payments.html}.
The main implementation parts are distributed over various
code locations:
\begin{description}
\item[Peer-to-peer payment operations in wallet:] \url{https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-core/src/operations/pay-peer.ts}
\item[Database schema with p2p state in it:] \url{https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-core/src/db.ts#n2065}
\item[Peer-to-peer transactions in the transaction list type declarations:] \url{https://git.taler.net/wallet-core.git/tree/packages/taler-util/src/transactions-types.ts#n251}
\item[WebExtension UI stuff related to peer-to-peer:] \url{https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-webextension/src/cta/InvoiceCreate}, \url{https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-webextension/src/cta/InvoicePay}
\item[Exchange] \url{https://git.taler.net/exchange.git/tree/src/exchange/},
specifically {\tt taler-exchange-httpd\_purses\_*.c}, {\tt taler-exchange-httpd\_reserves\_purse\_*.c},
{\tt taler-exchange-httpd\_contract.*},
{\tt taler-exchange-expire.c} (plus related changes in the database, client libraries, history, auditor),
and the main test case at {\tt https://git.taler.net/exchange.git/tree/src/testing/test\_exchange\_p2p.c}
\end{description}
\end{document}

View File

Before

Width:  |  Height:  |  Size: 4.9 MiB

After

Width:  |  Height:  |  Size: 4.9 MiB

View File

Before

Width:  |  Height:  |  Size: 5.1 MiB

After

Width:  |  Height:  |  Size: 5.1 MiB

BIN
m4/srf-taler-screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB