mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-19 06:31:57 +00:00
Merge branch 'develop' into 2702-proposal-pol-round-validation
This commit is contained in:
+98
-21
@@ -2,12 +2,14 @@ package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/merkle"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
@@ -15,7 +17,7 @@ import (
|
||||
|
||||
const (
|
||||
// MaxHeaderBytes is a maximum header size (including amino overhead).
|
||||
MaxHeaderBytes int64 = 537
|
||||
MaxHeaderBytes int64 = 653
|
||||
|
||||
// MaxAminoOverheadForBlock - maximum amino overhead to encode a block (up to
|
||||
// MaxBlockSizeBytes in size) not including it's parts except Data.
|
||||
@@ -57,54 +59,117 @@ func MakeBlock(height int64, txs []Tx, lastCommit *Commit, evidence []Evidence)
|
||||
|
||||
// ValidateBasic performs basic validation that doesn't involve state data.
|
||||
// It checks the internal consistency of the block.
|
||||
// Further validation is done using state#ValidateBlock.
|
||||
func (b *Block) ValidateBasic() error {
|
||||
if b == nil {
|
||||
return errors.New("Nil blocks are invalid")
|
||||
return errors.New("nil block")
|
||||
}
|
||||
b.mtx.Lock()
|
||||
defer b.mtx.Unlock()
|
||||
|
||||
if b.Height < 0 {
|
||||
return fmt.Errorf(
|
||||
"Negative Block.Header.Height: %v",
|
||||
b.Height,
|
||||
)
|
||||
if len(b.ChainID) > MaxChainIDLen {
|
||||
return fmt.Errorf("ChainID is too long. Max is %d, got %d", MaxChainIDLen, len(b.ChainID))
|
||||
}
|
||||
|
||||
if b.Height < 0 {
|
||||
return errors.New("Negative Header.Height")
|
||||
} else if b.Height == 0 {
|
||||
return errors.New("Zero Header.Height")
|
||||
}
|
||||
|
||||
// NOTE: Timestamp validation is subtle and handled elsewhere.
|
||||
|
||||
newTxs := int64(len(b.Data.Txs))
|
||||
if b.NumTxs != newTxs {
|
||||
return fmt.Errorf(
|
||||
"Wrong Block.Header.NumTxs. Expected %v, got %v",
|
||||
return fmt.Errorf("Wrong Header.NumTxs. Expected %v, got %v",
|
||||
newTxs,
|
||||
b.NumTxs,
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: fix tests so we can do this
|
||||
/*if b.TotalTxs < b.NumTxs {
|
||||
return fmt.Errorf("Header.TotalTxs (%d) is less than Header.NumTxs (%d)", b.TotalTxs, b.NumTxs)
|
||||
}*/
|
||||
if b.TotalTxs < 0 {
|
||||
return errors.New("Negative Header.TotalTxs")
|
||||
}
|
||||
|
||||
if err := b.LastBlockID.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("Wrong Header.LastBlockID: %v", err)
|
||||
}
|
||||
|
||||
// Validate the last commit and its hash.
|
||||
if b.Header.Height > 1 {
|
||||
if b.LastCommit == nil {
|
||||
return errors.New("nil LastCommit")
|
||||
}
|
||||
if err := b.LastCommit.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("Wrong LastCommit")
|
||||
}
|
||||
}
|
||||
if err := ValidateHash(b.LastCommitHash); err != nil {
|
||||
return fmt.Errorf("Wrong Header.LastCommitHash: %v", err)
|
||||
}
|
||||
if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
|
||||
return fmt.Errorf(
|
||||
"Wrong Block.Header.LastCommitHash. Expected %v, got %v",
|
||||
b.LastCommitHash,
|
||||
return fmt.Errorf("Wrong Header.LastCommitHash. Expected %v, got %v",
|
||||
b.LastCommit.Hash(),
|
||||
b.LastCommitHash,
|
||||
)
|
||||
}
|
||||
if b.Header.Height != 1 {
|
||||
if err := b.LastCommit.ValidateBasic(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate the hash of the transactions.
|
||||
// NOTE: b.Data.Txs may be nil, but b.Data.Hash()
|
||||
// still works fine
|
||||
if err := ValidateHash(b.DataHash); err != nil {
|
||||
return fmt.Errorf("Wrong Header.DataHash: %v", err)
|
||||
}
|
||||
if !bytes.Equal(b.DataHash, b.Data.Hash()) {
|
||||
return fmt.Errorf(
|
||||
"Wrong Block.Header.DataHash. Expected %v, got %v",
|
||||
b.DataHash,
|
||||
"Wrong Header.DataHash. Expected %v, got %v",
|
||||
b.Data.Hash(),
|
||||
b.DataHash,
|
||||
)
|
||||
}
|
||||
|
||||
// Basic validation of hashes related to application data.
|
||||
// Will validate fully against state in state#ValidateBlock.
|
||||
if err := ValidateHash(b.ValidatorsHash); err != nil {
|
||||
return fmt.Errorf("Wrong Header.ValidatorsHash: %v", err)
|
||||
}
|
||||
if err := ValidateHash(b.NextValidatorsHash); err != nil {
|
||||
return fmt.Errorf("Wrong Header.NextValidatorsHash: %v", err)
|
||||
}
|
||||
if err := ValidateHash(b.ConsensusHash); err != nil {
|
||||
return fmt.Errorf("Wrong Header.ConsensusHash: %v", err)
|
||||
}
|
||||
// NOTE: AppHash is arbitrary length
|
||||
if err := ValidateHash(b.LastResultsHash); err != nil {
|
||||
return fmt.Errorf("Wrong Header.LastResultsHash: %v", err)
|
||||
}
|
||||
|
||||
// Validate evidence and its hash.
|
||||
if err := ValidateHash(b.EvidenceHash); err != nil {
|
||||
return fmt.Errorf("Wrong Header.EvidenceHash: %v", err)
|
||||
}
|
||||
// NOTE: b.Evidence.Evidence may be nil, but we're just looping.
|
||||
for i, ev := range b.Evidence.Evidence {
|
||||
if err := ev.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("Invalid evidence (#%d): %v", i, err)
|
||||
}
|
||||
}
|
||||
if !bytes.Equal(b.EvidenceHash, b.Evidence.Hash()) {
|
||||
return fmt.Errorf(
|
||||
"Wrong Block.Header.EvidenceHash. Expected %v, got %v",
|
||||
return fmt.Errorf("Wrong Header.EvidenceHash. Expected %v, got %v",
|
||||
b.EvidenceHash,
|
||||
b.Evidence.Hash(),
|
||||
)
|
||||
}
|
||||
|
||||
if len(b.ProposerAddress) != crypto.AddressSize {
|
||||
return fmt.Errorf("Expected len(Header.ProposerAddress) to be %d, got %d",
|
||||
crypto.AddressSize, len(b.ProposerAddress))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -719,6 +784,18 @@ func (blockID BlockID) Key() string {
|
||||
return string(blockID.Hash) + string(bz)
|
||||
}
|
||||
|
||||
// ValidateBasic performs basic validation.
|
||||
func (blockID BlockID) ValidateBasic() error {
|
||||
// Hash can be empty in case of POLBlockID in Proposal.
|
||||
if err := ValidateHash(blockID.Hash); err != nil {
|
||||
return fmt.Errorf("Wrong Hash")
|
||||
}
|
||||
if err := blockID.PartsHeader.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("Wrong PartsHeader: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns a human readable string representation of the BlockID
|
||||
func (blockID BlockID) String() string {
|
||||
return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader)
|
||||
|
||||
+13
-10
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
@@ -79,11 +80,13 @@ func TestBlockValidateBasic(t *testing.T) {
|
||||
blk.EvidenceHash = []byte("something else")
|
||||
}, true},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
for i, tc := range testCases {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
block := MakeBlock(h, txs, commit, evList)
|
||||
block.ProposerAddress = valSet.GetProposer().Address
|
||||
tc.malleateBlock(block)
|
||||
assert.Equal(t, tc.expErr, block.ValidateBasic() != nil, "ValidateBasic had an unexpected result")
|
||||
err = block.ValidateBasic()
|
||||
assert.Equal(t, tc.expErr, err != nil, "#%d: %v", i, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -116,7 +119,7 @@ func TestBlockMakePartSetWithEvidence(t *testing.T) {
|
||||
|
||||
partSet := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList).MakePartSet(1024)
|
||||
assert.NotNil(t, partSet)
|
||||
assert.Equal(t, 2, partSet.Total())
|
||||
assert.Equal(t, 3, partSet.Total())
|
||||
}
|
||||
|
||||
func TestBlockHashesTo(t *testing.T) {
|
||||
@@ -262,7 +265,7 @@ func TestMaxHeaderBytes(t *testing.T) {
|
||||
AppHash: tmhash.Sum([]byte("app_hash")),
|
||||
LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
|
||||
EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
|
||||
ProposerAddress: tmhash.Sum([]byte("proposer_address")),
|
||||
ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
|
||||
}
|
||||
|
||||
bz, err := cdc.MarshalBinaryLengthPrefixed(h)
|
||||
@@ -292,9 +295,9 @@ func TestBlockMaxDataBytes(t *testing.T) {
|
||||
}{
|
||||
0: {-10, 1, 0, true, 0},
|
||||
1: {10, 1, 0, true, 0},
|
||||
2: {750, 1, 0, true, 0},
|
||||
3: {751, 1, 0, false, 0},
|
||||
4: {752, 1, 0, false, 1},
|
||||
2: {886, 1, 0, true, 0},
|
||||
3: {887, 1, 0, false, 0},
|
||||
4: {888, 1, 0, false, 1},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
@@ -320,9 +323,9 @@ func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) {
|
||||
}{
|
||||
0: {-10, 1, true, 0},
|
||||
1: {10, 1, true, 0},
|
||||
2: {833, 1, true, 0},
|
||||
3: {834, 1, false, 0},
|
||||
4: {835, 1, false, 1},
|
||||
2: {984, 1, true, 0},
|
||||
3: {985, 1, false, 0},
|
||||
4: {986, 1, false, 1},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
|
||||
+14
-16
@@ -23,14 +23,13 @@ type CanonicalPartSetHeader struct {
|
||||
}
|
||||
|
||||
type CanonicalProposal struct {
|
||||
Type SignedMsgType // type alias for byte
|
||||
Height int64 `binary:"fixed64"`
|
||||
Round int64 `binary:"fixed64"`
|
||||
POLRound int64 `binary:"fixed64"`
|
||||
Timestamp time.Time
|
||||
BlockPartsHeader CanonicalPartSetHeader
|
||||
POLBlockID CanonicalBlockID
|
||||
ChainID string
|
||||
Type 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 {
|
||||
@@ -71,14 +70,13 @@ func CanonicalizePartSetHeader(psh PartSetHeader) CanonicalPartSetHeader {
|
||||
|
||||
func CanonicalizeProposal(chainID string, proposal *Proposal) CanonicalProposal {
|
||||
return CanonicalProposal{
|
||||
Type: 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),
|
||||
Timestamp: proposal.Timestamp,
|
||||
BlockPartsHeader: CanonicalizePartSetHeader(proposal.BlockPartsHeader),
|
||||
POLBlockID: CanonicalizeBlockID(proposal.POLBlockID),
|
||||
ChainID: chainID,
|
||||
Type: 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),
|
||||
BlockID: CanonicalizeBlockID(proposal.BlockID),
|
||||
Timestamp: proposal.Timestamp,
|
||||
ChainID: chainID,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,10 @@ func (b *EventBus) PublishEventVote(data EventDataVote) error {
|
||||
return b.Publish(EventVote, data)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventValidBlock(data EventDataRoundState) error {
|
||||
return b.Publish(EventValidBlock, data)
|
||||
}
|
||||
|
||||
// PublishEventTx publishes tx event with tags from Result. Note it will add
|
||||
// predefined tags (EventTypeKey, TxHashKey). Existing tags with the same names
|
||||
// will be overwritten.
|
||||
|
||||
@@ -23,6 +23,7 @@ const (
|
||||
EventTimeoutWait = "TimeoutWait"
|
||||
EventTx = "Tx"
|
||||
EventUnlock = "Unlock"
|
||||
EventValidBlock = "ValidBlock"
|
||||
EventValidatorSetUpdates = "ValidatorSetUpdates"
|
||||
EventVote = "Vote"
|
||||
)
|
||||
@@ -119,6 +120,7 @@ var (
|
||||
EventQueryTx = QueryForEvent(EventTx)
|
||||
EventQueryUnlock = QueryForEvent(EventUnlock)
|
||||
EventQueryValidatorSetUpdates = QueryForEvent(EventValidatorSetUpdates)
|
||||
EventQueryValidBlock = QueryForEvent(EventValidBlock)
|
||||
EventQueryVote = QueryForEvent(EventVote)
|
||||
)
|
||||
|
||||
|
||||
+22
-1
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
|
||||
amino "github.com/tendermint/go-amino"
|
||||
@@ -14,7 +15,7 @@ import (
|
||||
|
||||
const (
|
||||
// MaxEvidenceBytes is a maximum size of any evidence (including amino overhead).
|
||||
MaxEvidenceBytes int64 = 444
|
||||
MaxEvidenceBytes int64 = 484
|
||||
)
|
||||
|
||||
// ErrEvidenceInvalid wraps a piece of evidence and the error denoting how or why it is invalid.
|
||||
@@ -60,6 +61,7 @@ type Evidence interface {
|
||||
Verify(chainID string, pubKey crypto.PubKey) error // verify the evidence
|
||||
Equal(Evidence) bool // check equality of evidence
|
||||
|
||||
ValidateBasic() error
|
||||
String() string
|
||||
}
|
||||
|
||||
@@ -172,6 +174,23 @@ func (dve *DuplicateVoteEvidence) Equal(ev Evidence) bool {
|
||||
return bytes.Equal(dveHash, evHash)
|
||||
}
|
||||
|
||||
// ValidateBasic performs basic validation.
|
||||
func (dve *DuplicateVoteEvidence) ValidateBasic() error {
|
||||
if len(dve.PubKey.Bytes()) == 0 {
|
||||
return errors.New("Empty PubKey")
|
||||
}
|
||||
if dve.VoteA == nil || dve.VoteB == nil {
|
||||
return fmt.Errorf("One or both of the votes are empty %v, %v", dve.VoteA, dve.VoteB)
|
||||
}
|
||||
if err := dve.VoteA.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("Invalid VoteA: %v", err)
|
||||
}
|
||||
if err := dve.VoteB.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("Invalid VoteB: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
// UNSTABLE
|
||||
@@ -201,6 +220,7 @@ func (e MockGoodEvidence) Equal(ev Evidence) bool {
|
||||
return e.Height_ == e2.Height_ &&
|
||||
bytes.Equal(e.Address_, e2.Address_)
|
||||
}
|
||||
func (e MockGoodEvidence) ValidateBasic() error { return nil }
|
||||
func (e MockGoodEvidence) String() string {
|
||||
return fmt.Sprintf("GoodEvidence: %d/%s", e.Height_, e.Address_)
|
||||
}
|
||||
@@ -218,6 +238,7 @@ func (e MockBadEvidence) Equal(ev Evidence) bool {
|
||||
return e.Height_ == e2.Height_ &&
|
||||
bytes.Equal(e.Address_, e2.Address_)
|
||||
}
|
||||
func (e MockBadEvidence) ValidateBasic() error { return nil }
|
||||
func (e MockBadEvidence) String() string {
|
||||
return fmt.Sprintf("BadEvidence: %d/%s", e.Height_, e.Address_)
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ func TestEvidence(t *testing.T) {
|
||||
{vote1, makeVote(val, chainID, 0, 10, 3, 1, blockID2), false}, // wrong round
|
||||
{vote1, makeVote(val, chainID, 0, 10, 2, 2, blockID2), false}, // wrong step
|
||||
{vote1, makeVote(val2, chainID, 0, 10, 2, 1, blockID), false}, // wrong validator
|
||||
{vote1, badVote, false}, // signed by wrong key
|
||||
{vote1, badVote, false}, // signed by wrong key
|
||||
}
|
||||
|
||||
pubKey := val.GetPubKey()
|
||||
|
||||
@@ -3,6 +3,8 @@ package types
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
)
|
||||
|
||||
@@ -50,3 +52,32 @@ func (heartbeat *Heartbeat) String() string {
|
||||
heartbeat.Height, heartbeat.Round, heartbeat.Sequence,
|
||||
fmt.Sprintf("/%X.../", cmn.Fingerprint(heartbeat.Signature[:])))
|
||||
}
|
||||
|
||||
// ValidateBasic performs basic validation.
|
||||
func (heartbeat *Heartbeat) ValidateBasic() error {
|
||||
if len(heartbeat.ValidatorAddress) != crypto.AddressSize {
|
||||
return fmt.Errorf("Expected ValidatorAddress size to be %d bytes, got %d bytes",
|
||||
crypto.AddressSize,
|
||||
len(heartbeat.ValidatorAddress),
|
||||
)
|
||||
}
|
||||
if heartbeat.ValidatorIndex < 0 {
|
||||
return errors.New("Negative ValidatorIndex")
|
||||
}
|
||||
if heartbeat.Height < 0 {
|
||||
return errors.New("Negative Height")
|
||||
}
|
||||
if heartbeat.Round < 0 {
|
||||
return errors.New("Negative Round")
|
||||
}
|
||||
if heartbeat.Sequence < 0 {
|
||||
return errors.New("Negative Sequence")
|
||||
}
|
||||
if len(heartbeat.Signature) == 0 {
|
||||
return errors.New("Signature is missing")
|
||||
}
|
||||
if len(heartbeat.Signature) > MaxSignatureSize {
|
||||
return fmt.Errorf("Signature is too big (max: %d)", MaxSignatureSize)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+60
-12
@@ -17,12 +17,13 @@ const (
|
||||
// ConsensusParams contains consensus critical parameters that determine the
|
||||
// validity of blocks.
|
||||
type ConsensusParams struct {
|
||||
BlockSize `json:"block_size_params"`
|
||||
EvidenceParams `json:"evidence_params"`
|
||||
BlockSize BlockSizeParams `json:"block_size"`
|
||||
Evidence EvidenceParams `json:"evidence"`
|
||||
Validator ValidatorParams `json:"validator"`
|
||||
}
|
||||
|
||||
// BlockSize contain limits on the block size.
|
||||
type BlockSize struct {
|
||||
// BlockSizeParams define limits on the block size.
|
||||
type BlockSizeParams struct {
|
||||
MaxBytes int64 `json:"max_bytes"`
|
||||
MaxGas int64 `json:"max_gas"`
|
||||
}
|
||||
@@ -32,17 +33,24 @@ type EvidenceParams struct {
|
||||
MaxAge int64 `json:"max_age"` // only accept new evidence more recent than this
|
||||
}
|
||||
|
||||
// ValidatorParams restrict the public key types validators can use.
|
||||
// NOTE: uses ABCI pubkey naming, not Amino routes.
|
||||
type ValidatorParams struct {
|
||||
PubKeyTypes []string `json:"pub_key_types"`
|
||||
}
|
||||
|
||||
// DefaultConsensusParams returns a default ConsensusParams.
|
||||
func DefaultConsensusParams() *ConsensusParams {
|
||||
return &ConsensusParams{
|
||||
DefaultBlockSize(),
|
||||
DefaultBlockSizeParams(),
|
||||
DefaultEvidenceParams(),
|
||||
DefaultValidatorParams(),
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultBlockSize returns a default BlockSize.
|
||||
func DefaultBlockSize() BlockSize {
|
||||
return BlockSize{
|
||||
// DefaultBlockSizeParams returns a default BlockSizeParams.
|
||||
func DefaultBlockSizeParams() BlockSizeParams {
|
||||
return BlockSizeParams{
|
||||
MaxBytes: 22020096, // 21MB
|
||||
MaxGas: -1,
|
||||
}
|
||||
@@ -55,6 +63,12 @@ func DefaultEvidenceParams() EvidenceParams {
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultValidatorParams returns a default ValidatorParams, which allows
|
||||
// only ed25519 pubkeys.
|
||||
func DefaultValidatorParams() ValidatorParams {
|
||||
return ValidatorParams{[]string{ABCIPubKeyTypeEd25519}}
|
||||
}
|
||||
|
||||
// Validate validates the ConsensusParams to ensure all values are within their
|
||||
// allowed limits, and returns an error if they are not.
|
||||
func (params *ConsensusParams) Validate() error {
|
||||
@@ -72,9 +86,22 @@ func (params *ConsensusParams) Validate() error {
|
||||
params.BlockSize.MaxGas)
|
||||
}
|
||||
|
||||
if params.EvidenceParams.MaxAge <= 0 {
|
||||
if params.Evidence.MaxAge <= 0 {
|
||||
return cmn.NewError("EvidenceParams.MaxAge must be greater than 0. Got %d",
|
||||
params.EvidenceParams.MaxAge)
|
||||
params.Evidence.MaxAge)
|
||||
}
|
||||
|
||||
if len(params.Validator.PubKeyTypes) == 0 {
|
||||
return cmn.NewError("len(Validator.PubKeyTypes) must be greater than 0")
|
||||
}
|
||||
|
||||
// Check if keyType is a known ABCIPubKeyType
|
||||
for i := 0; i < len(params.Validator.PubKeyTypes); i++ {
|
||||
keyType := params.Validator.PubKeyTypes[i]
|
||||
if _, ok := ABCIPubKeyTypesToAminoRoutes[keyType]; !ok {
|
||||
return cmn.NewError("params.Validator.PubKeyTypes[%d], %s, is an unknown pubkey type",
|
||||
i, keyType)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -94,6 +121,24 @@ func (params *ConsensusParams) Hash() []byte {
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
func (params *ConsensusParams) Equals(params2 *ConsensusParams) bool {
|
||||
return params.BlockSize == params2.BlockSize &&
|
||||
params.Evidence == params2.Evidence &&
|
||||
stringSliceEqual(params.Validator.PubKeyTypes, params2.Validator.PubKeyTypes)
|
||||
}
|
||||
|
||||
func stringSliceEqual(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(a); i++ {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Update returns a copy of the params with updates from the non-zero fields of p2.
|
||||
// NOTE: note: must not modify the original
|
||||
func (params ConsensusParams) Update(params2 *abci.ConsensusParams) ConsensusParams {
|
||||
@@ -108,8 +153,11 @@ func (params ConsensusParams) Update(params2 *abci.ConsensusParams) ConsensusPar
|
||||
res.BlockSize.MaxBytes = params2.BlockSize.MaxBytes
|
||||
res.BlockSize.MaxGas = params2.BlockSize.MaxGas
|
||||
}
|
||||
if params2.EvidenceParams != nil {
|
||||
res.EvidenceParams.MaxAge = params2.EvidenceParams.MaxAge
|
||||
if params2.Evidence != nil {
|
||||
res.Evidence.MaxAge = params2.Evidence.MaxAge
|
||||
}
|
||||
if params2.Validator != nil {
|
||||
res.Validator.PubKeyTypes = params2.Validator.PubKeyTypes
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
+42
-27
@@ -9,23 +9,32 @@ import (
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
)
|
||||
|
||||
var (
|
||||
valEd25519 = []string{ABCIPubKeyTypeEd25519}
|
||||
valSecp256k1 = []string{ABCIPubKeyTypeSecp256k1}
|
||||
)
|
||||
|
||||
func TestConsensusParamsValidation(t *testing.T) {
|
||||
testCases := []struct {
|
||||
params ConsensusParams
|
||||
valid bool
|
||||
}{
|
||||
// test block size
|
||||
0: {makeParams(1, 0, 1), true},
|
||||
1: {makeParams(0, 0, 1), false},
|
||||
2: {makeParams(47*1024*1024, 0, 1), true},
|
||||
3: {makeParams(10, 0, 1), true},
|
||||
4: {makeParams(100*1024*1024, 0, 1), true},
|
||||
5: {makeParams(101*1024*1024, 0, 1), false},
|
||||
6: {makeParams(1024*1024*1024, 0, 1), false},
|
||||
7: {makeParams(1024*1024*1024, 0, -1), false},
|
||||
0: {makeParams(1, 0, 1, valEd25519), true},
|
||||
1: {makeParams(0, 0, 1, valEd25519), false},
|
||||
2: {makeParams(47*1024*1024, 0, 1, valEd25519), true},
|
||||
3: {makeParams(10, 0, 1, valEd25519), true},
|
||||
4: {makeParams(100*1024*1024, 0, 1, valEd25519), true},
|
||||
5: {makeParams(101*1024*1024, 0, 1, valEd25519), false},
|
||||
6: {makeParams(1024*1024*1024, 0, 1, valEd25519), false},
|
||||
7: {makeParams(1024*1024*1024, 0, -1, valEd25519), false},
|
||||
// test evidence age
|
||||
8: {makeParams(1, 0, 0), false},
|
||||
9: {makeParams(1, 0, -1), false},
|
||||
8: {makeParams(1, 0, 0, valEd25519), false},
|
||||
9: {makeParams(1, 0, -1, valEd25519), false},
|
||||
// test no pubkey type provided
|
||||
10: {makeParams(1, 0, 1, []string{}), false},
|
||||
// test invalid pubkey type provided
|
||||
11: {makeParams(1, 0, 1, []string{"potatoes make good pubkeys"}), false},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
if tc.valid {
|
||||
@@ -36,28 +45,31 @@ func TestConsensusParamsValidation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func makeParams(blockBytes, blockGas, evidenceAge int64) ConsensusParams {
|
||||
func makeParams(blockBytes, blockGas, evidenceAge int64, pubkeyTypes []string) ConsensusParams {
|
||||
return ConsensusParams{
|
||||
BlockSize: BlockSize{
|
||||
BlockSize: BlockSizeParams{
|
||||
MaxBytes: blockBytes,
|
||||
MaxGas: blockGas,
|
||||
},
|
||||
EvidenceParams: EvidenceParams{
|
||||
Evidence: EvidenceParams{
|
||||
MaxAge: evidenceAge,
|
||||
},
|
||||
Validator: ValidatorParams{
|
||||
PubKeyTypes: pubkeyTypes,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestConsensusParamsHash(t *testing.T) {
|
||||
params := []ConsensusParams{
|
||||
makeParams(4, 2, 3),
|
||||
makeParams(1, 4, 3),
|
||||
makeParams(1, 2, 4),
|
||||
makeParams(2, 5, 7),
|
||||
makeParams(1, 7, 6),
|
||||
makeParams(9, 5, 4),
|
||||
makeParams(7, 8, 9),
|
||||
makeParams(4, 6, 5),
|
||||
makeParams(4, 2, 3, valEd25519),
|
||||
makeParams(1, 4, 3, valEd25519),
|
||||
makeParams(1, 2, 4, valEd25519),
|
||||
makeParams(2, 5, 7, valEd25519),
|
||||
makeParams(1, 7, 6, valEd25519),
|
||||
makeParams(9, 5, 4, valEd25519),
|
||||
makeParams(7, 8, 9, valEd25519),
|
||||
makeParams(4, 6, 5, valEd25519),
|
||||
}
|
||||
|
||||
hashes := make([][]byte, len(params))
|
||||
@@ -83,23 +95,26 @@ func TestConsensusParamsUpdate(t *testing.T) {
|
||||
}{
|
||||
// empty updates
|
||||
{
|
||||
makeParams(1, 2, 3),
|
||||
makeParams(1, 2, 3, valEd25519),
|
||||
&abci.ConsensusParams{},
|
||||
makeParams(1, 2, 3),
|
||||
makeParams(1, 2, 3, valEd25519),
|
||||
},
|
||||
// fine updates
|
||||
{
|
||||
makeParams(1, 2, 3),
|
||||
makeParams(1, 2, 3, valEd25519),
|
||||
&abci.ConsensusParams{
|
||||
BlockSize: &abci.BlockSize{
|
||||
BlockSize: &abci.BlockSizeParams{
|
||||
MaxBytes: 100,
|
||||
MaxGas: 200,
|
||||
},
|
||||
EvidenceParams: &abci.EvidenceParams{
|
||||
Evidence: &abci.EvidenceParams{
|
||||
MaxAge: 300,
|
||||
},
|
||||
Validator: &abci.ValidatorParams{
|
||||
PubKeyTypes: valSecp256k1,
|
||||
},
|
||||
},
|
||||
makeParams(100, 200, 300),
|
||||
makeParams(100, 200, 300, valSecp256k1),
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
|
||||
+25
-1
@@ -2,11 +2,12 @@ package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto/merkle"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
@@ -36,6 +37,17 @@ func (part *Part) Hash() []byte {
|
||||
return part.hash
|
||||
}
|
||||
|
||||
// ValidateBasic performs basic validation.
|
||||
func (part *Part) ValidateBasic() error {
|
||||
if part.Index < 0 {
|
||||
return errors.New("Negative Index")
|
||||
}
|
||||
if len(part.Bytes) > BlockPartSizeBytes {
|
||||
return fmt.Errorf("Too big (max: %d)", BlockPartSizeBytes)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (part *Part) String() string {
|
||||
return part.StringIndented("")
|
||||
}
|
||||
@@ -70,6 +82,18 @@ func (psh PartSetHeader) Equals(other PartSetHeader) bool {
|
||||
return psh.Total == other.Total && bytes.Equal(psh.Hash, other.Hash)
|
||||
}
|
||||
|
||||
// ValidateBasic performs basic validation.
|
||||
func (psh PartSetHeader) ValidateBasic() error {
|
||||
if psh.Total < 0 {
|
||||
return errors.New("Negative Total")
|
||||
}
|
||||
// Hash can be empty in case of POLBlockID.PartsHeader in Proposal.
|
||||
if err := ValidateHash(psh.Hash); err != nil {
|
||||
return errors.Wrap(err, "Wrong Hash")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
type PartSet struct {
|
||||
|
||||
+53
-20
@@ -15,39 +15,72 @@ var (
|
||||
)
|
||||
|
||||
// Proposal defines a block proposal for the consensus.
|
||||
// It refers to the block only by its PartSetHeader.
|
||||
// It refers to the block by BlockID field.
|
||||
// It must be signed by the correct proposer for the given Height/Round
|
||||
// to be considered valid. It may depend on votes from a previous round,
|
||||
// a so-called Proof-of-Lock (POL) round, as noted in the POLRound and POLBlockID.
|
||||
// a so-called Proof-of-Lock (POL) round, as noted in the POLRound.
|
||||
// If POLRound >= 0, then BlockID corresponds to the block that is locked in POLRound.
|
||||
type Proposal struct {
|
||||
Height int64 `json:"height"`
|
||||
Round int `json:"round"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
BlockPartsHeader PartSetHeader `json:"block_parts_header"`
|
||||
POLRound int `json:"pol_round"` // -1 if null.
|
||||
POLBlockID BlockID `json:"pol_block_id"` // zero if null.
|
||||
Signature []byte `json:"signature"`
|
||||
Type SignedMsgType
|
||||
Height int64 `json:"height"`
|
||||
Round int `json:"round"`
|
||||
POLRound int `json:"pol_round"` // -1 if null.
|
||||
BlockID BlockID `json:"block_id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Signature []byte `json:"signature"`
|
||||
}
|
||||
|
||||
// NewProposal returns a new Proposal.
|
||||
// If there is no POLRound, polRound should be -1.
|
||||
func NewProposal(height int64, round int, blockPartsHeader PartSetHeader, polRound int, polBlockID BlockID) *Proposal {
|
||||
func NewProposal(height int64, round int, polRound int, blockID BlockID) *Proposal {
|
||||
return &Proposal{
|
||||
Height: height,
|
||||
Round: round,
|
||||
Timestamp: tmtime.Now(),
|
||||
BlockPartsHeader: blockPartsHeader,
|
||||
POLRound: polRound,
|
||||
POLBlockID: polBlockID,
|
||||
Type: ProposalType,
|
||||
Height: height,
|
||||
Round: round,
|
||||
BlockID: blockID,
|
||||
POLRound: polRound,
|
||||
Timestamp: tmtime.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateBasic performs basic validation.
|
||||
func (p *Proposal) ValidateBasic() error {
|
||||
if p.Type != ProposalType {
|
||||
return errors.New("Invalid Type")
|
||||
}
|
||||
if p.Height < 0 {
|
||||
return errors.New("Negative Height")
|
||||
}
|
||||
if p.Round < 0 {
|
||||
return errors.New("Negative Round")
|
||||
}
|
||||
if p.POLRound < -1 {
|
||||
return errors.New("Negative POLRound (exception: -1)")
|
||||
}
|
||||
if err := p.BlockID.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("Wrong BlockID: %v", err)
|
||||
}
|
||||
|
||||
// NOTE: Timestamp validation is subtle and handled elsewhere.
|
||||
|
||||
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)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns a string representation of the Proposal.
|
||||
func (p *Proposal) String() string {
|
||||
return fmt.Sprintf("Proposal{%v/%v %v (%v,%v) %X @ %s}",
|
||||
p.Height, p.Round, p.BlockPartsHeader, p.POLRound,
|
||||
p.POLBlockID,
|
||||
cmn.Fingerprint(p.Signature), CanonicalTime(p.Timestamp))
|
||||
return fmt.Sprintf("Proposal{%v/%v (%v, %v) %X @ %s}",
|
||||
p.Height,
|
||||
p.Round,
|
||||
p.BlockID,
|
||||
p.POLRound,
|
||||
cmn.Fingerprint(p.Signature),
|
||||
CanonicalTime(p.Timestamp))
|
||||
}
|
||||
|
||||
// SignBytes returns the Proposal bytes for signing
|
||||
|
||||
@@ -15,11 +15,11 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
testProposal = &Proposal{
|
||||
Height: 12345,
|
||||
Round: 23456,
|
||||
BlockPartsHeader: PartSetHeader{111, []byte("blockparts")},
|
||||
POLRound: -1,
|
||||
Timestamp: stamp,
|
||||
Height: 12345,
|
||||
Round: 23456,
|
||||
BlockID: BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}},
|
||||
POLRound: -1,
|
||||
Timestamp: stamp,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestProposalSignable(t *testing.T) {
|
||||
|
||||
func TestProposalString(t *testing.T) {
|
||||
str := testProposal.String()
|
||||
expected := `Proposal{12345/23456 111:626C6F636B70 (-1,:0:000000000000) 000000000000 @ 2018-02-11T07:09:22.765Z}`
|
||||
expected := `Proposal{12345/23456 (010203:111:626C6F636B70, -1) 000000000000 @ 2018-02-11T07:09:22.765Z}`
|
||||
if str != expected {
|
||||
t.Errorf("Got unexpected string for Proposal. Expected:\n%v\nGot:\n%v", expected, str)
|
||||
}
|
||||
@@ -44,7 +44,9 @@ func TestProposalVerifySignature(t *testing.T) {
|
||||
privVal := NewMockPV()
|
||||
pubKey := privVal.GetPubKey()
|
||||
|
||||
prop := NewProposal(4, 2, PartSetHeader{777, []byte("proper")}, 2, BlockID{})
|
||||
prop := NewProposal(
|
||||
4, 2, 2,
|
||||
BlockID{[]byte{1, 2, 3}, PartSetHeader{777, []byte("proper")}})
|
||||
signBytes := prop.SignBytes("test_chain_id")
|
||||
|
||||
// sign it
|
||||
|
||||
+180
-82
@@ -1,22 +1,9 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: block.proto
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: types/proto3/block.proto
|
||||
|
||||
/*
|
||||
Package proto3 is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
block.proto
|
||||
|
||||
It has these top-level messages:
|
||||
PartSetHeader
|
||||
BlockID
|
||||
Header
|
||||
Version
|
||||
Timestamp
|
||||
*/
|
||||
package proto3
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
@@ -29,17 +16,39 @@ var _ = math.Inf
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type PartSetHeader struct {
|
||||
Total int32 `protobuf:"zigzag32,1,opt,name=Total" json:"Total,omitempty"`
|
||||
Hash []byte `protobuf:"bytes,2,opt,name=Hash,proto3" json:"Hash,omitempty"`
|
||||
Total int32 `protobuf:"varint,1,opt,name=Total,proto3" json:"Total,omitempty"`
|
||||
Hash []byte `protobuf:"bytes,2,opt,name=Hash,proto3" json:"Hash,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *PartSetHeader) Reset() { *m = PartSetHeader{} }
|
||||
func (m *PartSetHeader) String() string { return proto.CompactTextString(m) }
|
||||
func (*PartSetHeader) ProtoMessage() {}
|
||||
func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
func (m *PartSetHeader) Reset() { *m = PartSetHeader{} }
|
||||
func (m *PartSetHeader) String() string { return proto.CompactTextString(m) }
|
||||
func (*PartSetHeader) ProtoMessage() {}
|
||||
func (*PartSetHeader) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_block_57c41dfc0fc285b3, []int{0}
|
||||
}
|
||||
func (m *PartSetHeader) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PartSetHeader.Unmarshal(m, b)
|
||||
}
|
||||
func (m *PartSetHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_PartSetHeader.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *PartSetHeader) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PartSetHeader.Merge(dst, src)
|
||||
}
|
||||
func (m *PartSetHeader) XXX_Size() int {
|
||||
return xxx_messageInfo_PartSetHeader.Size(m)
|
||||
}
|
||||
func (m *PartSetHeader) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PartSetHeader.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_PartSetHeader proto.InternalMessageInfo
|
||||
|
||||
func (m *PartSetHeader) GetTotal() int32 {
|
||||
if m != nil {
|
||||
@@ -56,14 +65,36 @@ func (m *PartSetHeader) GetHash() []byte {
|
||||
}
|
||||
|
||||
type BlockID struct {
|
||||
Hash []byte `protobuf:"bytes,1,opt,name=Hash,proto3" json:"Hash,omitempty"`
|
||||
PartsHeader *PartSetHeader `protobuf:"bytes,2,opt,name=PartsHeader" json:"PartsHeader,omitempty"`
|
||||
Hash []byte `protobuf:"bytes,1,opt,name=Hash,proto3" json:"Hash,omitempty"`
|
||||
PartsHeader *PartSetHeader `protobuf:"bytes,2,opt,name=PartsHeader" json:"PartsHeader,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *BlockID) Reset() { *m = BlockID{} }
|
||||
func (m *BlockID) String() string { return proto.CompactTextString(m) }
|
||||
func (*BlockID) ProtoMessage() {}
|
||||
func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
func (m *BlockID) Reset() { *m = BlockID{} }
|
||||
func (m *BlockID) String() string { return proto.CompactTextString(m) }
|
||||
func (*BlockID) ProtoMessage() {}
|
||||
func (*BlockID) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_block_57c41dfc0fc285b3, []int{1}
|
||||
}
|
||||
func (m *BlockID) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_BlockID.Unmarshal(m, b)
|
||||
}
|
||||
func (m *BlockID) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_BlockID.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *BlockID) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_BlockID.Merge(dst, src)
|
||||
}
|
||||
func (m *BlockID) XXX_Size() int {
|
||||
return xxx_messageInfo_BlockID.Size(m)
|
||||
}
|
||||
func (m *BlockID) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_BlockID.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_BlockID proto.InternalMessageInfo
|
||||
|
||||
func (m *BlockID) GetHash() []byte {
|
||||
if m != nil {
|
||||
@@ -82,11 +113,11 @@ func (m *BlockID) GetPartsHeader() *PartSetHeader {
|
||||
type Header struct {
|
||||
// basic block info
|
||||
Version *Version `protobuf:"bytes,1,opt,name=Version" json:"Version,omitempty"`
|
||||
ChainID string `protobuf:"bytes,2,opt,name=ChainID" json:"ChainID,omitempty"`
|
||||
Height int64 `protobuf:"zigzag64,3,opt,name=Height" json:"Height,omitempty"`
|
||||
ChainID string `protobuf:"bytes,2,opt,name=ChainID,proto3" json:"ChainID,omitempty"`
|
||||
Height int64 `protobuf:"varint,3,opt,name=Height,proto3" json:"Height,omitempty"`
|
||||
Time *Timestamp `protobuf:"bytes,4,opt,name=Time" json:"Time,omitempty"`
|
||||
NumTxs int64 `protobuf:"zigzag64,5,opt,name=NumTxs" json:"NumTxs,omitempty"`
|
||||
TotalTxs int64 `protobuf:"zigzag64,6,opt,name=TotalTxs" json:"TotalTxs,omitempty"`
|
||||
NumTxs int64 `protobuf:"varint,5,opt,name=NumTxs,proto3" json:"NumTxs,omitempty"`
|
||||
TotalTxs int64 `protobuf:"varint,6,opt,name=TotalTxs,proto3" json:"TotalTxs,omitempty"`
|
||||
// prev block info
|
||||
LastBlockID *BlockID `protobuf:"bytes,7,opt,name=LastBlockID" json:"LastBlockID,omitempty"`
|
||||
// hashes of block data
|
||||
@@ -99,14 +130,36 @@ type Header struct {
|
||||
AppHash []byte `protobuf:"bytes,13,opt,name=AppHash,proto3" json:"AppHash,omitempty"`
|
||||
LastResultsHash []byte `protobuf:"bytes,14,opt,name=LastResultsHash,proto3" json:"LastResultsHash,omitempty"`
|
||||
// consensus info
|
||||
EvidenceHash []byte `protobuf:"bytes,15,opt,name=EvidenceHash,proto3" json:"EvidenceHash,omitempty"`
|
||||
ProposerAddress []byte `protobuf:"bytes,16,opt,name=ProposerAddress,proto3" json:"ProposerAddress,omitempty"`
|
||||
EvidenceHash []byte `protobuf:"bytes,15,opt,name=EvidenceHash,proto3" json:"EvidenceHash,omitempty"`
|
||||
ProposerAddress []byte `protobuf:"bytes,16,opt,name=ProposerAddress,proto3" json:"ProposerAddress,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Header) Reset() { *m = Header{} }
|
||||
func (m *Header) String() string { return proto.CompactTextString(m) }
|
||||
func (*Header) ProtoMessage() {}
|
||||
func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
func (m *Header) Reset() { *m = Header{} }
|
||||
func (m *Header) String() string { return proto.CompactTextString(m) }
|
||||
func (*Header) ProtoMessage() {}
|
||||
func (*Header) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_block_57c41dfc0fc285b3, []int{2}
|
||||
}
|
||||
func (m *Header) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Header.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Header.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Header) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Header.Merge(dst, src)
|
||||
}
|
||||
func (m *Header) XXX_Size() int {
|
||||
return xxx_messageInfo_Header.Size(m)
|
||||
}
|
||||
func (m *Header) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Header.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Header proto.InternalMessageInfo
|
||||
|
||||
func (m *Header) GetVersion() *Version {
|
||||
if m != nil {
|
||||
@@ -221,14 +274,36 @@ func (m *Header) GetProposerAddress() []byte {
|
||||
}
|
||||
|
||||
type Version struct {
|
||||
Block uint64 `protobuf:"varint,1,opt,name=Block" json:"Block,omitempty"`
|
||||
App uint64 `protobuf:"varint,2,opt,name=App" json:"App,omitempty"`
|
||||
Block uint64 `protobuf:"varint,1,opt,name=Block,proto3" json:"Block,omitempty"`
|
||||
App uint64 `protobuf:"varint,2,opt,name=App,proto3" json:"App,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Version) Reset() { *m = Version{} }
|
||||
func (m *Version) String() string { return proto.CompactTextString(m) }
|
||||
func (*Version) ProtoMessage() {}
|
||||
func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
func (m *Version) Reset() { *m = Version{} }
|
||||
func (m *Version) String() string { return proto.CompactTextString(m) }
|
||||
func (*Version) ProtoMessage() {}
|
||||
func (*Version) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_block_57c41dfc0fc285b3, []int{3}
|
||||
}
|
||||
func (m *Version) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Version.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Version.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Version) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Version.Merge(dst, src)
|
||||
}
|
||||
func (m *Version) XXX_Size() int {
|
||||
return xxx_messageInfo_Version.Size(m)
|
||||
}
|
||||
func (m *Version) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Version.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Version proto.InternalMessageInfo
|
||||
|
||||
func (m *Version) GetBlock() uint64 {
|
||||
if m != nil {
|
||||
@@ -250,14 +325,36 @@ func (m *Version) GetApp() uint64 {
|
||||
// https://github.com/google/protobuf/blob/d2980062c859649523d5fd51d6b55ab310e47482/src/google/protobuf/timestamp.proto#L123-L135
|
||||
// NOTE/XXX: nanos do not get skipped if they are zero in amino.
|
||||
type Timestamp struct {
|
||||
Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"`
|
||||
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
|
||||
Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
|
||||
Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Timestamp) Reset() { *m = Timestamp{} }
|
||||
func (m *Timestamp) String() string { return proto.CompactTextString(m) }
|
||||
func (*Timestamp) ProtoMessage() {}
|
||||
func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||
func (m *Timestamp) Reset() { *m = Timestamp{} }
|
||||
func (m *Timestamp) String() string { return proto.CompactTextString(m) }
|
||||
func (*Timestamp) ProtoMessage() {}
|
||||
func (*Timestamp) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_block_57c41dfc0fc285b3, []int{4}
|
||||
}
|
||||
func (m *Timestamp) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Timestamp.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Timestamp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Timestamp.Merge(dst, src)
|
||||
}
|
||||
func (m *Timestamp) XXX_Size() int {
|
||||
return xxx_messageInfo_Timestamp.Size(m)
|
||||
}
|
||||
func (m *Timestamp) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Timestamp.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Timestamp proto.InternalMessageInfo
|
||||
|
||||
func (m *Timestamp) GetSeconds() int64 {
|
||||
if m != nil {
|
||||
@@ -281,36 +378,37 @@ func init() {
|
||||
proto.RegisterType((*Timestamp)(nil), "proto3.Timestamp")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("block.proto", fileDescriptor0) }
|
||||
func init() { proto.RegisterFile("types/proto3/block.proto", fileDescriptor_block_57c41dfc0fc285b3) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 443 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0xcd, 0x6a, 0xdb, 0x40,
|
||||
0x10, 0x46, 0xb5, 0x6c, 0xc7, 0x23, 0x3b, 0x4e, 0x86, 0xb6, 0x88, 0x9e, 0x8c, 0x68, 0x8b, 0x7b,
|
||||
0x31, 0x24, 0x39, 0x94, 0xd2, 0x93, 0x6b, 0x17, 0x12, 0x28, 0x21, 0x6c, 0x8d, 0xef, 0x1b, 0x6b,
|
||||
0xa9, 0x45, 0x2d, 0xad, 0xd0, 0xac, 0x4b, 0xde, 0xb0, 0xaf, 0x55, 0x66, 0x56, 0x52, 0x23, 0x93,
|
||||
0x93, 0xf7, 0xfb, 0x99, 0x6f, 0x76, 0xc7, 0x23, 0x88, 0x1e, 0x0f, 0x76, 0xf7, 0x7b, 0x51, 0x56,
|
||||
0xd6, 0x59, 0x1c, 0xc8, 0xcf, 0x4d, 0xf2, 0x05, 0x26, 0x0f, 0xba, 0x72, 0x3f, 0x8d, 0xbb, 0x35,
|
||||
0x3a, 0x35, 0x15, 0xbe, 0x86, 0xfe, 0xc6, 0x3a, 0x7d, 0x88, 0x83, 0x59, 0x30, 0xbf, 0x54, 0x1e,
|
||||
0x20, 0x42, 0x78, 0xab, 0x69, 0x1f, 0xbf, 0x9a, 0x05, 0xf3, 0xb1, 0x92, 0x73, 0xb2, 0x85, 0xe1,
|
||||
0x37, 0x4e, 0xbc, 0x5b, 0xb7, 0x72, 0xf0, 0x5f, 0xc6, 0xcf, 0x10, 0x71, 0x32, 0xf9, 0x5c, 0xa9,
|
||||
0x8c, 0xae, 0xdf, 0xf8, 0xf6, 0x37, 0x8b, 0x4e, 0x53, 0xf5, 0xdc, 0x99, 0xfc, 0x0d, 0x61, 0x50,
|
||||
0x5f, 0xe6, 0x13, 0x0c, 0xb7, 0xa6, 0xa2, 0xcc, 0x16, 0x12, 0x1d, 0x5d, 0x4f, 0x9b, 0xfa, 0x9a,
|
||||
0x56, 0x8d, 0x8e, 0x31, 0x0c, 0x57, 0x7b, 0x9d, 0x15, 0x77, 0x6b, 0x69, 0x35, 0x52, 0x0d, 0xc4,
|
||||
0xb7, 0x1c, 0x97, 0xfd, 0xda, 0xbb, 0xb8, 0x37, 0x0b, 0xe6, 0xa8, 0x6a, 0x84, 0x1f, 0x20, 0xdc,
|
||||
0x64, 0xb9, 0x89, 0x43, 0x49, 0xbe, 0x6c, 0x92, 0x99, 0x23, 0xa7, 0xf3, 0x52, 0x89, 0xcc, 0xe5,
|
||||
0xf7, 0xc7, 0x7c, 0xf3, 0x44, 0x71, 0xdf, 0x97, 0x7b, 0x84, 0xef, 0xe0, 0x4c, 0x66, 0xc3, 0xca,
|
||||
0x40, 0x94, 0x16, 0xe3, 0x15, 0x44, 0x3f, 0x34, 0xb9, 0x7a, 0x3c, 0xf1, 0xb0, 0x7b, 0xf7, 0x9a,
|
||||
0x56, 0xcf, 0x3d, 0xf8, 0x11, 0xce, 0x19, 0xae, 0x6c, 0x9e, 0x67, 0x4e, 0x86, 0x79, 0x26, 0xc3,
|
||||
0x3c, 0x61, 0xb9, 0xed, 0x5a, 0x3b, 0x2d, 0x8e, 0x91, 0x38, 0x5a, 0xcc, 0x19, 0x5b, 0x7d, 0xc8,
|
||||
0x52, 0xed, 0x6c, 0x45, 0xe2, 0x00, 0x9f, 0xd1, 0x65, 0x71, 0x01, 0x78, 0x6f, 0x9e, 0xdc, 0x89,
|
||||
0x37, 0x12, 0xef, 0x0b, 0x0a, 0xbe, 0x87, 0xc9, 0xca, 0x16, 0x64, 0x0a, 0x3a, 0x7a, 0xeb, 0x58,
|
||||
0xac, 0x5d, 0x92, 0xff, 0x81, 0x65, 0x59, 0x8a, 0x3e, 0x11, 0xbd, 0x81, 0x38, 0x87, 0x29, 0xbf,
|
||||
0x42, 0x19, 0x3a, 0x1e, 0x9c, 0x4f, 0x38, 0x17, 0xc7, 0x29, 0x8d, 0x09, 0x8c, 0xbf, 0xff, 0xc9,
|
||||
0x52, 0x53, 0xec, 0x8c, 0xd8, 0xa6, 0x62, 0xeb, 0x70, 0x9c, 0xf6, 0x50, 0xd9, 0xd2, 0x92, 0xa9,
|
||||
0x96, 0x69, 0x5a, 0x19, 0xa2, 0xf8, 0xc2, 0xa7, 0x9d, 0xd0, 0xc9, 0x55, 0xbb, 0x3e, 0xbc, 0xd6,
|
||||
0x32, 0x69, 0xd9, 0xa3, 0x50, 0x79, 0x80, 0x17, 0xd0, 0x5b, 0x96, 0xa5, 0x2c, 0x4c, 0xa8, 0xf8,
|
||||
0x98, 0x7c, 0x85, 0x51, 0xbb, 0x00, 0xfc, 0x22, 0x32, 0x3b, 0x5b, 0xa4, 0x24, 0x65, 0x3d, 0xd5,
|
||||
0x40, 0x8e, 0x2b, 0x74, 0x61, 0x49, 0x4a, 0xfb, 0xca, 0x83, 0xc7, 0xfa, 0xa3, 0xfa, 0x17, 0x00,
|
||||
0x00, 0xff, 0xff, 0x8f, 0x82, 0xc0, 0x0c, 0x6a, 0x03, 0x00, 0x00,
|
||||
var fileDescriptor_block_57c41dfc0fc285b3 = []byte{
|
||||
// 451 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0x5f, 0x6f, 0xd3, 0x30,
|
||||
0x10, 0x57, 0x68, 0xda, 0xae, 0x97, 0x76, 0x1d, 0x27, 0x40, 0x16, 0x4f, 0x55, 0x04, 0xa8, 0xbc,
|
||||
0x74, 0xda, 0xf6, 0x80, 0x10, 0x4f, 0xa5, 0x45, 0xda, 0x24, 0x34, 0x4d, 0xa6, 0xea, 0xbb, 0xd7,
|
||||
0x58, 0x34, 0xa2, 0x89, 0xa3, 0x9c, 0x8b, 0xc6, 0x27, 0xe4, 0x6b, 0x21, 0x9f, 0x93, 0xd0, 0x44,
|
||||
0x7b, 0xf3, 0xef, 0xcf, 0xfd, 0xce, 0xbe, 0x5c, 0x40, 0xd8, 0x3f, 0x85, 0xa6, 0xcb, 0xa2, 0x34,
|
||||
0xd6, 0xdc, 0x5c, 0x3e, 0x1e, 0xcc, 0xee, 0xd7, 0x82, 0x01, 0x0e, 0x3c, 0x17, 0x7f, 0x86, 0xc9,
|
||||
0x83, 0x2a, 0xed, 0x0f, 0x6d, 0x6f, 0xb5, 0x4a, 0x74, 0x89, 0xaf, 0xa0, 0xbf, 0x31, 0x56, 0x1d,
|
||||
0x44, 0x30, 0x0b, 0xe6, 0x7d, 0xe9, 0x01, 0x22, 0x84, 0xb7, 0x8a, 0xf6, 0xe2, 0xc5, 0x2c, 0x98,
|
||||
0x8f, 0x25, 0x9f, 0xe3, 0x2d, 0x0c, 0xbf, 0xba, 0xc4, 0xbb, 0x75, 0x23, 0x07, 0xff, 0x65, 0xfc,
|
||||
0x04, 0x91, 0x4b, 0x26, 0x9f, 0xcb, 0x95, 0xd1, 0xf5, 0x6b, 0xdf, 0xfe, 0x66, 0xd1, 0x6a, 0x2a,
|
||||
0x4f, 0x9d, 0xf1, 0xdf, 0x10, 0x06, 0xd5, 0x65, 0x3e, 0xc2, 0x70, 0xab, 0x4b, 0x4a, 0x4d, 0xce,
|
||||
0xd1, 0xd1, 0xf5, 0xb4, 0xae, 0xaf, 0x68, 0x59, 0xeb, 0x28, 0x60, 0xb8, 0xda, 0xab, 0x34, 0xbf,
|
||||
0x5b, 0x73, 0xab, 0x91, 0xac, 0x21, 0xbe, 0x71, 0x71, 0xe9, 0xcf, 0xbd, 0x15, 0xbd, 0x59, 0x30,
|
||||
0xef, 0xc9, 0x0a, 0xe1, 0x7b, 0x08, 0x37, 0x69, 0xa6, 0x45, 0xc8, 0xc9, 0x2f, 0xeb, 0x64, 0xc7,
|
||||
0x91, 0x55, 0x59, 0x21, 0x59, 0x76, 0xe5, 0xf7, 0xc7, 0x6c, 0xf3, 0x44, 0xa2, 0xef, 0xcb, 0x3d,
|
||||
0xc2, 0xb7, 0x70, 0xc6, 0xb3, 0x71, 0xca, 0x80, 0x95, 0x06, 0xe3, 0x15, 0x44, 0xdf, 0x15, 0xd9,
|
||||
0x6a, 0x3c, 0x62, 0xd8, 0xbe, 0x7b, 0x45, 0xcb, 0x53, 0x0f, 0x7e, 0x80, 0x73, 0x07, 0x57, 0x26,
|
||||
0xcb, 0x52, 0xcb, 0xc3, 0x3c, 0xe3, 0x61, 0x76, 0x58, 0xd7, 0x76, 0xad, 0xac, 0x62, 0xc7, 0x88,
|
||||
0x1d, 0x0d, 0x76, 0x19, 0x5b, 0x75, 0x48, 0x13, 0x65, 0x4d, 0x49, 0xec, 0x00, 0x9f, 0xd1, 0x66,
|
||||
0x71, 0x01, 0x78, 0xaf, 0x9f, 0x6c, 0xc7, 0x1b, 0xb1, 0xf7, 0x19, 0x05, 0xdf, 0xc1, 0x64, 0x65,
|
||||
0x72, 0xd2, 0x39, 0x1d, 0xbd, 0x75, 0xcc, 0xd6, 0x36, 0xe9, 0xbe, 0xc0, 0xb2, 0x28, 0x58, 0x9f,
|
||||
0xb0, 0x5e, 0x43, 0x9c, 0xc3, 0xd4, 0xbd, 0x42, 0x6a, 0x3a, 0x1e, 0xac, 0x4f, 0x38, 0x67, 0x47,
|
||||
0x97, 0xc6, 0x18, 0xc6, 0xdf, 0x7e, 0xa7, 0x89, 0xce, 0x77, 0x9a, 0x6d, 0x53, 0xb6, 0xb5, 0x38,
|
||||
0x97, 0xf6, 0x50, 0x9a, 0xc2, 0x90, 0x2e, 0x97, 0x49, 0x52, 0x6a, 0x22, 0x71, 0xe1, 0xd3, 0x3a,
|
||||
0x74, 0x7c, 0xd5, 0xac, 0x8f, 0x5b, 0x6b, 0x9e, 0x34, 0xef, 0x51, 0x28, 0x3d, 0xc0, 0x0b, 0xe8,
|
||||
0x2d, 0x8b, 0x82, 0x17, 0x26, 0x94, 0xee, 0x18, 0x7f, 0x81, 0x51, 0xb3, 0x00, 0xee, 0x45, 0xa4,
|
||||
0x77, 0x26, 0x4f, 0x88, 0xcb, 0x7a, 0xb2, 0x86, 0x2e, 0x2e, 0x57, 0xb9, 0x21, 0x2e, 0xed, 0x4b,
|
||||
0x0f, 0x1e, 0xab, 0x9f, 0xea, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4f, 0x84, 0xb5, 0xf8, 0x77,
|
||||
0x03, 0x00, 0x00,
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package proto3;
|
||||
|
||||
|
||||
message PartSetHeader {
|
||||
sint32 Total = 1;
|
||||
int32 Total = 1;
|
||||
bytes Hash = 2;
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@ message Header {
|
||||
// basic block info
|
||||
Version Version = 1;
|
||||
string ChainID = 2;
|
||||
sint64 Height = 3;
|
||||
int64 Height = 3;
|
||||
Timestamp Time = 4;
|
||||
sint64 NumTxs = 5;
|
||||
sint64 TotalTxs = 6;
|
||||
int64 NumTxs = 5;
|
||||
int64 TotalTxs = 6;
|
||||
|
||||
// prev block info
|
||||
BlockID LastBlockID = 7;
|
||||
|
||||
+18
-6
@@ -24,6 +24,12 @@ const (
|
||||
ABCIPubKeyTypeSecp256k1 = "secp256k1"
|
||||
)
|
||||
|
||||
// TODO: Make non-global by allowing for registration of more pubkey types
|
||||
var ABCIPubKeyTypesToAminoRoutes = map[string]string{
|
||||
ABCIPubKeyTypeEd25519: ed25519.PubKeyAminoRoute,
|
||||
ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyAminoRoute,
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
|
||||
// TM2PB is used for converting Tendermint ABCI to protobuf ABCI.
|
||||
@@ -119,12 +125,15 @@ func (tm2pb) ValidatorUpdates(vals *ValidatorSet) []abci.ValidatorUpdate {
|
||||
|
||||
func (tm2pb) ConsensusParams(params *ConsensusParams) *abci.ConsensusParams {
|
||||
return &abci.ConsensusParams{
|
||||
BlockSize: &abci.BlockSize{
|
||||
BlockSize: &abci.BlockSizeParams{
|
||||
MaxBytes: params.BlockSize.MaxBytes,
|
||||
MaxGas: params.BlockSize.MaxGas,
|
||||
},
|
||||
EvidenceParams: &abci.EvidenceParams{
|
||||
MaxAge: params.EvidenceParams.MaxAge,
|
||||
Evidence: &abci.EvidenceParams{
|
||||
MaxAge: params.Evidence.MaxAge,
|
||||
},
|
||||
Validator: &abci.ValidatorParams{
|
||||
PubKeyTypes: params.Validator.PubKeyTypes,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -215,12 +224,15 @@ func (pb2tm) ValidatorUpdates(vals []abci.ValidatorUpdate) ([]*Validator, error)
|
||||
|
||||
func (pb2tm) ConsensusParams(csp *abci.ConsensusParams) ConsensusParams {
|
||||
return ConsensusParams{
|
||||
BlockSize: BlockSize{
|
||||
BlockSize: BlockSizeParams{
|
||||
MaxBytes: csp.BlockSize.MaxBytes,
|
||||
MaxGas: csp.BlockSize.MaxGas,
|
||||
},
|
||||
EvidenceParams: EvidenceParams{
|
||||
MaxAge: csp.EvidenceParams.MaxAge,
|
||||
Evidence: EvidenceParams{
|
||||
MaxAge: csp.Evidence.MaxAge,
|
||||
},
|
||||
Validator: ValidatorParams{
|
||||
PubKeyTypes: csp.Validator.PubKeyTypes,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,6 @@ func TestABCIValidators(t *testing.T) {
|
||||
|
||||
func TestABCIConsensusParams(t *testing.T) {
|
||||
cp := DefaultConsensusParams()
|
||||
cp.EvidenceParams.MaxAge = 0 // TODO add this to ABCI
|
||||
abciCP := TM2PB.ConsensusParams(cp)
|
||||
cp2 := PB2TM.ConsensusParams(abciCP)
|
||||
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
)
|
||||
|
||||
var (
|
||||
// MaxSignatureSize is a maximum allowed signature size for the Heartbeat,
|
||||
// Proposal and Vote.
|
||||
// XXX: secp256k1 does not have Size nor MaxSize defined.
|
||||
MaxSignatureSize = cmn.MaxInt(ed25519.SignatureSize, 64)
|
||||
)
|
||||
|
||||
// Signable is an interface for all signable things.
|
||||
// It typically removes signatures before serializing.
|
||||
// SignBytes returns the bytes to be signed
|
||||
|
||||
@@ -15,11 +15,10 @@ const (
|
||||
HeartbeatType SignedMsgType = 0x30
|
||||
)
|
||||
|
||||
func IsVoteTypeValid(type_ SignedMsgType) bool {
|
||||
switch type_ {
|
||||
case PrevoteType:
|
||||
return true
|
||||
case PrecommitType:
|
||||
// IsVoteTypeValid returns true if t is a valid vote type.
|
||||
func IsVoteTypeValid(t SignedMsgType) bool {
|
||||
switch t {
|
||||
case PrevoteType, PrecommitType:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
)
|
||||
|
||||
// ValidateTime does a basic time validation ensuring time does not drift too
|
||||
// much: +/- one year.
|
||||
// TODO: reduce this to eg 1 day
|
||||
// NOTE: DO NOT USE in ValidateBasic methods in this package. This function
|
||||
// can only be used for real time validation, like on proposals and votes
|
||||
// in the consensus. If consensus is stuck, and rounds increase for more than a day,
|
||||
// having only a 1-day band here could break things...
|
||||
// Can't use for validating blocks because we may be syncing years worth of history.
|
||||
func ValidateTime(t time.Time) error {
|
||||
var (
|
||||
now = tmtime.Now()
|
||||
oneYear = 8766 * time.Hour
|
||||
)
|
||||
if t.Before(now.Add(-oneYear)) || t.After(now.Add(oneYear)) {
|
||||
return fmt.Errorf("Time drifted too much. Expected: -1 < %v < 1 year", now)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateHash returns an error if the hash is not empty, but its
|
||||
// size != tmhash.Size.
|
||||
func ValidateHash(h []byte) error {
|
||||
if len(h) > 0 && len(h) != tmhash.Size {
|
||||
return fmt.Errorf("Expected size to be %d bytes, got %d bytes",
|
||||
tmhash.Size,
|
||||
len(h),
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+4
-4
@@ -77,15 +77,15 @@ func (v *Validator) Hash() []byte {
|
||||
}
|
||||
|
||||
// Bytes computes the unique encoding of a validator with a given voting power.
|
||||
// These are the bytes that gets hashed in consensus. It excludes pubkey
|
||||
// as its redundant with the address. This also excludes accum which changes
|
||||
// These are the bytes that gets hashed in consensus. It excludes address
|
||||
// as its redundant with the pubkey. This also excludes accum which changes
|
||||
// every round.
|
||||
func (v *Validator) Bytes() []byte {
|
||||
return cdcEncode((struct {
|
||||
Address Address
|
||||
PubKey crypto.PubKey
|
||||
VotingPower int64
|
||||
}{
|
||||
v.Address,
|
||||
v.PubKey,
|
||||
v.VotingPower,
|
||||
}))
|
||||
}
|
||||
|
||||
+43
-6
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
const (
|
||||
// MaxVoteBytes is a maximum vote size (including amino overhead).
|
||||
MaxVoteBytes int64 = 203
|
||||
MaxVoteBytes int64 = 223
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -46,15 +46,16 @@ func NewConflictingVoteError(val *Validator, voteA, voteB *Vote) *ErrVoteConflic
|
||||
// Address is hex bytes.
|
||||
type Address = crypto.Address
|
||||
|
||||
// Represents a prevote, precommit, or commit vote from validators for consensus.
|
||||
// Vote represents a prevote, precommit, or commit vote from validators for
|
||||
// consensus.
|
||||
type Vote struct {
|
||||
ValidatorAddress Address `json:"validator_address"`
|
||||
ValidatorIndex int `json:"validator_index"`
|
||||
Type SignedMsgType `json:"type"`
|
||||
Height int64 `json:"height"`
|
||||
Round int `json:"round"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Type SignedMsgType `json:"type"`
|
||||
BlockID BlockID `json:"block_id"` // zero if vote is nil.
|
||||
ValidatorAddress Address `json:"validator_address"`
|
||||
ValidatorIndex int `json:"validator_index"`
|
||||
Signature []byte `json:"signature"`
|
||||
}
|
||||
|
||||
@@ -94,7 +95,8 @@ func (vote *Vote) String() string {
|
||||
typeString,
|
||||
cmn.Fingerprint(vote.BlockID.Hash),
|
||||
cmn.Fingerprint(vote.Signature),
|
||||
CanonicalTime(vote.Timestamp))
|
||||
CanonicalTime(vote.Timestamp),
|
||||
)
|
||||
}
|
||||
|
||||
func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
|
||||
@@ -107,3 +109,38 @@ func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateBasic performs basic validation.
|
||||
func (vote *Vote) ValidateBasic() error {
|
||||
if !IsVoteTypeValid(vote.Type) {
|
||||
return errors.New("Invalid Type")
|
||||
}
|
||||
if vote.Height < 0 {
|
||||
return errors.New("Negative Height")
|
||||
}
|
||||
if vote.Round < 0 {
|
||||
return errors.New("Negative Round")
|
||||
}
|
||||
|
||||
// NOTE: Timestamp validation is subtle and handled elsewhere.
|
||||
|
||||
if err := vote.BlockID.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("Wrong BlockID: %v", err)
|
||||
}
|
||||
if len(vote.ValidatorAddress) != crypto.AddressSize {
|
||||
return fmt.Errorf("Expected ValidatorAddress size to be %d bytes, got %d bytes",
|
||||
crypto.AddressSize,
|
||||
len(vote.ValidatorAddress),
|
||||
)
|
||||
}
|
||||
if vote.ValidatorIndex < 0 {
|
||||
return errors.New("Negative ValidatorIndex")
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
+22
-7
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
)
|
||||
@@ -26,12 +27,10 @@ func exampleVote(t byte) *Vote {
|
||||
}
|
||||
|
||||
return &Vote{
|
||||
ValidatorAddress: tmhash.Sum([]byte("validator_address")),
|
||||
ValidatorIndex: 56789,
|
||||
Height: 12345,
|
||||
Round: 2,
|
||||
Timestamp: stamp,
|
||||
Type: SignedMsgType(t),
|
||||
Type: SignedMsgType(t),
|
||||
Height: 12345,
|
||||
Round: 2,
|
||||
Timestamp: stamp,
|
||||
BlockID: BlockID{
|
||||
Hash: tmhash.Sum([]byte("blockID_hash")),
|
||||
PartsHeader: PartSetHeader{
|
||||
@@ -39,6 +38,8 @@ func exampleVote(t byte) *Vote {
|
||||
Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")),
|
||||
},
|
||||
},
|
||||
ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
|
||||
ValidatorIndex: 56789,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +212,7 @@ func TestMaxVoteBytes(t *testing.T) {
|
||||
timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
|
||||
|
||||
vote := &Vote{
|
||||
ValidatorAddress: tmhash.Sum([]byte("validator_address")),
|
||||
ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
|
||||
ValidatorIndex: math.MaxInt64,
|
||||
Height: math.MaxInt64,
|
||||
Round: math.MaxInt64,
|
||||
@@ -235,3 +236,17 @@ func TestMaxVoteBytes(t *testing.T) {
|
||||
|
||||
assert.EqualValues(t, MaxVoteBytes, len(bz))
|
||||
}
|
||||
|
||||
func TestVoteString(t *testing.T) {
|
||||
str := examplePrecommit().String()
|
||||
expected := `Vote{56789:6AF1F4111082 12345/02/2(Precommit) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}`
|
||||
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}`
|
||||
if str2 != expected {
|
||||
t.Errorf("Got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str2)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user