Browse Source

privval: migrate to protobuf (#4985)

pull/4997/head
Marko 5 years ago
committed by GitHub
parent
commit
f6243d8b9e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 3582 additions and 1009 deletions
  1. +2
    -0
      CHANGELOG_PENDING.md
  2. +4
    -1
      blockchain/v1/reactor_test.go
  3. +8
    -2
      consensus/byzantine_test.go
  4. +8
    -2
      consensus/common_test.go
  5. +14
    -4
      consensus/replay_test.go
  6. +9
    -3
      consensus/state.go
  7. +9
    -2
      consensus/state_test.go
  8. +6
    -1
      consensus/types/height_vote_set_test.go
  9. +1
    -0
      crypto/ed25519/ed25519.go
  10. +9
    -3
      evidence/pool_test.go
  11. +12
    -0
      libs/math/safemath.go
  12. +4
    -2
      light/helpers_test.go
  13. +0
    -14
      privval/codec.go
  14. +5
    -4
      privval/errors.go
  15. +18
    -19
      privval/file.go
  16. +38
    -31
      privval/file_test.go
  17. +31
    -56
      privval/messages.go
  18. +3
    -2
      privval/retry_signer_client.go
  19. +31
    -18
      privval/signer_client.go
  20. +135
    -41
      privval/signer_client_test.go
  21. +11
    -7
      privval/signer_endpoint.go
  22. +4
    -3
      privval/signer_listener_endpoint.go
  23. +34
    -19
      privval/signer_requestHandler.go
  24. +7
    -8
      privval/signer_server.go
  25. +1315
    -468
      proto/privval/msgs.pb.go
  26. +18
    -5
      proto/privval/msgs.proto
  27. +73
    -29
      proto/privval/types.pb.go
  28. +10
    -1
      proto/privval/types.proto
  29. +1407
    -0
      proto/types/canonical.pb.go
  30. +37
    -0
      proto/types/canonical.proto
  31. +87
    -79
      proto/types/types.pb.go
  32. +2
    -2
      proto/types/types.proto
  33. +11
    -3
      rpc/client/evidence_test.go
  34. +1
    -1
      state/tx_filter_test.go
  35. +38
    -12
      state/validation_test.go
  36. +8
    -4
      tools/tm-signer-harness/internal/test_harness.go
  37. +1
    -1
      tools/tm-signer-harness/internal/test_harness_test.go
  38. +2
    -1
      types/block.go
  39. +7
    -7
      types/block_test.go
  40. +11
    -41
      types/canonical.go
  41. +22
    -10
      types/evidence.go
  42. +11
    -3
      types/evidence_test.go
  43. +11
    -8
      types/priv_validator.go
  44. +8
    -4
      types/proposal.go
  45. +33
    -17
      types/proposal_test.go
  46. +9
    -2
      types/test_util.go
  47. +3
    -1
      types/validator_set_test.go
  48. +14
    -5
      types/vote.go
  49. +40
    -63
      types/vote_test.go

+ 2
- 0
CHANGELOG_PENDING.md View File

@ -49,6 +49,8 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
- [store] \#4778 Transition store module to protobuf encoding - [store] \#4778 Transition store module to protobuf encoding
- `BlockStoreStateJSON` is now `BlockStoreState` and is encoded as binary in the database - `BlockStoreStateJSON` is now `BlockStoreState` and is encoded as binary in the database
- [rpc] \#4968 JSON encoding is now handled by `libs/json`, not Amino - [rpc] \#4968 JSON encoding is now handled by `libs/json`, not Amino
- [types] \#4852 Vote & Proposal `SignBytes` is now func `VoteSignBytes` & `ProposalSignBytes`
- [privval] \#4985 `privval` reactor migration to Protobuf encoding
- [evidence] \#4949 `evidence` reactor migration to Protobuf encoding - [evidence] \#4949 `evidence` reactor migration to Protobuf encoding
- Apps - Apps


+ 4
- 1
blockchain/v1/reactor_test.go View File

@ -69,7 +69,10 @@ func makeVote(
BlockID: blockID, BlockID: blockID,
} }
_ = privVal.SignVote(header.ChainID, vote)
vpb := vote.ToProto()
_ = privVal.SignVote(header.ChainID, vpb)
vote.Signature = vpb.Signature
return vote return vote
} }


+ 8
- 2
consensus/byzantine_test.go View File

@ -181,18 +181,24 @@ func byzantineDecideProposalFunc(t *testing.T, height int64, round int32, cs *St
block1, blockParts1 := cs.createProposalBlock() block1, blockParts1 := cs.createProposalBlock()
polRound, propBlockID := cs.ValidRound, types.BlockID{Hash: block1.Hash(), PartsHeader: blockParts1.Header()} polRound, propBlockID := cs.ValidRound, types.BlockID{Hash: block1.Hash(), PartsHeader: blockParts1.Header()}
proposal1 := types.NewProposal(height, round, polRound, propBlockID) proposal1 := types.NewProposal(height, round, polRound, propBlockID)
if err := cs.privValidator.SignProposal(cs.state.ChainID, proposal1); err != nil {
p1 := proposal1.ToProto()
if err := cs.privValidator.SignProposal(cs.state.ChainID, p1); err != nil {
t.Error(err) t.Error(err)
} }
proposal1.Signature = p1.Signature
// Create a new proposal block from state/txs from the mempool. // Create a new proposal block from state/txs from the mempool.
block2, blockParts2 := cs.createProposalBlock() block2, blockParts2 := cs.createProposalBlock()
polRound, propBlockID = cs.ValidRound, types.BlockID{Hash: block2.Hash(), PartsHeader: blockParts2.Header()} polRound, propBlockID = cs.ValidRound, types.BlockID{Hash: block2.Hash(), PartsHeader: blockParts2.Header()}
proposal2 := types.NewProposal(height, round, polRound, propBlockID) proposal2 := types.NewProposal(height, round, polRound, propBlockID)
if err := cs.privValidator.SignProposal(cs.state.ChainID, proposal2); err != nil {
p2 := proposal2.ToProto()
if err := cs.privValidator.SignProposal(cs.state.ChainID, p2); err != nil {
t.Error(err) t.Error(err)
} }
proposal2.Signature = p2.Signature
block1Hash := block1.Hash() block1Hash := block1.Hash()
block2Hash := block2.Hash() block2Hash := block2.Hash()


+ 8
- 2
consensus/common_test.go View File

@ -105,8 +105,10 @@ func (vs *validatorStub) signVote(
Type: voteType, Type: voteType,
BlockID: types.BlockID{Hash: hash, PartsHeader: header}, BlockID: types.BlockID{Hash: hash, PartsHeader: header},
} }
v := vote.ToProto()
err = vs.PrivValidator.SignVote(config.ChainID(), v)
vote.Signature = v.Signature
err = vs.PrivValidator.SignVote(config.ChainID(), vote)
return vote, err return vote, err
} }
@ -200,9 +202,13 @@ func decideProposal(
// Make proposal // Make proposal
polRound, propBlockID := validRound, types.BlockID{Hash: block.Hash(), PartsHeader: blockParts.Header()} polRound, propBlockID := validRound, types.BlockID{Hash: block.Hash(), PartsHeader: blockParts.Header()}
proposal = types.NewProposal(height, round, polRound, propBlockID) proposal = types.NewProposal(height, round, polRound, propBlockID)
if err := vs.SignProposal(chainID, proposal); err != nil {
p := proposal.ToProto()
if err := vs.SignProposal(chainID, p); err != nil {
panic(err) panic(err)
} }
proposal.Signature = p.Signature
return return
} }


+ 14
- 4
consensus/replay_test.go View File

