This commit is contained in:
Christian Grothoff 2023-05-07 17:52:46 +02:00
parent 6d363488a1
commit fddd06c152
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
19 changed files with 1065 additions and 0 deletions

3
doc/flows/Makefile Normal file
View File

@ -0,0 +1,3 @@
all:
pdflatex main.tex
pdflatex main.tex

39
doc/flows/fees-coins.tex Normal file
View File

@ -0,0 +1,39 @@
\section{Fees per coin} \label{sec:fees:coin}
Payments with Taler are always made using coins. Each coin has a specific
denomination, and an exchange will issue coins in different denominations (in
the same currency). The fees per coin depend on the operation and the
denomination.
The primary fee to be paid is a {\bf deposit} fee that is
charged whenever a coin is fully or partially deposited
into a bank account or another wallet.
A secondary fee to be paid is a {\bf change} fee that is
charged whenever a coin partially spent and change must
be rendered.
Coins also have an {\bf expiration} date of approximately {\bf one year}.
After the expiration date, coins become worthless. Wallets that are online
{\bf three months} {\em before} a coin expires will automatically trade any
such coins for one or more fresh coins with a later expiration date. This
process is also subject to the {\bf change} fee.
\begin{table}[h!]
\caption{Fees per coin. Coin denomination values are given in units of CHF 0.01.}
\label{table:fees:coins}
\begin{center}
\begin{tabular}{l|c|r}
{\bf Denomination} & {\bf Fee type} & {\bf Amount} \\ \hline \hline
$2^{-4}-2^{ 0}$ & deposit & {\em CHF 0.00125} \\
$2^{-4}-2^{ 0}$ & change & {\em CHF 0.00125} \\
$2^{ 0}-2^{ 3}$ & deposit & {\em CHF 0.00250} \\
$2^{ 0}-2^{ 3}$ & change & {\em CHF 0.00125} \\
$2^{ 4}-2^{ 8}$ & deposit & {\em CHF 0.005} \\
$2^{ 4}-2^{ 8}$ & change & {\em CHF 0.00125} \\
$2^{ 8}-2^{12}$ & deposit & {\em CHF 0.01} \\
$2^{ 8}-2^{12}$ & change & {\em CHF 0.00125} \\
\end{tabular}
\end{center}
\end{table}

30
doc/flows/fees-wire.tex Normal file
View File

@ -0,0 +1,30 @@
\section{Fees per wire} \label{sec:fees:wire}
Wire fees apply whenever an exchange needs to initiate a wire transfer to
another bank account. Wire fees do not apply to every individual payment to a
merchant, as merchants can choose to {\em aggregate} multiple micropayments
into one large payment on the wire. Wire fees also do not apply to
wallet-to-wallet payments within the Taler system.
A {\bf wire} fee is applied when a merchant receives
an aggregated payment into their bank account.
A {\bf closing} fee is applied when a wallet fails to
withdraw coins and money has to be sent back to the
originating bank account.
\begin{table}[h!]
\caption{Table with wire fees. Wire fees are set annually.}
\label{table:fees:wire}
\begin{center}
\begin{tabular}{l|c|r}
{\bf Year} & {\bf Fee type} & {\bf Amount} \\ \hline \hline
2023 & wire & {\em CHF 0.05} \\
2023 & closing & {\em CHF 0.10} \\
2024 & wire & {\em CHF 0.05} \\
2024 & closing & {\em CHF 0.10} \\
2025 & wire & {\em CHF 0.05} \\
2025 & closing & {\em CHF 0.10} \\
\end{tabular}
\end{center}
\end{table}

52
doc/flows/int-deposit.tex Normal file
View File

