Skip to content

Commit

Permalink
feat: simplified tls protocol support
Browse files Browse the repository at this point in the history
  • Loading branch information
hlolli committed Dec 4, 2023
1 parent 511f1d2 commit a799c57
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 207 deletions.
2 changes: 1 addition & 1 deletion apps/arweave/include/ar.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@
%% The global sequence number of the nonce limiter step at which the block was found.
global_step_number = 1,
%% ?VDF_CHECKPOINT_COUNT_IN_STEP checkpoints from the most recent step in the nonce
%% limiter process.
%% limiter process.
last_step_checkpoints = [],
%% A list of the output of each step of the nonce limiting process. Note: each step
%% has ?VDF_CHECKPOINT_COUNT_IN_STEP checkpoints, the last of which is that step's output.
Expand Down
4 changes: 2 additions & 2 deletions apps/arweave/include/ar_config.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,6 @@
transaction_blacklist_urls = [],
transaction_whitelist_files = [],
transaction_whitelist_urls = [],
gateway_domain = not_set,
gateway_custom_domains = [],
requests_per_minute_limit = ?DEFAULT_REQUESTS_PER_MINUTE_LIMIT,
requests_per_minute_limit_by_ip = #{},
max_propagation_peers = ?DEFAULT_MAX_PROPAGATION_PEERS,
Expand Down Expand Up @@ -186,6 +184,8 @@
defragmentation_modules = [],
block_throttle_by_ip_interval = ?DEFAULT_BLOCK_THROTTLE_BY_IP_INTERVAL_MS,
block_throttle_by_solution_interval = ?DEFAULT_BLOCK_THROTTLE_BY_SOLUTION_INTERVAL_MS,
tls_cert_file = not_set, %% required to enable TLS
tls_key_file = not_set, %% required to enable TLS
p3 = #p3_config{},
coordinated_mining = false,
cm_api_secret = not_set,
Expand Down
33 changes: 20 additions & 13 deletions apps/arweave/src/ar.erl
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ show_help() ->
{"defragment_module",
"Run defragmentation of the chunk storage files from the given storage module."
" Assumes the run_defragmentation flag is provided."},
{"tls_cert_file",
"Optional path to the TLS certificate file for TLS support, depends on 'tls_key_file' being set as well."},
{"tls_key_file",
"The path to the TLS key file for TLS support, depends on 'tls_cert_file' being set as well."},
{"coordinated_mining", "Enable coordinated mining. You need to also set "
"cm_api_secret, cm_peer, and cm_exit_peer."},
{"cm_api_secret", "Coordinated mining secret for authenticated "
Expand Down Expand Up @@ -424,10 +428,14 @@ parse_cli_args(["enable", Feature | Rest ], C = #config{ enable = Enabled }) ->
parse_cli_args(Rest, C#config{ enable = [ list_to_atom(Feature) | Enabled ] });
parse_cli_args(["disable", Feature | Rest ], C = #config{ disable = Disabled }) ->
parse_cli_args(Rest, C#config{ disable = [ list_to_atom(Feature) | Disabled ] });
parse_cli_args(["gateway", Domain | Rest ], C) ->
parse_cli_args(Rest, C#config{ gateway_domain = list_to_binary(Domain) });
parse_cli_args(["custom_domain", Domain | Rest], C = #config{ gateway_custom_domains = Ds }) ->
parse_cli_args(Rest, C#config{ gateway_custom_domains = [ list_to_binary(Domain) | Ds ] });
parse_cli_args(["gateway", _ | Rest ], C) ->
?LOG_WARNING("Deprecated option found 'gateway': "
" this option has been removed and is now a no-op.", []),
parse_cli_args(Rest, C#config{ });
parse_cli_args(["custom_domain", _ | Rest], C = #config{ }) ->
?LOG_WARNING("Deprecated option found 'custom_domain': "
" this option has been removed and is a no-op.", []),
parse_cli_args(Rest, C#config{ });
parse_cli_args(["requests_per_minute_limit", Num | Rest], C) ->
parse_cli_args(Rest, C#config{ requests_per_minute_limit = list_to_integer(Num) });
parse_cli_args(["max_propagation_peers", Num | Rest], C) ->
Expand Down Expand Up @@ -498,6 +506,14 @@ parse_cli_args(["defragment_module", DefragModuleString | Rest], C) ->
io:format("~ndefragment_module value must be in the [number],[address] format.~n~n"),
erlang:halt()
end;
parse_cli_args(["tls_cert_file", CertFilePath | Rest], C) ->
AbsCertFilePath = filename:absname(CertFilePath),
ar_util:assert_file_exists_and_readable(AbsCertFilePath),
parse_cli_args(Rest, C#config{ tls_cert_file = AbsCertFilePath });
parse_cli_args(["tls_key_file", KeyFilePath | Rest], C) ->
AbsKeyFilePath = filename:absname(KeyFilePath),
ar_util:assert_file_exists_and_readable(AbsKeyFilePath),
parse_cli_args(Rest, C#config{ tls_key_file = AbsKeyFilePath });
parse_cli_args(["coordinated_mining" | Rest], C) ->
parse_cli_args(Rest, C#config{ coordinated_mining = true });
parse_cli_args(["cm_api_secret", CMSecret | Rest], C)
Expand Down Expand Up @@ -623,15 +639,6 @@ start(normal, _Args) ->
prometheus_registry:register_collector(ar_metrics_collector),
%% Register custom metrics.
ar_metrics:register(Config#config.metrics_dir),
%% Verify port collisions when gateway is enabled.
case {Config#config.port, Config#config.gateway_domain} of
{P, D} when is_binary(D) andalso (P == 80 orelse P == 443) ->
io:format(
"~nThe port must be different than 80 or 443 when the gateway is enabled.~n~n"),
erlang:halt();
_ ->
do_nothing
end,
%% Start other apps which we depend on.
ok = prepare_graphql(),
case Config#config.ipfs_pin of
Expand Down
25 changes: 7 additions & 18 deletions apps/arweave/src/ar_config.erl
Original file line number Diff line number Diff line change
Expand Up @@ -390,25 +390,14 @@ parse_options([{<<"disable">>, Features} | Rest], Config) when is_list(Features)
end;
parse_options([{<<"disable">>, Features} | _], _) ->
{error, {bad_type, disable, array}, Features};

parse_options([{<<"gateway">>, Domain} | Rest], Config) when is_binary(Domain) ->
parse_options(Rest, Config#config{ gateway_domain = Domain });
parse_options([{<<"gateway">>, false} | Rest], Config) ->
parse_options([{<<"gateway">>, _} | Rest], Config) ->
?LOG_WARNING("Deprecated option found 'gateway': "
" this option has been removed and is a no-op.", []),
parse_options(Rest, Config);
parse_options([{<<"custom_domains">>, _} | Rest], Config) ->
?LOG_WARNING("Deprecated option found 'custom_domains': "
" this option has been removed and is a no-op.", []),
parse_options(Rest, Config);
parse_options([{<<"gateway">>, Gateway} | _], _) ->
{error, {bad_type, gateway, string}, Gateway};

parse_options([{<<"custom_domains">>, CustomDomains} | Rest], Config)
when is_list(CustomDomains) ->
case lists:all(fun is_binary/1, CustomDomains) of
true ->
parse_options(Rest, Config#config{ gateway_custom_domains = CustomDomains });
false ->
{error, bad_custom_domains}
end;
parse_options([{<<"custom_domains">>, CustomDomains} | _], _) ->
{error, {bad_type, custom_domains, array}, CustomDomains};

parse_options([{<<"webhooks">>, WebhookConfigs} | Rest], Config) when is_list(WebhookConfigs) ->
case parse_webhooks(WebhookConfigs, []) of
{ok, ParsedWebhooks} ->
Expand Down
18 changes: 3 additions & 15 deletions apps/arweave/src/ar_http_iface_middleware.erl
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@
%% middlewares. It uses the `handler` env value set by cowboy_router
%% to determine whether or not it should run, otherwise it lets
%% the cowboy_handler middleware run prometheus_cowboy2_handler.
execute(Req, #{ handler := ar_http_iface_handler } = Env) ->
execute(Req, #{ handler := ar_http_iface_handler }) ->
Pid = self(),
Req1 = with_arql_semaphore_req_field(Req, Env),
HandlerPid = spawn_link(fun() ->
Pid ! {handled, handle(Req1, Pid)}
Pid ! {handled, handle(Req, Pid)}
end),
{ok, TimeoutRef} = timer:send_after(
?HANDLER_TIMEOUT,
Expand All @@ -47,8 +46,6 @@ execute(Req, Env) ->
%%% Private functions.
%%%===================================================================

with_arql_semaphore_req_field(Req, #{ arql_semaphore := Name }) ->
Req#{ '_ar_http_iface_middleware_arql_semaphore' => Name }.

%% @doc In order to be able to have a handler-side timeout, we need to
%% handle the request asynchronously. However, cowboy doesn't allow
Expand Down Expand Up @@ -240,7 +237,6 @@ handle(<<"GET">>, [<<"queue">>], Req, _Pid) ->
%% Return additional information about the transaction with the given identifier (hash).
%% GET request to endpoint /tx/{hash}/status.
handle(<<"GET">>, [<<"tx">>, Hash, <<"status">>], Req, _Pid) ->
ar_semaphore:acquire(arql_semaphore(Req), 5000),
case ar_node:is_joined() of
false ->
not_joined(Req);
Expand Down Expand Up @@ -282,7 +278,6 @@ handle(<<"POST">>, [<<"arql">>], Req, Pid) ->
{ok, Config} = application:get_env(arweave, config),
case lists:member(serve_arql, Config#config.enable) of
true ->
ar_semaphore:acquire(arql_semaphore(Req), 5000),
case ar_node:is_joined() of
false ->
not_joined(Req);
Expand Down Expand Up @@ -1108,7 +1103,6 @@ handle(<<"GET">>, [<<"wallet">>, Addr, <<"txs">>], Req, _Pid) ->
{ok, Config} = application:get_env(arweave, config),
case lists:member(serve_wallet_txs, Config#config.enable) of
true ->
ar_semaphore:acquire(arql_semaphore(Req), 5000),
{Status, Headers, Body} = handle_get_wallet_txs(Addr, none),
{Status, Headers, Body, Req};
false ->
Expand All @@ -1122,7 +1116,6 @@ handle(<<"GET">>, [<<"wallet">>, Addr, <<"txs">>, EarliestTX], Req, _Pid) ->
{ok, Config} = application:get_env(arweave, config),
case lists:member(serve_wallet_txs, Config#config.enable) of
true ->
ar_semaphore:acquire(arql_semaphore(Req), 5000),
{Status, Headers, Body} = handle_get_wallet_txs(Addr, ar_util:decode(EarliestTX)),
{Status, Headers, Body, Req};
false ->
Expand All @@ -1136,7 +1129,6 @@ handle(<<"GET">>, [<<"wallet">>, Addr, <<"deposits">>], Req, _Pid) ->
{ok, Config} = application:get_env(arweave, config),
case lists:member(serve_wallet_deposits, Config#config.enable) of
true ->
ar_semaphore:acquire(arql_semaphore(Req), 5000),
case catch ar_arql_db:select_txs_by([{to, [Addr]}]) of
TXMaps when is_list(TXMaps) ->
TXIDs = lists:map(fun(#{ id := ID }) -> ID end, TXMaps),
Expand All @@ -1155,7 +1147,6 @@ handle(<<"GET">>, [<<"wallet">>, Addr, <<"deposits">>, EarliestDeposit], Req, _P
{ok, Config} = application:get_env(arweave, config),
case lists:member(serve_wallet_deposits, Config#config.enable) of
true ->
ar_semaphore:acquire(arql_semaphore(Req), 5000),
case catch ar_arql_db:select_txs_by([{to, [Addr]}]) of
TXMaps when is_list(TXMaps) ->
TXIDs = lists:map(fun(#{ id := ID }) -> ID end, TXMaps),
Expand Down Expand Up @@ -1533,9 +1524,6 @@ handle_get_block_index_range(Start, End, CurrentHeight, RecentBI, Req, Encoding)
sendfile(Filename) ->
{sendfile, 0, filelib:file_size(Filename), Filename}.

arql_semaphore(#{'_ar_http_iface_middleware_arql_semaphore' := Name}) ->
Name.

not_found(Req) ->
{400, #{}, <<"Request type not found.">>, Req}.

Expand Down Expand Up @@ -2227,7 +2215,7 @@ check_api_secret(Header, Secret, APIName, Req) ->
%% Reduce efficiency of timing attacks by sleeping randomly between 1-2s.
timer:sleep(rand:uniform(1000) + 1000),
{reject, {
421, #{},
421, #{},
<<APIName/bitstring, " disabled or invalid ", APIName/bitstring, " secret in request.">>
}}
end,
Expand Down
Loading

0 comments on commit a799c57

Please sign in to comment.