JJ: Description from the destination commit:

+ test disable auditor

JJ: Description from source commit:
+ wire + drain
This commit is contained in:
swrup 2026-02-25 20:12:13 +01:00
parent 05cfa7a5b1
commit f2d1fba932
9 changed files with 386 additions and 193 deletions

View file

@ -624,44 +624,6 @@ module GlobalFees = struct
|> finish |> finish
end end
module WireSetupMessage = struct
type t = {
payto_uri: string;
master_sig_wire: MasterWireDetails.t;
master_sig_add: MasterAddWire.t;
validity_start: Timestamp.t;
bank_label: string option;
priority: int option;
}
let jsont =
let make payto_uri master_sig_wire master_sig_add validity_start bank_label
priority =
{
payto_uri;
master_sig_wire;
master_sig_add;
validity_start;
bank_label;
priority;
}
in
let payto_uri v = v.payto_uri in
let master_sig_wire v = v.master_sig_wire in
let master_sig_add v = v.master_sig_add in
let validity_start v = v.validity_start in
let bank_label v = v.bank_label in
let priority v = v.priority in
map ~kind:"WireSetupMessage" make
|> mem "payto_uri" Jsont.string ~enc:payto_uri
|> mem "master_sig_wire" MasterWireDetails.jsont ~enc:master_sig_wire
|> mem "master_sig_add" MasterAddWire.jsont ~enc:master_sig_add
|> mem "validity_start" Timestamp.jsont ~enc:validity_start
|> mem "bank_label" (Jsont.option Jsont.string) ~enc:bank_label
|> mem "priority" (Jsont.option Jsont.int) ~enc:priority
|> finish
end
module WireTeardownMessage = struct module WireTeardownMessage = struct
type t = { type t = {
payto_uri: string; payto_uri: string;
@ -685,7 +647,7 @@ end
module DrainProfitsMessage = struct module DrainProfitsMessage = struct
type t = { type t = {
wtid: B32.t; wtid: Bytes32.t;
debit_account_section: string; debit_account_section: string;
credit_payto_uri: string; credit_payto_uri: string;
date: Timestamp.t; date: Timestamp.t;
@ -1137,6 +1099,61 @@ module AccountRestriction = struct
|> finish |> finish
end end
module WireSetupMessage = struct
type t = {
payto_uri: string;
master_sig_wire: MasterWireDetails.t;
master_sig_add: MasterAddWire.t;
conversion_url: string option;
credit_restrictions: AccountRestriction.t list;
debit_restrictions: AccountRestriction.t list;
validity_start: Timestamp.t;
bank_label: string option;
priority: int option;
}
let jsont =
let make payto_uri master_sig_wire master_sig_add conversion_url
credit_restrictions debit_restrictions validity_start bank_label
priority =
{
payto_uri;
master_sig_wire;
master_sig_add;
conversion_url;
credit_restrictions;
debit_restrictions;
validity_start;
bank_label;
priority;
}
in
let payto_uri v = v.payto_uri in
let master_sig_wire v = v.master_sig_wire in
let master_sig_add v = v.master_sig_add in
let conversion_url v = v.conversion_url in
let credit_restrictions v = v.credit_restrictions in
let debit_restrictions v = v.debit_restrictions in
let validity_start v = v.validity_start in
let bank_label v = v.bank_label in
let priority v = v.priority in
map ~kind:"WireSetupMessage" make
|> mem "payto_uri" Jsont.string ~enc:payto_uri
|> mem "master_sig_wire" MasterWireDetails.jsont ~enc:master_sig_wire
|> mem "master_sig_add" MasterAddWire.jsont ~enc:master_sig_add
|> mem "conversion_url" (Jsont.option Jsont.string) ~enc:conversion_url
|> mem "credit_restrictions"
(Jsont.list AccountRestriction.jsont)
~enc:credit_restrictions
|> mem "debit_restrictions"
(Jsont.list AccountRestriction.jsont)
~enc:debit_restrictions
|> mem "validity_start" Timestamp.jsont ~enc:validity_start
|> mem "bank_label" (Jsont.option Jsont.string) ~enc:bank_label
|> mem "priority" (Jsont.option Jsont.int) ~enc:priority
|> finish
end
module ExchangeWireAccount = struct module ExchangeWireAccount = struct
type t = { type t = {
payto_uri: string; payto_uri: string;

19
src/auditor.ml Normal file
View file

@ -0,0 +1,19 @@
type t = {
auditor_pub: Crypto.EddsaPublicKey.t;
auditor_url: string;
auditor_name: string;
last_change: Timestamp.t;
is_active: bool;
}
let of_setup_message
Api.AuditorSetupMessage.
{ auditor_url; auditor_name; auditor_pub; master_sig= _; validity_start }
=
{
auditor_url;
auditor_name;
auditor_pub;
last_change= validity_start;
is_active= true;
}

View file

@ -153,24 +153,22 @@ module Auditors = struct
h_auditor_url= Hash.Cstring.H64.hash auditor_url; h_auditor_url= Hash.Cstring.H64.hash auditor_url;
} }
(* TODO monotonic time *)
let do_ ~db_conn v = let do_ ~db_conn v =
let auditor_pub = v.AuditorSetupMessage.auditor_pub in let auditor_pub = v.AuditorSetupMessage.auditor_pub in
let validity_start = v.AuditorSetupMessage.validity_start in let validity_start = v.AuditorSetupMessage.validity_start in
let* last_date_opt = let* opt = Pg.find_auditor db_conn auditor_pub |> unwrap_err_caqti in
Pg.get_auditor_timestamp db_conn auditor_pub |> unwrap_err_caqti match opt with
in
match last_date_opt with
| None -> | None ->
let+ () = Pg.insert_auditor db_conn v |> unwrap_err_caqti in let auditor = Auditor.of_setup_message v in
let+ () = Pg.update_auditor db_conn auditor |> unwrap_err_caqti in
Logs.info (fun m -> m "enabled auditor"); Logs.info (fun m -> m "enabled auditor");
() ()
| Some last_date -> | Some auditor ->
if Timestamp.compare last_date validity_start > 0 then if Timestamp.compare auditor.last_change validity_start > 0 then
Error Error
"database has more recent auditor data for this auditor public key" "database has more recent auditor data for this auditor public key"
else else
let+ () = Pg.update_auditor db_conn v |> unwrap_err_caqti in let+ () = Pg.update_auditor db_conn auditor |> unwrap_err_caqti in
Logs.info (fun m -> m "updated auditor"); Logs.info (fun m -> m "updated auditor");
() ()
@ -198,26 +196,36 @@ module Auditors_disable = struct
let do_ ~db_conn auditor_pub let do_ ~db_conn auditor_pub
AuditorTeardownMessage.{ master_sig= _; validity_end } = AuditorTeardownMessage.{ master_sig= _; validity_end } =
let* last_date_opt = let* opt = Pg.find_auditor db_conn auditor_pub |> unwrap_err_caqti in
Pg.get_auditor_timestamp db_conn auditor_pub |> unwrap_err_caqti match opt with
in
match last_date_opt with
| None -> Error "auditor not found" | None -> Error "auditor not found"
| Some last_date -> | Some auditor -> (
if Timestamp.compare last_date validity_end > 0 then match Timestamp.compare auditor.last_change validity_end > 0 with
Error | true ->
"database has more recent auditor data for this auditor public key" Error
else "database has more recent auditor data for this auditor public \
let+ () = key"
Pg.disable_auditor db_conn ~auditor_pub ~change_date:validity_end | false -> (
|> unwrap_err_caqti match auditor.is_active with
in | false ->
() Logs.info (fun m -> m "auditor was already revoked");
Ok ()
| true ->
let auditor =
{ auditor with last_change= validity_end; is_active= false }
in
let+ () =
Pg.update_auditor db_conn auditor |> unwrap_err_caqti
in
Logs.info (fun m ->
m "revoked auditor `%s`"
(Crypto.EddsaPublicKey.to_b32 auditor_pub));
()))
let jsont = AuditorTeardownMessage.jsont let jsont = AuditorTeardownMessage.jsont
let f req auditor_pub server _env = let f req auditor_pub server _env =
Logs.info (fun m -> m "POST /management/auditors/$AUDITOR_PUB/revoke/"); Logs.info (fun m -> m "POST /management/auditors/$AUDITOR_PUB/disable/");
let keys = Vif.Server.device Devices.keys server in let keys = Vif.Server.device Devices.keys server in
let db_conn = Vif.Server.device Devices.db_connection server in let db_conn = Vif.Server.device Devices.db_connection server in
let res = let res =
@ -367,22 +375,37 @@ module Wire = struct
payto_uri; payto_uri;
master_sig_wire; master_sig_wire;
master_sig_add; master_sig_add;
conversion_url;
credit_restrictions;
debit_restrictions;
validity_start; validity_start;
bank_label= _; bank_label= _;
priority= _; priority= _;
} = } =
(* TODO are those read from payto_uri? *) (* TODO wire
let conversion_url = "" in hash over json, hash over string option? *)
let credit_restrictions = "" in let* () =
let debit_restrictions = "" in match (credit_restrictions, debit_restrictions) with
| [], [] -> Ok ()
| _ ->
Fmt.error
"wire setup: credit_restrictions and debit_restrictions are not \
supported"
in
let h_wire_details = Hash.FullPaytoHash.hash payto_uri in
let h_conversion_url =
Hash.Cstring.H64.hash ((* ?? *) Option.value ~default:"" conversion_url)
in
let h_credit_restrictions = Hash.Cstring.H64.hash "" in
let h_debit_restrictions = Hash.Cstring.H64.hash "" in
let* () = let* () =
let open Signatures.MasterWireDetails in let open Signatures.MasterWireDetails in
verify Config.master_public_key master_sig_wire verify Config.master_public_key master_sig_wire
{ {
h_wire_details= FullPaytoHash.hash payto_uri; h_wire_details;
h_conversion_url= Hash.Cstring.H64.hash conversion_url; h_conversion_url;
h_credit_restrictions= Hash.Cstring.H64.hash credit_restrictions; h_credit_restrictions;
h_debit_restrictions= Hash.Cstring.H64.hash debit_restrictions; h_debit_restrictions;
} }
in in
let* () = let* () =
@ -390,38 +413,56 @@ module Wire = struct
verify Config.master_public_key master_sig_add verify Config.master_public_key master_sig_add
{ {
start_date= validity_start; start_date= validity_start;
h_wire= FullPaytoHash.hash payto_uri; h_wire= h_wire_details;
h_conversion_url= Hash.Cstring.H64.hash conversion_url; h_conversion_url;
h_credit_restrictions= Hash.Cstring.H64.hash credit_restrictions; h_credit_restrictions;
h_debit_restrictions= Hash.Cstring.H64.hash debit_restrictions; h_debit_restrictions;
} }
in in
Ok () Ok ()
let do_ ~db_conn v = let do_ ~db_conn
let* last_change_opt = WireSetupMessage.
let payto_uri = v.WireSetupMessage.payto_uri in {
Pg.get_wire_timestamp db_conn ~payto_uri |> unwrap_err_caqti payto_uri;
in master_sig_wire;
match last_change_opt with master_sig_add= _;
| Some _ -> Error "wire already setup" conversion_url;
credit_restrictions;
debit_restrictions;
validity_start;
bank_label;
priority;
} =
let* opt = Pg.find_wire db_conn ~payto_uri |> unwrap_err_caqti in
match opt with
| Some wire ->
let+ () =
Pg.update_wire db_conn ~is_active:true ~last_change:validity_start
wire
|> unwrap_err_caqti
in
Logs.info (fun m -> m "updated wire method");
()
| None -> | None ->
let r = let wire =
ExchangeWireAccount. ExchangeWireAccount.
{ {
payto_uri= v.payto_uri; payto_uri;
conversion_url= None; conversion_url;
debit_restrictions= []; credit_restrictions;
credit_restrictions= []; debit_restrictions;
master_sig= v.master_sig_wire; master_sig= master_sig_wire;
bank_label= v.bank_label; bank_label;
priority= v.priority; priority;
} }
in in
let+ () = let+ () =
Pg.insert_wire db_conn ~last_change:v.validity_start r Pg.update_wire db_conn ~is_active:true ~last_change:validity_start
wire
|> unwrap_err_caqti |> unwrap_err_caqti
in in
Logs.info (fun m -> m "added wire method");
() ()
let jsont = WireSetupMessage.jsont let jsont = WireSetupMessage.jsont
@ -448,15 +489,15 @@ module Wire_disable = struct
let do_ ~db_conn let do_ ~db_conn
WireTeardownMessage.{ payto_uri; master_sig_del= _; validity_end } = WireTeardownMessage.{ payto_uri; master_sig_del= _; validity_end } =
let* last_change_opt = let* opt = Pg.find_wire db_conn ~payto_uri |> unwrap_err_caqti in
Pg.get_wire_timestamp db_conn ~payto_uri |> unwrap_err_caqti match opt with
in
match last_change_opt with
| None -> Error "wire not found" | None -> Error "wire not found"
| Some _ -> | Some wire ->
let+ () = let+ () =
Pg.disable_wire db_conn ~payto_uri ~validity_end |> unwrap_err_caqti Pg.update_wire db_conn ~is_active:false ~last_change:validity_end wire
|> unwrap_err_caqti
in in
Logs.info (fun m -> m "disabled wire method");
() ()
let jsont = WireTeardownMessage.jsont let jsont = WireTeardownMessage.jsont
@ -496,8 +537,18 @@ module Drain = struct
} }
let do_ ~db_conn v = let do_ ~db_conn v =
let+ () = Pg.insert_drain_profit db_conn v |> unwrap_err_caqti in let* opt =
() Pg.find_drain_profit db_conn v.DrainProfitsMessage.wtid
|> unwrap_err_caqti
in
match opt with
| Some _ ->
Logs.info (fun m -> m "drain profit message already added to database");
Ok ()
| None ->
let+ () = Pg.insert_drain_profit db_conn v |> unwrap_err_caqti in
Logs.info (fun m -> m "added drain profit message to database");
()
let jsont = DrainProfitsMessage.jsont let jsont = DrainProfitsMessage.jsont