@ -0,0 +1,52 @@
\section{Deposit}
\begin{figure}[h!]
\begin{sequencediagram}
\newinst{wallet}{\shortstack{Customer wallet \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] { Unique \\ Wallet ID};
\end{tikzpicture}
}}
\newinst[2]{exchange}{\shortstack{Taler (exchange) \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\newinst[2]{bank}{\shortstack{Customer bank \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] {Checking \\ Accounts};
\end{tikzpicture}
}}
\postlevel
\begin{callself}{wallet}{Review deposit fees}{}
\end{callself}
\mess[0]{wallet}{Deposit {(Coins)}}{exchange}
\begin{sdblock}{Acceptable account?}{}
\mess[0]{exchange}{{Refuse deposit}}{wallet}
\end{sdblock}
\begin{sdblock}{KYC/AML required?}{}
\begin{callself}{exchange}{Figures~\ref{fig:proc:kyc}, \ref{fig:proc:aml}}{}
\end{callself}
\end{sdblock}
% \prelevel
% \prelevel
% \begin{sdblock}{User abort?}{}
% \mess[0]{wallet}{{Request abort}}{exchange}
% \mess[0]{exchange}{{Abort confirmation}}{wallet}
% \end{sdblock}
\mess[0]{exchange}{{Initiate transfer}}{bank}
\end{sequencediagram}
\caption{Deposit interactions between customer, Taler exchange (payment
service provider) and customer's bank.}
\label{fig:int:deposit}
\end{figure}
We do {\bf not} permit the customer to regain control over their funds {\em
unless} they pass the KYC/AML checks. The technical reason is simply that
the KYC/AML checks happen {\em after} the aggregation logic and at this point
refunds are no longer permitted. From a compliance perspective, this also
prevents malicious customers from risk-free probing of the system.

58
doc/flows/int-pay.tex Normal file
View File

@ -0,0 +1,58 @@
\section{Pay}
\begin{figure}[h!]
\begin{sequencediagram}
\newinst{wallet}{\shortstack{Customer wallet \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] { Unique \\ Wallet ID};
\end{tikzpicture}
}}
\newinst[1]{merchant}{\shortstack{Merchant \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\newinst[1]{exchange}{\shortstack{Taler (exchange) \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\newinst[1]{bank}{\shortstack{Merchant bank \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] {Commercial \\ Accounts};
\end{tikzpicture}
}}
\postlevel
\mess[0]{wallet}{Browse catalog}{merchant}
\mess[0]{merchant}{Commercial offer}{wallet}
\begin{callself}{wallet}{Review offer}{}
\end{callself}
\mess[0]{wallet}{Send payment {(Coins)}}{merchant}
\mess[0]{merchant}{Deposit {(Coins)}}{exchange}
\begin{sdblock}{Acceptable account?}{}
\mess[0]{exchange}{{Refuse deposit}}{merchant}
\mess[0]{merchant}{{Refund purchase}}{wallet}
\end{sdblock}
\mess[0]{exchange}{{Confirm deposit}}{merchant}
\mess[0]{merchant}{Fulfill order}{wallet}
\begin{callself}{exchange}{Aggregate transactions}{}
\end{callself}
\begin{sdblock}{KYC/AML required?}{}
\begin{callself}{exchange}{Figures~\ref{fig:proc:kyc}, \ref{fig:proc:aml}}{}
\end{callself}
\end{sdblock}
\mess[0]{exchange}{{Initiate transfer}}{bank}
\end{sequencediagram}
\caption{Deposit interactions between customer, merchant,
Taler exchange (payment service provider) and merchant bank.}
\label{fig:int:pay}
\end{figure}
{\bf Internal note:} The exchange refusing a deposit immediately based on
unaccaptable merchant accounts may not be fully implemented (this is a very
recent feature, after all); especially the merchant then automatically
refunding the purchase to the customer is certainly missing. However,
the entire situation only arises when a merchant is incorrectly configured
and in violation of the terms of service.

55
doc/flows/int-pull.tex Normal file
View File

@ -0,0 +1,55 @@
\section{Pull payment (aka invoicing)}
\begin{figure}[h!]
\begin{sequencediagram}
\newinst{payer}{\shortstack{Payer \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] {Pre-funded \\ Wallet};
\end{tikzpicture}
}}
\newinst[2]{exchange}{\shortstack{Taler (exchange) \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\newinst[2]{payee}{\shortstack{Payee \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] { Unique \\ Wallet ID};
\end{tikzpicture}
}}
\postlevel
\begin{callself}{payee}{Review pull payment fees}{}
\end{callself}
\mess[0]{payee}{{Create invoice (Wallet ID)}}{exchange}
\mess[0]{exchange}{{Invoice ready}}{payee}
\mess[0]{payee}{{Send invoice (e.g. via QR code)}}{payer}
\begin{callself}{payer}{Review invoice}{}
\end{callself}
\mess[0]{payer}{{Make payment (Coins)}}{exchange}
\begin{sdblock}{Domestic wallet?}{}
\begin{callself}{exchange}{Figure~\ref{fig:proc:domestic}}{}
\end{callself}
\end{sdblock}
\begin{sdblock}{KYC/AML required?}{}
\begin{callself}{exchange}{Figures~\ref{fig:proc:kyc}, \ref{fig:proc:aml}}{}
\end{callself}
\end{sdblock}
\mess[0]{exchange}{{Distribute digital cash}}{payee}
\end{sequencediagram}
\caption{Interactions between wallets and Taler exchange
in a pull payment.}
\label{fig:int:pull}
\end{figure}
We do {\bf not} permit the payer to regain control over their funds, once the
payment was made they are locked {\em until} the payee passes the KYC/AML
checks. We only do the AML/KYC process once the funds are locked at the
exchange. This ensures we know the actual transacted amounts (which may be
lower than the total amounts requested) and prevents risk-free probing
attacks.

47
doc/flows/int-push.tex Normal file
View File

@ -0,0 +1,47 @@
\section{Push payment}
\begin{figure}[h!]
\begin{sequencediagram}
\newinst{payer}{\shortstack{Payer \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] {Pre-funded \\ Wallet};
\end{tikzpicture}
}}
\newinst[2]{exchange}{\shortstack{Taler (exchange) \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\newinst[2]{payee}{\shortstack{Payee \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] { Unique \\ Wallet ID};
\end{tikzpicture}
}}
\postlevel
\begin{callself}{payer}{Review push payment fees}{}
\end{callself}
\mess[0]{payer}{{Push funds (Coins)}}{exchange}
\mess[0]{payer}{{Offer payment (e.g. via QR code)}}{payee}
\begin{callself}{payee}{Review payment offer}{}
\end{callself}
\mess[0]{payee}{{Request funds (Wallet ID)}}{exchange}
\begin{sdblock}{Domestic wallet?}{}
\begin{callself}{exchange}{Figure~\ref{fig:proc:domestic}}{}
\end{callself}
\end{sdblock}
\begin{sdblock}{KYC/AML required?}{}
\begin{callself}{exchange}{Figures~\ref{fig:proc:kyc}, \ref{fig:proc:aml}}{}
\end{callself}
\end{sdblock}
\mess[0]{exchange}{{Distribute digital cash}}{payee}
% \postlevel
\begin{sdblock}{Payment offer expired?}{}
\mess[0]{exchange}{{Return funds}}{payer}
\end{sdblock}
\end{sequencediagram}
\caption{Interactions between wallets and Taler exchange
in a push payment.}
\label{fig:int:push}
\end{figure}

39
doc/flows/int-refund.tex Normal file
View File

@ -0,0 +1,39 @@
\section{Refund}
\begin{figure}[h!]
\begin{sequencediagram}
\newinst{wallet}{\shortstack{Customer wallet \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] { Unique \\ Wallet ID};
\end{tikzpicture}
}}
\newinst[2]{merchant}{\shortstack{Merchant \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\newinst[2]{exchange}{\shortstack{Taler (exchange) \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\postlevel
\begin{callself}{merchant}{Initiate refund}{}
\end{callself}
\mess[0]{merchant}{{Refund offer (QR code)}}{wallet}
\mess[0]{wallet}{Request refund}{merchant}
\mess[0]{merchant}{Approve refund}{exchange}
\mess[0]{exchange}{Confirm refund}{merchant}
\mess[0]{merchant}{Return refund confirmation}{wallet}
\end{sequencediagram}
\caption{Refund processing when a merchant is unable to fulfill
a contract. Refunds must happen {\em before} the
exchange has aggregated the original transaction for
a bank transfer to the merchant. Furthermore, refunds
can only go to the customer who made the original payment
and the refund cannot exceed the amount of the original
payment.}
\label{fig:int:refund}
\end{figure}

View File

@ -0,0 +1,48 @@
\section{Shutdown}
\begin{figure}[h!]
\begin{sequencediagram}
\newinst{wallet}{\shortstack{Customer wallet \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] { Unique \\ Wallet ID};
\end{tikzpicture}
}}
\newinst[2]{exchange}{\shortstack{Taler (exchange) \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\newinst[2]{bank}{\shortstack{Customer bank \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] {Checking \\ Accounts};
\end{tikzpicture}
}}
\postlevel
\begin{callself}{exchange}{Operator initiates shutdown}{}
\end{callself}
\mess[0]{exchange}{{Shutdown alert}}{wallet}
\begin{sdblock}{Bank account known?}{}
\begin{callself}{wallet}{Designate bank account}{}
\end{callself}
\end{sdblock}
\mess[0]{wallet}{{Deposit (Coins)}}{exchange}
\begin{sdblock}{Acceptable account?}{}
\mess[0]{exchange}{{Refuse deposit}}{wallet}
\end{sdblock}
\begin{sdblock}{KYC/AML required?}{}
\begin{callself}{exchange}{Figures~\ref{fig:proc:kyc}, \ref{fig:proc:aml}}{}
\end{callself}
\end{sdblock}
\mess[0]{exchange}{{Initiate transfer}}{bank}
\end{sequencediagram}
\caption{Shutdown interactions between customer, Taler exchange (payment
service provider) and bank.}
\label{fig:int:shutdown}
\end{figure}
KYC/AML requirements are relaxed in cases where the customer is able to
cryptographically demonstrate that they previously withdrew these coins from
the designated checking account. Thus, KYC/AML checks here primarily still
apply if the customer received the funds via P2P transfers from other wallets.

View File

@ -0,0 +1,49 @@
\section{Withdraw}
\begin{figure}[h!]
\begin{sequencediagram}
\newinst{wallet}{\shortstack{Customer wallet \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] { Unique \\ Wallet ID};
\end{tikzpicture}
}}
\newinst[2]{exchange}{\shortstack{Taler (exchange) \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\newinst[2]{bank}{\shortstack{Customer bank \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] {Checking \\ Accounts};
\end{tikzpicture}
}}
\postlevel
\mess[0]{wallet}{Withdraw {(Amount)}}{exchange}
\mess[0]{exchange}{{Configuration (ToS, Fees)}}{wallet}
\begin{sdblock}{once}{}
\begin{callself}{wallet}{Accept ToS}{}
\end{callself}
\end{sdblock}
\begin{callself}{wallet}{Review withdraw fees}{}
\end{callself}
\mess[0]{wallet}{{Initiate transfer (Amount, Credit account, Wallet ID)}}{bank}
\mess[0]{bank}{{Credit (Wallet ID)}}{exchange}
\begin{sdblock}{Acceptable transfer?}{}
\mess[0]{exchange}{{Bounce funds}}{bank}
\end{sdblock}
\postlevel
\mess[0]{exchange}{Confirm wire transfer}{wallet}
\mess[0]{wallet}{Request digital cash}{exchange}
\mess[0]{exchange}{Distribute digital cash}{wallet}
\postlevel
\begin{sdblock}{Withdraw period expired?}{}
\mess[0]{exchange}{{Return remaining funds}}{bank}
\end{sdblock}
\end{sequencediagram}
\caption{Withdraw interactions between customer, Taler exchange (payment
service provider) and bank. The amount of digital cash distributed is
subject to limits per origin account (see Figure~\ref{fig:kyc:withdraw}).}
\label{fig:int:withdraw}
\end{figure}

57
doc/flows/kyc-balance.tex Normal file
View File

@ -0,0 +1,57 @@
\section{KYC: Balance}
Note: this process is not implemented and would require non-trivial extra work
if required.
\begin{figure}[h!]
\begin{center}
\begin{tikzpicture}[node distance=1cm,font=\sffamily,
start/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=yellow!30},
end/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=red!30},
process/.style={rectangle, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=orange!30},
failed/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=red!30},
io/.style={trapezium, trapezium left angle=70, trapezium right angle=110, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=blue!30},
decision/.style={diamond, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=green!30},
arr/.style={very thick,-latex},
every edge quotes/.style = {auto, font=\footnotesize, sloped}
]
\node (start) [start] {Start};
\node (balance) [decision,below=of start,text width=3cm] {Transaction leaves wallet balance below AML threshold?};
\node (registered) [decision,below=of balance,text width=3cm] {Wallet has been subject to KYC?};
\node (kyc) [process, below=of registered] {KYC process};
\node (aml) [process, left=of kyc] {AML process};
\node (allow) [end, right=of balance] {Allow};
\node (deny) [failed, right=of registered] {Deny};
\draw[arr] (start) -> (balance) {};
\draw[arr] (balance) -> (registered);
\draw (balance) edge["No"] (registered);
\draw[arr] (balance) -> (allow);
\draw (balance) edge["Yes"] (allow);
\draw[arr] (registered) -> (kyc);
\draw (registered) edge["No"] (kyc);
\draw[arr] (registered) -> (deny);
\draw (registered) edge["Yes"] (deny);
\draw[arr] (kyc) -> (deny);
\draw (kyc) edge["Failed"] (deny);
\draw[arr] (kyc) -> (aml);
\draw (kyc) edge["Ok"] (aml);
\draw[arr] (aml) -> (balance.west);
\draw (aml) edge["New threshold"] (balance.west);
\end{tikzpicture}
\end{center}
\caption{Regulatory process when a wallet exceeds its AML threshold.
When the transfer is denied the transaction (withdraw, P2P transfer)
is refused by the wallet.}
\end{figure}
\begin{table}[h!]
\caption{Settings for the balance trigger}
\begin{tabular}{l|l|r}
{\bf Setting} & {\bf Type} & {\bf Value} \\ \hline \hline
Default AML threshold & Amount & {\em 1000 CHF} \\
\end{tabular}
\end{table}

71
doc/flows/kyc-deposit.tex Normal file
View File

@ -0,0 +1,71 @@
\section{KYC: Deposit}
\begin{figure}[h!]
\begin{center}
\begin{tikzpicture}[node distance=1cm,font=\sffamily,
start/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=yellow!30},
end/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=red!30},
process/.style={rectangle, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=orange!30},
failed/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=red!30},
io/.style={trapezium, trapezium left angle=70, trapezium right angle=110, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=blue!30},
decision/.style={diamond, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=green!30},
arr/.style={very thick,-latex},
every edge quotes/.style = {auto, font=\footnotesize, sloped}
]
\node (start) [start] {Start};
\node (country) [decision,below=of start,text width=2.5cm] {Target account in allowed country?};
\node (amount) [decision, below=of country,text width=2.5cm] {Target account received less than KYC threshold?};
\node (kyc) [process, right=of amount] {KYC process};
\node (high) [decision, below=of amount,text width=2.5cm] {Target account received more than its AML threshold?};
\node (aml) [process, right=of high] {AML process};
\node (dummy) [below right=of aml] {};
\node (allow) [end, below right=of dummy] {Allow};
\node (deny) [failed, right=of kyc] {Deny};
\draw[arr] (start) -> (country) {};
\draw[arr] (country) -> (amount);
\draw (country) edge["Yes"] (amount);
\draw[arr] (country.east) -> (deny);
\draw (country.east) edge["No"] (deny);
\draw[arr] (amount) -> (high);
\draw (amount) edge["Yes"] (high);
\draw[arr] (amount.east) -> (kyc);
\draw (amount.east) edge["No"] (kyc);
\draw[arr] (kyc) -> (deny);
\draw (kyc) edge["Failed"] (deny);
\draw[arr] (kyc) -> (high);
\draw (kyc) edge["Succeeded"] (high);
\draw[arr] (high.south) -> (allow);
\draw (high.south) edge["Yes"] (allow);
\draw[arr] (high.east) -> (aml);
\draw (high.east) edge["No"] (aml);
\draw[arr] (aml) -> (deny);
\draw (aml) edge["Violation"] (deny);
\draw[arr] (aml) -> (allow);
\draw (aml) edge["Ok"] (allow);
\end{tikzpicture}
\end{center}
\caption{Regulatory process when depositing digital cash into a bank
account. When the transfer is denied, the money is returned to the
originating wallet.}
\end{figure}
\begin{table}[h!]
\caption{Settings for the deposit trigger}
\begin{tabular}{l|l|r}
{\bf Setting} & {\bf Type} & {\bf Value} \\ \hline \hline
Allowed bank accounts & RFC 8905 RegEx & {\em CH*} \\ \hline
KYC deposit threshold & Amount & {\em 1000 CHF} \\
Default AML deposit threshold & Amount & {\em 2500 CHF} \\
\end{tabular}
\end{table}

78
doc/flows/kyc-pull.tex Normal file
View File

@ -0,0 +1,78 @@
\section{KYC/AML: Pull Payment}
\begin{figure}[h!]
\begin{center}
\begin{tikzpicture}[node distance=0.9cm,font=\sffamily,
start/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=yellow!30},
end/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=red!30},
process/.style={rectangle, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=orange!30},
failed/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=red!30},
io/.style={trapezium, trapezium left angle=70, trapezium right angle=110, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=blue!30},
decision/.style={diamond, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=green!30},
arr/.style={very thick,-latex},
every edge quotes/.style = {auto, font=\footnotesize, sloped}
]
\node (start) [start] {Start};
\node (wallet) [decision,below=of start,text width=2.5cm] {Wallet linked to (domestic) phone number?};
\node (domestic) [process, right=of wallet] {Validate phone number};
\node (amount) [decision, below=of wallet,text width=2.5cm] {Wallet received less than KYC threshold from other wallets?};
\node (kyc) [process, right=of amount] {KYC process};
\node (high) [decision, below=of amount,text width=2.5cm] {Wallet received more than its AML threshold?};
\node (aml) [process, right=of high] {AML process};
\node (dummy) [below right=of aml] {};
\node (allow) [end, below right=of dummy] {Allow invoicing};
\node (deny) [failed, right=of kyc] {Deny};
\draw[arr] (start) -> (wallet) {};
\draw[arr] (wallet) -> (amount);
\draw (wallet) edge["Yes"] (amount);
\draw[arr] (wallet.east) -> (domestic);
\draw (wallet.east) edge["No"] (domestic);
\draw[arr] (domestic) -> (amount);
\draw (domestic) edge["Confirmed"] (amount);
\draw[arr] (domestic) -> (deny);
\draw (domestic) edge["Failed"] (deny);
\draw[arr] (amount) -> (high);
\draw (amount) edge["Yes"] (high);
\draw[arr] (amount.east) -> (kyc);
\draw (amount.east) edge["No"] (kyc);
\draw[arr] (kyc) -> (deny);
\draw (kyc) edge["Failed"] (deny);
\draw[arr] (kyc) -> (high);
\draw (kyc) edge["Succeeded"] (high);
\draw[arr] (high.south) -> (allow);
\draw (high.south) edge["Yes"] (allow);
\draw[arr] (high.east) -> (aml);
\draw (high.east) edge["No"] (aml);
\draw[arr] (aml) -> (deny);
\draw (aml) edge["Violation"] (deny);
\draw[arr] (aml) -> (allow);
\draw (aml) edge["Ok"] (allow);
\end{tikzpicture}
\end{center}
\caption{Regulatory process when receiving payments from another wallet.
The threshold depends on the risk profile from the KYC process.
When invoicing is denied the wallet cannot generate the invoice.}
\end{figure}
\begin{table}[h!]
\caption{Settings for the pull payment trigger}
\begin{tabular}{l|l|r}
{\bf Setting} & {\bf Type} & {\bf Value} \\ \hline \hline
Permitted phone numbers & Dialing prefix & {\em +41} \\
P2P KYC threshold & Amount & {\em 100 CHF} \\
Default P2P AML threshold & Amount & {\em 1000 CHF} \\
\end{tabular}
\end{table}

