Handle empty block id#66
Conversation
| impl From<&block::Id> for BlockId { | ||
| fn from(bid: &block::Id) -> Self { | ||
| let bid_hash = bid.hash.as_bytes().unwrap().to_vec(); | ||
| let bid_hash = bid.hash.as_bytes().unwrap_or(&[]).to_vec(); |
There was a problem hiding this comment.
This seems like a weird way of addressing the problem... doesn't it result in an invalid BlockId?
I'd suggest changing this whole impl to either:
impl From<&block::Id> for Option<BlockId>or
impl TryFrom<&block::Id> for BlockIdThere was a problem hiding this comment.
This is how golang tendermint handled this. I agree we should do better. But we have to handle the serialization identical to golang version to compute signing bytes, what do you think of that?
There was a problem hiding this comment.
In Rust I think it's more idiomatic to reflect the distinction using the type system
There was a problem hiding this comment.
I think we can also remove the Option in the parts_header field. I think when hash is not empty, parts_header can't be empty.
1c34c3b to
54da372
Compare
|
I've changed |
1508abb to
23b0a08
Compare
|
I've removed branch |
23b0a08 to
e6d188d
Compare
and correctly compute header hash when block id is empty. Represent empty Hash with Option
e6d188d to
8b1d3dc
Compare
ebuchman
left a comment
There was a problem hiding this comment.
Thanks for this, though it seems a bit unfortunate. I opened an issue on the Tendermint repo to consider if we should address this more fundamentally: tendermint/tendermint#4241
ebuchman
left a comment
There was a problem hiding this comment.
To be honest I don't fully understand this. Why couldn't we somehow utilize the fact that Hash is an enum with a Null variant to deal with this? We changed all the header fields to Options but Options are themselves just enum types so I'd imagine we could do this more cleanly using the Hash type with a Null variant ...
|
@ebuchman it's definitely another option (there and back again). It looks like In retrospect, I can see how |
|
#84 included this PR so that's why it was removed there too. I think for this case where we have these possibly null types where the possibility of being null is almost always only related to the first block (rather than normal operation) we could have a cleaner solution by encapsulating the possibility of null in the underlying types rather than in their wrappers. Still not sure, but it does seem it'd be a bit cleaner and simpler. |
|
|
|
Could go either way on that, but I don't frequently see |
|
Put a |
|
Would it be better to explicitly code the type of the first block without all the fields that will be empty and then use a |
|
Ok opened an issue: #101 |
I think it's only the deserialisation code needs some extra care here, other than that, |
|
What's the problem with all zero hashes then? It seems that's what rust version of cardano did: |
|
@yihuang IMO an all-zero hash is about the worst thing you can do... the outputs of digest functions are supposed to be random oracles, and all zeroes are anything but. The risk is an all-zero hash value is inadvertently included in something like a Merkle tree computation. |
Fix panic when dealing with empty block id in the first block.