From 79caa8decbb21228cf3f5cbe32fbf972c40e70dc Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Mon, 27 Oct 2014 01:30:15 +0100 Subject: Check that entries are actually present when receiving new STH from merge nodes --- src/db.erl | 9 ++++++--- src/frontend.erl | 55 ++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/db.erl b/src/db.erl index f7c2057..2a64935 100644 --- a/src/db.erl +++ b/src/db.erl @@ -7,7 +7,7 @@ %% API. -export([start_link/0, stop/0]). -export([add/4, add/2, add_entryhash/2, add_index/2, set_treesize/1, size/0]). --export([get_by_index/1, get_by_indices/3, get_by_leaf_hash/1, get_by_entry_hash/1, entry_for_leafhash/1, leafhash_for_index/1]). +-export([get_by_index/1, get_by_indices/3, get_by_leaf_hash/1, get_by_entry_hash/1, entry_for_leafhash/1, leafhash_for_index/1, leafhash_for_indices/2, indexsize/0]). %% gen_server callbacks. -export([init/1, handle_call/3, terminate/2, handle_cast/2, handle_info/2, code_change/3]). @@ -18,6 +18,9 @@ size() -> binary_to_integer(atomic:readfile(treesize_path())). +indexsize() -> + index:indexsize(index_path()). + init(_Args) -> {ok, []}. @@ -158,7 +161,7 @@ handle_call({add, {LeafHash, EntryHash, Data, Index}}, _From, State) -> ok = perm:ensurefile(indexforhash_root_path(), LeafHash, integer_to_binary(Index)), ok = index:add(index_path(), Index, LeafHash), - ok = atomic:replacefile(treesize_path(), integer_to_list(Index+1)), + ok = atomic:replacefile(treesize_path(), integer_to_binary(Index+1)), {reply, ok, State}; handle_call({add, {LeafHash, Data}}, _From, State) -> @@ -178,7 +181,7 @@ handle_call({add_index, {LeafHash, Index}}, _From, State) -> {reply, ok, State}; handle_call({set_treesize, Size}, _From, State) -> - ok = atomic:replacefile(treesize_path(), integer_to_list(Size)), + ok = atomic:replacefile(treesize_path(), integer_to_binary(Size)), {reply, ok, State}; handle_call({get_by_indices, {Start, End, _Sorted}}, _From, State) -> diff --git a/src/frontend.erl b/src/frontend.erl index a8a8b9e..9c69517 100644 --- a/src/frontend.erl +++ b/src/frontend.erl @@ -39,13 +39,33 @@ request(post, "ct/frontend/sendsth", Input) -> {error, E} -> html("sendentry: bad input:", E); {struct, PropList} -> + OldSize = db:size(), Treesize = proplists:get_value(<<"tree_size">>, PropList), - - ok = db:set_treesize(Treesize), - - ht:reset_tree([db:size() - 1]), - - success({[{result, <<"ok">>}]}) + Indexsize = db:indexsize(), + + if + Treesize < OldSize -> + html("Size is older than current size", OldSize); + Treesize == OldSize -> + success({[{result, <<"ok">>}]}); + Treesize > Indexsize -> + html("Has too few entries", Indexsize); + true -> + NewEntries = db:leafhash_for_indices(OldSize, Treesize - 1), + lager:debug("old size: ~p new size: ~p entries: ~p", + [OldSize, Treesize, NewEntries]), + + Errors = check_entries(NewEntries, OldSize, Treesize - 1), + + case Errors of + [] -> + ok = db:set_treesize(Treesize), + ht:reset_tree([db:size() - 1]), + success({[{result, <<"ok">>}]}); + _ -> + html("Database not complete", Errors) + end + end end; request(get, "ct/frontend/currentposition", _Query) -> @@ -56,19 +76,40 @@ request(get, "ct/frontend/currentposition", _Query) -> request(get, "ct/frontend/missingentries", _Query) -> Size = db:size(), Missing = fetchmissingentries(Size), + lager:debug("missingentries: ~p", [Missing]), success({[{result, <<"ok">>}, - {entries, Missing}]}). + {entries, lists:map(fun (Entry) -> base64:encode(Entry) end, + Missing)}]}). +check_entries(Entries, Start, End) -> + lists:foldl(fun ({Hash, Index}, Acc) -> + case check_entry(Hash, Index) of + ok -> + Acc; + Error -> + [Error | Acc] + end + end, [], lists:zip(Entries, lists:seq(Start, End))). + +check_entry(Hash, Index) -> + case db:get_by_leaf_hash(Hash) of + notfound -> + {notfound, Index}; + _ -> + ok + end. fetchmissingentries(Index) -> lists:reverse(fetchmissingentries(Index, [])). fetchmissingentries(Index, Acc) -> + lager:debug("index ~p", [Index]), case db:leafhash_for_index(Index) of noentry -> Acc; Hash -> case db:entry_for_leafhash(Hash) of noentry -> + lager:debug("didn't find hash ~p", [Hash]), fetchmissingentries(Index + 1, [Hash | Acc]); _ -> fetchmissingentries(Index + 1, Acc) -- cgit v1.1