79
doc/flows/kyc-push.tex Normal file
View File

@ -0,0 +1,79 @@
\section{KYC/AML: Push Payment}
\begin{figure}[h!]
\begin{center}
\begin{tikzpicture}[node distance=0.9cm,font=\sffamily,
start/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=yellow!30},
end/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=red!30},
process/.style={rectangle, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=orange!30},
failed/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=red!30},
io/.style={trapezium, trapezium left angle=70, trapezium right angle=110, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=blue!30},
decision/.style={diamond, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=green!30},
arr/.style={very thick,-latex},
every edge quotes/.style = {auto, font=\footnotesize, sloped}
]
\node (start) [start] {Start};
\node (wallet) [decision,below=of start,text width=2.5cm] {Wallet linked to (domestic) phone number?};
\node (domestic) [process, right=of wallet] {Validate phone number};
\node (amount) [decision, below=of wallet,text width=2.5cm] {Wallet received less than KYC threshold from other wallets?};
\node (kyc) [process, right=of amount] {KYC process};
\node (high) [decision, below=of amount,text width=2.5cm] {Wallet received more than its AML threshold?};
\node (aml) [process, right=of high] {AML process};
\node (dummy) [below right=of aml] {};
\node (allow) [end, below right=of dummy] {Allow};
\node (deny) [failed, right=of kyc] {Deny};
\draw[arr] (start) -> (wallet) {};
\draw[arr] (wallet) -> (amount);
\draw (wallet) edge["Yes"] (amount);
\draw[arr] (wallet.east) -> (domestic);
\draw (wallet.east) edge["No"] (domestic);
\draw[arr] (domestic) -> (amount);
\draw (domestic) edge["Confirmed"] (amount);
\draw[arr] (domestic) -> (deny);
\draw (domestic) edge["Failed"] (deny);
\draw[arr] (amount) -> (high);
\draw (amount) edge["Yes"] (high);
\draw[arr] (amount.east) -> (kyc);
\draw (amount.east) edge["No"] (kyc);
\draw[arr] (kyc) -> (deny);
\draw (kyc) edge["Failed"] (deny);
\draw[arr] (kyc) -> (high);
\draw (kyc) edge["Succeeded"] (high);
\draw[arr] (high.south) -> (allow);
\draw (high.south) edge["Yes"] (allow);
\draw[arr] (high.east) -> (aml);
\draw (high.east) edge["No"] (aml);
\draw[arr] (aml) -> (deny);
\draw (aml) edge["Violation"] (deny);
\draw[arr] (aml) -> (allow);
\draw (aml) edge["Ok"] (allow);
\end{tikzpicture}
\end{center}
\caption{Regulatory process when receiving payments from another wallet.
The threshold depends on the risk profile from the KYC process.
When the transfer is denied the money is (eventually) returned to
the originating wallet.}
\end{figure}
\begin{table}[h!]
\caption{Settings for the push payment trigger}
\begin{tabular}{l|l|r}
{\bf Setting} & {\bf Type} & {\bf Value} \\ \hline \hline
Permitted phone numbers & Dialing prefix & {\em +41} \\
P2P KYC threshold & Amount & {\em 100 CHF} \\
Default P2P AML threshold & Amount & {\em 1000 CHF} \\
\end{tabular}
\end{table}

