228 lines
7.2 KiB
OCaml
228 lines
7.2 KiB
OCaml
open Parse_config
|
|
|
|
let config_filename = "mte.conf"
|
|
let secrets_dir = Fpath.v "secrets"
|
|
let secmod_dir = Fpath.(secrets_dir / "secmod")
|
|
|
|
(* TODO config *)
|
|
let secmod_eddsa_dir = Fpath.(secrets_dir / "secmod_eddsa")
|
|
|
|
let config_data =
|
|
match Assets_crunch.read config_filename with
|
|
| None -> fail "static file not found: `%s`" config_filename
|
|
| Some data ->
|
|
let v = Config_section.parse data in
|
|
v
|
|
|
|
module Exchange = struct
|
|
let get_opt field = get_opt config_data ~section:"exchange" ~field
|
|
let get field = get config_data ~section:"exchange" ~field
|
|
|
|
(* - *)
|
|
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
|
|
|
|
(* TODO Defaults to 0.0 if not specified. *)
|
|
let stefan_abs = get "stefan_abs" |> amount
|
|
let stefan_log = get "stefan_log" |> amount
|
|
|
|
let stefan_lin =
|
|
get_opt "stefan_lin" |> Option.map float |> Option.value ~default:0.0
|
|
|
|
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
|
|
let terms_etag = get "terms_etag" |> etag
|
|
let privacy_etag = get "privacy_etag" |> etag
|
|
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
|
|
|
|
(* 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 *)
|
|
end
|
|
|
|
module Exchangedb = struct
|
|
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
|
|
end
|
|
|
|
module Exchangedb_postgres = struct
|
|
let config =
|
|
get config_data ~section:"exchangedb-postgres" ~field:"config" |> uri
|
|
end
|
|
|
|
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
|
|
{
|
|
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;
|
|
alt_unit_names=
|
|
get "alt_unit_names" |> Alt_unit_names.decode |> Parse_config.unwrap;
|
|
}
|
|
|
|
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 ->
|
|
fail "section `[currency-%s]` not found, currency `%s` is not defined"
|
|
Exchange.currency Exchange.currency
|
|
| Some v -> (
|
|
match v.enabled = `YES with
|
|
| false -> fail "currency `%s` is not enabled" Exchange.currency
|
|
| true -> v)
|
|
end
|
|
|
|
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;
|
|
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
|
|
| `YES -> fail "`age_restricted = YES` is not supported" );
|
|
}
|
|
|
|
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
|
|
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?
|
|
*)
|
|
end
|
|
|
|
(* -- *)
|
|
include Exchange
|