Skip to content

Commit

Permalink
Track solutions found and rejected for a solo miner
Browse files Browse the repository at this point in the history
Also introduce ar_mining_router to route requests based on the
node configuration, e.g.:
solo miner vs. cm miner vs. cm exit node vs. pool miner vs. pool cm
  • Loading branch information
JamesPiechota committed Jul 19, 2024
1 parent e39b4cc commit 2ebe7cc
Show file tree
Hide file tree
Showing 12 changed files with 324 additions and 235 deletions.
13 changes: 6 additions & 7 deletions apps/arweave/include/ar_mining.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,28 @@
session_key = not_set, %% serialized
start_interval_number = not_set, %% serialized
step_number = not_set, %% serialized
label = <<"not_set">> %% not atom, for prevent atom table pollution DoS
label = <<"not_set">> %% not atom, in order to prevent atom table pollution DoS
}).

-record(mining_solution, {
last_step_checkpoints = [],
merkle_rebase_threshold = 0,
last_step_checkpoints = [],
mining_address = << 0:256 >>,
next_seed = << 0:(8 * 48) >>,
next_vdf_difficulty = 0,
nonce = 0,
nonce_limiter_output = << 0:256 >>,
partition_number = 0,
partition_upper_bound = 0,
poa1 = #poa{},
poa2 = #poa{},
preimage = << 0:256 >>,
recall_byte1 = 0,
recall_byte2 = undefined,
seed = << 0:(8 * 48) >>,
solution_hash = << 0:256 >>,
start_interval_number = 0,
step_number = 0,
steps = [],
seed = << 0:(8 * 48) >>,
mining_address = << 0:256 >>,
partition_upper_bound = 0
steps = []
}).

-endif.
5 changes: 4 additions & 1 deletion apps/arweave/src/ar_chain_stats.erl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
-behaviour(gen_server).

-include_lib("arweave/include/ar.hrl").
-include_lib("arweave/include/ar_config.hrl").
-include_lib("arweave/include/ar_chain_stats.hrl").
-include_lib("eunit/include/eunit.hrl").

Expand Down Expand Up @@ -38,7 +39,9 @@ get_forks(StartTime) ->
init([]) ->
%% Trap exit to avoid corrupting any open files on quit..
process_flag(trap_exit, true),
ok = ar_kv:open(filename:join(?ROCKS_DB_DIR, "forks_db"), forks_db),
{ok, Config} = application:get_env(arweave, config),
RocksDBDir = filename:join(Config#config.data_dir, ?ROCKS_DB_DIR),
ok = ar_kv:open(filename:join(RocksDBDir, "forks_db"), forks_db),
{ok, #{}}.

handle_call({get_forks, StartTime}, _From, State) ->
Expand Down
4 changes: 2 additions & 2 deletions apps/arweave/src/ar_http_iface_middleware.erl
Original file line number Diff line number Diff line change
Expand Up @@ -3260,8 +3260,8 @@ handle_mining_h2(Req, Pid) ->
Payload) end),
{200, #{}, <<>>, Req2};
_ ->
ar_mining_server:prepare_and_post_solution(Candidate),
ar_mining_stats:h2_received_from_peer(Peer),
ar_mining_router:prepare_solution(Candidate),
{200, #{}, <<>>, Req}
end
end;
Expand All @@ -3288,7 +3288,7 @@ handle_mining_cm_publish(Req, Pid) ->
?LOG_INFO("Block candidate ~p from ~p ~n", [
ar_util:encode(Solution#mining_solution.solution_hash),
ar_util:format_peer(Peer)]),
ar_mining_server:post_solution(Solution),
ar_mining_router:post_solution(Solution),
{200, #{}, <<>>, Req}
end;
{error, _} ->
Expand Down
88 changes: 88 additions & 0 deletions apps/arweave/src/ar_mining_router.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
-module(ar_mining_router).

-behaviour(gen_server).

-export([start_link/0, prepare_solution/1, post_solution/1]).

-export([init/1, handle_cast/2, handle_call/3, handle_info/2, terminate/2]).

-include_lib("arweave/include/ar.hrl").
-include_lib("arweave/include/ar_config.hrl").
-include_lib("arweave/include/ar_mining.hrl").
-include_lib("eunit/include/eunit.hrl").
-include_lib("stdlib/include/ms_transform.hrl").

-record(state, {
}).

%%%===================================================================
%%% Public interface.
%%%===================================================================

%% @doc Start the gen_server.
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

prepare_solution(Candidate) ->
%% A pool client does not validate VDF before sharing a solution.
{ok, Config} = application:get_env(arweave, config),
ar_mining_server:prepare_solution(Candidate, Config#config.is_pool_client).

post_solution(Solution) ->
{ok, Config} = application:get_env(arweave, config),
post_solution(Config#config.cm_exit_peer, Config#config.is_pool_client, Solution).

%%%===================================================================
%%% Generic server callbacks.
%%%===================================================================

init([]) ->
{ok, #state{}}.

handle_call(Request, _From, State) ->
?LOG_WARNING([{event, unhandled_call}, {module, ?MODULE}, {request, Request}]),
{reply, ok, State}.

handle_cast(Cast, State) ->
?LOG_WARNING([{event, unhandled_cast}, {module, ?MODULE}, {cast, Cast}]),
{noreply, State}.

handle_info(Message, State) ->
?LOG_WARNING([{event, unhandled_info}, {module, ?MODULE}, {message, Message}]),
{noreply, State}.

terminate(_Reason, _State) ->
ok.

%%%===================================================================
%%% Private functions.
%%%===================================================================

post_solution(not_set, true, Solution) ->
%% When posting a partial solution the pool client will skip many of the validation steps
%% that are normally performed before sharing a solution.
ar_pool:post_partial_solution(Solution);
post_solution(not_set, _IsPoolClient, Solution) ->
ar_mining_server:validate_solution(Solution);
post_solution(ExitPeer, true, Solution) ->
case ar_http_iface_client:post_partial_solution(ExitPeer, Solution) of
{ok, _} ->
ok;
{error, Reason} ->
?LOG_WARNING([{event, found_partial_solution_but_failed_to_reach_exit_node},
{reason, io_lib:format("~p", [Reason])}]),
ar:console("We found a partial solution but failed to reach the exit node, "
"error: ~p.", [io_lib:format("~p", [Reason])])
end;
post_solution(ExitPeer, _IsPoolClient, Solution) ->
case ar_http_iface_client:cm_publish_send(ExitPeer, Solution) of
{ok, _} ->
ok;
{error, Reason} ->
?LOG_WARNING([{event, solution_rejected},
{reason, failed_to_reach_exit_node},
{message, io_lib:format("~p", [Reason])}]),
ar:console("We found a solution but failed to reach the exit node, "
"error: ~p.", [io_lib:format("~p", [Reason])]),
ar_mining_stats:solution(rejected)
end.
Loading

0 comments on commit 2ebe7cc

Please sign in to comment.