@ -360,10 +360,13 @@ func TestSimulateValidatorsChange(t *testing.T) {
propBlock, _ := css[0].createProposalBlock() //changeProposer(t, cs1, vs2) propBlock, _ := css[0].createProposalBlock() //changeProposer(t, cs1, vs2)
propBlockParts := propBlock.MakePartSet(partSize) propBlockParts := propBlock.MakePartSet(partSize)
blockID := types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()} blockID := types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()}
proposal := types.NewProposal(vss[1].Height, round, -1, blockID) proposal := types.NewProposal(vss[1].Height, round, -1, blockID)
if err := vss[1].SignProposal(config.ChainID(), proposal); err != nil {
p := proposal.ToProto()
if err := vss[1].SignProposal(config.ChainID(), p); err != nil {
t.Fatal("failed to sign bad proposal", err) t.Fatal("failed to sign bad proposal", err)
} }
proposal.Signature = p.Signature
// set the proposal block // set the proposal block
if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil {
@ -389,10 +392,13 @@ func TestSimulateValidatorsChange(t *testing.T) {
propBlock, _ = css[0].createProposalBlock() //changeProposer(t, cs1, vs2) propBlock, _ = css[0].createProposalBlock() //changeProposer(t, cs1, vs2)
propBlockParts = propBlock.MakePartSet(partSize) propBlockParts = propBlock.MakePartSet(partSize)
blockID = types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()} blockID = types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()}
proposal = types.NewProposal(vss[2].Height, round, -1, blockID) proposal = types.NewProposal(vss[2].Height, round, -1, blockID)
if err := vss[2].SignProposal(config.ChainID(), proposal); err != nil {
p = proposal.ToProto()
if err := vss[2].SignProposal(config.ChainID(), p); err != nil {
t.Fatal("failed to sign bad proposal", err) t.Fatal("failed to sign bad proposal", err)
} }
proposal.Signature = p.Signature
// set the proposal block // set the proposal block
if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil {
@ -447,9 +453,11 @@ func TestSimulateValidatorsChange(t *testing.T) {
selfIndex := valIndexFn(0) selfIndex := valIndexFn(0)
proposal = types.NewProposal(vss[3].Height, round, -1, blockID) proposal = types.NewProposal(vss[3].Height, round, -1, blockID)
if err := vss[3].SignProposal(config.ChainID(), proposal); err != nil {
p = proposal.ToProto()
if err := vss[3].SignProposal(config.ChainID(), p); err != nil {
t.Fatal("failed to sign bad proposal", err) t.Fatal("failed to sign bad proposal", err)
} }
proposal.Signature = p.Signature
// set the proposal block // set the proposal block
if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil {
@ -508,9 +516,11 @@ func TestSimulateValidatorsChange(t *testing.T) {
selfIndex = valIndexFn(0) selfIndex = valIndexFn(0)
proposal = types.NewProposal(vss[1].Height, round, -1, blockID) proposal = types.NewProposal(vss[1].Height, round, -1, blockID)
if err := vss[1].SignProposal(config.ChainID(), proposal); err != nil {
p = proposal.ToProto()
if err := vss[1].SignProposal(config.ChainID(), p); err != nil {
t.Fatal("failed to sign bad proposal", err) t.Fatal("failed to sign bad proposal", err)
} }
proposal.Signature = p.Signature
// set the proposal block // set the proposal block
if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil {


+ 9
- 3
consensus/state.go View File

@ -1032,7 +1032,9 @@ func (cs *State) defaultDecideProposal(height int64, round int32) {
// Make proposal // Make proposal
propBlockID := types.BlockID{Hash: block.Hash(), PartsHeader: blockParts.Header()} propBlockID := types.BlockID{Hash: block.Hash(), PartsHeader: blockParts.Header()}
proposal := types.NewProposal(height, round, cs.ValidRound, propBlockID) proposal := types.NewProposal(height, round, cs.ValidRound, propBlockID)
if err := cs.privValidator.SignProposal(cs.state.ChainID, proposal); err == nil {
p := proposal.ToProto()
if err := cs.privValidator.SignProposal(cs.state.ChainID, p); err == nil {
proposal.Signature = p.Signature
// send proposal and block parts on internal msg queue // send proposal and block parts on internal msg queue
cs.sendInternalMessage(msgInfo{&ProposalMessage{proposal}, ""}) cs.sendInternalMessage(msgInfo{&ProposalMessage{proposal}, ""})
@ -1683,11 +1685,13 @@ func (cs *State) defaultSetProposal(proposal *types.Proposal) error {
return ErrInvalidProposalPOLRound return ErrInvalidProposalPOLRound
} }
p := proposal.ToProto()
// Verify signature // Verify signature
if !cs.Validators.GetProposer().PubKey.VerifyBytes(proposal.SignBytes(cs.state.ChainID), proposal.Signature) {
if !cs.Validators.GetProposer().PubKey.VerifyBytes(types.ProposalSignBytes(cs.state.ChainID, p), proposal.Signature) {
return ErrInvalidProposalSignature return ErrInvalidProposalSignature
} }
proposal.Signature = p.Signature
cs.Proposal = proposal cs.Proposal = proposal
// We don't update cs.ProposalBlockParts if it is already set. // We don't update cs.ProposalBlockParts if it is already set.
// This happens if we're already in cstypes.RoundStepCommit or if there is a valid block in the current round. // This happens if we're already in cstypes.RoundStepCommit or if there is a valid block in the current round.
@ -2008,8 +2012,10 @@ func (cs *State) signVote(
Type: msgType, Type: msgType,
BlockID: types.BlockID{Hash: hash, PartsHeader: header}, BlockID: types.BlockID{Hash: hash, PartsHeader: header},
} }
v := vote.ToProto()
err = cs.privValidator.SignVote(cs.state.ChainID, v)
vote.Signature = v.Signature
err = cs.privValidator.SignVote(cs.state.ChainID, vote)
return vote, err return vote, err
} }


+ 9
- 2
consensus/state_test.go View File

@ -205,10 +205,13 @@ func TestStateBadProposal(t *testing.T) {
propBlockParts := propBlock.MakePartSet(partSize) propBlockParts := propBlock.MakePartSet(partSize)
blockID := types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()} blockID := types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()}
proposal := types.NewProposal(vs2.Height, round, -1, blockID) proposal := types.NewProposal(vs2.Height, round, -1, blockID)
if err := vs2.SignProposal(config.ChainID(), proposal); err != nil {
p := proposal.ToProto()
if err := vs2.SignProposal(config.ChainID(), p); err != nil {
t.Fatal("failed to sign bad proposal", err) t.Fatal("failed to sign bad proposal", err)
} }
proposal.Signature = p.Signature
// set the proposal block // set the proposal block
if err := cs1.SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { if err := cs1.SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil {
t.Fatal(err) t.Fatal(err)
@ -1034,9 +1037,13 @@ func TestStateLockPOLSafety2(t *testing.T) {
round++ // moving to the next round round++ // moving to the next round
// in round 2 we see the polkad block from round 0 // in round 2 we see the polkad block from round 0
newProp := types.NewProposal(height, round, 0, propBlockID0) newProp := types.NewProposal(height, round, 0, propBlockID0)
if err := vs3.SignProposal(config.ChainID(), newProp); err != nil {
p := newProp.ToProto()
if err := vs3.SignProposal(config.ChainID(), p); err != nil {
t.Fatal(err) t.Fatal(err)
} }
newProp.Signature = p.Signature
if err := cs1.SetProposalAndBlock(newProp, propBlock0, propBlockParts0, "some peer"); err != nil { if err := cs1.SetProposalAndBlock(newProp, propBlock0, propBlockParts0, "some peer"); err != nil {
t.Fatal(err) t.Fatal(err)
} }


+ 6
- 1
consensus/types/height_vote_set_test.go View File

@ -70,9 +70,14 @@ func makeVoteHR(t *testing.T, height int64, valIndex, round int32, privVals []ty
BlockID: types.BlockID{Hash: []byte("fakehash"), PartsHeader: types.PartSetHeader{}}, BlockID: types.BlockID{Hash: []byte("fakehash"), PartsHeader: types.PartSetHeader{}},
} }
chainID := config.ChainID() chainID := config.ChainID()
err = privVal.SignVote(chainID, vote)
v := vote.ToProto()
err = privVal.SignVote(chainID, v)
if err != nil { if err != nil {
panic(fmt.Sprintf("Error signing vote: %v", err)) panic(fmt.Sprintf("Error signing vote: %v", err))
} }
vote.Signature = v.Signature
return vote return vote
} }

+ 1
- 0
crypto/ed25519/ed25519.go View File

@ -150,6 +150,7 @@ func (pubKey PubKey) VerifyBytes(msg []byte, sig []byte) bool {
if len(sig) != SignatureSize { if len(sig) != SignatureSize {
return false return false
} }
return ed25519.Verify(ed25519.PublicKey(pubKey), msg, sig) return ed25519.Verify(ed25519.PublicKey(pubKey), msg, sig)
} }


+ 9
- 3
evidence/pool_test.go View File

@ -331,14 +331,20 @@ func TestPotentialAmnesiaEvidence(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
voteA := makeVote(25, 0, 0, pubKey.Address(), firstBlockID) voteA := makeVote(25, 0, 0, pubKey.Address(), firstBlockID)
err = val.SignVote(evidenceChainID, voteA)
vA := voteA.ToProto()
err = val.SignVote(evidenceChainID, vA)
voteA.Signature = vA.Signature
require.NoError(t, err) require.NoError(t, err)
voteB := makeVote(25, 1, 0, pubKey.Address(), secondBlockID) voteB := makeVote(25, 1, 0, pubKey.Address(), secondBlockID)
err = val.SignVote(evidenceChainID, voteB)
vB := voteB.ToProto()
err = val.SignVote(evidenceChainID, vB)
voteB.Signature = vB.Signature
require.NoError(t, err) require.NoError(t, err)
voteC := makeVote(25, 0, 0, pubKey.Address(), firstBlockID) voteC := makeVote(25, 0, 0, pubKey.Address(), firstBlockID)
voteC.Timestamp.Add(1 * time.Second) voteC.Timestamp.Add(1 * time.Second)
err = val.SignVote(evidenceChainID, voteC)
vC := voteC.ToProto()
err = val.SignVote(evidenceChainID, vC)
voteC.Signature = vC.Signature
require.NoError(t, err) require.NoError(t, err)
ev := types.PotentialAmnesiaEvidence{ ev := types.PotentialAmnesiaEvidence{
VoteA: voteA, VoteA: voteA,


+ 12
- 0
libs/math/safemath.go View File

@ -7,6 +7,7 @@ import (
var ErrOverflowInt32 = errors.New("int32 overflow") var ErrOverflowInt32 = errors.New("int32 overflow")
var ErrOverflowUint8 = errors.New("uint8 overflow") var ErrOverflowUint8 = errors.New("uint8 overflow")
var ErrOverflowInt8 = errors.New("int8 overflow")
// SafeAddInt32 adds two int32 integers // SafeAddInt32 adds two int32 integers
// If there is an overflow this will panic // If there is an overflow this will panic
@ -51,3 +52,14 @@ func SafeConvertUint8(a int64) (uint8, error) {
} }
return uint8(a), nil return uint8(a), nil
} }
// SafeConvertInt8 takes an int64 and checks if it overflows
// If there is an overflow it returns an error
func SafeConvertInt8(a int64) (int8, error) {
if a > math.MaxInt8 {
return 0, ErrOverflowInt8
} else if a < math.MinInt8 {
return 0, ErrOverflowInt8
}
return int8(a), nil
}

+ 4
- 2
light/helpers_test.go View File

@ -108,13 +108,15 @@ func makeVote(header *types.Header, valset *types.ValidatorSet,
Type: tmproto.PrecommitType, Type: tmproto.PrecommitType,
BlockID: blockID, BlockID: blockID,
} }
v := vote.ToProto()
// Sign it // Sign it
signBytes := vote.SignBytes(header.ChainID)
// TODO Consider reworking makeVote API to return an error
signBytes := types.VoteSignBytes(header.ChainID, v)
sig, err := key.Sign(signBytes) sig, err := key.Sign(signBytes)
if err != nil { if err != nil {
panic(err) panic(err)
} }
vote.Signature = sig vote.Signature = sig
return vote return vote


+ 0
- 14
privval/codec.go View File

@ -1,14 +0,0 @@
package privval
import (
amino "github.com/tendermint/go-amino"
cryptoamino "github.com/tendermint/tendermint/crypto/encoding/amino"
)
var cdc = amino.NewCodec()
func init() {
cryptoamino.RegisterAmino(cdc)
RegisterRemoteSignerMsg(cdc)
}

+ 5
- 4
privval/errors.go View File

@ -1,6 +1,7 @@
package privval package privval
import ( import (
"errors"
"fmt" "fmt"
) )
@ -13,12 +14,12 @@ func (e EndpointTimeoutError) Temporary() bool { return true }
// Socket errors. // Socket errors.
var ( var (
ErrUnexpectedResponse = fmt.Errorf("received unexpected response")
ErrNoConnection = fmt.Errorf("endpoint is not connected")
ErrUnexpectedResponse = errors.New("received unexpected response")
ErrNoConnection = errors.New("endpoint is not connected")
ErrConnectionTimeout = EndpointTimeoutError{} ErrConnectionTimeout = EndpointTimeoutError{}
ErrReadTimeout = fmt.Errorf("endpoint read timed out")
ErrWriteTimeout = fmt.Errorf("endpoint write timed out")
ErrReadTimeout = errors.New("endpoint read timed out")
ErrWriteTimeout = errors.New("endpoint write timed out")
) )
// RemoteSignerError allows (remote) validators to include meaningful error descriptions in their reply. // RemoteSignerError allows (remote) validators to include meaningful error descriptions in their reply.


+ 18
- 19
privval/file.go View File

@ -7,6 +7,8 @@ import (
"io/ioutil" "io/ioutil"
"time" "time"
"github.com/gogo/protobuf/proto"
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/ed25519"
tmbytes "github.com/tendermint/tendermint/libs/bytes" tmbytes "github.com/tendermint/tendermint/libs/bytes"
@ -27,7 +29,7 @@ const (
) )
// A vote is either stepPrevote or stepPrecommit. // A vote is either stepPrevote or stepPrecommit.
func voteToStep(vote *types.Vote) int8 {
func voteToStep(vote *tmproto.Vote) int8 {
switch vote.Type { switch vote.Type {
case tmproto.PrevoteType: case tmproto.PrevoteType:
return stepPrevote return stepPrevote
@ -199,6 +201,7 @@ func loadFilePV(keyFilePath, stateFilePath string, loadState bool) *FilePV {
pvKey.filePath = keyFilePath pvKey.filePath = keyFilePath
pvState := FilePVLastSignState{} pvState := FilePVLastSignState{}
if loadState { if loadState {
stateJSONBytes, err := ioutil.ReadFile(stateFilePath) stateJSONBytes, err := ioutil.ReadFile(stateFilePath)
if err != nil { if err != nil {
@ -245,7 +248,7 @@ func (pv *FilePV) GetPubKey() (crypto.PubKey, error) {
// SignVote signs a canonical representation of the vote, along with the // SignVote signs a canonical representation of the vote, along with the
// chainID. Implements PrivValidator. // chainID. Implements PrivValidator.
func (pv *FilePV) SignVote(chainID string, vote *types.Vote) error {
func (pv *FilePV) SignVote(chainID string, vote *tmproto.Vote) error {
if err := pv.signVote(chainID, vote); err != nil { if err := pv.signVote(chainID, vote); err != nil {
return fmt.Errorf("error signing vote: %v", err) return fmt.Errorf("error signing vote: %v", err)
} }
@ -254,7 +257,7 @@ func (pv *FilePV) SignVote(chainID string, vote *types.Vote) error {
// SignProposal signs a canonical representation of the proposal, along with // SignProposal signs a canonical representation of the proposal, along with
// the chainID. Implements PrivValidator. // the chainID. Implements PrivValidator.
func (pv *FilePV) SignProposal(chainID string, proposal *types.Proposal) error {
func (pv *FilePV) SignProposal(chainID string, proposal *tmproto.Proposal) error {
if err := pv.signProposal(chainID, proposal); err != nil { if err := pv.signProposal(chainID, proposal); err != nil {
return fmt.Errorf("error signing proposal: %v", err) return fmt.Errorf("error signing proposal: %v", err)
} }
@ -295,7 +298,7 @@ func (pv *FilePV) String() string {
// signVote checks if the vote is good to sign and sets the vote signature. // signVote checks if the vote is good to sign and sets the vote signature.
// It may need to set the timestamp as well if the vote is otherwise the same as // It may need to set the timestamp as well if the vote is otherwise the same as
// a previously signed vote (ie. we crashed after signing but before the vote hit the WAL). // a previously signed vote (ie. we crashed after signing but before the vote hit the WAL).
func (pv *FilePV) signVote(chainID string, vote *types.Vote) error {
func (pv *FilePV) signVote(chainID string, vote *tmproto.Vote) error {
height, round, step := vote.Height, vote.Round, voteToStep(vote) height, round, step := vote.Height, vote.Round, voteToStep(vote)
lss := pv.LastSignState lss := pv.LastSignState
@ -305,7 +308,7 @@ func (pv *FilePV) signVote(chainID string, vote *types.Vote) error {
return err return err
} }
signBytes := vote.SignBytes(chainID)
signBytes := types.VoteSignBytes(chainID, vote)
// We might crash before writing to the wal, // We might crash before writing to the wal,
// causing us to try to re-sign for the same HRS. // causing us to try to re-sign for the same HRS.
@ -337,7 +340,7 @@ func (pv *FilePV) signVote(chainID string, vote *types.Vote) error {
// signProposal checks if the proposal is good to sign and sets the proposal signature. // signProposal checks if the proposal is good to sign and sets the proposal signature.
// It may need to set the timestamp as well if the proposal is otherwise the same as // It may need to set the timestamp as well if the proposal is otherwise the same as
// a previously signed proposal ie. we crashed after signing but before the proposal hit the WAL). // a previously signed proposal ie. we crashed after signing but before the proposal hit the WAL).
func (pv *FilePV) signProposal(chainID string, proposal *types.Proposal) error {
func (pv *FilePV) signProposal(chainID string, proposal *tmproto.Proposal) error {
height, round, step := proposal.Height, proposal.Round, stepPropose height, round, step := proposal.Height, proposal.Round, stepPropose
lss := pv.LastSignState lss := pv.LastSignState
@ -347,7 +350,7 @@ func (pv *FilePV) signProposal(chainID string, proposal *types.Proposal) error {
return err return err
} }
signBytes := proposal.SignBytes(chainID)
signBytes := types.ProposalSignBytes(chainID, proposal)
// We might crash before writing to the wal, // We might crash before writing to the wal,
// causing us to try to re-sign for the same HRS. // causing us to try to re-sign for the same HRS.
@ -393,11 +396,11 @@ func (pv *FilePV) saveSigned(height int64, round int32, step int8,
// returns the timestamp from the lastSignBytes. // returns the timestamp from the lastSignBytes.
// returns true if the only difference in the votes is their timestamp. // returns true if the only difference in the votes is their timestamp.
func checkVotesOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.Time, bool) { func checkVotesOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.Time, bool) {
var lastVote, newVote types.CanonicalVote
if err := cdc.UnmarshalBinaryLengthPrefixed(lastSignBytes, &lastVote); err != nil {
var lastVote, newVote tmproto.CanonicalVote
if err := proto.Unmarshal(lastSignBytes, &lastVote); err != nil {
panic(fmt.Sprintf("LastSignBytes cannot be unmarshalled into vote: %v", err)) panic(fmt.Sprintf("LastSignBytes cannot be unmarshalled into vote: %v", err))
} }
if err := cdc.UnmarshalBinaryLengthPrefixed(newSignBytes, &newVote); err != nil {
if err := proto.Unmarshal(newSignBytes, &newVote); err != nil {
panic(fmt.Sprintf("signBytes cannot be unmarshalled into vote: %v", err)) panic(fmt.Sprintf("signBytes cannot be unmarshalled into vote: %v", err))
} }
@ -407,20 +410,18 @@ func checkVotesOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.T
now := tmtime.Now() now := tmtime.Now()
lastVote.Timestamp = now lastVote.Timestamp = now
newVote.Timestamp = now newVote.Timestamp = now
lastVoteBytes, _ := tmjson.Marshal(lastVote)
newVoteBytes, _ := tmjson.Marshal(newVote)
return lastTime, bytes.Equal(newVoteBytes, lastVoteBytes)
return lastTime, proto.Equal(&newVote, &lastVote)
} }
// returns the timestamp from the lastSignBytes. // returns the timestamp from the lastSignBytes.
// returns true if the only difference in the proposals is their timestamp // returns true if the only difference in the proposals is their timestamp
func checkProposalsOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.Time, bool) { func checkProposalsOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.Time, bool) {
var lastProposal, newProposal types.CanonicalProposal
if err := cdc.UnmarshalBinaryLengthPrefixed(lastSignBytes, &lastProposal); err != nil {
var lastProposal, newProposal tmproto.CanonicalProposal
if err := proto.Unmarshal(lastSignBytes, &lastProposal); err != nil {
panic(fmt.Sprintf("LastSignBytes cannot be unmarshalled into proposal: %v", err)) panic(fmt.Sprintf("LastSignBytes cannot be unmarshalled into proposal: %v", err))
} }
if err := cdc.UnmarshalBinaryLengthPrefixed(newSignBytes, &newProposal); err != nil {
if err := proto.Unmarshal(newSignBytes, &newProposal); err != nil {
panic(fmt.Sprintf("signBytes cannot be unmarshalled into proposal: %v", err)) panic(fmt.Sprintf("signBytes cannot be unmarshalled into proposal: %v", err))
} }
@ -429,8 +430,6 @@ func checkProposalsOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (ti
now := tmtime.Now() now := tmtime.Now()
lastProposal.Timestamp = now lastProposal.Timestamp = now
newProposal.Timestamp = now newProposal.Timestamp = now
lastProposalBytes, _ := cdc.MarshalBinaryLengthPrefixed(lastProposal)
newProposalBytes, _ := cdc.MarshalBinaryLengthPrefixed(newProposal)
return lastTime, bytes.Equal(newProposalBytes, lastProposalBytes)
return lastTime, proto.Equal(&newProposal, &lastProposal)
} }

+ 38
- 31
privval/file_test.go View File

@ -52,10 +52,10 @@ func TestResetValidator(t *testing.T) {
// test vote // test vote
height, round := int64(10), int32(1) height, round := int64(10), int32(1)
voteType := byte(tmproto.PrevoteType)
voteType := tmproto.PrevoteType
blockID := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{}} blockID := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{}}
vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID) vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID)
err = privVal.SignVote("mychainid", vote)
err = privVal.SignVote("mychainid", vote.ToProto())
assert.NoError(t, err, "expected no error signing vote") assert.NoError(t, err, "expected no error signing vote")
// priv val after signing is not same as empty // priv val after signing is not same as empty
@ -121,8 +121,8 @@ func TestUnmarshalValidatorKey(t *testing.T) {
privKey := ed25519.GenPrivKey() privKey := ed25519.GenPrivKey()
pubKey := privKey.PubKey() pubKey := privKey.PubKey()
addr := pubKey.Address() addr := pubKey.Address()
pubBytes := []byte(pubKey.(ed25519.PubKey))
privBytes := []byte(privKey)
pubBytes := pubKey.Bytes()
privBytes := privKey.Bytes()
pubB64 := base64.StdEncoding.EncodeToString(pubBytes) pubB64 := base64.StdEncoding.EncodeToString(pubBytes)
privB64 := base64.StdEncoding.EncodeToString(privBytes) privB64 := base64.StdEncoding.EncodeToString(privBytes)
@ -167,15 +167,16 @@ func TestSignVote(t *testing.T) {
block2 := types.BlockID{Hash: []byte{3, 2, 1}, PartsHeader: types.PartSetHeader{}} block2 := types.BlockID{Hash: []byte{3, 2, 1}, PartsHeader: types.PartSetHeader{}}
height, round := int64(10), int32(1) height, round := int64(10), int32(1)
voteType := byte(tmproto.PrevoteType)
voteType := tmproto.PrevoteType
// sign a vote for first time // sign a vote for first time
vote := newVote(privVal.Key.Address, 0, height, round, voteType, block1) vote := newVote(privVal.Key.Address, 0, height, round, voteType, block1)
err = privVal.SignVote("mychainid", vote)
v := vote.ToProto()
err = privVal.SignVote("mychainid", v)
assert.NoError(err, "expected no error signing vote") assert.NoError(err, "expected no error signing vote")
// try to sign the same vote again; should be fine // try to sign the same vote again; should be fine
err = privVal.SignVote("mychainid", vote)
err = privVal.SignVote("mychainid", v)
assert.NoError(err, "expected no error on signing same vote") assert.NoError(err, "expected no error on signing same vote")
// now try some bad votes // now try some bad votes
@ -187,14 +188,15 @@ func TestSignVote(t *testing.T) {
} }
for _, c := range cases { for _, c := range cases {
err = privVal.SignVote("mychainid", c)
cpb := c.ToProto()
err = privVal.SignVote("mychainid", cpb)
assert.Error(err, "expected error on signing conflicting vote") assert.Error(err, "expected error on signing conflicting vote")
} }
// try signing a vote with a different time stamp // try signing a vote with a different time stamp
sig := vote.Signature sig := vote.Signature
vote.Timestamp = vote.Timestamp.Add(time.Duration(1000)) vote.Timestamp = vote.Timestamp.Add(time.Duration(1000))
err = privVal.SignVote("mychainid", vote)
err = privVal.SignVote("mychainid", v)
assert.NoError(err) assert.NoError(err)
assert.Equal(sig, vote.Signature) assert.Equal(sig, vote.Signature)
} }
@ -215,11 +217,12 @@ func TestSignProposal(t *testing.T) {
// sign a proposal for first time // sign a proposal for first time
proposal := newProposal(height, round, block1) proposal := newProposal(height, round, block1)
err = privVal.SignProposal("mychainid", proposal)
pbp := proposal.ToProto()
err = privVal.SignProposal("mychainid", pbp)
assert.NoError(err, "expected no error signing proposal") assert.NoError(err, "expected no error signing proposal")
// try to sign the same proposal again; should be fine // try to sign the same proposal again; should be fine
err = privVal.SignProposal("mychainid", proposal)
err = privVal.SignProposal("mychainid", pbp)
assert.NoError(err, "expected no error on signing same proposal") assert.NoError(err, "expected no error on signing same proposal")
// now try some bad Proposals // now try some bad Proposals
@ -231,14 +234,14 @@ func TestSignProposal(t *testing.T) {
} }
for _, c := range cases { for _, c := range cases {
err = privVal.SignProposal("mychainid", c)
err = privVal.SignProposal("mychainid", c.ToProto())
assert.Error(err, "expected error on signing conflicting proposal") assert.Error(err, "expected error on signing conflicting proposal")
} }
// try signing a proposal with a different time stamp // try signing a proposal with a different time stamp
sig := proposal.Signature sig := proposal.Signature
proposal.Timestamp = proposal.Timestamp.Add(time.Duration(1000)) proposal.Timestamp = proposal.Timestamp.Add(time.Duration(1000))
err = privVal.SignProposal("mychainid", proposal)
err = privVal.SignProposal("mychainid", pbp)
assert.NoError(err) assert.NoError(err)
assert.Equal(sig, proposal.Signature) assert.Equal(sig, proposal.Signature)
} }
@ -258,56 +261,60 @@ func TestDifferByTimestamp(t *testing.T) {
// test proposal // test proposal
{ {
proposal := newProposal(height, round, block1) proposal := newProposal(height, round, block1)
err := privVal.SignProposal(chainID, proposal)
pb := proposal.ToProto()
err := privVal.SignProposal(chainID, pb)
assert.NoError(t, err, "expected no error signing proposal") assert.NoError(t, err, "expected no error signing proposal")
signBytes := proposal.SignBytes(chainID)
signBytes := types.ProposalSignBytes(chainID, pb)
sig := proposal.Signature sig := proposal.Signature
timeStamp := proposal.Timestamp timeStamp := proposal.Timestamp
// manipulate the timestamp. should get changed back // manipulate the timestamp. should get changed back
proposal.Timestamp = proposal.Timestamp.Add(time.Millisecond)
pb.Timestamp = pb.Timestamp.Add(time.Millisecond)
var emptySig []byte var emptySig []byte
proposal.Signature = emptySig proposal.Signature = emptySig
err = privVal.SignProposal("mychainid", proposal)
err = privVal.SignProposal("mychainid", pb)
assert.NoError(t, err, "expected no error on signing same proposal") assert.NoError(t, err, "expected no error on signing same proposal")
assert.Equal(t, timeStamp, proposal.Timestamp)
assert.Equal(t, signBytes, proposal.SignBytes(chainID))
assert.Equal(t, timeStamp, pb.Timestamp)
assert.Equal(t, signBytes, types.ProposalSignBytes(chainID, pb))
assert.Equal(t, sig, proposal.Signature) assert.Equal(t, sig, proposal.Signature)
} }
// test vote // test vote
{ {
voteType := byte(tmproto.PrevoteType)
voteType := tmproto.PrevoteType
blockID := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{}} blockID := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{}}
vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID) vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID)
err := privVal.SignVote("mychainid", vote)
v := vote.ToProto()
err := privVal.SignVote("mychainid", v)
assert.NoError(t, err, "expected no error signing vote") assert.NoError(t, err, "expected no error signing vote")
signBytes := vote.SignBytes(chainID)
sig := vote.Signature
signBytes := types.VoteSignBytes(chainID, v)
sig := v.Signature
timeStamp := vote.Timestamp timeStamp := vote.Timestamp
// manipulate the timestamp. should get changed back // manipulate the timestamp. should get changed back
vote.Timestamp = vote.Timestamp.Add(time.Millisecond)
v.Timestamp = v.Timestamp.Add(time.Millisecond)
var emptySig []byte var emptySig []byte
vote.Signature = emptySig
err = privVal.SignVote("mychainid", vote)
v.Signature = emptySig
err = privVal.SignVote("mychainid", v)
assert.NoError(t, err, "expected no error on signing same vote") assert.NoError(t, err, "expected no error on signing same vote")
assert.Equal(t, timeStamp, vote.Timestamp)
assert.Equal(t, signBytes, vote.SignBytes(chainID))
assert.Equal(t, sig, vote.Signature)
assert.Equal(t, timeStamp, v.Timestamp)
assert.Equal(t, signBytes, types.VoteSignBytes(chainID, v))
assert.Equal(t, sig, v.Signature)
} }
} }
func newVote(addr types.Address, idx int32, height int64, round int32, typ byte, blockID types.BlockID) *types.Vote {
func newVote(addr types.Address, idx int32, height int64, round int32,
typ tmproto.SignedMsgType, blockID types.BlockID) *types.Vote {
return &types.Vote{ return &types.Vote{
ValidatorAddress: addr, ValidatorAddress: addr,
ValidatorIndex: idx, ValidatorIndex: idx,
Height: height, Height: height,
Round: round, Round: round,
Type: tmproto.SignedMsgType(typ),
Type: typ,
Timestamp: tmtime.Now(), Timestamp: tmtime.Now(),
BlockID: blockID, BlockID: blockID,
} }


+ 31
- 56
privval/messages.go View File

@ -1,65 +1,40 @@
package privval package privval
import ( import (
amino "github.com/tendermint/go-amino"
"fmt"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/types"
)
// SignerMessage is sent between Signer Clients and Servers.
type SignerMessage interface{}
func RegisterRemoteSignerMsg(cdc *amino.Codec) {
cdc.RegisterInterface((*SignerMessage)(nil), nil)
cdc.RegisterConcrete(&PubKeyRequest{}, "tendermint/remotesigner/PubKeyRequest", nil)
cdc.RegisterConcrete(&PubKeyResponse{}, "tendermint/remotesigner/PubKeyResponse", nil)
cdc.RegisterConcrete(&SignVoteRequest{}, "tendermint/remotesigner/SignVoteRequest", nil)
cdc.RegisterConcrete(&SignedVoteResponse{}, "tendermint/remotesigner/SignedVoteResponse", nil)
cdc.RegisterConcrete(&SignProposalRequest{}, "tendermint/remotesigner/SignProposalRequest", nil)
cdc.RegisterConcrete(&SignedProposalResponse{}, "tendermint/remotesigner/SignedProposalResponse", nil)
"github.com/gogo/protobuf/proto"
cdc.RegisterConcrete(&PingRequest{}, "tendermint/remotesigner/PingRequest", nil)
cdc.RegisterConcrete(&PingResponse{}, "tendermint/remotesigner/PingResponse", nil)
}
privvalproto "github.com/tendermint/tendermint/proto/privval"
)
// TODO: Add ChainIDRequest // TODO: Add ChainIDRequest
// PubKeyRequest requests the consensus public key from the remote signer.
type PubKeyRequest struct{}
// PubKeyResponse is a response message containing the public key.
type PubKeyResponse struct {
PubKey crypto.PubKey
Error *RemoteSignerError
}
// SignVoteRequest is a request to sign a vote
type SignVoteRequest struct {
Vote *types.Vote
}
// SignedVoteResponse is a response containing a signed vote or an error
type SignedVoteResponse struct {
Vote *types.Vote
Error *RemoteSignerError
}
// SignProposalRequest is a request to sign a proposal
type SignProposalRequest struct {
Proposal *types.Proposal
}
// SignedProposalResponse is response containing a signed proposal or an error
type SignedProposalResponse struct {
Proposal *types.Proposal
Error *RemoteSignerError
}
// PingRequest is a request to confirm that the connection is alive.
type PingRequest struct {
}
// PingResponse is a response to confirm that the connection is alive.
type PingResponse struct {
func mustWrapMsg(pb proto.Message) privvalproto.Message {
msg := privvalproto.Message{}
switch pb := pb.(type) {
case *privvalproto.Message:
msg = *pb
case *privvalproto.PubKeyRequest:
msg.Sum = &privvalproto.Message_PubKeyRequest{PubKeyRequest: pb}
case *privvalproto.PubKeyResponse:
msg.Sum = &privvalproto.Message_PubKeyResponse{PubKeyResponse: pb}
case *privvalproto.SignVoteRequest:
msg.Sum = &privvalproto.Message_SignVoteRequest{SignVoteRequest: pb}
case *privvalproto.SignedVoteResponse:
msg.Sum = &privvalproto.Message_SignedVoteResponse{SignedVoteResponse: pb}
case *privvalproto.SignedProposalResponse:
msg.Sum = &privvalproto.Message_SignedProposalResponse{SignedProposalResponse: pb}
case *privvalproto.SignProposalRequest:
msg.Sum = &privvalproto.Message_SignProposalRequest{SignProposalRequest: pb}
case *privvalproto.PingRequest:
msg.Sum = &privvalproto.Message_PingRequest{}
case *privvalproto.PingResponse:
msg.Sum = &privvalproto.Message_PingResponse{}
default:
panic(fmt.Errorf("unknown message type %T", msg))
}
return msg
} }

+ 3
- 2
privval/retry_signer_client.go View File

@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
tmproto "github.com/tendermint/tendermint/proto/types"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
) )
@ -58,7 +59,7 @@ func (sc *RetrySignerClient) GetPubKey() (crypto.PubKey, error) {
return nil, fmt.Errorf("exhausted all attempts to get pubkey: %w", err) return nil, fmt.Errorf("exhausted all attempts to get pubkey: %w", err)
} }
func (sc *RetrySignerClient) SignVote(chainID string, vote *types.Vote) error {
func (sc *RetrySignerClient) SignVote(chainID string, vote *tmproto.Vote) error {
var err error var err error
for i := 0; i < sc.retries || sc.retries == 0; i++ { for i := 0; i < sc.retries || sc.retries == 0; i++ {
err = sc.next.SignVote(chainID, vote) err = sc.next.SignVote(chainID, vote)
@ -70,7 +71,7 @@ func (sc *RetrySignerClient) SignVote(chainID string, vote *types.Vote) error {
return fmt.Errorf("exhausted all attempts to sign vote: %w", err) return fmt.Errorf("exhausted all attempts to sign vote: %w", err)
} }
func (sc *RetrySignerClient) SignProposal(chainID string, proposal *types.Proposal) error {
func (sc *RetrySignerClient) SignProposal(chainID string, proposal *tmproto.Proposal) error {
var err error var err error
for i := 0; i < sc.retries || sc.retries == 0; i++ { for i := 0; i < sc.retries || sc.retries == 0; i++ {
err = sc.next.SignProposal(chainID, proposal) err = sc.next.SignProposal(chainID, proposal)


+ 31
- 18
privval/signer_client.go View File

@ -1,10 +1,14 @@
package privval package privval
import ( import (
"errors"
"fmt" "fmt"
"time" "time"
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
cryptoenc "github.com/tendermint/tendermint/crypto/encoding"
privvalproto "github.com/tendermint/tendermint/proto/privval"
tmproto "github.com/tendermint/tendermint/proto/types"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
) )
@ -48,15 +52,15 @@ func (sc *SignerClient) WaitForConnection(maxWait time.Duration) error {
// Ping sends a ping request to the remote signer // Ping sends a ping request to the remote signer
func (sc *SignerClient) Ping() error { func (sc *SignerClient) Ping() error {
response, err := sc.endpoint.SendRequest(&PingRequest{})
response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.PingRequest{}))
if err != nil { if err != nil {
sc.endpoint.Logger.Error("SignerClient::Ping", "err", err) sc.endpoint.Logger.Error("SignerClient::Ping", "err", err)
return nil return nil
} }
_, ok := response.(*PingResponse)
if !ok {
pb := response.GetPingResponse()
if pb == nil {
sc.endpoint.Logger.Error("SignerClient::Ping", "err", "response != PingResponse") sc.endpoint.Logger.Error("SignerClient::Ping", "err", "response != PingResponse")
return err return err
} }
@ -67,64 +71,73 @@ func (sc *SignerClient) Ping() error {
// GetPubKey retrieves a public key from a remote signer // GetPubKey retrieves a public key from a remote signer
// returns an error if client is not able to provide the key // returns an error if client is not able to provide the key
func (sc *SignerClient) GetPubKey() (crypto.PubKey, error) { func (sc *SignerClient) GetPubKey() (crypto.PubKey, error) {
response, err := sc.endpoint.SendRequest(&PubKeyRequest{})
response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.PubKeyRequest{}))
if err != nil { if err != nil {
sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", err) sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", err)
return nil, fmt.Errorf("send: %w", err) return nil, fmt.Errorf("send: %w", err)
} }
pubKeyResp, ok := response.(*PubKeyResponse)
if !ok {
pubKeyResp := response.GetPubKeyResponse()
if pubKeyResp == nil {
sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", "response != PubKeyResponse") sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", "response != PubKeyResponse")
return nil, fmt.Errorf("unexpected response type %T", response) return nil, fmt.Errorf("unexpected response type %T", response)
} }
if pubKeyResp.Error != nil { if pubKeyResp.Error != nil {
sc.endpoint.Logger.Error("failed to get private validator's public key", "err", pubKeyResp.Error) sc.endpoint.Logger.Error("failed to get private validator's public key", "err", pubKeyResp.Error)
return nil, fmt.Errorf("remote error: %w", pubKeyResp.Error)
return nil, fmt.Errorf("remote error: %w", errors.New(pubKeyResp.Error.Description))
} }
return pubKeyResp.PubKey, nil
pk, err := cryptoenc.PubKeyFromProto(*pubKeyResp.PubKey)
if err != nil {
return nil, err
}
return pk, nil
} }
// SignVote requests a remote signer to sign a vote // SignVote requests a remote signer to sign a vote
func (sc *SignerClient) SignVote(chainID string, vote *types.Vote) error {
response, err := sc.endpoint.SendRequest(&SignVoteRequest{Vote: vote})
func (sc *SignerClient) SignVote(chainID string, vote *tmproto.Vote) error {
response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.SignVoteRequest{Vote: vote}))
if err != nil { if err != nil {
sc.endpoint.Logger.Error("SignerClient::SignVote", "err", err) sc.endpoint.Logger.Error("SignerClient::SignVote", "err", err)
return err return err
} }
resp, ok := response.(*SignedVoteResponse)
if !ok {
resp := response.GetSignedVoteResponse()
if resp == nil {
sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", "response != SignedVoteResponse") sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", "response != SignedVoteResponse")
return ErrUnexpectedResponse return ErrUnexpectedResponse
} }
if resp.Error != nil { if resp.Error != nil {
return resp.Error
return &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description}
} }
*vote = *resp.Vote *vote = *resp.Vote
return nil return nil
} }
// SignProposal requests a remote signer to sign a proposal // SignProposal requests a remote signer to sign a proposal
func (sc *SignerClient) SignProposal(chainID string, proposal *types.Proposal) error {
response, err := sc.endpoint.SendRequest(&SignProposalRequest{Proposal: proposal})
func (sc *SignerClient) SignProposal(chainID string, proposal *tmproto.Proposal) error {
response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.SignProposalRequest{Proposal: *proposal}))
if err != nil { if err != nil {
sc.endpoint.Logger.Error("SignerClient::SignProposal", "err", err) sc.endpoint.Logger.Error("SignerClient::SignProposal", "err", err)
return err return err
} }
resp, ok := response.(*SignedProposalResponse)
if !ok {
resp := response.GetSignedProposalResponse()
if resp == nil {
sc.endpoint.Logger.Error("SignerClient::SignProposal", "err", "response != SignedProposalResponse") sc.endpoint.Logger.Error("SignerClient::SignProposal", "err", "response != SignedProposalResponse")
return ErrUnexpectedResponse return ErrUnexpectedResponse
} }
if resp.Error != nil { if resp.Error != nil {
return resp.Error
return &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description}
} }
*proposal = *resp.Proposal *proposal = *resp.Proposal
return nil return nil


+ 135
- 41
privval/signer_client_test.go View File

@ -8,7 +8,10 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/tmhash"
tmrand "github.com/tendermint/tendermint/libs/rand" tmrand "github.com/tendermint/tendermint/libs/rand"
privvalproto "github.com/tendermint/tendermint/proto/privval"
tmproto "github.com/tendermint/tendermint/proto/types" tmproto "github.com/tendermint/tendermint/proto/types"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
) )
@ -95,14 +98,29 @@ func TestSignerGetPubKey(t *testing.T) {
func TestSignerProposal(t *testing.T) { func TestSignerProposal(t *testing.T) {
for _, tc := range getSignerTestCases(t) { for _, tc := range getSignerTestCases(t) {
ts := time.Now() ts := time.Now()
want := &types.Proposal{Timestamp: ts}
have := &types.Proposal{Timestamp: ts}
hash := tmrand.Bytes(tmhash.Size)
have := &types.Proposal{
Type: tmproto.ProposalType,
Height: 1,
Round: 2,
POLRound: 2,
BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}},
Timestamp: ts,
}
want := &types.Proposal{
Type: tmproto.ProposalType,
Height: 1,
Round: 2,
POLRound: 2,
BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}},
Timestamp: ts,
}
defer tc.signerServer.Stop() defer tc.signerServer.Stop()
defer tc.signerClient.Close() defer tc.signerClient.Close()
require.NoError(t, tc.mockPV.SignProposal(tc.chainID, want))
require.NoError(t, tc.signerClient.SignProposal(tc.chainID, have))
require.NoError(t, tc.mockPV.SignProposal(tc.chainID, want.ToProto()))
require.NoError(t, tc.signerClient.SignProposal(tc.chainID, have.ToProto()))
assert.Equal(t, want.Signature, have.Signature) assert.Equal(t, want.Signature, have.Signature)
} }
@ -111,14 +129,33 @@ func TestSignerProposal(t *testing.T) {
func TestSignerVote(t *testing.T) { func TestSignerVote(t *testing.T) {
for _, tc := range getSignerTestCases(t) { for _, tc := range getSignerTestCases(t) {
ts := time.Now() ts := time.Now()
want := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType}
have := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType}
hash := tmrand.Bytes(tmhash.Size)
valAddr := tmrand.Bytes(crypto.AddressSize)
want := &types.Vote{
Type: tmproto.PrecommitType,
Height: 1,
Round: 2,
BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}},
Timestamp: ts,
ValidatorAddress: valAddr,
ValidatorIndex: 1,
}
have := &types.Vote{
Type: tmproto.PrecommitType,
Height: 1,
Round: 2,
BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}},
Timestamp: ts,
ValidatorAddress: valAddr,
ValidatorIndex: 1,
}
defer tc.signerServer.Stop() defer tc.signerServer.Stop()
defer tc.signerClient.Close() defer tc.signerClient.Close()
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
require.NoError(t, tc.signerClient.SignVote(tc.chainID, have))
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto()))
require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto()))
assert.Equal(t, want.Signature, have.Signature) assert.Equal(t, want.Signature, have.Signature)
} }
@ -127,16 +164,35 @@ func TestSignerVote(t *testing.T) {
func TestSignerVoteResetDeadline(t *testing.T) { func TestSignerVoteResetDeadline(t *testing.T) {
for _, tc := range getSignerTestCases(t) { for _, tc := range getSignerTestCases(t) {
ts := time.Now() ts := time.Now()
want := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType}
have := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType}
hash := tmrand.Bytes(tmhash.Size)
valAddr := tmrand.Bytes(crypto.AddressSize)
want := &types.Vote{
Type: tmproto.PrecommitType,
Height: 1,
Round: 2,
BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}},
Timestamp: ts,
ValidatorAddress: valAddr,
ValidatorIndex: 1,
}
have := &types.Vote{
Type: tmproto.PrecommitType,
Height: 1,
Round: 2,
BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}},
Timestamp: ts,
ValidatorAddress: valAddr,
ValidatorIndex: 1,
}
defer tc.signerServer.Stop() defer tc.signerServer.Stop()
defer tc.signerClient.Close() defer tc.signerClient.Close()
time.Sleep(testTimeoutReadWrite2o3) time.Sleep(testTimeoutReadWrite2o3)
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
require.NoError(t, tc.signerClient.SignVote(tc.chainID, have))
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto()))
require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto()))
assert.Equal(t, want.Signature, have.Signature) assert.Equal(t, want.Signature, have.Signature)
// TODO(jleni): Clarify what is actually being tested // TODO(jleni): Clarify what is actually being tested
@ -144,8 +200,8 @@ func TestSignerVoteResetDeadline(t *testing.T) {
// This would exceed the deadline if it was not extended by the previous message // This would exceed the deadline if it was not extended by the previous message
time.Sleep(testTimeoutReadWrite2o3) time.Sleep(testTimeoutReadWrite2o3)
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
require.NoError(t, tc.signerClient.SignVote(tc.chainID, have))
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto()))
require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto()))
assert.Equal(t, want.Signature, have.Signature) assert.Equal(t, want.Signature, have.Signature)
} }
} }
@ -153,8 +209,27 @@ func TestSignerVoteResetDeadline(t *testing.T) {
func TestSignerVoteKeepAlive(t *testing.T) { func TestSignerVoteKeepAlive(t *testing.T) {
for _, tc := range getSignerTestCases(t) { for _, tc := range getSignerTestCases(t) {
ts := time.Now() ts := time.Now()
want := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType}
have := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType}
hash := tmrand.Bytes(tmhash.Size)
valAddr := tmrand.Bytes(crypto.AddressSize)
want := &types.Vote{
Type: tmproto.PrecommitType,
Height: 1,
Round: 2,
BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}},
Timestamp: ts,
ValidatorAddress: valAddr,
ValidatorIndex: 1,
}
have := &types.Vote{
Type: tmproto.PrecommitType,
Height: 1,
Round: 2,
BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}},
Timestamp: ts,
ValidatorAddress: valAddr,
ValidatorIndex: 1,
}
defer tc.signerServer.Stop() defer tc.signerServer.Stop()
defer tc.signerClient.Close() defer tc.signerClient.Close()
@ -168,8 +243,8 @@ func TestSignerVoteKeepAlive(t *testing.T) {
time.Sleep(testTimeoutReadWrite * 3) time.Sleep(testTimeoutReadWrite * 3)
tc.signerServer.Logger.Debug("TEST: Forced Wait DONE---------------------------------------------") tc.signerServer.Logger.Debug("TEST: Forced Wait DONE---------------------------------------------")
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
require.NoError(t, tc.signerClient.SignVote(tc.chainID, have))
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto()))
require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto()))
assert.Equal(t, want.Signature, have.Signature) assert.Equal(t, want.Signature, have.Signature)
} }
@ -185,14 +260,24 @@ func TestSignerSignProposalErrors(t *testing.T) {
defer tc.signerClient.Close() defer tc.signerClient.Close()
ts := time.Now() ts := time.Now()
proposal := &types.Proposal{Timestamp: ts}
err := tc.signerClient.SignProposal(tc.chainID, proposal)
hash := tmrand.Bytes(tmhash.Size)
proposal := &types.Proposal{
Type: tmproto.ProposalType,
Height: 1,
Round: 2,
POLRound: 2,
BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}},
Timestamp: ts,
Signature: []byte("signature"),
}
err := tc.signerClient.SignProposal(tc.chainID, proposal.ToProto())
require.Equal(t, err.(*RemoteSignerError).Description, types.ErroringMockPVErr.Error()) require.Equal(t, err.(*RemoteSignerError).Description, types.ErroringMockPVErr.Error())
err = tc.mockPV.SignProposal(tc.chainID, proposal)
err = tc.mockPV.SignProposal(tc.chainID, proposal.ToProto())
require.Error(t, err) require.Error(t, err)
err = tc.signerClient.SignProposal(tc.chainID, proposal)
err = tc.signerClient.SignProposal(tc.chainID, proposal.ToProto())
require.Error(t, err) require.Error(t, err)
} }
} }
@ -200,7 +285,18 @@ func TestSignerSignProposalErrors(t *testing.T) {
func TestSignerSignVoteErrors(t *testing.T) { func TestSignerSignVoteErrors(t *testing.T) {
for _, tc := range getSignerTestCases(t) { for _, tc := range getSignerTestCases(t) {
ts := time.Now() ts := time.Now()
vote := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType}
hash := tmrand.Bytes(tmhash.Size)
valAddr := tmrand.Bytes(crypto.AddressSize)
vote := &types.Vote{
Type: tmproto.PrecommitType,
Height: 1,
Round: 2,
BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}},
Timestamp: ts,
ValidatorAddress: valAddr,
ValidatorIndex: 1,
Signature: []byte("signature"),
}
// Replace signer service privval with one that always fails // Replace signer service privval with one that always fails
tc.signerServer.privVal = types.NewErroringMockPV() tc.signerServer.privVal = types.NewErroringMockPV()
@ -209,34 +305,32 @@ func TestSignerSignVoteErrors(t *testing.T) {
defer tc.signerServer.Stop() defer tc.signerServer.Stop()
defer tc.signerClient.Close() defer tc.signerClient.Close()
err := tc.signerClient.SignVote(tc.chainID, vote)
err := tc.signerClient.SignVote(tc.chainID, vote.ToProto())
require.Equal(t, err.(*RemoteSignerError).Description, types.ErroringMockPVErr.Error()) require.Equal(t, err.(*RemoteSignerError).Description, types.ErroringMockPVErr.Error())
err = tc.mockPV.SignVote(tc.chainID, vote)
err = tc.mockPV.SignVote(tc.chainID, vote.ToProto())
require.Error(t, err) require.Error(t, err)
err = tc.signerClient.SignVote(tc.chainID, vote)
err = tc.signerClient.SignVote(tc.chainID, vote.ToProto())
require.Error(t, err) require.Error(t, err)
} }
} }
func brokenHandler(privVal types.PrivValidator, request SignerMessage, chainID string) (SignerMessage, error) {
var res SignerMessage
func brokenHandler(privVal types.PrivValidator, request privvalproto.Message,
chainID string) (privvalproto.Message, error) {
var res privvalproto.Message
var err error var err error
switch r := request.(type) {
switch r := request.Sum.(type) {
// This is broken and will answer most requests with a pubkey response // This is broken and will answer most requests with a pubkey response
case *PubKeyRequest:
res = &PubKeyResponse{nil, nil}
case *SignVoteRequest:
res = &PubKeyResponse{nil, nil}
case *SignProposalRequest:
res = &PubKeyResponse{nil, nil}
case *PingRequest:
err, res = nil, &PingResponse{}
case *privvalproto.Message_PubKeyRequest:
res = mustWrapMsg(&privvalproto.PubKeyResponse{PubKey: nil, Error: nil})
case *privvalproto.Message_SignVoteRequest:
res = mustWrapMsg(&privvalproto.PubKeyResponse{PubKey: nil, Error: nil})
case *privvalproto.Message_SignProposalRequest:
res = mustWrapMsg(&privvalproto.PubKeyResponse{PubKey: nil, Error: nil})
case *privvalproto.Message_PingRequest:
err, res = nil, mustWrapMsg(&privvalproto.PingResponse{})
default: default:
err = fmt.Errorf("unknown msg: %v", r) err = fmt.Errorf("unknown msg: %v", r)
} }
@ -257,7 +351,7 @@ func TestSignerUnexpectedResponse(t *testing.T) {
ts := time.Now() ts := time.Now()
want := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType} want := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType}
e := tc.signerClient.SignVote(tc.chainID, want)
e := tc.signerClient.SignVote(tc.chainID, want.ToProto())
assert.EqualError(t, e, "received unexpected response") assert.EqualError(t, e, "received unexpected response")
} }
} }

