cashless2ecash

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

commit 75562a6d5d6044a059d63e376cfd6ec396284dd8
parent a5a3f4c27761a3551986a5fe265b221259b32995
Author: Joel-Haeberli <haebu@rubigen.ch>
Date:   Fri, 31 May 2024 15:23:47 +0200

fix: support required exchange config

Diffstat:
Mc2ec/api-bank-integration.go | 38++++++++++++++++++++------------------
Mc2ec/c2ec-config.conf | 4++++
Mc2ec/c2ec-config.yaml | 1+
Mc2ec/config.go | 7+++++++
Mdocs/content/results/discussion.tex | 3++-
Mdocs/thesis.pdf | 0
Msimulation/c2ec-simulation | 0
Msimulation/sim-terminal.go | 1+
Msimulation/sim-wallet.go | 19++++++++++---------
9 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/c2ec/api-bank-integration.go b/c2ec/api-bank-integration.go @@ -52,15 +52,16 @@ type BankWithdrawalOperationPostResponse struct { } type BankWithdrawalOperationStatus struct { - Status WithdrawalOperationStatus `json:"status"` - Amount string `json:"amount"` - CardFees string `json:"card_fees"` - SenderWire string `json:"sender_wire"` - WireTypes []string `json:"wire_types"` - ReservePubKey EddsaPublicKey `json:"selected_reserve_pub"` - Aborted bool `json:"aborted"` - SelectionDone bool `json:"selection_done"` - TransferDone bool `json:"transfer_done"` + Status WithdrawalOperationStatus `json:"status"` + Amount string `json:"amount"` + CardFees string `json:"card_fees"` + SenderWire string `json:"sender_wire"` + WireTypes []string `json:"wire_types"` + ReservePubKey EddsaPublicKey `json:"selected_reserve_pub"` + RequiredExchange string `json:"required_exchange"` + Aborted bool `json:"aborted"` + SelectionDone bool `json:"selection_done"` + TransferDone bool `json:"transfer_done"` } func bankIntegrationConfig(res http.ResponseWriter, req *http.Request) { @@ -386,15 +387,16 @@ func formatWithdrawalOrErrorStatus(w *Withdrawal) ([]byte, int) { return nil, HTTP_INTERNAL_SERVER_ERROR } else { withdrawalStatusBytes, err := NewJsonCodec[BankWithdrawalOperationStatus]().EncodeToBytes(&BankWithdrawalOperationStatus{ - Status: w.WithdrawalStatus, - Amount: FormatAmount(amount, CONFIG.Server.CurrencyFractionDigits), - CardFees: FormatAmount(fees, CONFIG.Server.CurrencyFractionDigits), - SenderWire: fmt.Sprintf("payto://%s/%d", operator.PaytoTargetType, w.ProviderTransactionId), - WireTypes: []string{operator.PaytoTargetType}, - ReservePubKey: EddsaPublicKey((encodeCrock(w.ReservePubKey))), - Aborted: w.WithdrawalStatus == ABORTED, - SelectionDone: w.WithdrawalStatus == SELECTED, - TransferDone: w.WithdrawalStatus == CONFIRMED, + Status: w.WithdrawalStatus, + Amount: FormatAmount(amount, CONFIG.Server.CurrencyFractionDigits), + CardFees: FormatAmount(fees, CONFIG.Server.CurrencyFractionDigits), + SenderWire: fmt.Sprintf("payto://%s/%d", operator.PaytoTargetType, w.ProviderTransactionId), + WireTypes: []string{operator.PaytoTargetType}, + ReservePubKey: EddsaPublicKey((encodeCrock(w.ReservePubKey))), + RequiredExchange: CONFIG.Server.ExchangeBaseUrl, + Aborted: w.WithdrawalStatus == ABORTED, + SelectionDone: w.WithdrawalStatus == SELECTED, + TransferDone: w.WithdrawalStatus == CONFIRMED, }) if err != nil { LogError("bank-integration-api", err) diff --git a/c2ec/c2ec-config.conf b/c2ec/c2ec-config.conf @@ -25,6 +25,10 @@ UNIXPATH_MODE = 660 # forced when PROD = true FAIL_ON_MISSING_ATTESTORS = false +# This exchange will be sent to the wallet in order +# to allow the withdrawal through it. +EXCHANGE_BASE_URL = "http://exchange.test.net" + # The account where the exchange receives payments # of the providers. Must be the same, in the providers # backend. diff --git a/c2ec/c2ec-config.yaml b/c2ec/c2ec-config.yaml @@ -6,6 +6,7 @@ c2ec: unix-socket-path: "c2ec.sock" unix-path-mode: 660 fail-on-missing-attestors: false # forced if prod=true + exchange-base-url: "http://exchange.test.net" credit-account: "payto://IBAN/CH50030202099498" # this account must be specified at the providers backends as well currency: "CHF" currency-fraction-digits: 2 diff --git a/c2ec/config.go b/c2ec/config.go @@ -23,6 +23,7 @@ type C2ECServerConfig struct { UnixSocketPath string `yaml:"unix-socket-path"` UnixPathMode int `yaml:"unix-path-mode"` StrictAttestors bool `yaml:"fail-on-missing-attestors"` + ExchangeBaseUrl string `yaml:"exchange-base-url"` CreditAccount string `yaml:"credit-account"` Currency string `yaml:"currency"` CurrencyFractionDigits int `yaml:"currency-fraction-digits"` @@ -168,6 +169,12 @@ func ParseIni(content []byte) (*C2ECConfig, error) { return nil, err } + value, err = s.GetKey("EXCHANGE_BASE_URL") + if err != nil { + return nil, err + } + cfg.Server.ExchangeBaseUrl = value.String() + value, err = s.GetKey("EXCHANGE_ACCOUNT") if err != nil { return nil, err diff --git a/docs/content/results/discussion.tex b/docs/content/results/discussion.tex @@ -8,7 +8,7 @@ The implementation of the existing Bank-Integration and Wire-Gateway API were a A challenge which was encountered during the implementation of the terminal application and the C2EC component, was the concurrency of processes. To make the withdrawal flow as easy and useful as possible to the user, a lot of tasks need to be covered in the background and run in parallel. This added the technical requirement to decouple steps and leverage retries to increase the robustness of the process. -Towards the end of the implementation it became obvious that a simple authorization was not enough to imitate the real time feeling of the withdrawal. Other Requests were necessary to do so. To findout which requests needed to be filed against the Wallee backend some investigation had to be made. The documentation does explain which states exists in Wallee's transaction scheme but it does not explain, which operation do trigger the transition of one state to another. This made the investigation somewhat cumbersome. Also the integration of the backend needed more investigation than I thought. +Towards the end of the implementation it became obvious that a simple authorization was not enough to imitate the real time feeling of the withdrawal. Other requests were necessary to do so. To findout which requests needed to be filed against the Wallee backend some investigation had to be made. The documentation does explain which states exists in Wallee's transaction scheme but does not explain, which operation must be triggered to transition states. This made the investigation somewhat cumbersome. Also the integration of the backend needed more investigation than I thought. For the analysis of the security of the system I was happy to find STRIDE which gave me some boundaries and guided me through the process. I found it hard to identify real threats and not loosing time about threats which were out of scope. In the end I think the solution is quite secure in terms of money. Of course you can steal terminals and wreck the nerves of the terminal operators but you won't be able to somehow manipulate the payment process which will allow you to @@ -27,6 +27,7 @@ C2EC introduces new ways to access digital cash using GNU Taler. Due to the shor \subsection{Improvements} \begin{enumerate} + \item Wallet integration: the integration of the wallet needs to be further tested \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. diff --git a/docs/thesis.pdf b/docs/thesis.pdf Binary files differ. diff --git a/simulation/c2ec-simulation b/simulation/c2ec-simulation Binary files differ. diff --git a/simulation/sim-terminal.go b/simulation/sim-terminal.go @@ -130,6 +130,7 @@ func Terminal(in chan *SimulatedPhysicalInteraction, out chan *SimulatedPhysical return } + fmt.Printf("TERMINAL: wallet should use exchange=%s\n", response.RequiredExchange) awaitSelection <- response }() diff --git a/simulation/sim-wallet.go b/simulation/sim-wallet.go @@ -173,13 +173,14 @@ type BankWithdrawalOperationPostResponse struct { } type BankWithdrawalOperationStatus struct { - Status WithdrawalOperationStatus `json:"status"` - Amount string `json:"amount"` - CardFees string `json:"card_fees"` - SenderWire string `json:"sender_wire"` - WireTypes []string `json:"wire_types"` - ReservePubKey EddsaPublicKey `json:"selected_reserve_pub"` - Aborted bool `json:"aborted"` - SelectionDone bool `json:"selection_done"` - TransferDone bool `json:"transfer_done"` + Status WithdrawalOperationStatus `json:"status"` + Amount string `json:"amount"` + CardFees string `json:"card_fees"` + SenderWire string `json:"sender_wire"` + WireTypes []string `json:"wire_types"` + ReservePubKey EddsaPublicKey `json:"selected_reserve_pub"` + RequiredExchange string `json:"required_exchange"` + Aborted bool `json:"aborted"` + SelectionDone bool `json:"selection_done"` + TransferDone bool `json:"transfer_done"` }