You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
8.2 KiB

7 years ago
  1. package types
  2. import (
  3. "errors"
  4. "fmt"
  5. "time"
  6. "github.com/tendermint/tendermint/crypto/ed25519"
  7. "github.com/tendermint/tendermint/crypto/secp256k1"
  8. "github.com/tendermint/tendermint/crypto/sr25519"
  9. "github.com/tendermint/tendermint/crypto/tmhash"
  10. tmstrings "github.com/tendermint/tendermint/libs/strings"
  11. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  12. )
  13. const (
  14. // MaxBlockSizeBytes is the maximum permitted size of the blocks.
  15. MaxBlockSizeBytes = 104857600 // 100MB
  16. // BlockPartSizeBytes is the size of one block part.
  17. BlockPartSizeBytes uint32 = 65536 // 64kB
  18. // MaxBlockPartsCount is the maximum number of block parts.
  19. MaxBlockPartsCount = (MaxBlockSizeBytes / BlockPartSizeBytes) + 1
  20. ABCIPubKeyTypeEd25519 = ed25519.KeyType
  21. ABCIPubKeyTypeSecp256k1 = secp256k1.KeyType
  22. ABCIPubKeyTypeSr25519 = sr25519.KeyType
  23. )
  24. var ABCIPubKeyTypesToNames = map[string]string{
  25. ABCIPubKeyTypeEd25519: ed25519.PubKeyName,
  26. ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyName,
  27. ABCIPubKeyTypeSr25519: sr25519.PubKeyName,
  28. }
  29. // ConsensusParams contains consensus critical parameters that determine the
  30. // validity of blocks.
  31. type ConsensusParams struct {
  32. Block BlockParams `json:"block"`
  33. Evidence EvidenceParams `json:"evidence"`
  34. Validator ValidatorParams `json:"validator"`
  35. Version VersionParams `json:"version"`
  36. }
  37. // HashedParams is a subset of ConsensusParams.
  38. // It is amino encoded and hashed into
  39. // the Header.ConsensusHash.
  40. type HashedParams struct {
  41. BlockMaxBytes int64
  42. BlockMaxGas int64
  43. }
  44. // BlockParams define limits on the block size and gas plus minimum time
  45. // between blocks.
  46. type BlockParams struct {
  47. MaxBytes int64 `json:"max_bytes,string"`
  48. MaxGas int64 `json:"max_gas,string"`
  49. }
  50. // EvidenceParams determine how we handle evidence of malfeasance.
  51. type EvidenceParams struct {
  52. MaxAgeNumBlocks int64 `json:"max_age_num_blocks,string"` // only accept new evidence more recent than this
  53. MaxAgeDuration time.Duration `json:"max_age_duration,string"`
  54. MaxBytes int64 `json:"max_bytes,string"`
  55. }
  56. // ValidatorParams restrict the public key types validators can use.
  57. // NOTE: uses ABCI pubkey naming, not Amino names.
  58. type ValidatorParams struct {
  59. PubKeyTypes []string `json:"pub_key_types"`
  60. }
  61. type VersionParams struct {
  62. AppVersion uint64 `json:"app_version,string"`
  63. }
  64. // DefaultConsensusParams returns a default ConsensusParams.
  65. func DefaultConsensusParams() *ConsensusParams {
  66. return &ConsensusParams{
  67. Block: DefaultBlockParams(),
  68. Evidence: DefaultEvidenceParams(),
  69. Validator: DefaultValidatorParams(),
  70. Version: DefaultVersionParams(),
  71. }
  72. }
  73. // DefaultBlockParams returns a default BlockParams.
  74. func DefaultBlockParams() BlockParams {
  75. return BlockParams{
  76. MaxBytes: 22020096, // 21MB
  77. MaxGas: -1,
  78. }
  79. }
  80. // DefaultEvidenceParams returns a default EvidenceParams.
  81. func DefaultEvidenceParams() EvidenceParams {
  82. return EvidenceParams{
  83. MaxAgeNumBlocks: 100000, // 27.8 hrs at 1block/s
  84. MaxAgeDuration: 48 * time.Hour,
  85. MaxBytes: 1048576, // 1MB
  86. }
  87. }
  88. // DefaultValidatorParams returns a default ValidatorParams, which allows
  89. // only ed25519 pubkeys.
  90. func DefaultValidatorParams() ValidatorParams {
  91. return ValidatorParams{
  92. PubKeyTypes: []string{ABCIPubKeyTypeEd25519},
  93. }
  94. }
  95. func DefaultVersionParams() VersionParams {
  96. return VersionParams{
  97. AppVersion: 0,
  98. }
  99. }
  100. func (val *ValidatorParams) IsValidPubkeyType(pubkeyType string) bool {
  101. for i := 0; i < len(val.PubKeyTypes); i++ {
  102. if val.PubKeyTypes[i] == pubkeyType {
  103. return true
  104. }
  105. }
  106. return false
  107. }
  108. // Validate validates the ConsensusParams to ensure all values are within their
  109. // allowed limits, and returns an error if they are not.
  110. func (params ConsensusParams) ValidateConsensusParams() error {
  111. if params.Block.MaxBytes <= 0 {
  112. return fmt.Errorf("block.MaxBytes must be greater than 0. Got %d",
  113. params.Block.MaxBytes)
  114. }
  115. if params.Block.MaxBytes > MaxBlockSizeBytes {
  116. return fmt.Errorf("block.MaxBytes is too big. %d > %d",
  117. params.Block.MaxBytes, MaxBlockSizeBytes)
  118. }
  119. if params.Block.MaxGas < -1 {
  120. return fmt.Errorf("block.MaxGas must be greater or equal to -1. Got %d",
  121. params.Block.MaxGas)
  122. }
  123. if params.Evidence.MaxAgeNumBlocks <= 0 {
  124. return fmt.Errorf("evidence.MaxAgeNumBlocks must be greater than 0. Got %d",
  125. params.Evidence.MaxAgeNumBlocks)
  126. }
  127. if params.Evidence.MaxAgeDuration <= 0 {
  128. return fmt.Errorf("evidence.MaxAgeDuration must be grater than 0 if provided, Got %v",
  129. params.Evidence.MaxAgeDuration)
  130. }
  131. if params.Evidence.MaxBytes > params.Block.MaxBytes {
  132. return fmt.Errorf("evidence.MaxBytesEvidence is greater than upper bound, %d > %d",
  133. params.Evidence.MaxBytes, params.Block.MaxBytes)
  134. }
  135. if params.Evidence.MaxBytes < 0 {
  136. return fmt.Errorf("evidence.MaxBytes must be non negative. Got: %d",
  137. params.Evidence.MaxBytes)
  138. }
  139. if len(params.Validator.PubKeyTypes) == 0 {
  140. return errors.New("len(Validator.PubKeyTypes) must be greater than 0")
  141. }
  142. // Check if keyType is a known ABCIPubKeyType
  143. for i := 0; i < len(params.Validator.PubKeyTypes); i++ {
  144. keyType := params.Validator.PubKeyTypes[i]
  145. if _, ok := ABCIPubKeyTypesToNames[keyType]; !ok {
  146. return fmt.Errorf("params.Validator.PubKeyTypes[%d], %s, is an unknown pubkey type",
  147. i, keyType)
  148. }
  149. }
  150. return nil
  151. }
  152. // Hash returns a hash of a subset of the parameters to store in the block header.
  153. // Only the Block.MaxBytes and Block.MaxGas are included in the hash.
  154. // This allows the ConsensusParams to evolve more without breaking the block
  155. // protocol. No need for a Merkle tree here, just a small struct to hash.
  156. func (params ConsensusParams) HashConsensusParams() []byte {
  157. hasher := tmhash.New()
  158. hp := tmproto.HashedParams{
  159. BlockMaxBytes: params.Block.MaxBytes,
  160. BlockMaxGas: params.Block.MaxGas,
  161. }
  162. bz, err := hp.Marshal()
  163. if err != nil {
  164. panic(err)
  165. }
  166. _, err = hasher.Write(bz)
  167. if err != nil {
  168. panic(err)
  169. }
  170. return hasher.Sum(nil)
  171. }
  172. func (params *ConsensusParams) Equals(params2 *ConsensusParams) bool {
  173. return params.Block == params2.Block &&
  174. params.Evidence == params2.Evidence &&
  175. tmstrings.StringSliceEqual(params.Validator.PubKeyTypes, params2.Validator.PubKeyTypes)
  176. }
  177. // Update returns a copy of the params with updates from the non-zero fields of p2.
  178. // NOTE: note: must not modify the original
  179. func (params ConsensusParams) UpdateConsensusParams(params2 *tmproto.ConsensusParams) ConsensusParams {
  180. res := params // explicit copy
  181. if params2 == nil {
  182. return res
  183. }
  184. // we must defensively consider any structs may be nil
  185. if params2.Block != nil {
  186. res.Block.MaxBytes = params2.Block.MaxBytes
  187. res.Block.MaxGas = params2.Block.MaxGas
  188. }
  189. if params2.Evidence != nil {
  190. res.Evidence.MaxAgeNumBlocks = params2.Evidence.MaxAgeNumBlocks
  191. res.Evidence.MaxAgeDuration = params2.Evidence.MaxAgeDuration
  192. res.Evidence.MaxBytes = params2.Evidence.MaxBytes
  193. }
  194. if params2.Validator != nil {
  195. // Copy params2.Validator.PubkeyTypes, and set result's value to the copy.
  196. // This avoids having to initialize the slice to 0 values, and then write to it again.
  197. res.Validator.PubKeyTypes = append([]string{}, params2.Validator.PubKeyTypes...)
  198. }
  199. if params2.Version != nil {
  200. res.Version.AppVersion = params2.Version.AppVersion
  201. }
  202. return res
  203. }
  204. func (params *ConsensusParams) ToProto() tmproto.ConsensusParams {
  205. return tmproto.ConsensusParams{
  206. Block: &tmproto.BlockParams{
  207. MaxBytes: params.Block.MaxBytes,
  208. MaxGas: params.Block.MaxGas,
  209. },
  210. Evidence: &tmproto.EvidenceParams{
  211. MaxAgeNumBlocks: params.Evidence.MaxAgeNumBlocks,
  212. MaxAgeDuration: params.Evidence.MaxAgeDuration,
  213. MaxBytes: params.Evidence.MaxBytes,
  214. },
  215. Validator: &tmproto.ValidatorParams{
  216. PubKeyTypes: params.Validator.PubKeyTypes,
  217. },
  218. Version: &tmproto.VersionParams{
  219. AppVersion: params.Version.AppVersion,
  220. },
  221. }
  222. }
  223. func ConsensusParamsFromProto(pbParams tmproto.ConsensusParams) ConsensusParams {
  224. return ConsensusParams{
  225. Block: BlockParams{
  226. MaxBytes: pbParams.Block.MaxBytes,
  227. MaxGas: pbParams.Block.MaxGas,
  228. },
  229. Evidence: EvidenceParams{
  230. MaxAgeNumBlocks: pbParams.Evidence.MaxAgeNumBlocks,
  231. MaxAgeDuration: pbParams.Evidence.MaxAgeDuration,
  232. MaxBytes: pbParams.Evidence.MaxBytes,
  233. },
  234. Validator: ValidatorParams{
  235. PubKeyTypes: pbParams.Validator.PubKeyTypes,
  236. },
  237. Version: VersionParams{
  238. AppVersion: pbParams.Version.AppVersion,
  239. },
  240. }
  241. }