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

Secure Message Delivery initial changes #1714

Merged
merged 4 commits into from Jul 19, 2019
Merged

Conversation

fizyk20
Copy link
Contributor

@fizyk20 fizyk20 commented Jul 16, 2019

This PR makes some initial changes related to SMD:

  • Add a BLS emulation layer in order to enable writing code that pretends to use BLS before BLS is merged in
  • Add our_history and their_keys to the shared state
  • Update our_history together with our_infos

Closes #1672
Closes #1673
Closes #1674
Closes #1675

@fizyk20 fizyk20 added the wip label Jul 16, 2019
Copy link
Contributor

@jeanphilippeD jeanphilippeD left a comment

Choose a reason for hiding this comment

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

Looks good a couple of comments.
Mostly can we test the new code?


impl fmt::Debug for PublicKey {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "[BLS PublicKey]")
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe use the SectionInfo debug value here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right. This was pre-SectionInfo, but it makes sense now 👍

src/chain/bls_emu.rs Show resolved Hide resolved

#[derive(Clone, PartialEq, Eq)]
pub struct SectionProofBlock {
key: PublicKey,
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make sense as BlsPublicKey and BlsSignature?
I'm thinking having 2 different crypto keys/signature will cause confusion if we are not explicit.

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 was kind of aiming for a drop-in replacement of BLS. With these names, we can just replace use bls_emu::... with use threshold_crypto::... and it should (mostly) just work. I can use bls_emu::PublicKey as BlsPublicKey etc., though.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, could also do that at the crate level in lib.rs so you only do it once and then use crate::{BlsPublicKey, ...}

src/chain/chain.rs Show resolved Hide resolved
jeanphilippeD
jeanphilippeD previously approved these changes Jul 17, 2019
Copy link
Contributor

@jeanphilippeD jeanphilippeD left a comment

Choose a reason for hiding this comment

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

Looks good to me.

@fizyk20 fizyk20 changed the title WIP: Secure Message Delivery initial changes Secure Message Delivery initial changes Jul 17, 2019
@fizyk20 fizyk20 removed the wip label Jul 17, 2019
jeanphilippeD
jeanphilippeD previously approved these changes Jul 18, 2019
Copy link
Contributor

@jeanphilippeD jeanphilippeD left a comment

Choose a reason for hiding this comment

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

Looks good

pub struct PublicKeyShare(PublicId);

#[derive(Clone, PartialEq, Eq)]
pub struct Signature {
Copy link
Member

Choose a reason for hiding this comment

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

shall the name of the struct to be Signatures ?
Also, as it only contains one field, shall it be Signatures(BTreeMap<PublicId, SignatureShare>) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This struct is supposed to emulate the BLS Signature type, hence it's singular - with BLS, this would be indeed just a single signature, here we just emulate the functionality using a set of signatures.
I could make it a tuple struct, though.

Copy link
Contributor

Choose a reason for hiding this comment

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

Quite happy with the struct with a name as it is personally.

}

#[derive(Clone, PartialEq, Eq)]
pub struct PublicKey(PublicKeySet);
Copy link
Member

Choose a reason for hiding this comment

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

I got little bit confused with the first glance of this PublicKey(PublicKeySet).
Also, the name of the file is bls_emu.rs.
However the comment at #1714 (comment) mentioned BlsPublicKey as well for the shared state.
I am not sure, however shall we use Bls... here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Like with Signature - this is an emulated implementation of threshold_crypto::PublicKey. I want to keep the names the same as they are in threshold_crypto, so that when we merge BLS, we can just replace this module with threshold_crypto crate and keep the rest of the code mostly intact.

In this case, we would replace this in lib.rs:
pub use crate::chain::bls_emu::PublicKey as BlsPublicKey;
with this:
pub use threshold_crypto::PublicKey as BlsPublicKey;
when BLS is merged.


pub fn from_section_info(threshold: usize, sec_info: SectionInfo) -> Self {
Self {
threshold,
Copy link
Member

Choose a reason for hiding this comment

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

just wondering, can the threshold be deduced from the section info?
and in which case the threshold can be un-related to the section info?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In our use cases, it probably can - but I wanted to keep the code as generic as possible. This part probably won't make it to the code after BLS is merged, so maybe coupling the threshold with the section info here is not such a bad idea. What do you think @jeanphilippeD ?

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 you can make that function non public as well.
Since it is code that is going to go away, I'd go for whatever is simpler.

It seem it may be simplifying code & test if you use your delivery_group function inside it instead of taking the threshold param? would it?

Copy link
Contributor

Choose a reason for hiding this comment

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

(as in you are using in in PublicKey, so why not moving it into PublicKeySet?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I originally wanted to calculate the threshold completely outside this module to make the functionality boundaries more clear (BLS won't be aware of our threshold requirements, we'll have to pass it the threshold we want explicitly), but then I did this thing in PublicKey. I'm not sure which is better - make the method in PublicKey also take the threshold from outside, or just move this into PublicKeySet. Might be that it's the latter, as this code won't work with real BLS, anyway (we won't be able to derive keys from SectionInfos, we'll have to get them from DKG).

Copy link
Contributor

Choose a reason for hiding this comment

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

Correct me if I'm wrong, but we will not pass the threshold to either signature or public key, only the DKG.

The way we'll know we reach the threshold is if the combined signature is valid against the public key.

If anything, we would use the threshold directly in the signature validation. But where it is fine too (i.e pre-computed once and cached). and I don't want us spend too much time on something that is going to be disappearing soon-ish :-)

Copy link
Contributor

Choose a reason for hiding this comment

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

(also I still assume we'll have to fix stuff when moving to real BLS).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I think you're right - the threshold is passed to the DKG, then it is actually stored in the resulting PublicKeySet IIRC (it has to know what the degree of the polynomial needs to be when combining the signatures).

.map(|(pk, ss)| (pk.0, *ss))
.collect();
if sigs.len() <= self.threshold {
None
Copy link
Member

Choose a reason for hiding this comment

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

the name of the function is combine, however here seems a threshold screening ?
if it's really required, would it be better to at least have a comment to explain?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This emulates threshold_crypto::PublicKeySet::combine_signatures, which can only succeed if there are more than threshold valid signatures. Again, the reason here is the emulation of BLS functionality. I can add a comment 👍

Copy link
Member

Choose a reason for hiding this comment

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

yeah, pls add a comment then. thx

impl PublicKey {
pub fn from_section_info(sec_info: &SectionInfo) -> Self {
let threshold = delivery_group_size(sec_info.members().len()) - 1;
PublicKey(PublicKeySet::from_section_info(threshold, sec_info.clone()))
Copy link
Member

Choose a reason for hiding this comment

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

as mentioned above, I'd prefer the threshold to be calculated inside the PublicKeySet::from_section_info function.

self.blocks.push(block);
}

#[allow(unused)]
Copy link
Member

Choose a reason for hiding this comment

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

if this function is only to be used during test, shall we use cfg(test) guard instead of the allow(unused)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's only used in tests now, but it is intended to be used in production code as well in the future - it will probably be useful during verification of chains attached to messages.

let mut current_pk = &self.genesis_pk;
for block in &self.blocks {
if !block.verify_with_pk(current_pk) {
return false;
Copy link
Member

Choose a reason for hiding this comment

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

maybe log some info about which block fails the verification?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What kind of message would you have in mind, though? The blocks don't really contain any meaningful data that would make it easier to identify the offender - it's a public key and a signature, neither is very readable.

Copy link
Member

Choose a reason for hiding this comment

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

maybe the public key (which is a public id)?
In case of failure, we need to find out who is failing anyway, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The public key here is more of a set of public IDs, not a single one - and it actually contains a full section info... But it makes sense 👍

Copy link
Member

Choose a reason for hiding this comment

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

right, then maybe that shall be inside the PublicKey::verify, we shall log which one is failing or whether it's not reaching the threshold.
Maybe no need to log whehter reaching the threshold.
However failing a signature is some behaviour shall be noticed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Would not spend too much time on that, when we debug the first issue we will find out what log we need and we can add it then (it might be neither of the options, as I think we will probably want the id of the current node).

So I'd say, add something minimal if that make sense otherwise happy to leave it as is.

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 think I'd leave it as is for now, then - adding some logging to the verification with a single public ID would make the code there quite a bit uglier, which we can probably do temporarily when debugging, but I'm not sure if it's worth it to have such code by default.

@jeanphilippeD jeanphilippeD merged commit 1622e11 into maidsafe:fleming Jul 19, 2019
@fizyk20 fizyk20 deleted the smd branch July 19, 2019 08:42
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.