mirror of
https://github.com/tendermint/tendermint.git
synced 2026-07-19 22:42:24 +00:00
privval: migrate to protobuf (#4985)
This commit is contained in:
@@ -49,6 +49,8 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
|
||||
- [store] \#4778 Transition store module to protobuf encoding
|
||||
- `BlockStoreStateJSON` is now `BlockStoreState` and is encoded as binary in the database
|
||||
- [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
|
||||
|
||||
- Apps
|
||||
|
||||
@@ -69,7 +69,10 @@ func makeVote(
|
||||
BlockID: blockID,
|
||||
}
|
||||
|
||||
_ = privVal.SignVote(header.ChainID, vote)
|
||||
vpb := vote.ToProto()
|
||||
|
||||
_ = privVal.SignVote(header.ChainID, vpb)
|
||||
vote.Signature = vpb.Signature
|
||||
|
||||
return vote
|
||||
}
|
||||
|
||||
@@ -181,18 +181,24 @@ func byzantineDecideProposalFunc(t *testing.T, height int64, round int32, cs *St
|
||||
block1, blockParts1 := cs.createProposalBlock()
|
||||
polRound, propBlockID := cs.ValidRound, types.BlockID{Hash: block1.Hash(), PartsHeader: blockParts1.Header()}
|
||||
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)
|
||||
}
|
||||
|
||||
proposal1.Signature = p1.Signature
|
||||
|
||||
// Create a new proposal block from state/txs from the mempool.
|
||||
block2, blockParts2 := cs.createProposalBlock()
|
||||
polRound, propBlockID = cs.ValidRound, types.BlockID{Hash: block2.Hash(), PartsHeader: blockParts2.Header()}
|
||||
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)
|
||||
}
|
||||
|
||||
proposal2.Signature = p2.Signature
|
||||
|
||||
block1Hash := block1.Hash()
|
||||
block2Hash := block2.Hash()
|
||||
|
||||
|
||||
@@ -105,8 +105,10 @@ func (vs *validatorStub) signVote(
|
||||
Type: voteType,
|
||||
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
|
||||
}
|
||||
|
||||
@@ -200,9 +202,13 @@ func decideProposal(
|
||||
// Make proposal
|
||||
polRound, propBlockID := validRound, types.BlockID{Hash: block.Hash(), PartsHeader: blockParts.Header()}
|
||||
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)
|
||||
}
|
||||
|
||||
proposal.Signature = p.Signature
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -360,10 +360,13 @@ func TestSimulateValidatorsChange(t *testing.T) {
|
||||
propBlock, _ := css[0].createProposalBlock() //changeProposer(t, cs1, vs2)
|
||||
propBlockParts := propBlock.MakePartSet(partSize)
|
||||
blockID := types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()}
|
||||
|
||||
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)
|
||||
}
|
||||
proposal.Signature = p.Signature
|
||||
|
||||
// set the proposal block
|
||||
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)
|
||||
propBlockParts = propBlock.MakePartSet(partSize)
|
||||
blockID = types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()}
|
||||
|
||||
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)
|
||||
}
|
||||
proposal.Signature = p.Signature
|
||||
|
||||
// set the proposal block
|
||||
if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil {
|
||||
@@ -447,9 +453,11 @@ func TestSimulateValidatorsChange(t *testing.T) {
|
||||
selfIndex := valIndexFn(0)
|
||||
|
||||
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)
|
||||
}
|
||||
proposal.Signature = p.Signature
|
||||
|
||||
// set the proposal block
|
||||
if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil {
|
||||
@@ -508,9 +516,11 @@ func TestSimulateValidatorsChange(t *testing.T) {
|
||||
|
||||
selfIndex = valIndexFn(0)
|
||||
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)
|
||||
}
|
||||
proposal.Signature = p.Signature
|
||||
|
||||
// set the proposal block
|
||||
if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil {
|
||||
|
||||
+9
-3
@@ -1032,7 +1032,9 @@ func (cs *State) defaultDecideProposal(height int64, round int32) {
|
||||
// Make proposal
|
||||
propBlockID := types.BlockID{Hash: block.Hash(), PartsHeader: blockParts.Header()}
|
||||
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
|
||||
cs.sendInternalMessage(msgInfo{&ProposalMessage{proposal}, ""})
|
||||
@@ -1683,11 +1685,13 @@ func (cs *State) defaultSetProposal(proposal *types.Proposal) error {
|
||||
return ErrInvalidProposalPOLRound
|
||||
}
|
||||
|
||||
p := proposal.ToProto()
|
||||
// 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
|
||||
}
|
||||
|
||||
proposal.Signature = p.Signature
|
||||
cs.Proposal = proposal
|
||||
// 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.
|
||||
@@ -2008,8 +2012,10 @@ func (cs *State) signVote(
|
||||
Type: msgType,
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -205,10 +205,13 @@ func TestStateBadProposal(t *testing.T) {
|
||||
propBlockParts := propBlock.MakePartSet(partSize)
|
||||
blockID := types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()}
|
||||
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)
|
||||
}
|
||||
|
||||
proposal.Signature = p.Signature
|
||||
|
||||
// set the proposal block
|
||||
if err := cs1.SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -1034,9 +1037,13 @@ func TestStateLockPOLSafety2(t *testing.T) {
|
||||
round++ // moving to the next round
|
||||
// in round 2 we see the polkad block from round 0
|
||||
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)
|
||||
}
|
||||
|
||||
newProp.Signature = p.Signature
|
||||
|
||||
if err := cs1.SetProposalAndBlock(newProp, propBlock0, propBlockParts0, "some peer"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -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{}},
|
||||
}
|
||||
chainID := config.ChainID()
|
||||
err = privVal.SignVote(chainID, vote)
|
||||
|
||||
v := vote.ToProto()
|
||||
err = privVal.SignVote(chainID, v)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Error signing vote: %v", err))
|
||||
}
|
||||
|
||||
vote.Signature = v.Signature
|
||||
|
||||
return vote
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ func (pubKey PubKey) VerifyBytes(msg []byte, sig []byte) bool {
|
||||
if len(sig) != SignatureSize {
|
||||
return false
|
||||
}
|
||||
|
||||
return ed25519.Verify(ed25519.PublicKey(pubKey), msg, sig)
|
||||
}
|
||||
|
||||
|
||||
@@ -331,14 +331,20 @@ func TestPotentialAmnesiaEvidence(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
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)
|
||||
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)
|
||||
voteC := makeVote(25, 0, 0, pubKey.Address(), firstBlockID)
|
||||
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)
|
||||
ev := types.PotentialAmnesiaEvidence{
|
||||
VoteA: voteA,
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
var ErrOverflowInt32 = errors.New("int32 overflow")
|
||||
var ErrOverflowUint8 = errors.New("uint8 overflow")
|
||||
var ErrOverflowInt8 = errors.New("int8 overflow")
|
||||
|
||||
// SafeAddInt32 adds two int32 integers
|
||||
// If there is an overflow this will panic
|
||||
@@ -51,3 +52,14 @@ func SafeConvertUint8(a int64) (uint8, error) {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -108,13 +108,15 @@ func makeVote(header *types.Header, valset *types.ValidatorSet,
|
||||
Type: tmproto.PrecommitType,
|
||||
BlockID: blockID,
|
||||
}
|
||||
|
||||
v := vote.ToProto()
|
||||
// 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)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
vote.Signature = sig
|
||||
|
||||
return vote
|
||||
|
||||
@@ -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
@@ -1,6 +1,7 @@
|
||||
package privval
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
@@ -13,12 +14,12 @@ func (e EndpointTimeoutError) Temporary() bool { return true }
|
||||
|
||||
// Socket errors.
|
||||
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{}
|
||||
|
||||
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.
|
||||
|
||||
+18
-19
@@ -7,6 +7,8 @@ import (
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
tmbytes "github.com/tendermint/tendermint/libs/bytes"
|
||||
@@ -27,7 +29,7 @@ const (
|
||||
)
|
||||
|
||||
// A vote is either stepPrevote or stepPrecommit.
|
||||
func voteToStep(vote *types.Vote) int8 {
|
||||
func voteToStep(vote *tmproto.Vote) int8 {
|
||||
switch vote.Type {
|
||||
case tmproto.PrevoteType:
|
||||
return stepPrevote
|
||||
@@ -199,6 +201,7 @@ func loadFilePV(keyFilePath, stateFilePath string, loadState bool) *FilePV {
|
||||
pvKey.filePath = keyFilePath
|
||||
|
||||
pvState := FilePVLastSignState{}
|
||||
|
||||
if loadState {
|
||||
stateJSONBytes, err := ioutil.ReadFile(stateFilePath)
|
||||
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
|
||||
// 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 {
|
||||
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
|
||||
// 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 {
|
||||
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.
|
||||
// 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).
|
||||
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)
|
||||
|
||||
lss := pv.LastSignState
|
||||
@@ -305,7 +308,7 @@ func (pv *FilePV) signVote(chainID string, vote *types.Vote) error {
|
||||
return err
|
||||
}
|
||||
|
||||
signBytes := vote.SignBytes(chainID)
|
||||
signBytes := types.VoteSignBytes(chainID, vote)
|
||||
|
||||
// We might crash before writing to the wal,
|
||||
// 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.
|
||||
// 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).
|
||||
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
|
||||
|
||||
lss := pv.LastSignState
|
||||
@@ -347,7 +350,7 @@ func (pv *FilePV) signProposal(chainID string, proposal *types.Proposal) error {
|
||||
return err
|
||||
}
|
||||
|
||||
signBytes := proposal.SignBytes(chainID)
|
||||
signBytes := types.ProposalSignBytes(chainID, proposal)
|
||||
|
||||
// We might crash before writing to the wal,
|
||||
// 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 true if the only difference in the votes is their timestamp.
|
||||
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))
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
||||
@@ -407,20 +410,18 @@ func checkVotesOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.T
|
||||
now := tmtime.Now()
|
||||
lastVote.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 true if the only difference in the proposals is their timestamp
|
||||
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))
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
||||
@@ -429,8 +430,6 @@ func checkProposalsOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (ti
|
||||
now := tmtime.Now()
|
||||
lastProposal.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
@@ -52,10 +52,10 @@ func TestResetValidator(t *testing.T) {
|
||||
|
||||
// test vote
|
||||
height, round := int64(10), int32(1)
|
||||
voteType := byte(tmproto.PrevoteType)
|
||||
voteType := tmproto.PrevoteType
|
||||
blockID := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{}}
|
||||
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")
|
||||
|
||||
// priv val after signing is not same as empty
|
||||
@@ -121,8 +121,8 @@ func TestUnmarshalValidatorKey(t *testing.T) {
|
||||
privKey := ed25519.GenPrivKey()
|
||||
pubKey := privKey.PubKey()
|
||||
addr := pubKey.Address()
|
||||
pubBytes := []byte(pubKey.(ed25519.PubKey))
|
||||
privBytes := []byte(privKey)
|
||||
pubBytes := pubKey.Bytes()
|
||||
privBytes := privKey.Bytes()
|
||||
pubB64 := base64.StdEncoding.EncodeToString(pubBytes)
|
||||
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{}}
|
||||
|
||||
height, round := int64(10), int32(1)
|
||||
voteType := byte(tmproto.PrevoteType)
|
||||
voteType := tmproto.PrevoteType
|
||||
|
||||
// sign a vote for first time
|
||||
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")
|
||||
|
||||
// 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")
|
||||
|
||||
// now try some bad votes
|
||||
@@ -187,14 +188,15 @@ func TestSignVote(t *testing.T) {
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// try signing a vote with a different time stamp
|
||||
sig := vote.Signature
|
||||
vote.Timestamp = vote.Timestamp.Add(time.Duration(1000))
|
||||
err = privVal.SignVote("mychainid", vote)
|
||||
err = privVal.SignVote("mychainid", v)
|
||||
assert.NoError(err)
|
||||
assert.Equal(sig, vote.Signature)
|
||||
}
|
||||
@@ -215,11 +217,12 @@ func TestSignProposal(t *testing.T) {
|
||||
|
||||
// sign a proposal for first time
|
||||
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")
|
||||
|
||||
// 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")
|
||||
|
||||
// now try some bad Proposals
|
||||
@@ -231,14 +234,14 @@ func TestSignProposal(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
err = privVal.SignProposal("mychainid", c)
|
||||
err = privVal.SignProposal("mychainid", c.ToProto())
|
||||
assert.Error(err, "expected error on signing conflicting proposal")
|
||||
}
|
||||
|
||||
// try signing a proposal with a different time stamp
|
||||
sig := proposal.Signature
|
||||
proposal.Timestamp = proposal.Timestamp.Add(time.Duration(1000))
|
||||
err = privVal.SignProposal("mychainid", proposal)
|
||||
err = privVal.SignProposal("mychainid", pbp)
|
||||
assert.NoError(err)
|
||||
assert.Equal(sig, proposal.Signature)
|
||||
}
|
||||
@@ -258,56 +261,60 @@ func TestDifferByTimestamp(t *testing.T) {
|
||||
// test proposal
|
||||
{
|
||||
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")
|
||||
signBytes := proposal.SignBytes(chainID)
|
||||
signBytes := types.ProposalSignBytes(chainID, pb)
|
||||
|
||||
sig := proposal.Signature
|
||||
timeStamp := proposal.Timestamp
|
||||
|
||||
// manipulate the timestamp. should get changed back
|
||||
proposal.Timestamp = proposal.Timestamp.Add(time.Millisecond)
|
||||
pb.Timestamp = pb.Timestamp.Add(time.Millisecond)
|
||||
var emptySig []byte
|
||||
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.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)
|
||||
}
|
||||
|
||||
// test vote
|
||||
{
|
||||
voteType := byte(tmproto.PrevoteType)
|
||||
voteType := tmproto.PrevoteType
|
||||
blockID := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{}}
|
||||
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")
|
||||
|
||||
signBytes := vote.SignBytes(chainID)
|
||||
sig := vote.Signature
|
||||
signBytes := types.VoteSignBytes(chainID, v)
|
||||
sig := v.Signature
|
||||
timeStamp := vote.Timestamp
|
||||
|
||||
// manipulate the timestamp. should get changed back
|
||||
vote.Timestamp = vote.Timestamp.Add(time.Millisecond)
|
||||
v.Timestamp = v.Timestamp.Add(time.Millisecond)
|
||||
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.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{
|
||||
ValidatorAddress: addr,
|
||||
ValidatorIndex: idx,
|
||||
Height: height,
|
||||
Round: round,
|
||||
Type: tmproto.SignedMsgType(typ),
|
||||
Type: typ,
|
||||
Timestamp: tmtime.Now(),
|
||||
BlockID: blockID,
|
||||
}
|
||||
|
||||
+29
-54
@@ -1,65 +1,40 @@
|
||||
package privval
|
||||
|
||||
import (
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"fmt"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
privvalproto "github.com/tendermint/tendermint/proto/privval"
|
||||
)
|
||||
|
||||
// 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)
|
||||
|
||||
cdc.RegisterConcrete(&PingRequest{}, "tendermint/remotesigner/PingRequest", nil)
|
||||
cdc.RegisterConcrete(&PingResponse{}, "tendermint/remotesigner/PingResponse", nil)
|
||||
}
|
||||
|
||||
// TODO: Add ChainIDRequest
|
||||
|
||||
// PubKeyRequest requests the consensus public key from the remote signer.
|
||||
type PubKeyRequest struct{}
|
||||
func mustWrapMsg(pb proto.Message) privvalproto.Message {
|
||||
msg := privvalproto.Message{}
|
||||
|
||||
// PubKeyResponse is a response message containing the public key.
|
||||
type PubKeyResponse struct {
|
||||
PubKey crypto.PubKey
|
||||
Error *RemoteSignerError
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return msg
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
tmproto "github.com/tendermint/tendermint/proto/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)
|
||||
}
|
||||
|
||||
func (sc *RetrySignerClient) SignVote(chainID string, vote *types.Vote) error {
|
||||
func (sc *RetrySignerClient) SignVote(chainID string, vote *tmproto.Vote) error {
|
||||
var err error
|
||||
for i := 0; i < sc.retries || sc.retries == 0; i++ {
|
||||
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)
|
||||
}
|
||||
|
||||
func (sc *RetrySignerClient) SignProposal(chainID string, proposal *types.Proposal) error {
|
||||
func (sc *RetrySignerClient) SignProposal(chainID string, proposal *tmproto.Proposal) error {
|
||||
var err error
|
||||
for i := 0; i < sc.retries || sc.retries == 0; i++ {
|
||||
err = sc.next.SignProposal(chainID, proposal)
|
||||
|
||||
+31
-18
@@ -1,10 +1,14 @@
|
||||
package privval
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -48,15 +52,15 @@ func (sc *SignerClient) WaitForConnection(maxWait time.Duration) error {
|
||||
|
||||
// Ping sends a ping request to the remote signer
|
||||
func (sc *SignerClient) Ping() error {
|
||||
response, err := sc.endpoint.SendRequest(&PingRequest{})
|
||||
response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.PingRequest{}))
|
||||
|
||||
if err != nil {
|
||||
sc.endpoint.Logger.Error("SignerClient::Ping", "err", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
_, ok := response.(*PingResponse)
|
||||
if !ok {
|
||||
pb := response.GetPingResponse()
|
||||
if pb == nil {
|
||||
sc.endpoint.Logger.Error("SignerClient::Ping", "err", "response != PingResponse")
|
||||
return err
|
||||
}
|
||||
@@ -67,64 +71,73 @@ func (sc *SignerClient) Ping() error {
|
||||
// GetPubKey retrieves a public key from a remote signer
|
||||
// returns an error if client is not able to provide the key
|
||||
func (sc *SignerClient) GetPubKey() (crypto.PubKey, error) {
|
||||
response, err := sc.endpoint.SendRequest(&PubKeyRequest{})
|
||||
response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.PubKeyRequest{}))
|
||||
if err != nil {
|
||||
sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", 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")
|
||||
return nil, fmt.Errorf("unexpected response type %T", response)
|
||||
}
|
||||
|
||||
if pubKeyResp.Error != nil {
|
||||
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
|
||||
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 {
|
||||
sc.endpoint.Logger.Error("SignerClient::SignVote", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
resp, ok := response.(*SignedVoteResponse)
|
||||
if !ok {
|
||||
resp := response.GetSignedVoteResponse()
|
||||
if resp == nil {
|
||||
sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", "response != SignedVoteResponse")
|
||||
return ErrUnexpectedResponse
|
||||
}
|
||||
|
||||
if resp.Error != nil {
|
||||
return resp.Error
|
||||
return &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description}
|
||||
}
|
||||
|
||||
*vote = *resp.Vote
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
sc.endpoint.Logger.Error("SignerClient::SignProposal", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
resp, ok := response.(*SignedProposalResponse)
|
||||
if !ok {
|
||||
resp := response.GetSignedProposalResponse()
|
||||
if resp == nil {
|
||||
sc.endpoint.Logger.Error("SignerClient::SignProposal", "err", "response != SignedProposalResponse")
|
||||
return ErrUnexpectedResponse
|
||||
}
|
||||
if resp.Error != nil {
|
||||
return resp.Error
|
||||
return &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description}
|
||||
}
|
||||
|
||||
*proposal = *resp.Proposal
|
||||
|
||||
return nil
|
||||
|
||||
+135
-41
@@ -8,7 +8,10 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
privvalproto "github.com/tendermint/tendermint/proto/privval"
|
||||
tmproto "github.com/tendermint/tendermint/proto/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
@@ -95,14 +98,29 @@ func TestSignerGetPubKey(t *testing.T) {
|
||||
func TestSignerProposal(t *testing.T) {
|
||||
for _, tc := range getSignerTestCases(t) {
|
||||
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.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)
|
||||
}
|
||||
@@ -111,14 +129,33 @@ func TestSignerProposal(t *testing.T) {
|
||||
func TestSignerVote(t *testing.T) {
|
||||
for _, tc := range getSignerTestCases(t) {
|
||||
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.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)
|
||||
}
|
||||
@@ -127,16 +164,35 @@ func TestSignerVote(t *testing.T) {
|
||||
func TestSignerVoteResetDeadline(t *testing.T) {
|
||||
for _, tc := range getSignerTestCases(t) {
|
||||
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.signerClient.Close()
|
||||
|
||||
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)
|
||||
|
||||
// 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
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -153,8 +209,27 @@ func TestSignerVoteResetDeadline(t *testing.T) {
|
||||
func TestSignerVoteKeepAlive(t *testing.T) {
|
||||
for _, tc := range getSignerTestCases(t) {
|
||||
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.signerClient.Close()
|
||||
@@ -168,8 +243,8 @@ func TestSignerVoteKeepAlive(t *testing.T) {
|
||||
time.Sleep(testTimeoutReadWrite * 3)
|
||||
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)
|
||||
}
|
||||
@@ -185,14 +260,24 @@ func TestSignerSignProposalErrors(t *testing.T) {
|
||||
defer tc.signerClient.Close()
|
||||
|
||||
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())
|
||||
|
||||
err = tc.mockPV.SignProposal(tc.chainID, proposal)
|
||||
err = tc.mockPV.SignProposal(tc.chainID, proposal.ToProto())
|
||||
require.Error(t, err)
|
||||
|
||||
err = tc.signerClient.SignProposal(tc.chainID, proposal)
|
||||
err = tc.signerClient.SignProposal(tc.chainID, proposal.ToProto())
|
||||
require.Error(t, err)
|
||||
}
|
||||
}
|
||||
@@ -200,7 +285,18 @@ func TestSignerSignProposalErrors(t *testing.T) {
|
||||
func TestSignerSignVoteErrors(t *testing.T) {
|
||||
for _, tc := range getSignerTestCases(t) {
|
||||
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
|
||||
tc.signerServer.privVal = types.NewErroringMockPV()
|
||||
@@ -209,34 +305,32 @@ func TestSignerSignVoteErrors(t *testing.T) {
|
||||
defer tc.signerServer.Stop()
|
||||
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())
|
||||
|
||||
err = tc.mockPV.SignVote(tc.chainID, vote)
|
||||
err = tc.mockPV.SignVote(tc.chainID, vote.ToProto())
|
||||
require.Error(t, err)
|
||||
|
||||
err = tc.signerClient.SignVote(tc.chainID, vote)
|
||||
err = tc.signerClient.SignVote(tc.chainID, vote.ToProto())
|
||||
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
|
||||
|
||||
switch r := request.(type) {
|
||||
|
||||
switch r := request.Sum.(type) {
|
||||
// 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:
|
||||
err = fmt.Errorf("unknown msg: %v", r)
|
||||
}
|
||||
@@ -257,7 +351,7 @@ func TestSignerUnexpectedResponse(t *testing.T) {
|
||||
ts := time.Now()
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/protoio"
|
||||
"github.com/tendermint/tendermint/libs/service"
|
||||
privvalproto "github.com/tendermint/tendermint/proto/privval"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -78,14 +80,13 @@ func (se *signerEndpoint) DropConnection() {
|
||||
}
|
||||
|
||||
// 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()
|
||||
defer se.connMtx.Unlock()
|
||||
|
||||
if !se.isConnected() {
|
||||
return nil, fmt.Errorf("endpoint is not connected")
|
||||
return msg, fmt.Errorf("endpoint is not connected: %w", ErrNoConnection)
|
||||
}
|
||||
|
||||
// Reset read deadline
|
||||
deadline := time.Now().Add(se.timeoutReadWrite)
|
||||
|
||||
@@ -93,15 +94,16 @@ func (se *signerEndpoint) ReadMessage() (msg SignerMessage, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
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 err != nil {
|
||||
err = fmt.Errorf("%v: %w", err, ErrReadTimeout)
|
||||
} else {
|
||||
err = fmt.Errorf("empty error: %w", ErrReadTimeout)
|
||||
}
|
||||
|
||||
se.Logger.Debug("Dropping [read]", "obj", se)
|
||||
se.dropConnection()
|
||||
}
|
||||
@@ -110,7 +112,7 @@ func (se *signerEndpoint) ReadMessage() (msg SignerMessage, err error) {
|
||||
}
|
||||
|
||||
// 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()
|
||||
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)
|
||||
}
|
||||
|
||||
protoWriter := protoio.NewDelimitedWriter(se.conn)
|
||||
|
||||
// Reset read deadline
|
||||
deadline := time.Now().Add(se.timeoutReadWrite)
|
||||
err = se.conn.SetWriteDeadline(deadline)
|
||||
@@ -125,7 +129,7 @@ func (se *signerEndpoint) WriteMessage(msg SignerMessage) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = cdc.MarshalBinaryLengthPrefixedWriter(se.conn, msg)
|
||||
_, err = protoWriter.WriteMsg(&msg)
|
||||
if _, ok := err.(timeoutError); ok {
|
||||
if err != nil {
|
||||
err = fmt.Errorf("%v: %w", err, ErrWriteTimeout)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
"github.com/tendermint/tendermint/libs/service"
|
||||
privvalproto "github.com/tendermint/tendermint/proto/privval"
|
||||
)
|
||||
|
||||
// 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
|
||||
func (sl *SignerListenerEndpoint) SendRequest(request SignerMessage) (SignerMessage, error) {
|
||||
func (sl *SignerListenerEndpoint) SendRequest(request privvalproto.Message) (*privvalproto.Message, error) {
|
||||
sl.instanceMtx.Lock()
|
||||
defer sl.instanceMtx.Unlock()
|
||||
|
||||
@@ -102,7 +103,7 @@ func (sl *SignerListenerEndpoint) SendRequest(request SignerMessage) (SignerMess
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func (sl *SignerListenerEndpoint) ensureConnection(maxWait time.Duration) error {
|
||||
@@ -185,7 +186,7 @@ func (sl *SignerListenerEndpoint) pingLoop() {
|
||||
select {
|
||||
case <-sl.pingTimer.C:
|
||||
{
|
||||
_, err := sl.SendRequest(&PingRequest{})
|
||||
_, err := sl.SendRequest(mustWrapMsg(&privvalproto.PingRequest{}))
|
||||
if err != nil {
|
||||
sl.Logger.Error("SignerListener: Ping timeout")
|
||||
sl.triggerReconnect()
|
||||
|
||||
@@ -4,45 +4,60 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
cryptoenc "github.com/tendermint/tendermint/crypto/encoding"
|
||||
privvalproto "github.com/tendermint/tendermint/proto/privval"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
func DefaultValidationRequestHandler(
|
||||
privVal types.PrivValidator,
|
||||
req SignerMessage,
|
||||
req privvalproto.Message,
|
||||
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
|
||||
pubKey, err = privVal.GetPubKey()
|
||||
pk, err := cryptoenc.PubKeyToProto(pubKey)
|
||||
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 {
|
||||
res = &SignedVoteResponse{nil, &RemoteSignerError{0, err.Error()}}
|
||||
res = mustWrapMsg(&privvalproto.PubKeyResponse{
|
||||
PubKey: nil, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}})
|
||||
} 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 {
|
||||
res = &SignedProposalResponse{nil, &RemoteSignerError{0, err.Error()}}
|
||||
res = mustWrapMsg(&privvalproto.SignedVoteResponse{
|
||||
Vote: nil, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}})
|
||||
} 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:
|
||||
err = fmt.Errorf("unknown msg: %v", r)
|
||||
|
||||
@@ -5,14 +5,15 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/service"
|
||||
privvalproto "github.com/tendermint/tendermint/proto/privval"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// ValidationRequestHandlerFunc handles different remoteSigner requests
|
||||
type ValidationRequestHandlerFunc func(
|
||||
privVal types.PrivValidator,
|
||||
requestMessage SignerMessage,
|
||||
chainID string) (SignerMessage, error)
|
||||
requestMessage privvalproto.Message,
|
||||
chainID string) (privvalproto.Message, error)
|
||||
|
||||
type SignerServer struct {
|
||||
service.BaseService
|
||||
@@ -70,7 +71,7 @@ func (ss *SignerServer) servicePendingRequest() {
|
||||
return
|
||||
}
|
||||
|
||||
var res SignerMessage
|
||||
var res privvalproto.Message
|
||||
{
|
||||
// limit the scope of the 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+950
-103
File diff suppressed because it is too large
Load Diff
@@ -17,18 +17,18 @@ message PubKeyRequest {}
|
||||
|
||||
// PubKeyResponse is a response message containing the public key.
|
||||
message PubKeyResponse {
|
||||
tendermint.proto.crypto.keys.PublicKey pub_key = 1 [(gogoproto.nullable) = false];
|
||||
tendermint.proto.crypto.keys.PublicKey pub_key = 1;
|
||||
RemoteSignerError error = 2;
|
||||
}
|
||||
|
||||
// SignVoteRequest is a request to sign a vote
|
||||
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
|
||||
message SignVoteResponse {
|
||||
tendermint.proto.types.Vote vote = 1 [(gogoproto.nullable) = false];
|
||||
message SignedVoteResponse {
|
||||
tendermint.proto.types.Vote vote = 1;
|
||||
RemoteSignerError error = 2;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ message SignProposalRequest {
|
||||
|
||||
// SignedProposalResponse is response containing a signed proposal or an error
|
||||
message SignedProposalResponse {
|
||||
tendermint.proto.types.Proposal proposal = 1 [(gogoproto.nullable) = false];
|
||||
tendermint.proto.types.Proposal proposal = 1;
|
||||
RemoteSignerError error = 2;
|
||||
}
|
||||
|
||||
@@ -48,3 +48,16 @@ message PingRequest {}
|
||||
|
||||
// PingResponse is a response to confirm that the connection is alive.
|
||||
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
@@ -24,6 +24,43 @@ var _ = math.Inf
|
||||
// proto package needs to be updated.
|
||||
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.
|
||||
type FilePVKey struct {
|
||||
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.
|
||||
type FilePVLastSignState struct {
|
||||
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"`
|
||||
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"`
|
||||
@@ -143,7 +180,7 @@ func (m *FilePVLastSignState) GetHeight() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *FilePVLastSignState) GetRound() int64 {
|
||||
func (m *FilePVLastSignState) GetRound() int32 {
|
||||
if m != nil {
|
||||
return m.Round
|
||||
}
|
||||
@@ -179,6 +216,7 @@ func (m *FilePVLastSignState) GetFilePath() string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("tendermint.proto.privval.Errors", Errors_name, Errors_value)
|
||||
proto.RegisterType((*FilePVKey)(nil), "tendermint.proto.privval.FilePVKey")
|
||||
proto.RegisterType((*FilePVLastSignState)(nil), "tendermint.proto.privval.FilePVLastSignState")
|
||||
}
|
||||
@@ -186,32 +224,38 @@ func init() {
|
||||
func init() { proto.RegisterFile("proto/privval/types.proto", fileDescriptor_a9d74c406df3ad93) }
|
||||
|
||||
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) {
|
||||
@@ -645,7 +689,7 @@ func (m *FilePVLastSignState) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Round |= int64(b&0x7F) << shift
|
||||
m.Round |= int32(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -18,10 +18,19 @@ message FilePVKey {
|
||||
// FilePVLastSignState stores the mutable part of PrivValidator.
|
||||
message FilePVLastSignState {
|
||||
int64 height = 1;
|
||||
int64 round = 2;
|
||||
int32 round = 2;
|
||||
int32 step = 3;
|
||||
bytes signature = 4;
|
||||
bytes sign_bytes = 5;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -54,6 +54,10 @@ var BlockIDFlag_value = map[string]int32{
|
||||
"BLOCK_ID_FLAG_NIL": 3,
|
||||
}
|
||||
|
||||
func (x BlockIDFlag) String() string {
|
||||
return proto.EnumName(BlockIDFlag_name, int32(x))
|
||||
}
|
||||
|
||||
func (BlockIDFlag) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ff06f8095857fb18, []int{0}
|
||||
}
|
||||
@@ -82,6 +86,10 @@ var SignedMsgType_value = map[string]int32{
|
||||
"PROPOSAL_TYPE": 3,
|
||||
}
|
||||
|
||||
func (x SignedMsgType) String() string {
|
||||
return proto.EnumName(SignedMsgType_name, int32(x))
|
||||
}
|
||||
|
||||
func (SignedMsgType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ff06f8095857fb18, []int{1}
|
||||
}
|
||||
@@ -951,86 +959,86 @@ func init() { proto.RegisterFile("proto/types/types.proto", fileDescriptor_ff06f
|
||||
|
||||
var fileDescriptor_ff06f8095857fb18 = []byte{
|
||||
// 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, 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) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import "proto/version/version.proto";
|
||||
|
||||
// BlockIdFlag indicates which BlcokID the signature is for
|
||||
enum BlockIDFlag {
|
||||
option (gogoproto.goproto_enum_stringer) = false;
|
||||
option (gogoproto.goproto_enum_stringer) = true;
|
||||
option (gogoproto.goproto_enum_prefix) = false;
|
||||
|
||||
BLOCKD_ID_FLAG_UNKNOWN = 0;
|
||||
@@ -22,7 +22,7 @@ enum BlockIDFlag {
|
||||
|
||||
// SignedMsgType is a type of signed message in the consensus.
|
||||
enum SignedMsgType {
|
||||
option (gogoproto.goproto_enum_stringer) = false;
|
||||
option (gogoproto.goproto_enum_stringer) = true;
|
||||
option (gogoproto.goproto_enum_prefix) = false;
|
||||
|
||||
SIGNED_MSG_TYPE_UNKNOWN = 0;
|
||||
|
||||
@@ -25,10 +25,14 @@ func newEvidence(t *testing.T, val *privval.FilePV,
|
||||
chainID string) *types.DuplicateVoteEvidence {
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
return types.NewDuplicateVoteEvidence(vote, vote2)
|
||||
@@ -197,8 +201,12 @@ func TestBroadcastEvidence_ConflictingHeadersEvidence(t *testing.T) {
|
||||
Type: tmproto.PrecommitType,
|
||||
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)
|
||||
vote.Signature = v.Signature
|
||||
|
||||
h2.Commit.Signatures[0] = types.NewCommitSigForBlock(signBytes, pv.Key.Address, h2.Time)
|
||||
|
||||
t.Logf("h1 AppHash: %X", h1.AppHash)
|
||||
|
||||
@@ -26,7 +26,7 @@ func TestTxFilter(t *testing.T) {
|
||||
isErr bool
|
||||
}{
|
||||
{types.Tx(tmrand.Bytes(1680)), false},
|
||||
{types.Tx(tmrand.Bytes(1839)), true},
|
||||
{types.Tx(tmrand.Bytes(1853)), true},
|
||||
{types.Tx(tmrand.Bytes(3000)), true},
|
||||
}
|
||||
|
||||
|
||||
+38
-12
@@ -195,11 +195,17 @@ func TestValidateBlockCommit(t *testing.T) {
|
||||
Type: tmproto.PrecommitType,
|
||||
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)
|
||||
err = badPrivVal.SignVote(chainID, badVote)
|
||||
err = badPrivVal.SignVote(chainID, b)
|
||||
require.NoError(t, err, "height %d", height)
|
||||
|
||||
goodVote.Signature, badVote.Signature = g.Signature, b.Signature
|
||||
|
||||
wrongSigsCommit = types.NewCommit(goodVote.Height, goodVote.Round,
|
||||
blockID, []types.CommitSig{goodVote.CommitSig(), badVote.CommitSig()})
|
||||
}
|
||||
@@ -358,10 +364,14 @@ func TestValidateAmnesiaEvidence(t *testing.T) {
|
||||
state, stateDB, vals := makeState(1, int(height))
|
||||
addr, val := state.Validators.GetByIndex(0)
|
||||
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)
|
||||
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)
|
||||
ae := types.AmnesiaEvidence{
|
||||
PotentialAmnesiaEvidence: types.PotentialAmnesiaEvidence{
|
||||
@@ -434,13 +444,19 @@ func TestVerifyEvidenceWithAmnesiaEvidence(t *testing.T) {
|
||||
addr, val := state.Validators.GetByIndex(0)
|
||||
addr2, val2 := state.Validators.GetByIndex(1)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
//var ae types.Evidence
|
||||
badAe := types.AmnesiaEvidence{
|
||||
@@ -460,11 +476,15 @@ func TestVerifyEvidenceWithAmnesiaEvidence(t *testing.T) {
|
||||
}
|
||||
addr3, val3 := state.Validators.GetByIndex(2)
|
||||
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)
|
||||
voteD.Signature = vD.Signature
|
||||
addr4, val4 := state.Validators.GetByIndex(3)
|
||||
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)
|
||||
|
||||
goodAe := types.AmnesiaEvidence{
|
||||
@@ -513,7 +533,9 @@ func TestVerifyEvidenceWithLunaticValidatorEvidence(t *testing.T) {
|
||||
ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
|
||||
}
|
||||
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)
|
||||
ev := types.LunaticValidatorEvidence{
|
||||
Header: h,
|
||||
@@ -533,7 +555,9 @@ func TestVerifyEvidenceWithPhantomValidatorEvidence(t *testing.T) {
|
||||
state.ConsensusParams.Evidence.MaxAgeNumBlocks = 1
|
||||
addr, val := state.Validators.GetByIndex(0)
|
||||
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)
|
||||
ev := types.PhantomValidatorEvidence{
|
||||
Vote: vote,
|
||||
@@ -549,7 +573,9 @@ func TestVerifyEvidenceWithPhantomValidatorEvidence(t *testing.T) {
|
||||
privVal := types.NewMockPV()
|
||||
pubKey, _ := privVal.GetPubKey()
|
||||
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)
|
||||
ev = types.PhantomValidatorEvidence{
|
||||
Vote: vote2,
|
||||
|
||||
@@ -229,11 +229,13 @@ func (th *TestHarness) TestSignProposal() error {
|
||||
},
|
||||
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)
|
||||
return newTestHarnessError(ErrTestSignProposalFailed, err, "")
|
||||
}
|
||||
prop.Signature = p.Signature
|
||||
th.logger.Debug("Signed proposal", "prop", prop)
|
||||
// first check that it's a basically valid proposal
|
||||
if err := prop.ValidateBasic(); err != nil {
|
||||
@@ -276,12 +278,14 @@ func (th *TestHarness) TestSignVote() error {
|
||||
ValidatorAddress: tmhash.SumTruncated([]byte("addr")),
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
voteBytes := vote.SignBytes(th.chainID)
|
||||
v := vote.ToProto()
|
||||
voteBytes := types.VoteSignBytes(th.chainID, v)
|
||||
// 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)
|
||||
return newTestHarnessError(ErrTestSignVoteFailed, err, fmt.Sprintf("voteType=%d", voteType))
|
||||
}
|
||||
vote.Signature = v.Signature
|
||||
th.logger.Debug("Signed vote", "vote", vote)
|
||||
// validate the contents of the vote
|
||||
if err := vote.ValidateBasic(); err != nil {
|
||||
|
||||
@@ -23,7 +23,7 @@ const (
|
||||
"pub_key": {
|
||||
"type": "tendermint/PubKeyEd25519",
|
||||
"value": "ZCsuTjaczEyon70nmKxwvwu+jqrbq5OH3yQjcK0SFxc="
|
||||
},
|
||||
},
|
||||
"priv_key": {
|
||||
"type": "tendermint/PrivKeyEd25519",
|
||||
"value": "8O39AkQsoe1sBQwud/Kdul8lg8K9SFsql9aZvwXQSt1kKy5ONpzMTKifvSeYrHC/C76Oqturk4ffJCNwrRIXFw=="
|
||||
|
||||
+2
-1
@@ -773,7 +773,8 @@ func (commit *Commit) GetVote(valIdx int32) *Vote {
|
||||
// signed over are otherwise the same for all validators.
|
||||
// Panics if valIdx >= commit.Size().
|
||||
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
|
||||
|
||||
+7
-7
@@ -378,9 +378,9 @@ func TestBlockMaxDataBytes(t *testing.T) {
|
||||
}{
|
||||
0: {-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 {
|
||||
@@ -408,10 +408,10 @@ func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) {
|
||||
}{
|
||||
0: {-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 {
|
||||
|
||||
+11
-41
@@ -3,7 +3,6 @@ package types
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/bytes"
|
||||
tmproto "github.com/tendermint/tendermint/proto/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
)
|
||||
@@ -13,66 +12,37 @@ import (
|
||||
// TimeFormat is used for generating the sigs
|
||||
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
|
||||
|
||||
func CanonicalizeBlockID(blockID BlockID) CanonicalBlockID {
|
||||
return CanonicalBlockID{
|
||||
func CanonicalizeBlockID(blockID tmproto.BlockID) tmproto.CanonicalBlockID {
|
||||
return tmproto.CanonicalBlockID{
|
||||
Hash: blockID.Hash,
|
||||
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,
|
||||
Height: proposal.Height,
|
||||
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),
|
||||
Timestamp: proposal.Timestamp,
|
||||
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,
|
||||
Height: vote.Height,
|
||||
Round: int64(vote.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int)
|
||||
|
||||
+22
-10
@@ -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)",
|
||||
addr, pubKey, pubKey.Address())
|
||||
}
|
||||
|
||||
va := dve.VoteA.ToProto()
|
||||
vb := dve.VoteB.ToProto()
|
||||
// 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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -841,8 +842,8 @@ func (e PhantomValidatorEvidence) Bytes() []byte {
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -1072,11 +1074,14 @@ func (e PotentialAmnesiaEvidence) Verify(chainID string, pubKey crypto.PubKey) e
|
||||
addr, pubKey, pubKey.Address())
|
||||
}
|
||||
|
||||
va := e.VoteA.ToProto()
|
||||
vb := e.VoteB.ToProto()
|
||||
|
||||
// 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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -1247,7 +1252,8 @@ func (e ProofOfLockChange) ValidateVotes(valSet *ValidatorSet, chainID string) e
|
||||
for _, validator := range valSet.Validators {
|
||||
if bytes.Equal(validator.Address, vote.ValidatorAddress) {
|
||||
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",
|
||||
vote.ValidatorIndex, vote.Signature)
|
||||
}
|
||||
@@ -1615,7 +1621,13 @@ func NewMockPOLC(height int64, time time.Time, pubKey crypto.PubKey) ProofOfLock
|
||||
pKey, _ := voteVal.GetPubKey()
|
||||
vote := Vote{Type: tmproto.PrecommitType, Height: height, Round: 1, BlockID: BlockID{},
|
||||
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{
|
||||
Votes: []Vote{vote},
|
||||
PubKey: pubKey,
|
||||
|
||||
+11
-3
@@ -34,12 +34,17 @@ func TestEvidence(t *testing.T) {
|
||||
const chainID = "mychain"
|
||||
|
||||
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)
|
||||
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)
|
||||
|
||||
vote1.Signature = v1.Signature
|
||||
badVote.Signature = bv.Signature
|
||||
|
||||
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, blockID3, defaultVoteTime), true},
|
||||
@@ -542,10 +547,13 @@ func makeVote(
|
||||
BlockID: blockID,
|
||||
Timestamp: time,
|
||||
}
|
||||
err = val.SignVote(chainID, v)
|
||||
|
||||
vpb := v.ToProto()
|
||||
err = val.SignVote(chainID, vpb)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
v.Signature = vpb.Signature
|
||||
return v
|
||||
}
|
||||
|
||||
|
||||
+11
-8
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
tmproto "github.com/tendermint/tendermint/proto/types"
|
||||
)
|
||||
|
||||
// PrivValidator defines the functionality of a local Tendermint validator
|
||||
@@ -14,8 +15,8 @@ import (
|
||||
type PrivValidator interface {
|
||||
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
|
||||
@@ -71,12 +72,13 @@ func (pv MockPV) GetPubKey() (crypto.PubKey, error) {
|
||||
}
|
||||
|
||||
// Implements PrivValidator.
|
||||
func (pv MockPV) SignVote(chainID string, vote *Vote) error {
|
||||
func (pv MockPV) SignVote(chainID string, vote *tmproto.Vote) error {
|
||||
useChainID := chainID
|
||||
if pv.breakVoteSigning {
|
||||
useChainID = "incorrect-chain-id"
|
||||
}
|
||||
signBytes := vote.SignBytes(useChainID)
|
||||
|
||||
signBytes := VoteSignBytes(useChainID, vote)
|
||||
sig, err := pv.PrivKey.Sign(signBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -86,12 +88,13 @@ func (pv MockPV) SignVote(chainID string, vote *Vote) error {
|
||||
}
|
||||
|
||||
// Implements PrivValidator.
|
||||
func (pv MockPV) SignProposal(chainID string, proposal *Proposal) error {
|
||||
func (pv MockPV) SignProposal(chainID string, proposal *tmproto.Proposal) error {
|
||||
useChainID := chainID
|
||||
if pv.breakProposalSigning {
|
||||
useChainID = "incorrect-chain-id"
|
||||
}
|
||||
signBytes := proposal.SignBytes(useChainID)
|
||||
|
||||
signBytes := ProposalSignBytes(useChainID, proposal)
|
||||
sig, err := pv.PrivKey.Sign(signBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -128,12 +131,12 @@ type ErroringMockPV struct {
|
||||
var ErroringMockPVErr = errors.New("erroringMockPV always returns an error")
|
||||
|
||||
// Implements PrivValidator.
|
||||
func (pv *ErroringMockPV) SignVote(chainID string, vote *Vote) error {
|
||||
func (pv *ErroringMockPV) SignVote(chainID string, vote *tmproto.Vote) error {
|
||||
return ErroringMockPVErr
|
||||
}
|
||||
|
||||
// Implements PrivValidator.
|
||||
func (pv *ErroringMockPV) SignProposal(chainID string, proposal *Proposal) error {
|
||||
func (pv *ErroringMockPV) SignProposal(chainID string, proposal *tmproto.Proposal) error {
|
||||
return ErroringMockPVErr
|
||||
}
|
||||
|
||||
|
||||
+8
-4
@@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/bytes"
|
||||
tmproto "github.com/tendermint/tendermint/proto/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
@@ -71,6 +73,7 @@ func (p *Proposal) ValidateBasic() error {
|
||||
if len(p.Signature) == 0 {
|
||||
return errors.New("signature is missing")
|
||||
}
|
||||
|
||||
if len(p.Signature) > MaxSignatureSize {
|
||||
return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize)
|
||||
}
|
||||
@@ -88,9 +91,10 @@ func (p *Proposal) String() string {
|
||||
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 {
|
||||
panic(err)
|
||||
}
|
||||
@@ -100,7 +104,7 @@ func (p *Proposal) SignBytes(chainID string) []byte {
|
||||
// ToProto converts Proposal to protobuf
|
||||
func (p *Proposal) ToProto() *tmproto.Proposal {
|
||||
if p == nil {
|
||||
return nil
|
||||
return &tmproto.Proposal{}
|
||||
}
|
||||
pb := new(tmproto.Proposal)
|
||||
|
||||
|
||||
+33
-17
@@ -5,14 +5,19 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
tmproto "github.com/tendermint/tendermint/proto/types"
|
||||
)
|
||||
|
||||
var testProposal *Proposal
|
||||
var (
|
||||
testProposal *Proposal
|
||||
pbp *tmproto.Proposal
|
||||
)
|
||||
|
||||
func init() {
|
||||
var stamp, err = time.Parse(TimeFormat, "2018-02-11T07:09:22.765Z")
|
||||
@@ -26,13 +31,14 @@ func init() {
|
||||
POLRound: -1,
|
||||
Timestamp: stamp,
|
||||
}
|
||||
pbp = testProposal.ToProto()
|
||||
}
|
||||
|
||||
func TestProposalSignable(t *testing.T) {
|
||||
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.Equal(t, expected, signBytes, "Got unexpected sign bytes for Proposal")
|
||||
}
|
||||
@@ -52,41 +58,49 @@ func TestProposalVerifySignature(t *testing.T) {
|
||||
|
||||
prop := NewProposal(
|
||||
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
|
||||
err = privVal.SignProposal("test_chain_id", prop)
|
||||
err = privVal.SignProposal("test_chain_id", p)
|
||||
require.NoError(t, err)
|
||||
prop.Signature = p.Signature
|
||||
|
||||
// verify the same proposal
|
||||
valid := pubKey.VerifyBytes(signBytes, prop.Signature)
|
||||
require.True(t, valid)
|
||||
|
||||
// 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)
|
||||
err = cdc.UnmarshalBinaryLengthPrefixed(bs, &newProp)
|
||||
|
||||
err = proto.Unmarshal(bs, newProp)
|
||||
require.NoError(t, err)
|
||||
|
||||
np, err := ProposalFromProto(newProp)
|
||||
require.NoError(t, err)
|
||||
|
||||
// verify the transmitted proposal
|
||||
newSignBytes := newProp.SignBytes("test_chain_id")
|
||||
newSignBytes := ProposalSignBytes("test_chain_id", pb)
|
||||
require.Equal(t, string(signBytes), string(newSignBytes))
|
||||
valid = pubKey.VerifyBytes(newSignBytes, newProp.Signature)
|
||||
valid = pubKey.VerifyBytes(newSignBytes, np.Signature)
|
||||
require.True(t, valid)
|
||||
}
|
||||
|
||||
func BenchmarkProposalWriteSignBytes(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
testProposal.SignBytes("test_chain_id")
|
||||
ProposalSignBytes("test_chain_id", pbp)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkProposalSign(b *testing.B) {
|
||||
privVal := NewMockPV()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := privVal.SignProposal("test_chain_id", testProposal)
|
||||
err := privVal.SignProposal("test_chain_id", pbp)
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
@@ -95,13 +109,13 @@ func BenchmarkProposalSign(b *testing.B) {
|
||||
|
||||
func BenchmarkProposalVerifySignature(b *testing.B) {
|
||||
privVal := NewMockPV()
|
||||
err := privVal.SignProposal("test_chain_id", testProposal)
|
||||
err := privVal.SignProposal("test_chain_id", pbp)
|
||||
require.NoError(b, err)
|
||||
pubKey, err := privVal.GetPubKey()
|
||||
require.NoError(b, err)
|
||||
|
||||
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(
|
||||
4, 2, 2,
|
||||
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)
|
||||
tc.malleateProposal(prop)
|
||||
assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, "Validate Basic had an unexpected result")
|
||||
|
||||
+9
-2
@@ -36,10 +36,12 @@ func MakeCommit(blockID BlockID, height int64, round int32,
|
||||
}
|
||||
|
||||
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 {
|
||||
return false, err
|
||||
}
|
||||
vote.Signature = v.Signature
|
||||
return voteSet.AddVote(vote)
|
||||
}
|
||||
|
||||
@@ -66,9 +68,14 @@ func MakeVote(
|
||||
Type: tmproto.PrecommitType,
|
||||
BlockID: blockID,
|
||||
}
|
||||
if err := privVal.SignVote(chainID, vote); err != nil {
|
||||
v := vote.ToProto()
|
||||
|
||||
if err := privVal.SignVote(chainID, v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vote.Signature = v.Signature
|
||||
|
||||
return vote, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -667,7 +667,9 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
|
||||
Type: tmproto.PrecommitType,
|
||||
BlockID: blockID,
|
||||
}
|
||||
sig, err := privKey.Sign(vote.SignBytes(chainID))
|
||||
|
||||
v := vote.ToProto()
|
||||
sig, err := privKey.Sign(VoteSignBytes(chainID, v))
|
||||
assert.NoError(t, err)
|
||||
vote.Signature = sig
|
||||
commit := NewCommit(vote.Height, vote.Round, blockID, []CommitSig{vote.CommitSig()})
|
||||
|
||||
+14
-5
@@ -6,6 +6,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
tmbytes "github.com/tendermint/tendermint/libs/bytes"
|
||||
tmproto "github.com/tendermint/tendermint/proto/types"
|
||||
@@ -13,7 +15,7 @@ import (
|
||||
|
||||
const (
|
||||
// MaxVoteBytes is a maximum vote size (including amino overhead).
|
||||
MaxVoteBytes int64 = 211
|
||||
MaxVoteBytes int64 = 209
|
||||
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 {
|
||||
panic(err)
|
||||
}
|
||||
@@ -126,8 +131,8 @@ func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
|
||||
if !bytes.Equal(pubKey.Address(), vote.ValidatorAddress) {
|
||||
return ErrVoteInvalidValidatorAddress
|
||||
}
|
||||
|
||||
if !pubKey.VerifyBytes(vote.SignBytes(chainID), vote.Signature) {
|
||||
v := vote.ToProto()
|
||||
if !pubKey.VerifyBytes(VoteSignBytes(chainID, v), vote.Signature) {
|
||||
return ErrVoteInvalidSignature
|
||||
}
|
||||
return nil
|
||||
@@ -152,11 +157,13 @@ func (vote *Vote) ValidateBasic() error {
|
||||
if err := vote.BlockID.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("wrong BlockID: %v", err)
|
||||
}
|
||||
|
||||
// BlockID.ValidateBasic would not err if we for instance have an empty hash but a
|
||||
// non-empty PartsSetHeader:
|
||||
if !vote.BlockID.IsZero() && !vote.BlockID.IsComplete() {
|
||||
return fmt.Errorf("blockID must be either empty or complete, got: %v", vote.BlockID)
|
||||
}
|
||||
|
||||
if len(vote.ValidatorAddress) != crypto.AddressSize {
|
||||
return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes",
|
||||
crypto.AddressSize,
|
||||
@@ -169,9 +176,11 @@ func (vote *Vote) ValidateBasic() error {
|
||||
if len(vote.Signature) == 0 {
|
||||
return errors.New("signature is missing")
|
||||
}
|
||||
|
||||
if len(vote.Signature) > MaxSignatureSize {
|
||||
return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+40
-63
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@@ -47,9 +48,11 @@ func exampleVote(t byte) *Vote {
|
||||
|
||||
func TestVoteSignable(t *testing.T) {
|
||||
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.Equal(t, expected, signBytes, "Got unexpected sign bytes for Vote.")
|
||||
@@ -65,79 +68,47 @@ func TestVoteSignBytesTestVectors(t *testing.T) {
|
||||
0: {
|
||||
"", &Vote{},
|
||||
// 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):
|
||||
1: {
|
||||
"", &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},
|
||||
},
|
||||
// with proper (fixed size) height and round (PreVote):
|
||||
2: {
|
||||
"", &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: {
|
||||
"", &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:
|
||||
4: {
|
||||
"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 {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
pb, err := cdc.MarshalBinaryLengthPrefixed(p)
|
||||
pb, err := proto.Marshal(&p)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, vb, pb)
|
||||
}
|
||||
@@ -148,25 +119,26 @@ func TestVoteVerifySignature(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
vote := examplePrecommit()
|
||||
signBytes := vote.SignBytes("test_chain_id")
|
||||
v := vote.ToProto()
|
||||
signBytes := VoteSignBytes("test_chain_id", v)
|
||||
|
||||
// sign it
|
||||
err = privVal.SignVote("test_chain_id", vote)
|
||||
err = privVal.SignVote("test_chain_id", v)
|
||||
require.NoError(t, err)
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
err = cdc.UnmarshalBinaryLengthPrefixed(bs, &precommit)
|
||||
err = proto.Unmarshal(bs, precommit)
|
||||
require.NoError(t, err)
|
||||
|
||||
// verify the transmitted vote
|
||||
newSignBytes := precommit.SignBytes("test_chain_id")
|
||||
newSignBytes := VoteSignBytes("test_chain_id", precommit)
|
||||
require.Equal(t, string(signBytes), string(newSignBytes))
|
||||
valid = pubkey.VerifyBytes(newSignBytes, precommit.Signature)
|
||||
require.True(t, valid)
|
||||
@@ -233,11 +205,12 @@ func TestMaxVoteBytes(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
v := vote.ToProto()
|
||||
privVal := NewMockPV()
|
||||
err := privVal.SignVote("test_chain_id", vote)
|
||||
err := privVal.SignVote("test_chain_id", v)
|
||||
require.NoError(t, err)
|
||||
|
||||
bz, err := cdc.MarshalBinaryLengthPrefixed(vote)
|
||||
bz, err := proto.Marshal(v)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, MaxVoteBytes, len(bz))
|
||||
@@ -245,13 +218,13 @@ func TestMaxVoteBytes(t *testing.T) {
|
||||
|
||||
func TestVoteString(t *testing.T) {
|
||||
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 {
|
||||
t.Errorf("got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str)
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
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)
|
||||
tc.malleateVote(vote)
|
||||
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) {
|
||||
privVal := NewMockPV()
|
||||
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)
|
||||
|
||||
testCases := []struct {
|
||||
|
||||
Reference in New Issue
Block a user