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.

323 lines
9.8 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. Synchrony SynchronyParams `json:"synchrony"`
  37. }
  38. // HashedParams is a subset of ConsensusParams.
  39. // It is amino encoded and hashed into
  40. // the Header.ConsensusHash.
  41. type HashedParams struct {
  42. BlockMaxBytes int64
  43. BlockMaxGas int64
  44. }
  45. // BlockParams define limits on the block size and gas plus minimum time
  46. // between blocks.
  47. type BlockParams struct {
  48. MaxBytes int64 `json:"max_bytes,string"`
  49. MaxGas int64 `json:"max_gas,string"`
  50. }
  51. // EvidenceParams determine how we handle evidence of malfeasance.
  52. type EvidenceParams struct {
  53. MaxAgeNumBlocks int64 `json:"max_age_num_blocks,string"` // only accept new evidence more recent than this
  54. MaxAgeDuration time.Duration `json:"max_age_duration,string"`
  55. MaxBytes int64 `json:"max_bytes,string"`
  56. }
  57. // ValidatorParams restrict the public key types validators can use.
  58. // NOTE: uses ABCI pubkey naming, not Amino names.
  59. type ValidatorParams struct {
  60. PubKeyTypes []string `json:"pub_key_types"`
  61. }
  62. type VersionParams struct {
  63. AppVersion uint64 `json:"app_version,string"`
  64. }
  65. // SynchronyParams influence the validity of block timestamps.
  66. // For more information on the relationship of the synchrony parameters to
  67. // block validity, see the Proposer-Based Timestamps specification:
  68. // https://github.com/tendermint/spec/blob/master/spec/consensus/proposer-based-timestamp/README.md
  69. type SynchronyParams struct {
  70. Precision time.Duration `json:"precision,string"`
  71. MessageDelay time.Duration `json:"message_delay,string"`
  72. }
  73. // DefaultConsensusParams returns a default ConsensusParams.
  74. func DefaultConsensusParams() *ConsensusParams {
  75. return &ConsensusParams{
  76. Block: DefaultBlockParams(),
  77. Evidence: DefaultEvidenceParams(),
  78. Validator: DefaultValidatorParams(),
  79. Version: DefaultVersionParams(),
  80. Synchrony: DefaultSynchronyParams(),
  81. }
  82. }
  83. // DefaultBlockParams returns a default BlockParams.
  84. func DefaultBlockParams() BlockParams {
  85. return BlockParams{
  86. MaxBytes: 22020096, // 21MB
  87. MaxGas: -1,
  88. }
  89. }
  90. // DefaultEvidenceParams returns a default EvidenceParams.
  91. func DefaultEvidenceParams() EvidenceParams {
  92. return EvidenceParams{
  93. MaxAgeNumBlocks: 100000, // 27.8 hrs at 1block/s
  94. MaxAgeDuration: 48 * time.Hour,
  95. MaxBytes: 1048576, // 1MB
  96. }
  97. }
  98. // DefaultValidatorParams returns a default ValidatorParams, which allows
  99. // only ed25519 pubkeys.
  100. func DefaultValidatorParams() ValidatorParams {
  101. return ValidatorParams{
  102. PubKeyTypes: []string{ABCIPubKeyTypeEd25519},
  103. }
  104. }
  105. func DefaultVersionParams() VersionParams {
  106. return VersionParams{
  107. AppVersion: 0,
  108. }
  109. }
  110. func DefaultSynchronyParams() SynchronyParams {
  111. // TODO(@wbanfield): Determine experimental values for these defaults
  112. // https://github.com/tendermint/tendermint/issues/7202
  113. return SynchronyParams{
  114. Precision: 500 * time.Millisecond,
  115. MessageDelay: 2 * time.Second,
  116. }
  117. }
  118. func (val *ValidatorParams) IsValidPubkeyType(pubkeyType string) bool {
  119. for i := 0; i < len(val.PubKeyTypes); i++ {
  120. if val.PubKeyTypes[i] == pubkeyType {
  121. return true
  122. }
  123. }
  124. return false
  125. }
  126. // Validate validates the ConsensusParams to ensure all values are within their
  127. // allowed limits, and returns an error if they are not.
  128. func (params ConsensusParams) ValidateConsensusParams() error {
  129. if params.Block.MaxBytes <= 0 {
  130. return fmt.Errorf("block.MaxBytes must be greater than 0. Got %d",
  131. params.Block.MaxBytes)
  132. }
  133. if params.Block.MaxBytes > MaxBlockSizeBytes {
  134. return fmt.Errorf("block.MaxBytes is too big. %d > %d",
  135. params.Block.MaxBytes, MaxBlockSizeBytes)
  136. }
  137. if params.Block.MaxGas < -1 {
  138. return fmt.Errorf("block.MaxGas must be greater or equal to -1. Got %d",
  139. params.Block.MaxGas)
  140. }
  141. if params.Evidence.MaxAgeNumBlocks <= 0 {
  142. return fmt.Errorf("evidence.MaxAgeNumBlocks must be greater than 0. Got %d",
  143. params.Evidence.MaxAgeNumBlocks)
  144. }
  145. if params.Evidence.MaxAgeDuration <= 0 {
  146. return fmt.Errorf("evidence.MaxAgeDuration must be greater than 0 if provided, Got %v",
  147. params.Evidence.MaxAgeDuration)
  148. }
  149. if params.Evidence.MaxBytes > params.Block.MaxBytes {
  150. return fmt.Errorf("evidence.MaxBytesEvidence is greater than upper bound, %d > %d",
  151. params.Evidence.MaxBytes, params.Block.MaxBytes)
  152. }
  153. if params.Evidence.MaxBytes < 0 {
  154. return fmt.Errorf("evidence.MaxBytes must be non negative. Got: %d",
  155. params.Evidence.MaxBytes)
  156. }
  157. if params.Synchrony.MessageDelay <= 0 {
  158. return fmt.Errorf("synchrony.MessageDelay must be greater than 0. Got: %d",
  159. params.Synchrony.MessageDelay)
  160. }
  161. if params.Synchrony.Precision <= 0 {
  162. return fmt.Errorf("synchrony.Precision must be greater than 0. Got: %d",
  163. params.Synchrony.Precision)
  164. }
  165. if len(params.Validator.PubKeyTypes) == 0 {
  166. return errors.New("len(Validator.PubKeyTypes) must be greater than 0")
  167. }
  168. // Check if keyType is a known ABCIPubKeyType
  169. for i := 0; i < len(params.Validator.PubKeyTypes); i++ {
  170. keyType := params.Validator.PubKeyTypes[i]
  171. if _, ok := ABCIPubKeyTypesToNames[keyType]; !ok {
  172. return fmt.Errorf("params.Validator.PubKeyTypes[%d], %s, is an unknown pubkey type",
  173. i, keyType)
  174. }
  175. }
  176. return nil
  177. }
  178. // Hash returns a hash of a subset of the parameters to store in the block header.
  179. // Only the Block.MaxBytes and Block.MaxGas are included in the hash.
  180. // This allows the ConsensusParams to evolve more without breaking the block
  181. // protocol. No need for a Merkle tree here, just a small struct to hash.
  182. func (params ConsensusParams) HashConsensusParams() []byte {
  183. hasher := tmhash.New()
  184. hp := tmproto.HashedParams{
  185. BlockMaxBytes: params.Block.MaxBytes,
  186. BlockMaxGas: params.Block.MaxGas,
  187. }
  188. bz, err := hp.Marshal()
  189. if err != nil {
  190. panic(err)
  191. }
  192. _, err = hasher.Write(bz)
  193. if err != nil {
  194. panic(err)
  195. }
  196. return hasher.Sum(nil)
  197. }
  198. func (params *ConsensusParams) Equals(params2 *ConsensusParams) bool {
  199. return params.Block == params2.Block &&
  200. params.Evidence == params2.Evidence &&
  201. params.Version == params2.Version &&
  202. params.Synchrony == params2.Synchrony &&
  203. tmstrings.StringSliceEqual(params.Validator.PubKeyTypes, params2.Validator.PubKeyTypes)
  204. }
  205. // Update returns a copy of the params with updates from the non-zero fields of p2.
  206. // NOTE: note: must not modify the original
  207. func (params ConsensusParams) UpdateConsensusParams(params2 *tmproto.ConsensusParams) ConsensusParams {
  208. res := params // explicit copy
  209. if params2 == nil {
  210. return res
  211. }
  212. // we must defensively consider any structs may be nil
  213. if params2.Block != nil {
  214. res.Block.MaxBytes = params2.Block.MaxBytes
  215. res.Block.MaxGas = params2.Block.MaxGas
  216. }
  217. if params2.Evidence != nil {
  218. res.Evidence.MaxAgeNumBlocks = params2.Evidence.MaxAgeNumBlocks
  219. res.Evidence.MaxAgeDuration = params2.Evidence.MaxAgeDuration
  220. res.Evidence.MaxBytes = params2.Evidence.MaxBytes
  221. }
  222. if params2.Validator != nil {
  223. // Copy params2.Validator.PubkeyTypes, and set result's value to the copy.
  224. // This avoids having to initialize the slice to 0 values, and then write to it again.
  225. res.Validator.PubKeyTypes = append([]string{}, params2.Validator.PubKeyTypes...)
  226. }
  227. if params2.Version != nil {
  228. res.Version.AppVersion = params2.Version.AppVersion
  229. }
  230. if params2.Synchrony != nil {
  231. res.Synchrony.Precision = params2.Synchrony.Precision
  232. res.Synchrony.MessageDelay = params2.Synchrony.MessageDelay
  233. }
  234. return res
  235. }
  236. func (params *ConsensusParams) ToProto() tmproto.ConsensusParams {
  237. return tmproto.ConsensusParams{
  238. Block: &tmproto.BlockParams{
  239. MaxBytes: params.Block.MaxBytes,
  240. MaxGas: params.Block.MaxGas,
  241. },
  242. Evidence: &tmproto.EvidenceParams{
  243. MaxAgeNumBlocks: params.Evidence.MaxAgeNumBlocks,
  244. MaxAgeDuration: params.Evidence.MaxAgeDuration,
  245. MaxBytes: params.Evidence.MaxBytes,
  246. },
  247. Validator: &tmproto.ValidatorParams{
  248. PubKeyTypes: params.Validator.PubKeyTypes,
  249. },
  250. Version: &tmproto.VersionParams{
  251. AppVersion: params.Version.AppVersion,
  252. },
  253. Synchrony: &tmproto.SynchronyParams{
  254. MessageDelay: params.Synchrony.MessageDelay,
  255. Precision: params.Synchrony.Precision,
  256. },
  257. }
  258. }
  259. func ConsensusParamsFromProto(pbParams tmproto.ConsensusParams) ConsensusParams {
  260. return ConsensusParams{
  261. Block: BlockParams{
  262. MaxBytes: pbParams.Block.MaxBytes,
  263. MaxGas: pbParams.Block.MaxGas,
  264. },
  265. Evidence: EvidenceParams{
  266. MaxAgeNumBlocks: pbParams.Evidence.MaxAgeNumBlocks,
  267. MaxAgeDuration: pbParams.Evidence.MaxAgeDuration,
  268. MaxBytes: pbParams.Evidence.MaxBytes,
  269. },
  270. Validator: ValidatorParams{
  271. PubKeyTypes: pbParams.Validator.PubKeyTypes,
  272. },
  273. Version: VersionParams{
  274. AppVersion: pbParams.Version.AppVersion,
  275. },
  276. Synchrony: SynchronyParams{
  277. MessageDelay: pbParams.Synchrony.MessageDelay,
  278. Precision: pbParams.Synchrony.Precision,
  279. },
  280. }
  281. }