github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/types/params.go (about)

     1  package types
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"time"
     7  
     8  	abci "github.com/franono/tendermint/abci/types"
     9  	"github.com/franono/tendermint/crypto/tmhash"
    10  	tmstrings "github.com/franono/tendermint/libs/strings"
    11  )
    12  
    13  const (
    14  	// MaxBlockSizeBytes is the maximum permitted size of the blocks.
    15  	MaxBlockSizeBytes = 104857600 // 100MB
    16  
    17  	// BlockPartSizeBytes is the size of one block part.
    18  	BlockPartSizeBytes = 65536 // 64kB
    19  
    20  	// MaxBlockPartsCount is the maximum number of block parts.
    21  	MaxBlockPartsCount = (MaxBlockSizeBytes / BlockPartSizeBytes) + 1
    22  
    23  	// Restrict the upper bound of the amount of evidence (uses uint16 for safe conversion)
    24  	MaxEvidencePerBlock = 65535
    25  )
    26  
    27  // ConsensusParams contains consensus critical parameters that determine the
    28  // validity of blocks.
    29  type ConsensusParams struct {
    30  	Block     BlockParams     `json:"block"`
    31  	Evidence  EvidenceParams  `json:"evidence"`
    32  	Validator ValidatorParams `json:"validator"`
    33  }
    34  
    35  // HashedParams is a subset of ConsensusParams.
    36  // It is amino encoded and hashed into the Header.ConsensusHash.
    37  type HashedParams struct {
    38  	BlockMaxBytes int64
    39  	BlockMaxGas   int64
    40  }
    41  
    42  // BlockParams defines limits on the block size and gas plus minimum time
    43  // between blocks.
    44  type BlockParams struct {
    45  	MaxBytes int64 `json:"max_bytes"`
    46  	MaxGas   int64 `json:"max_gas"`
    47  	// Minimum time increment between consecutive blocks (in milliseconds)
    48  	// Not exposed to the application.
    49  	TimeIotaMs int64 `json:"time_iota_ms"`
    50  }
    51  
    52  // EvidenceParams determines how we handle evidence of malfeasance.
    53  //
    54  // Evidence older than MaxAgeNumBlocks && MaxAgeDuration is considered
    55  // stale and ignored.
    56  //
    57  // In Cosmos-SDK based blockchains, MaxAgeDuration is usually equal to the
    58  // unbonding period. MaxAgeNumBlocks is calculated by dividing the unboding
    59  // period by the average block time (e.g. 2 weeks / 6s per block = 2d8h).
    60  type EvidenceParams struct {
    61  	// Max age of evidence, in blocks.
    62  	//
    63  	// The basic formula for calculating this is: MaxAgeDuration / {average block
    64  	// time}.
    65  	MaxAgeNumBlocks int64 `json:"max_age_num_blocks"`
    66  
    67  	// Max age of evidence, in time.
    68  	//
    69  	// It should correspond with an app's "unbonding period" or other similar
    70  	// mechanism for handling [Nothing-At-Stake
    71  	// attacks](https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed).
    72  	MaxAgeDuration time.Duration `json:"max_age_duration"`
    73  
    74  	// This sets the maximum number of evidence that can be committed in a single block.
    75  	// and should fall comfortably under the max block bytes when we consider the size of
    76  	// each evidence (See MaxEvidenceBytes). The maximum number is MaxEvidencePerBlock.
    77  	// Default is 50
    78  	MaxNum uint32 `json:"max_num"`
    79  }
    80  
    81  // ValidatorParams restrict the public key types validators can use.
    82  // NOTE: uses ABCI pubkey naming, not Amino names.
    83  type ValidatorParams struct {
    84  	PubKeyTypes []string `json:"pub_key_types"`
    85  }
    86  
    87  // DefaultConsensusParams returns a default ConsensusParams.
    88  func DefaultConsensusParams() *ConsensusParams {
    89  	return &ConsensusParams{
    90  		DefaultBlockParams(),
    91  		DefaultEvidenceParams(),
    92  		DefaultValidatorParams(),
    93  	}
    94  }
    95  
    96  // DefaultBlockParams returns a default BlockParams.
    97  func DefaultBlockParams() BlockParams {
    98  	return BlockParams{
    99  		MaxBytes:   22020096, // 21MB
   100  		MaxGas:     -1,
   101  		TimeIotaMs: 1000, // 1s
   102  	}
   103  }
   104  
   105  // DefaultEvidenceParams returns a default EvidenceParams.
   106  func DefaultEvidenceParams() EvidenceParams {
   107  	return EvidenceParams{
   108  		MaxAgeNumBlocks: 100000, // 27.8 hrs at 1block/s
   109  		MaxAgeDuration:  48 * time.Hour,
   110  		MaxNum:          50,
   111  	}
   112  }
   113  
   114  // DefaultValidatorParams returns a default ValidatorParams, which allows
   115  // only ed25519 pubkeys.
   116  func DefaultValidatorParams() ValidatorParams {
   117  	return ValidatorParams{[]string{ABCIPubKeyTypeEd25519}}
   118  }
   119  
   120  func (params *ValidatorParams) IsValidPubkeyType(pubkeyType string) bool {
   121  	for i := 0; i < len(params.PubKeyTypes); i++ {
   122  		if params.PubKeyTypes[i] == pubkeyType {
   123  			return true
   124  		}
   125  	}
   126  	return false
   127  }
   128  
   129  // Validate validates the ConsensusParams to ensure all values are within their
   130  // allowed limits, and returns an error if they are not.
   131  func (params *ConsensusParams) Validate() error {
   132  	if params.Block.MaxBytes <= 0 {
   133  		return fmt.Errorf("block.MaxBytes must be greater than 0. Got %d",
   134  			params.Block.MaxBytes)
   135  	}
   136  	if params.Block.MaxBytes > MaxBlockSizeBytes {
   137  		return fmt.Errorf("block.MaxBytes is too big. %d > %d",
   138  			params.Block.MaxBytes, MaxBlockSizeBytes)
   139  	}
   140  
   141  	if params.Block.MaxGas < -1 {
   142  		return fmt.Errorf("block.MaxGas must be greater or equal to -1. Got %d",
   143  			params.Block.MaxGas)
   144  	}
   145  
   146  	if params.Block.TimeIotaMs <= 0 {
   147  		return fmt.Errorf("block.TimeIotaMs must be greater than 0. Got %v",
   148  			params.Block.TimeIotaMs)
   149  	}
   150  
   151  	if params.Evidence.MaxAgeNumBlocks <= 0 {
   152  		return fmt.Errorf("evidenceParams.MaxAgeNumBlocks must be greater than 0. Got %d",
   153  			params.Evidence.MaxAgeNumBlocks)
   154  	}
   155  
   156  	if params.Evidence.MaxAgeDuration <= 0 {
   157  		return fmt.Errorf("evidenceParams.MaxAgeDuration must be grater than 0 if provided, Got %v",
   158  			params.Evidence.MaxAgeDuration)
   159  	}
   160  
   161  	if params.Evidence.MaxNum > MaxEvidencePerBlock {
   162  		return fmt.Errorf("evidenceParams.MaxNumEvidence is greater than upper bound, %d > %d",
   163  			params.Evidence.MaxNum, MaxEvidencePerBlock)
   164  	}
   165  
   166  	if int64(params.Evidence.MaxNum)*MaxEvidenceBytes > params.Block.MaxBytes {
   167  		return fmt.Errorf("total possible evidence size is bigger than block.MaxBytes, %d > %d",
   168  			int64(params.Evidence.MaxNum)*MaxEvidenceBytes, params.Block.MaxBytes)
   169  	}
   170  
   171  	if len(params.Validator.PubKeyTypes) == 0 {
   172  		return errors.New("len(Validator.PubKeyTypes) must be greater than 0")
   173  	}
   174  
   175  	// Check if keyType is a known ABCIPubKeyType
   176  	for i := 0; i < len(params.Validator.PubKeyTypes); i++ {
   177  		keyType := params.Validator.PubKeyTypes[i]
   178  		if _, ok := ABCIPubKeyTypesToAminoNames[keyType]; !ok {
   179  			return fmt.Errorf("params.Validator.PubKeyTypes[%d], %s, is an unknown pubkey type",
   180  				i, keyType)
   181  		}
   182  	}
   183  
   184  	return nil
   185  }
   186  
   187  // Hash returns a hash of a subset of the parameters to store in the block header.
   188  // Only the Block.MaxBytes and Block.MaxGas are included in the hash.
   189  // This allows the ConsensusParams to evolve more without breaking the block
   190  // protocol. No need for a Merkle tree here, just a small struct to hash.
   191  func (params *ConsensusParams) Hash() []byte {
   192  	hasher := tmhash.New()
   193  	bz := cdcEncode(HashedParams{
   194  		params.Block.MaxBytes,
   195  		params.Block.MaxGas,
   196  	})
   197  	if bz == nil {
   198  		panic("cannot fail to encode ConsensusParams")
   199  	}
   200  	hasher.Write(bz)
   201  	return hasher.Sum(nil)
   202  }
   203  
   204  func (params *ConsensusParams) Equals(params2 *ConsensusParams) bool {
   205  	return params.Block == params2.Block &&
   206  		params.Evidence == params2.Evidence &&
   207  		tmstrings.StringSliceEqual(params.Validator.PubKeyTypes, params2.Validator.PubKeyTypes)
   208  }
   209  
   210  // Update returns a copy of the params with updates from the non-zero fields of p2.
   211  // NOTE: note: must not modify the original
   212  func (params ConsensusParams) Update(params2 *abci.ConsensusParams) ConsensusParams {
   213  	res := params // explicit copy
   214  
   215  	if params2 == nil {
   216  		return res
   217  	}
   218  
   219  	// we must defensively consider any structs may be nil
   220  	if params2.Block != nil {
   221  		res.Block.MaxBytes = params2.Block.MaxBytes
   222  		res.Block.MaxGas = params2.Block.MaxGas
   223  	}
   224  	if params2.Evidence != nil {
   225  		res.Evidence.MaxAgeNumBlocks = params2.Evidence.MaxAgeNumBlocks
   226  		res.Evidence.MaxAgeDuration = params2.Evidence.MaxAgeDuration
   227  		res.Evidence.MaxNum = params2.Evidence.MaxNum
   228  	}
   229  	if params2.Validator != nil {
   230  		// Copy params2.Validator.PubkeyTypes, and set result's value to the copy.
   231  		// This avoids having to initialize the slice to 0 values, and then write to it again.
   232  		res.Validator.PubKeyTypes = append([]string{}, params2.Validator.PubKeyTypes...)
   233  	}
   234  	return res
   235  }