summaryrefslogtreecommitdiff
path: root/src/plop.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/plop.erl')
-rw-r--r--src/plop.erl89
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]),