View file

@ -115,43 +115,23 @@ let insert_signkey_revocation =
fun (module Conn : CONN) exchange_pub master_sig -> fun (module Conn : CONN) exchange_pub master_sig ->
Conn.exec req (exchange_pub, master_sig) Conn.exec req (exchange_pub, master_sig)
let get_auditor_timestamp = let find_auditor =
let req = let req =
Caqti_type.(eddsa_pub ->? time) Caqti_type.(eddsa_pub ->? auditor)
"SELECT last_change FROM auditors WHERE auditor_pub=$1" "SELECT auditor_pub, auditor_name, auditor_url, last_change, is_active \
FROM auditors WHERE auditor_pub=$1"
in in
fun (module Conn : CONN) auditor_pub -> Conn.find_opt req auditor_pub fun (module Conn : CONN) auditor_pub -> Conn.find_opt req auditor_pub
let insert_auditor =
let req =
Caqti_type.(t4 eddsa_pub string string time ->. unit)
"INSERT INTO auditors (auditor_pub, auditor_name, auditor_url, \
is_active, last_change) VALUES ($1, $2, $3, true, $4)"
in
fun (module Conn : CONN)
AuditorSetupMessage.
{ auditor_url; auditor_name; auditor_pub; master_sig= _; validity_start }
-> Conn.exec req (auditor_pub, auditor_name, auditor_url, validity_start)
let update_auditor = let update_auditor =
let req = let req =
Caqti_type.(t5 eddsa_pub string string bool time ->. unit) Caqti_type.(auditor ->. unit)
"UPDATE auditors SET auditor_url=$2, auditor_name=$3, is_active=$4, \ "INSERT INTO auditors (auditor_pub, auditor_name, auditor_url, \
last_change=$5 WHERE auditor_pub=$1" last_change, is_active) VALUES ($1, $2, $3, $4, $5) ON CONFLICT \
(auditor_pub) DO UPDATE SET auditor_name=$2, auditor_url=$3, \
last_change=$4, is_active=$5"
in in
fun (module Conn : CONN) fun (module Conn : CONN) auditor -> Conn.exec req auditor
AuditorSetupMessage.
{ auditor_url; auditor_name; auditor_pub; master_sig= _; validity_start }
-> Conn.exec req (auditor_pub, auditor_url, auditor_name, true, validity_start)
let disable_auditor =
let req =
Caqti_type.(t5 eddsa_pub string string bool time ->. unit)
"UPDATE auditors SET auditor_url=$2, auditor_name=$3, is_active=$4, \
last_change=$5 WHERE auditor_pub=$1"
in
fun (module Conn : CONN) ~auditor_pub ~change_date ->
Conn.exec req (auditor_pub, "", "", false, change_date)
let insert_auditor_denom_sig = let insert_auditor_denom_sig =
let req = let req =
@ -167,6 +147,7 @@ let insert_auditor_denom_sig =
Conn.exec req (auditor_pub, h_denom_pub, auditor_sig) Conn.exec req (auditor_pub, h_denom_pub, auditor_sig)
(* todo auditors (* todo auditors
map to Auditor.t record
maybe check that url and name are unique/same for each auditor_pub maybe check that url and name are unique/same for each auditor_pub
and do the ht logic out of pg.ml? *) and do the ht logic out of pg.ml? *)
(* this does not return auditors that are not auditing any denom *) (* this does not return auditors that are not auditing any denom *)
@ -274,46 +255,30 @@ let insert_global_fees =
in in
fun (module Conn : CONN) v -> Conn.exec req v fun (module Conn : CONN) v -> Conn.exec req v
let get_wire_timestamp = let find_wire =
let req = let req =
Caqti_type.(payto_uri ->? time) Caqti_type.(payto_uri ->? exchange_wire_account)
"SELECT last_change FROM wire_accounts WHERE payto_uri=$1" "SELECT payto_uri, conversion_url, debit_restrictions::TEXT, \
credit_restrictions::TEXT, master_sig, bank_label, priority FROM \
wire_accounts WHERE payto_uri=$1"
in in
fun (module Conn : CONN) ~payto_uri -> Conn.find_opt req payto_uri fun (module Conn : CONN) ~payto_uri -> Conn.find_opt req payto_uri
let insert_wire = let update_wire =
let req = let req =
Caqti_type.(t3 exchange_wire_account bool time ->. unit) Caqti_type.(t3 exchange_wire_account bool time ->. unit)
"INSERT INTO wire_accounts (payto_uri, conversion_url, \ "INSERT INTO wire_accounts (payto_uri, conversion_url, \
credit_restrictions, debit_restrictions, master_sig, bank_label, \ credit_restrictions, debit_restrictions, master_sig, bank_label, \
priority, is_active, last_change) VALUES \ priority, is_active, last_change) VALUES \
($1,$2,$3::TEXT::JSONB,$4::TEXT::JSONB,$5,$6,$7,true,$8)" ($1,$2,$3::TEXT::JSONB,$4::TEXT::JSONB,$5,$6,$7,$8,$9) ON CONFLICT \
in (payto_uri) DO UPDATE SET conversion_url=$2, \
fun (module Conn : CONN) ~last_change v -> credit_restrictions=$3::TEXT::JSONB, \
let is_active = true in debit_restrictions=$4::TEXT::JSONB, master_sig=$5, bank_label=$6, \
Conn.exec req (v, is_active, last_change) priority=$7, is_active=$8, last_change=$9"
let update_wire =
let req =
Caqti_type.(t3 exchange_wire_account bool time ->. unit)
"UPDATE wire_accounts SET conversion_url=$2, \
debit_restrictions=$3::TEXT::JSONB, \
credit_restrictions=$4::TEXT::JSONB, master_sig=$5, bank_label=$6, \
priority=$7, is_active=$8, last_change=$9 WHERE payto_uri=$1"
in in
fun (module Conn : CONN) ~is_active ~last_change v -> fun (module Conn : CONN) ~is_active ~last_change v ->
Conn.exec req (v, is_active, last_change) Conn.exec req (v, is_active, last_change)
let disable_wire =
let req =
Caqti_type.(t2 payto_uri time ->. unit)
"UPDATE wire_accounts SET conversion_url=NULL, debit_restrictions=NULL, \
credit_restrictions=NULL, master_sig=NULL, bank_label=NULL, \
priority=NULL, is_active=FALSE, last_change=$2 WHERE payto_uri=$1"
in
fun (module Conn : CONN) ~payto_uri ~validity_end ->
Conn.exec req (payto_uri, validity_end)
let get_wire_accounts = let get_wire_accounts =
let req = let req =
Caqti_type.(unit ->* exchange_wire_account) Caqti_type.(unit ->* exchange_wire_account)
@ -323,11 +288,20 @@ let get_wire_accounts =
in in
fun (module Conn : CONN) () -> Conn.collect_list req () fun (module Conn : CONN) () -> Conn.collect_list req ()
let find_drain_profit =
let req =
Caqti_type.(octets ->? drain_profit_message)
"SELECT wtid, account_section, payto_uri, trigger_date, (amount).*, \
master_sig FROM profit_drains WHERE wtid=$1"
in
fun (module Conn : CONN) wtid -> Conn.find_opt req wtid
let insert_drain_profit = let insert_drain_profit =
let req = let req =
Caqti_type.(drain_profit_message ->. unit) Caqti_type.(drain_profit_message ->. unit)
"INSERT INTO profit_drains (wtid, account_section, payto_uri, \ "INSERT INTO profit_drains (wtid, account_section, payto_uri, \
trigger_date, amount, master_sig) VALUES ($1, $2, $3, $4, ($5,$6), $7)" trigger_date, amount, master_sig) VALUES ($1::BYTEA, $2, $3, $4, \
($5,$6), $7)"
in in
fun (module Conn : CONN) v -> Conn.exec req v fun (module Conn : CONN) v -> Conn.exec req v

