Skip to content
This repository has been archived by the owner on Jun 12, 2023. It is now read-only.

Commit

Permalink
support validator pool creating challenges
Browse files Browse the repository at this point in the history
  • Loading branch information
andymck committed Mar 16, 2022
1 parent 13a13c3 commit a2c69fe
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 169 deletions.
4 changes: 2 additions & 2 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

{deps, [
{blockchain, {git, "https://github.com/helium/blockchain-core.git",
{branch, "andymck/poc-grpc-v2"}}},
{branch, "andymck/poc-grpc-v2-plus-vals-as-chall"}}},
{sibyl, {git, "https://github.com/helium/sibyl.git",
{branch, "andymck/poc-grpc"}}},
{branch, "andymck/poc-grpc-plus-vals-as-chall"}}},
{hbbft, {git, "https://github.com/helium/erlang-hbbft.git",
{branch, "master"}}},
{dkg, {git, "https://github.com/helium/erlang-dkg.git", {branch, "master"}}},
Expand Down
6 changes: 3 additions & 3 deletions rebar.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{<<"base64url">>,{pkg,<<"base64url">>,<<"1.0.1">>},1},
{<<"blockchain">>,
{git,"https://github.com/helium/blockchain-core.git",
{ref,"5881ad571903c1908fbbaed396a59bc7efa505ce"}},
{ref,"61fd00a24e93ef67f4d526e2955910d79f330965"}},
0},
{<<"certifi">>,{pkg,<<"certifi">>,<<"2.8.0">>},2},
{<<"chatterbox">>,
Expand Down Expand Up @@ -107,7 +107,7 @@
0},
{<<"helium_proto">>,
{git,"https://github.com/helium/proto.git",
{ref,"f743a80e534bdc78805e3c5438cb466bec3c0b6f"}},
{ref,"5e663437950c3e6d71fbd230e1435005be26603f"}},
1},
{<<"hpack">>,{pkg,<<"hpack_erl">>,<<"0.2.3">>},3},
{<<"http2_client">>,
Expand Down Expand Up @@ -176,7 +176,7 @@
3},
{<<"sibyl">>,
{git,"https://github.com/helium/sibyl.git",
{ref,"a5a86c9441a0db5e0db136af47fa09fb0ae50c02"}},
{ref,"f735165f4413198e1cfeb981cadce382a95a88ed"}},
0},
{<<"sidejob">>,{pkg,<<"sidejob">>,<<"2.1.0">>},2},
{<<"small_ints">>,{pkg,<<"small_ints">>,<<"0.1.0">>},4},
Expand Down
31 changes: 5 additions & 26 deletions src/handlers/miner_hbbft_handler.erl
Original file line number Diff line number Diff line change
Expand Up @@ -106,24 +106,15 @@ metadata(Version, Meta, Chain) ->
_ -> 1
end,
lager:debug("poc challenge rate ~p", [ChallengeRate] ),
%% if a val is in the ignore list then dont generate poc keys for it
%% TODO: this is a temp hack. remove when testing finished
IgnoreVals = application:get_env(sibyl, validator_ignore_list, []),
SelfPubKeyBin = blockchain_swarm:pubkey_bin(),
case not lists:member(SelfPubKeyBin, IgnoreVals) of
true ->
{EmpKeys, EmpKeyHashes} = generate_ephemeral_keys(N, ChallengeRate),
lager:debug("poc ephemeral keys ~p", [EmpKeys]),
lager:debug("node ~p generating poc ephemeral key hashes ~p", [SelfPubKeyBin, EmpKeyHashes]),
ok = miner_poc_mgr:save_poc_keys(Height, EmpKeys),
maps:put(poc_keys, {SelfPubKeyBin, EmpKeyHashes}, ChainMeta);
false ->
ChainMeta
end;
NumKeys = max(1, trunc(ChallengeRate / (((N-1)/3) * 2 ))),
POCEphemeralKeys = miner_poc_mgr:get_random_poc_key_proposals(NumKeys, Ledger),
lager:debug("node ~p submitting poc ephemeral key hashes ~p", [SelfPubKeyBin, POCEphemeralKeys]),
maps:put(poc_keys, POCEphemeralKeys, ChainMeta);
_ ->
ChainMeta