View File

@ -0,0 +1,45 @@
\section{KYC: Withdraw}
\begin{figure}[h!]
\begin{center}
\begin{tikzpicture}[node distance=1cm,font=\sffamily,
start/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=yellow!30},
end/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=red!30},
process/.style={rectangle, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=orange!30},
failed/.style={rectangle, rounded corners, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=red!30},
io/.style={trapezium, trapezium left angle=70, trapezium right angle=110, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=blue!30},
decision/.style={diamond, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=green!30},
arr/.style={very thick,-latex},
every edge quotes/.style = {auto, font=\footnotesize, sloped}
]
\node (start) [start] {Start};
\node (country) [decision,below=of start,text width=3cm] {Wire transfer originates from allowed country?};
\node (amount) [decision, below=of country,text width=3cm] {Transferred less than maximum amount from origin account over last month?};
\node (allow) [end, below=of amount] {Allow};
\node (deny) [failed, right=of allow] {Deny};
\draw[arr] (start) -> (country) {};
\draw[arr] (country) -> (amount);
\draw (country) edge["Yes"] (amount);
\draw[arr] (country.east) -> (deny);
\draw (country.east) edge["No"] (deny);
\draw[arr] (amount) -> (allow);
\draw (amount) edge["Yes"] (allow);
\draw[arr] (amount.east) -> (deny);
\draw (amount.east) edge["No"] (deny);
\end{tikzpicture}
\end{center}
\caption{Regulatory process when withdrawing digital cash from a
bank account.
When the transfer is denied the money is (eventually) returned to
the originating bank account.}
\label{fig:kyc:withdraw}
\end{figure}
\begin{table}[h!]
\caption{Settings for the withdraw trigger}
\begin{tabular}{l|l|r}
{\bf Setting} & {\bf Type} & {\bf Value} \\ \hline \hline
Allowed bank accounts & RFC 8905 RegEx & {\em CH*} \\ \hline
Monthly withdraw maximum & Amount & {\em 1000 CHF} \\
\end{tabular}
\end{table}