View file

@ -24,7 +24,6 @@ let eddsa_sig = EddsaSignature.caqti
(* todo: enum type for wire_method? *) (* todo: enum type for wire_method? *)
let wire_method = Caqti_type.string let wire_method = Caqti_type.string
let payto_uri = Caqti_type.string let payto_uri = Caqti_type.string
let b32 = B32.caqti
include struct include struct
(* alias for hash *) (* alias for hash *)
@ -266,7 +265,7 @@ let drain_profit_message =
amount; amount;
master_sig; master_sig;
}) })
Caqti_type.(t6 b32 string string time amount master_sig) Caqti_type.(t6 octets string string time amount master_sig)
let aml_officer_setup = let aml_officer_setup =
let master_sig = Signatures.MasterAmlOfficerStatus.caqti in let master_sig = Signatures.MasterAmlOfficerStatus.caqti in
@ -351,3 +350,14 @@ let exchange_partner_setup =
wad_fee; wad_fee;
}) })
Caqti_type.(t7 eddsa_pub time time time_span amount master_sig string) Caqti_type.(t7 eddsa_pub time time time_span amount master_sig string)
let auditor =
let open Auditor in
Caqti_type.custom
~encode:(fun
{ auditor_pub; auditor_url; auditor_name; last_change; is_active } ->
Ok (auditor_pub, auditor_url, auditor_name, last_change, is_active))
~decode:(fun
(auditor_pub, auditor_url, auditor_name, last_change, is_active) ->
Ok { auditor_pub; auditor_url; auditor_name; last_change; is_active })
Caqti_type.(t5 eddsa_pub string string time bool)

