From 4f1a715a3f2a6b049dcb9dcc5b38f6f2716e4101 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Sat, 20 Sep 2014 15:33:06 +0200 Subject: Store and retrieve extra-data in/from db. Also, add more specs to db. --- src/db.erl | 19 +++++++++++-------- src/db.hrl | 2 ++ src/ht.erl | 2 +- src/plop.erl | 46 ++++++++++++++++++++++++++-------------------- 4 files changed, 40 insertions(+), 29 deletions(-) (limited to 'src') 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), -- cgit v1.1