cash2ecash

cash2ecash: cash acceptor that issues digital cash (experimental)
Log | Files | Refs | README | LICENSE

commit 285b884edfab8d63d9fd8ffd5a2118a9c3728ae0
parent 123c4a344533f83ce5d5933404bf6e4a82715573
Author: Tellenbach Reto <tellr1@bfh.ch>
Date:   Sun, 31 May 2026 21:29:37 +0200

[ref] thinker_TalerAPI: moved to src and added license consistently

Diffstat:
ACMakeLists.txt | 10++++++++++
ACMakePresets.json | 15+++++++++++++++
MREADME.md | 8++++++--
Asrc/CMakeLists.txt | 13+++++++++++++
Asrc/error_codes.h | 46++++++++++++++++++++++++++++++++++++++++++++++
Asrc/lib/CMakeLists.txt | 12++++++++++++
Asrc/lib/bank_api_curl_defaults.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/lib/bank_api_curl_defaults.h | 40++++++++++++++++++++++++++++++++++++++++
Asrc/lib/bank_api_get_config.c | 319+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/lib/bank_api_get_config.h | 214+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/taler-digitizer.c | 288+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/taler/taler_digitizer_service.h | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/taler_digitizer_util.h | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ataler-digitizer.conf | 34++++++++++++++++++++++++++++++++++
14 files changed, 1226 insertions(+), 2 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -0,0 +1,10 @@ +# Project Config +cmake_minimum_required(VERSION 3.13) +project(taler-digitizer LANGUAGES C ) + +# Langage requirements +set(CMAKE_C_STANDARD 17) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) + +add_subdirectory(src) diff --git a/CMakePresets.json b/CMakePresets.json @@ -0,0 +1,14 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "debug", + "binaryDir": "${sourceDir}/build/debug", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "CMAKE_C_FLAGS": "-Wall -Wextra -g" + } + } + ] +} +\ No newline at end of file diff --git a/README.md b/README.md @@ -2,4 +2,8 @@ This software is meant for use on a system which is designed, to allow users to topup their wallet with cash. **Note: -This software is currently under developpement. Do not attempt to use it on a system with real customers!** -\ No newline at end of file +This software is currently under developpement. Do not attempt to use it on a system with real customers!** + +# Building + +`export TALER_DIGITIZER_PREFIX=<installation_path>` +\ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt @@ -0,0 +1,12 @@ +# Add files and libs +add_executable(taler-digitizer taler-digitizer.c) + +find_package(PkgConfig REQUIRED) + + +add_subdirectory(lib) + +# Manage libs +target_link_libraries(taler-digitizer + PRIVATE bank +) +\ No newline at end of file diff --git a/src/error_codes.h b/src/error_codes.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER cash2ecash + Copyright (C) 2026 GNUnet e.V. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +/** + * @file error_codes.h + * @brief error codes for Cash Digitizer + * @author Reto Tellenbach + */ + +#ifndef ERROR_CODES_H +#define ERROR_CODES_H + +/** + * Taler client Cash Digitizer errors. + */ +enum DIGITIZER_ErrorCode +{ + /** + * indicate success (no error) + */ + DIGITIZER_EC_NONE = 0, + + /** + * non specific fail + */ + DIGITIZER_EC_GENERIC = 1, +}; + +#endif +\ No newline at end of file diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt @@ -0,0 +1,11 @@ +# Add files +add_library(bank bank_api_get_config.c bank_api_curl_defaults.c) + +find_package(CURL REQUIRED) +pkg_check_modules(GNUNET REQUIRED gnunetutil) +pkg_check_modules(LIBMICROHTTPD REQUIRED libmicrohttpd) + +target_link_libraries(bank + PUBLIC CURL::libcurl gnunetutil talerutil microhttpd + PRIVATE talercurl talerjson gnunetutil gnunetcurl gnunetjson jansson +) +\ No newline at end of file diff --git a/src/lib/bank_api_curl_defaults.c b/src/lib/bank_api_curl_defaults.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2014-2018, 2021 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/bank_api_curl_defaults.c + * @brief curl easy handle defaults + * @author Florian Dold + */ +#include "taler/taler_curl_lib.h" +#include "bank_api_curl_defaults.h" + + +CURL * +TALER_BANK_curl_easy_get_ (const char *url) +{ + CURL *eh; + + eh = curl_easy_init (); + if (NULL == eh) + { + GNUNET_break (0); + return NULL; + } + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_URL, + url)); + TALER_curl_set_secure_redirect_policy (eh, + url); + /* Enable compression (using whatever curl likes), see + https://curl.se/libcurl/c/CURLOPT_ACCEPT_ENCODING.html */ + GNUNET_break (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_ACCEPT_ENCODING, + "")); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_TCP_FASTOPEN, + 1L)); + return eh; +} diff --git a/src/lib/bank_api_curl_defaults.h b/src/lib/bank_api_curl_defaults.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + Copyright (C) 2014-2018 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ + +/** + * @file lib/bank_api_curl_defaults.h + * @brief curl easy handle defaults + * @author Florian Dold + */ + +#ifndef _TALER_CURL_DEFAULTS_H +#define _TALER_CURL_DEFAULTS_H + + +#include <gnunet/gnunet_curl_lib.h> + + +/** + * Get a curl handle with the right defaults + * for the interaction with the lib. + * + * @param url URL to query + */ +CURL * +TALER_BANK_curl_easy_get_ (const char *url); + +#endif /* _TALER_CURL_DEFAULTS_H */ diff --git a/src/lib/bank_api_get_config.c b/src/lib/bank_api_get_config.c @@ -0,0 +1,319 @@ +/* + This file is part of TALER cash2ecash + Copyright (C) 2026 GNUnet e.V. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +/** + * @file bank_api_get_config.c + * @brief Implementation of the GET /config request of the bank's HTTP API + * @author Reto Tellenbach + */ + +#include <microhttpd.h> +#include "bank_api_get_config.h" +#include "bank_api_curl_defaults.h" +#include "taler/taler_json_lib.h" + +/** + * Which revision of the Taler core-bank protocol is implemented + * by this library? Used to determine compatibility. + */ +#define TALER_PROTOCOL_CURRENT 12 + +/** + * How many revisions back are we compatible to? + */ +#define TALER_PROTOCOL_AGE 0 + + +/** + * Log error related to CURL operations. + * + * @param type log level + * @param function which function failed to run + * @param code what was the curl error code + */ +#define CURL_STRERROR(type, function, code) \ + GNUNET_log (type, \ + "Curl function `%s' has failed at `%s:%d' with error: %s", \ + function, __FILE__, __LINE__, curl_easy_strerror (code)); + + +/** + * Handle for the get config request. + */ +struct TALER_BANK_GetConfigHandle +{ + /** + * The context of this handle + */ + struct GNUNET_CURL_Context *ctx; + + /** + * Function to call with the , + * NULL if this has already been done. + */ + TALER_BANK_ConfigCallback config_cb; + + /** + * Closure to pass to + */ + void *config_cb_cls; + + /** + * Data for the request to get the /config of a bank, + * NULL once we are past stage #MHS_INIT. + */ + struct GNUNET_CURL_Job *job; + + /** + * The whole request line + */ + char *job_url; +}; + + +/** + * Decode the JSON in @a resp_obj from the /config response + * + * @param[in] resp_obj JSON object to parse + * @param[in,out] vi where to store the results we decoded + * @param[out] vc where to store config compatibility data + * @return #TALER_EC_NONE on success + */ +static enum TALER_ErrorCode +decode_config_json (const json_t *resp_obj, + struct TALER_BANK_ConfigInformation *vi, + enum TALER_BANK_VersionCompatibility *vc) +{ + struct TALER_JSON_ProtocolVersion pv; + const char *ver; + bool bank_name_missing; + + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_version ("version", + &pv), + GNUNET_JSON_spec_string ("version", + &ver), + GNUNET_JSON_spec_string ("currency", + &vi->currency), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("bank_name", + &vi->bank_name), + &bank_name_missing), + GNUNET_JSON_spec_end () + }; + + if (JSON_OBJECT != json_typeof (resp_obj)) + { + GNUNET_break_op (0); + return TALER_EC_GENERIC_JSON_INVALID; + } + if (GNUNET_OK != + GNUNET_JSON_parse (resp_obj, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return TALER_EC_GENERIC_JSON_INVALID; + } + + /* Set default fot optional values */ + if (bank_name_missing) + { + vi->bank_name = GNUNET_strdup("Taler Bank"); + } + + /* Version comparison */ + vi->version = ver; + *vc = TALER_BANK_VC_MATCH; + if (TALER_PROTOCOL_CURRENT < pv.current) + { + *vc |= TALER_BANK_VC_NEWER; + if (TALER_PROTOCOL_CURRENT < pv.current - pv.age) + *vc |= TALER_BANK_VC_INCOMPATIBLE; + } + if (TALER_PROTOCOL_CURRENT > pv.current) + { + *vc |= TALER_BANK_VC_OLDER; + if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > pv.current) + *vc |= TALER_BANK_VC_INCOMPATIBLE; + } + + struct GNUNET_JSON_Specification spec2[] = { + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_amount ("min_wire_transfer_amount", + vi->currency, + &vi->min_wire_transfer_amount), + NULL), + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_amount ("max_wire_transfer_amount", + vi->currency, + &vi->max_wire_transfer_amount), + NULL), + TALER_JSON_spec_currency_specification ("currency_specification", + vi->currency, + &vi->currency_specification), + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_amount("wire_transfer_fees", + vi->currency, + &vi->wire_transfer_fees), + NULL), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (resp_obj, + spec2, + NULL, NULL)) + { + GNUNET_break_op (0); + return TALER_EC_GENERIC_JSON_INVALID; + } + + return TALER_EC_NONE; +} + + +/** + * Callback used when http reply arived to a /config request. + * + * @param cls the `struct TALER_BANK_GetConfigHandle` + * @param response_code HTTP response code or 0 on error + * @param gresp_obj JSON result, NULL on error, must be a `const json_t *` + */ +static void +response_cb(void *cls, + long response_code, + const void *gresp_obj) +{ + struct TALER_BANK_GetConfigHandle *bank = cls; + const json_t *resp_obj = gresp_obj; + + struct TALER_BANK_ConfigResponse cr = { + .hr.response = resp_obj, + .hr.http_status = (unsigned int)response_code + }; + + bank->job = NULL; //job was successfull, curl job cancel not needed anymore in cleanup + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received config from URL `%s' with status %ld.\n", + bank->job_url, + response_code); + + switch (response_code) + { + case 0: + GNUNET_break_op (0); + cr.hr.ec = TALER_EC_INVALID; + break; + case MHD_HTTP_OK: + if (NULL == resp_obj) + { + GNUNET_break_op (0); + cr.hr.http_status = 0; + cr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; + } + cr.hr.ec = decode_config_json (resp_obj, + &cr.details.ok.configi, + &cr.details.ok.version_compa); + if (TALER_EC_NONE != cr.hr.ec) + { + GNUNET_break_op (0); + cr.hr.http_status = 0; + break; + } + break; + case MHD_HTTP_INTERNAL_SERVER_ERROR: + cr.hr.ec = TALER_JSON_get_error_code (resp_obj); + cr.hr.hint = TALER_JSON_get_error_hint (resp_obj); + break; + default: + cr.hr.ec = TALER_JSON_get_error_code (resp_obj); + cr.hr.hint = TALER_JSON_get_error_hint (resp_obj); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u/%d\n", + (unsigned int) response_code, + (int) cr.hr.ec); + break; + } + + bank->config_cb (bank->config_cb_cls, &cr); + TALER_BANK_get_config_cancel(bank); +} + + +struct TALER_BANK_GetConfigHandle * +TALER_BANK_get_config ( struct GNUNET_CURL_Context *ctx, + const char *url, + TALER_BANK_ConfigCallback config_cb, + void *config_cb_cls) +{ + struct TALER_BANK_GetConfigHandle *bank; + CURL *eh; + + bank = GNUNET_new(struct TALER_BANK_GetConfigHandle); + bank->config_cb = config_cb; + bank->config_cb_cls = config_cb_cls; + bank->ctx = ctx; + bank->job_url = TALER_url_join(url,"config",NULL); + if(NULL == bank->job_url) + { + GNUNET_break(0); + GNUNET_free(bank); + return NULL; + } + + GNUNET_log( GNUNET_ERROR_TYPE_INFO, + "Requesting bank config with URL `%s'.\n", + bank->job_url); + eh = TALER_BANK_curl_easy_get_(bank->job_url); + if(NULL == eh) + { + GNUNET_break(0); + TALER_BANK_get_config_cancel(bank); + return NULL; + } + bank->job = GNUNET_CURL_job_add(bank->ctx, + eh, + &response_cb, + bank); + if(NULL == bank->job) + { + GNUNET_break(0); + TALER_BANK_get_config_cancel(bank); + return NULL; + } + + return bank; +} + + + +void +TALER_BANK_get_config_cancel ( struct TALER_BANK_GetConfigHandle *bank) +{ + if(NULL != bank->job) + { + GNUNET_CURL_job_cancel(bank->job); + bank->job = NULL; + } + GNUNET_free(bank->job_url); + GNUNET_free(bank); +} + diff --git a/src/lib/bank_api_get_config.h b/src/lib/bank_api_get_config.h @@ -0,0 +1,213 @@ +/* + This file is part of TALER cash2ecash + Copyright (C) 2026 GNUnet e.V. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +/** + * @file bank_api_get_config.h + * @brief Implementation of the GET /config request of the bank's HTTP API + * @author Reto Tellenbach + */ + +#ifndef BANK_API_GET_CONFIG_H +#define BANK_API_GET_CONFIG_H + +#include "../taler/taler_digitizer_service.h" + + +/** + * @brief Information we get from the bank about itself. and is needed for the digitizer + */ +struct TALER_BANK_ConfigInformation +{ + + /** + * Supported Taler protocol version by the bank. + * String in the format current:revision:age using the + * semantics of GNU libtool. See + * https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning + */ + const char *version; + + /** + * Currency used by this bank. + */ + const char *currency; + + /** + * Minimum wire transfer amount allowed. Only applies to bank transactions and withdrawals. + */ + struct TALER_Amount min_wire_transfer_amount; + + /** + * Maximum wire transfer amount allowed. Only applies to bank transactions and withdrawals. + */ + struct TALER_Amount max_wire_transfer_amount; + + /** + * How the bank SPA should render this currency. + */ + struct TALER_CurrencySpecification currency_specification; + + /** + * Bank display name to be used in user interfaces. + * For consistency use "Taler Bank" if missing. + */ + const char *bank_name; + + /** + * Wire transfer execution fees. Only applies to bank transactions and withdrawals. + */ + struct TALER_Amount wire_transfer_fees; + + // /** + // * Name of api + // */ + // const char *api_name; + + + // /** + // * Advertised base URL to use when you sharing an URL with another program. + // */ + // const char *base_url; + + // /** If 'true' the server provides local currency conversion support + // * If 'false' some parts of the API are not supported and return 501 + // */ + // const bool allow_conversion; + + // /** If 'true' anyone can register + // * If 'false' only admin can + // */ + // const bool allow_registrations; + + // /** + // * If 'true' account can delete themselves + // * If 'false' only admin can delete accounts + // */ + // const bool allow_deletions; + + // /** + // * If 'true' anyone can edit their name + // * If 'false' only admin can + // */ + // const bool allow_edit_name; + + // /** + // * If 'true' anyone can edit their cashout account + // * If 'false' only admin can + // */ + // const bool allow_edit_cashout_payto_uri; + + // /** + // * Default debt limit for newly created accounts + // */ + // const struct TALER_AmountNBO default_debit_threshold; + + // /** + // * Stand in string for the TAN channel. Not used in the callbacks + // * when used needs to be addapted + // * TAN channels supported by the server + // */ + // const char *supported_tan_channels; + + // /** + // * Wire transfer type supported by the bank. + // * Defaults to 'iban' is missing + // */ + // const char *wire_type; + +}; + +/** + * Response details for a config request + */ +struct TALER_BANK_ConfigResponse +{ + + /** + * HTTP response + */ + struct TALER_BANK_HttpResponse hr; + + /** + * Details returned depending on the @e http_status. + */ + union + { + + /** + * Details if status was request was succesfull + */ + struct + { + + /** + * Protocol compatibility evaluation. + */ + enum TALER_BANK_VersionCompatibility version_compa; + + /** + * Config data returned by /config. + */ + struct TALER_BANK_ConfigInformation configi; + + } ok; + + } details; + +}; + + +/** + * Function called with information about the bank. + * + * @param cls closure + * @param vr response data + */ +typedef void +(*TALER_BANK_ConfigCallback) ( + void *cls, + const struct TALER_BANK_ConfigResponse *vr); + + +/** + * Handle for the get config request. + */ +struct TALER_BANK_GetConfigHandle; + + +/** + * Obtain config inforamtion about the connected Bank + * @param ctx + * @param url + * @return NULL on failure + */ +struct TALER_BANK_GetConfigHandle * +TALER_BANK_get_config ( struct GNUNET_CURL_Context *ctx, + const char *url, + TALER_BANK_ConfigCallback config_cb, + void *config_cb_cls); + +/** + * Cancel config request. Handles the GNUNet canelation. + */ +void +TALER_BANK_get_config_cancel ( struct TALER_BANK_GetConfigHandle *bank); + + +#endif //BANK_API_GET_CONFIG_H +\ No newline at end of file diff --git a/src/taler-digitizer.c b/src/taler-digitizer.c @@ -0,0 +1,287 @@ +/* + This file is part of TALER cash2ecash + Copyright (C) 2026 GNUnet e.V. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +/** + * @file taler-digitizer.c + * @brief runs the logic for the embeded Cash Digitizer machine + * @author Reto Tellenbach + */ + + +#include <gnunet/gnunet_util_lib.h> +#include "taler_digitizer_util.h" +#include "lib/bank_api_get_config.h" + + +/** + * Time unit for PERSON_WITHDRAL_PERIOD config. + * Normal in Days but can be changed for testing + */ +#define DIGITIZER_PERSON_WITHDRAWL_PERIOD_TIME_UNIT GNUNET_TIME_UNIT_DAYS + +/** + * Global return value + */ +static int global_ret; + +/** + * Global option '-d' to enable diagnostics set. + */ +static int enable_diagnostics; + +/** + * Taler Backend url read from configuration file + */ +static char *cfg_backend_base_url; + +/** + * Currency read from configuration file + */ +static char *cfg_currency; + +/** + * Minimum balance read from configuration file + */ +static unsigned long long cfg_backend_min_balance; + +/** + * Per-person withdrawal limit read from configuration file + */ +static unsigned long long cfg_person_withdrawllimit; + +/** + * Per-person withdrawal period read from configuration file + */ +static struct GNUNET_TIME_Relative cfg_person_withdrawl_period; + +/** + * KYC functionality flag read from configuration file + */ +static enum GNUNET_GenericReturnValue cfg_kyc_functionality; + +/** + * Handle to the context for interacting with the bank. + */ +static struct GNUNET_CURL_Context *curl_ctx; + +/** + * Scheduler context for running the @e ctx. + */ +static struct GNUNET_CURL_RescheduleContext *reschedule_ctx; + +/** + * Handle for get_config request + */ +static struct TALER_BANK_GetConfigHandle *get_config_handle; + + +static void +on_config_received (void *cls, + const struct TALER_BANK_ConfigResponse *vr) +{ + (void) cls; + (void) vr; + + get_config_handle = NULL; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Config Callback\n"); + + GNUNET_SCHEDULER_shutdown (); +} + + +/** + * @brief Cleanup when no task is scheduled anymore + * + * @param cls closure + */ +static void +shutdown_task (void *cls) +{ + (void)cls; + + if (NULL != get_config_handle) + { + TALER_BANK_get_config_cancel (get_config_handle); + get_config_handle = NULL; + } + if (NULL != reschedule_ctx) + { + GNUNET_CURL_gnunet_rc_destroy (reschedule_ctx); + reschedule_ctx = NULL; + } + if (NULL != curl_ctx) + { + GNUNET_CURL_fini (curl_ctx); + curl_ctx = NULL; + } +} + + +/** + * @brief Start the application + * + * @param cls closure + * @param args arguments left + * @param cfgfile config file name + * @param cfg handle for the configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + (void) cls; + (void) args; + (void) cfgfile; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Parse Configuration\n"); + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "taler-digitizer", + "BACKEND_BASE_URL", + &cfg_backend_base_url)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "taler-digitizer", + "BACKEND_BASE_URL"); + global_ret = EXIT_FAILURE; + return; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "taler-digitizer", + "CURRENCY", + &cfg_currency)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "taler-digitizer", + "CURRENCY"); + global_ret = EXIT_FAILURE; + return; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + "taler-digitizer", + "BANK_MIN_BALANCE", + &cfg_backend_min_balance)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "taler-digitizer", + "BANK_MIN_BALANCE"); + global_ret = EXIT_FAILURE; + return; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + "taler-digitizer", + "PERSON_WITHDRAWLLIMIT", + &cfg_person_withdrawllimit)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "taler-digitizer", + "PERSON_WITHDRAWLLIMIT"); + global_ret = EXIT_FAILURE; + return; + } + + unsigned long long person_withdrawl_period_number; + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + "taler-digitizer", + "PERSON_WITHDRAL_PERIOD", + &person_withdrawl_period_number)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "taler-digitizer", + "PERSON_WITHDRAL_PERIOD"); + global_ret = EXIT_FAILURE; + return; + } + cfg_person_withdrawl_period = GNUNET_TIME_relative_multiply ( + DIGITIZER_PERSON_WITHDRAWL_PERIOD_TIME_UNIT, + person_withdrawl_period_number); + + cfg_kyc_functionality = GNUNET_CONFIGURATION_get_value_yesno (cfg, + "taler-digitizer", + "KYC_FUNCTIONALITY"); + if (GNUNET_SYSERR == cfg_kyc_functionality) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "taler-digitizer", + "KYC_FUNCTIONALITY"); + global_ret = EXIT_FAILURE; + return; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Config URL: %s\n", + cfg_backend_base_url); + + curl_ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &reschedule_ctx); + reschedule_ctx = GNUNET_CURL_gnunet_rc_create (curl_ctx); + + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); + + get_config_handle = TALER_BANK_get_config (curl_ctx, + cfg_backend_base_url, + &on_config_received, + NULL); + + + return; +} + + +int +main (int argc, + char *const *argv) +{ + int ret; + + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_option_flag ('d', + "enable-diagnostics", + "enable diagnostics for debuging", + &enable_diagnostics), + GNUNET_GETOPT_OPTION_END + }; + + ret = GNUNET_PROGRAM_run (TALER_DIGITIZER_project_data (), + argc, + argv, + "taler-digitizer", + "This is an application for the Cash Digitizer." + " It accepts cash and transfers it to the Taler Wallet.\n", + options, + &run, + NULL); + + if (GNUNET_NO == ret) + return 0; + if (GNUNET_OK != ret) + return 1; + return global_ret; +} +\ No newline at end of file diff --git a/src/taler/taler_digitizer_service.h b/src/taler/taler_digitizer_service.h @@ -0,0 +1,118 @@ +/* + This file is part of TALER cash2ecash + Copyright (C) 2026 GNUnet e.V. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +/** + * @file include/taler/taler_bank_service.h + * @brief C interface for taler libs used by the digitizer + * @author Reto Tellenbach + */ + +#ifndef _TALER_DIGITIZER_SERVICE_H +#define _TALER_DIGITIZER_SERVICE_H + + +#include <taler/taler_bank_service.h> +#include <taler/taler_util.h> +#include "../lib/bank_api_get_config.h" + +/** + * How compatible are the protocol version of the bank and this + * client? The bits (1,2,4) can be used to test if the auditor's + * version is incompatible, older or newer respectively. + */ +enum TALER_BANK_VersionCompatibility +{ + + /** + * The bank runs exactly the same protocol version. + */ + TALER_BANK_VC_MATCH = 0, + + /** + * The bank is too old or too new to be compatible with this + * implementation (bit) + */ + TALER_BANK_VC_INCOMPATIBLE = 1, + + /** + * The bank is older than this implementation (bit) + */ + TALER_BANK_VC_OLDER = 2, + + /** + * The bank is too old to be compatible with + * this implementation. + */ + TALER_BANK_VC_INCOMPATIBLE_OUTDATED + = TALER_BANK_VC_INCOMPATIBLE + | TALER_BANK_VC_OLDER, + + /** + * The bank is more recent than this implementation (bit). + */ + TALER_BANK_VC_NEWER = 4, + + /** + * The bank is too recent for this implementation. + */ + TALER_BANK_VC_INCOMPATIBLE_NEWER + = TALER_BANK_VC_INCOMPATIBLE + | TALER_BANK_VC_NEWER, + + /** + * We could not even parse the version data. + */ + TALER_BANK_VC_PROTOCOL_ERROR = 8 + +}; + + +/** + * General information about the HTTP response we obtained + * from the bank for a request. + */ +struct TALER_BANK_HttpResponse +{ + + /** + * Full response, NULL if body was not in JSON format. + */ + const json_t *response; + + /** + * Set to the human-readable 'hint' that is optionally + * provided by the exchange together with errors. NULL + * if no hint was provided or if there was no error. + */ + const char *hint; + + /** + * HTTP status code for the response. + */ + unsigned int http_status; + + /** + * Taler error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + +}; + + +#endif +\ No newline at end of file diff --git a/src/taler_digitizer_util.h b/src/taler_digitizer_util.h @@ -0,0 +1,56 @@ +/* + This file is part of TALER cash2ecash + Copyright (C) 2026 GNUnet e.V. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +/** + * @file taler-digitizer_util.h + * @brief Interface for common utility functions, and base project settings + * @author Reto Tellenbach + */ +#ifndef TALER_DIGITIZER_UTIL_H +#define TALER_DIGITIZER_UTIL_H + +#include <gnunet/gnunet_util_lib.h> + +/** + * Default project data. When shipping use a seperate os_installation.c which sets values at installation. + */ +static const struct GNUNET_OS_ProjectData digitizer_pd = { + .base_config_varname = "TALER_DIGITIZER_PREFIX", + .bug_email = "taler@lists.gnu.org", + .homepage = "http://www.gnu.org/s/taler/", + .config_file = "taler-digitizer.conf", + .user_config_file = "~/.config/taler-digitizer.conf", + .version = "0.1.0", + .is_gnu = 0, + .gettext_domain = NULL, + .gettext_path = NULL, +}; + +/** + * Return default project data. + */ +const struct GNUNET_OS_ProjectData * +TALER_DIGITIZER_project_data (void) +{ + return &digitizer_pd; +} + + + +#endif diff --git a/taler-digitizer.conf b/taler-digitizer.conf @@ -0,0 +1,34 @@ +[taler-digitizer] +BACKEND_BASE_URL = https://exchange.demo.taler.net/ +CURRENCY = KUDOS + +#BANK_ACCOUNT = sdflksdflsdkjf + +# Balance required to start a Transaction +BANK_MIN_BALANCE = 1000 + +# Withdrawl limitation per person, for a limited time period. +# This can only be enforced with KYC functionality +PERSON_WITHDRAWLLIMIT = 200 +PERSON_WITHDRAL_PERIOD = 10 + + +#BACKEND_AUTHORIZATION = Bearer secret-token:sandbox +KYC_FUNCTIONALITY = NO + +# Name of the framebuffer to use for the QR code. +FRAMEBUFFER_DEVICE = /dev/fb1 + +# Name of the backlight file for the framebuffer +FRAMEBUFFER_BACKLIGHT = /sys/class/backlight/soc:backlight/brightness + +[coin-acceptor] +ENABLE = YES +GPIO_CHIP = /dev/gpiochip0 +GPIO_PIN = 16 +bigest_denomination = 5 + + +[bill-acceptor] +ENABLE = NO +bigest_denomination = 100