Skip to content

Commit

Permalink
Simplify /info and /recent serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesPiechota committed Jul 8, 2024
1 parent 2d62fed commit 423df01
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 62 deletions.
8 changes: 4 additions & 4 deletions apps/arweave/include/ar.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,11 @@

%% The number of blocks returned in the /info 'recent' field
-ifdef(DEBUG).
-define(INFO_BLOCKS, 5).
-define(INFO_BLOCKS_WITHOUT_TIMESTAMP, 2).
-define(RECENT_BLOCKS, 5).
-define(RECENT_BLOCKS_WITHOUT_TIMESTAMP, 2).
-else.
-define(INFO_BLOCKS, 10).
-define(INFO_BLOCKS_WITHOUT_TIMESTAMP, 5).
-define(RECENT_BLOCKS, 10).
-define(RECENT_BLOCKS_WITHOUT_TIMESTAMP, 5).
-endif.

%% How long to wait before giving up on test(s).
Expand Down
2 changes: 0 additions & 2 deletions apps/arweave/src/ar_block_cache.erl
Original file line number Diff line number Diff line change
Expand Up @@ -474,8 +474,6 @@ update_timestamp(Tab, H, ReceiveTimestamp) ->
ok
end;
[] ->
?LOG_ERROR([
{event, ignored_block_missing_from_cache}, {block, ar_util:encode(H)}]),
not_found
end.

Expand Down
2 changes: 0 additions & 2 deletions apps/arweave/src/ar_block_index.erl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
-export([init/1, update/2, member/1, get_list/1, get_list_by_hash/1, get_element_by_height/1,
get_block_bounds/1, get_intersection/2, get_intersection/1, get_range/2]).

-include_lib("arweave/include/ar.hrl").