View file

@ -46,12 +46,16 @@ offline_tool enable-auditor \
--output $b \ --output $b \
--auditor_url "auditor.example.com" \ --auditor_url "auditor.example.com" \
--auditor_name "auditor example" \ --auditor_name "auditor example" \
--auditor_pub $auditor_pub \ --auditor_pub $auditor_pub
--validity_start 0
offline_tool upload --input $b --url $url"/management/auditors" offline_tool upload --input $b --url $url"/management/auditors"
echo "[OK] /management/auditors" echo "[OK] /management/auditors"
# todo test disable auditor offline_tool disable-auditor \
--master_key $master_key \
--output $b \
--auditor_pub $auditor_pub
offline_tool upload --input $b --url $url"/management/auditors/"$auditor_pub"/disable"
echo "[OK] /management/auditors/\$AUDITOR_PUB/disable"
offline_tool wire-fee \ offline_tool wire-fee \
--master_key $master_key \ --master_key $master_key \
@ -78,8 +82,31 @@ offline_tool global-fees \
offline_tool upload --input $b --url $url"/management/global-fees" offline_tool upload --input $b --url $url"/management/global-fees"
echo "[OK] /management/global-fees" echo "[OK] /management/global-fees"
# todo test enable wire offline_tool enable-wire \
# todo test disable wire --master_key $master_key \
# todo test drain --output $b \
# todo test aml-officer --payto_uri "" \
# todo test partners --bank_label "" \
--priority 4
offline_tool upload --input $b --url $url"/management/wire"
echo "[OK] /management/wire"
offline_tool disable-wire \
--master_key $master_key \
--output $b \
--payto_uri ""
offline_tool upload --input $b --url $url"/management/wire/disable"
echo "[OK] /management/wire/disable"
# wtid (after base32 decode) must be 32bytes
wtid="000G40R40M30E209185GR38E1W8124GK2GAHC5RR34D1P70X3RFG"
offline_tool drain \
--master_key $master_key \
--output $b \
--debit_account_section "" \
--credit_payto_uri "" \
--wtid $wtid \
--date 0 \
--amount $zero_euro
offline_tool upload --input $b --url $url"/management/drain"
echo "[OK] /management/drain"

