From bccabcb1c037561da9ae0cedeee06acdfaf02606 Mon Sep 17 00:00:00 2001 From: Craig Everett Date: Mon, 26 May 2025 16:34:21 +0900 Subject: [PATCH 1/8] WIP: Configuration interface --- ebin/gajumine.app | 2 +- src/gajumine.erl | 2 +- src/gmc_con.erl | 287 +++++++++++----------------------------------- src/gmc_gui.erl | 117 ++++++++++++------- src/gmc_setup.erl | 4 +- src/gmc_sup.erl | 2 +- zomp.meta | 2 +- 7 files changed, 148 insertions(+), 268 deletions(-) diff --git a/ebin/gajumine.app b/ebin/gajumine.app index c6ebfdc..2fa06ad 100644 --- a/ebin/gajumine.app +++ b/ebin/gajumine.app @@ -3,6 +3,6 @@ {registered,[]}, {included_applications,[]}, {applications,[stdlib,kernel]}, - {vsn,"0.1.4"}, + {vsn,"0.2.0"}, {modules,[gajumine,gmc_con,gmc_gui,gmc_setup,gmc_sup]}, {mod,{gajumine,[]}}]}. diff --git a/src/gajumine.erl b/src/gajumine.erl index 1034a62..0385105 100644 --- a/src/gajumine.erl +++ b/src/gajumine.erl @@ -3,7 +3,7 @@ %%% @end -module(gajumine). --vsn("0.1.4"). +-vsn("0.2.0"). -behavior(application). -author("Craig Everett "). -copyright("Craig Everett "). diff --git a/src/gmc_con.erl b/src/gmc_con.erl index 1e9cf77..0739d43 100644 --- a/src/gmc_con.erl +++ b/src/gmc_con.erl @@ -3,14 +3,15 @@ %%% @end -module(gmc_con). --vsn("0.1.4"). +-vsn("0.2.0"). -author("Craig Everett "). -copyright("Craig Everett "). -license("GPL-3.0-or-later"). -behavior(gen_server). -export([start_stop/0, gajudesk/0]). --export([unlock/1, make_key/2, load_key/3, end_setup/0, bin_dir/0]). +-export([conf/0, conf/1]). +-export([bin_dir/0]). -export([network/0]). -export([start_link/0, stop/0]). -export([init/1, terminate/2, code_change/3, @@ -23,12 +24,14 @@ -record(s, - {version = 1 :: integer(), - window = none :: none | wx:wx_object(), - network = <<"testnet">> :: binary(), % <<"testnet">> | <<"mainnet">> - exec_dir = platform_dir() :: file:filename(), - key = none :: none | {blob, binary()} | #key{}, - pass = none :: none | binary()}). + {version = 1 :: integer(), + window = none :: none | wx:wx_object(), + network = <<"mainnet">> :: binary(), % <<"testnet">> | <<"mainnet">> + exec_dir = platform_dir() :: file:filename(), + acc = none :: none | binary(), + keys = [] :: [], + mem_limit = 3550722201 :: pos_integer(), + prefs = #{} :: #{}}). -type state() :: #s{}. @@ -48,34 +51,22 @@ gajudesk() -> gen_server:cast(?MODULE, gajudesk). --spec unlock(Phrase) -> ok - when Phrase :: string(). +-spec conf() -> {Account, Keys, Network} + when Account :: none | binary(), % <<"ak_...">> + Keys :: [binary()], + Network :: binary(). % <<"mainnet">> | <<"testnet">> | <<"devnet">> -unlock(Phrase) -> - gen_server:cast(?MODULE, {unlock, Phrase}). +conf() -> + gen_server:call(?MODULE, conf). --spec make_key(Phrase, Network) -> ok - when Phrase :: string(), - Network :: mainnet | testnet. +-spec conf({Account, Keys, Network}) -> ok + when Account :: none | binary(), % <<"ak_...">> + Keys :: [binary()], + Network :: binary(). % <<"mainnet">> | <<"testnet">> | <<"devnet">> -make_key(Phrase, Network) -> - gen_server:cast(?MODULE, {make_key, Phrase, Network}). - - --spec load_key(Phrase, Mnemonic, Network) -> ok - when Phrase :: string(), - Mnemonic :: string(), - Network :: mainnet | testnet. - -load_key(Phrase, Mnemonic, Network) -> - gen_server:cast(?MODULE, {load_key, Phrase, Mnemonic, Network}). - - --spec end_setup() -> ok. - -end_setup() -> - gen_server:call(?MODULE, end_setup). +conf(Info) -> + gen_server:cast(?MODULE, {conf, Info}). -spec bin_dir() -> file:filename(). @@ -118,43 +109,19 @@ start_link() -> init(none) -> ok = log(info, "Starting"), _ = process_flag(sensitive, true), - case open_wallet() of - {blob, Binary} -> - NewState = start_gui(#s{key = {blob, Binary}}), - ok = gmc_gui:ask_passphrase(), - {ok, NewState}; - {ok, Wallet, NetworkID} -> - NewState = start_gui(#s{key = Wallet, network = NetworkID}), - {ok, NewState}; - error -> - Window = gmc_setup:start_link(#{}), - ok = log(info, "Window: ~p", [Window]), - State = #s{window = Window}, - {ok, State} - end. + {Acc, Keys, Network, MemLimit} = + case read_conf() of + {ok, C} -> + {maps:get(account, C, none), + maps:get(keys, C, []), + maps:get(network, C, <<"mainnet">>), + maps:get(mem_limit, C, 3550722201)}; + none -> + {none, [], <<"mainnet">>, 3550722201} + end, + State = #s{network = Network, acc = Acc, keys = Keys, mem_limit = MemLimit}, + {ok, start_gui(State)}. -open_wallet() -> - GDPrefs = gd_read_prefs(), - Wallets = gd_get_prefs(wallets, GDPrefs, []), - case lists:keyfind(gm_name(), #wr.name, Wallets) of - #wr{path = Path, pass = true} -> - case file:read_file(Path) of - {ok, Binary} -> {blob, Binary}; - Error -> Error - end; - #wr{path = Path, pass = false} -> - case file:read_file(Path) of - {ok, Binary} -> - % TODO: Comply with GD's wallet upgrade system - {ok, #wallet{keys = Keys, nets = [#net{id = NetID}]}} = zx_lib:b_to_t(Binary), - Key = lists:keyfind(gm_name(), #key.name, Keys), - {ok, Key, NetID}; - Error -> - Error - end; - false -> - error - end. platform_dir() -> #{deps := Deps} = zx_daemon:meta(), @@ -173,9 +140,9 @@ platform_dir() -> filename:join(Priv, Dir). -start_gui(State = #s{key = #key{id = ID}}) -> +start_gui(State = #s{acc = none}) -> Window = gmc_gui:start_link(#{}), - ok = gmc_gui:set_account(ID), + ok = gmc_gui:ask_conf(), State#s{window = Window}; start_gui(State) -> Window = gmc_gui:start_link(#{}), @@ -185,11 +152,10 @@ start_gui(State) -> %%% gen_server Message Handling Callbacks -handle_call(end_setup, _, State) -> - NewState = end_setup(State), - {reply, ok, NewState}; handle_call(network, _, State = #s{network = Network}) -> {reply, Network, State}; +handle_call(conf, _, State = #s{acc = Acc, keys = Keys, network = Network}) -> + {reply, {Acc, Keys, Network}, State}; handle_call(bin_dir, _, State = #s{exec_dir = BinDir}) -> {reply, BinDir, State}; handle_call(Unexpected, From, State) -> @@ -197,15 +163,6 @@ handle_call(Unexpected, From, State) -> {noreply, State}. -handle_cast({unlock, Phrase}, State) -> - NewState = unlock(Phrase, State), - {noreply, NewState}; -handle_cast({make_key, Phrase, Network}, State) -> - NewState = make_key(Phrase, Network, State), - {noreply, NewState}; -handle_cast({load_key, Phrase, Mnemonic, Network}, State) -> - NewState = load_key(Phrase, Mnemonic, Network, State), - {noreply, NewState}; handle_cast(start_stop, State) -> ok = do_start_stop(State), {noreply, State}; @@ -233,8 +190,9 @@ code_change(_, State, _) -> {ok, State}. -terminate(Reason, _) -> +terminate(Reason, State) -> ok = log(info, "Reason: ~p,", [Reason]), + ok = persist(State), case whereis(gd_con) of undefined -> zx:stop(); @@ -253,92 +211,7 @@ do_stop() -> %%% Doers -unlock(Phrase, State = #s{key = {blob, Cipher}}) -> - Pass = pass(unicode:characters_to_binary(Phrase)), - case decrypt(Pass, Cipher) of - {ok, Binary} -> - {ok, #wallet{keys = Keys}} = zx_lib:b_to_t(Binary), - Name = gm_name(), - Unlocked = #key{id = ID, pair = Pair} = lists:keyfind(Name, #key.name, Keys), - #{secret := Secret} = Pair, - Encrypted = Pair#{secret => encrypt(Pass, Secret)}, - ok = gmc_gui:set_account(ID), - State#s{key = Unlocked#key{pair = Encrypted}, pass = Pass}; - {error, bad_password} -> - ok = gmc_gui:ask_passphrase(), - State - end. - - -make_key(Phrase, Network, State) -> - {ID, Pair = #{secret := <>}} = hz_key_master:make_key(<<>>), - Mnemonic = hz_key_master:encode(K), - ok = gmc_setup:done(Mnemonic), - finalize_key(Phrase, ID, Pair, Network, State). - - -load_key(Phrase, Mnemonic, Network, State) -> - case hz_key_master:decode(Mnemonic) of - {ok, Secret} -> - {ID, Pair} = hz_key_master:make_key(Secret), - ok = gmc_setup:done(), - finalize_key(Phrase, ID, Pair, Network, State); - Error -> - ok = gmc_setup:trouble(Error), - State - end. - - -finalize_key(Phrase, ID, Pair, Network, State) -> - NetBin = atom_to_binary(Network), - Pass = - case Phrase =:= "" of - false -> pass(unicode:characters_to_binary(Phrase)); - true -> none - end, - Key = #key{id = ID} = add_wallet(Pass, ID, Pair, NetBin), - State#s{key = Key, pass = Pass, network = NetBin}. - - -add_wallet(Pass, ID, Pair = #{secret := Secret}, Network) -> - GDPrefsPath = gd_prefs_path(), - GDPrefs = - case file:consult(GDPrefsPath) of - {ok, Prefs} -> proplists:to_map(Prefs); - {error, enoent} -> #{} - end, - Wallets = gd_get_prefs(wallets, GDPrefs, []), - WalletPath = gajumining_wallet(), - Created = #key{name = gm_name(), id = ID, pair = Pair}, - Net = #net{id = Network}, - ChainID = <<"groot.", Network/binary>>, - Node = #node{ip = unicode:characters_to_list(lists:join($., ["groot", Network, "gajumaru", "io"]))}, - New = #wallet{name = gm_name(), - poas = [#poa{name = gm_name(), id = ID}], - keys = [Created], - chain_id = ChainID, - endpoint = Node, - nets = [Net]}, - {WalletBin, KeyPair, HasPass} = - case Pass =:= none of - false -> {encrypt(Pass, term_to_binary(New)), Pair#{secret => {cipher, encrypt(Pass, Secret)}}, true}; - true -> {term_to_binary(New), Pair, false} - end, - Entry = #wr{name = gm_name(), path = WalletPath, pass = HasPass}, - NewWallets = lists:keystore(gm_name(), #wr.name, Wallets, Entry), - NewGDPrefs = gd_put_prefs(wallets, NewWallets, GDPrefs), - ok = file:write_file(WalletPath, WalletBin), - ok = zx_lib:write_terms(GDPrefsPath, proplists:from_map(NewGDPrefs)), - Created#key{pair = KeyPair}. - - -end_setup(State = #s{window = Window}) -> - PID = wx_object:get_pid(Window), - true = unlink(PID), - start_gui(State#s{window = none}). - - -do_start_stop(#s{key = #key{id = PubKey}, network = Network}) -> +do_start_stop(#s{acc = PubKey, network = Network, mem_limit = MemLimit}) -> % smrt guy stuff happens here {Bits, Eureka} = case Network of @@ -365,7 +238,7 @@ do_start_stop(#s{key = #key{id = PubKey}, network = Network}) -> end end, Miner = unicode:characters_to_binary([Fatness, Bits, "-", Type]), - Count = optimize_count(), + Count = optimize_count(MemLimit), Instance = #{<<"executable">> => Miner, <<"executable_group">> => <<"gajumine">>}, Workers = lists:duplicate(Count, Instance), Profile = @@ -387,7 +260,7 @@ do_start_stop(#s{key = #key{id = PubKey}, network = Network}) -> disconnected], lists:foreach(fun gmhc_events:ensure_subscribed/1, Events). -optimize_count() -> +optimize_count(MemLimit) -> {Procs, Memory} = case os:type() of {unix, linux} -> @@ -404,7 +277,7 @@ optimize_count() -> M = list_to_integer(string:strip(lists:nth(2, string:split(os:cmd("wmic computersystem get TotalPhysicalMemory"), "\r\r\n", all)))), {P, M} end, - MeanMaps = Memory div 3550722201, + MeanMaps = min(MemLimit, Memory) div 3550722201, Recommended = max(min(Procs, MeanMaps) - 1, 1), Notice = fun(F, A) -> gmc_gui:message({notice, io_lib:format(F, A)}) end, ok = Notice("Physical Processors: ~p", [Procs]), @@ -436,60 +309,28 @@ run_gajudesk() -> %%% Utils -%% Encryption stuff -% TODO: Expose these from GD itself - -encrypt(Pass, Binary) -> - Flags = [{encrypt, true}, {padding, pkcs_padding}], - crypto:crypto_one_time(aes_256_ecb, Pass, Binary, Flags). - - -decrypt(Pass, Binary) -> - Flags = [{encrypt, false}, {padding, pkcs_padding}], - try - {ok, crypto:crypto_one_time(aes_256_ecb, Pass, Binary, Flags)} - catch - error:{error, L, "Can't finalize"} -> - ok = log(info, "Decrypt failed at ~p", [L]), - {error, bad_password}; - E:R -> - {E, R} - end. - - -pass(Phrase) -> - crypto:hash(sha3_256, Phrase). - %% Paths and Names -gm_name() -> - "GajuMine". - -gajumining_wallet() -> - filename:join(zx_lib:path(var, "otpr", "gajudesk"), "gajumining.gaju"). +persist(#s{network = Network, acc = Acc, keys = Keys, mem_limit = MemLimit, prefs = Prefs}) -> + Update = #{network => Network, account => Acc, keys => Keys, mem_limit => MemLimit}, + Conf = maps:to_list(maps:merge(Prefs, Update)), + Path = gmc_prefs_path(), + ok = filelib:ensure_dir(Path), + zx_lib:write_terms(Path, Conf). -gd_prefs_path() -> - filename:join(zx_lib:path(etc, "otpr", "gajudesk"), "prefs.eterms"). - - -%% GajuDesk Prefs -% TODO: Glob these into a gd_prefs module exposed from GD itself - -gd_get_prefs(K, M, D) -> - P = maps:get(gd_con, M, #{}), - maps:get(K, P, D). - - -gd_put_prefs(K, V, M) -> - P = maps:get(gd_con, M, #{}), - NewP = maps:put(K, V, P), - maps:put(gd_con, NewP, M). - - -gd_read_prefs() -> - case file:consult(gd_prefs_path()) of - {ok, Prefs} -> proplists:to_map(Prefs); - {error, enoent} -> #{} +read_conf() -> + Path = gmc_prefs_path(), + case file:consult(Path) of + {ok, Conf} -> + {ok, maps:from_list(Conf)}; + {error, enoent} -> + none; + {error, Other} -> + ok = log(info, "Path ~p could not be read. Failed with ~p. Continuing.", [Path, Other]), + none end. + +gmc_prefs_path() -> + filename:join(zx_lib:path(etc, "qpq", "gajumine"), "prefs.eterms"). diff --git a/src/gmc_gui.erl b/src/gmc_gui.erl index 02ac508..e970ce4 100644 --- a/src/gmc_gui.erl +++ b/src/gmc_gui.erl @@ -3,14 +3,14 @@ %%% @end -module(gmc_gui). --vsn("0.1.4"). +-vsn("0.2.0"). -author("Craig Everett "). -copyright("Craig Everett "). -license("GPL-3.0-or-later"). -behavior(wx_object). -include_lib("wx/include/wx.hrl"). --export([ask_passphrase/0, set_account/1, difficulty/1, speed/1, candidate/1, message/1]). +-export([ask_conf/0, set_account/1, difficulty/1, speed/1, candidate/1, message/1]). -export([start_link/1]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2, handle_event/2]). @@ -34,7 +34,7 @@ candy = none :: none | wx:wx_object(), height = none :: none | wx:wx_object(), block = none :: none | wx:wx_object(), - % solved = 0 :: non_neg_integer(), % Add a widget to show this. Maybe + % solved = 0 :: non_neg_integer(), % TODO: Add a widget to show this. Maybe mess = none :: none | wx:wx_object(), buff = new_buff() :: buff(), buttons = [] :: [#w{}]}). @@ -55,8 +55,8 @@ new_buff() -> %%% Interface functions -ask_passphrase() -> - wx_object:cast(?MODULE, ask_passphrase). +ask_conf() -> + wx_object:cast(?MODULE, ask_conf). set_account(ID) -> @@ -102,7 +102,7 @@ init(Prefs) -> Labels = [J("ID"), J("Target"), J("Maps/s"), J("Candidate"), J("Height"), J("BlockHash")], {Grid, [ID_C, DiffC, PerfC, CandyC, HeightC, BlockC]} = display_box(Frame, Labels), - Style = ?wxTE_MULTILINE bor ?wxTE_READONLY, + Style = ?wxDEFAULT bor ?wxTE_MULTILINE bor ?wxTE_READONLY, MessSz = wxStaticBoxSizer:new(?wxVERTICAL, Frame, [{label, J("Messages")}]), MessC = wxTextCtrl:new(Frame, ?wxID_ANY, [{style, Style}]), _ = wxStaticBoxSizer:add(MessSz, MessC, zxw:flags(wide)), @@ -111,7 +111,8 @@ init(Prefs) -> [{start_stop, J("Start")}, {gajudesk, J("Open Wallet")}, {eureka, J("GajuMining")}, - {explorer, J("ChainExplorer")}], + {explorer, J("ChainExplorer")}, + {conf, J("Configure")}], MakeButton = fun({Name, Label}) -> @@ -167,8 +168,8 @@ handle_call(Unexpected, From, State) -> {noreply, State}. -handle_cast(ask_passphrase, State) -> - ok = ask_passphrase(State), +handle_cast(ask_conf, State) -> + ok = conf(State), {noreply, State}; handle_cast({set_account, ID}, State) -> ok = set_account(ID, State), @@ -203,6 +204,7 @@ handle_event(#wx{event = #wxCommand{type = command_button_clicked}, id = ID}, #w{name = gajudesk} -> gajudesk(State); #w{name = eureka} -> eureka(State); #w{name = explorer} -> explorer(State); + #w{name = conf} -> conf(State); false -> State end, {noreply, NewState}; @@ -223,34 +225,6 @@ terminate(Reason, State) -> wx:destroy(). -ask_passphrase(#s{frame = Frame, j = J}) -> - Label = J("Unlock Account"), - Dialog = wxDialog:new(Frame, ?wxID_ANY, Label, [{size, {500, 115}}]), - Sizer = wxBoxSizer:new(?wxVERTICAL), - PassSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Password")}]), - PassTx = wxTextCtrl:new(Dialog, ?wxID_ANY, [{style, ?wxTE_PASSWORD}]), - _ = wxStaticBoxSizer:add(PassSz, PassTx, zxw:flags(wide)), - ButtSz = wxBoxSizer:new(?wxHORIZONTAL), - Affirm = wxButton:new(Dialog, ?wxID_OK), - Cancel = wxButton:new(Dialog, ?wxID_CANCEL), - _ = wxBoxSizer:add(ButtSz, Affirm, zxw:flags(wide)), - _ = wxBoxSizer:add(ButtSz, Cancel, zxw:flags(wide)), - _ = wxBoxSizer:add(Sizer, PassSz, zxw:flags(base)), - _ = wxBoxSizer:add(Sizer, ButtSz, zxw:flags(wide)), - ok = wxDialog:setSizer(Dialog, Sizer), - ok = wxBoxSizer:layout(Sizer), - ok = wxFrame:center(Dialog), - ok = - case wxDialog:showModal(Dialog) of - ?wxID_OK -> - Phrase = wxTextCtrl:getValue(PassTx), - gmc_con:unlock(Phrase); - ?wxID_CANCEL -> - retire(Frame) - end, - wxDialog:destroy(Dialog). - - set_account(ID, #s{id = Widget}) -> wxStaticText:setLabel(Widget, ID). @@ -364,7 +338,9 @@ add_message2(Entry, {OMax, 0, IMax, 0, []}) -> {append, {OMax, 1, IMax, 1, [[Entry]]}}. -start_stop(State) -> +start_stop(State = #s{buttons = Buttons}) -> + #w{wx = SSB} = lists:keyfind(start_stop, #w.name, Buttons), + _ = wxButton:disable(SSB), ok = gmc_con:start_stop(), State. @@ -401,7 +377,70 @@ explorer_url() -> none -> "https://groot.mainnet.gajumaru.io"; Network -> unicode:characters_to_list(["https://groot.", Network, ".gajumaru.io"]) end. - + + +conf(State = #s{frame = Frame, j = J}) -> + Outcome = conf(Frame, J), + ok = tell("Outcome: ~p", [Outcome]), + State. + +conf(Frame, J) -> + {Acc, Keys, NetNum} = get_conf(), + Label = J("Configure GajuMine"), + Dialog = wxDialog:new(Frame, ?wxID_ANY, Label, [{size, {400, 400}}]), + Sizer = wxBoxSizer:new(?wxVERTICAL), + Network = wxRadioBox:new(Dialog, ?wxID_ANY, J("Network"), {0, 0}, {50, 50}, [J("Mainnet"), J("Testnet")]), + ok = wxRadioBox:setSelection(Network, NetNum), + GMAccSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("GajuMining Account ID")}]), + GMAccTx = wxTextCtrl:new(Dialog, ?wxID_ANY, [{style, ?wxTE_PASSWORD}, {value, Acc}]), + _ = wxStaticBoxSizer:add(GMAccSz, GMAccTx, zxw:flags(wide)), + AccsSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Additional Account IDs (optional)")}]), + AccsTx = wxTextCtrl:new(Dialog, ?wxID_ANY, [{style, ?wxTE_MULTILINE}, {value, Keys}]), + _ = wxStaticBoxSizer:add(AccsSz, AccsTx, zxw:flags(wide)), + ButtSz = wxBoxSizer:new(?wxHORIZONTAL), + Affirm = wxButton:new(Dialog, ?wxID_OK), + Cancel = wxButton:new(Dialog, ?wxID_CANCEL), + _ = wxBoxSizer:add(ButtSz, Affirm, zxw:flags(wide)), + _ = wxBoxSizer:add(ButtSz, Cancel, zxw:flags(wide)), + _ = wxBoxSizer:add(Sizer, Network, zxw:flags(base)), + _ = wxBoxSizer:add(Sizer, GMAccSz, zxw:flags(base)), + _ = wxBoxSizer:add(Sizer, AccsSz, zxw:flags(base)), + _ = wxBoxSizer:add(Sizer, ButtSz, zxw:flags(wide)), + ok = wxDialog:setSizer(Dialog, Sizer), + ok = wxBoxSizer:layout(Sizer), + ok = wxFrame:center(Dialog), + Outcome = + case wxDialog:showModal(Dialog) of + ?wxID_OK -> + Net = + case wxRadioBox:getSelection(Network) of + 0 -> <<"mainnet">>; + 1 -> <<"testnet">>; + _ -> <<"mainnet">> + end, + AccID = wxTextCtrl:getValue(GMAccTx), + MOAR_IDs = wxTextCtrl:getValue(AccsTx), + {Net, AccID, MOAR_IDs}; + ?wxID_CANCEL -> + cancel + end, + ok = wxDialog:destroy(Dialog), + Outcome. + +get_conf() -> + {ID, List, Network} = gmc_con:conf(), + {acc(ID), keys(List), net_num(Network)}. + +acc(none) -> ""; +acc(AKID) -> AKID. + +keys(List) -> + unicode:characters_to_list(lists:join("\n", List)). + +net_num(<<"mainnet">>) -> 0; +net_num(<<"testnet">>) -> 1; +net_num(_) -> 0. + open_browser(Frame, J, URL) -> case wx_misc:launchDefaultBrowser(URL) of diff --git a/src/gmc_setup.erl b/src/gmc_setup.erl index d58ce49..f5a91cb 100644 --- a/src/gmc_setup.erl +++ b/src/gmc_setup.erl @@ -12,7 +12,7 @@ %%% @end -module(gmc_setup). --vsn("0.1.4"). +-vsn("0.2.0"). -author("Craig Everett "). -copyright("Craig Everett "). -license("GPL-3.0-or-later"). @@ -190,7 +190,7 @@ new_key(Frame, J) -> _ = wxBoxSizer:add(Sizer, PassSz2, zxw:flags(base)), _ = wxBoxSizer:add(Sizer, ButtSz, zxw:flags(wide)), ok = wxDialog:setSizer(Dialog, Sizer), - ok = wxDialog:setSize(Dialog, {400, 250}), + ok = wxDialog:setSize(Dialog, {400, 300}), ok = wxBoxSizer:layout(Sizer), ok = wxFrame:center(Dialog), Outcome = diff --git a/src/gmc_sup.erl b/src/gmc_sup.erl index 8973c16..6573c91 100644 --- a/src/gmc_sup.erl +++ b/src/gmc_sup.erl @@ -12,7 +12,7 @@ %%% @end -module(gmc_sup). --vsn("0.1.4"). +-vsn("0.2.0"). -behaviour(supervisor). -author("Craig Everett "). -copyright("Craig Everett "). diff --git a/zomp.meta b/zomp.meta index 9c9526e..6644827 100644 --- a/zomp.meta +++ b/zomp.meta @@ -4,7 +4,7 @@ {author,"Craig Everett"}. {prefix,"gmc"}. {desc,"Mining client for the Gajumaru Root"}. -{package_id,{"qpq","gajumine",{0,1,4}}}. +{package_id,{"qpq","gajumine",{0,2,0}}}. {deps,[{"uwiger","gmconfig",{0,1,2}}, {"uwiger","gproc",{1,0,1}}, {"uwiger","gmhive_client",{0,2,1}}, -- 2.30.2 From f901ba6c9d99e61d049f019515cf1be5f0d60428 Mon Sep 17 00:00:00 2001 From: Craig Everett Date: Tue, 27 May 2025 20:12:23 +0900 Subject: [PATCH 2/8] WIP: Adding config interface --- src/gmc_con.erl | 110 ++++++++++------ src/gmc_conf.erl | 249 +++++++++++++++++++++++++++++++++++ src/gmc_gui.erl | 66 +--------- src/gmc_setup.erl | 327 ---------------------------------------------- 4 files changed, 323 insertions(+), 429 deletions(-) create mode 100644 src/gmc_conf.erl delete mode 100644 src/gmc_setup.erl diff --git a/src/gmc_con.erl b/src/gmc_con.erl index 0739d43..0a5a758 100644 --- a/src/gmc_con.erl +++ b/src/gmc_con.erl @@ -30,8 +30,10 @@ exec_dir = platform_dir() :: file:filename(), acc = none :: none | binary(), keys = [] :: [], - mem_limit = 3550722201 :: pos_integer(), - prefs = #{} :: #{}}). + max_cores = 2 :: pos_integer(), + max_mem = 3550722201 :: pos_integer(), + prefs = #{} :: #{}, + gmc_conf = none :: none | reference()}). -type state() :: #s{}. @@ -51,19 +53,18 @@ gajudesk() -> gen_server:cast(?MODULE, gajudesk). --spec conf() -> {Account, Keys, Network} - when Account :: none | binary(), % <<"ak_...">> - Keys :: [binary()], - Network :: binary(). % <<"mainnet">> | <<"testnet">> | <<"devnet">> +-spec conf() -> ok. conf() -> - gen_server:call(?MODULE, conf). + gen_server:cast(?MODULE, conf). --spec conf({Account, Keys, Network}) -> ok - when Account :: none | binary(), % <<"ak_...">> - Keys :: [binary()], - Network :: binary(). % <<"mainnet">> | <<"testnet">> | <<"devnet">> +-spec conf({Account, Keys, Network, MaxCores, MaxMem}) -> ok + when Account :: none | binary(), % <<"ak_...">> + Keys :: [binary()], % [<<"ak_...">>] + Network :: binary(), % <<"mainnet">> | <<"testnet">> | <<"devnet">> + MaxCores :: none | integer(), + MaxMem :: none | integer(). conf(Info) -> gen_server:cast(?MODULE, {conf, Info}). @@ -109,17 +110,18 @@ start_link() -> init(none) -> ok = log(info, "Starting"), _ = process_flag(sensitive, true), - {Acc, Keys, Network, MemLimit} = + {Acc, Keys, Network, MaxCores, MaxMem} = case read_conf() of {ok, C} -> {maps:get(account, C, none), maps:get(keys, C, []), maps:get(network, C, <<"mainnet">>), - maps:get(mem_limit, C, 3550722201)}; + maps:get(max_cores, C, 2), + maps:get(max_mem, C, 3550722201)}; none -> - {none, [], <<"mainnet">>, 3550722201} + {none, [], <<"mainnet">>, 2, 3550722201} end, - State = #s{network = Network, acc = Acc, keys = Keys, mem_limit = MemLimit}, + State = #s{network = Network, acc = Acc, keys = Keys, max_cores = MaxCores, max_mem = MaxMem}, {ok, start_gui(State)}. @@ -154,8 +156,6 @@ start_gui(State) -> handle_call(network, _, State = #s{network = Network}) -> {reply, Network, State}; -handle_call(conf, _, State = #s{acc = Acc, keys = Keys, network = Network}) -> - {reply, {Acc, Keys, Network}, State}; handle_call(bin_dir, _, State = #s{exec_dir = BinDir}) -> {reply, BinDir, State}; handle_call(Unexpected, From, State) -> @@ -169,6 +169,12 @@ handle_cast(start_stop, State) -> handle_cast(gajudesk, State) -> ok = do_gajudesk(), {noreply, State}; +handle_cast(conf, State) -> + NewState = run_gmc_conf(State), + {noreply, NewState}; +handle_cast({conf, Info}, State) -> + NewState = do_conf(Info, State), + {noreply, NewState}; handle_cast(stop, State) -> ok = do_stop(), ok = log(info, "Received a 'stop' message."), @@ -181,6 +187,10 @@ handle_cast(Unexpected, State) -> handle_info({gproc_ps_event, Event, Data}, State) -> ok = gmc_gui:message({Event, Data}), {noreply, State}; +handle_info({'DOWN', Mon, process, PID, Info}, State = #s{gmc_conf = Mon}) -> + ok = log(info, "gmc_conf ~p closed with ~p", [PID, Info]), + NewState = State#s{gmc_conf = none}, + {noreply, NewState}; handle_info(Unexpected, State) -> ok = log(warning, "Unexpected info: ~tp~n", [Unexpected]), {noreply, State}. @@ -211,7 +221,7 @@ do_stop() -> %%% Doers -do_start_stop(#s{acc = PubKey, network = Network, mem_limit = MemLimit}) -> +do_start_stop(#s{acc = PubKey, network = Network, max_mem = MaxMem}) -> % smrt guy stuff happens here {Bits, Eureka} = case Network of @@ -238,8 +248,8 @@ do_start_stop(#s{acc = PubKey, network = Network, mem_limit = MemLimit}) -> end end, Miner = unicode:characters_to_binary([Fatness, Bits, "-", Type]), - Count = optimize_count(MemLimit), - Instance = #{<<"executable">> => Miner, <<"executable_group">> => <<"gajumine">>}, + Count = optimize_count(MaxMem), + Instance = #{<<"executable">> => Miner}, Workers = lists:duplicate(Count, Instance), Profile = [{pubkey, PubKey}, @@ -260,24 +270,9 @@ do_start_stop(#s{acc = PubKey, network = Network, mem_limit = MemLimit}) -> disconnected], lists:foreach(fun gmhc_events:ensure_subscribed/1, Events). -optimize_count(MemLimit) -> - {Procs, Memory} = - case os:type() of - {unix, linux} -> - {processor, Cores} = hd(erlang:system_info(cpu_topology)), - P = length(Cores), - M = list_to_integer(string:trim(os:cmd("cat /proc/meminfo | grep MemTotal | awk '{print $2}'"))) * 1024, - {P, M}; - {unix, darwin} -> - P = list_to_integer(string:trim(os:cmd("sysctl -n hw.physicalcpu"))), - M = list_to_integer(string:trim(os:cmd("sysctl -n hw.memsize"))), - {P, M}; - {win32, nt} -> - P = list_to_integer(os:getenv("NUMBER_OF_PROCESSORS")), - M = list_to_integer(string:strip(lists:nth(2, string:split(os:cmd("wmic computersystem get TotalPhysicalMemory"), "\r\r\n", all)))), - {P, M} - end, - MeanMaps = min(MemLimit, Memory) div 3550722201, +optimize_count(MaxMem) -> + {Procs, Memory} = proc_mem(), + MeanMaps = min(MaxMem, Memory) div 3550722201, Recommended = max(min(Procs, MeanMaps) - 1, 1), Notice = fun(F, A) -> gmc_gui:message({notice, io_lib:format(F, A)}) end, ok = Notice("Physical Processors: ~p", [Procs]), @@ -286,6 +281,23 @@ optimize_count(MemLimit) -> ok = Notice("Workers: ~p", [Recommended]), Recommended. +proc_mem() -> + case os:type() of + {unix, linux} -> + {processor, Cores} = hd(erlang:system_info(cpu_topology)), + P = length(Cores), + M = list_to_integer(string:trim(os:cmd("cat /proc/meminfo | grep MemTotal | awk '{print $2}'"))) * 1024, + {P, M}; + {unix, darwin} -> + P = list_to_integer(string:trim(os:cmd("sysctl -n hw.physicalcpu"))), + M = list_to_integer(string:trim(os:cmd("sysctl -n hw.memsize"))), + {P, M}; + {win32, nt} -> + P = list_to_integer(os:getenv("NUMBER_OF_PROCESSORS")), + M = list_to_integer(string:strip(lists:nth(2, string:split(os:cmd("wmic computersystem get TotalPhysicalMemory"), "\r\r\n", all)))), + {P, M} + end. + do_gajudesk() -> ok = tell(info, "Running gajudesk"), @@ -307,13 +319,31 @@ run_gajudesk() -> end. +run_gmc_conf(State = #s{gmc_conf = none, network = Net, acc = Acc, keys = Keys, + max_cores = MProcs, max_mem = MMem, + prefs = Prefs}) -> + {AProcs, AMem} = proc_mem(), + Win = gmc_conf:start_link({Prefs, {Net, Acc, Keys, {AProcs, AMem, MProcs, MMem}}}), + PID = wx_object:get_pid(Win), + Mon = monitor(process, PID), + ok = gmc_conf:to_front(), + State#s{gmc_conf = Mon}; +run_gmc_conf(State) -> + ok = gmc_conf:to_front(), + State. + + +do_conf({Network, AccID, Keys, MaxCores, MaxMem}, State) -> + State#s{network = Network, acc = AccID, keys = Keys, max_cores = MaxCores, max_mem = MaxMem}. + + %%% Utils %% Paths and Names -persist(#s{network = Network, acc = Acc, keys = Keys, mem_limit = MemLimit, prefs = Prefs}) -> - Update = #{network => Network, account => Acc, keys => Keys, mem_limit => MemLimit}, +persist(#s{network = Network, acc = Acc, keys = Keys, max_cores = MaxCores, max_mem = MaxMem, prefs = Prefs}) -> + Update = #{network => Network, account => Acc, keys => Keys, max_cores => MaxCores, max_mem => MaxMem}, Conf = maps:to_list(maps:merge(Prefs, Update)), Path = gmc_prefs_path(), ok = filelib:ensure_dir(Path), diff --git a/src/gmc_conf.erl b/src/gmc_conf.erl new file mode 100644 index 0000000..771b14e --- /dev/null +++ b/src/gmc_conf.erl @@ -0,0 +1,249 @@ +%%% @doc +%%% GajuMine Configuration GUI +%%% @end + +-module(gmc_conf). +-vsn("0.2.0"). +-author("Craig Everett "). +-copyright("Craig Everett "). +-license("GPL-3.0-or-later"). + +-behavior(wx_object). +-include_lib("wx/include/wx.hrl"). +-export([to_front/0, trouble/1]). +-export([start_link/1]). +-export([init/1, terminate/2, code_change/3, + handle_call/3, handle_cast/2, handle_info/2, handle_event/2]). +-include("$zx_include/zx_logger.hrl"). + + +-record(s, + {wx = none :: none | wx:wx_object(), + frame = none :: none | wx:wx_object(), + lang = en :: en | jp, + j = none :: none | fun(), + net = none :: none | wx:wx_object(), + acc = none :: none | wx:wx_object(), + keys = none :: none | wx:wx_object(), + cores = none :: none | wx:wx_object(), + memory = none :: none | wx:wx_object()}). + + + +%%% Interface functions + + +-spec to_front() -> ok. + +to_front() -> + wx_object:cast(?MODULE, to_front). + + +-spec trouble(term()) -> ok. + +trouble(Info) -> + wx_object:cast(?MODULE, {trouble, Info}). + + + +%%% Startup Functions + +start_link(Prefs) -> + wx_object:start_link({local, ?MODULE}, ?MODULE, Prefs, []). + + +init({Prefs, {Net, Acc, Keys, {AProcs, AMem, MProcs, MMem}}}) -> + ok = log(info, "GUI starting..."), + Lang = maps:get(lang, Prefs, en_US), + Trans = gd_jt:read_translations(?MODULE), + J = gd_jt:j(Lang, Trans), + Label = J("Configure GajuMine"), + + WX = wx:new(), + Frame = wxFrame:new(WX, ?wxID_ANY, Label), + MainSz = wxBoxSizer:new(?wxVERTICAL), + + AccSz = wxStaticBoxSizer:new(?wxVERTICAL, Frame, [{label, J("GajuMining Account ID")}]), + AccTx = wxTextCtrl:new(Frame, ?wxID_ANY, [{value, acc(Acc)}]), + _ = wxStaticBoxSizer:add(AccSz, AccTx, wide(5)), + KeysSz = wxStaticBoxSizer:new(?wxVERTICAL, Frame, [{label, J("Additional Account IDs (optional)")}]), + KeysTx = wxTextCtrl:new(Frame, ?wxID_ANY, [{style, ?wxTE_MULTILINE}, {value, keys(Keys)}]), + _ = wxStaticBoxSizer:add(KeysSz, KeysTx, wide(5)), + StatSz = wxStaticBoxSizer:new(?wxVERTICAL, Frame, [{label, J("Max System Committment (optional)")}]), + AProcsS = integer_to_list(AProcs), + MProcsS = integer_to_list(MProcs), + AMemS = gigs(AMem), + MMemS = gigs(MMem), + Labels = [{J("HW Cores"), J("Max Cores"), AProcsS, MProcsS}, {J("Memory (GB)"), J("Max Memory"), AMemS, MMemS}], + {Grid, [CoresTx, MemoryTx]} = display_box(Frame, Labels), + Network = wxRadioBox:new(Frame, ?wxID_ANY, J("Network"), {0, 0}, {50, 50}, [J("Mainnet"), J("Testnet")]), + ok = wxRadioBox:setSelection(Network, net_num(Net)), + + ButtSz = wxBoxSizer:new(?wxHORIZONTAL), + Affirm = wxButton:new(Frame, ?wxID_OK), + Cancel = wxButton:new(Frame, ?wxID_CANCEL), + _ = wxBoxSizer:add(StatSz, Grid, wide(5)), + _ = wxBoxSizer:add(ButtSz, Affirm, wide(5)), + _ = wxBoxSizer:add(ButtSz, Cancel, wide(5)), + _ = wxBoxSizer:add(MainSz, AccSz, base(5)), + _ = wxBoxSizer:add(MainSz, KeysSz, wide(5)), + _ = wxBoxSizer:add(MainSz, StatSz, base(5)), + _ = wxBoxSizer:add(MainSz, Network, base(5)), + _ = wxBoxSizer:add(MainSz, ButtSz, base(5)), + ok = wxFrame:setSizer(Frame, MainSz), + ok = wxBoxSizer:layout(MainSz), + ok = wxFrame:connect(Frame, command_button_clicked), + ok = wxFrame:connect(Frame, close_window), + ok = wxFrame:setSize(Frame, {500, 500}), + ok = wxFrame:center(Frame), + true = wxFrame:show(Frame), + State = + #s{wx = WX, frame = Frame, + lang = Lang, j = J, + net = Network, acc = AccTx, keys = KeysTx, + cores = CoresTx, memory = MemoryTx}, + {Frame, State}. + + +base(Padding) -> [{proportion, 0}, {flag, ?wxEXPAND bor ?wxALL}, {border, Padding}]. + +wide(Padding) -> [{proportion, 1}, {flag, ?wxEXPAND bor ?wxALL}, {border, Padding}]. + +center() -> [{proportion, 0}, {flag, ?wxEXPAND bor ?wxALIGN_CENTER_VERTICAL}]. + +gigs(Bytes) -> + float_to_list(Bytes / gig(), [{decimals, 2}, compact]). + +gig() -> 1_073_741_824. + +display_box(Parent, Labels) -> + Grid = wxFlexGridSizer:new(2, 4, 4), + ok = wxFlexGridSizer:setFlexibleDirection(Grid, ?wxHORIZONTAL), + ok = wxFlexGridSizer:addGrowableCol(Grid, 1), + Make = + fun({SO, SI, VS, VM}) -> + LO = [SO, ":"], + LI = [SI, ":"], + T_LO = wxStaticText:new(Parent, ?wxID_ANY, LO), + T_CO = wxStaticText:new(Parent, ?wxID_ANY, VS, [{style, ?wxALIGN_LEFT}]), + T_LI = wxStaticText:new(Parent, ?wxID_ANY, LI), + T_CI = wxTextCtrl:new(Parent, ?wxID_ANY, [{value, VM}]), + _ = wxFlexGridSizer:add(Grid, T_LO, center()), + _ = wxFlexGridSizer:add(Grid, T_CO, center()), + _ = wxFlexGridSizer:add(Grid, T_LI, center()), + _ = wxFlexGridSizer:add(Grid, T_CI, zxw:flags(wide)), + T_CI + end, + Controls = lists:map(Make, Labels), + {Grid, Controls}. + + + +handle_call(Unexpected, From, State) -> + ok = log(warning, "Unexpected call from ~tp: ~tp~n", [From, Unexpected]), + {noreply, State}. + + +handle_cast(to_front, State = #s{frame = Frame}) -> + ok = wxFrame:raise(Frame), + {noreply, State}; +handle_cast({trouble, Info}, State) -> + ok = handle_troubling(State, Info), + {noreply, State}; +handle_cast(Unexpected, State) -> + ok = log(warning, "Unexpected cast: ~tp~n", [Unexpected]), + {noreply, State}. + + +handle_info(Unexpected, State) -> + ok = log(warning, "Unexpected info: ~tp~n", [Unexpected]), + {noreply, State}. + + +handle_event(#wx{event = #wxCommand{type = command_button_clicked}, id = ID}, State) -> + ok = + case ID of + ?wxID_OK -> done(State); + ?wxID_CANCEL -> buh_bye(State) + end, + {noreply, State}; +handle_event(#wx{event = #wxClose{}}, State) -> + ok = buh_bye(State), + {noreply, State}; +handle_event(Event, State) -> + ok = tell(info, "Unexpected event ~tp State: ~tp~n", [Event, State]), + {noreply, State}. + + +handle_troubling(#s{frame = Frame}, Info) -> + zxw:show_message(Frame, Info). + + +code_change(_, State, _) -> + {ok, State}. + + +terminate(Reason, State) -> + ok = log(info, "Reason: ~tp, State: ~tp", [Reason, State]), + wx:destroy(). + +buh_bye(#s{frame = Frame}) -> + wxWindow:destroy(Frame). + + +%%% Doers + +done(State = #s{net = Network, acc = AccTx, keys = KeysTx, cores = CoresTx, memory = MemTx}) -> + Net = + case wxRadioBox:getSelection(Network) of + 0 -> <<"mainnet">>; + 1 -> <<"testnet">>; + _ -> <<"mainnet">> + end, + AccID = wxTextCtrl:getValue(AccTx), + MOAR_IDs = wxTextCtrl:getValue(KeysTx), + CoreS = wxTextCtrl:getValue(CoresTx), + GigsS = wxTextCtrl:getValue(MemTx), + ok = gmc_con:conf({Net, list_to_binary(AccID), binify_keys(MOAR_IDs), cores(CoreS), bytes(GigsS)}), + buh_bye(State). + +cores("") -> + none; +cores(CoreS) -> + try + list_to_integer(CoreS) + catch + _:_ -> none + end. + +bytes("") -> + none; +bytes(GigsS) -> + try + list_to_integer(GigsS) * gig() + catch + _:_ -> + try + trunc(list_to_float(GigsS) * gig()) + catch + _:_ -> none + end + end. + + +% NOTE: 32 is space, 12288 is full-width space. +binify_keys(MOAR) -> + [list_to_binary(K) || K <- string:lexemes(MOAR, [$\r, $\n, 32, 12288, $\t, $,, $;])]. + + +acc(none) -> ""; +acc(AKID) -> AKID. + + +keys(List) -> + unicode:characters_to_list(lists:join("\n", List)). + + +net_num(<<"mainnet">>) -> 0; +net_num(<<"testnet">>) -> 1; +net_num(_) -> 0. diff --git a/src/gmc_gui.erl b/src/gmc_gui.erl index e970ce4..f040b84 100644 --- a/src/gmc_gui.erl +++ b/src/gmc_gui.erl @@ -169,8 +169,8 @@ handle_call(Unexpected, From, State) -> handle_cast(ask_conf, State) -> - ok = conf(State), - {noreply, State}; + NewState = conf(State), + {noreply, NewState}; handle_cast({set_account, ID}, State) -> ok = set_account(ID, State), {noreply, State}; @@ -379,68 +379,10 @@ explorer_url() -> end. -conf(State = #s{frame = Frame, j = J}) -> - Outcome = conf(Frame, J), - ok = tell("Outcome: ~p", [Outcome]), +conf(State) -> + ok = gmc_con:conf(), State. -conf(Frame, J) -> - {Acc, Keys, NetNum} = get_conf(), - Label = J("Configure GajuMine"), - Dialog = wxDialog:new(Frame, ?wxID_ANY, Label, [{size, {400, 400}}]), - Sizer = wxBoxSizer:new(?wxVERTICAL), - Network = wxRadioBox:new(Dialog, ?wxID_ANY, J("Network"), {0, 0}, {50, 50}, [J("Mainnet"), J("Testnet")]), - ok = wxRadioBox:setSelection(Network, NetNum), - GMAccSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("GajuMining Account ID")}]), - GMAccTx = wxTextCtrl:new(Dialog, ?wxID_ANY, [{style, ?wxTE_PASSWORD}, {value, Acc}]), - _ = wxStaticBoxSizer:add(GMAccSz, GMAccTx, zxw:flags(wide)), - AccsSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Additional Account IDs (optional)")}]), - AccsTx = wxTextCtrl:new(Dialog, ?wxID_ANY, [{style, ?wxTE_MULTILINE}, {value, Keys}]), - _ = wxStaticBoxSizer:add(AccsSz, AccsTx, zxw:flags(wide)), - ButtSz = wxBoxSizer:new(?wxHORIZONTAL), - Affirm = wxButton:new(Dialog, ?wxID_OK), - Cancel = wxButton:new(Dialog, ?wxID_CANCEL), - _ = wxBoxSizer:add(ButtSz, Affirm, zxw:flags(wide)), - _ = wxBoxSizer:add(ButtSz, Cancel, zxw:flags(wide)), - _ = wxBoxSizer:add(Sizer, Network, zxw:flags(base)), - _ = wxBoxSizer:add(Sizer, GMAccSz, zxw:flags(base)), - _ = wxBoxSizer:add(Sizer, AccsSz, zxw:flags(base)), - _ = wxBoxSizer:add(Sizer, ButtSz, zxw:flags(wide)), - ok = wxDialog:setSizer(Dialog, Sizer), - ok = wxBoxSizer:layout(Sizer), - ok = wxFrame:center(Dialog), - Outcome = - case wxDialog:showModal(Dialog) of - ?wxID_OK -> - Net = - case wxRadioBox:getSelection(Network) of - 0 -> <<"mainnet">>; - 1 -> <<"testnet">>; - _ -> <<"mainnet">> - end, - AccID = wxTextCtrl:getValue(GMAccTx), - MOAR_IDs = wxTextCtrl:getValue(AccsTx), - {Net, AccID, MOAR_IDs}; - ?wxID_CANCEL -> - cancel - end, - ok = wxDialog:destroy(Dialog), - Outcome. - -get_conf() -> - {ID, List, Network} = gmc_con:conf(), - {acc(ID), keys(List), net_num(Network)}. - -acc(none) -> ""; -acc(AKID) -> AKID. - -keys(List) -> - unicode:characters_to_list(lists:join("\n", List)). - -net_num(<<"mainnet">>) -> 0; -net_num(<<"testnet">>) -> 1; -net_num(_) -> 0. - open_browser(Frame, J, URL) -> case wx_misc:launchDefaultBrowser(URL) of diff --git a/src/gmc_setup.erl b/src/gmc_setup.erl deleted file mode 100644 index f5a91cb..0000000 --- a/src/gmc_setup.erl +++ /dev/null @@ -1,327 +0,0 @@ -%%% @doc -%%% GajuMine Setup GUI -%%% -%%% In the common case, when a user first runs the program they will not have any -%%% accounrts, keys, or mining system setup. The purpose of this program is to provide -%%% a first-run guide for them to get set up for mining and explain to the user what is -%%% going on. -%%% -%%% There are two cases to cover: -%%% 1. A new miner who doesn't know how anything works and needs to get set up from scratch. -%%% 2. A miner who does know a bit about how things work and wants to import a key. -%%% @end - --module(gmc_setup). --vsn("0.2.0"). --author("Craig Everett "). --copyright("Craig Everett "). --license("GPL-3.0-or-later"). - --behavior(wx_object). --include_lib("wx/include/wx.hrl"). --export([trouble/1, done/0, done/1]). --export([start_link/1]). --export([init/1, terminate/2, code_change/3, - handle_call/3, handle_cast/2, handle_info/2, handle_event/2]). --include("$zx_include/zx_logger.hrl"). - - --record(w, - {name = none :: atom(), - id = 0 :: integer(), - wx = none :: none | wx:wx_object()}). - --record(s, - {wx = none :: none | wx:wx_object(), - frame = none :: none | wx:wx_object(), - lang = en :: en | jp, - j = none :: none | fun(), - buttons = [] :: [#w{}]}). - - - -%%% Interface functions - -trouble(Info) -> - wx_object:cast(?MODULE, {trouble, Info}). - - -done() -> - wx_object:cast(?MODULE, done). - - -done(Mnemonic) -> - wx_object:cast(?MODULE, {done, Mnemonic}). - - - -%%% Startup Functions - -start_link(Prefs) -> - wx_object:start_link({local, ?MODULE}, ?MODULE, Prefs, []). - - -init(Prefs) -> - ok = log(info, "GUI starting..."), - Lang = maps:get(lang, Prefs, en_US), - Trans = gd_jt:read_translations(?MODULE), - J = gd_jt:j(Lang, Trans), - - WX = wx:new(), - Frame = wxFrame:new(WX, ?wxID_ANY, J("GajuMine Setup")), - MainSz = wxBoxSizer:new(?wxVERTICAL), - - ButtonTemplates = - [{new_key, J("Create a New Account")}, - {recover, J("Recover Existing Account")}], - - MakeButton = - fun({Name, Label}) -> - B = wxButton:new(Frame, ?wxID_ANY, [{label, Label}]), - #w{name = Name, id = wxButton:getId(B), wx = B} - end, - - Buttons = lists:map(MakeButton, ButtonTemplates), - - Add = fun(#w{wx = Button}) -> wxBoxSizer:add(MainSz, Button, zxw:flags(wide)) end, - ok = lists:foreach(Add, Buttons), - - ok = wxFrame:setSizer(Frame, MainSz), - ok = wxSizer:layout(MainSz), - - ok = wxFrame:connect(Frame, command_button_clicked), - ok = wxFrame:connect(Frame, close_window), - ok = wxFrame:setSize(Frame, {300, 300}), - ok = wxFrame:center(Frame), - true = wxFrame:show(Frame), - State = - #s{wx = WX, frame = Frame, - lang = Lang, j = J, - buttons = Buttons}, - {Frame, State}. - - -handle_call(Unexpected, From, State) -> - ok = log(warning, "Unexpected call from ~tp: ~tp~n", [From, Unexpected]), - {noreply, State}. - - -handle_cast({trouble, Info}, State) -> - ok = handle_troubling(State, Info), - {noreply, State}; -handle_cast(done, State = #s{frame = Frame}) -> - ok = gmc_con:end_setup(), - ok = wxWindow:destroy(Frame), - {noreply, State}; -handle_cast({done, Mnemonic}, State) -> - ok = done(Mnemonic, State), - {noreply, State}; -handle_cast(Unexpected, State) -> - ok = log(warning, "Unexpected cast: ~tp~n", [Unexpected]), - {noreply, State}. - - -handle_info(Unexpected, State) -> - ok = log(warning, "Unexpected info: ~tp~n", [Unexpected]), - {noreply, State}. - - -handle_event(#wx{event = #wxCommand{type = command_button_clicked}, - id = ID}, - State = #s{buttons = Buttons}) -> - ok = - case lists:keyfind(ID, #w.id, Buttons) of - #w{name = new_key} -> new_key(State); - #w{name = recover} -> recover(State) - end, - {noreply, State}; -handle_event(#wx{event = #wxClose{}}, State = #s{frame = Frame}) -> - ok = gmc_con:stop(), - ok = wxWindow:destroy(Frame), - {noreply, State}; -handle_event(Event, State) -> - ok = tell(info, "Unexpected event ~tp State: ~tp~n", [Event, State]), - {noreply, State}. - - -handle_troubling(#s{frame = Frame}, Info) -> - zxw:show_message(Frame, Info). - - -code_change(_, State, _) -> - {ok, State}. - - -terminate(Reason, State) -> - ok = log(info, "Reason: ~tp, State: ~tp", [Reason, State]), - wx:destroy(). - - -new_key(State = #s{frame = Frame, j = J}) -> - case new_key(Frame, J) of - {ok, Phrase, Network} -> - gmc_con:make_key(Phrase, Network); - mismatch -> - ok = zxw:show_message(Frame, J("Password entered incorrectly. Try again.")), - new_key(State); - cancel -> - ok - end. - - -new_key(Frame, J) -> - Label = J("Generate New Account Key"), - Dialog = wxDialog:new(Frame, ?wxID_ANY, Label, [{size, {500, 180}}]), - Sizer = wxBoxSizer:new(?wxVERTICAL), - Network = wxRadioBox:new(Dialog, ?wxID_ANY, J("Network"), {0, 0}, {50, 50}, [J("Mainnet"), J("Testnet")]), - PassSz1 = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Create Password")}]), - PassTx1 = wxTextCtrl:new(Dialog, ?wxID_ANY, [{style, ?wxTE_PASSWORD}]), - _ = wxStaticBoxSizer:add(PassSz1, PassTx1, zxw:flags(wide)), - PassSz2 = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Confirm Password")}]), - PassTx2 = wxTextCtrl:new(Dialog, ?wxID_ANY, [{style, ?wxTE_PASSWORD}]), - _ = wxStaticBoxSizer:add(PassSz2, PassTx2, zxw:flags(wide)), - ButtSz = wxBoxSizer:new(?wxHORIZONTAL), - Affirm = wxButton:new(Dialog, ?wxID_OK), - Cancel = wxButton:new(Dialog, ?wxID_CANCEL), - _ = wxBoxSizer:add(ButtSz, Affirm, zxw:flags(wide)), - _ = wxBoxSizer:add(ButtSz, Cancel, zxw:flags(wide)), - _ = wxBoxSizer:add(Sizer, Network, zxw:flags(base)), - _ = wxBoxSizer:add(Sizer, PassSz1, zxw:flags(base)), - _ = wxBoxSizer:add(Sizer, PassSz2, zxw:flags(base)), - _ = wxBoxSizer:add(Sizer, ButtSz, zxw:flags(wide)), - ok = wxDialog:setSizer(Dialog, Sizer), - ok = wxDialog:setSize(Dialog, {400, 300}), - ok = wxBoxSizer:layout(Sizer), - ok = wxFrame:center(Dialog), - Outcome = - case wxDialog:showModal(Dialog) of - ?wxID_OK -> - Net = - case wxRadioBox:getSelection(Network) of - 0 -> mainnet; - 1 -> testnet; - _ -> mainnet - end, - Pass1 = wxTextCtrl:getValue(PassTx1), - Pass2 = wxTextCtrl:getValue(PassTx2), - case Pass1 =:= Pass2 of - true -> {ok, Pass1, Net}; - false -> mismatch - end; - ?wxID_CANCEL -> - cancel - end, - ok = wxDialog:destroy(Dialog), - Outcome. - - -recover(State = #s{frame = Frame, j = J}) -> - case recover(Frame, J) of - {ok, Phrase, Mnemonic, Network} -> - gmc_con:load_key(Phrase, Mnemonic, Network); - mismatch -> - ok = zxw:show_message(Frame, J("Password entered incorrectly. Try again.")), - recover(State); - cancel -> - ok - end. - -recover(Frame, J) -> - Dialog = wxDialog:new(Frame, ?wxID_ANY, J("Import Account Key")), - Sizer = wxBoxSizer:new(?wxVERTICAL), - Network = wxRadioBox:new(Dialog, ?wxID_ANY, J("Network"), {0, 0}, {50, 50}, [J("Mainnet"), J("Testnet")]), - PassSz1 = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Create Password")}]), - PassTx1 = wxTextCtrl:new(Dialog, ?wxID_ANY, [{style, ?wxTE_PASSWORD}]), - _ = wxStaticBoxSizer:add(PassSz1, PassTx1, zxw:flags(wide)), - PassSz2 = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Confirm Password")}]), - PassTx2 = wxTextCtrl:new(Dialog, ?wxID_ANY, [{style, ?wxTE_PASSWORD}]), - _ = wxStaticBoxSizer:add(PassSz2, PassTx2, zxw:flags(wide)), - MnemSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Recovery Phrase")}]), - MnemTx = wxTextCtrl:new(Dialog, ?wxID_ANY, [{style, ?wxTE_MULTILINE}]), - _ = wxStaticBoxSizer:add(MnemSz, MnemTx, zxw:flags(wide)), - ButtSz = wxBoxSizer:new(?wxHORIZONTAL), - Affirm = wxButton:new(Dialog, ?wxID_OK), - Cancel = wxButton:new(Dialog, ?wxID_CANCEL), - _ = wxBoxSizer:add(ButtSz, Affirm, zxw:flags(wide)), - _ = wxBoxSizer:add(ButtSz, Cancel, zxw:flags(wide)), - _ = wxBoxSizer:add(Sizer, Network, zxw:flags(base)), - _ = wxBoxSizer:add(Sizer, PassSz1, zxw:flags(base)), - _ = wxBoxSizer:add(Sizer, PassSz2, zxw:flags(base)), - _ = wxBoxSizer:add(Sizer, MnemSz, zxw:flags(wide)), - _ = wxBoxSizer:add(Sizer, ButtSz, zxw:flags(base)), - ok = wxDialog:setSizer(Dialog, Sizer), - ok = wxDialog:setSize(Dialog, {400, 400}), - ok = wxBoxSizer:layout(Sizer), - ok = wxFrame:center(Dialog), - Outcome = - case wxDialog:showModal(Dialog) of - ?wxID_OK -> - Pass1 = wxTextCtrl:getValue(PassTx1), - Pass2 = wxTextCtrl:getValue(PassTx2), - case Pass1 =:= Pass2 of - true -> - Net = - case wxRadioBox:getSelection(Network) of - 0 -> mainnet; - 1 -> testnet; - _ -> mainnet - end, - Mnemonic = wxTextCtrl:getValue(MnemTx), - {ok, Pass1, Mnemonic, Net}; - false -> - mismatch - end; - ?wxID_CANCEL -> - cancel - end, - ok = wxDialog:destroy(Dialog), - Outcome. - - - -done(Mnemonic, #s{frame = Frame, j = J}) -> - Dialog = wxDialog:new(Frame, ?wxID_ANY, J("Mnemonic")), - Sizer = wxBoxSizer:new(?wxVERTICAL), - MnemSz = wxStaticBoxSizer:new(?wxVERTICAL, Dialog, [{label, J("Recovery Phrase")}]), - Options = [{value, Mnemonic}, {style, ?wxTE_MULTILINE bor ?wxTE_READONLY}], - MnemTx = wxTextCtrl:new(Dialog, ?wxID_ANY, Options), - _ = wxStaticBoxSizer:add(MnemSz, MnemTx, zxw:flags(wide)), - ButtSz = wxBoxSizer:new(?wxHORIZONTAL), - CloseB = wxButton:new(Dialog, ?wxID_CANCEL, [{label, J("Close")}]), - CopyB = wxButton:new(Dialog, ?wxID_OK, [{label, J("Copy to Clipboard")}]), - _ = wxBoxSizer:add(ButtSz, CloseB, zxw:flags(wide)), - _ = wxBoxSizer:add(ButtSz, CopyB, zxw:flags(wide)), - _ = wxBoxSizer:add(Sizer, MnemSz, zxw:flags(wide)), - _ = wxBoxSizer:add(Sizer, ButtSz, zxw:flags(base)), - ok = wxDialog:setSizer(Dialog, Sizer), - ok = wxBoxSizer:layout(Sizer), - ok = wxFrame:center(Dialog), - ok = wxStyledTextCtrl:setFocus(MnemTx), - ok = - case wxDialog:showModal(Dialog) of - ?wxID_CANCEL -> ok; - ?wxID_OK -> copy_to_clipboard(Mnemonic) - end, - ok = wxDialog:destroy(Dialog), - ok = gmc_con:end_setup(), - ok = wxWindow:destroy(Frame), - ok. - - -copy_to_clipboard(String) -> - CB = wxClipboard:get(), - case wxClipboard:open(CB) of - true -> - Text = wxTextDataObject:new([{text, String}]), - case wxClipboard:setData(CB, Text) of - true -> - R = wxClipboard:flush(CB), - log(info, "String copied to system clipboard. Flushed: ~p", [R]); - false -> - log(info, "Failed to copy to clipboard") - end, - ok = wxClipboard:close(CB); - false -> - log(info, "Failed to acquire the clipboard.") - end. - -- 2.30.2 From 562f86e0781887f565016acd2fc1a991ae88d37f Mon Sep 17 00:00:00 2001 From: Craig Everett Date: Tue, 27 May 2025 20:56:00 +0900 Subject: [PATCH 3/8] Test candidate 1 --- src/gmc_con.erl | 83 +++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/src/gmc_con.erl b/src/gmc_con.erl index 0a5a758..45d146a 100644 --- a/src/gmc_con.erl +++ b/src/gmc_con.erl @@ -11,7 +11,6 @@ -behavior(gen_server). -export([start_stop/0, gajudesk/0]). -export([conf/0, conf/1]). --export([bin_dir/0]). -export([network/0]). -export([start_link/0, stop/0]). -export([init/1, terminate/2, code_change/3, @@ -27,7 +26,6 @@ {version = 1 :: integer(), window = none :: none | wx:wx_object(), network = <<"mainnet">> :: binary(), % <<"testnet">> | <<"mainnet">> - exec_dir = platform_dir() :: file:filename(), acc = none :: none | binary(), keys = [] :: [], max_cores = 2 :: pos_integer(), @@ -70,12 +68,6 @@ conf(Info) -> gen_server:cast(?MODULE, {conf, Info}). --spec bin_dir() -> file:filename(). - -bin_dir() -> - gen_server:call(?MODULE, bin_dir). - - -spec network() -> mainnet | testnet | none. network() -> @@ -109,7 +101,6 @@ start_link() -> init(none) -> ok = log(info, "Starting"), - _ = process_flag(sensitive, true), {Acc, Keys, Network, MaxCores, MaxMem} = case read_conf() of {ok, C} -> @@ -125,29 +116,14 @@ init(none) -> {ok, start_gui(State)}. -platform_dir() -> - #{deps := Deps} = zx_daemon:meta(), - AppID = lists:keyfind("cuckoo_cpu", 2, Deps), - Priv = filename:join(zx_lib:ppath(lib, AppID), "priv"), - Dir = - case os:type() of - {unix, linux} -> - "linux_x86_64"; - {unix, darwin} -> - % TODO: Check M2 vs x86 - "mac_m2"; - {win32, nt} -> - "win_x86_64" - end, - filename:join(Priv, Dir). - start_gui(State = #s{acc = none}) -> Window = gmc_gui:start_link(#{}), ok = gmc_gui:ask_conf(), State#s{window = Window}; -start_gui(State) -> +start_gui(State = #s{acc = AccID}) -> Window = gmc_gui:start_link(#{}), + ok = gmc_gui:set_account(AccID), State#s{window = Window}. @@ -156,8 +132,6 @@ start_gui(State) -> handle_call(network, _, State = #s{network = Network}) -> {reply, Network, State}; -handle_call(bin_dir, _, State = #s{exec_dir = BinDir}) -> - {reply, BinDir, State}; handle_call(Unexpected, From, State) -> ok = log(warning, "Unexpected call from ~tp: ~tp~n", [From, Unexpected]), {noreply, State}. @@ -221,7 +195,7 @@ do_stop() -> %%% Doers -do_start_stop(#s{acc = PubKey, network = Network, max_mem = MaxMem}) -> +do_start_stop(#s{acc = PubKey, keys = Keys, network = Network, max_cores = MaxCores, max_mem = MaxMem}) -> % smrt guy stuff happens here {Bits, Eureka} = case Network of @@ -247,14 +221,15 @@ do_start_stop(#s{acc = PubKey, network = Network, max_mem = MaxMem}) -> <<"testnet">> -> {"mean", "generic.exe"} end end, - Miner = unicode:characters_to_binary([Fatness, Bits, "-", Type]), - Count = optimize_count(MaxMem), + Miner = filename:join(platform_dir(), unicode:characters_to_binary([Fatness, Bits, "-", Type])), + Count = optimize_count(MaxCores, MaxMem), Instance = #{<<"executable">> => Miner}, Workers = lists:duplicate(Count, Instance), Profile = - [{pubkey, PubKey}, - {workers, Workers}, - {pool_admin_url, Eureka}], + [{pubkey, PubKey}, + {workers, Workers}, + {pool_admin_url, Eureka}, + {additional_keys, Keys}], ok = gmc_gui:message({notice, "Starting..."}), ok = gmc_gui:message({notice, ["Miner: ", Miner]}), {ok, Apps} = gmhc_app:start(Profile), @@ -270,17 +245,41 @@ do_start_stop(#s{acc = PubKey, network = Network, max_mem = MaxMem}) -> disconnected], lists:foreach(fun gmhc_events:ensure_subscribed/1, Events). -optimize_count(MaxMem) -> + +optimize_count(MaxC, MaxM) -> + MapSize = 3550722201, + MaxCores = max(1, MaxC), + MaxMem = max(MapSize, MaxM), {Procs, Memory} = proc_mem(), - MeanMaps = min(MaxMem, Memory) div 3550722201, - Recommended = max(min(Procs, MeanMaps) - 1, 1), + MeanMaps = min(MaxMem, Memory) div MapSize, + Recommended = min(MaxCores, max(min(Procs, MeanMaps) - 1, 1)), Notice = fun(F, A) -> gmc_gui:message({notice, io_lib:format(F, A)}) end, ok = Notice("Physical Processors: ~p", [Procs]), ok = Notice("Physical Memory: ~p", [Memory]), + ok = Notice("Max Processor Commit: ~p", [MaxCores]), + ok = Notice("Max Memory Commit: ~p", [MaxMem]), ok = Notice("29-bit Mean Map Space: ~p", [MeanMaps]), ok = Notice("Workers: ~p", [Recommended]), Recommended. + +platform_dir() -> + #{deps := Deps} = zx_daemon:meta(), + AppID = lists:keyfind("cuckoo_cpu", 2, Deps), + Priv = filename:join(zx_lib:ppath(lib, AppID), "priv"), + Dir = + case os:type() of + {unix, linux} -> + "linux_x86_64"; + {unix, darwin} -> + % TODO: Check M2 vs x86 + "mac_m2"; + {win32, nt} -> + "win_x86_64" + end, + filename:join(Priv, Dir). + + proc_mem() -> case os:type() of {unix, linux} -> @@ -334,7 +333,15 @@ run_gmc_conf(State) -> do_conf({Network, AccID, Keys, MaxCores, MaxMem}, State) -> - State#s{network = Network, acc = AccID, keys = Keys, max_cores = MaxCores, max_mem = MaxMem}. + ok = gmc_gui:set_account(AccID), + NewState = + State#s{network = Network, + acc = AccID, + keys = Keys, + max_cores = MaxCores, + max_mem = MaxMem}, + ok = persist(NewState), + NewState. %%% Utils -- 2.30.2 From 74c7f2bb9cb28483673cd9e47047fdccb332f020 Mon Sep 17 00:00:00 2001 From: Craig Everett Date: Tue, 27 May 2025 21:03:50 +0900 Subject: [PATCH 4/8] Update deps --- zomp.meta | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zomp.meta b/zomp.meta index 6644827..68c8b64 100644 --- a/zomp.meta +++ b/zomp.meta @@ -1,18 +1,18 @@ {name,"GajuMine"}. {type,gui}. {modules,[]}. -{author,"Craig Everett"}. {prefix,"gmc"}. +{author,"Craig Everett"}. {desc,"Mining client for the Gajumaru Root"}. {package_id,{"qpq","gajumine",{0,2,0}}}. -{deps,[{"uwiger","gmconfig",{0,1,2}}, +{deps,[{"uwiger","gmhive_client",{0,4,0}}, + {"uwiger","gmcuckoo",{1,1,1}}, + {"uwiger","gmhive_worker",{0,3,0}}, + {"uwiger","gmconfig",{0,1,2}}, {"uwiger","gproc",{1,0,1}}, - {"uwiger","gmhive_client",{0,2,1}}, {"qpq","cuckoo_cpu",{0,2,0}}, - {"uwiger","gmhive_worker",{0,1,1}}, {"uwiger","gmhive_protocol",{0,1,1}}, {"uwiger","enoise",{1,3,0}}, - {"uwiger","gmcuckoo",{1,1,0}}, {"uwiger","setup",{2,2,4}}, {"otpr","hakuzaru",{0,6,1}}, {"otpr","gajudesk",{0,5,3}}, -- 2.30.2 From f0326f4b9930305536ece0ebdadacacf8a9fd205 Mon Sep 17 00:00:00 2001 From: Craig Everett Date: Tue, 27 May 2025 21:55:47 +0900 Subject: [PATCH 5/8] Fix cuckoo_cpu priv dir lookup --- src/gmc_con.erl | 4 +--- zomp.meta | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/gmc_con.erl b/src/gmc_con.erl index 45d146a..7c90ea5 100644 --- a/src/gmc_con.erl +++ b/src/gmc_con.erl @@ -264,9 +264,7 @@ optimize_count(MaxC, MaxM) -> platform_dir() -> - #{deps := Deps} = zx_daemon:meta(), - AppID = lists:keyfind("cuckoo_cpu", 2, Deps), - Priv = filename:join(zx_lib:ppath(lib, AppID), "priv"), + Priv = cuckoo_cpu:priv(), Dir = case os:type() of {unix, linux} -> diff --git a/zomp.meta b/zomp.meta index 68c8b64..cd1ccc2 100644 --- a/zomp.meta +++ b/zomp.meta @@ -5,12 +5,12 @@ {author,"Craig Everett"}. {desc,"Mining client for the Gajumaru Root"}. {package_id,{"qpq","gajumine",{0,2,0}}}. -{deps,[{"uwiger","gmhive_client",{0,4,0}}, +{deps,[{"qpq","cuckoo_cpu",{0,3,0}}, + {"uwiger","gmhive_client",{0,4,0}}, {"uwiger","gmcuckoo",{1,1,1}}, {"uwiger","gmhive_worker",{0,3,0}}, {"uwiger","gmconfig",{0,1,2}}, {"uwiger","gproc",{1,0,1}}, - {"qpq","cuckoo_cpu",{0,2,0}}, {"uwiger","gmhive_protocol",{0,1,1}}, {"uwiger","enoise",{1,3,0}}, {"uwiger","setup",{2,2,4}}, -- 2.30.2 From 7f2b3c6a45a9d5540fe5fdcd16b691fc49f0b953 Mon Sep 17 00:00:00 2001 From: Craig Everett Date: Tue, 27 May 2025 22:08:12 +0900 Subject: [PATCH 6/8] Fix config key --- src/gmc_con.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gmc_con.erl b/src/gmc_con.erl index 7c90ea5..4670086 100644 --- a/src/gmc_con.erl +++ b/src/gmc_con.erl @@ -226,10 +226,10 @@ do_start_stop(#s{acc = PubKey, keys = Keys, network = Network, max_cores = MaxCo Instance = #{<<"executable">> => Miner}, Workers = lists:duplicate(Count, Instance), Profile = - [{pubkey, PubKey}, - {workers, Workers}, - {pool_admin_url, Eureka}, - {additional_keys, Keys}], + [{pubkey, PubKey}, + {workers, Workers}, + {pool_admin_url, Eureka}, + {extra_pubkeys, Keys}], ok = gmc_gui:message({notice, "Starting..."}), ok = gmc_gui:message({notice, ["Miner: ", Miner]}), {ok, Apps} = gmhc_app:start(Profile), -- 2.30.2 From 558c2d6920f153efcfcb911b9cffc01470bc5aa8 Mon Sep 17 00:00:00 2001 From: Craig Everett Date: Tue, 27 May 2025 22:27:04 +0900 Subject: [PATCH 7/8] Ensure the madness of Windows console noises do not plague the ears of the innocent --- src/gmc_gui.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gmc_gui.erl b/src/gmc_gui.erl index f040b84..a026f62 100644 --- a/src/gmc_gui.erl +++ b/src/gmc_gui.erl @@ -102,7 +102,7 @@ init(Prefs) -> Labels = [J("ID"), J("Target"), J("Maps/s"), J("Candidate"), J("Height"), J("BlockHash")], {Grid, [ID_C, DiffC, PerfC, CandyC, HeightC, BlockC]} = display_box(Frame, Labels), - Style = ?wxDEFAULT bor ?wxTE_MULTILINE bor ?wxTE_READONLY, + Style = ?wxTE_MULTILINE bor ?wxTE_READONLY, MessSz = wxStaticBoxSizer:new(?wxVERTICAL, Frame, [{label, J("Messages")}]), MessC = wxTextCtrl:new(Frame, ?wxID_ANY, [{style, Style}]), _ = wxStaticBoxSizer:add(MessSz, MessC, zxw:flags(wide)), -- 2.30.2 From 104f303a8ade008bcd085cab0eb31533d9ab961c Mon Sep 17 00:00:00 2001 From: Craig Everett Date: Tue, 27 May 2025 22:48:40 +0900 Subject: [PATCH 8/8] Add tags, fix default notices --- ebin/gajumine.app | 2 +- src/gajumine.erl | 2 +- src/gmc_con.erl | 2 +- src/gmc_conf.erl | 2 +- src/gmc_gui.erl | 2 +- src/gmc_sup.erl | 2 +- zomp.meta | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ebin/gajumine.app b/ebin/gajumine.app index 2fa06ad..c7be8a7 100644 --- a/ebin/gajumine.app +++ b/ebin/gajumine.app @@ -4,5 +4,5 @@ {included_applications,[]}, {applications,[stdlib,kernel]}, {vsn,"0.2.0"}, - {modules,[gajumine,gmc_con,gmc_gui,gmc_setup,gmc_sup]}, + {modules,[gajumine,gmc_con,gmc_conf,gmc_gui,gmc_sup]}, {mod,{gajumine,[]}}]}. diff --git a/src/gajumine.erl b/src/gajumine.erl index 0385105..f11f36c 100644 --- a/src/gajumine.erl +++ b/src/gajumine.erl @@ -6,7 +6,7 @@ -vsn("0.2.0"). -behavior(application). -author("Craig Everett "). --copyright("Craig Everett "). +-copyright("QPQ AG "). -license("GPL-3.0-or-later"). -export([start/2, stop/1, exec_bin_dir/0]). diff --git a/src/gmc_con.erl b/src/gmc_con.erl index 4670086..2e9463f 100644 --- a/src/gmc_con.erl +++ b/src/gmc_con.erl @@ -5,7 +5,7 @@ -module(gmc_con). -vsn("0.2.0"). -author("Craig Everett "). --copyright("Craig Everett "). +-copyright("QPQ AG "). -license("GPL-3.0-or-later"). -behavior(gen_server). diff --git a/src/gmc_conf.erl b/src/gmc_conf.erl index 771b14e..8cdc35f 100644 --- a/src/gmc_conf.erl +++ b/src/gmc_conf.erl @@ -5,7 +5,7 @@ -module(gmc_conf). -vsn("0.2.0"). -author("Craig Everett "). --copyright("Craig Everett "). +-copyright("QPQ AG "). -license("GPL-3.0-or-later"). -behavior(wx_object). diff --git a/src/gmc_gui.erl b/src/gmc_gui.erl index a026f62..553f737 100644 --- a/src/gmc_gui.erl +++ b/src/gmc_gui.erl @@ -5,7 +5,7 @@ -module(gmc_gui). -vsn("0.2.0"). -author("Craig Everett "). --copyright("Craig Everett "). +-copyright("QPQ AG "). -license("GPL-3.0-or-later"). -behavior(wx_object). diff --git a/src/gmc_sup.erl b/src/gmc_sup.erl index 6573c91..04134af 100644 --- a/src/gmc_sup.erl +++ b/src/gmc_sup.erl @@ -15,7 +15,7 @@ -vsn("0.2.0"). -behaviour(supervisor). -author("Craig Everett "). --copyright("Craig Everett "). +-copyright("QPQ AG "). -license("GPL-3.0-or-later"). -export([start_link/0]). diff --git a/zomp.meta b/zomp.meta index cd1ccc2..37ad5e7 100644 --- a/zomp.meta +++ b/zomp.meta @@ -28,9 +28,9 @@ {key_name,none}. {a_email,"craigeverett@qpq.swiss"}. {c_email,"craigeverett@qpq.swiss"}. -{copyright,"Craig Everett"}. +{copyright,"QPQ AG"}. {file_exts,[]}. {license,"GPL-3.0-or-later"}. {repo_url,"https://git.qpq.swiss/zxq9/GajuMine"}. -{tags,[]}. +{tags,["qpq","gaju","gajumaru","hive","mining","crypto"]}. {ws_url,"https://gajumining.com"}. -- 2.30.2