%%%===================================================================
%%% Public interface.
%%%===================================================================
Expand Down
2 changes: 1 addition & 1 deletion apps/arweave/src/ar_data_sync.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1470,7 +1470,7 @@ handle_info({event, disksup, {remaining_disk_space, StoreID, true, _Percentage,
handle_info({event, disksup, _}, State) ->
{noreply, State};

handle_info({'EXIT', _, normal}, State) ->
handle_info({'EXIT', _PID, normal}, State) ->
{noreply, State};

handle_info({'DOWN', _, process, _, normal}, State) ->
Expand Down
4 changes: 2 additions & 2 deletions apps/arweave/src/ar_http_iface_client.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,7 @@ get_info(Peer, Type) ->
case get_info(Peer) of
info_unavailable -> info_unavailable;
Info ->
maps:get(Type, Info)
maps:get(atom_to_binary(Type), Info)
end.
get_info(Peer) ->
case
Expand All @@ -1102,7 +1102,7 @@ get_info(Peer) ->
{ok, {{<<"200">>, _}, _, JSON, _, _}} ->
case ar_serialize:json_decode(JSON, [return_maps]) of
{ok, JsonMap} ->
ar_serialize:json_map_to_info_map(JsonMap);
JsonMap;
{error, _} ->
info_unavailable
end;
Expand Down
3 changes: 3 additions & 0 deletions apps/arweave/src/ar_http_iface_middleware.erl
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ handle(<<"GET">>, [], Req, _Pid) ->
handle(<<"GET">>, [<<"info">>], Req, _Pid) ->
{200, #{}, ar_serialize:jsonify(ar_info:get_info()), Req};

handle(<<"GET">>, [<<"recent">>], Req, _Pid) ->
{200, #{}, ar_serialize:jsonify(ar_info:get_recent()), Req};

handle(<<"GET">>, [<<"is_tx_blacklisted">>, EncodedTXID], Req, _Pid) ->
case ar_util:safe_decode(EncodedTXID) of
{error, invalid} ->
Expand Down
51 changes: 27 additions & 24 deletions apps/arweave/src/ar_info.erl
Original file line number Diff line number Diff line change
@@ -1,67 +1,70 @@
%%%
%%% @doc Gathers the data for the /info and /recent endpoints.
%%%

-module(ar_info).

-export([get_keys/0, get_info/0]).
-export([get_info/0, get_recent/0]).

-include_lib("arweave/include/ar.hrl").

get_keys() ->
[
network, version, release, height, current, blocks, peers,
queue_length, node_state_latency, recent
].

get_info() ->
{Time, Current} =
timer:tc(fun() -> ar_node:get_current_block_hash() end),
{Time2, Height} =
timer:tc(fun() -> ar_node:get_height() end),
[{_, BlockCount}] = ets:lookup(ar_header_sync, synced_blocks),
#{
network => list_to_binary(?NETWORK_NAME),
version => ?CLIENT_VERSION,
release => ?RELEASE_NUMBER,
height =>
<<"network">> => list_to_binary(?NETWORK_NAME),
<<"version">> => ?CLIENT_VERSION,
<<"release">> => ?RELEASE_NUMBER,
<<"height">> =>
case Height of
not_joined -> -1;
H -> H
end,
current =>
<<"current">> =>
case is_atom(Current) of
true -> atom_to_binary(Current, utf8);
false -> ar_util:encode(Current)
end,
blocks => BlockCount,
peers => prometheus_gauge:value(arweave_peer_count),
queue_length =>
<<"blocks">> => BlockCount,
<<"peers">> => prometheus_gauge:value(arweave_peer_count),
<<"queue_length">> =>
element(
2,
erlang:process_info(whereis(ar_node_worker), message_queue_len)
),
node_state_latency => (Time + Time2) div 2,
<<"node_state_latency">> => (Time + Time2) div 2
}.

get_recent() ->
#{
%% {
%% "id": <indep_hash>,
%% "received": <received_timestamp>"
%% }
recent => get_recent_blocks(Height)
<<"blocks">> => get_recent_blocks(ar_node:get_height())
}.

get_recent_blocks(CurrentHeight) ->
lists:foldl(
fun({H, _WeaveSize, _TXRoot}, Acc) ->
Acc ++ [#{
id => ar_util:encode(H),
received => get_block_timestamp(H, length(Acc))
<<"id">> => ar_util:encode(H),
<<"received">> => get_block_timestamp(H, length(Acc))
}]
end,
[],
lists:sublist(ar_block_index:get_list(CurrentHeight), ?INFO_BLOCKS)
lists:sublist(ar_block_index:get_list(CurrentHeight), ?RECENT_BLOCKS)
).

get_block_timestamp(H, Depth) when Depth =< ?INFO_BLOCKS_WITHOUT_TIMESTAMP ->
"pending";
get_block_timestamp(H, Depth) when Depth < ?RECENT_BLOCKS_WITHOUT_TIMESTAMP ->
<<"pending">>;
get_block_timestamp(H, _Depth) ->
B = ar_block_cache:get(block_cache, H),
case B#block.receive_timestamp of
undefined -> "pending";
undefined -> <<"pending">>;
Timestamp -> ar_util:timestamp_to_seconds(Timestamp)
end.
end.

16 changes: 1 addition & 15 deletions apps/arweave/src/ar_serialize.erl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
json_map_to_candidate/1,
jobs_to_json_struct/1, json_struct_to_jobs/1,
partial_solution_response_to_json_struct/1,
pool_cm_jobs_to_json_struct/1, json_map_to_pool_cm_jobs/1, json_map_to_info_map/1]).
pool_cm_jobs_to_json_struct/1, json_map_to_pool_cm_jobs/1]).

-include_lib("arweave/include/ar.hrl").
-include_lib("arweave/include/ar_vdf.hrl").
Expand Down Expand Up @@ -1406,7 +1406,6 @@ json_struct_to_poa({JSONStruct}) ->
chunk = ar_util:decode(find_value(<<"chunk">>, JSONStruct))
}.

% FIXME. remove [return_maps] in ar_http_iface_middleware and make code uniform
json_struct_to_poa_from_map(JSONStruct) ->
#poa{
option = binary_to_integer(maps:get(<<"option">>, JSONStruct)),
Expand Down Expand Up @@ -1968,19 +1967,6 @@ json_map_to_solution(JSON) ->
steps = Steps
}.

json_map_to_info_map(JSONMap) ->
lists:foldl(
fun(Key, Acc) ->
BinaryKey = atom_to_binary(Key, utf8),
case maps:get(BinaryKey, JSONMap, undefined) of
undefined -> Acc;
Value -> maps:put(Key, Value, Acc)
end
end,
#{},
ar_info:get_keys()
).

