From 6ddc0199ef6347eec178d4a41b24b26129018293 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 19 Sep 2018 19:34:08 +0200 Subject: [PATCH] WIP: get a feel for what changes will be necessary and where to put the new Response / Request types --- types/canonical_json.go | 12 ------------ types/evidence.go | 33 +++++++++++++++++---------------- types/priv_validator.go | 16 ++++++++++------ types/signable.go | 4 +--- types/test_util.go | 3 ++- types/validator_set.go | 2 +- types/vote.go | 21 ++++++++++++++++++--- 7 files changed, 49 insertions(+), 42 deletions(-) diff --git a/types/canonical_json.go b/types/canonical_json.go index d8399ff19..0c5d8f726 100644 --- a/types/canonical_json.go +++ b/types/canonical_json.go @@ -83,18 +83,6 @@ func CanonicalProposal(chainID string, proposal *Proposal) CanonicalJSONProposal } } -func CanonicalVote(chainID string, vote *Vote) CanonicalJSONVote { - return CanonicalJSONVote{ - ChainID: chainID, - Type: "vote", - BlockID: CanonicalBlockID(vote.BlockID), - Height: vote.Height, - Round: vote.Round, - Timestamp: CanonicalTime(vote.Timestamp), - VoteType: vote.Type, - } -} - func CanonicalHeartbeat(chainID string, heartbeat *Heartbeat) CanonicalJSONHeartbeat { return CanonicalJSONHeartbeat{ ChainID: chainID, diff --git a/types/evidence.go b/types/evidence.go index 2526a3942..3c988caf1 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -4,7 +4,7 @@ import ( "bytes" "fmt" - amino "github.com/tendermint/go-amino" + "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/merkle" @@ -62,8 +62,9 @@ func MaxEvidenceBytesPerBlock(blockMaxBytes int) int { // DuplicateVoteEvidence contains evidence a validator signed two conflicting votes. type DuplicateVoteEvidence struct { PubKey crypto.PubKey - VoteA *Vote - VoteB *Vote + // TODO(ismail): this probably need to be `SignedVoteReply`s + VoteA *SignVoteReply + VoteB *SignVoteReply } // String returns a string representation of the evidence. @@ -74,7 +75,7 @@ func (dve *DuplicateVoteEvidence) String() string { // Height returns the height this evidence refers to. func (dve *DuplicateVoteEvidence) Height() int64 { - return dve.VoteA.Height + return dve.VoteA.Vote.Height } // Address returns the address of the validator. @@ -91,39 +92,39 @@ func (dve *DuplicateVoteEvidence) Hash() []byte { // To be conflicting, they must be from the same validator, for the same H/R/S, but for different blocks. func (dve *DuplicateVoteEvidence) Verify(chainID string, pubKey crypto.PubKey) error { // H/R/S must be the same - if dve.VoteA.Height != dve.VoteB.Height || - dve.VoteA.Round != dve.VoteB.Round || - dve.VoteA.Type != dve.VoteB.Type { + if dve.VoteA.Vote.Height != dve.VoteB.Vote.Height || + dve.VoteA.Vote.Round != dve.VoteB.Vote.Round || + dve.VoteA.Vote.Type != dve.VoteB.Vote.Type { return fmt.Errorf("DuplicateVoteEvidence Error: H/R/S does not match. Got %v and %v", dve.VoteA, dve.VoteB) } // Address must be the same - if !bytes.Equal(dve.VoteA.ValidatorAddress, dve.VoteB.ValidatorAddress) { - return fmt.Errorf("DuplicateVoteEvidence Error: Validator addresses do not match. Got %X and %X", dve.VoteA.ValidatorAddress, dve.VoteB.ValidatorAddress) + if !bytes.Equal(dve.VoteA.Vote.ValidatorAddress, dve.VoteB.Vote.ValidatorAddress) { + return fmt.Errorf("DuplicateVoteEvidence Error: Validator addresses do not match. Got %X and %X", dve.VoteA.Vote.ValidatorAddress, dve.VoteB.Vote.ValidatorAddress) } // Index must be the same - if dve.VoteA.ValidatorIndex != dve.VoteB.ValidatorIndex { - return fmt.Errorf("DuplicateVoteEvidence Error: Validator indices do not match. Got %d and %d", dve.VoteA.ValidatorIndex, dve.VoteB.ValidatorIndex) + if dve.VoteA.Vote.ValidatorIndex != dve.VoteB.Vote.ValidatorIndex { + return fmt.Errorf("DuplicateVoteEvidence Error: Validator indices do not match. Got %d and %d", dve.VoteA.Vote.ValidatorIndex, dve.VoteB.Vote.ValidatorIndex) } // BlockIDs must be different - if dve.VoteA.BlockID.Equals(dve.VoteB.BlockID) { - return fmt.Errorf("DuplicateVoteEvidence Error: BlockIDs are the same (%v) - not a real duplicate vote", dve.VoteA.BlockID) + if dve.VoteA.Vote.BlockID.Equals(dve.VoteB.Vote.BlockID) { + return fmt.Errorf("DuplicateVoteEvidence Error: BlockIDs are the same (%v) - not a real duplicate vote", dve.VoteA.Vote.BlockID) } // pubkey must match address (this should already be true, sanity check) - addr := dve.VoteA.ValidatorAddress + addr := dve.VoteA.Vote.ValidatorAddress if !bytes.Equal(pubKey.Address(), addr) { return fmt.Errorf("DuplicateVoteEvidence FAILED SANITY CHECK - address (%X) doesn't match pubkey (%v - %X)", addr, pubKey, pubKey.Address()) } // Signatures must be valid - if !pubKey.VerifyBytes(dve.VoteA.SignBytes(chainID), dve.VoteA.Signature) { + if !pubKey.VerifyBytes(dve.VoteA.Vote.SignBytes(), dve.VoteA.Signature) { return fmt.Errorf("DuplicateVoteEvidence Error verifying VoteA: %v", ErrVoteInvalidSignature) } - if !pubKey.VerifyBytes(dve.VoteB.SignBytes(chainID), dve.VoteB.Signature) { + if !pubKey.VerifyBytes(dve.VoteB.Vote.SignBytes(), dve.VoteB.Signature) { return fmt.Errorf("DuplicateVoteEvidence Error verifying VoteB: %v", ErrVoteInvalidSignature) } diff --git a/types/priv_validator.go b/types/priv_validator.go index 1642be41b..f5ec04ee3 100644 --- a/types/priv_validator.go +++ b/types/priv_validator.go @@ -14,7 +14,7 @@ type PrivValidator interface { GetAddress() Address // redundant since .PubKey().Address() GetPubKey() crypto.PubKey - SignVote(chainID string, vote *Vote) error + SignVote(vote *Vote) (SignVoteReply, error) SignProposal(chainID string, proposal *Proposal) error SignHeartbeat(chainID string, heartbeat *Heartbeat) error } @@ -62,14 +62,18 @@ func (pv *MockPV) GetPubKey() crypto.PubKey { } // Implements PrivValidator. -func (pv *MockPV) SignVote(chainID string, vote *Vote) error { - signBytes := vote.SignBytes(chainID) +func (pv *MockPV) SignVote(vote *Vote) (SignVoteReply, error) { + signBytes := vote.SignBytes() sig, err := pv.privKey.Sign(signBytes) if err != nil { - return err + // TODO(ismail): encapsulate error into reply! + return SignVoteReply{}, err } - vote.Signature = sig - return nil + + return SignVoteReply{ + Vote: *vote, + Signature: sig, + }, nil } // Implements PrivValidator. diff --git a/types/signable.go b/types/signable.go index cc6498882..beed64f95 100644 --- a/types/signable.go +++ b/types/signable.go @@ -3,9 +3,7 @@ package types // Signable is an interface for all signable things. // It typically removes signatures before serializing. // SignBytes returns the bytes to be signed -// NOTE: chainIDs are part of the SignBytes but not -// necessarily the object themselves. // NOTE: Expected to panic if there is an error marshalling. type Signable interface { - SignBytes(chainID string) []byte + SignBytes() []byte } diff --git a/types/test_util.go b/types/test_util.go index e20ea212e..c7b47fbd0 100644 --- a/types/test_util.go +++ b/types/test_util.go @@ -31,7 +31,8 @@ func MakeCommit(blockID BlockID, height int64, round int, } func signAddVote(privVal PrivValidator, vote *Vote, voteSet *VoteSet) (signed bool, err error) { - err = privVal.SignVote(voteSet.ChainID(), vote) + vote.ChainID = voteSet.ChainID() + repl, err := privVal.SignVote(vote) if err != nil { return false, err } diff --git a/types/validator_set.go b/types/validator_set.go index 4dab4d840..67631bb32 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -287,7 +287,7 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height i } _, val := vals.GetByIndex(idx) // Validate signature. - precommitSignBytes := precommit.SignBytes(chainID) + precommitSignBytes := precommit.SignBytes() if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) { return fmt.Errorf("Invalid commit -- invalid signature: %v", precommit) } diff --git a/types/vote.go b/types/vote.go index 6481f56b9..c7be0805e 100644 --- a/types/vote.go +++ b/types/vote.go @@ -73,11 +73,26 @@ type Vote struct { Timestamp time.Time `json:"timestamp"` Type byte `json:"type"` BlockID BlockID `json:"block_id"` // zero if vote is nil. - Signature []byte `json:"signature"` + ChainID string `json:"chain_id"` } -func (vote *Vote) SignBytes(chainID string) []byte { - bz, err := cdc.MarshalJSON(CanonicalVote(chainID, vote)) +type SignVoteRequest struct { + Vote Vote +} + +type SignVoteReply struct { + Vote Vote + Signature []byte + Err Error +} + +type Error struct { + ErrCode uint16 + Description string +} + +func (vote *Vote) SignBytes() []byte { + bz, err := cdc.MarshalBinary(vote) if err != nil { panic(err) }