mte/src/config.ml

229 lines
7.2 KiB
OCaml
Raw Normal View History

2025-11-20 18:38:01 +01:00
open Parse_config
2025-10-13 11:48:29 +02:00
2026-02-10 11:59:51 +01:00
let config_filename = "mte.conf"
let secrets_dir = Fpath.v "secrets"
2026-02-17 09:30:20 +01:00
let secmod_dir = Fpath.(secrets_dir / "secmod")
2026-02-10 11:59:51 +01:00
2026-02-18 23:08:55 +01:00
(* TODO config *)
let secmod_eddsa_dir = Fpath.(secrets_dir / "secmod_eddsa")
2025-11-20 18:38:01 +01:00
let config_data =
2026-02-10 11:59:51 +01:00
match Assets_crunch.read config_filename with
| None -> fail "static file not found: `%s`" config_filename
2025-11-20 18:38:01 +01:00
| Some data ->
let v = Config_section.parse data in
2025-11-20 18:38:01 +01:00
v
2025-10-13 11:48:29 +02:00
module Exchange = struct
2025-11-20 18:38:01 +01:00
let get_opt field = get_opt config_data ~section:"exchange" ~field
let get field = get config_data ~section:"exchange" ~field
2025-10-13 11:48:29 +02:00
2025-11-20 18:38:01 +01:00
(* - *)
let currency = (* todo: constraint on currency string *) get "currency"
let currency_round_unit = get "currency_round_unit" |> amount
let db = get "db" |> const_value "postgres"
let attribute_encryption_key = get "attribute_encryption_key"
let port = get "port" |> int
let bind_to = get "bind_to"
let master_public_key = get "master_public_key" |> ed25519
2026-01-19 20:54:39 +01:00
(* TODO Defaults to 0.0 if not specified. *)
2025-11-20 18:38:01 +01:00
let stefan_abs = get "stefan_abs" |> amount
let stefan_log = get "stefan_log" |> amount
2026-01-19 20:54:39 +01:00
let stefan_lin =
get_opt "stefan_lin" |> Option.map float |> Option.value ~default:0.0
2025-10-13 11:48:29 +02:00
2025-11-20 18:38:01 +01:00
let aggregator_idle_sleep_interval =
get "aggregator_idle_sleep_interval" |> duration
let closer_idle_sleep_interval = get "closer_idle_sleep_interval" |> duration
let transfer_idle_sleep_interval =
get "transfer_idle_sleep_interval" |> duration
let wirewatch_idle_sleep_interval =
get "wirewatch_idle_sleep_interval" |> duration
let signkey_legal_duration = get "signkey_legal_duration" |> duration
let max_keys_caching = get "max_keys_caching" |> duration
let enable_kyc = get "enable_kyc" |> yes_no
2026-02-12 11:25:57 +01:00
let terms_etag = get "terms_etag" |> etag
let privacy_etag = get "privacy_etag" |> etag
2025-12-14 23:34:25 +01:00
let base_url = get "base_url"
let shopping_url = get_opt "shopping_url"
let open_banking_gateway_url = get_opt "open_banking_gateway_url"
let bank_compliance_language = get_opt "bank_compliance_language"
let aml_spa_dialect = get_opt "aml_spa_dialect"
let toplevel_redirect_url = get_opt "toplevel_redirect_url"
let tiny_amount = get_opt "tiny_amount" |> Option.map amount
2025-10-13 11:48:29 +02:00
2025-11-20 18:38:01 +01:00
(* not implemented or not relevant to MTE:
let max_requests = get "max_requests" |> int
aggregator_shard_size
serve
unixpath
unixpath_mode
terms_dir
privacy_dir *)
2025-10-13 11:48:29 +02:00
end
2025-11-11 03:12:12 +01:00
module Exchangedb = struct
2025-11-20 18:38:01 +01:00
let get field = get config_data ~section:"exchangedb" ~field
(* - *)
let idle_reserve_expiration_time =
get "idle_reserve_expiration_time" |> duration
let legal_reserve_expiration_time =
get "legal_reserve_expiration_time" |> duration
let aggregator_shift = get "aggregator_shift" |> duration
let max_aml_program_runtime = get "max_aml_program_runtime" |> duration
let default_purse_limit = get "default_purse_limit" |> int
2025-11-11 03:12:12 +01:00
end
module Exchangedb_postgres = struct
let config =
2025-11-20 18:38:01 +01:00
get config_data ~section:"exchangedb-postgres" ~field:"config" |> uri
2025-11-11 03:12:12 +01:00
end
2025-11-20 18:38:01 +01:00
module Currency = struct
type t = {
enabled: [ `YES | `NO ];
code: string;
name: string;
fractional_input_digits: int;
fractional_normal_digits: int;
fractional_trailing_zero_digits: int;
alt_unit_names: (int * string) list;
}
let currency_sections =
List.filter
(fun v -> String.starts_with ~prefix:"currency-" v.header)
config_data
let parse_currency section =
let get field = get config_data ~section:section.header ~field in
2025-10-16 08:23:40 +02:00
{
2025-11-20 18:38:01 +01:00
enabled= get "enabled" |> yes_no;
code= get "code";
name= get "name";
fractional_input_digits= get "fractional_input_digits" |> int;
fractional_normal_digits= get "fractional_normal_digits" |> int;
fractional_trailing_zero_digits=
get "fractional_trailing_zero_digits" |> int;
2025-12-22 19:20:32 +01:00
alt_unit_names=
get "alt_unit_names" |> Alt_unit_names.decode |> Parse_config.unwrap;
2025-10-16 08:23:40 +02:00
}
2025-10-13 11:48:29 +02:00
2025-11-20 18:38:01 +01:00
let all_currencies = List.map parse_currency currency_sections
(* I think the exchange only handle one currency *)
let v =
match
List.find_opt (fun v -> v.code = Exchange.currency) all_currencies
with
| None ->
2025-11-29 19:36:35 +01:00
fail "section `[currency-%s]` not found, currency `%s` is not defined"
Exchange.currency Exchange.currency
2025-11-20 18:38:01 +01:00
| Some v -> (
match v.enabled = `YES with
2025-11-29 19:36:35 +01:00
| false -> fail "currency `%s` is not enabled" Exchange.currency
2025-11-20 18:38:01 +01:00
| true -> v)
end
2025-10-16 10:18:22 +02:00
2025-11-20 18:38:01 +01:00
module Coin = struct
type t = {
section_name: string;
value: Amount.t;
duration_withdraw: Time.Relative.t;
duration_spend: Time.Relative.t;
duration_legal: Time.Relative.t;
2025-11-20 18:38:01 +01:00
fee_withdraw: Amount.t;
fee_deposit: Amount.t;
fee_refresh: Amount.t;
fee_refund: Amount.t;
cipher: [ (* `CS |*) `RSA ];
rsa_keysize: int; (* : int option (only if `RSA) *)
age_restricted: [ (*`YES|*) `NO ];
}
let coin_sections =
List.filter
(fun v ->
(* note: here its a '_' not '-' *)
String.starts_with ~prefix:"coin_" v.header)
config_data
let parse_coin section =
let get field = get config_data ~section:section.header ~field in
let section_name =
String.sub section.header 5 (String.length section.header - 5)
in
{
section_name;
value= get "value" |> amount;
duration_withdraw= get "duration_withdraw" |> duration;
duration_spend= get "duration_spend" |> duration;
duration_legal= get "duration_legal" |> duration;
fee_withdraw= get "fee_withdraw" |> amount;
fee_deposit= get "fee_deposit" |> amount;
fee_refresh= get "fee_refresh" |> amount;
fee_refund= get "fee_refund" |> amount;
cipher= (get "cipher" |> const_value "RSA" |> fun _s -> `RSA);
rsa_keysize= get "rsa_keysize" |> int;
age_restricted=
( get "age_restricted" |> yes_no |> function
| `NO -> `NO
2025-11-29 19:36:35 +01:00
| `YES -> fail "`age_restricted = YES` is not supported" );
2025-11-20 18:38:01 +01:00
}
let all_coins = List.map parse_coin coin_sections
end
module Exchange_secmod_rsa = struct
let get field =
let section = "taler-exchange-secmod-" ^ "rsa" in
get config_data ~section ~field
let lookahead_sign = get "lookahead_sign" |> duration
let overlap_duration = get "overlap_duration" |> duration
(* not relevant: sm_priv_key key_dir unixpath *)
end
module Exchange_secmod_eddsa = struct
let get field =
let section = "taler-exchange-secmod-" ^ "eddsa" in
get config_data ~section ~field
let lookahead_sign = get "lookahead_sign" |> duration
let overlap_duration = get "overlap_duration" |> duration
2026-02-18 23:08:55 +01:00
let duration = get "duration" |> duration
(* TODO config
LOOKAHEAD_SIGN
How long do we generate denomination and signing keys ahead of time?
OVERLAP_DURATION
How much should validity periods for coins overlap? Should be long enough to avoid problems with wallets picking one key and then due to network latency another key being valid. The DURATION_WITHDRAW period must be longer than this value.
DURATION
For how long should EdDSA keys be valid for signing?
SM_PRIV_KEY
Where should the security module store its long-term private key?
KEY_DIR
Where should the security module store the private keys it manages?
UNIXPATH
On which path should the security module listen for signing requests?
*)
2025-11-20 18:38:01 +01:00
end
2025-11-20 22:14:45 +01:00
(* -- *)
include Exchange