Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make {TERM, b} messages count towards {BVAL, b} thresholds #38

Merged
merged 2 commits into from
Jan 25, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions src/hbbft_bba.erl
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ handle_msg(_Data, _J, _Msg) ->
bval(Data=#bba_data{f=F}, Id, V) ->
%% add to witnesses
Witness = add_witness(Id, V, Data#bba_data.bval_witness, true),
WitnessCount = maps:get({val, V}, Witness, 0),
WitnessCount = maps:get({val, V}, Witness, 0) + maps:get({val, V}, Data#bba_data.terminate_witness, 0),
Copy link
Contributor

@evanmcc evanmcc Jan 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some safety concerns here. This implementation allows nodes to effectively vote twice for a value. I think that this is only safe if the witness tracks the source and only allows one vote per node.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which kind of vote, it is technically valid, I think, for a node to vote for a bval value twice?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I was thinking that a malign set of nodes could emit both immediately, which would push the node over the threshold I think?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add_witness has an 'allow union' flag that prevents changing your vote in the case of a TERM message. BVAL votes are allowed to be made for both values (as the node will emit a {BVAL, b} message once it sees f+1 {BVAL, b} messages).

I'm not clear how many AUX messages can be emitted per round. I think just one, but I'm not sure. Currently it allows a node to propose both.

CONF messages don't use add_witness, but they probably should. and they should allow only a single vote from a node per round.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a commit to prevent more than one AUX or CONF message per round. TERM was already limited and BVAL should allow multiples.


{NewData, ToSend} = case WitnessCount >= F+1 andalso not has(V, Data#bba_data.broadcasted) of
true ->
Expand All @@ -166,8 +166,7 @@ bval(Data=#bba_data{f=F}, Id, V) ->
case WitnessCount >= 2*F+1 of
true ->
%% add to binvalues
NewData2 = Data#bba_data{bval_witness=Witness,
bin_values=add(V, NewData#bba_data.bin_values)},
NewData2 = NewData#bba_data{bin_values=add(V, NewData#bba_data.bin_values)},
{NewData3, ToSend2} = case NewData2#bba_data.aux_sent == false of
true ->
%% XXX How many times do we send AUX per round? I think just once
Expand All @@ -183,15 +182,20 @@ bval(Data=#bba_data{f=F}, Id, V) ->

-spec aux(bba_data(), non_neg_integer(), 0 | 1) -> {bba_data(), ok | {send, [hbbft_utils:multicast(conf_msg())]}}.
aux(Data, Id, V) ->
Witness = add_witness(Id, V, Data#bba_data.aux_witness, true),
Witness = add_witness(Id, V, Data#bba_data.aux_witness, false),
NewData = Data#bba_data{aux_witness = Witness},
decide(NewData, []).

-spec conf(bba_data(), non_neg_integer(), 0 | 1) -> {bba_data(), ok | {send, [hbbft_utils:multicast(coin_msg())]}}.
conf(Data, Id, V) ->
Witness = maps:put(Id, V, Data#bba_data.conf_witness),
NewData = Data#bba_data{conf_witness = Witness},
decide(NewData, []).
case maps:is_key(Id, Data#bba_data.conf_witness) of
false ->
Witness = maps:put(Id, V, Data#bba_data.conf_witness),
NewData = Data#bba_data{conf_witness = Witness},
decide(NewData, []);
true ->
{Data, ok}
end.

sort_msgs(A, B) ->
msg_order(A) =< msg_order(B).
Expand Down