summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nordberg <linus@nordberg.se>2014-09-20 15:33:06 +0200
committerLinus Nordberg <linus@nordberg.se>2014-09-20 15:33:06 +0200
commit4f1a715a3f2a6b049dcb9dcc5b38f6f2716e4101 (patch)
tree035e8e4e93da8629de125d5036b1f5c8c3b0b6cb
parent209fc7ed4d44f0d613aabdb9b1c59b8621dc1339 (diff)
Store and retrieve extra-data in/from db.
Also, add more specs to db.
-rw-r--r--src/db.erl19
-rw-r--r--src/db.hrl2
-rw-r--r--src/ht.erl2
-rw-r--r--src/plop.erl46
4 files changed, 40 insertions, 29 deletions
diff --git a/src/db.erl b/src/db.erl
index 91e379e..3ab2d1b 100644
--- a/src/db.erl
+++ b/src/db.erl
@@ -72,20 +72,22 @@ stop() ->
%%%%%%%%%%%%%%%%%%%%
%% Public API.
--spec add(binary()) -> ok.
+-spec add(plop()) -> {atomic, ok}.
add(Entry) ->
gen_server:call(?MODULE, {add, Entry}).
%% @doc Find one entry.
--spec find(entryhash | mtlhash | index, binary()) -> ht:mtl().
+-spec find(entryhash | mtlhash | index, binary()) ->
+ [] | plop() | duplicate_hash_in_db.
find(Type, Hash) ->
gen_server:call(?MODULE, {find, Type, Hash}).
--spec get_by_index(non_neg_integer(), non_neg_integer()) -> [ht:mtl()].
+-spec get_by_index(non_neg_integer(), non_neg_integer()) -> [{mtl(), binary()}].
get_by_index(Start, End) ->
gen_server:call(?MODULE, {get_by_index, {Start, End}}).
--spec get_by_index_sorted(non_neg_integer(), non_neg_integer()) -> [listht:mtl()].
+-spec get_by_index_sorted(non_neg_integer(), non_neg_integer()) ->
+ [{mtl(), binary()}].
get_by_index_sorted(Start, End) ->
gen_server:call(?MODULE, {get_by_index_sorted, {Start, End}}).
@@ -144,12 +146,12 @@ handle_call({find, index, Index}, _From, State) ->
State};
handle_call({get_by_index, {Start, End}}, _From, State) ->
- Res = [X || [_, X] <- select_index(Start, End)],
+ Res = [{MTL, Extra} || [_Index, MTL, Extra] <- select_index(Start, End)],
{reply, Res, State};
handle_call({get_by_index_sorted, {Start, End}}, _From, State) ->
%% FIXME: RAM hog -- how bad is it?
- Res = [X || [_, X] <- lists:sort(select_index(Start, End))],
+ Res = [{MTL, Extra} || [_Index, MTL, Extra] <- lists:sort(select_index(Start, End))],
{reply, Res, State}.
%%%%%%%%%%%%%%%%%%%%
@@ -157,8 +159,8 @@ handle_call({get_by_index_sorted, {Start, End}}, _From, State) ->
select_index(Start, End) ->
F = fun() ->
- %% Get index and mtl.
- MatchHead = {plop, '$1', '_', '_', '$2', '_'},
+ %% Get index, mtl and extra_data.
+ MatchHead = {plop, '$1', '_', '_', '$2', '$3', '_'},
Guard = [{'>=', '$1', Start}, {'=<', '$1', End}],
Result = ['$$'],
mnesia:select(plop, [{MatchHead, Guard, Result}])
@@ -166,6 +168,7 @@ select_index(Start, End) ->
{atomic, Res} = mnesia:transaction(F),
Res.
+-spec find_entry(fun()) -> [] | plop() | duplicate_hash_in_db.
find_entry(Fun) ->
{atomic, Result} = mnesia:transaction(Fun),
case length(Result) of
diff --git a/src/db.hrl b/src/db.hrl
index b5ceb2e..bea9131 100644
--- a/src/db.hrl
+++ b/src/db.hrl
@@ -11,5 +11,7 @@
entryhash :: binary(), % Hash over #plop_entry{} in mtl.
mtlhash :: binary(), % Merkle Tree Leaf hash.
mtl :: mtl(), % Merkle Tree Leaf.
+ extra_data :: binary(), % Data not part of mtl.
spt :: spt() % Signed Plop Timestamp.
}).
+-type plop() :: #plop{}.
diff --git a/src/ht.erl b/src/ht.erl
index ec8527f..74f8ab4 100644
--- a/src/ht.erl
+++ b/src/ht.erl
@@ -264,7 +264,7 @@ new([Version]) when is_integer(Version) ->
foldl(fun(MTL, Tree) ->
%% Return value becomes Tree in next invocation.
add(Tree, plop:serialise(MTL))
- end, new([]), db:get_by_index_sorted(0, Version));
+ end, new([]), [X || {X, _} <- db:get_by_index_sorted(0, Version)]);
%% Initialise tree from List.
new([List]) when is_list(List) ->
foldl(fun(SerialisedMTL, Tree) -> add(Tree, SerialisedMTL) end,
diff --git a/src/plop.erl b/src/plop.erl
index abd7d87..0cb29f5 100644
--- a/src/plop.erl
+++ b/src/plop.erl
@@ -26,7 +26,7 @@
%% API.
-export([start_link/2, stop/0]).
-export([get_logid/0, serialise/1]).
--export([add/1, sth/0, get/2, consistency/2, inclusion/2, inclusion_and_leaf/2]).
+-export([add/2, sth/0, get/2, consistency/2, inclusion/2, inclusion_and_more/2]).
%% API for tests.
-export([read_keyfile_rsa/2, read_keyfiles_ec/2]).
-export([testing_get_pubkey/0]).
@@ -104,23 +104,24 @@ terminate(_Reason, _State) ->
ok.
%%%%%%%%%%%%%%%%%%%%
--spec add(timestamped_entry()) -> spt().
-add(Data) ->
- gen_server:call(?MODULE, {add, Data}).
+-spec add(timestamped_entry(), binary()) -> spt().
+add(Entry, ExtraData) ->
+ gen_server:call(?MODULE, {add, {Entry, ExtraData}}).
sth() ->
gen_server:call(?MODULE, {sth, []}).
+-spec get(non_neg_integer(), non_neg_integer()) -> [{mtl(), binary()}].
get(Start, End) ->
gen_server:call(?MODULE, {get, {Start, End}}).
consistency(TreeSizeFirst, TreeSizeSecond) ->
gen_server:call(?MODULE, {consistency, {TreeSizeFirst, TreeSizeSecond}}).
-spec inclusion(binary(), non_neg_integer()) ->
- {ok|notfound, plop_entry() | string()}.
+ {ok, mtl()} | {notfound, string()}.
inclusion(Hash, TreeSize) ->
gen_server:call(?MODULE, {inclusion, {Hash, TreeSize}}).
--spec inclusion_and_leaf(non_neg_integer(), non_neg_integer()) ->
- {ok|notfound, plop_entry() | string()}.
-inclusion_and_leaf(Index, TreeSize) ->
- gen_server:call(?MODULE, {inclusion_and_leaf, {Index, TreeSize}}).
+-spec inclusion_and_more(non_neg_integer(), non_neg_integer()) ->
+ {ok, {mtl(), binary()}} | {notfound, string()}.
+inclusion_and_more(Index, TreeSize) ->
+ gen_server:call(?MODULE, {inclusion_and_more, {Index, TreeSize}}).
get_logid() ->
gen_server:call(?MODULE, {get, logid}).
testing_get_pubkey() ->
@@ -132,15 +133,15 @@ handle_call(stop, _From, State) ->
%% FIXME: What's the right interface for add()? Need to be able to set
%% version and signature type, at least. That's missing from
%% #timestamped_entry, so add it somehow.
-handle_call({add, #timestamped_entry{
- timestamp = Timestamp_in, entry = Entry}},
+handle_call({add,
+ {#timestamped_entry{timestamp = Timestamp_in, entry = Entry},
+ ExtraData}},
_From,
- State = #state{privkey = Privkey,
- logid = LogID}) ->
+ State = #state{privkey = Privkey, logid = LogID}) ->
TimestampedEntry = #timestamped_entry{
timestamp = timestamp(Timestamp_in),
entry = Entry},
- {ok, SPT} = do_add(TimestampedEntry, Privkey, LogID),
+ {ok, SPT} = do_add(TimestampedEntry, ExtraData, Privkey, LogID),
{reply, SPT, State};
handle_call({sth, Data}, _From,
@@ -161,17 +162,17 @@ handle_call({inclusion, {Hash, TreeSize}}, _From, Plop) ->
R = case db:find(mtlhash, Hash) of
[] ->
{notfound, "Unknown hash"}; % FIXME: include Hash
- {plop, I, _EntryHash, _MTLHash, _MTL, _SPT} ->
+ {plop, I, _EntryHash, _MTLHash, _MTL, _ExtraData, _SPT} ->
{ok, I, ht:path(I, TreeSize - 1)}
end,
{reply, R, Plop};
-handle_call({inclusion_and_leaf, {Index, TreeSize}}, _From, Plop) ->
+handle_call({inclusion_and_more, {Index, TreeSize}}, _From, Plop) ->
R = case db:find(index, Index) of
[] ->
{notfound, "Unknown index"}; % FIXME: include Index
- {plop, I, _EntryHash, _MTLHash, MTL, _SPT} ->
- {ok, MTL, ht:path(I, TreeSize - 1)}
+ {plop, I, _EntryHash, _MTLHash, MTL, ExtraData, _SPT} ->
+ {ok, MTL, ExtraData, ht:path(I, TreeSize - 1)}
end,
{reply, R, Plop};
@@ -186,9 +187,10 @@ handle_call({test, pubkey}, _From,
%% Data.
-spec do_add(timestamped_entry(),
+ binary(),
public_key:rsa_private_key(),
- binary()) -> {ok|error, binary()}.
-do_add(TimestampedEntry, Privkey, LogID) ->
+ binary()) -> {ok, spt()} | {error, any()}.
+do_add(TimestampedEntry, ExtraData, Privkey, LogID) ->
DB_hash = crypto:hash(sha256,
serialise(TimestampedEntry#timestamped_entry.entry)),
Record = db:find(entryhash, DB_hash),
@@ -208,6 +210,7 @@ do_add(TimestampedEntry, Privkey, LogID) ->
entryhash = DB_hash,
mtlhash = ht:leaf_hash(MTLtext),
mtl = MTL,
+ extra_data = ExtraData,
spt = NewSPT},
{atomic, ok} = db:add(DB_data),
{ht:add(MTLtext), NewSPT};
@@ -458,16 +461,19 @@ add_test() ->
{ok, S} = init([?TESTPRIVKEYFILE, ?TESTPUBKEYFILE]),
Data1 = <<"some data">>,
+ ExtraData1 = <<"some extra data">>,
{_Tree, SPT} =
do_add(#timestamped_entry{
timestamp = 4711,
entry = #plop_entry{type = test, data = Data1}},
+ ExtraData1,
S#state.privkey,
S#state.logid),
{_Tree1, SPT1} =
do_add(#timestamped_entry{
timestamp = 4712,
entry = #plop_entry{type = test, data = Data1}},
+ ExtraData1,
S#state.privkey,
S#state.logid),
?assertEqual(SPT, SPT1),