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

Implement broadcasting a pre-image #530

Merged
merged 3 commits into from Feb 18, 2020
Merged

Conversation

linked0
Copy link
Contributor

@linked0 linked0 commented Feb 7, 2020

This PR is about broadcasting a pre-image and saving it into the validator set table.

  • sendPreimage endpoint in Validator API

#492

@codecov
Copy link

codecov bot commented Feb 7, 2020

Codecov Report

Merging #530 into v0.x.x will decrease coverage by 1%.
The diff coverage is 84.28%.

Impacted file tree graph

@@            Coverage Diff             @@
##           v0.x.x     #530      +/-   ##
==========================================
- Coverage   89.14%   88.14%   -1.01%     
==========================================
  Files          59       58       -1     
  Lines        4285     4320      +35     
==========================================
- Hits         3820     3808      -12     
- Misses        465      512      +47
Flag Coverage Δ
#integration ?
#unittests 88.14% <84.28%> (+0.02%) ⬆️
Impacted Files Coverage Δ
source/agora/test/EnrollmentManager.d 96.29% <100%> (+0.64%) ⬆️
source/agora/network/NetworkClient.d 92.1% <100%> (+0.43%) ⬆️
source/agora/node/GossipProtocol.d 100% <100%> (ø) ⬆️
source/agora/node/Node.d 86.56% <100%> (-10.36%) ⬇️
source/agora/test/Base.d 87.7% <100%> (+0.2%) ⬆️
source/agora/network/NetworkManager.d 69.86% <75%> (-4.79%) ⬇️
source/agora/consensus/EnrollmentManager.d 86.24% <80.76%> (-1.32%) ⬇️
source/agora/common/Task.d 0% <0%> (-100%) ⬇️
source/agora/common/Config.d 72.72% <0%> (-17.49%) ⬇️
... and 7 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6584fcf...99f3c12. Read the comment docs.