159
doc/flows/main.tex Normal file
View File

@ -0,0 +1,159 @@
\documentclass[10pt,a4paper,oneside]{book}
\usepackage[utf8]{inputenc}
\usepackage{url}
\usepackage{graphicx}
\usepackage{hyperref}
\usepackage{qrcode}
\usepackage{pgf-umlsd}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{positioning}
\usetikzlibrary{calc}
\usetikzlibrary{quotes}
\author{Christian Grothoff}
\title{Flows in the GNU Taler System}
\begin{document}
\tableofcontents
\chapter{Interactions} \label{chap:interactions}
This chapter introduces the main payment interactions in the GNU Taler payment
system. For each interaction, we introduce the parties involved and in which
order they interact and how. In each interaction it is possible that the
Taler exchange needs to trigger a compliance process. These regulatory
riggers are described in more detail in Chapter~\ref{chap:triggers}.
The main interactions of the system are:
\begin{description}
\item[withdraw] a customer withdraws digital cash to their wallet
\item[deposit] a customer returns digital cash into their bank account
\item[pay] a customer pays into bank account of a merchant
\item[refund] a merchant decides to return funds to a customer
\item[push] a customer sends a payment to another wallet
\item[pull] a customer requests a payment from another wallet (effectively sending an invoice)
\item[shutdown] the Taler payment system operator informs the customers that the system is being shut down for good
\end{description}
Taler has no accounts (this is digital cash) and thus there is no ``opening''
or ``closing'' of accounts. The equivalent of ``opening'' an account is thus
to withdraw digital cash. The equivalent of ``closing'' an account is to
either (1) deposit the funds explicitly into a bank account, or (2) the coins
will expire if the wallet was lost (including long-term offline or
uninstalled). Finally, if a wallet remains (occasionally) online but a user
does simply not spend the coins will (3) diminish in value from the change
fees (see Section~\ref{sec:fees:coin}) that apply to prevent the coins from
expiring outright.
The following sections describe the respective processes for each of these
interactions.
\include{int-withdraw}
\include{int-deposit}
\include{int-pay}
\include{int-refund}
\include{int-push}
\include{int-pull}
\include{int-shutdown}
\chapter{Regulatory Triggers} \label{chap:triggers}
In this chapter we show decision diagrams for regulatory processes of the
various core operations of the GNU Taler payment system. In each case, the
{\bf start} state refers to one of the interactions described in the previous
chapter. The payment system will then use the process to arrive at an {\bf
allow} decision which permits the transaction to go through, or at a {\bf
deny} decision which ensures that the funds are not moved.
The specific {\em decisions} (in green) depend on the risk profile and the
regulatory environment. The tables in each section list the specific values
that are to be configured.
There are five types if interactions that can trigger regulatory processes:
\begin{description}
\item[withdraw] a customer withdraws digital cash from their {\bf bank account}
\item[deposit] a merchant's {\bf bank account} is designated to receive a payment in digital cash
\item[push] a {\bf wallet} accepts a payment from another wallet
\item[pull] a {\bf wallet} requests a payment from another wallet
\item[balance] a withdraw or P2P payment causes the balance of a {\bf wallet} to exceed a given threshold
\end{description}
We note in bold the {\bf anchor} for the regulator process. The anchor is used
to link the interaction to an identity. Once an identity has been established
for a particular anchor, that link is considered established for all types of
activities involving that anchor. A wallet is uniquely identified in the
system by its unique cryptographic key. A bank account is uniquely identified
in the system by its (RFC 8905) bank routing data (usually including BIC, IBAN
and account owner name).
The KYC and AML processes themselves are described in
Chapter~\ref{chap:regproc}.
\include{kyc-withdraw}
\include{kyc-deposit}
\include{kyc-push}
\include{kyc-pull}
\include{kyc-balance}
\chapter{Regulatory Processes} \label{chap:regproc}
This chapter describes the interactions between the customer, exchange and
organizations or staff assisting with regulatory processes designed to ensure
that customers are residents in the area of operation of the payment service
provider, are properly identified, and do not engage in money laundering.
The three main regulatory processes are:
\begin{description}
\item[domestic check] This process establishes that a user is generally
eligible to use the payment system. The process checks that the user has an
eligible address, but stops short of establishing the user's identity.
\item[kyc] This process establishes a user's legal identity, possibly
using external providers to review documents and check against blacklists.
\item[aml] The AML process reviews suspicious payment activities for
money laundering. Here AML staff reviews all collected information.
\end{description}
\include{proc-domestic}
\include{proc-kyc}
\include{proc-aml}
\chapter{Fees} \label{chap:fees}
The business model for operating a Taler exchange is to charge transaction
fees. Fees are charged on certain operations by the exchange. There are two
types of fees, {\bf wire fees} and {\bf coin fees}. This chapter describes
the fee structure.
Fixed, amount-independent {\bf wire fees} are charged on wire transfers using
the core banking system. Details on wire fees are described in
Section~\ref{sec:fees:wire}.
Coin fees are more complex, as they do not exactly follow neither the usual
percentage of volume model of other payment systems. Instead, coin fees are
applied per coin, resulting in a {\em logarithmic} fee structure. As a
result, the effective fee {\em percentage} for tiny transactions is high (for
example 50\% for transactions of 0.0025 CHF) while the effective fee
percentage for large transactions is nominal (for example $\approx$ 0.05\% for
transactions of $\approx$ 40 CHF). Details on coin fees are described in
Section~\ref{sec:fees:coin}.
Fees are configurable (and that fee types beyond those described here are
supported by the software). Thus, the specific fees may be adjusted in the
future based on business decisions. However, changes to the fees are never
retroactively applied to coins already in circulation. Wire fees that have
been publicly announced for a particular time period also cannot be changed.
Finally, any change to the terms of service must also be explicitly accepted
by the users before they withdraw additional funds.
\include{fees-wire}
\include{fees-coins}
%\include{fees-other}
\end{document}

47
doc/flows/proc-aml.tex Normal file
View File

@ -0,0 +1,47 @@
\section{AML process}
\begin{figure}[h!]
\begin{sequencediagram}
\newinst{wallet}{\shortstack{Customer \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] { Unique \\ Action};
\end{tikzpicture}
}}
\newinst[2]{exchange}{\shortstack{Taler (exchange) \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\newinst[2]{staff}{\shortstack{AML staff \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] { Access \\ Token};
\end{tikzpicture}
}}
\postlevel
\mess[0]{wallet}{{Initial action}}{exchange}
\begin{callself}{exchange}{Establish AML requirement}{}
\end{callself}
\begin{callself}{exchange}{Queue AML task}{}
\end{callself}
\mess[0]{exchange}{Wait for AML}{wallet}
\mess[0]{staff}{Request AML work}{exchange}
\mess[0]{exchange}{{Open AML task(s)}}{staff}
\mess[0]{staff}{Request details}{exchange}
\mess[0]{exchange}{KYC/AML data}{staff}
\begin{callself}{staff}{Review and decide}{}
\end{callself}
\mess[0]{staff}{{Decision documentation}}{exchange}
\mess[0]{exchange}{AML decision}{wallet}
\mess[0]{wallet}{{Retry action}}{exchange}
\end{sequencediagram}
\caption{Deposit interactions between customer, Taler exchange (payment
service provider) and the AML staff. The process can be
triggered by various {\em actions} described in Chapter~\ref{chap:triggers}.
AML staff interactions are cryptographically secured and
decisions and the provided reasoning are archived by the exchange.
AML staff may interact with the customer (out-of-band)
in its decision process.
}
\label{fig:proc:aml}
\end{figure}

View File

@ -0,0 +1,66 @@
\section{Domestic wallet check}
\begin{figure}[h!]
\begin{sequencediagram}
\newinst{wallet}{\shortstack{Customer wallet \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] { Unique \\ Wallet ID};
\end{tikzpicture}
}}
\newinst[2]{exchange}{\shortstack{Taler (exchange) \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\newinst[2]{sms}{\shortstack{Address validator}}
\postlevel
\mess[0]{wallet}{{P2P payment (Wallet ID)}}{exchange}
\begin{callself}{exchange}{New wallet?}{}
\end{callself}
\mess[0]{exchange}{Request address validation}{sms}
\mess[0]{sms}{Validation process ID}{exchange}
\mess[0]{exchange}{Request address validation}{wallet}
\mess[0]{wallet}{Send address}{sms}
\mess[0]{sms}{{Send PIN/TAN code (to address)}}{wallet}
\mess[0]{wallet}{Supply PIN/TAN code}{sms}
\mess[0]{sms}{{Confirmed customer address}}{exchange}
\mess[0]{exchange}{{Confirm completion}}{wallet}
\mess[0]{wallet}{{Retry action}}{exchange}
\end{sequencediagram}
\caption{Deposit interactions between customer, Taler exchange (payment
service provider) and external address validation service. The process can be
triggered by wallet-to-wallet (P2P) payments described in Chapter~\ref{chap:triggers}.}
\label{fig:proc:domestic}
\end{figure}
Our users have to accept the terms of service which restrict the use of the
service to domestic customers. For interactions with the core banking system,
this simply means that we only accept payments from or to domestic bank
accounts. For P2P payments between wallets, we require that the wallets are
controlled by a domestic entity. We define domestic entities as those that
are able to receive messages at a domestic address. Two types of addresses are
supported:
\begin{itemize}
\item Control over a domestic {\bf mobile phone number} is established
by sending an SMS message with a PIN/TAN to the MSIN.
\item Control over a domestic {\bf postal address} is established by
sending a letter with a PIN/TAN to the address.
\end{itemize}
Depending on the type of address, a validation has a limited validity period,
as shown in Table~\ref{table:proc:domestic}. When the validity period is
over, a wallet has to re-do the address validation before they can receive any
further funds through the service.
\begin{table}[h!]
\caption{Restrictions on address validations}
\label{table:proc:domestic}
\begin{tabular}{l|l|r}
{\bf Type} & {\bf Validity period} & {\bf Restricted to} \\ \hline \hline
Mobile phone number & 12 months & {\em +41} \\
Postal address & 36 months & {\em Switzerland} \\
\end{tabular}
\end{table}

43
doc/flows/proc-kyc.tex Normal file
View File

@ -0,0 +1,43 @@
\section{KYC process}
\begin{figure}[h!]
\begin{sequencediagram}
\newinst{wallet}{\shortstack{Customer \\
\\ \begin{tikzpicture}
\node [fill=gray!20,draw=black,thick,align=center] { Unique \\ Action};
\end{tikzpicture}
}}
\newinst[2]{exchange}{\shortstack{Taler (exchange) \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\newinst[2]{kyc}{\shortstack{KYC provider \\
\\ \begin{tikzpicture}[shape aspect=.5]
\tikzset{every node/.style={cylinder,shape border rotate=90, draw,fill=gray!25}}
\node at (1.5,0) {\shortstack{{{\tiny Database}}}};
\end{tikzpicture}
}}
\postlevel
\mess[0]{wallet}{{Initial action}}{exchange}
\begin{callself}{exchange}{Establish KYC requirement}{}
\end{callself}
\mess[0]{exchange}{Request new KYC process}{kyc}
\mess[0]{kyc}{{Process identifier (PI)}}{exchange}
\mess[0]{exchange}{{KYC required (PI)}}{wallet}
\mess[0]{wallet}{{KYC start (PI)}}{kyc}
\mess[0]{kyc}{{Request identity documentation}}{wallet}
\mess[0]{wallet}{{Upload identity documentation}}{kyc}
\begin{callself}{kyc}{Validate documentation}{}
\end{callself}
\mess[0]{kyc}{{Share documentation (PI)}}{exchange}
\mess[0]{kyc}{{Confirm completion}}{wallet}
\mess[0]{wallet}{{Retry action}}{exchange}
\end{sequencediagram}
\caption{Deposit interactions between customer, Taler exchange (payment
service provider) and external KYC provider. The process can be
triggered by various {\em actions} described in Chapter~\ref{chap:triggers}.}
\label{fig:proc:kyc}
\end{figure}