end,
end,
lager:info("ChainMeta1 ~p", [ChainMeta1]),
t2b(maps:merge(Meta, ChainMeta1))
end.
Expand Down Expand Up @@ -854,18 +845,6 @@ bin_to_msg(<<Bin/binary>>) ->
{error, truncated}
end.

-spec generate_ephemeral_keys(pos_integer(), pos_integer()) ->{[#{secret => libp2p_crypto:privkey(), public => libp2p_crypto:pubkey()}], [binary()]}.
generate_ephemeral_keys(N, ChallengeRate) ->
NumKeys = max(1, trunc(ChallengeRate / (((N-1)/3) * 2 ))),
lists:foldl(
fun(_N, {AccKeys, AccHashes})->
Keys = libp2p_crypto:generate_keys(ecc_compact),
#{public := OnionCompactKey} = Keys,
OnionHash = crypto:hash(sha256, libp2p_crypto:pubkey_to_bin(OnionCompactKey)),
{[Keys | AccKeys], [OnionHash | AccHashes]}
end,
{[], []}, lists:seq(1, NumKeys)).

-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").

Expand Down
13 changes: 3 additions & 10 deletions src/miner.erl
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,7 @@ snapshot_hash(Ledger, BlockHeightNext, Metadata, VotesNeeded) ->
M :: metadata(),
B :: blockchain_block:hash().
poc_keys(Ledger, Metadata, BlockHash) ->
%% Construct a set of poc keys. Each node will define its own set within the metadata
%% Construct a set of poc keys. Each node will pull a random list from a pool of keys
%% We want to take a deterministic random subset of these up to a max of poc challenge rate
%% Use the blockhash as the seed
RandState = blockchain_utils:rand_state(BlockHash),
Expand All @@ -763,15 +763,8 @@ poc_keys(Ledger, Metadata, BlockHash) ->
{ok, V} -> V;
_ -> 1
end,
PocKeys0 = [{MinerAddr, Keys} || {_, #{poc_keys := {MinerAddr, Keys}}} <- metadata_only_v2(Metadata)],
{ok, CGMembers} = blockchain_ledger_v1:consensus_members(Ledger),
PocKeys1 = lists:foldl(
fun({MinerAddr, PocKeys}, Acc)->
Pos = miner_util:index_of(MinerAddr, CGMembers),
NormalisedKeys = lists:map(fun(PocKey) -> {Pos, PocKey} end, PocKeys),
[NormalisedKeys | Acc]
end, [], PocKeys0),
sort_and_truncate_poc_keys(lists:flatten(PocKeys1), ChallengeRate, RandState).
PocKeys0 = [POCKeys || {_, #{poc_keys := POCKeys}} <- metadata_only_v2(Metadata)],
sort_and_truncate_poc_keys(lists:flatten(PocKeys0), ChallengeRate, RandState).

sort_and_truncate_poc_keys(L, MaxKeys, RandState) ->
{_, TruncList} = blockchain_utils:deterministic_subset(MaxKeys, RandState, L),
Expand Down
6 changes: 4 additions & 2 deletions src/miner_keys.erl
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,10 @@ keys(#{pubkey := _PubKey, ecdh_fun := _ECDH, sig_fun := _Sig} = KeyInfo) ->
key_config() ->
BaseDir = application:get_env(blockchain, base_dir, "data"),
case application:get_env(blockchain, key, undefined) of
undefined -> {file, BaseDir};
KC -> KC
undefined ->
{file, BaseDir};
KC ->
KC
end.

-spec libp2p_to_gateway_key(libp2p_crypto:key_map()) -> libp2p_crypto:key_map().
Expand Down
8 changes: 6 additions & 2 deletions src/miner_restart_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,14 @@ init(_Opts) ->
%% NOTE: validators do not require the onion or lora server
%% however removing these here breaks tests
%% there is no harm done by leaving them running

%% core and sibyl need to callback to miner_poc_mgr
%% and so we need to set an env var to let it know the mod name
application:set_env(blockchain, poc_mgr_mod, miner_poc_mgr),
application:set_env(sibyl, poc_mgr_mod, miner_poc_mgr),
application:set_env(sibyl, poc_report_handler, miner_poc_report_handler),
PocMgrTab = miner_poc_mgr:make_ets_table(),
POCMgrOpts = #{tab1 => PocMgrTab},
[PocMgrTab1, PocMgrTab2] = miner_poc_mgr:make_ets_table(),
POCMgrOpts = #{tab1 => PocMgrTab1, tab2 => PocMgrTab2},
POCOpts = #{base_dir => BaseDir,
cfs => ["default",
"poc_mgr_cf"
Expand Down
55 changes: 54 additions & 1 deletion src/miner_val_heartbeat.erl
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,11 @@ handle_info({blockchain_event, {add_block, Hash, Sync, _Ledger}},
%% we need to construct and submit a heartbeat txn
{ok, CBMod} = blockchain_ledger_v1:config(?predicate_callback_mod, Ledger),
{ok, Callback} = blockchain_ledger_v1:config(?predicate_callback_fun, Ledger),
{EmpKeys, EmpKeyHashes} = generate_poc_keys(Ledger),
lager:debug("HB poc ephemeral keys ~p", [EmpKeys]),
ok = miner_poc_mgr:save_local_poc_keys(Height, EmpKeys),
UnsignedTxn =
blockchain_txn_validator_heartbeat_v1:new(Address, Height, CBMod:Callback()),
blockchain_txn_validator_heartbeat_v1:new(Address, Height, CBMod:Callback(), EmpKeyHashes),
Txn = blockchain_txn_validator_heartbeat_v1:sign(UnsignedTxn, SigFun),
lager:info("submitting txn ~p for val ~p ~p ~p", [Txn, Val, N, HBInterval]),
Self = self(),
Expand Down Expand Up @@ -132,3 +135,53 @@ code_change(_OldVsn, State, _Extra) ->
%%%===================================================================
%%% Internal functions
%%%===================================================================
-spec generate_poc_keys(blockchain:ledger()) ->
{[#{secret => libp2p_crypto:privkey(), public => libp2p_crypto:pubkey()}], [binary()]}.
generate_poc_keys(Ledger) ->
case blockchain_ledger_v1:config(?poc_challenger_type, Ledger) of
{ok, validator} ->
%% if a val is in the ignore list then dont generate poc keys for it
%% TODO: this is a temp hack. remove when testing finished
IgnoreVals = application:get_env(sibyl, validator_ignore_list, []),
SelfPubKeyBin = blockchain_swarm:pubkey_bin(),
case not lists:member(SelfPubKeyBin, IgnoreVals) of
true ->
%% generate a set of ephemeral keys for POC usage
%% count is based on the num of active validators and the
%% target challenge rate
%% we also have to consider that key proposals are
%% submitted by validators as part of their heartbeats
%% which are only submitted periodically
%% so we need to ensure we have sufficient count of
%% key proposals submitted per HB
%% to help with this we reduce the number of val count
%% by 20% so that we have surplus keys being submitted
EphemeralKeyCount =
case sibyl_mgr:validator_count() of
NumVals when NumVals > 0 ->
{ok, ChallengeRate} = blockchain_ledger_v1:config(?poc_challenge_rate, Ledger),
{ok, HBInterval} = blockchain_ledger_v1:config(?validator_liveness_interval, Ledger),
round((ChallengeRate / (NumVals * 0.8 )) * HBInterval);
_ ->
0
end,
lager:info("heartbeat ephemeral key count ~p", [EphemeralKeyCount]),
generate_ephemeral_keys(EphemeralKeyCount);
false ->
{[], []}
end;
_ ->
{[], []}

end.

-spec generate_ephemeral_keys(pos_integer()) -> {[#{secret => libp2p_crypto:privkey(), public => libp2p_crypto:pubkey()}], [binary()]}.
generate_ephemeral_keys(NumKeys) ->
lists:foldl(
fun(_N, {AccKeys, AccHashes})->
Keys = libp2p_crypto:generate_keys(ecc_compact),
#{public := OnionCompactKey} = Keys,
OnionHash = crypto:hash(sha256, libp2p_crypto:pubkey_to_bin(OnionCompactKey)),
{[Keys | AccKeys], [OnionHash | AccHashes]}
end,
{[], []}, lists:seq(1, NumKeys)).
Loading

0 comments on commit a2c69fe

Please sign in to comment.