{
public Hash utxo_key;
public Hash hash;
public uint round;
Copy link
Collaborator

Choose a reason for hiding this comment

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

That's an interesting approach. When we were originally talking about it, I had in mind that this would by block height, not round. Because the issue is that if you re-use the same utxo_key (as you would), then you can do replay attacks.
Of course validation would fail, but you could potentially pretend a node sent you the wrong preimage data. We didn't factor any slashing rules that could be triggered by this tho.

A downside of using the block_height is that it's harder to pre-emptively broadcast preimage as you don't know whe height at which it'll be included. But that can be dealt with when the enrollment is received.

Copy link
Collaborator

Choose a reason for hiding this comment

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

In any case, this could use some documentation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd like accept your thought because it's more convenient to recognize the block to which the preimage is related. So, I could add the variable named start_block_height into the Enrollment structure which is the block height where a validator is supposed to participate in validating. Then, The variable, round of the PreimageInfo structure could be replaced with a variable like round_block_height. How about this?

Copy link
Collaborator

Choose a reason for hiding this comment

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

start_block_height

Minor stylistic note: "height" is pretty unambiguous in blockchain code, so you can just use start_height (because there's no other height that block height).

which is the block height where a validator is supposed to participate in validating

I'll have to double check, the exact flow, but bear in mind that if we go this way, it is an implicit value. What I mean is that, when you create an Enrollment structure and sign it, you cannot know which start_height you will be assigned, because it has to be accepted by the validators. Same goes for transactions, when you create a transaction, you cannot know at which height it will be.

Does that make sense ? Also, I think both approaches have their merits, so maybe let's have a whiteboarding session about it ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I understand what you're considering. After a bit of thought, I can use the enrolled_height variable which is implemented by Henry. The value of enrolled_height + 1 will have the same value as what I want to have with the start_block_height variable. It's good to have a whiteboarding session.

PreimageInfo preimage;
auto round = 1000;
assert(man.getPreimage(1000, preimage));
assert(preimage.hash == man.preimages[round-1]);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should also test with 0 and > ValidatorCycleLength

{
public Hash utxo_key;
public Hash hash;
public uint round;
Copy link
Collaborator

Choose a reason for hiding this comment

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

In any case, this could use some documentation

///
unittest
{
uint CycleLength = 1008;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use const if it isn't going to be modified

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also, since you made it a constant in an earlier commit, can we just use it ?

*******************************************************************************/

public string isInvalidPreimageReason (const ref Hash preimage, const uint round,
const ref Hash init_seed, immutable uint cycle_length) nothrow @safe
Copy link
Collaborator

Choose a reason for hiding this comment

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

For value type, const / immutable does not make sense. So just use uint.


// check the pre-image has a right hash value
Hash temp_hash = preimage;
for (int i = round; i < cycle_length; i++)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
for (int i = round; i < cycle_length; i++)
for (uint i = round; i < cycle_length; i++)


***************************************************************************/

public void sendPreimage (PreimageInfo preimage) @trusted
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
public void sendPreimage (PreimageInfo preimage) @trusted
public void sendPreimage (ref PreimageInfo preimage) @trusted


*******************************************************************************/

public struct PreimageInfo
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should probably be in consensus.data

@@ -433,6 +433,12 @@ public interface TestAPI : API

///
public abstract Enrollment createEnrollmentData();

///
public abstract PreimageInfo getNodePreimage(uint round);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
public abstract PreimageInfo getNodePreimage(uint round);
public abstract PreimageInfo getNodePreimage (uint round);


***************************************************************************/

public void sendPreimage (PreimageInfo preimage);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Naming wise, we have receiveEnvelope but sendPreimage. I don't mind either way but we should be consistent.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean changing the function name into a name like receivePreimage? If you do, changing the name is not a problem for me. I mean I can change the neme.

preimage_1 = node_1.getNodePreimage(1000);
node_1.sendPreimage(preimage_1);
auto preimage_2 = node_2.getValidatorPreimage(preimage_1.enroll_key);
assert(preimage_1 == preimage_2);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not black box testing. Adding 2 special methods means you aren't really testing the API.
A better test would be to send a pre-image and check if the (X) next block contains it.
Additionally you could filter the sendPreimage function of a block to see if it propagates correctly even in the absence of the preimage in one block (but that depends on Henry's PR)/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My original approach is not to save pre-images into a block. It's stored only in the validator set table. A pre-image can be restored from another nodes if the database has been crashed. In that case, another API endpoint like getPreimage is needed with the getNodePreimage and getValidatorPreimage removed. Anyway the two functions could be confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is another approach about saving pre-images. It's to store the source value of the random seed encrypted with a node's private key into the Enrollment structure. With that, if the database crashed, the source value of the random seed used for enrollment can be restored from the chain.

@linked0 linked0 force-pushed the send-preimage branch 2 times, most recently from 029981c to 2939554 Compare February 11, 2020 00:43
***************************************************************************/

public bool getPreimage (uint round, out PreimageInfo preimage)
@trusted nothrow
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why @trusted ?

@linked0
Copy link
Contributor Author

linked0 commented Feb 12, 2020

I will make a smaller PR including two commits of this PR and apply reviewer's suggestion in the new PR. And then, I will handle with the remaining commits of this PR which is not inluded in the new PR.

@linked0
Copy link
Contributor Author

linked0 commented Feb 17, 2020

Ready for review.
In order to make smaller PRs, I am splitting this PR to three or four PRs inclusive of this PR. So In this PR, I only put the code about the sendPreimage endpoint in Validator API.

source/agora/consensus/EnrollmentManager.d Outdated Show resolved Hide resolved
@linked0 linked0 force-pushed the send-preimage branch 2 times, most recently from c739564 to 0bde88c Compare February 17, 2020 05:42
Copy link
Contributor

@AndrejMitrovic AndrejMitrovic left a comment

Choose a reason for hiding this comment

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

Not done reviewing, github won't let me continue because of a push.

source/agora/consensus/EnrollmentManager.d Outdated Show resolved Hide resolved
source/agora/consensus/EnrollmentManager.d Outdated Show resolved Hide resolved
source/agora/consensus/EnrollmentManager.d Show resolved Hide resolved
Copy link
Contributor

@AndrejMitrovic AndrejMitrovic left a comment

Choose a reason for hiding this comment

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

Reviewed first commit.

source/agora/consensus/EnrollmentManager.d Outdated Show resolved Hide resolved
{
() @trusted {
this.db.execute("UPDATE validator_set SET preimage = ? " ~
"WHERE key = ?", buffer, preimage.enroll_key.toString());
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment about memory allocation, toString() allocates. Can use sformat to write the entire string to a buffer before calling execute.

source/agora/consensus/EnrollmentManager.d Outdated Show resolved Hide resolved
source/agora/network/NetworkClient.d Outdated Show resolved Hide resolved
source/agora/node/GossipProtocol.d Outdated Show resolved Hide resolved
source/agora/node/GossipProtocol.d Outdated Show resolved Hide resolved
source/agora/test/Base.d Outdated Show resolved Hide resolved

// tests for revealing a pre-image
auto preimage = node_1.getPreimage(1000);
node_1.receivePreimage(preimage);
Copy link
Contributor

Choose a reason for hiding this comment

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

This node should already know about its own preimages. It is odd that it would need to send the preimage to itself in order to know about it, no?

@AndrejMitrovic
Copy link
Contributor

Done with review.

@linked0 linked0 force-pushed the send-preimage branch 2 times, most recently from 9c943dc to 74c5006 Compare February 18, 2020 05:39
The EnrollmentManger class must provide functions to add a piece of
pre-image information and check existence of it for broadcasting preimage.
A Node reveals a pre-image information into the network. The broadcasting of
a pre-image is processed through the gossip protocol.
Copy link
Collaborator

@Geod24 Geod24 left a comment

Choose a reason for hiding this comment

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

LGTM, let's move forward with this.

@@ -43,6 +43,8 @@
module agora.api.Validator;

import agora.common.crypto.Key;
import agora.common.Hash;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
import agora.common.Hash;
import agora.common.Types;

@Geod24 Geod24 dismissed stale reviews from TrustHenry and AndrejMitrovic February 18, 2020 07:56

Addressed

@Geod24 Geod24 merged commit b6c859f into bosagora:v0.x.x Feb 18, 2020
@linked0 linked0 deleted the send-preimage branch March 29, 2020 02:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants