cashless2ecash

cashless2ecash: pay with cards for digital cash (experimental)
Log | Files | Refs | README

commit 454a09a97fe81fc935248ac3481b1d80167d3d5a
parent 794b483c5004cffe21039b29061033e6fc485af4
Author: Joel-Haeberli <haebu@rubigen.ch>
Date:   Thu, 30 May 2024 12:28:18 +0200

docs: enhance implementation docs

Diffstat:
Mc2ec/amount_test.go | 25++-----------------------
Mcli/README | 2++
Mdocs/content/acknowledgements.tex | 2+-
Mdocs/content/implementation/a-bank-integration-api.tex | 6+++---
Mdocs/content/implementation/a-c2ec.tex | 27+++++++++++++++------------
Mdocs/content/implementation/a-processes.tex | 8+++++---
Mdocs/content/implementation/a-providers.tex | 10+++++-----
Mdocs/content/implementation/a-terminal-api.tex | 2+-
Mdocs/content/implementation/b-terminal.tex | 16++++++++--------
Mdocs/content/implementation/c-database.tex | 4++--
Mdocs/content/implementation/f-cli.tex | 2+-
Mdocs/content/implementation/g-deployment.tex | 2+-
Mdocs/content/introduction/goal.tex | 1+
Mdocs/content/results/discussion.tex | 2+-
Mdocs/content/results/reflexion.tex | 14++++++++------
Mdocs/project.bib | 15+++++++++++++++
Mdocs/thesis.pdf | 0
Msimulation/README | 25+++++++++++++++++++++++++
Msimulation/c2ec-simulation | 0
Msimulation/config.yaml | 1+
Msimulation/main.go | 1+
Msimulation/sim-terminal.go | 4++--
22 files changed, 100 insertions(+), 69 deletions(-)