encode_if_set(JSON, _JSONProperty, not_set, _Encoder) ->
JSON;
encode_if_set(JSON, _JSONProperty, undefined, _Encoder) ->
Expand Down
52 changes: 40 additions & 12 deletions apps/arweave/test/ar_info_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
-include_lib("eunit/include/eunit.hrl").
-include_lib("arweave/include/ar.hrl").

recent_test_() ->
recent_blocks_test_() ->
[
{timeout, 120, fun test_recent_blocks_post/0},
{timeout, 120, fun test_recent_blocks_announcement/0}
].

%% -------------------------------------------------------------------------------------------
%% Recent blocks tests
%% -------------------------------------------------------------------------------------------
test_recent_blocks_post() ->
test_recent_blocks(post).

Expand All @@ -20,12 +23,11 @@ test_recent_blocks(Type) ->
ar_test_node:start_peer(peer1, B0),
GenesisBlock = [#{
<<"id">> => ar_util:encode(B0#block.indep_hash),
<<"received">> => "pending"
<<"received">> => <<"pending">>
}],
?assertEqual(GenesisBlock,
ar_http_iface_client:get_info(ar_test_node:peer_ip(peer1), recent)),
?assertEqual(GenesisBlock, get_recent(ar_test_node:peer_ip(peer1), blocks)),

TargetHeight = ?INFO_BLOCKS+2,
TargetHeight = ?RECENT_BLOCKS+2,
PeerBI = lists:foldl(
fun(Height, _Acc) ->
ar_test_node:mine(peer1),
Expand All @@ -37,7 +39,7 @@ test_recent_blocks(Type) ->
%% Peer1 recent has no timestamps since it hasn't received any of its own blocks
%% gossipped back
?assertEqual(expected_blocks(peer1, PeerBI, true),
ar_http_iface_client:get_info(ar_test_node:peer_ip(peer1), recent)),
get_recent(ar_test_node:peer_ip(peer1), blocks)),

%% Share blocks to peer1
lists:foreach(
Expand All @@ -63,7 +65,7 @@ test_recent_blocks(Type) ->
%% Peer1 recent should now have timestamps, but also black out the most recent
%% ones.
?assertEqual(expected_blocks(peer1, PeerBI),
ar_http_iface_client:get_info(ar_test_node:peer_ip(peer1), recent)).
get_recent(ar_test_node:peer_ip(peer1), blocks)).

expected_blocks(Node, BI) ->
expected_blocks(Node, BI, false).
Expand All @@ -72,10 +74,10 @@ expected_blocks(Node, BI, ForcePending) ->
fun({H, _WeaveSize, _TXRoot}, Acc) ->
B = ar_test_node:remote_call(Node, ar_block_cache, get, [block_cache, H]),
Timestamp = case ForcePending of
true -> "pending";
true -> <<"pending">>;
false ->
case length(Acc) >= (?INFO_BLOCKS - ?INFO_BLOCKS_WITHOUT_TIMESTAMP - 1) of
true -> "pending";
case length(Acc) >= (?RECENT_BLOCKS - ?RECENT_BLOCKS_WITHOUT_TIMESTAMP - 1) of
true -> <<"pending">>;
false -> ar_util:timestamp_to_seconds(B#block.receive_timestamp)
end
end,
Expand All @@ -85,5 +87,31 @@ expected_blocks(Node, BI, ForcePending) ->
} | Acc]
end,
[],
lists:reverse(lists:sublist(BI, ?INFO_BLOCKS))
).
lists:reverse(lists:sublist(BI, ?RECENT_BLOCKS))
).

get_recent(Peer, Type) ->
case get_recent(Peer) of
info_unavailable -> info_unavailable;
Info ->
maps:get(atom_to_binary(Type), Info)
end.
get_recent(Peer) ->
case
ar_http:req(#{
method => get,
peer => Peer,
path => "/recent",
connect_timeout => 1000,
timeout => 2 * 1000
})
of
{ok, {{<<"200">>, _}, _, JSON, _, _}} ->
case ar_serialize:json_decode(JSON, [return_maps]) of
{ok, JsonMap} ->
JsonMap;
{error, _} ->
info_unavailable
end;
_ -> info_unavailable
end.

0 comments on commit 423df01

Please sign in to comment.