diff options
Diffstat (limited to 'src/plop.erl')
-rw-r--r-- | src/plop.erl | 89 |
1 files changed, 60 insertions, 29 deletions
diff --git a/src/plop.erl b/src/plop.erl index 8ce3186..46b402b 100644 --- a/src/plop.erl +++ b/src/plop.erl @@ -25,9 +25,10 @@ %% API. -export([initsize/0]). -export([get_logid/0, serialise/1, signature_type/1]). --export([add/3, sth/0, get/1, get/2, spt/1, consistency/2, inclusion/2, inclusion_and_entry/2]). +-export([add/2, commit/3, sth/0, get/1, get/2, spt/2, + consistency/2, inclusion/2, inclusion_and_entry/2]). -export([generate_timestamp/0, save_sth/1, verify_sth/4]). --export([get_by_leaf_hash/1, entry_for_leafhash/1]). +-export([get_by_leaf_hash/1, entry_for_leafhash/1, spt_from_entry/1, get_spt/1, add_spt/2]). %% API for tests. -export([testing_get_pubkey/0]). @@ -60,18 +61,19 @@ handle_http_reply(TreeLeafHash, RepliesUntilQuorum, [mochihex:to_hex(TreeLeafHash), Body]), {struct, PropList} = mochijson2:decode(Body), Result = proplists:get_value(<<"result">>, PropList), + Signature = proplists:get_value(<<"sig">>, PropList), if Result == <<"ok">>, StatusCode == 200 -> case RepliesUntilQuorum - 1 of 0 -> %% reached quorum lager:debug("leafhash ~s: reached quorum", [mochihex:to_hex(TreeLeafHash)]), - {ok}; + {ok, Signature}; NewRepliesUntilQuorum -> lager:debug("leafhash ~s: replies until quorum: ~p", [mochihex:to_hex(TreeLeafHash), NewRepliesUntilQuorum]), - {continue, NewRepliesUntilQuorum} + {continue, NewRepliesUntilQuorum, Signature} end end. @@ -90,20 +92,47 @@ unwrap_entry(WrappedEntry) -> error end. +spt_data(Entry) -> + {ok, {Module, Function}} = application:get_env(plop, spt_data), + Module:Function(Entry). + +spt_from_entry(LogEntry) -> + spt_data(unwrap_entry(LogEntry)). + +get_spt(Hash) -> + perm:getvalue(sptcache, Hash). + +add_spt(LeafHash, SPT) -> + ok = perm:addvalue(sptcache, LeafHash, SPT), + perm:commit(sptcache), + ok. + %%%%%%%%%%%%%%%%%%%% --spec add(binary(), binary(), binary()) -> ok. -add(LogEntry, TreeLeafHash, EntryHash) -> +-spec add(binary(), binary()) -> {ok, list()}. +add(LogEntry, TreeLeafHash) -> lager:debug("add leafhash ~s", [mochihex:to_hex(TreeLeafHash)]), WrappedLogEntry = wrap_entry(LogEntry), case storage_nodes() of [] -> exit(internal_merge_not_supported); Nodes -> - util:spawn_and_wait(fun () -> - store_at_all_nodes(Nodes, {WrappedLogEntry, TreeLeafHash, EntryHash}) - end) + util:spawn_and_wait( + fun () -> + store_at_all_nodes(Nodes, {WrappedLogEntry, TreeLeafHash}) + end) end. +commit(TreeLeafHash, EntryHash, SPT) -> + Nodes = storage_nodes(), + util:spawn_and_wait( + fun () -> + lists:foreach( + fun (URLBase) -> + send_storage_entrycommitted(URLBase, EntryHash, + TreeLeafHash, SPT) + end, Nodes) + end). + save_sth(STH) -> {ok, STHFile} = application:get_env(plop, sth_path), {struct, PropList} = STH, @@ -151,11 +180,11 @@ get(Hash) -> {notfetched, LeafHash, unwrap_entry(Entry)} end. -spt(Data) -> +spt(Data, Signatures) -> #signature{algorithm = #sig_and_hash_alg{ hash_alg = sha256, signature_alg = ecdsa}, - signature = sign:sign_sct(Data)}. + signature = sign:sign_sct(Data, Signatures)}. consistency(TreeSizeFirst, TreeSizeSecond) -> TreeSize = db:size(), @@ -250,15 +279,21 @@ send_storage_sendentry(URLBase, LogEntry, TreeLeafHash) -> RequestId = send_http_request(TreeLeafHash, URLBase ++ "sendentry", [{"Content-Type", "text/json"}], list_to_binary(Request)), {RequestId, URLBase}. -send_storage_entrycommitted(URLBase, EntryHash, TreeLeafHash) -> +send_storage_entrycommitted(URLBase, EntryHash, TreeLeafHash, SPT) -> Request = mochijson2:encode( {[{plop_version, 1}, {entryhash, base64:encode(EntryHash)}, - {treeleafhash, base64:encode(TreeLeafHash)} + {treeleafhash, base64:encode(TreeLeafHash)}, + {timestamp_signature, base64:encode(SPT)} ]}), send_http_request(TreeLeafHash, URLBase ++ "entrycommitted", [{"Content-Type", "text/json"}], list_to_binary(Request)). -store_loop(TreeLeafHash, Requests, RepliesUntilQuorum) -> +add_if_not_undefined(undefined, Signatures) -> + Signatures; +add_if_not_undefined(Signature, Signatures) -> + [Signature | Signatures]. + +store_loop(TreeLeafHash, Requests, RepliesUntilQuorum, Signatures) -> receive {http, {RequestId, {StatusLine, _Headers, Body}}} -> {_HttpVersion, StatusCode, _ReasonPhrase} = StatusLine, @@ -267,16 +302,16 @@ store_loop(TreeLeafHash, Requests, RepliesUntilQuorum) -> lager:info("leafhash ~s: stray storage reply: ~p", [mochihex:to_hex(TreeLeafHash), {StatusLine, Body}]), - store_loop(TreeLeafHash, Requests, RepliesUntilQuorum); + store_loop(TreeLeafHash, Requests, RepliesUntilQuorum, Signatures); true -> NewRequests = dict:erase(RequestId, Requests), case handle_http_reply(TreeLeafHash, RepliesUntilQuorum, StatusCode, Body) of - {ok} -> - ok; - {continue, NewRepliesUntilQuorum} -> + {ok, Signature} -> + {ok, add_if_not_undefined(Signature, Signatures)}; + {continue, NewRepliesUntilQuorum, Signature} -> store_loop(TreeLeafHash, NewRequests, - NewRepliesUntilQuorum) + NewRepliesUntilQuorum, add_if_not_undefined(Signature, Signatures)) end end after @@ -291,20 +326,16 @@ store_loop(TreeLeafHash, Requests, RepliesUntilQuorum) -> end. -store_at_all_nodes(Nodes, {LogEntry, TreeLeafHash, EntryHash}) -> +store_at_all_nodes(Nodes, {LogEntry, TreeLeafHash}) -> lager:debug("leafhash ~s: send requests to ~p", [mochihex:to_hex(TreeLeafHash), Nodes]), Requests = [send_storage_sendentry(URLBase, LogEntry, TreeLeafHash) || URLBase <- Nodes], case store_loop(TreeLeafHash, dict:from_list(Requests), - storage_nodes_quorum()) of - ok -> - lager:debug("leafhash ~s: all requests answered", - [mochihex:to_hex(TreeLeafHash)]), - lists:foreach(fun (URLBase) -> - send_storage_entrycommitted(URLBase, EntryHash, - TreeLeafHash) - end, Nodes), - ok; + storage_nodes_quorum(), []) of + {ok, Signatures} -> + lager:debug("leafhash ~s: all requests answered: ~p", + [mochihex:to_hex(TreeLeafHash), Signatures]), + {ok, Signatures}; Any -> lager:debug("leafhash ~s: error: ~p", [mochihex:to_hex(TreeLeafHash), Any]), |