diff --git a/c2ec/amount_test.go b/c2ec/amount_test.go @@ -78,7 +78,7 @@ func TestParseValid(t *testing.T) { "CHF:30", "EUR:20.34", "CHF:23.99", - "CHF:50.350", + "CHF:50.35", "USD:109992332", } @@ -120,6 +120,7 @@ func TestFormatAmountValid(t *testing.T) { "USD:109992332", "CHF:20.05", "USD:109992332.01", + "CHF:10.00", "", } amntsParsed := make([]Amount, 0) @@ -200,25 +201,3 @@ func TestFormatAmountInvalid(t *testing.T) { } } } - -func TestParseFloat(t *testing.T) { - - floats := []float64{ - 0.5, - 0.3, - 0.0004, - 1234.9923, - } - - for _, f := range floats { - - formatted := fmt.Sprintf("CHF:%.8f", f) - fmt.Println("formatted:", formatted) - amount, err := parseAmount(formatted) - if err != nil { - fmt.Println("failed!", err) - } - - fmt.Println(FormatAmount(&amount, 2)) - } -} diff --git a/cli/README b/cli/README @@ -8,6 +8,8 @@ The CLI will take care of generating the access tokens for the newly registered ## Build +IMPORTANT: You need at least Go v1.22! + `go build .` ## Run diff --git a/docs/content/acknowledgements.tex b/docs/content/acknowledgements.tex @@ -2,7 +2,7 @@ I would like to thank Prof. Dr. Benjamin Fehrensen and Prof. Dr. Christian Groth The GNU Taler team deserves a big thank you to discuss, reflect and sharpen the Terminals API which was an important part of the thesis. -Also I thank my colleagues from the class who motivated me during thesis. Especially I would like to thank Jan Fuhrer for the nice friday night coding sessions, Christian Blättler for the valuable discussion about Taler and Andy Bigler for the exchange about Android applications. They were crucial to gain a better understanding of how the components work and how I must do the implementation. +Also I thank my colleagues from the class who motivated me during the thesis. Especially I would like to thank Jan Fuhrer for the nice friday night coding sessions, Christian Blättler for the valuable discussion about Taler and Andy Bigler for the exchange about Android applications. They were crucial to gain a better understanding of how the components work and how I must do the implementation. Additionally I would like to thank Meret Staub for her critical thoughts during the proofreading of the thesis. diff --git a/docs/content/implementation/a-bank-integration-api.tex b/docs/content/implementation/a-bank-integration-api.tex @@ -21,7 +21,7 @@ Namely this are the following endpoints: \textbf{Configuration (/config)} -The configuration of the Bank-Integration endpoint is important for Wallets to check their compatibility and readiness. Also the currency specification can be retrieved by this endpoint, which allows the +The configuration of the Bank-Integration endpoint is important for Wallets to check their compatibility and readiness. Also the currency specification can be retrieved by this endpoint. \textbf{Status of withdrawal (/withdrawal-operation/[WOPID])} \label{sec-implementation-bank-integration-api-status} @@ -32,7 +32,7 @@ The \textit{/withdrawal-operation/[WOPID]} endpoint returns the status of withdr This endpoint is used by the Wallet to register the reserve public key generated by the Wallet, which will eventually hold the digital cash at the Exchange. This reserve public key is unique and the API will return a conflict response if a withdrawal with the reserve public key specified in the request already exists. This is also the case if a mapping for the given \textit{WOPID} was already created. -\textbf{Aborting a withdrawal (/withdrawal-operation/[WOPID]/abort)} +\textbf{Abort withdrawal (/withdrawal-operation/[WOPID]/abort)} \label{sec-implementation-bank-integration-api-abort} -This endpoint simply allows the abortion of the withdrawal. This will change the status of the withdrawal to the \textit{aborted} state. +This endpoint simply allows to abort the withdrawal. This will change the status of the withdrawal to the \textit{aborted} state. diff --git a/docs/content/implementation/a-c2ec.tex b/docs/content/implementation/a-c2ec.tex @@ -18,49 +18,52 @@ The implementation of the terminals API can be found in \autoref{sec-implementat \subsubsection{Decoupling steps using Events} -The concept of publishers and subscribers is used heavily in the implementation. It allows decoupling different steps of the process and allows different steps to be handled and executed in their own processes. Publishers can also be called notifiers or similar, while the subscriber can also be called listener or similar. +The concept of publishers and subscribers is used in the implementation. It allows decoupling different steps of the process and allows different steps to be handled and executed in their own processes. Publishers can also be called notifiers or similar, while the subscriber can also be called listener or similar. -The communication of publishers and subscribers happends through channels. A publisher will publish to a certain channel when a defined state is reached. The subscriber who is subscribed or listens to this channel will capture the message sent through the channel by the publisher and start processing it. +The communication of publishers and subscribers happens through channels. A publisher will publish to a certain channel when a defined state is reached. The subscriber who listens to this channel will capture the message sent through the channel by the publisher and start processing it. -The publish-subscribe scheme enables loose coupling and therefore helps to improve the performance of individual processes, because they cannot be hindered by others. - -To decouple different steps in the withdrawal process an event based architecture is implemented. This means that every write action to the database will represent an operation which will trigger an event. The applications processes are listening to those events. The consumer of the API can wait to be notified by the API, by registering to those events via a long polling request at the API. This long-polling will then wait until the listener receives the event and return the received event to the consumer. +To decouple different steps in the withdrawal process an event based architecture is implemented. This means that every action which leads to a state transition of the withdrawal will trigger an event. The applications processes are listening to those events. The consumer of the API can wait to be notified by the API, by registering to those events via a long polling request at the API. This long-polling will then wait until the listener receives the event and return the received messages to the consumer. Following a short list of events and from whom they are triggered and who listens to them: \begin{itemize} - \item Registration of the withdrawal operation parameters. + \item Pending -> Selected \begin{itemize} + \item Description: Registration of the withdrawal operation parameters. \item Registered by: Wallet \item Listened by: Terminal \end{itemize} - \item Payment confirmation request sent to the Bank-Integration API of C2EC. + \item Selected -> Confirming \begin{itemize} + \item Description: Payment confirmation request sent to the Bank-Integration API of C2EC. \item Registered by: Terminal \item Listened by: Confirmation \end{itemize} - \item Payment confirmation success will send a withdrawal operation status update event. + \item Selected -> Confirmed \begin{itemize} + \item Description: Payment confirmation success will send a withdrawal operation status update event. \item Registered by: Confirmation \item Listened by: Consumers (via Bank-Integration-API) \end{itemize} - \item Payment confirmation failure will trigger a retry event. + \item Selected -> Aborted \begin{itemize} + \item Description: Payment confirmation failure will trigger a retry event. \item Registered by: Confirmation \item Listened by: Retrier \end{itemize} - \item Transfers which represent refunds in C2EC. + \item Refund \begin{itemize} + \item Description: Transfers which represent refunds in C2EC. \item Registered by: Exchange (through the wire gateway API) \item Listened by: Transfer \end{itemize} \end{itemize} -\subsection{Abortion Handling} +\subsection{Abort Handling} A withdrawal might be aborted through the terminal or the wallet. These cases are implemented through the respective \textit{abort} endpoint in the bank-integration API \autoref{sec-implementation-bank-integration-api-abort} and terminals API \autoref{sec-implementation-terminal-api-abort}. If in doubt whether to abort the withdrawal or not, it should be aborted. In case of abortion and failure cases, the security of the money is weighted higher than the user-experience. If the user must restart the withdrawal in case of a failure in the process, it is less severe than opening possible security holes by somehow processing the withdrawal anyway. On the other hand the system must be as stable as possible to make this error cases very rare. If they occur too often, the customer might not use the technology and therefore would make it worthless. -The withdrawal can only be aborted, when it is not yet confirmed by the confirmation process (described in \autoref{sec-implementation-processes-confirmation}). +The withdrawal can only be aborted, when it is not yet confirmed by the confirmation process (described in \autoref{sec-implementation-processes-confirmation}). When the customer wants his money back they can wait for the reserve to be closed by the Exchange or get in touch with the operator who might trigger a manual refund. \newpage \include{content/implementation/a-terminal-api} diff --git a/docs/content/implementation/a-processes.tex b/docs/content/implementation/a-processes.tex @@ -10,7 +10,7 @@ The confirmation of a transaction is crucial, since this is the action which all \subsubsection{Confirmation Retrier} -If the confirmation fails, but the transaction is not in the refund state as specified by the provider's transaction, the problem could simply be that the service was not available or the transaction was not yet processed by the provider's backend. In order to not need to abort the transaction directly and give the system some robustness, a retry mechanism was implemented which allows retrying the confirmation step. This retry mechanism is run in a separate process started through the main process. +If the confirmation fails, but the transaction is not in the refund state as specified by the provider's transaction, the problem could simply be that the service was not available or the transaction was not yet processed by the provider's backend. In order to not need to abort the transaction directly and give the system some robustness a retry mechanism was implemented. It allows retrying the confirmation step. This retry mechanism is run in a separate process started through the main process. The retry will only be executed, when the transaction confirmation failed because the transaction was not in the abort state or if for some reason the transaction information could not have been retrieved. @@ -18,4 +18,6 @@ The retry will only be executed, when the transaction confirmation failed becaus The Exchange may send a transfer request to the C2EC component, due to the closing of a reserve or an issue. This will trigger a refund process at the providers backend. This refund process may fail and therefore like in the confirmation case to increase the robustness of the system, a retry mechanism is implemented, which will retry the transfer before ultimatively failing the transfer. -\textbf{Randomizing delays due to self synchronization} -\ No newline at end of file +\textbf{Randomizing delays due to self synchronization} + +All processes doing retries use a randomized exponential backoff algorithm for scheduling the retries. The randomization prevents that the retry processes are all triggered at the exact same time and could crash the server due to heavy load. For the implementation a hard coded threshold of 20 percent of the targeted delay was chosen. The value can be adjusted by changing the constant. +\ No newline at end of file diff --git a/docs/content/implementation/a-providers.tex b/docs/content/implementation/a-providers.tex @@ -13,7 +13,7 @@ The provider client interface defines three functions: \begin{enumerate} \item SetupClient: The setup function is called by the startup of the application and used to initialize the client. Here it makes sense to check that everything needed for the specific client is in place and that properties like access credentials are available. \item GetTransaction: This function is used by the confirmation process to retrieve the transaction of the provider system. It takes the transaction identifier supplied with the withdrawal confirmation request and loads the information about the transaction. Based on this information the decision to confirm or abort the transaction is done. - \item Refund: Since the transaction of the money itself is done by the provider, also refunds will be unwind by the provider. This functions mean is to trigger this refund transaction at the provider. + \item Refund: Since the transaction of the money itself is done by the provider, also refunds will be unwind by the provider. This functions mean is to trigger this refund transaction at the provider. Before triggering the transaction, the refunded amount should be checked. The amount must not be bigger than the withdrawen amount. It can be smaller though, if the Exchange makes a partial refund. \end{enumerate} \subsubsection{Provider Transaction} @@ -24,8 +24,9 @@ Since the confirmation process is implemented to support any provider, also the The provider client interface defines following functions: \begin{enumerate} - \item AllowWithdrawal: This function shall return true, when the transaction received by the provider enters a positive final state. This means that the provider accepted the transaction and could process it. This means that the \textit{Exchange} can create the reserve and allow the customer the withdrawal of the digital cash. - \item AbortWithdrawal: It doesn't mean that if a transaction does not allow to do the withdrawal, that the transaction shall be cancelled immediately. It could also be that the transaction was not yet processed by the provider. In this case we need means to check if the provider transaction is in an abort state if it is not ready for withdrawal, before aborting it. AbortWithdrawal shall therefore answer the question if the provider transaction is in a negative final state, which means the transaction is to be aborted. + \item AllowWithdrawal: This function shall return true, when the transaction received by the provider enters a positive final state. This means that the provider accepted the transaction and could process it. This means that the \textit{Exchange} can create the reserve and allow the customer the withdrawal of the digital cash. This function is responsible to guarantee the \textbf{finality} (\autoref{sec-goals-properties}). + \item AbortWithdrawal: It doesn't mean that if a transaction does not allow to do the withdrawal, that the transaction shall be cancelled immediately. It could also be that the transaction was not yet processed by the provider. In this case a handle to check if the provider transaction is in an abort state. An abort state is a final state which will not change anymore. This indicates C2EC to stop retrying and abort the withdrawal. + \item Confirm: This function is called during the confirmation and contains business specific checks wether to confirm the payment or not. It must be separately implemented, because the transaction format varies between different payment system providers. \item Bytes: This function shall return a byte level representation of the transaction which will be used as proof of the transaction and stored in the exchanges database. \end{enumerate} @@ -48,4 +49,4 @@ Additionally to the Wallee Client a Simulation Client was implemented which can \subsubsection{Adding a new provider} -To add a new provider, the client- and transaction-interfaces must be implemented as described in \autoref{sec-provider-client-interface} and \autoref{sec-provider-transaction-interface}. The \texttt{SetupClient} function of the client interface must make sure to register itself to the global map of registered providers. Additionally, to the newly added provider implementation, the provider must also be registered in the database (\autoref{sec-implementation-cli} describes how to achieve this). When the client adds itself to the registered providers clients, the application will load the provider client at startup of C2EC. If C2EC fails to find the specified provider in the database, it won't start. This behaviour makes sure, that only needed providers are running and that if a new provider was added, it is effectively registered and configured correctly (the setup function of the provider interface is responsible to check the provider specific configuration and do readiness or liveness checks if needed). If the new added provider requires a new payto target type, a new entry is to be created with the GANA in order to prevent conflicts in the future. -\ No newline at end of file +Adding a new provider requires the implementation of the client- and transaction-interfaces as described in \autoref{sec-provider-client-interface} and \autoref{sec-provider-transaction-interface}. The \texttt{SetupClient} function of the client interface must make sure to register itself to the global map of registered providers (accessible through \texttt{PROVIDER\_CLIENTS}). Additionally, to the newly added provider implementation, the provider must also be registered in the database (\autoref{sec-implementation-cli} describes how this could work). When the client adds itself to the registered providers clients, the application will load the provider client at startup of C2EC. If C2EC fails to find the specified provider in the database, it won't start. This behaviour makes sure, that only needed providers are running and that if a new provider was added, it is effectively registered and configured correctly (the setup function of the provider interface is responsible to check the provider specific configuration and do readiness or liveness checks if needed). If the new added provider requires a new payto target type, adding a new entry to GANA in order to prevent conflicts in the future might be a good idea. diff --git a/docs/content/implementation/a-terminal-api.tex b/docs/content/implementation/a-terminal-api.tex @@ -37,7 +37,7 @@ When the terminal setup the withdrawal successful and received the \textit{WOPID \textbf{Trigger Confirmation (/withdrawals/[WOPID]/check)} -Once the terminal authorized the transaction at the providers backend and received the notification, that the transaction was processed at the providers backend, the terminal can trigger the confirmation of the transaction by calling this endpoint. This is also the point where the terminal can know the fees of the provider (if any) and send them to the C2EC component. +Once the terminal authorized the transaction at the providers backend and received the notification, that the transaction was processed at the providers backend, the terminal can trigger the confirmation of the transaction by calling this endpoint. This is also the point where the terminal can know the fees of the provider (if any) and send them to the C2EC component. If for some reason it is not possible to know the fees here, potential fees can also be considered during the confirmation of the payment \autoref{sec-implementation-processes-confirmation} \textbf{Trigger Confirmation (/withdrawals/[WOPID]/abort)} \label{sec-implementation-terminal-api-abort} diff --git a/docs/content/implementation/b-terminal.tex b/docs/content/implementation/b-terminal.tex @@ -11,7 +11,7 @@ In the register parameters screen, a QR code is displayed, which must be scanned If this request is successful, the terminals shows a summary of the transaction and a button to leave the withdrawal activity. The wallet of the user should eventually be able to withdraw the amount authorized from the exchange. -\begin{figure}[h] +\begin{figure}[H] \centering \includegraphics[width=0.7\textwidth]{pictures/diagrams/terminal_flow.png} \caption{The flow of the terminal app} @@ -20,13 +20,13 @@ If this request is successful, the terminals shows a summary of the transaction \subsection{Screens} -The Application is implemented using jetpack compose \cite{app-jetpack-compose} and each of the screens described in \autoref{sec-wallee-withdrawal-flow} is implemented as composable screen. This allows to handle the entire withdrawal flow in one single activity and therefore makes state handling easier, because the state of the withdrawal can be bound to the activity and also will be removed when the activity finishes or is terminated due to an error. It also prevents illegal states and that different withdrawals interfere each other. The state is maintained in a view model as described by androids documentation \cite{app-viewmodel}. The withdrawal activity handles the lifecycle of the view model instance and initializes the routing of the screens using androids navigation controller as documented \cite{app-navigation}. The navigation integration of android allows the declarative definition of the in-app routing and is defined at the creation of the withdrawal activity. +The Application is implemented using jetpack compose \cite{app-jetpack-compose} and each of the screens described in \autoref{sec-wallee-withdrawal-flow} is implemented as composable screen. This allows to handle the entire withdrawal flow in one single activity and therefore makes state handling easier. The state is bound to the activity and compose will make sure to rebuild the UI if values change. It also prevents illegal states and that different withdrawals interfere each other. The state is maintained in a view model as described by Android's documentation \cite{app-viewmodel}. The withdrawal activity handles the lifecycle of the view model instance and initializes the routing of the screens using Android's navigation controller as documented \cite{app-navigation}. The navigation integration of Android allows the declarative definition of the in-app routing and is defined at the creation of the withdrawal activity. \subsubsection{Choose Exchange Screen} On the screen \autoref{fig-terminal-screen-choose-exchange} the user chooses the exchange to withdraw from. This allows the terminal to support withdrawals from various exchanges and therefore enhances the flexibility. When the user selected the exchange, the configuration of the exchange is loaded. This will define the currency of the withdrawal and tell the terminal where to reach the Terminals API of the C2EC server. -\begin{figure}[h] +\begin{figure}[H] \centering \includegraphics[width=0.7\textwidth]{pictures/wallee/choose_exchange_screen.png} \caption{Terminal: Select the exchange to withdraw from} @@ -37,7 +37,7 @@ On the screen \autoref{fig-terminal-screen-choose-exchange} the user chooses the The amount screen in \autoref{fig-terminal-screen-amount} is used to ask the user what amount they would like to withdraw. When the amount was entered and the \textit{withdraw}-button was clicked, the terminal sets up the withdrawal using the Terminal API. The Terminals API will send the \textit{WOPID} to the terminal, which allows the terminal to generate the taler withdraw URI according to \cite{taler-uri-scheme-rfc}. -\begin{figure}[h] +\begin{figure}[H] \centering \includegraphics[width=0.7\textwidth]{pictures/wallee/amount_screen.png} \caption{Terminal: Enter the desired amount to withdraw} @@ -48,7 +48,7 @@ The amount screen in \autoref{fig-terminal-screen-amount} is used to ask the use This screen in \autoref{fig-terminal-screen-register-parameters} displays a QR code which contains the taler withdraw URI of the withdrawal. This allows the customer to scan it using their Taler Wallet app and register the parameters for the withdrawal (namely the reserve public key). The withdrawal can be aborted on the screen. This step is important to make sure, that the customer has a working Taler Wallet installed and allows them to accept the terms of service for the respective exchange, if they did not yet registered the exchange on their wallet. -\begin{figure}[h] +\begin{figure}[H] \centering \includegraphics[width=0.7\textwidth]{pictures/wallee/register_parameters_screen.png} \caption{Terminal: Register withdrawal parameters} @@ -59,16 +59,16 @@ This screen in \autoref{fig-terminal-screen-register-parameters} displays a QR c The authorization screen will use Wallee's \textit{Android Till SDK} \cite{wallee-till-sdk} to authorize the amount at the Wallee backend. The response handler of the SDK will delegate the response to the implementation of the terminal, which allows triggering the confirmation of the payment by C2EC using the Terminals API. When the authorization process is not started and the transaction therefore is created at the backend system of Wallee, the screen \autoref{fig-terminal-screen-authorizing} will be displayed. This signals the user, that the payment authorization must still be done and is about to be started. The user can abort the transaction at this point. -\begin{figure}[h] +\begin{figure}[H] \centering \includegraphics[width=0.7\textwidth]{pictures/wallee/authorize_transaction_screen_1.png} - \caption{Terminal: Waiting to start the authorization of the android till SDK} + \caption{Terminal: Waiting to start the authorization of the Android Till SDK} \label{fig-terminal-screen-authorizing} \end{figure} When the transaction was processed successfully, the summary of the transaction will be displayed on this screen as can be seen in \autoref{fig-terminal-screen-authorized}. -\begin{figure}[h] +\begin{figure}[H] \centering \includegraphics[width=0.7\textwidth]{pictures/wallee/authorize_transaction_screen_2.png} \caption{Terminal: Payment authorized} diff --git a/docs/content/implementation/c-database.tex b/docs/content/implementation/c-database.tex @@ -13,7 +13,7 @@ For the C2EC component the schema c2ec is created. It holds tables to store the \subsubsection{Terminal Provider} -The \textit{terminal provider} table holds information about the provider. It contains the information, which payto target type is used to make transactions by the provider. This information is needed in the refund case where the \textit{Exchange} sends a transfer request. It also holds information about the confirmation endpoint. Namely the base url and the credentials to authenticate the confirmation process against the API of the providers backend. When adding the provider using the cli, the credentials are formatted in the correct way and also encrypted. +The \textit{terminal provider} table holds information about the provider. It contains the information, which payto target type is used to make transactions by the provider. This information is needed in the refund case where the \textit{Exchange} sends a transfer request. It also holds information about the confirmation endpoint. Namely the base url and the credentials to authenticate the confirmation process against the API of the providers backend. When adding the provider using the cli, the credentials are formatted in the correct way and also hashed. \begin{figure}[h] \centering @@ -24,7 +24,7 @@ The \textit{terminal provider} table holds information about the provider. It co \subsubsection{Terminal} -Each Terminal must register before withdrawals are possible using the terminal. Therefore this table holds the information needed for withdrawals. A terminal can be deactivated by setting the \textit{active} field accordingly. The terminals are authenticated using an access token generated during the registration process. Like adding the provider through the cli also the terminal access tokens will be encrypted using a PBKDF (namely argon2). The terminal is linked through the \textit{provider\_id} as foreign key to its provider. The \textit{description} field can hold any information about the terminal which might be useful to the operator and help identify the device (location, device identifier, etc.). The operator will be asked for the respective values, when using the cli for the registration of the terminal. +Each Terminal must register before withdrawals are possible using the terminal. Therefore this table holds the information needed for withdrawals. A terminal can be deactivated by setting the \textit{active} field accordingly. The terminals are authenticated using an access token generated during the registration process. Like adding the provider through the cli also the terminal access tokens will be hashed using a PBKDF (namely argon2). The terminal is linked through the \textit{provider\_id} as foreign key to its provider. The \textit{description} field can hold any information about the terminal which might be useful to the operator and help identify the device (location, device identifier, etc.). The operator will be asked for the respective values, when using the cli for the registration of the terminal. \begin{figure}[h] \centering diff --git a/docs/content/implementation/f-cli.tex b/docs/content/implementation/f-cli.tex @@ -7,7 +7,7 @@ The cli was implemented to be usable and as it was out of scope of the thesis, t \subsection{Adding a Wallee provider} -Adding the Wallee provider is as easy as calling \textit{rp} (register-provider). It will then ask for properties like the base url and the credentials of the API user (generated by Wallee). Since the payto target type in case of Wallee will always be \textit{wallee-transaction}, this is hard coded. The credentials supplied are encrypted using argon2 and stored as hash. If the database leaks for some reason, the passwords cannot be abused easily. +Adding the Wallee provider is as easy as calling \textit{rp} (register-provider). It will then ask for properties like the base url and the credentials of the API user (generated by Wallee). Since the payto target type in case of Wallee will always be \textit{wallee-transaction}, this is hard coded. The credentials supplied are hashed using argon2 \cite{rfc9106}. If the database leaks for some reason, the passwords cannot be abused easily. \subsection{Adding a terminal} diff --git a/docs/content/implementation/g-deployment.tex b/docs/content/implementation/g-deployment.tex @@ -24,7 +24,7 @@ For the deployment of the Wallee POS Terminal app, the following steps are neces \subsection{Setup} -Once the steps from the preparation were succesfully done, the \textit{setup}-script can now be run. It will initiate the database and setup the users (as described in \autoref{sec-security-db-users}) with the correct permissions. It will further generate the executables for C2EC, the cli and the simulation inside the specified \texttt{C2EC\_HOME}. The setup script contains sensitive credentials and shall be deleted after using it. Maybe it can be stored in a save location like a password manager. Like this it will be still available in the future but will not lie around on the filesystem unencrypted. +Once the steps from the preparation were succesfully done, the \textit{setup}-script can now be run. It will initiate the database and setup the users (as described in \autoref{sec-security-db-users}) with the correct permissions. It will further generate the executables for C2EC, the cli and the simulation inside the specified \texttt{C2EC\_HOME}. The setup script contains sensitive credentials and shall be deleted after using it. Maybe it can be stored in a save location like a password manager. Like this it will be still available in the future but will not lie around on the filesystem unhashed. \subsubsection{Setting up Wallee as provider} diff --git a/docs/content/introduction/goal.tex b/docs/content/introduction/goal.tex @@ -5,6 +5,7 @@ The goal of this thesis is to design and implement a framework for cashless with The framework aims to achieve the following key objectives: \begin{enumerate} + \label{sec-goals-properties} \item Finality: Liability for the money is not on the side of the Taler operator \item Convenience: The user-experience follows established patterns \item Abort: Robust and secure payment flow allowing abort handling without loss of money diff --git a/docs/content/results/discussion.tex b/docs/content/results/discussion.tex @@ -30,5 +30,5 @@ C2EC introduces new ways to access digital cash using GNU Taler. Due to the shor \item Run the existing implementation as part of the BFH Taler CHF-Exchange \item Paydroid app: Run a Wallee terminal on behalf of the BFH. \item C2EC: Remove doubled provider structures. Currently providers are saved to the database and must be configured in the configuration. To make the setup and management easier, the providers could only be configured inside the configuration. - \item IPv6 support: The process must also listen on IPv6 addresses. + \item IPv6 support: The process must also listen on IPv6 addresses. \end{enumerate} diff --git a/docs/content/results/reflexion.tex b/docs/content/results/reflexion.tex @@ -2,7 +2,7 @@ \subsection{Technically} -Generally I think I did an acceptable job in the implementation. I was able to implement the required processes and the targeted user-experience. The implementation (in C2EC as well as in the Paydroid app) suffers of some technical debts which I finally accepted, because I had to prioritize the formal parts of the thesis, such as the poster, video, book entry or this documentation. I could have prevented some of these issues, when I read the documentation and specification more concentrated. +Generally I think I did an acceptable job in the implementation. I was able to implement the required processes and the targeted user-experience. The implementation (in C2EC as well as in the Paydroid app) suffers of some technical debts which I finally accepted, because I had to prioritize the formal parts of the thesis, such as the poster, video, book entry or this documentation. I could have prevented some of these issues, when I read the documentation and specification more concentrated. But overall I am satisfied with the work I did concerning the small time range that was available for the implementation. \subsubsection{C2EC} @@ -18,16 +18,18 @@ I think I could apply a lot of knowledge I gained through the past three years. The paydroid application was challenging to me since I never wrote a real Android application on my own. That's why I think I did a good job by implementing a best practice structure with the view models, composable and navigation controller. Through the feedback of Prof. Dr. Benjamin Fehrensen I was able to verify the correctness of these best practices. -I first had problems to understand how exactly the versioning in Android works. The backward compatibility is given even when big time gaps between the feature needed and the version in use occur. In the beginning I suffered a little to understand the difference of the none compose and compose era of Android programming and mixed the patterns. In the end I think I implemented a modern Android app. +I first had problems to understand how exactly the versioning in Android works. The backward compatibility is given even when big time gaps between the feature needed and the version in use occur. In the beginning I suffered a little to understand the difference of the none compose and compose era of Android programming and mixed the patterns first. In the end I think I implemented a modern Android app. -Since the app needs to do requests in the background I had to understand how this could be achieved. Therefore I needed to understand how I can access other threads. I think in this area is the biggest shortcoming of my implementation. I failed to implement a proper asynchronous state-handling. Threads running detached from the UI-Thread will update the model, which will lead to the regeneration of the composables. I think it would be a better way to implement a proper pub / sub model using a library like rxjs or similar. Due to the lack of time I decided to not do this anymore. +Since the app needs to do requests in the background I had to understand how this could be achieved. Therefore I needed to understand how I can access other threads. I think in this area is the biggest shortcoming of my implementation. I implemented a asynchronous state-handling. Threads running detached from the UI-Thread will update the model, which will lead to the regeneration of the composables. I think it would be a better way to implement a proper pub / sub model using a library like rxjs or similar. Due to the lack of time I decided to not do this anymore. + +It was interesting to learn about the difference of Go's goroutines and Kotlin coroutines. While running background tasks using goroutines works perfectly fine, in Kotlin on Android I learnt it is required to start a new thread and launch coroutines on the new thread. Otherwise Android will not allow network requests, because it disallows I/O operations on its UI thread. From my point of view this shows a limitation of coroutines on top of JVM threads. They are not real parallel but just suspend work on the thread and check periodically if the can process further. Go resolves this problem in an elegant way by simply putting all network related I/O into a special queue. \subsection{Methodically} -To organize the work I did a rough planning of the work and the artefacts. On top of this plan I did a weekly iterative planning of the work I wanted to do. This plan was presented through the weekly meeting with Prof. Dr. Christian Grothoff and Prof. Dr. Benjamin Fehrensen. Sometimes the plan needed to be sligthly adjusted due to their feedback. This led to the organization of doing my planning at thursday night so I could plan my work and adjust the plan after our weekly meeting at wednesday morning. I think I could have made the process a bit more transparent but in the end I was able to deliver the artefacts and deliverables on time. +To organize the work I did a rough planning of the work and the artefacts. On top of this plan I did a weekly iterative planning of the work I wanted to do. This plan was presented through the weekly meeting with Prof. Dr. Christian Grothoff and Prof. Dr. Benjamin Fehrensen. Sometimes the plan needed to be sligthly adjusted due to their feedback. This led to the organization of doing my planning at thursday night so I could plan my work and adjust the plan after our weekly meeting at wednesday morning. I think I could have made the process a bit more transparent but in the end I was able to deliver the artefacts and deliverables on time. Sometimes I lost focus because there were so much loose ends to keep up with. I then did something different and ordered my thoughts. This helped sometimes but not always. When the stress level was rising this was more difficult. \subsection{Personally} -The thesis was constrained with a lot of insecurities for me. How does the process look? How can I implement the process? How does GNU Taler even work? How does Wallee work? In the end I am proud of what I accomplished during the thesis. I was able to understand the API and write a program which fulfills the properties needed for the withdrawal. Additionally I could learn a lot about designing an API. I am thankful that the Bern University of Applied Sciences supports free software projects like GNU Taler. It was a great opportunity for me as student to gain direct insights and work on a GNU project during my thesis. I remember that Prof. Dr. Christian Grothoff during a onsite session told me: "Nicht so kurzfristig denken!". This also shows the horizon of the project. It tries to sustainably change the payment lanscape. That is what I like the most about free software. It is built to last. +The thesis was constrained with a lot of insecurities for me. How does the process look? How can I implement the process? How does GNU Taler even work? How does Wallee work? In the end I am proud of what I accomplished during the thesis. I was able to understand the API and write a program which fulfills the properties needed for the withdrawal. Additionally I could learn a lot about designing an API. I am thankful that the Bern University of Applied Sciences supports free software projects like GNU Taler. It was a great opportunity for me as student to gain direct insights and work on a GNU project during my thesis. I remember that Prof. Dr. Christian Grothoff during an onsite session told me: "Nicht so kurzfristig denken!". This also shows the horizon of the project. It tries to sustainably change the payment landscape. That is what I like the most about free software. It is built to last. -The world of payment systems seems a bit chaotic to me. I think this is the result of a lot of different approaches developed at the same time for the same problem. There are standards but they mainly suggest things and do not enforce them. The technical documentation is obfuscated in big documents with a lot of boiler plate text. This makes it very hard to do the correct thing from my point of view. +The world of payment systems seems a bit chaotic to me. I think this is the result of a lot of different approaches developed at the same time for the same problem. There are standards but they mainly suggest things and do not enforce them. The technical documentation is obfuscated in big documents with a lot of boiler plate text. This makes it very hard to handle appropriately without finding out how a process works exactly by hand. For example to bring a Wallee transaction into the fulfill state (which allows the shipping of goods) you must settle the transaction and execeute the final balance. The documentation does not care about this. I had to write e-mails with Wallee to finally understand this. Even the people of Wallee messed up their own transaction states. diff --git a/docs/project.bib b/docs/project.bib @@ -111,6 +111,21 @@ urldate = {2024-05-11} } +@misc{rfc9106, + series = {Request for Comments}, + number = 9106, + howpublished = {RFC 9106}, + publisher = {RFC Editor}, + doi = {10.17487/RFC9106}, + url = {https://www.rfc-editor.org/info/rfc9106}, + author = {Alex Biryukov and Daniel Dinu and Dmitry Khovratovich and Simon Josefsson}, + title = {{Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications}}, + pagetotal = 21, + year = 2021, + month = sep, + abstract = {This document describes the Argon2 memory-hard function for password hashing and proof-of-work applications. We provide an implementer-oriented description with test vectors. The purpose is to simplify adoption of Argon2 for Internet protocols. This document is a product of the Crypto Forum Research Group (CFRG) in the IRTF.}, +} + @misc{rfc8959, series = {Request for Comments}, number = 8959, diff --git a/docs/thesis.pdf b/docs/thesis.pdf Binary files differ. diff --git a/simulation/README b/simulation/README @@ -0,0 +1,25 @@ +# C2EC Simulation + +This is a simulation testing the withdrawal flow supplied by C2EC. It can be seen as an integration testing environment. + +## Build + +IMPORTANT: You need at least Go v1.22! + +`go build .` + +## Configure + +Before configuring and running the simulation you must add the simulation provider +and terminal to your installation by using the CLI. Make sure to note the credentials +of the terminal, since they are needed during the configuration. The access token +won't be recoverable after the initial setup. + +Copy and configure the default configuration `config.yaml`. + +When using delays care must be taken because setting some of them to short will provoke EOF exceptions, because +time has exceeded. + +## Run + +`./c2ec-simulation [PATH-TO-CONFIG]` diff --git a/simulation/c2ec-simulation b/simulation/c2ec-simulation Binary files differ. diff --git a/simulation/config.yaml b/simulation/config.yaml @@ -2,6 +2,7 @@ disable-delays: false c2ec-base-url: "http://localhost:8080" parallel-withdrawals: 1 provider-backend-payment-delay: 1000 +amount: "CHF:10.05" terminal-accept-card-delay: 4000 terminal-provider: "Simulation" terminal-id: "1" diff --git a/simulation/main.go b/simulation/main.go @@ -93,6 +93,7 @@ type SimulationConfig struct { // simulates the terminal talking to its backend system and executing the payment. ProviderBackendPaymentDelay int `yaml:"provider-backend-payment-delay"` // simulates the user presenting his card to the terminal + Amount string `yaml:"amount"` TerminalAcceptCardDelay int `yaml:"terminal-accept-card-delay"` TerminalProvider string `yaml:"terminal-provider"` TerminalId string `yaml:"terminal-id"` diff --git a/simulation/sim-terminal.go b/simulation/sim-terminal.go @@ -50,8 +50,8 @@ func Terminal(in chan *SimulatedPhysicalInteraction, out chan *SimulatedPhysical } setupReq := &TerminalWithdrawalSetup{ - Amount: "CHF:10.50", - SuggestedAmount: "CHF:10.50", + Amount: CONFIG.Amount, + SuggestedAmount: "", ProviderTransactionId: "", TerminalFees: "", RequestUid: uuid.String(),