summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Ahltorp <map@kth.se>2014-10-27 01:30:15 +0100
committerMagnus Ahltorp <map@kth.se>2014-10-27 01:30:15 +0100
commit79caa8decbb21228cf3f5cbe32fbf972c40e70dc (patch)
tree5e5ae633f29ce8aaa0155ef4595ad5c4b2efaa8c
parentfb3b9591cc81158824db13818cf6320d5f4a0f7b (diff)
Check that entries are actually present when receiving new STH from merge nodes
-rw-r--r--src/db.erl9
-rw-r--r--src/frontend.erl55
2 files changed, 54 insertions, 10 deletions
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)