View file

@ -2,7 +2,7 @@
(public_name offline) (public_name offline)
(name offline) (name offline)
(modules offline offline_impl) (modules offline offline_impl)
(libraries cmdliner bos fmt mirage-crypto ptime mte vif)) (libraries cmdliner bos fmt mirage-crypto mtime ptime mte vif))
(executable (executable
(public_name gen_registry_files) (public_name gen_registry_files)

View file

@ -1,13 +1,6 @@
(* TODO (* not done:
all management operations: /management/aml-officers (for /aml)
/management/wire /management/partners (for /wads) *)
/management/wire/disable
/management/aml-officers
-> /aml
/management/partners
-> /wads *)
open Cmdliner open Cmdliner
open Cmdliner.Term.Syntax open Cmdliner.Term.Syntax
open Offline_impl open Offline_impl
@ -199,35 +192,26 @@ let enable_auditor_cmd =
let auditor_pub = let auditor_pub =
Arg.(required & opt (some eddsa_pub) None & info [ "auditor_pub" ]) Arg.(required & opt (some eddsa_pub) None & info [ "auditor_pub" ])
in in
let validity_start =
Arg.(required & opt (some timestamp) None & info [ "validity_start" ])
in
Cmd.make (Cmd.info "enable-auditor" ~doc) Cmd.make (Cmd.info "enable-auditor" ~doc)
@@ @@
let+ output = output let+ output = output
and+ master_key = master_key and+ master_key = master_key
and+ auditor_url = auditor_url and+ auditor_url = auditor_url
and+ auditor_name = auditor_name and+ auditor_name = auditor_name
and+ auditor_pub = auditor_pub and+ auditor_pub = auditor_pub in
and+ validity_start = validity_start in
enable_auditor ~output ~master_key ~auditor_url ~auditor_name ~auditor_pub enable_auditor ~output ~master_key ~auditor_url ~auditor_name ~auditor_pub
~validity_start
let disable_auditor_cmd = let disable_auditor_cmd =
let doc = "Disable auditor." in let doc = "Disable auditor." in
let auditor_pub = let auditor_pub =
Arg.(required & opt (some eddsa_pub) None & info [ "auditor_pub" ]) Arg.(required & opt (some eddsa_pub) None & info [ "auditor_pub" ])
in in
let validity_end =
Arg.(required & opt (some timestamp) None & info [ "validity_end" ])
in
Cmd.make (Cmd.info "disable-auditor" ~doc) Cmd.make (Cmd.info "disable-auditor" ~doc)
@@ @@
let+ output = output let+ output = output
and+ master_key = master_key and+ master_key = master_key
and+ auditor_pub = auditor_pub and+ auditor_pub = auditor_pub in
and+ validity_end = validity_end in disable_auditor ~output ~master_key ~auditor_pub
disable_auditor ~output ~master_key ~auditor_pub ~validity_end
let wire_fee_cmd = let wire_fee_cmd =
let doc = "Provides wire fee configuration." in let doc = "Provides wire fee configuration." in
@ -301,6 +285,36 @@ let global_fees_cmd =
~account_fee ~purse_fee ~history_expiration ~purse_account_limit ~account_fee ~purse_fee ~history_expiration ~purse_account_limit
~purse_timeout ~purse_timeout
let enable_wire_cmd =
let doc = "Enable wire method." in
let payto_uri =
Arg.(required & opt (some string) None & info [ "payto_uri" ])
in
let bank_label =
Arg.(value & opt (some string) None & info [ "bank_label" ])
in
let priority = Arg.(value & opt (some int) None & info [ "priority" ]) in
Cmd.make (Cmd.info "enable-wire" ~doc)
@@
let+ output = output
and+ master_key = master_key
and+ payto_uri = payto_uri
and+ bank_label = bank_label
and+ priority = priority in
enable_wire ~output ~master_key ~payto_uri ~bank_label ~priority
let disable_wire_cmd =
let doc = "Disable wire method." in
let payto_uri =
Arg.(required & opt (some string) None & info [ "payto_uri" ])
in
Cmd.make (Cmd.info "disable-wire" ~doc)
@@
let+ output = output
and+ master_key = master_key
and+ payto_uri = payto_uri in
disable_wire ~output ~master_key ~payto_uri
let drain_cmd = let drain_cmd =
let doc = let doc =
"Drain profits from the exchange. The actual drain requires running the \ "Drain profits from the exchange. The actual drain requires running the \
@ -344,7 +358,10 @@ let cli =
disable_auditor_cmd; disable_auditor_cmd;
wire_fee_cmd; wire_fee_cmd;
global_fees_cmd; global_fees_cmd;
enable_wire_cmd;
disable_wire_cmd;
drain_cmd; drain_cmd;
(* - *)
test_hash64_cmd; test_hash64_cmd;
] ]

