Skip to content

Commit

Permalink
Introduce and use IsZero & IsComplete:
Browse files Browse the repository at this point in the history
 - update IsZero method according to spec and introduce IsComplete
 - use methods in validate basic to validate: proposals come with a
 "complete" blockId and votes are either complete or empty
 - update spec: BlockID.IsNil() -> BlockID.IsZero() and fix typo
  • Loading branch information
liamsi committed Jan 3, 2019
1 parent c966b6a commit 9296f04
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 9 deletions.
8 changes: 4 additions & 4 deletions docs/spec/consensus/signing.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ type PartSetHeader struct {
```

To be included in a valid vote or proposal, BlockID must either represent a `nil` block, or a complete one.
We introduce two methods, `BlockID.IsNil()` and `BlockID.IsComplete()` for these cases, respectively.
We introduce two methods, `BlockID.IsZero()` and `BlockID.IsComplete()` for these cases, respectively.

`BlockID.IsNil()` returns true for BlockID `b` if each of the following
`BlockID.IsZero()` returns true for BlockID `b` if each of the following
are true:

```
Expand All @@ -81,7 +81,7 @@ len(b.PartsHeader.Hash) == 32

## Proposals

The structure of a propsal for signing looks like:
The structure of a proposal for signing looks like:

```
type CanonicalProposal struct {
Expand Down Expand Up @@ -130,7 +130,7 @@ A vote is valid if each of the following lines evaluates to true for vote `v`:
v.Type == 0x1 || v.Type == 0x2
v.Height > 0
v.Round >= 0
v.BlockID.IsNil() || v.BlockID.IsValid()
v.BlockID.IsZero() || v.BlockID.IsComplete()
```

In other words, a vote is valid for signing if it contains the type of a Prevote
Expand Down
20 changes: 15 additions & 5 deletions types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/crypto/tmhash"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/version"
)
Expand Down Expand Up @@ -788,11 +789,6 @@ type BlockID struct {
PartsHeader PartSetHeader `json:"parts"`
}

// IsZero returns true if this is the BlockID for a nil-block
func (blockID BlockID) IsZero() bool {
return len(blockID.Hash) == 0 && blockID.PartsHeader.IsZero()
}

// Equals returns true if the BlockID matches the given BlockID
func (blockID BlockID) Equals(other BlockID) bool {
return bytes.Equal(blockID.Hash, other.Hash) &&
Expand Down Expand Up @@ -820,6 +816,20 @@ func (blockID BlockID) ValidateBasic() error {
return nil
}

// IsZero returns true if this is the BlockID of a nil block.
func (blockID BlockID) IsZero() bool {
return blockID.Hash == nil &&
blockID.PartsHeader.Total == 0 &&
blockID.PartsHeader.Hash == nil
}

// IsComplete returns true if this is a valid BlockID of a non-nil block.
func (blockID BlockID) IsComplete() bool {
return len(blockID.Hash) == tmhash.Size &&
blockID.PartsHeader.Total > 0 &&
len(blockID.PartsHeader.Hash) == tmhash.Size
}

// String returns a human readable string representation of the BlockID
func (blockID BlockID) String() string {
return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader)
Expand Down
4 changes: 4 additions & 0 deletions types/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ func (p *Proposal) ValidateBasic() error {
if err := p.BlockID.ValidateBasic(); err != nil {
return fmt.Errorf("Wrong BlockID: %v", err)
}
// ValidateBasic above would pass even if the blockId was empty:
if !p.BlockID.IsComplete() {
return fmt.Errorf("Expected a complete, non-empty BlockID, got: %v", p.BlockID)
}

// NOTE: Timestamp validation is subtle and handled elsewhere.

Expand Down
5 changes: 5 additions & 0 deletions types/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ func (vote *Vote) ValidateBasic() error {
if err := vote.BlockID.ValidateBasic(); err != nil {
return fmt.Errorf("Wrong BlockID: %v", err)
}
// BlockID.ValidateBasic would not err if we for instance we have an empty hash but a
// non-empty PartsSetHeader:
if !vote.BlockID.IsZero() && !vote.BlockID.IsComplete() {
return fmt.Errorf("BlockID must be either empty or complete, got: %v", vote.BlockID)
}
if len(vote.ValidatorAddress) != crypto.AddressSize {
return fmt.Errorf("Expected ValidatorAddress size to be %d bytes, got %d bytes",
crypto.AddressSize,
Expand Down

0 comments on commit 9296f04

Please sign in to comment.