+ 11
- 7
privval/signer_endpoint.go View File

@ -6,7 +6,9 @@ import (
"sync" "sync"
"time" "time"
"github.com/tendermint/tendermint/libs/protoio"
"github.com/tendermint/tendermint/libs/service" "github.com/tendermint/tendermint/libs/service"
privvalproto "github.com/tendermint/tendermint/proto/privval"
) )
const ( const (
@ -78,14 +80,13 @@ func (se *signerEndpoint) DropConnection() {
} }
// ReadMessage reads a message from the endpoint // ReadMessage reads a message from the endpoint
func (se *signerEndpoint) ReadMessage() (msg SignerMessage, err error) {
func (se *signerEndpoint) ReadMessage() (msg privvalproto.Message, err error) {
se.connMtx.Lock() se.connMtx.Lock()
defer se.connMtx.Unlock() defer se.connMtx.Unlock()
if !se.isConnected() { if !se.isConnected() {
return nil, fmt.Errorf("endpoint is not connected")
return msg, fmt.Errorf("endpoint is not connected: %w", ErrNoConnection)
} }
// Reset read deadline // Reset read deadline
deadline := time.Now().Add(se.timeoutReadWrite) deadline := time.Now().Add(se.timeoutReadWrite)
@ -93,15 +94,16 @@ func (se *signerEndpoint) ReadMessage() (msg SignerMessage, err error) {
if err != nil { if err != nil {
return return
} }
const maxRemoteSignerMsgSize = 1024 * 10 const maxRemoteSignerMsgSize = 1024 * 10
_, err = cdc.UnmarshalBinaryLengthPrefixedReader(se.conn, &msg, maxRemoteSignerMsgSize)
protoReader := protoio.NewDelimitedReader(se.conn, maxRemoteSignerMsgSize)
err = protoReader.ReadMsg(&msg)
if _, ok := err.(timeoutError); ok { if _, ok := err.(timeoutError); ok {
if err != nil { if err != nil {
err = fmt.Errorf("%v: %w", err, ErrReadTimeout) err = fmt.Errorf("%v: %w", err, ErrReadTimeout)
} else { } else {
err = fmt.Errorf("empty error: %w", ErrReadTimeout) err = fmt.Errorf("empty error: %w", ErrReadTimeout)
} }
se.Logger.Debug("Dropping [read]", "obj", se) se.Logger.Debug("Dropping [read]", "obj", se)
se.dropConnection() se.dropConnection()
} }
@ -110,7 +112,7 @@ func (se *signerEndpoint) ReadMessage() (msg SignerMessage, err error) {
} }
// WriteMessage writes a message from the endpoint // WriteMessage writes a message from the endpoint
func (se *signerEndpoint) WriteMessage(msg SignerMessage) (err error) {
func (se *signerEndpoint) WriteMessage(msg privvalproto.Message) (err error) {
se.connMtx.Lock() se.connMtx.Lock()
defer se.connMtx.Unlock() defer se.connMtx.Unlock()
@ -118,6 +120,8 @@ func (se *signerEndpoint) WriteMessage(msg SignerMessage) (err error) {
return fmt.Errorf("endpoint is not connected: %w", ErrNoConnection) return fmt.Errorf("endpoint is not connected: %w", ErrNoConnection)
} }
protoWriter := protoio.NewDelimitedWriter(se.conn)
// Reset read deadline // Reset read deadline
deadline := time.Now().Add(se.timeoutReadWrite) deadline := time.Now().Add(se.timeoutReadWrite)
err = se.conn.SetWriteDeadline(deadline) err = se.conn.SetWriteDeadline(deadline)
@ -125,7 +129,7 @@ func (se *signerEndpoint) WriteMessage(msg SignerMessage) (err error) {
return return
} }
_, err = cdc.MarshalBinaryLengthPrefixedWriter(se.conn, msg)
_, err = protoWriter.WriteMsg(&msg)
if _, ok := err.(timeoutError); ok { if _, ok := err.(timeoutError); ok {
if err != nil { if err != nil {
err = fmt.Errorf("%v: %w", err, ErrWriteTimeout) err = fmt.Errorf("%v: %w", err, ErrWriteTimeout)


+ 4
- 3
privval/signer_listener_endpoint.go View File

@ -8,6 +8,7 @@ import (
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/libs/service" "github.com/tendermint/tendermint/libs/service"
privvalproto "github.com/tendermint/tendermint/proto/privval"
) )
// SignerValidatorEndpointOption sets an optional parameter on the SocketVal. // SignerValidatorEndpointOption sets an optional parameter on the SocketVal.
@ -83,7 +84,7 @@ func (sl *SignerListenerEndpoint) WaitForConnection(maxWait time.Duration) error
} }
// SendRequest ensures there is a connection, sends a request and waits for a response // SendRequest ensures there is a connection, sends a request and waits for a response
func (sl *SignerListenerEndpoint) SendRequest(request SignerMessage) (SignerMessage, error) {
func (sl *SignerListenerEndpoint) SendRequest(request privvalproto.Message) (*privvalproto.Message, error) {
sl.instanceMtx.Lock() sl.instanceMtx.Lock()
defer sl.instanceMtx.Unlock() defer sl.instanceMtx.Unlock()
@ -102,7 +103,7 @@ func (sl *SignerListenerEndpoint) SendRequest(request SignerMessage) (SignerMess
return nil, err return nil, err
} }
return res, nil
return &res, nil
} }
func (sl *SignerListenerEndpoint) ensureConnection(maxWait time.Duration) error { func (sl *SignerListenerEndpoint) ensureConnection(maxWait time.Duration) error {
@ -185,7 +186,7 @@ func (sl *SignerListenerEndpoint) pingLoop() {
select { select {
case <-sl.pingTimer.C: case <-sl.pingTimer.C:
{ {
_, err := sl.SendRequest(&PingRequest{})
_, err := sl.SendRequest(mustWrapMsg(&privvalproto.PingRequest{}))
if err != nil { if err != nil {
sl.Logger.Error("SignerListener: Ping timeout") sl.Logger.Error("SignerListener: Ping timeout")
sl.triggerReconnect() sl.triggerReconnect()


+ 34
- 19
privval/signer_requestHandler.go View File

@ -4,45 +4,60 @@ import (
"fmt" "fmt"
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
cryptoenc "github.com/tendermint/tendermint/crypto/encoding"
privvalproto "github.com/tendermint/tendermint/proto/privval"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
) )
func DefaultValidationRequestHandler( func DefaultValidationRequestHandler(
privVal types.PrivValidator, privVal types.PrivValidator,
req SignerMessage,
req privvalproto.Message,
chainID string, chainID string,
) (SignerMessage, error) {
var res SignerMessage
var err error
) (privvalproto.Message, error) {
var (
res privvalproto.Message
err error
)
switch r := req.(type) {
case *PubKeyRequest:
switch r := req.Sum.(type) {
case *privvalproto.Message_PubKeyRequest:
var pubKey crypto.PubKey var pubKey crypto.PubKey
pubKey, err = privVal.GetPubKey() pubKey, err = privVal.GetPubKey()
pk, err := cryptoenc.PubKeyToProto(pubKey)
if err != nil { if err != nil {
res = &PubKeyResponse{nil, &RemoteSignerError{0, err.Error()}}
} else {
res = &PubKeyResponse{pubKey, nil}
return res, err
} }
case *SignVoteRequest:
err = privVal.SignVote(chainID, r.Vote)
if err != nil { if err != nil {
res = &SignedVoteResponse{nil, &RemoteSignerError{0, err.Error()}}
res = mustWrapMsg(&privvalproto.PubKeyResponse{
PubKey: nil, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}})
} else { } else {
res = &SignedVoteResponse{r.Vote, nil}
res = mustWrapMsg(&privvalproto.PubKeyResponse{PubKey: &pk, Error: nil})
} }
case *SignProposalRequest:
err = privVal.SignProposal(chainID, r.Proposal)
case *privvalproto.Message_SignVoteRequest:
vote := r.SignVoteRequest.Vote
err = privVal.SignVote(chainID, vote)
if err != nil { if err != nil {
res = &SignedProposalResponse{nil, &RemoteSignerError{0, err.Error()}}
res = mustWrapMsg(&privvalproto.SignedVoteResponse{
Vote: nil, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}})
} else { } else {
res = &SignedProposalResponse{r.Proposal, nil}
res = mustWrapMsg(&privvalproto.SignedVoteResponse{Vote: vote, Error: nil})
} }
case *PingRequest:
err, res = nil, &PingResponse{}
case *privvalproto.Message_SignProposalRequest:
proposal := r.SignProposalRequest.Proposal
err = privVal.SignProposal(chainID, &proposal)
if err != nil {
res = mustWrapMsg(&privvalproto.SignedProposalResponse{
Proposal: nil, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}})
} else {
res = mustWrapMsg(&privvalproto.SignedProposalResponse{Proposal: &proposal, Error: nil})
}
case *privvalproto.Message_PingRequest:
err, res = nil, mustWrapMsg(&privvalproto.PingResponse{})
default: default:
err = fmt.Errorf("unknown msg: %v", r) err = fmt.Errorf("unknown msg: %v", r)


+ 7
- 8
privval/signer_server.go View File

@ -5,14 +5,15 @@ import (
"sync" "sync"
"github.com/tendermint/tendermint/libs/service" "github.com/tendermint/tendermint/libs/service"
privvalproto "github.com/tendermint/tendermint/proto/privval"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
) )
// ValidationRequestHandlerFunc handles different remoteSigner requests // ValidationRequestHandlerFunc handles different remoteSigner requests
type ValidationRequestHandlerFunc func( type ValidationRequestHandlerFunc func(
privVal types.PrivValidator, privVal types.PrivValidator,
requestMessage SignerMessage,
chainID string) (SignerMessage, error)
requestMessage privvalproto.Message,
chainID string) (privvalproto.Message, error)
type SignerServer struct { type SignerServer struct {
service.BaseService service.BaseService
@ -70,7 +71,7 @@ func (ss *SignerServer) servicePendingRequest() {
return return
} }
var res SignerMessage
var res privvalproto.Message
{ {
// limit the scope of the lock // limit the scope of the lock
ss.handlerMtx.Lock() ss.handlerMtx.Lock()
@ -82,11 +83,9 @@ func (ss *SignerServer) servicePendingRequest() {
} }
} }
if res != nil {
err = ss.endpoint.WriteMessage(res)
if err != nil {
ss.Logger.Error("SignerServer: writeMessage", "err", err)
}
err = ss.endpoint.WriteMessage(res)
if err != nil {
ss.Logger.Error("SignerServer: writeMessage", "err", err)
} }
} }


+ 1315
- 468
proto/privval/msgs.pb.go
File diff suppressed because it is too large
View File


+ 18
- 5
proto/privval/msgs.proto View File

@ -17,18 +17,18 @@ message PubKeyRequest {}
// PubKeyResponse is a response message containing the public key. // PubKeyResponse is a response message containing the public key.
message PubKeyResponse { message PubKeyResponse {
tendermint.proto.crypto.keys.PublicKey pub_key = 1 [(gogoproto.nullable) = false];
tendermint.proto.crypto.keys.PublicKey pub_key = 1;
RemoteSignerError error = 2; RemoteSignerError error = 2;
} }
// SignVoteRequest is a request to sign a vote // SignVoteRequest is a request to sign a vote
message SignVoteRequest { message SignVoteRequest {
tendermint.proto.types.Vote vote = 1 [(gogoproto.nullable) = false];
tendermint.proto.types.Vote vote = 1;
} }
// SignedVoteResponse is a response containing a signed vote or an error // SignedVoteResponse is a response containing a signed vote or an error
message SignVoteResponse {
tendermint.proto.types.Vote vote = 1 [(gogoproto.nullable) = false];
message SignedVoteResponse {
tendermint.proto.types.Vote vote = 1;
RemoteSignerError error = 2; RemoteSignerError error = 2;
} }
@ -39,7 +39,7 @@ message SignProposalRequest {
// SignedProposalResponse is response containing a signed proposal or an error // SignedProposalResponse is response containing a signed proposal or an error
message SignedProposalResponse { message SignedProposalResponse {
tendermint.proto.types.Proposal proposal = 1 [(gogoproto.nullable) = false];
tendermint.proto.types.Proposal proposal = 1;
RemoteSignerError error = 2; RemoteSignerError error = 2;
} }
@ -48,3 +48,16 @@ message PingRequest {}
// PingResponse is a response to confirm that the connection is alive. // PingResponse is a response to confirm that the connection is alive.
message PingResponse {} message PingResponse {}
message Message {
oneof sum {
PubKeyRequest pub_key_request = 1;
PubKeyResponse pub_key_response = 2;
SignVoteRequest sign_vote_request = 3;
SignedVoteResponse signed_vote_response = 4;
SignProposalRequest sign_proposal_request = 5;
SignedProposalResponse signed_proposal_response = 6;
PingRequest ping_request = 7;
PingResponse ping_response = 8;
}
}

+ 73
- 29
proto/privval/types.pb.go View File

@ -24,6 +24,43 @@ var _ = math.Inf
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type Errors int32
const (
Errors_ERRORS_UNKNOWN Errors = 0
Errors_ERRORS_UNEXPECTED_RESPONSE Errors = 1
Errors_ERRORS_NO_CONNECTION Errors = 2
Errors_ERRORS_CONNECTION_TIMEOUT Errors = 3
Errors_ERRORS_READ_TIMEOUT Errors = 4
Errors_ERRORS_WRITE_TIMEOUT Errors = 5
)
var Errors_name = map[int32]string{
0: "ERRORS_UNKNOWN",
1: "ERRORS_UNEXPECTED_RESPONSE",
2: "ERRORS_NO_CONNECTION",
3: "ERRORS_CONNECTION_TIMEOUT",
4: "ERRORS_READ_TIMEOUT",
5: "ERRORS_WRITE_TIMEOUT",
}
var Errors_value = map[string]int32{
"ERRORS_UNKNOWN": 0,
"ERRORS_UNEXPECTED_RESPONSE": 1,
"ERRORS_NO_CONNECTION": 2,
"ERRORS_CONNECTION_TIMEOUT": 3,
"ERRORS_READ_TIMEOUT": 4,
"ERRORS_WRITE_TIMEOUT": 5,
}
func (x Errors) String() string {
return proto.EnumName(Errors_name, int32(x))
}
func (Errors) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_a9d74c406df3ad93, []int{0}
}
// FilePVKey stores the immutable part of PrivValidator. // FilePVKey stores the immutable part of PrivValidator.
type FilePVKey struct { type FilePVKey struct {
Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
@ -96,7 +133,7 @@ func (m *FilePVKey) GetFilePath() string {
// FilePVLastSignState stores the mutable part of PrivValidator. // FilePVLastSignState stores the mutable part of PrivValidator.
type FilePVLastSignState struct { type FilePVLastSignState struct {
Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"`
Round int64 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"`
Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"`
Step int32 `protobuf:"varint,3,opt,name=step,proto3" json:"step,omitempty"` Step int32 `protobuf:"varint,3,opt,name=step,proto3" json:"step,omitempty"`
Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"` Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"`
SignBytes []byte `protobuf:"bytes,5,opt,name=sign_bytes,json=signBytes,proto3" json:"sign_bytes,omitempty"` SignBytes []byte `protobuf:"bytes,5,opt,name=sign_bytes,json=signBytes,proto3" json:"sign_bytes,omitempty"`
@ -143,7 +180,7 @@ func (m *FilePVLastSignState) GetHeight() int64 {
return 0 return 0
} }
func (m *FilePVLastSignState) GetRound() int64 {
func (m *FilePVLastSignState) GetRound() int32 {
if m != nil { if m != nil {
return m.Round return m.Round
} }
@ -179,6 +216,7 @@ func (m *FilePVLastSignState) GetFilePath() string {
} }
func init() { func init() {
proto.RegisterEnum("tendermint.proto.privval.Errors", Errors_name, Errors_value)
proto.RegisterType((*FilePVKey)(nil), "tendermint.proto.privval.FilePVKey") proto.RegisterType((*FilePVKey)(nil), "tendermint.proto.privval.FilePVKey")
proto.RegisterType((*FilePVLastSignState)(nil), "tendermint.proto.privval.FilePVLastSignState") proto.RegisterType((*FilePVLastSignState)(nil), "tendermint.proto.privval.FilePVLastSignState")
} }
@ -186,32 +224,38 @@ func init() {
func init() { proto.RegisterFile("proto/privval/types.proto", fileDescriptor_a9d74c406df3ad93) } func init() { proto.RegisterFile("proto/privval/types.proto", fileDescriptor_a9d74c406df3ad93) }
var fileDescriptor_a9d74c406df3ad93 = []byte{ var fileDescriptor_a9d74c406df3ad93 = []byte{
// 385 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x52, 0x4d, 0x8e, 0xd3, 0x30,
0x14, 0x8e, 0x69, 0x9b, 0x4e, 0xcc, 0xac, 0x0c, 0x42, 0x61, 0x60, 0x42, 0x35, 0x0b, 0xc8, 0x2a,
0x91, 0xe0, 0x06, 0x5d, 0x8c, 0x40, 0xc3, 0xa2, 0xca, 0x48, 0x2c, 0xd8, 0x44, 0x4e, 0xf3, 0x48,
0xac, 0xc9, 0x24, 0x96, 0xfd, 0x52, 0xc9, 0xb7, 0xe0, 0x2a, 0xdc, 0x62, 0x96, 0xdd, 0x20, 0xb1,
0x42, 0xa8, 0xbd, 0x08, 0xb2, 0x53, 0x94, 0x56, 0x2c, 0x66, 0xf7, 0xbe, 0xcf, 0xcf, 0xdf, 0x8f,
0x65, 0xfa, 0x52, 0xaa, 0x0e, 0xbb, 0x54, 0x2a, 0xb1, 0xd9, 0xf0, 0x26, 0x45, 0x23, 0x41, 0x27,
0x8e, 0x63, 0x21, 0x42, 0x5b, 0x82, 0xba, 0x17, 0x2d, 0x0e, 0x4c, 0x72, 0xd8, 0xba, 0x78, 0x8b,
0xb5, 0x50, 0x65, 0x2e, 0xb9, 0x42, 0x93, 0x0e, 0x02, 0x55, 0x57, 0x75, 0xe3, 0x34, 0xec, 0x5f,
0x5c, 0x0e, 0xcc, 0x5a, 0x19, 0x89, 0x5d, 0x7a, 0x07, 0x46, 0x1f, 0x1b, 0x5c, 0xfd, 0x24, 0x34,
0xb8, 0x16, 0x0d, 0xac, 0xbe, 0xdc, 0x80, 0x61, 0x21, 0x9d, 0xf3, 0xb2, 0x54, 0xa0, 0x75, 0x48,
0x16, 0x24, 0x3e, 0xcf, 0xfe, 0x41, 0x76, 0x4d, 0xe7, 0xb2, 0x2f, 0xf2, 0x3b, 0x30, 0xe1, 0x93,
0x05, 0x89, 0x9f, 0xbe, 0x7f, 0x97, 0xfc, 0x17, 0x6d, 0xf0, 0x48, 0xac, 0x47, 0xb2, 0xea, 0x8b,
0x46, 0xac, 0x6f, 0xc0, 0x2c, 0xa7, 0x0f, 0xbf, 0xdf, 0x78, 0x99, 0x2f, 0xfb, 0xc2, 0x3a, 0x7c,
0xa2, 0x67, 0xb6, 0x81, 0x13, 0x9a, 0x38, 0xa1, 0xf8, 0x11, 0x21, 0x25, 0x36, 0x1c, 0x61, 0x54,
0x9a, 0xdb, 0xfb, 0x56, 0xea, 0x15, 0x0d, 0xbe, 0x89, 0x06, 0x72, 0xc9, 0xb1, 0x0e, 0xa7, 0x0b,
0x12, 0x07, 0xd9, 0x99, 0x25, 0x56, 0x1c, 0xeb, 0xab, 0x1f, 0x84, 0x3e, 0x1b, 0x7a, 0x7d, 0xe6,
0x1a, 0x6f, 0x45, 0xd5, 0xde, 0x22, 0x47, 0x60, 0x2f, 0xa8, 0x5f, 0x83, 0xa8, 0x6a, 0x74, 0x05,
0x27, 0xd9, 0x01, 0xb1, 0xe7, 0x74, 0xa6, 0xba, 0xbe, 0x2d, 0x5d, 0xbb, 0x49, 0x36, 0x00, 0xc6,
0xe8, 0x54, 0x23, 0x48, 0x97, 0x74, 0x96, 0xb9, 0x99, 0xbd, 0xa6, 0x81, 0x16, 0x55, 0xcb, 0xb1,
0x57, 0xe0, 0x6c, 0xcf, 0xb3, 0x91, 0x60, 0x97, 0x94, 0x5a, 0x90, 0x17, 0x06, 0x41, 0x87, 0xb3,
0xf1, 0x78, 0x69, 0x89, 0xd3, 0xcc, 0xfe, 0x69, 0xe6, 0xe5, 0xc7, 0x87, 0x5d, 0x44, 0xb6, 0xbb,
0x88, 0xfc, 0xd9, 0x45, 0xe4, 0xfb, 0x3e, 0xf2, 0xb6, 0xfb, 0xc8, 0xfb, 0xb5, 0x8f, 0xbc, 0xaf,
0x49, 0x25, 0xb0, 0xee, 0x8b, 0x64, 0xdd, 0xdd, 0xa7, 0xe3, 0x6b, 0x1d, 0x8f, 0x27, 0x5f, 0xa8,
0xf0, 0x1d, 0xfc, 0xf0, 0x37, 0x00, 0x00, 0xff, 0xff, 0xe5, 0xc6, 0x2f, 0x79, 0x5a, 0x02, 0x00,
0x00,
// 493 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x52, 0xcf, 0x6e, 0xd3, 0x4e,
0x18, 0xcc, 0x36, 0x89, 0xd3, 0xec, 0xaf, 0xfa, 0x29, 0xda, 0x56, 0xe0, 0x06, 0x62, 0xa2, 0x1e,
0x20, 0xe2, 0x60, 0x4b, 0xf0, 0x04, 0x24, 0xdd, 0x8a, 0x28, 0x60, 0x5b, 0x6b, 0x97, 0x22, 0x2e,
0x96, 0x1d, 0x2f, 0xf6, 0xaa, 0xa9, 0x6d, 0xad, 0xd7, 0x91, 0xfc, 0x16, 0x3c, 0x06, 0x57, 0xde,
0xa2, 0xc7, 0x5e, 0x90, 0x38, 0x21, 0x94, 0xbc, 0x08, 0xf2, 0x1f, 0xe2, 0x44, 0x1c, 0xb8, 0x7d,
0x33, 0xf3, 0x79, 0xe6, 0x1b, 0x79, 0xe1, 0x79, 0xc2, 0x63, 0x11, 0x6b, 0x09, 0x67, 0xeb, 0xb5,
0xbb, 0xd2, 0x44, 0x9e, 0xd0, 0x54, 0x2d, 0x39, 0x24, 0x0b, 0x1a, 0xf9, 0x94, 0xdf, 0xb1, 0x48,
0x54, 0x8c, 0x5a, 0x6f, 0x0d, 0x9f, 0x8b, 0x90, 0x71, 0xdf, 0x49, 0x5c, 0x2e, 0x72, 0xad, 0x32,
0x08, 0xe2, 0x20, 0x6e, 0xa6, 0x6a, 0x7f, 0x38, 0xaa, 0x98, 0x25, 0xcf, 0x13, 0x11, 0x6b, 0xb7,
0x34, 0x4f, 0xf7, 0x03, 0x2e, 0xbe, 0x03, 0xd8, 0xbf, 0x62, 0x2b, 0x6a, 0x7e, 0x58, 0xd0, 0x1c,
0xc9, 0xb0, 0xe7, 0xfa, 0x3e, 0xa7, 0x69, 0x2a, 0x83, 0x31, 0x98, 0x9c, 0x90, 0x3f, 0x10, 0x5d,
0xc1, 0x5e, 0x92, 0x79, 0xce, 0x2d, 0xcd, 0xe5, 0xa3, 0x31, 0x98, 0xfc, 0xf7, 0xea, 0x85, 0xfa,
0xd7, 0x69, 0x55, 0x86, 0x5a, 0x64, 0xa8, 0x66, 0xe6, 0xad, 0xd8, 0x72, 0x41, 0xf3, 0x69, 0xe7,
0xfe, 0xe7, 0xb3, 0x16, 0x91, 0x92, 0xcc, 0x2b, 0x12, 0xe6, 0xf0, 0xb8, 0x68, 0x50, 0x1a, 0xb5,
0x4b, 0xa3, 0xc9, 0x3f, 0x8c, 0x38, 0x5b, 0xbb, 0x82, 0x36, 0x4e, 0xbd, 0xe2, 0xfb, 0xc2, 0xea,
0x09, 0xec, 0x7f, 0x66, 0x2b, 0xea, 0x24, 0xae, 0x08, 0xe5, 0xce, 0x18, 0x4c, 0xfa, 0xe4, 0xb8,
0x20, 0x4c, 0x57, 0x84, 0x17, 0xdf, 0x00, 0x3c, 0xad, 0x7a, 0xbd, 0x73, 0x53, 0x61, 0xb1, 0x20,
0xb2, 0x84, 0x2b, 0x28, 0x7a, 0x04, 0xa5, 0x90, 0xb2, 0x20, 0x14, 0x65, 0xc1, 0x36, 0xa9, 0x11,
0x3a, 0x83, 0x5d, 0x1e, 0x67, 0x91, 0x5f, 0xb6, 0xeb, 0x92, 0x0a, 0x20, 0x04, 0x3b, 0xa9, 0xa0,
0x49, 0x79, 0x69, 0x97, 0x94, 0x33, 0x7a, 0x0a, 0xfb, 0x29, 0x0b, 0x22, 0x57, 0x64, 0x9c, 0x96,
0xb1, 0x27, 0xa4, 0x21, 0xd0, 0x08, 0xc2, 0x02, 0x38, 0x5e, 0x2e, 0x68, 0x2a, 0x77, 0x1b, 0x79,
0x5a, 0x10, 0x87, 0x37, 0x4b, 0x87, 0x37, 0xbf, 0xfc, 0x0a, 0xa0, 0x84, 0x39, 0x8f, 0x79, 0x8a,
0x10, 0xfc, 0x1f, 0x13, 0x62, 0x10, 0xcb, 0xb9, 0xd6, 0x17, 0xba, 0x71, 0xa3, 0x0f, 0x5a, 0x48,
0x81, 0xc3, 0x1d, 0x87, 0x3f, 0x9a, 0x78, 0x66, 0xe3, 0x4b, 0x87, 0x60, 0xcb, 0x34, 0x74, 0x0b,
0x0f, 0x00, 0x92, 0xe1, 0x59, 0xad, 0xeb, 0x86, 0x33, 0x33, 0x74, 0x1d, 0xcf, 0xec, 0xb9, 0xa1,
0x0f, 0x8e, 0xd0, 0x08, 0x9e, 0xd7, 0x4a, 0x43, 0x3b, 0xf6, 0xfc, 0x3d, 0x36, 0xae, 0xed, 0x41,
0x1b, 0x3d, 0x86, 0xa7, 0xb5, 0x4c, 0xf0, 0x9b, 0xcb, 0x9d, 0xd0, 0xd9, 0x73, 0xbc, 0x21, 0x73,
0x1b, 0xef, 0x94, 0xee, 0xf4, 0xed, 0xfd, 0x46, 0x01, 0x0f, 0x1b, 0x05, 0xfc, 0xda, 0x28, 0xe0,
0xcb, 0x56, 0x69, 0x3d, 0x6c, 0x95, 0xd6, 0x8f, 0xad, 0xd2, 0xfa, 0xa4, 0x06, 0x4c, 0x84, 0x99,
0xa7, 0x2e, 0xe3, 0x3b, 0xad, 0xf9, 0xb1, 0xfb, 0xe3, 0xc1, 0x6b, 0xf7, 0xa4, 0x12, 0xbe, 0xfe,
0x1d, 0x00, 0x00, 0xff, 0xff, 0x60, 0xba, 0xbc, 0x27, 0x05, 0x03, 0x00, 0x00,
} }
func (m *FilePVKey) Marshal() (dAtA []byte, err error) { func (m *FilePVKey) Marshal() (dAtA []byte, err error) {
@ -645,7 +689,7 @@ func (m *FilePVLastSignState) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
m.Round |= int64(b&0x7F) << shift
m.Round |= int32(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }


+ 10
- 1
proto/privval/types.proto View File

@ -18,10 +18,19 @@ message FilePVKey {
// FilePVLastSignState stores the mutable part of PrivValidator. // FilePVLastSignState stores the mutable part of PrivValidator.
message FilePVLastSignState { message FilePVLastSignState {
int64 height = 1; int64 height = 1;
int64 round = 2;
int32 round = 2;
int32 step = 3; int32 step = 3;
bytes signature = 4; bytes signature = 4;
bytes sign_bytes = 5; bytes sign_bytes = 5;
string file_path = 6; string file_path = 6;
} }
enum Errors {
ERRORS_UNKNOWN = 0;
ERRORS_UNEXPECTED_RESPONSE = 1;
ERRORS_NO_CONNECTION = 2;
ERRORS_CONNECTION_TIMEOUT = 3;
ERRORS_READ_TIMEOUT = 4;
ERRORS_WRITE_TIMEOUT = 5;
}

+ 1407
- 0
proto/types/canonical.pb.go
File diff suppressed because it is too large
View File


+ 37
- 0
proto/types/canonical.proto View File

@ -0,0 +1,37 @@
syntax = "proto3";
package tendermint.proto.types;
option go_package = "github.com/tendermint/tendermint/proto/types";
import "third_party/proto/gogoproto/gogo.proto";
import "proto/types/types.proto";
import "google/protobuf/timestamp.proto";
message CanonicalBlockID {
bytes hash = 1;
CanonicalPartSetHeader parts_header = 2 [(gogoproto.nullable) = false];
}
message CanonicalPartSetHeader {
bytes hash = 1;
uint32 total = 2;
}
message CanonicalProposal {
SignedMsgType type = 1; // type alias for byte
int64 height = 2;
int64 round = 3;
int64 pol_round = 4 [(gogoproto.customname) = "POLRound"];
CanonicalBlockID block_id = 5 [(gogoproto.nullable) = false, (gogoproto.customname) = "BlockID"];
google.protobuf.Timestamp timestamp = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
string chain_id = 7 [(gogoproto.customname) = "ChainID"];
}
message CanonicalVote {
SignedMsgType type = 1; // type alias for byte
int64 height = 2;
int64 round = 3;
CanonicalBlockID block_id = 5 [(gogoproto.nullable) = false, (gogoproto.customname) = "BlockID"];
google.protobuf.Timestamp timestamp = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
string chain_id = 7 [(gogoproto.customname) = "ChainID"];
}

+ 87
- 79
proto/types/types.pb.go View File

@ -54,6 +54,10 @@ var BlockIDFlag_value = map[string]int32{
"BLOCK_ID_FLAG_NIL": 3, "BLOCK_ID_FLAG_NIL": 3,
} }
func (x BlockIDFlag) String() string {
return proto.EnumName(BlockIDFlag_name, int32(x))
}
func (BlockIDFlag) EnumDescriptor() ([]byte, []int) { func (BlockIDFlag) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_ff06f8095857fb18, []int{0} return fileDescriptor_ff06f8095857fb18, []int{0}
} }
@ -82,6 +86,10 @@ var SignedMsgType_value = map[string]int32{
"PROPOSAL_TYPE": 3, "PROPOSAL_TYPE": 3,
} }
func (x SignedMsgType) String() string {
return proto.EnumName(SignedMsgType_name, int32(x))
}
func (SignedMsgType) EnumDescriptor() ([]byte, []int) { func (SignedMsgType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_ff06f8095857fb18, []int{1} return fileDescriptor_ff06f8095857fb18, []int{1}
} }
@ -951,86 +959,86 @@ func init() { proto.RegisterFile("proto/types/types.proto", fileDescriptor_ff06f
var fileDescriptor_ff06f8095857fb18 = []byte{ var fileDescriptor_ff06f8095857fb18 = []byte{
// 1274 bytes of a gzipped FileDescriptorProto // 1274 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4f, 0x6f, 0x1a, 0x47,
0x14, 0x67, 0x61, 0x31, 0xf0, 0x00, 0x1b, 0xaf, 0xdc, 0x84, 0xe2, 0x16, 0x13, 0xdc, 0xa4, 0x4e,
0x1a, 0x41, 0xe5, 0x4a, 0x55, 0x23, 0xf5, 0x02, 0x86, 0x38, 0x28, 0x36, 0xa0, 0x85, 0xa6, 0x6a,
0x2f, 0xab, 0x81, 0x9d, 0x2c, 0xab, 0x2c, 0xbb, 0xab, 0xdd, 0xc1, 0x32, 0x39, 0xf4, 0x5c, 0xf9,
0x94, 0x2f, 0xe0, 0x53, 0x5a, 0xa9, 0xdf, 0xa2, 0x3d, 0xe6, 0x54, 0xe5, 0xd8, 0x53, 0x5a, 0xd9,
0xdf, 0xa0, 0xea, 0x07, 0xa8, 0xe6, 0xcf, 0x2e, 0x10, 0x4c, 0x1b, 0x35, 0x51, 0x2f, 0xf6, 0xce,
0x7b, 0xbf, 0xdf, 0x9b, 0x79, 0xbf, 0xf9, 0xcd, 0x8c, 0x80, 0xeb, 0xae, 0xe7, 0x10, 0xa7, 0x4a,
0xa6, 0x2e, 0xf6, 0xf9, 0xdf, 0x0a, 0x8b, 0x28, 0xd7, 0x08, 0xb6, 0x75, 0xec, 0x8d, 0x4d, 0x9b,
0xf0, 0x48, 0x85, 0x65, 0x0b, 0xb7, 0xc8, 0xc8, 0xf4, 0x74, 0xcd, 0x45, 0x1e, 0x99, 0x56, 0x39,
0xd9, 0x70, 0x0c, 0x67, 0xf6, 0xc5, 0xd1, 0x85, 0x1d, 0xc3, 0x71, 0x0c, 0x0b, 0x73, 0xc8, 0x60,
0xf2, 0xb8, 0x4a, 0xcc, 0x31, 0xf6, 0x09, 0x1a, 0xbb, 0x02, 0xb0, 0xcd, 0x29, 0x96, 0x39, 0xf0,
0xab, 0x03, 0x93, 0x2c, 0xcc, 0x5e, 0xd8, 0xe1, 0xc9, 0xa1, 0x37, 0x75, 0x89, 0x53, 0x1d, 0x63,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4d, 0x6f, 0x1a, 0x47,
0x18, 0xf6, 0xc2, 0x62, 0xe0, 0x05, 0x6c, 0xbc, 0x72, 0x13, 0x8a, 0x5b, 0x4c, 0x70, 0x93, 0x3a,
0x69, 0x04, 0x95, 0x2b, 0x55, 0x8d, 0xd4, 0x0b, 0x5f, 0x71, 0x50, 0x6c, 0x40, 0x0b, 0x4d, 0xd5,
0x5e, 0x56, 0x03, 0x3b, 0x59, 0x56, 0x59, 0x76, 0x57, 0xbb, 0x83, 0x65, 0x72, 0xe8, 0xb9, 0xf2,
0x29, 0x7f, 0xc0, 0xa7, 0xb4, 0x52, 0xff, 0x45, 0x7b, 0xcc, 0xa9, 0xca, 0xb1, 0xa7, 0xb4, 0xb2,
0xff, 0x41, 0xd5, 0x1f, 0x50, 0xcd, 0xc7, 0x2e, 0x10, 0x4c, 0x1b, 0x35, 0x51, 0x2f, 0xf6, 0xce,
0xfb, 0x3e, 0xcf, 0x3b, 0xf3, 0x3e, 0xf3, 0xcc, 0x8c, 0x80, 0xeb, 0xae, 0xe7, 0x10, 0xa7, 0x42,
0xa6, 0x2e, 0xf6, 0xf9, 0xdf, 0x32, 0x8b, 0x28, 0xd7, 0x08, 0xb6, 0x75, 0xec, 0x8d, 0x4d, 0x9b,
0xf0, 0x48, 0x99, 0x65, 0xf3, 0xb7, 0xc8, 0xc8, 0xf4, 0x74, 0xcd, 0x45, 0x1e, 0x99, 0x56, 0x38,
0xd9, 0x70, 0x0c, 0x67, 0xf6, 0xc5, 0xd1, 0xf9, 0x5d, 0xc3, 0x71, 0x0c, 0x0b, 0x73, 0xc8, 0x60,
0xf2, 0xb8, 0x42, 0xcc, 0x31, 0xf6, 0x09, 0x1a, 0xbb, 0x02, 0xb0, 0xc3, 0x29, 0x96, 0x39, 0xf0,
0x2b, 0x03, 0x93, 0x2c, 0xcc, 0x9e, 0xdf, 0xe5, 0xc9, 0xa1, 0x37, 0x75, 0x89, 0x53, 0x19, 0x63,
0xef, 0x89, 0x85, 0x17, 0x00, 0x82, 0x7d, 0x82, 0x3d, 0xdf, 0x74, 0xec, 0xe0, 0x3f, 0x4f, 0x96, 0xef, 0x89, 0x85, 0x17, 0x00, 0x82, 0x7d, 0x82, 0x3d, 0xdf, 0x74, 0xec, 0xe0, 0x3f, 0x4f, 0x96,
0xef, 0x41, 0xb6, 0x8b, 0x3c, 0xd2, 0xc3, 0xe4, 0x01, 0x46, 0x3a, 0xf6, 0x94, 0x2d, 0x88, 0x13,
0x87, 0x20, 0x2b, 0x2f, 0x95, 0xa4, 0xbd, 0xac, 0xca, 0x07, 0x8a, 0x02, 0xf2, 0x08, 0xf9, 0xa3,
0x7c, 0xb4, 0x24, 0xed, 0x65, 0x54, 0xf6, 0x5d, 0x9e, 0x80, 0x4c, 0xa9, 0x94, 0x61, 0xda, 0x3a,
0x3e, 0x0d, 0x18, 0x6c, 0x40, 0xa3, 0x83, 0x29, 0xc1, 0xbe, 0xa0, 0xf0, 0x81, 0x52, 0x83, 0xb8,
0xeb, 0x39, 0xce, 0xe3, 0x7c, 0xac, 0x24, 0xed, 0xa5, 0xf7, 0x6f, 0x56, 0x96, 0xa4, 0xe3, 0x7d,
0x54, 0x78, 0x1f, 0x95, 0x2e, 0x05, 0xd7, 0xe5, 0x17, 0xaf, 0x76, 0x22, 0x2a, 0x67, 0x96, 0xc7,
0x90, 0xa8, 0x5b, 0xce, 0xf0, 0x49, 0xab, 0x11, 0xae, 0x4a, 0x9a, 0xad, 0x4a, 0x69, 0x43, 0x86,
0x0a, 0xee, 0x6b, 0x23, 0xd6, 0x0f, 0x9b, 0xfe, 0xca, 0x89, 0xb8, 0x44, 0x0b, 0xcd, 0x8b, 0x89,
0xd2, 0xac, 0x00, 0x0f, 0x95, 0xff, 0x94, 0x61, 0x4d, 0x48, 0x73, 0x00, 0x09, 0x21, 0x1e, 0x9b,
0x31, 0xbd, 0xbf, 0xbb, 0x5c, 0x35, 0x50, 0xf7, 0xc0, 0xb1, 0x7d, 0x6c, 0xfb, 0x13, 0x5f, 0xd4,
0x0c, 0x98, 0xca, 0x2d, 0x48, 0x0e, 0x47, 0xc8, 0xb4, 0x35, 0x53, 0x67, 0x6b, 0x4b, 0xd5, 0xd3,
0x17, 0xaf, 0x76, 0x12, 0x07, 0x34, 0xd6, 0x6a, 0xa8, 0x09, 0x96, 0x6c, 0xe9, 0xca, 0x35, 0x58,
0x1b, 0x61, 0xd3, 0x18, 0x11, 0x26, 0x55, 0x4c, 0x15, 0x23, 0xe5, 0x0b, 0x90, 0xa9, 0x3d, 0xf2,
0x32, 0x5b, 0x41, 0xa1, 0xc2, 0xbd, 0x53, 0x09, 0xbc, 0x53, 0xe9, 0x07, 0xde, 0xa9, 0x27, 0xe9,
0xc4, 0xcf, 0x7e, 0xdf, 0x91, 0x54, 0xc6, 0x50, 0x5a, 0x90, 0xb5, 0x90, 0x4f, 0xb4, 0x01, 0x55,
0x8f, 0x4e, 0x1f, 0x67, 0x25, 0x76, 0x56, 0x49, 0x23, 0x54, 0x0e, 0x44, 0xa1, 0x5c, 0x1e, 0xd2,
0x95, 0x3d, 0xc8, 0xb1, 0x52, 0x43, 0x67, 0x3c, 0x36, 0x89, 0xc6, 0x36, 0x61, 0x8d, 0x6d, 0xc2,
0x3a, 0x8d, 0x1f, 0xb0, 0xf0, 0x03, 0xba, 0x1d, 0xdb, 0x90, 0xd2, 0x11, 0x41, 0x1c, 0x92, 0x60,
0x90, 0x24, 0x0d, 0xb0, 0xe4, 0xc7, 0xb0, 0x71, 0x82, 0x2c, 0x53, 0x47, 0xc4, 0xf1, 0x7c, 0x0e,
0x49, 0xf2, 0x2a, 0xb3, 0x30, 0x03, 0x7e, 0x0a, 0x5b, 0x36, 0x3e, 0x25, 0xda, 0xeb, 0xe8, 0x14,
0x43, 0x2b, 0x34, 0xf7, 0x68, 0x91, 0x71, 0x13, 0xd6, 0x87, 0xc1, 0x16, 0x70, 0x2c, 0x30, 0x6c,
0x36, 0x8c, 0x32, 0xd8, 0xfb, 0x90, 0x44, 0xae, 0xcb, 0x01, 0x69, 0x06, 0x48, 0x20, 0xd7, 0x65,
0xa9, 0x3b, 0xb0, 0xc9, 0x7a, 0xf4, 0xb0, 0x3f, 0xb1, 0x88, 0x28, 0x92, 0x61, 0x98, 0x0d, 0x9a,
0x50, 0x79, 0x9c, 0x61, 0x77, 0x21, 0x8b, 0x4f, 0x4c, 0x1d, 0xdb, 0x43, 0xcc, 0x71, 0x59, 0x86,
0xcb, 0x04, 0x41, 0x06, 0xba, 0x0d, 0x39, 0xd7, 0x73, 0x5c, 0xc7, 0xc7, 0x9e, 0x86, 0x74, 0xdd,
0xc3, 0xbe, 0x9f, 0x5f, 0xe7, 0xf5, 0x82, 0x78, 0x8d, 0x87, 0xcb, 0x77, 0x41, 0x6e, 0x20, 0x82,
0x94, 0x1c, 0xc4, 0xc8, 0xa9, 0x9f, 0x97, 0x4a, 0xb1, 0xbd, 0x8c, 0x4a, 0x3f, 0xaf, 0x3c, 0x88,
0x7f, 0x45, 0x41, 0x7e, 0xe4, 0x10, 0xac, 0xdc, 0x03, 0x99, 0x6e, 0x1d, 0x73, 0xe7, 0xfa, 0x6a,
0xcf, 0xf7, 0x4c, 0xc3, 0xc6, 0xfa, 0xb1, 0x6f, 0xf4, 0xa7, 0x2e, 0x56, 0x19, 0x65, 0xce, 0x6e,
0xd1, 0x05, 0xbb, 0x6d, 0x41, 0xdc, 0x73, 0x26, 0xb6, 0xce, 0x5c, 0x18, 0x57, 0xf9, 0x40, 0x79,
0x08, 0xc9, 0xd0, 0x45, 0xf2, 0x9b, 0xb9, 0x68, 0x83, 0xba, 0x88, 0x3a, 0x5d, 0x04, 0xd4, 0xc4,
0x40, 0x98, 0xa9, 0x0e, 0xa9, 0xf0, 0xc2, 0x13, 0x9e, 0x7c, 0x33, 0x5b, 0xcf, 0x68, 0xca, 0x27,
0xb0, 0x19, 0x7a, 0x23, 0x14, 0x97, 0x3b, 0x32, 0x17, 0x26, 0x84, 0xba, 0x0b, 0xb6, 0xd3, 0xf8,
0xd5, 0x95, 0x60, 0xdd, 0xcd, 0x6c, 0xd7, 0x62, 0x77, 0xd8, 0x07, 0x90, 0xf2, 0x4d, 0xc3, 0x46,
0x64, 0xe2, 0x61, 0xe1, 0xcc, 0x59, 0xa0, 0xfc, 0x3c, 0x0a, 0x6b, 0xdc, 0xe9, 0x73, 0xea, 0x49,
0x57, 0xab, 0x17, 0x5d, 0xa5, 0x5e, 0xec, 0x6d, 0xd5, 0x3b, 0x04, 0x08, 0x97, 0xe4, 0xe7, 0xe5,
0x52, 0x6c, 0x2f, 0xbd, 0x7f, 0x63, 0x55, 0x39, 0xbe, 0xdc, 0x9e, 0x69, 0x88, 0x43, 0x3d, 0x47,
0x0d, 0x9d, 0x15, 0x9f, 0xbb, 0x4c, 0x6b, 0x90, 0x1a, 0x98, 0x44, 0x43, 0x9e, 0x87, 0xa6, 0x4c,
0xce, 0xf4, 0xfe, 0x47, 0xcb, 0xb5, 0xe9, 0xbb, 0x54, 0xa1, 0xef, 0x52, 0xa5, 0x6e, 0x92, 0x1a,
0xc5, 0xaa, 0xc9, 0x81, 0xf8, 0x2a, 0x5f, 0x4a, 0x90, 0x0a, 0xa7, 0x55, 0x0e, 0x21, 0x1b, 0xb4,
0xae, 0x3d, 0xb6, 0x90, 0x21, 0xac, 0xba, 0xfb, 0x2f, 0xfd, 0xdf, 0xb7, 0x90, 0xa1, 0xa6, 0x45,
0xcb, 0x74, 0x70, 0xf5, 0x86, 0x47, 0x57, 0x6c, 0xf8, 0x82, 0xc3, 0x62, 0xff, 0xcd, 0x61, 0x0b,
0x5e, 0x90, 0x5f, 0xf7, 0xc2, 0xcf, 0x51, 0x48, 0x76, 0xd9, 0x21, 0x46, 0xd6, 0xff, 0x77, 0x0c,
0xb7, 0x21, 0xe5, 0x3a, 0x96, 0xc6, 0x33, 0x32, 0xcb, 0x24, 0x5d, 0xc7, 0x52, 0x97, 0x5c, 0x16,
0x7f, 0xa7, 0x67, 0x74, 0xed, 0x1d, 0x28, 0x98, 0x78, 0x5d, 0xc1, 0xef, 0x20, 0xc3, 0x05, 0x11,
0x8f, 0xed, 0xe7, 0x54, 0x09, 0xf6, 0x82, 0xf3, 0xb7, 0xb6, 0xb8, 0x6a, 0xf1, 0x1c, 0xaf, 0x0a,
0x34, 0xe5, 0xf1, 0x57, 0x49, 0xbc, 0xfc, 0xc5, 0x7f, 0x3e, 0x0b, 0xaa, 0x40, 0x97, 0x7f, 0x95,
0x20, 0xc5, 0xda, 0x3e, 0xc6, 0x04, 0x2d, 0x88, 0x27, 0xbd, 0xad, 0x78, 0x1f, 0x02, 0xf0, 0x62,
0xbe, 0xf9, 0x14, 0x8b, 0x8d, 0x4d, 0xb1, 0x48, 0xcf, 0x7c, 0x8a, 0x95, 0x2f, 0xc3, 0x4e, 0x63,
0x6f, 0xd2, 0xa9, 0x38, 0xba, 0x41, 0xbf, 0xd7, 0x21, 0x61, 0x4f, 0xc6, 0x1a, 0x7d, 0x26, 0x64,
0x6e, 0x19, 0x7b, 0x32, 0xee, 0x9f, 0xfa, 0x77, 0x7e, 0x91, 0x20, 0x3d, 0x77, 0x7c, 0x94, 0x02,
0x5c, 0xab, 0x1f, 0x75, 0x0e, 0x1e, 0x36, 0xb4, 0x56, 0x43, 0xbb, 0x7f, 0x54, 0x3b, 0xd4, 0xbe,
0x6a, 0x3f, 0x6c, 0x77, 0xbe, 0x6e, 0xe7, 0x22, 0x4a, 0x15, 0xb6, 0x58, 0x2e, 0x4c, 0xd5, 0xea,
0xbd, 0x66, 0xbb, 0x9f, 0x93, 0x0a, 0xef, 0x9d, 0x9d, 0x97, 0x36, 0xe7, 0xca, 0xd4, 0x06, 0x3e,
0xb6, 0xc9, 0x32, 0xe1, 0xa0, 0x73, 0x7c, 0xdc, 0xea, 0xe7, 0xa2, 0x4b, 0x04, 0x71, 0x43, 0xde,
0x86, 0xcd, 0x45, 0x42, 0xbb, 0x75, 0x94, 0x8b, 0x15, 0x94, 0xb3, 0xf3, 0xd2, 0xfa, 0x1c, 0xba,
0x6d, 0x5a, 0x85, 0xe4, 0xf7, 0xcf, 0x8b, 0x91, 0x9f, 0x7e, 0x28, 0x46, 0xee, 0xfc, 0x28, 0x41,
0x76, 0xe1, 0x94, 0x28, 0xdb, 0x70, 0xbd, 0xd7, 0x3a, 0x6c, 0x37, 0x1b, 0xda, 0x71, 0xef, 0x50,
0xeb, 0x7f, 0xd3, 0x6d, 0xce, 0x75, 0x71, 0x03, 0x32, 0x5d, 0xb5, 0xf9, 0xa8, 0xd3, 0x6f, 0xb2,
0x4c, 0x4e, 0x2a, 0x6c, 0x9c, 0x9d, 0x97, 0xd2, 0x5d, 0x0f, 0x9f, 0x38, 0x04, 0x33, 0xfe, 0x4d,
0x58, 0xef, 0xaa, 0x4d, 0xbe, 0x58, 0x0e, 0x8a, 0x16, 0x36, 0xcf, 0xce, 0x4b, 0xd9, 0xae, 0x87,
0xb9, 0x11, 0x18, 0x6c, 0x17, 0xb2, 0x5d, 0xb5, 0xd3, 0xed, 0xf4, 0x6a, 0x47, 0x1c, 0x15, 0x2b,
0xe4, 0xce, 0xce, 0x4b, 0x99, 0xe0, 0x88, 0x53, 0xd0, 0x6c, 0x9d, 0xf5, 0xfb, 0x2f, 0x2e, 0x8a,
0xd2, 0xcb, 0x8b, 0xa2, 0xf4, 0xc7, 0x45, 0x51, 0x7a, 0x76, 0x59, 0x8c, 0xbc, 0xbc, 0x2c, 0x46,
0x7e, 0xbb, 0x2c, 0x46, 0xbe, 0xbd, 0x6b, 0x98, 0x64, 0x34, 0x19, 0x54, 0x86, 0xce, 0xb8, 0x3a,
0xdb, 0xd5, 0xf9, 0xcf, 0xb9, 0x1f, 0x15, 0x83, 0x35, 0x36, 0xf8, 0xec, 0xef, 0x00, 0x00, 0x00,
0xff, 0xff, 0x5f, 0xad, 0x08, 0x71, 0x6a, 0x0c, 0x00, 0x00,
0xee, 0x41, 0xa6, 0x8b, 0x3c, 0xd2, 0xc3, 0xe4, 0x01, 0x46, 0x3a, 0xf6, 0x94, 0x6d, 0x88, 0x11,
0x87, 0x20, 0x2b, 0x27, 0x15, 0xa5, 0xfd, 0x8c, 0xca, 0x07, 0x8a, 0x02, 0xf2, 0x08, 0xf9, 0xa3,
0x5c, 0xa4, 0x28, 0xed, 0xa7, 0x55, 0xf6, 0x5d, 0x9a, 0x80, 0x4c, 0xa9, 0x94, 0x61, 0xda, 0x3a,
0x3e, 0x0d, 0x18, 0x6c, 0x40, 0xa3, 0x83, 0x29, 0xc1, 0xbe, 0xa0, 0xf0, 0x81, 0x52, 0x85, 0x98,
0xeb, 0x39, 0xce, 0xe3, 0x5c, 0xb4, 0x28, 0xed, 0xa7, 0x0e, 0x6e, 0x96, 0x97, 0xa4, 0xe3, 0x7d,
0x94, 0x79, 0x1f, 0xe5, 0x2e, 0x05, 0xd7, 0xe4, 0x17, 0xaf, 0x76, 0xd7, 0x54, 0xce, 0x2c, 0x8d,
0x21, 0x5e, 0xb3, 0x9c, 0xe1, 0x93, 0x56, 0x23, 0x5c, 0x95, 0x34, 0x5b, 0x95, 0xd2, 0x86, 0x34,
0x15, 0xdc, 0xd7, 0x46, 0xac, 0x1f, 0x36, 0xfd, 0x95, 0x13, 0x71, 0x89, 0x16, 0x9a, 0x17, 0x13,
0xa5, 0x58, 0x01, 0x1e, 0x2a, 0xfd, 0x29, 0xc3, 0xba, 0x90, 0xa6, 0x0e, 0x71, 0x21, 0x1e, 0x9b,
0x31, 0x75, 0xb0, 0xb7, 0x5c, 0x35, 0x50, 0xb7, 0xee, 0xd8, 0x3e, 0xb6, 0xfd, 0x89, 0x2f, 0x6a,
0x06, 0x4c, 0xe5, 0x16, 0x24, 0x86, 0x23, 0x64, 0xda, 0x9a, 0xa9, 0xb3, 0xb5, 0x25, 0x6b, 0xa9,
0x8b, 0x57, 0xbb, 0xf1, 0x3a, 0x8d, 0xb5, 0x1a, 0x6a, 0x9c, 0x25, 0x5b, 0xba, 0x72, 0x0d, 0xd6,
0x47, 0xd8, 0x34, 0x46, 0x84, 0x49, 0x15, 0x55, 0xc5, 0x48, 0xf9, 0x02, 0x64, 0x6a, 0x8f, 0x9c,
0xcc, 0x56, 0x90, 0x2f, 0x73, 0xef, 0x94, 0x03, 0xef, 0x94, 0xfb, 0x81, 0x77, 0x6a, 0x09, 0x3a,
0xf1, 0xb3, 0xdf, 0x77, 0x25, 0x95, 0x31, 0x94, 0x16, 0x64, 0x2c, 0xe4, 0x13, 0x6d, 0x40, 0xd5,
0xa3, 0xd3, 0xc7, 0x58, 0x89, 0xdd, 0x55, 0xd2, 0x08, 0x95, 0x03, 0x51, 0x28, 0x97, 0x87, 0x74,
0x65, 0x1f, 0xb2, 0xac, 0xd4, 0xd0, 0x19, 0x8f, 0x4d, 0xa2, 0xb1, 0x4d, 0x58, 0x67, 0x9b, 0xb0,
0x41, 0xe3, 0x75, 0x16, 0x7e, 0x40, 0xb7, 0x63, 0x07, 0x92, 0x3a, 0x22, 0x88, 0x43, 0xe2, 0x0c,
0x92, 0xa0, 0x01, 0x96, 0xfc, 0x18, 0x36, 0x4f, 0x90, 0x65, 0xea, 0x88, 0x38, 0x9e, 0xcf, 0x21,
0x09, 0x5e, 0x65, 0x16, 0x66, 0xc0, 0x4f, 0x61, 0xdb, 0xc6, 0xa7, 0x44, 0x7b, 0x1d, 0x9d, 0x64,
0x68, 0x85, 0xe6, 0x1e, 0x2d, 0x32, 0x6e, 0xc2, 0xc6, 0x30, 0xd8, 0x02, 0x8e, 0x05, 0x86, 0xcd,
0x84, 0x51, 0x06, 0x7b, 0x1f, 0x12, 0xc8, 0x75, 0x39, 0x20, 0xc5, 0x00, 0x71, 0xe4, 0xba, 0x2c,
0x75, 0x07, 0xb6, 0x58, 0x8f, 0x1e, 0xf6, 0x27, 0x16, 0x11, 0x45, 0xd2, 0x0c, 0xb3, 0x49, 0x13,
0x2a, 0x8f, 0x33, 0xec, 0x1e, 0x64, 0xf0, 0x89, 0xa9, 0x63, 0x7b, 0x88, 0x39, 0x2e, 0xc3, 0x70,
0xe9, 0x20, 0xc8, 0x40, 0xb7, 0x21, 0xeb, 0x7a, 0x8e, 0xeb, 0xf8, 0xd8, 0xd3, 0x90, 0xae, 0x7b,
0xd8, 0xf7, 0x73, 0x1b, 0xbc, 0x5e, 0x10, 0xaf, 0xf2, 0x70, 0xe9, 0x2e, 0xc8, 0x0d, 0x44, 0x90,
0x92, 0x85, 0x28, 0x39, 0xf5, 0x73, 0x52, 0x31, 0xba, 0x9f, 0x56, 0xe9, 0xe7, 0x95, 0x07, 0xf1,
0xaf, 0x08, 0xc8, 0x8f, 0x1c, 0x82, 0x95, 0x7b, 0x20, 0xd3, 0xad, 0x63, 0xee, 0xdc, 0x58, 0xed,
0xf9, 0x9e, 0x69, 0xd8, 0x58, 0x3f, 0xf6, 0x8d, 0xfe, 0xd4, 0xc5, 0x2a, 0xa3, 0xcc, 0xd9, 0x2d,
0xb2, 0x60, 0xb7, 0x6d, 0x88, 0x79, 0xce, 0xc4, 0xd6, 0x99, 0x0b, 0x63, 0x2a, 0x1f, 0x28, 0x0f,
0x21, 0x11, 0xba, 0x48, 0x7e, 0x33, 0x17, 0x6d, 0x52, 0x17, 0x51, 0xa7, 0x8b, 0x80, 0x1a, 0x1f,
0x08, 0x33, 0xd5, 0x20, 0x19, 0x5e, 0x78, 0xc2, 0x93, 0x6f, 0x66, 0xeb, 0x19, 0x4d, 0xf9, 0x04,
0xb6, 0x42, 0x6f, 0x84, 0xe2, 0x72, 0x47, 0x66, 0xc3, 0x84, 0x50, 0x77, 0xc1, 0x76, 0x1a, 0xbf,
0xba, 0xe2, 0xac, 0xbb, 0x99, 0xed, 0x5a, 0xec, 0x0e, 0xfb, 0x00, 0x92, 0xbe, 0x69, 0xd8, 0x88,
0x4c, 0x3c, 0x2c, 0x9c, 0x39, 0x0b, 0x94, 0x9e, 0x47, 0x60, 0x9d, 0x3b, 0x7d, 0x4e, 0x3d, 0xe9,
0x6a, 0xf5, 0x22, 0xab, 0xd4, 0x8b, 0xbe, 0xad, 0x7a, 0x87, 0x00, 0xe1, 0x92, 0xfc, 0x9c, 0x5c,
0x8c, 0xee, 0xa7, 0x0e, 0x6e, 0xac, 0x2a, 0xc7, 0x97, 0xdb, 0x33, 0x0d, 0x71, 0xa8, 0xe7, 0xa8,
0xa1, 0xb3, 0x62, 0x73, 0x97, 0x69, 0x15, 0x92, 0x03, 0x93, 0x68, 0xc8, 0xf3, 0xd0, 0x94, 0xc9,
0x99, 0x3a, 0xf8, 0x68, 0xb9, 0x36, 0x7d, 0x97, 0xca, 0xf4, 0x5d, 0x2a, 0xd7, 0x4c, 0x52, 0xa5,
0x58, 0x35, 0x31, 0x10, 0x5f, 0xa5, 0x4b, 0x09, 0x92, 0xe1, 0xb4, 0xca, 0x21, 0x64, 0x82, 0xd6,
0xb5, 0xc7, 0x16, 0x32, 0x84, 0x55, 0xf7, 0xfe, 0xa5, 0xff, 0xfb, 0x16, 0x32, 0xd4, 0x94, 0x68,
0x99, 0x0e, 0xae, 0xde, 0xf0, 0xc8, 0x8a, 0x0d, 0x5f, 0x70, 0x58, 0xf4, 0xbf, 0x39, 0x6c, 0xc1,
0x0b, 0xf2, 0xeb, 0x5e, 0xf8, 0x39, 0x02, 0x89, 0x2e, 0x3b, 0xc4, 0xc8, 0xfa, 0xff, 0x8e, 0xe1,
0x0e, 0x24, 0x5d, 0xc7, 0xd2, 0x78, 0x46, 0x66, 0x99, 0x84, 0xeb, 0x58, 0xea, 0x92, 0xcb, 0x62,
0xef, 0xf4, 0x8c, 0xae, 0xbf, 0x03, 0x05, 0xe3, 0xaf, 0x2b, 0xf8, 0x1d, 0xa4, 0xb9, 0x20, 0xe2,
0xb1, 0xfd, 0x9c, 0x2a, 0xc1, 0x5e, 0x70, 0xfe, 0xd6, 0x16, 0x56, 0x2d, 0x9e, 0xe3, 0x55, 0x81,
0xa6, 0x3c, 0xfe, 0x2a, 0x89, 0x97, 0xbf, 0xf0, 0xcf, 0x67, 0x41, 0x15, 0xe8, 0xd2, 0xaf, 0x12,
0x24, 0x59, 0xdb, 0xc7, 0x98, 0xa0, 0x05, 0xf1, 0xa4, 0xb7, 0x15, 0xef, 0x43, 0x00, 0x5e, 0xcc,
0x37, 0x9f, 0x62, 0xb1, 0xb1, 0x49, 0x16, 0xe9, 0x99, 0x4f, 0xb1, 0xf2, 0x65, 0xd8, 0x69, 0xf4,
0x4d, 0x3a, 0x15, 0x47, 0x37, 0xe8, 0xf7, 0x3a, 0xc4, 0xed, 0xc9, 0x58, 0xa3, 0xcf, 0x84, 0xcc,
0x2d, 0x63, 0x4f, 0xc6, 0xfd, 0x53, 0xff, 0xce, 0x2f, 0x12, 0xa4, 0xe6, 0x8e, 0x8f, 0x92, 0x87,
0x6b, 0xb5, 0xa3, 0x4e, 0xfd, 0x61, 0x43, 0x6b, 0x35, 0xb4, 0xfb, 0x47, 0xd5, 0x43, 0xed, 0xab,
0xf6, 0xc3, 0x76, 0xe7, 0xeb, 0x76, 0x76, 0x4d, 0xa9, 0xc0, 0x36, 0xcb, 0x85, 0xa9, 0x6a, 0xad,
0xd7, 0x6c, 0xf7, 0xb3, 0x52, 0xfe, 0xbd, 0xb3, 0xf3, 0xe2, 0xd6, 0x5c, 0x99, 0xea, 0xc0, 0xc7,
0x36, 0x59, 0x26, 0xd4, 0x3b, 0xc7, 0xc7, 0xad, 0x7e, 0x36, 0xb2, 0x44, 0x10, 0x37, 0xe4, 0x6d,
0xd8, 0x5a, 0x24, 0xb4, 0x5b, 0x47, 0xd9, 0x68, 0x5e, 0x39, 0x3b, 0x2f, 0x6e, 0xcc, 0xa1, 0xdb,
0xa6, 0x95, 0x4f, 0x7c, 0xff, 0xbc, 0xb0, 0xf6, 0xd3, 0x0f, 0x05, 0xe9, 0xce, 0x8f, 0x12, 0x64,
0x16, 0x4e, 0x89, 0xb2, 0x03, 0xd7, 0x7b, 0xad, 0xc3, 0x76, 0xb3, 0xa1, 0x1d, 0xf7, 0x0e, 0xb5,
0xfe, 0x37, 0xdd, 0xe6, 0x5c, 0x17, 0x37, 0x20, 0xdd, 0x55, 0x9b, 0x8f, 0x3a, 0xfd, 0x26, 0xcb,
0x64, 0xa5, 0xfc, 0xe6, 0xd9, 0x79, 0x31, 0xd5, 0xf5, 0xf0, 0x89, 0x43, 0x30, 0xe3, 0xdf, 0x84,
0x8d, 0xae, 0xda, 0xe4, 0x8b, 0xe5, 0xa0, 0x48, 0x7e, 0xeb, 0xec, 0xbc, 0x98, 0xe9, 0x7a, 0x98,
0x1b, 0x81, 0xc1, 0xf6, 0x20, 0xd3, 0x55, 0x3b, 0xdd, 0x4e, 0xaf, 0x7a, 0xc4, 0x51, 0xd1, 0x7c,
0xf6, 0xec, 0xbc, 0x98, 0x0e, 0x8e, 0x38, 0x05, 0xcd, 0xd6, 0x59, 0xbb, 0xff, 0xe2, 0xa2, 0x20,
0xbd, 0xbc, 0x28, 0x48, 0x7f, 0x5c, 0x14, 0xa4, 0x67, 0x97, 0x85, 0xb5, 0x97, 0x97, 0x85, 0xb5,
0xdf, 0x2e, 0x0b, 0x6b, 0xdf, 0xde, 0x35, 0x4c, 0x32, 0x9a, 0x0c, 0xca, 0x43, 0x67, 0x5c, 0x99,
0xed, 0xea, 0xfc, 0xe7, 0xdc, 0x8f, 0x8a, 0xc1, 0x3a, 0x1b, 0x7c, 0xf6, 0x77, 0x00, 0x00, 0x00,
0xff, 0xff, 0x94, 0x73, 0x22, 0x3b, 0x6a, 0x0c, 0x00, 0x00,
} }
func (m *PartSetHeader) Marshal() (dAtA []byte, err error) { func (m *PartSetHeader) Marshal() (dAtA []byte, err error) {


+ 2
- 2
proto/types/types.proto View File

@ -11,7 +11,7 @@ import "proto/version/version.proto";
// BlockIdFlag indicates which BlcokID the signature is for // BlockIdFlag indicates which BlcokID the signature is for
enum BlockIDFlag { enum BlockIDFlag {
option (gogoproto.goproto_enum_stringer) = false;
option (gogoproto.goproto_enum_stringer) = true;
option (gogoproto.goproto_enum_prefix) = false; option (gogoproto.goproto_enum_prefix) = false;
BLOCKD_ID_FLAG_UNKNOWN = 0; BLOCKD_ID_FLAG_UNKNOWN = 0;
@ -22,7 +22,7 @@ enum BlockIDFlag {
// SignedMsgType is a type of signed message in the consensus. // SignedMsgType is a type of signed message in the consensus.
enum SignedMsgType { enum SignedMsgType {
option (gogoproto.goproto_enum_stringer) = false;
option (gogoproto.goproto_enum_stringer) = true;
option (gogoproto.goproto_enum_prefix) = false; option (gogoproto.goproto_enum_prefix) = false;
SIGNED_MSG_TYPE_UNKNOWN = 0; SIGNED_MSG_TYPE_UNKNOWN = 0;


+ 11
- 3
rpc/client/evidence_test.go View File

@ -25,10 +25,14 @@ func newEvidence(t *testing.T, val *privval.FilePV,
chainID string) *types.DuplicateVoteEvidence { chainID string) *types.DuplicateVoteEvidence {
var err error var err error
vote.Signature, err = val.Key.PrivKey.Sign(vote.SignBytes(chainID))
v := vote.ToProto()
v2 := vote2.ToProto()
vote.Signature, err = val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v))
require.NoError(t, err) require.NoError(t, err)
vote2.Signature, err = val.Key.PrivKey.Sign(vote2.SignBytes(chainID))
vote2.Signature, err = val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v2))
require.NoError(t, err) require.NoError(t, err)
return types.NewDuplicateVoteEvidence(vote, vote2) return types.NewDuplicateVoteEvidence(vote, vote2)
@ -197,8 +201,12 @@ func TestBroadcastEvidence_ConflictingHeadersEvidence(t *testing.T) {
Type: tmproto.PrecommitType, Type: tmproto.PrecommitType,
BlockID: h2.Commit.BlockID, BlockID: h2.Commit.BlockID,
} }
signBytes, err := pv.Key.PrivKey.Sign(vote.SignBytes(chainID))
v := vote.ToProto()
signBytes, err := pv.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v))
require.NoError(t, err) require.NoError(t, err)
vote.Signature = v.Signature
h2.Commit.Signatures[0] = types.NewCommitSigForBlock(signBytes, pv.Key.Address, h2.Time) h2.Commit.Signatures[0] = types.NewCommitSigForBlock(signBytes, pv.Key.Address, h2.Time)
t.Logf("h1 AppHash: %X", h1.AppHash) t.Logf("h1 AppHash: %X", h1.AppHash)


+ 1
- 1
state/tx_filter_test.go View File

@ -26,7 +26,7 @@ func TestTxFilter(t *testing.T) {
isErr bool isErr bool
}{ }{
{types.Tx(tmrand.Bytes(1680)), false}, {types.Tx(tmrand.Bytes(1680)), false},
{types.Tx(tmrand.Bytes(1839)), true},
{types.Tx(tmrand.Bytes(1853)), true},
{types.Tx(tmrand.Bytes(3000)), true}, {types.Tx(tmrand.Bytes(3000)), true},
} }


+ 38
- 12
state/validation_test.go View File

@ -195,11 +195,17 @@ func TestValidateBlockCommit(t *testing.T) {
Type: tmproto.PrecommitType, Type: tmproto.PrecommitType,
BlockID: blockID, BlockID: blockID,
} }
err = badPrivVal.SignVote(chainID, goodVote)
g := goodVote.ToProto()
b := badVote.ToProto()
err = badPrivVal.SignVote(chainID, g)
require.NoError(t, err, "height %d", height) require.NoError(t, err, "height %d", height)
err = badPrivVal.SignVote(chainID, badVote)
err = badPrivVal.SignVote(chainID, b)
require.NoError(t, err, "height %d", height) require.NoError(t, err, "height %d", height)
goodVote.Signature, badVote.Signature = g.Signature, b.Signature
wrongSigsCommit = types.NewCommit(goodVote.Height, goodVote.Round, wrongSigsCommit = types.NewCommit(goodVote.Height, goodVote.Round,
blockID, []types.CommitSig{goodVote.CommitSig(), badVote.CommitSig()}) blockID, []types.CommitSig{goodVote.CommitSig(), badVote.CommitSig()})
} }
@ -358,10 +364,14 @@ func TestValidateAmnesiaEvidence(t *testing.T) {
state, stateDB, vals := makeState(1, int(height)) state, stateDB, vals := makeState(1, int(height))
addr, val := state.Validators.GetByIndex(0) addr, val := state.Validators.GetByIndex(0)
voteA := makeVote(height, 1, 0, addr, blockID) voteA := makeVote(height, 1, 0, addr, blockID)
err := vals[val.Address.String()].SignVote(chainID, voteA)
vA := voteA.ToProto()
err := vals[val.Address.String()].SignVote(chainID, vA)
voteA.Signature = vA.Signature
require.NoError(t, err) require.NoError(t, err)
voteB := makeVote(height, 2, 0, addr, types.BlockID{}) voteB := makeVote(height, 2, 0, addr, types.BlockID{})
err = vals[val.Address.String()].SignVote(chainID, voteB)
vB := voteB.ToProto()
err = vals[val.Address.String()].SignVote(chainID, vB)
voteB.Signature = vB.Signature
require.NoError(t, err) require.NoError(t, err)
ae := types.AmnesiaEvidence{ ae := types.AmnesiaEvidence{
PotentialAmnesiaEvidence: types.PotentialAmnesiaEvidence{ PotentialAmnesiaEvidence: types.PotentialAmnesiaEvidence{
@ -434,13 +444,19 @@ func TestVerifyEvidenceWithAmnesiaEvidence(t *testing.T) {
addr, val := state.Validators.GetByIndex(0) addr, val := state.Validators.GetByIndex(0)
addr2, val2 := state.Validators.GetByIndex(1) addr2, val2 := state.Validators.GetByIndex(1)
voteA := makeVote(height, 1, 0, addr, types.BlockID{}) voteA := makeVote(height, 1, 0, addr, types.BlockID{})
err := vals[val.Address.String()].SignVote(chainID, voteA)
vA := voteA.ToProto()
err := vals[val.Address.String()].SignVote(chainID, vA)
voteA.Signature = vA.Signature
require.NoError(t, err) require.NoError(t, err)
voteB := makeVote(height, 2, 0, addr, blockID) voteB := makeVote(height, 2, 0, addr, blockID)
err = vals[val.Address.String()].SignVote(chainID, voteB)
vB := voteB.ToProto()
err = vals[val.Address.String()].SignVote(chainID, vB)
voteB.Signature = vB.Signature
require.NoError(t, err) require.NoError(t, err)
voteC := makeVote(height, 2, 1, addr2, blockID) voteC := makeVote(height, 2, 1, addr2, blockID)
err = vals[val2.Address.String()].SignVote(chainID, voteC)
vC := voteC.ToProto()
err = vals[val2.Address.String()].SignVote(chainID, vC)
voteC.Signature = vC.Signature
require.NoError(t, err) require.NoError(t, err)
//var ae types.Evidence //var ae types.Evidence
badAe := types.AmnesiaEvidence{ badAe := types.AmnesiaEvidence{
@ -460,11 +476,15 @@ func TestVerifyEvidenceWithAmnesiaEvidence(t *testing.T) {
} }
addr3, val3 := state.Validators.GetByIndex(2) addr3, val3 := state.Validators.GetByIndex(2)
voteD := makeVote(height, 2, 2, addr3, blockID) voteD := makeVote(height, 2, 2, addr3, blockID)
err = vals[val3.Address.String()].SignVote(chainID, voteD)
vD := voteD.ToProto()
err = vals[val3.Address.String()].SignVote(chainID, vD)
require.NoError(t, err) require.NoError(t, err)
voteD.Signature = vD.Signature
addr4, val4 := state.Validators.GetByIndex(3) addr4, val4 := state.Validators.GetByIndex(3)
voteE := makeVote(height, 2, 3, addr4, blockID) voteE := makeVote(height, 2, 3, addr4, blockID)
err = vals[val4.Address.String()].SignVote(chainID, voteE)
vE := voteE.ToProto()
err = vals[val4.Address.String()].SignVote(chainID, vE)
voteE.Signature = vE.Signature
require.NoError(t, err) require.NoError(t, err)
goodAe := types.AmnesiaEvidence{ goodAe := types.AmnesiaEvidence{
@ -513,7 +533,9 @@ func TestVerifyEvidenceWithLunaticValidatorEvidence(t *testing.T) {
ProposerAddress: crypto.AddressHash([]byte("proposer_address")), ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
} }
vote := makeVote(3, 1, 0, addr, blockID) vote := makeVote(3, 1, 0, addr, blockID)
err := vals[val.Address.String()].SignVote(chainID, vote)
v := vote.ToProto()
err := vals[val.Address.String()].SignVote(chainID, v)
vote.Signature = v.Signature
require.NoError(t, err) require.NoError(t, err)
ev := types.LunaticValidatorEvidence{ ev := types.LunaticValidatorEvidence{
Header: h, Header: h,
@ -533,7 +555,9 @@ func TestVerifyEvidenceWithPhantomValidatorEvidence(t *testing.T) {
state.ConsensusParams.Evidence.MaxAgeNumBlocks = 1 state.ConsensusParams.Evidence.MaxAgeNumBlocks = 1
addr, val := state.Validators.GetByIndex(0) addr, val := state.Validators.GetByIndex(0)
vote := makeVote(3, 1, 0, addr, blockID) vote := makeVote(3, 1, 0, addr, blockID)
err := vals[val.Address.String()].SignVote(chainID, vote)
v := vote.ToProto()
err := vals[val.Address.String()].SignVote(chainID, v)
vote.Signature = v.Signature
require.NoError(t, err) require.NoError(t, err)
ev := types.PhantomValidatorEvidence{ ev := types.PhantomValidatorEvidence{
Vote: vote, Vote: vote,
@ -549,7 +573,9 @@ func TestVerifyEvidenceWithPhantomValidatorEvidence(t *testing.T) {
privVal := types.NewMockPV() privVal := types.NewMockPV()
pubKey, _ := privVal.GetPubKey() pubKey, _ := privVal.GetPubKey()
vote2 := makeVote(3, 1, 0, pubKey.Address(), blockID) vote2 := makeVote(3, 1, 0, pubKey.Address(), blockID)
err = privVal.SignVote(chainID, vote2)
v2 := vote2.ToProto()
err = privVal.SignVote(chainID, v2)
vote2.Signature = v2.Signature
require.NoError(t, err) require.NoError(t, err)
ev = types.PhantomValidatorEvidence{ ev = types.PhantomValidatorEvidence{
Vote: vote2, Vote: vote2,


+ 8
- 4
tools/tm-signer-harness/internal/test_harness.go View File

@ -229,11 +229,13 @@ func (th *TestHarness) TestSignProposal() error {
}, },
Timestamp: time.Now(), Timestamp: time.Now(),
} }
propBytes := prop.SignBytes(th.chainID)
if err := th.signerClient.SignProposal(th.chainID, prop); err != nil {
p := prop.ToProto()
propBytes := types.ProposalSignBytes(th.chainID, p)
if err := th.signerClient.SignProposal(th.chainID, p); err != nil {
th.logger.Error("FAILED: Signing of proposal", "err", err) th.logger.Error("FAILED: Signing of proposal", "err", err)
return newTestHarnessError(ErrTestSignProposalFailed, err, "") return newTestHarnessError(ErrTestSignProposalFailed, err, "")
} }
prop.Signature = p.Signature
th.logger.Debug("Signed proposal", "prop", prop) th.logger.Debug("Signed proposal", "prop", prop)
// first check that it's a basically valid proposal // first check that it's a basically valid proposal
if err := prop.ValidateBasic(); err != nil { if err := prop.ValidateBasic(); err != nil {
@ -276,12 +278,14 @@ func (th *TestHarness) TestSignVote() error {
ValidatorAddress: tmhash.SumTruncated([]byte("addr")), ValidatorAddress: tmhash.SumTruncated([]byte("addr")),
Timestamp: time.Now(), Timestamp: time.Now(),
} }
voteBytes := vote.SignBytes(th.chainID)
v := vote.ToProto()
voteBytes := types.VoteSignBytes(th.chainID, v)
// sign the vote // sign the vote
if err := th.signerClient.SignVote(th.chainID, vote); err != nil {
if err := th.signerClient.SignVote(th.chainID, v); err != nil {
th.logger.Error("FAILED: Signing of vote", "err", err) th.logger.Error("FAILED: Signing of vote", "err", err)
return newTestHarnessError(ErrTestSignVoteFailed, err, fmt.Sprintf("voteType=%d", voteType)) return newTestHarnessError(ErrTestSignVoteFailed, err, fmt.Sprintf("voteType=%d", voteType))
} }
vote.Signature = v.Signature
th.logger.Debug("Signed vote", "vote", vote) th.logger.Debug("Signed vote", "vote", vote)
// validate the contents of the vote // validate the contents of the vote
if err := vote.ValidateBasic(); err != nil { if err := vote.ValidateBasic(); err != nil {


+ 1
- 1
tools/tm-signer-harness/internal/test_harness_test.go View File

@ -23,7 +23,7 @@ const (
"pub_key": { "pub_key": {
"type": "tendermint/PubKeyEd25519", "type": "tendermint/PubKeyEd25519",
"value": "ZCsuTjaczEyon70nmKxwvwu+jqrbq5OH3yQjcK0SFxc=" "value": "ZCsuTjaczEyon70nmKxwvwu+jqrbq5OH3yQjcK0SFxc="
},
},
"priv_key": { "priv_key": {
"type": "tendermint/PrivKeyEd25519", "type": "tendermint/PrivKeyEd25519",
"value": "8O39AkQsoe1sBQwud/Kdul8lg8K9SFsql9aZvwXQSt1kKy5ONpzMTKifvSeYrHC/C76Oqturk4ffJCNwrRIXFw==" "value": "8O39AkQsoe1sBQwud/Kdul8lg8K9SFsql9aZvwXQSt1kKy5ONpzMTKifvSeYrHC/C76Oqturk4ffJCNwrRIXFw=="


+ 2
- 1
types/block.go View File

@ -773,7 +773,8 @@ func (commit *Commit) GetVote(valIdx int32) *Vote {
// signed over are otherwise the same for all validators. // signed over are otherwise the same for all validators.
// Panics if valIdx >= commit.Size(). // Panics if valIdx >= commit.Size().
func (commit *Commit) VoteSignBytes(chainID string, valIdx int32) []byte { func (commit *Commit) VoteSignBytes(chainID string, valIdx int32) []byte {
return commit.GetVote(valIdx).SignBytes(chainID)
v := commit.GetVote(valIdx).ToProto()
return VoteSignBytes(chainID, v)
} }
// Type returns the vote type of the commit, which is always VoteTypePrecommit // Type returns the vote type of the commit, which is always VoteTypePrecommit


+ 7
- 7
types/block_test.go View File

@ -378,9 +378,9 @@ func TestBlockMaxDataBytes(t *testing.T) {
}{ }{
0: {-10, 1, 0, true, 0}, 0: {-10, 1, 0, true, 0},
1: {10, 1, 0, true, 0}, 1: {10, 1, 0, true, 0},
2: {849, 1, 0, true, 0},
3: {850, 1, 0, false, 0},
4: {851, 1, 0, false, 1},
2: {846, 1, 0, true, 0},
3: {848, 1, 0, false, 0},
4: {849, 1, 0, false, 1},
} }
for i, tc := range testCases { for i, tc := range testCases {
@ -408,10 +408,10 @@ func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) {
}{ }{
0: {-10, 0, 1, true, 0}, 0: {-10, 0, 1, true, 0},
1: {10, 0, 1, true, 0}, 1: {10, 0, 1, true, 0},
2: {849, 0, 1, true, 0},
3: {850, 0, 1, false, 0},
4: {1294, 1, 1, false, 0},
5: {1295, 1, 1, false, 1},
2: {847, 0, 1, true, 0},
3: {848, 0, 1, false, 0},
4: {1292, 1, 1, false, 0},
5: {1293, 1, 1, false, 1},
} }
for i, tc := range testCases { for i, tc := range testCases {


+ 11
- 41
types/canonical.go View File

@ -3,7 +3,6 @@ package types
import ( import (
"time" "time"
"github.com/tendermint/tendermint/libs/bytes"
tmproto "github.com/tendermint/tendermint/proto/types" tmproto "github.com/tendermint/tendermint/proto/types"
tmtime "github.com/tendermint/tendermint/types/time" tmtime "github.com/tendermint/tendermint/types/time"
) )
@ -13,66 +12,37 @@ import (
// TimeFormat is used for generating the sigs // TimeFormat is used for generating the sigs
const TimeFormat = time.RFC3339Nano const TimeFormat = time.RFC3339Nano
type CanonicalBlockID struct {
Hash bytes.HexBytes
PartsHeader CanonicalPartSetHeader
}
type CanonicalPartSetHeader struct {
Hash bytes.HexBytes
Total uint32
}
type CanonicalProposal struct {
Type tmproto.SignedMsgType // type alias for byte
Height int64 `binary:"fixed64"`
Round int64 `binary:"fixed64"`
POLRound int64 `binary:"fixed64"`
BlockID CanonicalBlockID
Timestamp time.Time
ChainID string
}
type CanonicalVote struct {
Type tmproto.SignedMsgType // type alias for byte
Height int64 `binary:"fixed64"`
Round int64 `binary:"fixed64"`
BlockID CanonicalBlockID
Timestamp time.Time
ChainID string
}
//----------------------------------- //-----------------------------------
// Canonicalize the structs // Canonicalize the structs
func CanonicalizeBlockID(blockID BlockID) CanonicalBlockID {
return CanonicalBlockID{
func CanonicalizeBlockID(blockID tmproto.BlockID) tmproto.CanonicalBlockID {
return tmproto.CanonicalBlockID{
Hash: blockID.Hash, Hash: blockID.Hash,
PartsHeader: CanonicalizePartSetHeader(blockID.PartsHeader), PartsHeader: CanonicalizePartSetHeader(blockID.PartsHeader),
} }
} }
func CanonicalizePartSetHeader(psh PartSetHeader) CanonicalPartSetHeader {
return CanonicalPartSetHeader{
psh.Hash,
psh.Total,
func CanonicalizePartSetHeader(psh tmproto.PartSetHeader) tmproto.CanonicalPartSetHeader {
return tmproto.CanonicalPartSetHeader{
Hash: psh.Hash,
Total: psh.Total,
} }
} }
func CanonicalizeProposal(chainID string, proposal *Proposal) CanonicalProposal {
return CanonicalProposal{
func CanonicalizeProposal(chainID string, proposal *tmproto.Proposal) tmproto.CanonicalProposal {
return tmproto.CanonicalProposal{
Type: tmproto.ProposalType, Type: tmproto.ProposalType,
Height: proposal.Height, Height: proposal.Height,
Round: int64(proposal.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) Round: int64(proposal.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int)
POLRound: int64(proposal.POLRound),
POLRound: int64(proposal.PolRound),
BlockID: CanonicalizeBlockID(proposal.BlockID), BlockID: CanonicalizeBlockID(proposal.BlockID),
Timestamp: proposal.Timestamp, Timestamp: proposal.Timestamp,
ChainID: chainID, ChainID: chainID,
} }
} }
func CanonicalizeVote(chainID string, vote *Vote) CanonicalVote {
return CanonicalVote{
func CanonicalizeVote(chainID string, vote *tmproto.Vote) tmproto.CanonicalVote {
return tmproto.CanonicalVote{
Type: vote.Type, Type: vote.Type,
Height: vote.Height, Height: vote.Height,
Round: int64(vote.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) Round: int64(vote.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int)


+ 22
- 10
types/evidence.go View File

@ -463,12 +463,13 @@ func (dve *DuplicateVoteEvidence) Verify(chainID string, pubKey crypto.PubKey) e
return fmt.Errorf("address (%X) doesn't match pubkey (%v - %X)", return fmt.Errorf("address (%X) doesn't match pubkey (%v - %X)",
addr, pubKey, pubKey.Address()) addr, pubKey, pubKey.Address())
} }
va := dve.VoteA.ToProto()
vb := dve.VoteB.ToProto()
// Signatures must be valid // Signatures must be valid
if !pubKey.VerifyBytes(dve.VoteA.SignBytes(chainID), dve.VoteA.Signature) {
if !pubKey.VerifyBytes(VoteSignBytes(chainID, va), dve.VoteA.Signature) {
return fmt.Errorf("verifying VoteA: %w", ErrVoteInvalidSignature) return fmt.Errorf("verifying VoteA: %w", ErrVoteInvalidSignature)
} }
if !pubKey.VerifyBytes(dve.VoteB.SignBytes(chainID), dve.VoteB.Signature) {
if !pubKey.VerifyBytes(VoteSignBytes(chainID, vb), dve.VoteB.Signature) {
return fmt.Errorf("verifying VoteB: %w", ErrVoteInvalidSignature) return fmt.Errorf("verifying VoteB: %w", ErrVoteInvalidSignature)
} }
@ -841,8 +842,8 @@ func (e PhantomValidatorEvidence) Bytes() []byte {
func (e PhantomValidatorEvidence) Verify(chainID string, pubKey crypto.PubKey) error { func (e PhantomValidatorEvidence) Verify(chainID string, pubKey crypto.PubKey) error {
// signature must be verified to the chain ID
if !pubKey.VerifyBytes(e.Vote.SignBytes(chainID), e.Vote.Signature) {
v := e.Vote.ToProto()
if !pubKey.VerifyBytes(VoteSignBytes(chainID, v), e.Vote.Signature) {
return errors.New("invalid signature") return errors.New("invalid signature")
} }
@ -930,7 +931,8 @@ func (e LunaticValidatorEvidence) Verify(chainID string, pubKey crypto.PubKey) e
) )
} }
if !pubKey.VerifyBytes(e.Vote.SignBytes(chainID), e.Vote.Signature) {
v := e.Vote.ToProto()
if !pubKey.VerifyBytes(VoteSignBytes(chainID, v), e.Vote.Signature) {
return errors.New("invalid signature") return errors.New("invalid signature")
} }
@ -1072,11 +1074,14 @@ func (e PotentialAmnesiaEvidence) Verify(chainID string, pubKey crypto.PubKey) e
addr, pubKey, pubKey.Address()) addr, pubKey, pubKey.Address())
} }
va := e.VoteA.ToProto()
vb := e.VoteB.ToProto()
// Signatures must be valid // Signatures must be valid
if !pubKey.VerifyBytes(e.VoteA.SignBytes(chainID), e.VoteA.Signature) {
if !pubKey.VerifyBytes(VoteSignBytes(chainID, va), e.VoteA.Signature) {
return fmt.Errorf("verifying VoteA: %w", ErrVoteInvalidSignature) return fmt.Errorf("verifying VoteA: %w", ErrVoteInvalidSignature)
} }
if !pubKey.VerifyBytes(e.VoteB.SignBytes(chainID), e.VoteB.Signature) {
if !pubKey.VerifyBytes(VoteSignBytes(chainID, vb), e.VoteB.Signature) {
return fmt.Errorf("verifying VoteB: %w", ErrVoteInvalidSignature) return fmt.Errorf("verifying VoteB: %w", ErrVoteInvalidSignature)
} }
@ -1247,7 +1252,8 @@ func (e ProofOfLockChange) ValidateVotes(valSet *ValidatorSet, chainID string) e
for _, validator := range valSet.Validators { for _, validator := range valSet.Validators {
if bytes.Equal(validator.Address, vote.ValidatorAddress) { if bytes.Equal(validator.Address, vote.ValidatorAddress) {
exists = true exists = true
if !validator.PubKey.VerifyBytes(vote.SignBytes(chainID), vote.Signature) {
v := vote.ToProto()
if !validator.PubKey.VerifyBytes(VoteSignBytes(chainID, v), vote.Signature) {
return fmt.Errorf("cannot verify vote (from validator: %d) against signature: %v", return fmt.Errorf("cannot verify vote (from validator: %d) against signature: %v",
vote.ValidatorIndex, vote.Signature) vote.ValidatorIndex, vote.Signature)
} }
@ -1615,7 +1621,13 @@ func NewMockPOLC(height int64, time time.Time, pubKey crypto.PubKey) ProofOfLock
pKey, _ := voteVal.GetPubKey() pKey, _ := voteVal.GetPubKey()
vote := Vote{Type: tmproto.PrecommitType, Height: height, Round: 1, BlockID: BlockID{}, vote := Vote{Type: tmproto.PrecommitType, Height: height, Round: 1, BlockID: BlockID{},
Timestamp: time, ValidatorAddress: pKey.Address(), ValidatorIndex: 1, Signature: []byte{}} Timestamp: time, ValidatorAddress: pKey.Address(), ValidatorIndex: 1, Signature: []byte{}}
_ = voteVal.SignVote("mock-chain-id", &vote)
v := vote.ToProto()
if err := voteVal.SignVote("mock-chain-id", v); err != nil {
panic(err)
}
vote.Signature = v.Signature
return ProofOfLockChange{ return ProofOfLockChange{
Votes: []Vote{vote}, Votes: []Vote{vote},
PubKey: pubKey, PubKey: pubKey,


+ 11
- 3
types/evidence_test.go View File

@ -34,12 +34,17 @@ func TestEvidence(t *testing.T) {
const chainID = "mychain" const chainID = "mychain"
vote1 := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime) vote1 := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime)
err := val.SignVote(chainID, vote1)
v1 := vote1.ToProto()
err := val.SignVote(chainID, v1)
require.NoError(t, err) require.NoError(t, err)
badVote := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime) badVote := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime)
err = val2.SignVote(chainID, badVote)
bv := badVote.ToProto()
err = val2.SignVote(chainID, bv)
require.NoError(t, err) require.NoError(t, err)
vote1.Signature = v1.Signature
badVote.Signature = bv.Signature
cases := []voteData{ cases := []voteData{
{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, defaultVoteTime), true}, // different block ids {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, defaultVoteTime), true}, // different block ids
{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID3, defaultVoteTime), true}, {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID3, defaultVoteTime), true},
@ -542,10 +547,13 @@ func makeVote(
BlockID: blockID, BlockID: blockID,
Timestamp: time, Timestamp: time,
} }
err = val.SignVote(chainID, v)
vpb := v.ToProto()
err = val.SignVote(chainID, vpb)
if err != nil { if err != nil {
panic(err) panic(err)
} }
v.Signature = vpb.Signature
return v return v
} }


+ 11
- 8
types/priv_validator.go View File

@ -7,6 +7,7 @@ import (
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/ed25519"
tmproto "github.com/tendermint/tendermint/proto/types"
) )
// PrivValidator defines the functionality of a local Tendermint validator // PrivValidator defines the functionality of a local Tendermint validator
@ -14,8 +15,8 @@ import (
type PrivValidator interface { type PrivValidator interface {
GetPubKey() (crypto.PubKey, error) GetPubKey() (crypto.PubKey, error)
SignVote(chainID string, vote *Vote) error
SignProposal(chainID string, proposal *Proposal) error
SignVote(chainID string, vote *tmproto.Vote) error
SignProposal(chainID string, proposal *tmproto.Proposal) error
} }
type PrivValidatorsByAddress []PrivValidator type PrivValidatorsByAddress []PrivValidator
@ -71,12 +72,13 @@ func (pv MockPV) GetPubKey() (crypto.PubKey, error) {
} }
// Implements PrivValidator. // Implements PrivValidator.
func (pv MockPV) SignVote(chainID string, vote *Vote) error {
func (pv MockPV) SignVote(chainID string, vote *tmproto.Vote) error {
useChainID := chainID useChainID := chainID
if pv.breakVoteSigning { if pv.breakVoteSigning {
useChainID = "incorrect-chain-id" useChainID = "incorrect-chain-id"
} }
signBytes := vote.SignBytes(useChainID)
signBytes := VoteSignBytes(useChainID, vote)
sig, err := pv.PrivKey.Sign(signBytes) sig, err := pv.PrivKey.Sign(signBytes)
if err != nil { if err != nil {
return err return err
@ -86,12 +88,13 @@ func (pv MockPV) SignVote(chainID string, vote *Vote) error {
} }
// Implements PrivValidator. // Implements PrivValidator.
func (pv MockPV) SignProposal(chainID string, proposal *Proposal) error {
func (pv MockPV) SignProposal(chainID string, proposal *tmproto.Proposal) error {
useChainID := chainID useChainID := chainID
if pv.breakProposalSigning { if pv.breakProposalSigning {
useChainID = "incorrect-chain-id" useChainID = "incorrect-chain-id"
} }
signBytes := proposal.SignBytes(useChainID)
signBytes := ProposalSignBytes(useChainID, proposal)
sig, err := pv.PrivKey.Sign(signBytes) sig, err := pv.PrivKey.Sign(signBytes)
if err != nil { if err != nil {
return err return err
@ -128,12 +131,12 @@ type ErroringMockPV struct {
var ErroringMockPVErr = errors.New("erroringMockPV always returns an error") var ErroringMockPVErr = errors.New("erroringMockPV always returns an error")
// Implements PrivValidator. // Implements PrivValidator.
func (pv *ErroringMockPV) SignVote(chainID string, vote *Vote) error {
func (pv *ErroringMockPV) SignVote(chainID string, vote *tmproto.Vote) error {
return ErroringMockPVErr return ErroringMockPVErr
} }
// Implements PrivValidator. // Implements PrivValidator.
func (pv *ErroringMockPV) SignProposal(chainID string, proposal *Proposal) error {
func (pv *ErroringMockPV) SignProposal(chainID string, proposal *tmproto.Proposal) error {
return ErroringMockPVErr return ErroringMockPVErr
} }


+ 8
- 4
types/proposal.go View File

@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/gogo/protobuf/proto"
"github.com/tendermint/tendermint/libs/bytes" "github.com/tendermint/tendermint/libs/bytes"
tmproto "github.com/tendermint/tendermint/proto/types" tmproto "github.com/tendermint/tendermint/proto/types"
tmtime "github.com/tendermint/tendermint/types/time" tmtime "github.com/tendermint/tendermint/types/time"
@ -71,6 +73,7 @@ func (p *Proposal) ValidateBasic() error {
if len(p.Signature) == 0 { if len(p.Signature) == 0 {
return errors.New("signature is missing") return errors.New("signature is missing")
} }
if len(p.Signature) > MaxSignatureSize { if len(p.Signature) > MaxSignatureSize {
return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize)
} }
@ -88,9 +91,10 @@ func (p *Proposal) String() string {
CanonicalTime(p.Timestamp)) CanonicalTime(p.Timestamp))
} }
// SignBytes returns the Proposal bytes for signing
func (p *Proposal) SignBytes(chainID string) []byte {
bz, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeProposal(chainID, p))
// ProposalSignBytes returns the Proposal bytes for signing
func ProposalSignBytes(chainID string, p *tmproto.Proposal) []byte {
pb := CanonicalizeProposal(chainID, p)
bz, err := proto.Marshal(&pb)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -100,7 +104,7 @@ func (p *Proposal) SignBytes(chainID string) []byte {
// ToProto converts Proposal to protobuf // ToProto converts Proposal to protobuf
func (p *Proposal) ToProto() *tmproto.Proposal { func (p *Proposal) ToProto() *tmproto.Proposal {
if p == nil { if p == nil {
return nil
return &tmproto.Proposal{}
} }
pb := new(tmproto.Proposal) pb := new(tmproto.Proposal)


+ 33
- 17
types/proposal_test.go View File

@ -5,14 +5,19 @@ import (
"testing" "testing"
"time" "time"
"github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/crypto/tmhash"
tmrand "github.com/tendermint/tendermint/libs/rand"
tmproto "github.com/tendermint/tendermint/proto/types" tmproto "github.com/tendermint/tendermint/proto/types"
) )
var testProposal *Proposal
var (
testProposal *Proposal
pbp *tmproto.Proposal
)
func init() { func init() {
var stamp, err = time.Parse(TimeFormat, "2018-02-11T07:09:22.765Z") var stamp, err = time.Parse(TimeFormat, "2018-02-11T07:09:22.765Z")
@ -26,13 +31,14 @@ func init() {
POLRound: -1, POLRound: -1,
Timestamp: stamp, Timestamp: stamp,
} }
pbp = testProposal.ToProto()
} }
func TestProposalSignable(t *testing.T) { func TestProposalSignable(t *testing.T) {
chainID := "test_chain_id" chainID := "test_chain_id"
signBytes := testProposal.SignBytes(chainID)
expected, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeProposal(chainID, testProposal))
signBytes := ProposalSignBytes(chainID, pbp)
pb := CanonicalizeProposal(chainID, pbp)
expected, err := proto.Marshal(&pb)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Proposal") require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Proposal")
} }
@ -52,41 +58,49 @@ func TestProposalVerifySignature(t *testing.T) {
prop := NewProposal( prop := NewProposal(
4, 2, 2, 4, 2, 2,
BlockID{[]byte{1, 2, 3}, PartSetHeader{777, []byte("proper")}})
signBytes := prop.SignBytes("test_chain_id")
BlockID{tmrand.Bytes(tmhash.Size), PartSetHeader{777, tmrand.Bytes(tmhash.Size)}})
p := prop.ToProto()
signBytes := ProposalSignBytes("test_chain_id", p)
// sign it // sign it
err = privVal.SignProposal("test_chain_id", prop)
err = privVal.SignProposal("test_chain_id", p)
require.NoError(t, err) require.NoError(t, err)
prop.Signature = p.Signature
// verify the same proposal // verify the same proposal
valid := pubKey.VerifyBytes(signBytes, prop.Signature) valid := pubKey.VerifyBytes(signBytes, prop.Signature)
require.True(t, valid) require.True(t, valid)
// serialize, deserialize and verify again.... // serialize, deserialize and verify again....
newProp := new(Proposal)
bs, err := cdc.MarshalBinaryLengthPrefixed(prop)
newProp := new(tmproto.Proposal)
pb := prop.ToProto()
bs, err := proto.Marshal(pb)
require.NoError(t, err) require.NoError(t, err)
err = cdc.UnmarshalBinaryLengthPrefixed(bs, &newProp)
err = proto.Unmarshal(bs, newProp)
require.NoError(t, err)
np, err := ProposalFromProto(newProp)
require.NoError(t, err) require.NoError(t, err)
// verify the transmitted proposal // verify the transmitted proposal
newSignBytes := newProp.SignBytes("test_chain_id")
newSignBytes := ProposalSignBytes("test_chain_id", pb)
require.Equal(t, string(signBytes), string(newSignBytes)) require.Equal(t, string(signBytes), string(newSignBytes))
valid = pubKey.VerifyBytes(newSignBytes, newProp.Signature)
valid = pubKey.VerifyBytes(newSignBytes, np.Signature)
require.True(t, valid) require.True(t, valid)
} }
func BenchmarkProposalWriteSignBytes(b *testing.B) { func BenchmarkProposalWriteSignBytes(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
testProposal.SignBytes("test_chain_id")
ProposalSignBytes("test_chain_id", pbp)
} }
} }
func BenchmarkProposalSign(b *testing.B) { func BenchmarkProposalSign(b *testing.B) {
privVal := NewMockPV() privVal := NewMockPV()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
err := privVal.SignProposal("test_chain_id", testProposal)
err := privVal.SignProposal("test_chain_id", pbp)
if err != nil { if err != nil {
b.Error(err) b.Error(err)
} }
@ -95,13 +109,13 @@ func BenchmarkProposalSign(b *testing.B) {
func BenchmarkProposalVerifySignature(b *testing.B) { func BenchmarkProposalVerifySignature(b *testing.B) {
privVal := NewMockPV() privVal := NewMockPV()
err := privVal.SignProposal("test_chain_id", testProposal)
err := privVal.SignProposal("test_chain_id", pbp)
require.NoError(b, err) require.NoError(b, err)
pubKey, err := privVal.GetPubKey() pubKey, err := privVal.GetPubKey()
require.NoError(b, err) require.NoError(b, err)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
pubKey.VerifyBytes(testProposal.SignBytes("test_chain_id"), testProposal.Signature)
pubKey.VerifyBytes(ProposalSignBytes("test_chain_id", pbp), testProposal.Signature)
} }
} }
@ -136,7 +150,9 @@ func TestProposalValidateBasic(t *testing.T) {
prop := NewProposal( prop := NewProposal(
4, 2, 2, 4, 2, 2,
blockID) blockID)
err := privVal.SignProposal("test_chain_id", prop)
p := prop.ToProto()
err := privVal.SignProposal("test_chain_id", p)
prop.Signature = p.Signature
require.NoError(t, err) require.NoError(t, err)
tc.malleateProposal(prop) tc.malleateProposal(prop)
assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, "Validate Basic had an unexpected result") assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, "Validate Basic had an unexpected result")


+ 9
- 2
types/test_util.go View File

@ -36,10 +36,12 @@ func MakeCommit(blockID BlockID, height int64, round int32,
} }
func signAddVote(privVal PrivValidator, vote *Vote, voteSet *VoteSet) (signed bool, err error) { func signAddVote(privVal PrivValidator, vote *Vote, voteSet *VoteSet) (signed bool, err error) {
err = privVal.SignVote(voteSet.ChainID(), vote)
v := vote.ToProto()
err = privVal.SignVote(voteSet.ChainID(), v)
if err != nil { if err != nil {
return false, err return false, err
} }
vote.Signature = v.Signature
return voteSet.AddVote(vote) return voteSet.AddVote(vote)
} }
@ -66,9 +68,14 @@ func MakeVote(
Type: tmproto.PrecommitType, Type: tmproto.PrecommitType,
BlockID: blockID, BlockID: blockID,
} }
if err := privVal.SignVote(chainID, vote); err != nil {
v := vote.ToProto()
if err := privVal.SignVote(chainID, v); err != nil {
return nil, err return nil, err
} }
vote.Signature = v.Signature
return vote, nil return vote, nil
} }


+ 3
- 1
types/validator_set_test.go View File

@ -667,7 +667,9 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
Type: tmproto.PrecommitType, Type: tmproto.PrecommitType,
BlockID: blockID, BlockID: blockID,
} }
sig, err := privKey.Sign(vote.SignBytes(chainID))
v := vote.ToProto()
sig, err := privKey.Sign(VoteSignBytes(chainID, v))
assert.NoError(t, err) assert.NoError(t, err)
vote.Signature = sig vote.Signature = sig
commit := NewCommit(vote.Height, vote.Round, blockID, []CommitSig{vote.CommitSig()}) commit := NewCommit(vote.Height, vote.Round, blockID, []CommitSig{vote.CommitSig()})


+ 14
- 5
types/vote.go View File

@ -6,6 +6,8 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/gogo/protobuf/proto"
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
tmbytes "github.com/tendermint/tendermint/libs/bytes" tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmproto "github.com/tendermint/tendermint/proto/types" tmproto "github.com/tendermint/tendermint/proto/types"
@ -13,7 +15,7 @@ import (
const ( const (
// MaxVoteBytes is a maximum vote size (including amino overhead). // MaxVoteBytes is a maximum vote size (including amino overhead).
MaxVoteBytes int64 = 211
MaxVoteBytes int64 = 209
nilVoteStr string = "nil-Vote" nilVoteStr string = "nil-Vote"
) )
@ -81,8 +83,11 @@ func (vote *Vote) CommitSig() CommitSig {
} }
} }
func (vote *Vote) SignBytes(chainID string) []byte {
bz, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeVote(chainID, vote))
//VoteSignBytes take the chainID & a vote, represented in protobuf, and creates a signature.
// If any error arises this will panic
func VoteSignBytes(chainID string, vote *tmproto.Vote) []byte {
pb := CanonicalizeVote(chainID, vote)
bz, err := proto.Marshal(&pb)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -126,8 +131,8 @@ func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
if !bytes.Equal(pubKey.Address(), vote.ValidatorAddress) { if !bytes.Equal(pubKey.Address(), vote.ValidatorAddress) {
return ErrVoteInvalidValidatorAddress return ErrVoteInvalidValidatorAddress
} }
if !pubKey.VerifyBytes(vote.SignBytes(chainID), vote.Signature) {
v := vote.ToProto()
if !pubKey.VerifyBytes(VoteSignBytes(chainID, v), vote.Signature) {
return ErrVoteInvalidSignature return ErrVoteInvalidSignature
} }
return nil return nil
@ -152,11 +157,13 @@ func (vote *Vote) ValidateBasic() error {
if err := vote.BlockID.ValidateBasic(); err != nil { if err := vote.BlockID.ValidateBasic(); err != nil {
return fmt.Errorf("wrong BlockID: %v", err) return fmt.Errorf("wrong BlockID: %v", err)
} }
// BlockID.ValidateBasic would not err if we for instance have an empty hash but a // BlockID.ValidateBasic would not err if we for instance have an empty hash but a
// non-empty PartsSetHeader: // non-empty PartsSetHeader:
if !vote.BlockID.IsZero() && !vote.BlockID.IsComplete() { if !vote.BlockID.IsZero() && !vote.BlockID.IsComplete() {
return fmt.Errorf("blockID must be either empty or complete, got: %v", vote.BlockID) return fmt.Errorf("blockID must be either empty or complete, got: %v", vote.BlockID)
} }
if len(vote.ValidatorAddress) != crypto.AddressSize { if len(vote.ValidatorAddress) != crypto.AddressSize {
return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes", return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes",
crypto.AddressSize, crypto.AddressSize,
@ -169,9 +176,11 @@ func (vote *Vote) ValidateBasic() error {
if len(vote.Signature) == 0 { if len(vote.Signature) == 0 {
return errors.New("signature is missing") return errors.New("signature is missing")
} }
if len(vote.Signature) > MaxSignatureSize { if len(vote.Signature) > MaxSignatureSize {
return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize)
} }
return nil return nil
} }


+ 40
- 63
types/vote_test.go View File

@ -5,6 +5,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -47,9 +48,11 @@ func exampleVote(t byte) *Vote {
func TestVoteSignable(t *testing.T) { func TestVoteSignable(t *testing.T) {
vote := examplePrecommit() vote := examplePrecommit()
signBytes := vote.SignBytes("test_chain_id")
v := vote.ToProto()
signBytes := VoteSignBytes("test_chain_id", v)
pb := CanonicalizeVote("test_chain_id", v)
expected, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeVote("test_chain_id", vote))
expected, err := proto.Marshal(&pb)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Vote.") require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Vote.")
@ -65,79 +68,47 @@ func TestVoteSignBytesTestVectors(t *testing.T) {
0: { 0: {
"", &Vote{}, "", &Vote{},
// NOTE: Height and Round are skipped here. This case needs to be considered while parsing. // NOTE: Height and Round are skipped here. This case needs to be considered while parsing.
[]byte{0xd, 0x2a, 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1},
[]byte{0x2a, 0x2, 0x12, 0x0, 0x32, 0xb, 0x8, 0x80, 0x92, 0xb8,
0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1},
}, },
// with proper (fixed size) height and round (PreCommit): // with proper (fixed size) height and round (PreCommit):
1: { 1: {
"", &Vote{Height: 1, Round: 1, Type: tmproto.PrecommitType}, "", &Vote{Height: 1, Round: 1, Type: tmproto.PrecommitType},
[]byte{
0x21, // length
0x8, // (field_number << 3) | wire_type
0x2, // PrecommitType
0x11, // (field_number << 3) | wire_type
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height
0x19, // (field_number << 3) | wire_type
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round
0x2a, // (field_number << 3) | wire_type
// remaining fields (timestamp):
[]byte{0x8, 0x2, 0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0, 0x32,
0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1},
}, },
// with proper (fixed size) height and round (PreVote): // with proper (fixed size) height and round (PreVote):
2: { 2: {
"", &Vote{Height: 1, Round: 1, Type: tmproto.PrevoteType}, "", &Vote{Height: 1, Round: 1, Type: tmproto.PrevoteType},
[]byte{
0x21, // length
0x8, // (field_number << 3) | wire_type
0x1, // PrevoteType
0x11, // (field_number << 3) | wire_type
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height
0x19, // (field_number << 3) | wire_type
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round
0x2a, // (field_number << 3) | wire_type
// remaining fields (timestamp):
0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1},
[]byte{0x8, 0x1, 0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0,
0x32, 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1},
}, },
3: { 3: {
"", &Vote{Height: 1, Round: 1}, "", &Vote{Height: 1, Round: 1},
[]byte{
0x1f, // length
0x11, // (field_number << 3) | wire_type
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height
0x19, // (field_number << 3) | wire_type
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round
// remaining fields (timestamp):
0x2a,
0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1},
[]byte{0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0, 0x32, 0xb,
0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1},
}, },
// containing non-empty chain_id: // containing non-empty chain_id:
4: { 4: {
"test_chain_id", &Vote{Height: 1, Round: 1}, "test_chain_id", &Vote{Height: 1, Round: 1},
[]byte{
0x2e, // length
0x11, // (field_number << 3) | wire_type
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height
0x19, // (field_number << 3) | wire_type
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round
// remaining fields:
0x2a, // (field_number << 3) | wire_type
0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, // timestamp
// (field_number << 3) | wire_type
0x32,
0xd, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64}, // chainID
[]byte{0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0, 0x32, 0xb, 0x8,
0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, 0x3a, 0xd,
0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64},
}, },
} }
for i, tc := range tests { for i, tc := range tests {
got := tc.vote.SignBytes(tc.chainID)
v := tc.vote.ToProto()
got := VoteSignBytes(tc.chainID, v)
require.Equal(t, tc.want, got, "test case #%v: got unexpected sign bytes for Vote.", i) require.Equal(t, tc.want, got, "test case #%v: got unexpected sign bytes for Vote.", i)
} }
} }
func TestVoteProposalNotEq(t *testing.T) { func TestVoteProposalNotEq(t *testing.T) {
cv := CanonicalizeVote("", &Vote{Height: 1, Round: 1})
p := CanonicalizeProposal("", &Proposal{Height: 1, Round: 1})
vb, err := cdc.MarshalBinaryLengthPrefixed(cv)
cv := CanonicalizeVote("", &tmproto.Vote{Height: 1, Round: 1})
p := CanonicalizeProposal("", &tmproto.Proposal{Height: 1, Round: 1})
vb, err := proto.Marshal(&cv)
require.NoError(t, err) require.NoError(t, err)
pb, err := cdc.MarshalBinaryLengthPrefixed(p)
pb, err := proto.Marshal(&p)
require.NoError(t, err) require.NoError(t, err)
require.NotEqual(t, vb, pb) require.NotEqual(t, vb, pb)
} }
@ -148,25 +119,26 @@ func TestVoteVerifySignature(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
vote := examplePrecommit() vote := examplePrecommit()
signBytes := vote.SignBytes("test_chain_id")
v := vote.ToProto()
signBytes := VoteSignBytes("test_chain_id", v)
// sign it // sign it
err = privVal.SignVote("test_chain_id", vote)
err = privVal.SignVote("test_chain_id", v)
require.NoError(t, err) require.NoError(t, err)
// verify the same vote // verify the same vote
valid := pubkey.VerifyBytes(vote.SignBytes("test_chain_id"), vote.Signature)
valid := pubkey.VerifyBytes(VoteSignBytes("test_chain_id", v), v.Signature)
require.True(t, valid) require.True(t, valid)
// serialize, deserialize and verify again.... // serialize, deserialize and verify again....
precommit := new(Vote)
bs, err := cdc.MarshalBinaryLengthPrefixed(vote)
precommit := new(tmproto.Vote)
bs, err := proto.Marshal(v)
require.NoError(t, err) require.NoError(t, err)
err = cdc.UnmarshalBinaryLengthPrefixed(bs, &precommit)
err = proto.Unmarshal(bs, precommit)
require.NoError(t, err) require.NoError(t, err)
// verify the transmitted vote // verify the transmitted vote
newSignBytes := precommit.SignBytes("test_chain_id")
newSignBytes := VoteSignBytes("test_chain_id", precommit)
require.Equal(t, string(signBytes), string(newSignBytes)) require.Equal(t, string(signBytes), string(newSignBytes))
valid = pubkey.VerifyBytes(newSignBytes, precommit.Signature) valid = pubkey.VerifyBytes(newSignBytes, precommit.Signature)
require.True(t, valid) require.True(t, valid)
@ -233,11 +205,12 @@ func TestMaxVoteBytes(t *testing.T) {
}, },
} }
v := vote.ToProto()
privVal := NewMockPV() privVal := NewMockPV()
err := privVal.SignVote("test_chain_id", vote)
err := privVal.SignVote("test_chain_id", v)
require.NoError(t, err) require.NoError(t, err)
bz, err := cdc.MarshalBinaryLengthPrefixed(vote)
bz, err := proto.Marshal(v)
require.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, MaxVoteBytes, len(bz)) assert.EqualValues(t, MaxVoteBytes, len(bz))
@ -245,13 +218,13 @@ func TestMaxVoteBytes(t *testing.T) {
func TestVoteString(t *testing.T) { func TestVoteString(t *testing.T) {
str := examplePrecommit().String() str := examplePrecommit().String()
expected := `Vote{56789:6AF1F4111082 12345/02/2(Precommit) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}`
expected := `Vote{56789:6AF1F4111082 12345/02/PRECOMMIT_TYPE(Precommit) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` //nolint:lll //ignore line length for tests
if str != expected { if str != expected {
t.Errorf("got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str) t.Errorf("got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str)
} }
str2 := examplePrevote().String() str2 := examplePrevote().String()
expected = `Vote{56789:6AF1F4111082 12345/02/1(Prevote) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}`
expected = `Vote{56789:6AF1F4111082 12345/02/PREVOTE_TYPE(Prevote) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` //nolint:lll //ignore line length for tests
if str2 != expected { if str2 != expected {
t.Errorf("got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str2) t.Errorf("got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str2)
} }
@ -280,7 +253,9 @@ func TestVoteValidateBasic(t *testing.T) {
tc := tc tc := tc
t.Run(tc.testName, func(t *testing.T) { t.Run(tc.testName, func(t *testing.T) {
vote := examplePrecommit() vote := examplePrecommit()
err := privVal.SignVote("test_chain_id", vote)
v := vote.ToProto()
err := privVal.SignVote("test_chain_id", v)
vote.Signature = v.Signature
require.NoError(t, err) require.NoError(t, err)
tc.malleateVote(vote) tc.malleateVote(vote)
assert.Equal(t, tc.expectErr, vote.ValidateBasic() != nil, "Validate Basic had an unexpected result") assert.Equal(t, tc.expectErr, vote.ValidateBasic() != nil, "Validate Basic had an unexpected result")
@ -291,7 +266,9 @@ func TestVoteValidateBasic(t *testing.T) {
func TestVoteProtobuf(t *testing.T) { func TestVoteProtobuf(t *testing.T) {
privVal := NewMockPV() privVal := NewMockPV()
vote := examplePrecommit() vote := examplePrecommit()
err := privVal.SignVote("test_chain_id", vote)
v := vote.ToProto()
err := privVal.SignVote("test_chain_id", v)
vote.Signature = v.Signature
require.NoError(t, err) require.NoError(t, err)
testCases := []struct { testCases := []struct {


Loading…
Cancel
Save