Export verify_proof/4 and add get_target/2 #25
@ -136,12 +136,6 @@ test_target(Bin, Target) ->
|
|||||||
<<Val:32/big-unsigned-integer-unit:8>> = Bin,
|
<<Val:32/big-unsigned-integer-unit:8>> = Bin,
|
||||||
Val < Threshold.
|
Val < Threshold.
|
||||||
|
|
||||||
%% TODO: get target
|
|
||||||
%Bin = solution_to_binary(lists:sort(Soln), NodeSize * 8, <<>>),
|
|
||||||
%%Hash = aec_hash:hash(pow, Bin),
|
|
||||||
%%<<Val:32/big-unsigned-integer-unit:8>> = Hash,
|
|
||||||
%%Val
|
|
||||||
|
|
||||||
%%%=============================================================================
|
%%%=============================================================================
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%%=============================================================================
|
%%%=============================================================================
|
||||||
|
@ -25,7 +25,9 @@
|
|||||||
]).
|
]).
|
||||||
|
|
||||||
-export([generate/5,
|
-export([generate/5,
|
||||||
verify/5
|
verify/5,
|
||||||
|
verify_proof/4,
|
||||||
|
get_target/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export_type([hashable/0,
|
-export_type([hashable/0,
|
||||||
@ -53,6 +55,8 @@
|
|||||||
|
|
||||||
-type nonce() :: aeminer_pow:nonce().
|
-type nonce() :: aeminer_pow:nonce().
|
||||||
|
|
||||||
|
-type int_target() :: aeminer_pow:int_target().
|
||||||
|
|
||||||
-type sci_target() :: aeminer_pow:sci_target().
|
-type sci_target() :: aeminer_pow:sci_target().
|
||||||
|
|
||||||
-type instance() :: aeminer_pow:instance()
|
-type instance() :: aeminer_pow:instance()
|
||||||
@ -193,14 +197,35 @@ generate(Data, Target, Nonce, Config, Instance) when
|
|||||||
boolean().
|
boolean().
|
||||||
verify(Data, Nonce, Soln, Target, EdgeBits) when
|
verify(Data, Nonce, Soln, Target, EdgeBits) when
|
||||||
is_list(Soln), Nonce >= 0, Nonce =< ?MAX_NONCE ->
|
is_list(Soln), Nonce >= 0, Nonce =< ?MAX_NONCE ->
|
||||||
Hash = aeminer_blake2b_256:hash(Data),
|
|
||||||
case test_target(Soln, Target, EdgeBits) of
|
case test_target(Soln, Target, EdgeBits) of
|
||||||
true ->
|
true ->
|
||||||
verify_proof(Hash, Nonce, Soln, EdgeBits);
|
verify_proof(Data, Nonce, Soln, EdgeBits);
|
||||||
false ->
|
false ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%%------------------------------------------------------------------------------
|
||||||
|
%% @doc
|
||||||
|
%% Proof of Work verification
|
||||||
|
%% @end
|
||||||
|
%%------------------------------------------------------------------------------
|
||||||
|
-spec verify_proof(hashable(), nonce(), solution(), edge_bits()) -> boolean().
|
||||||
|
verify_proof(Data, Nonce, Solution, EdgeBits) ->
|
||||||
|
%% Cuckoo has an 80 byte header, we have to use that as well
|
||||||
|
%% packed Hash + Nonce = 56 bytes, add 24 bytes of 0:s
|
||||||
|
Hash = aeminer_blake2b_256:hash(Data),
|
||||||
|
Header0 = pack_header_and_nonce(Hash, Nonce),
|
||||||
|
Header = <<(list_to_binary(Header0))/binary, 0:(8*24)>>,
|
||||||
|
verify_proof_(Header, Solution, EdgeBits).
|
||||||
|
|
||||||
|
-spec get_target(solution(), edge_bits()) -> int_target().
|
||||||
|
get_target(Soln, EdgeBits) when is_list(Soln), length(Soln) =:= ?SOLUTION_SIZE ->
|
||||||
|
NodeSize = get_node_size(EdgeBits),
|
||||||
|
Bin = solution_to_binary(lists:sort(Soln), NodeSize * 8, <<>>),
|
||||||
|
Hash = aeminer_blake2b_256:hash(Bin),
|
||||||
|
<<Val:32/big-unsigned-integer-unit:8>> = Hash,
|
||||||
|
Val.
|
||||||
|
|
||||||
%% Internal functions.
|
%% Internal functions.
|
||||||
|
|
||||||
generate_int(Hash, Nonce, Target,
|
generate_int(Hash, Nonce, Target,
|
||||||
@ -270,20 +295,6 @@ exec_bin_dir(#config{exec_group = ExecGroup}) ->
|
|||||||
-define(POW_DEAD_END, {error, cycle_dead_ends}).
|
-define(POW_DEAD_END, {error, cycle_dead_ends}).
|
||||||
-define(POW_SHORT_CYCLE, {error, cycle_too_short}).
|
-define(POW_SHORT_CYCLE, {error, cycle_too_short}).
|
||||||
|
|
||||||
%%------------------------------------------------------------------------------
|
|
||||||
%% @doc
|
|
||||||
%% Proof of Work verification (difficulty check should be done before calling
|
|
||||||
%% this function)
|
|
||||||
%% @end
|
|
||||||
%%------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
verify_proof(Hash, Nonce, Solution, EdgeBits) ->
|
|
||||||
%% Cuckoo has an 80 byte header, we have to use that as well
|
|
||||||
%% packed Hash + Nonce = 56 bytes, add 24 bytes of 0:s
|
|
||||||
Header0 = pack_header_and_nonce(Hash, Nonce),
|
|
||||||
Header = <<(list_to_binary(Header0))/binary, 0:(8*24)>>,
|
|
||||||
verify_proof_(Header, Solution, EdgeBits).
|
|
||||||
|
|
||||||
verify_proof_(Header, Solution, EdgeBits) ->
|
verify_proof_(Header, Solution, EdgeBits) ->
|
||||||
{K0, K1, K2, K3} = aeminer_siphash24:create_keys(Header),
|
{K0, K1, K2, K3} = aeminer_siphash24:create_keys(Header),
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
-include("aeminer.hrl").
|
-include("aeminer.hrl").
|
||||||
|
|
||||||
-define(TEST_MODULE, aeminer_pow_cuckoo).
|
-define(TEST_MODULE, aeminer_pow_cuckoo).
|
||||||
|
-define(POW_MODULE, aeminer_pow).
|
||||||
|
|
||||||
-define(TEST_BIN, <<"wsffgujnjkqhduihsahswgdf">>).
|
-define(TEST_BIN, <<"wsffgujnjkqhduihsahswgdf">>).
|
||||||
-define(TEST_HIGH_NONCE, 38). %% Nonce with solution with high target.
|
-define(TEST_HIGH_NONCE, 38). %% Nonce with solution with high target.
|
||||||
@ -29,14 +30,18 @@ pow_test_() ->
|
|||||||
?assertMatch(L when length(L) == ?SOLUTION_SIZE, Soln),
|
?assertMatch(L when length(L) == ?SOLUTION_SIZE, Soln),
|
||||||
|
|
||||||
%% verify the nonce and the solution
|
%% verify the nonce and the solution
|
||||||
Res2 = ?TEST_MODULE:verify(?TEST_BIN, Nonce, Soln, Target, ?EDGE_BITS_15),
|
?assert(?TEST_MODULE:verify(?TEST_BIN, Nonce, Soln, Target, ?EDGE_BITS_15)),
|
||||||
?assert(Res2)
|
?assert(?TEST_MODULE:verify_proof(?TEST_BIN, Nonce, Soln, ?EDGE_BITS_15)),
|
||||||
|
|
||||||
|
SolnTarget = ?TEST_MODULE:get_target(Soln, ?EDGE_BITS_15),
|
||||||
|
?assert(SolnTarget =< ?HIGHEST_TARGET_INT)
|
||||||
end}
|
end}
|
||||||
},
|
},
|
||||||
{"Generate with a winning nonce but low target threshold, shall fail",
|
{"Generate with a winning nonce but low target threshold, shall fail",
|
||||||
{timeout, 90,
|
{timeout, 90,
|
||||||
fun() ->
|
fun() ->
|
||||||
Target = 16#01010000,
|
Target = 16#01010000,
|
||||||
|
TargetInt = ?POW_MODULE:scientific_to_integer(Target),
|
||||||
Nonce = ?TEST_HIGH_NONCE,
|
Nonce = ?TEST_HIGH_NONCE,
|
||||||
Config = fast_and_deterministic_cuckoo_pow(),
|
Config = fast_and_deterministic_cuckoo_pow(),
|
||||||
Res1 = spawn_worker(fun() ->
|
Res1 = spawn_worker(fun() ->
|
||||||
@ -56,7 +61,12 @@ pow_test_() ->
|
|||||||
?assertMatch(L when length(L) == ?SOLUTION_SIZE, Soln2),
|
?assertMatch(L when length(L) == ?SOLUTION_SIZE, Soln2),
|
||||||
%% ... then attempt to verify such solution (and
|
%% ... then attempt to verify such solution (and
|
||||||
%% nonce) with the low target threshold (shall fail).
|
%% nonce) with the low target threshold (shall fail).
|
||||||
?assertNot(?TEST_MODULE:verify(?TEST_BIN, Nonce, Soln2, Target, ?EDGE_BITS_15))
|
?assertNot(?TEST_MODULE:verify(?TEST_BIN, Nonce, Soln2, Target, ?EDGE_BITS_15)),
|
||||||
|
%% The solution is still valid though.
|
||||||
|
?assert(?TEST_MODULE:verify_proof(?TEST_BIN, Nonce, Soln2, ?EDGE_BITS_15)),
|
||||||
|
|
||||||
|
%% The target of the solution shall be higher than the low target.
|
||||||
|
?assert(?TEST_MODULE:get_target(Soln2, ?EDGE_BITS_15) > TargetInt)
|
||||||
end}
|
end}
|
||||||
},
|
},
|
||||||
{"Attempt to verify wrong solution for nonce that has a solution shall fail",
|
{"Attempt to verify wrong solution for nonce that has a solution shall fail",
|
||||||
@ -71,7 +81,8 @@ pow_test_() ->
|
|||||||
WrongSoln = lists:seq(0, 41),
|
WrongSoln = lists:seq(0, 41),
|
||||||
?assertMatch(L when length(L) == ?SOLUTION_SIZE, WrongSoln),
|
?assertMatch(L when length(L) == ?SOLUTION_SIZE, WrongSoln),
|
||||||
?assertNotEqual(Soln, WrongSoln),
|
?assertNotEqual(Soln, WrongSoln),
|
||||||
?assertNot(?TEST_MODULE:verify(?TEST_BIN, Nonce, WrongSoln, Target, ?EDGE_BITS_15))
|
?assertNot(?TEST_MODULE:verify(?TEST_BIN, Nonce, WrongSoln, Target, ?EDGE_BITS_15)),
|
||||||
|
?assertNot(?TEST_MODULE:verify_proof(?TEST_BIN, Nonce, WrongSoln, ?EDGE_BITS_15))
|
||||||
end},
|
end},
|
||||||
{"Attempt to verify nonce that does not have a solution (providing a dummy solution) shall fail",
|
{"Attempt to verify nonce that does not have a solution (providing a dummy solution) shall fail",
|
||||||
fun() ->
|
fun() ->
|
||||||
@ -82,8 +93,9 @@ pow_test_() ->
|
|||||||
spawn_worker(fun() -> ?TEST_MODULE:generate(?TEST_BIN, Target, Nonce, Config, undefined) end)),
|
spawn_worker(fun() -> ?TEST_MODULE:generate(?TEST_BIN, Target, Nonce, Config, undefined) end)),
|
||||||
|
|
||||||
DummySoln = lists:seq(0, 41),
|
DummySoln = lists:seq(0, 41),
|
||||||
?assertMatch(L when length(L) == ?SOLUTION_SIZE, DummySoln),
|
?assertMatch(L when length(L) =:= ?SOLUTION_SIZE, DummySoln),
|
||||||
?assertNot(?TEST_MODULE:verify(?TEST_BIN, Nonce, DummySoln, Target, ?EDGE_BITS_15))
|
?assertNot(?TEST_MODULE:verify(?TEST_BIN, Nonce, DummySoln, Target, ?EDGE_BITS_15)),
|
||||||
|
?assertNot(?TEST_MODULE:verify_proof(?TEST_BIN, Nonce, DummySoln, ?EDGE_BITS_15))
|
||||||
end},
|
end},
|
||||||
{"Attempt to verify nonce that is too big shall fail gracefully",
|
{"Attempt to verify nonce that is too big shall fail gracefully",
|
||||||
fun() ->
|
fun() ->
|
||||||
@ -99,7 +111,8 @@ pow_test_() ->
|
|||||||
117537386,120015599,125293300,125684682,129332159],
|
117537386,120015599,125293300,125684682,129332159],
|
||||||
Nonce = 17654096256755765485,
|
Nonce = 17654096256755765485,
|
||||||
Target = 536940240,
|
Target = 536940240,
|
||||||
?assertNot(?TEST_MODULE:verify(Hash, Nonce, Pow, Target, ?EDGE_BITS_15))
|
?assertNot(?TEST_MODULE:verify(Hash, Nonce, Pow, Target, ?EDGE_BITS_15)),
|
||||||
|
?assertNot(?TEST_MODULE:verify_proof(Hash, Nonce, Pow, ?EDGE_BITS_15))
|
||||||
end}
|
end}
|
||||||
].
|
].
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user