View file

@ -275,9 +275,10 @@ let global_fees ~output ~master_key ~start_date ~end_date ~history_fee
let* () = write_file output s in let* () = write_file output s in
Ok () Ok ()
let enable_auditor ~output ~master_key ~auditor_url ~auditor_name ~auditor_pub let enable_auditor ~output ~master_key ~auditor_url ~auditor_name ~auditor_pub =
~validity_start =
let* key = read_master_key_file master_key in let* key = read_master_key_file master_key in
let ns = Mtime_clock.now_ns () in
let validity_start = Timestamp.of_s @@ Int64.unsigned_div ns 1_000_000_000L in
let master_sig = let master_sig =
let open Signatures.MasterAddAuditor in let open Signatures.MasterAddAuditor in
signf (EddsaSignature.sign ~key) signf (EddsaSignature.sign ~key)
@ -295,8 +296,10 @@ let enable_auditor ~output ~master_key ~auditor_url ~auditor_name ~auditor_pub
let* () = write_file output s in let* () = write_file output s in
Ok () Ok ()
let disable_auditor ~output ~master_key ~auditor_pub ~validity_end = let disable_auditor ~output ~master_key ~auditor_pub =
let* key = read_master_key_file master_key in let* key = read_master_key_file master_key in
let ns = Mtime_clock.now_ns () in
let validity_end = Timestamp.of_s @@ Int64.unsigned_div ns 1_000_000_000L in
let master_sig = let master_sig =
let open Signatures.MasterDelAuditor in let open Signatures.MasterDelAuditor in
signf (EddsaSignature.sign ~key) { end_date= validity_end; auditor_pub } signf (EddsaSignature.sign ~key) { end_date= validity_end; auditor_pub }
@ -335,9 +338,84 @@ let wire_fee ~output ~master_key ~wire_method ~fee_start ~fee_end ~closing_fee
let* () = write_file output s in let* () = write_file output s in
Ok () Ok ()
(* TODO wire
hash over json, hash over string option?
~conversion_url ~credit_restrictions ~debit_restrictions *)
let enable_wire ~output ~master_key ~payto_uri ~bank_label ~priority =
let* key = read_master_key_file master_key in
let ns = Mtime_clock.now_ns () in
let validity_start = Timestamp.of_s @@ Int64.unsigned_div ns 1_000_000_000L in
let h_wire_details = Hash.FullPaytoHash.hash payto_uri in
let conversion_url = None in
let credit_restrictions = [] in
let debit_restrictions = [] in
let h_conversion_url =
Hash.Cstring.H64.hash ((* ?? *) Option.value ~default:"" conversion_url)
in
let h_credit_restrictions = Hash.Cstring.H64.hash "" in
let h_debit_restrictions = Hash.Cstring.H64.hash "" in
let master_sig_wire =
let open Signatures.MasterWireDetails in
signf (EddsaSignature.sign ~key)
{
h_wire_details;
h_conversion_url;
h_credit_restrictions;
h_debit_restrictions;
}
in
let master_sig_add =
let open Signatures.MasterAddWire in
signf (EddsaSignature.sign ~key)
{
start_date= validity_start;
h_wire= h_wire_details;
h_conversion_url;
h_credit_restrictions;
h_debit_restrictions;
}
in
let v =
Api.WireSetupMessage.
{
master_sig_wire;
master_sig_add;
payto_uri;
conversion_url;
credit_restrictions;
debit_restrictions;
validity_start;
bank_label;
priority;
}
in
let* s = Api.encode Api.WireSetupMessage.jsont v in
let* () = write_file output s in
Ok ()
let disable_wire ~output ~master_key ~payto_uri =
let* key = read_master_key_file master_key in
let ns = Mtime_clock.now_ns () in
let validity_end = Timestamp.of_s @@ Int64.unsigned_div ns 1_000_000_000L in
let h_wire = Hash.FullPaytoHash.hash payto_uri in
let master_sig_del =
let open Signatures.MasterDelWire in
signf (EddsaSignature.sign ~key) { end_date= validity_end; h_wire }
in
let v = Api.WireTeardownMessage.{ payto_uri; master_sig_del; validity_end } in
let* s = Api.encode Api.WireTeardownMessage.jsont v in
let* () = write_file output s in
Ok ()
let drain ~output ~master_key ~debit_account_section ~credit_payto_uri ~wtid let drain ~output ~master_key ~debit_account_section ~credit_payto_uri ~wtid
~date ~amount = ~date ~amount =
let* key = read_master_key_file master_key in let* key = read_master_key_file master_key in
let* () =
match String.length wtid = 32 with
| false -> Error "invalid wtid: must be 32 bytes"
| true -> Ok ()
in
let master_sig = let master_sig =
let open Signatures.MasterDrainProfit in let open Signatures.MasterDrainProfit in
signf (EddsaSignature.sign ~key) signf (EddsaSignature.sign ~key)