github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/types/params.go (about) 1 package types 2 3 import ( 4 "crypto/sha256" 5 "errors" 6 "fmt" 7 "time" 8 9 "github.com/ari-anchor/sei-tendermint/crypto/ed25519" 10 "github.com/ari-anchor/sei-tendermint/crypto/secp256k1" 11 "github.com/ari-anchor/sei-tendermint/crypto/sr25519" 12 tmstrings "github.com/ari-anchor/sei-tendermint/libs/strings" 13 tmproto "github.com/ari-anchor/sei-tendermint/proto/tendermint/types" 14 ) 15 16 const ( 17 // MaxBlockSizeBytes is the maximum permitted size of the blocks. 18 MaxBlockSizeBytes = 104857600 // 100MB 19 20 // BlockPartSizeBytes is the size of one block part. 21 BlockPartSizeBytes uint32 = 1048576 // 1MB 22 23 // MaxBlockPartsCount is the maximum number of block parts. 24 MaxBlockPartsCount = (MaxBlockSizeBytes / BlockPartSizeBytes) + 1 25 26 ABCIPubKeyTypeEd25519 = ed25519.KeyType 27 ABCIPubKeyTypeSecp256k1 = secp256k1.KeyType 28 ABCIPubKeyTypeSr25519 = sr25519.KeyType 29 ) 30 31 var ABCIPubKeyTypesToNames = map[string]string{ 32 ABCIPubKeyTypeEd25519: ed25519.PubKeyName, 33 ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyName, 34 ABCIPubKeyTypeSr25519: sr25519.PubKeyName, 35 } 36 37 // ConsensusParams contains consensus critical parameters that determine the 38 // validity of blocks. 39 type ConsensusParams struct { 40 Block BlockParams `json:"block"` 41 Evidence EvidenceParams `json:"evidence"` 42 Validator ValidatorParams `json:"validator"` 43 Version VersionParams `json:"version"` 44 Synchrony SynchronyParams `json:"synchrony"` 45 Timeout TimeoutParams `json:"timeout"` 46 ABCI ABCIParams `json:"abci"` 47 } 48 49 // HashedParams is a subset of ConsensusParams. 50 // It is amino encoded and hashed into 51 // the Header.ConsensusHash. 52 type HashedParams struct { 53 BlockMaxBytes int64 54 BlockMaxGas int64 55 } 56 57 // BlockParams define limits on the block size and gas plus minimum time 58 // between blocks. 59 type BlockParams struct { 60 MaxBytes int64 `json:"max_bytes,string"` 61 MaxGas int64 `json:"max_gas,string"` 62 } 63 64 // EvidenceParams determine how we handle evidence of malfeasance. 65 type EvidenceParams struct { 66 MaxAgeNumBlocks int64 `json:"max_age_num_blocks,string"` // only accept new evidence more recent than this 67 MaxAgeDuration time.Duration `json:"max_age_duration,string"` 68 MaxBytes int64 `json:"max_bytes,string"` 69 } 70 71 // ValidatorParams restrict the public key types validators can use. 72 // NOTE: uses ABCI pubkey naming, not Amino names. 73 type ValidatorParams struct { 74 PubKeyTypes []string `json:"pub_key_types"` 75 } 76 77 type VersionParams struct { 78 AppVersion uint64 `json:"app_version,string"` 79 } 80 81 // SynchronyParams influence the validity of block timestamps. 82 // For more information on the relationship of the synchrony parameters to 83 // block validity, see the Proposer-Based Timestamps specification: 84 // https://github.com/ari-anchor/sei-tendermint/blob/master/spec/consensus/proposer-based-timestamp/README.md 85 type SynchronyParams struct { 86 Precision time.Duration `json:"precision,string"` 87 MessageDelay time.Duration `json:"message_delay,string"` 88 } 89 90 // TimeoutParams configure the timings of the steps of the Tendermint consensus algorithm. 91 type TimeoutParams struct { 92 Propose time.Duration `json:"propose,string"` 93 ProposeDelta time.Duration `json:"propose_delta,string"` 94 Vote time.Duration `json:"vote,string"` 95 VoteDelta time.Duration `json:"vote_delta,string"` 96 Commit time.Duration `json:"commit,string"` 97 BypassCommitTimeout bool `json:"bypass_commit_timeout"` 98 } 99 100 // ABCIParams configure ABCI functionality specific to the Application Blockchain 101 // Interface. 102 type ABCIParams struct { 103 VoteExtensionsEnableHeight int64 `json:"vote_extensions_enable_height"` 104 RecheckTx bool `json:"recheck_tx"` 105 } 106 107 // VoteExtensionsEnabled returns true if vote extensions are enabled at height h 108 // and false otherwise. 109 func (a ABCIParams) VoteExtensionsEnabled(h int64) bool { 110 if a.VoteExtensionsEnableHeight == 0 { 111 return false 112 } 113 return a.VoteExtensionsEnableHeight <= h 114 } 115 116 // DefaultConsensusParams returns a default ConsensusParams. 117 func DefaultConsensusParams() *ConsensusParams { 118 return &ConsensusParams{ 119 Block: DefaultBlockParams(), 120 Evidence: DefaultEvidenceParams(), 121 Validator: DefaultValidatorParams(), 122 Version: DefaultVersionParams(), 123 Synchrony: DefaultSynchronyParams(), 124 Timeout: DefaultTimeoutParams(), 125 ABCI: DefaultABCIParams(), 126 } 127 } 128 129 // DefaultBlockParams returns a default BlockParams. 130 func DefaultBlockParams() BlockParams { 131 return BlockParams{ 132 MaxBytes: 22020096, // 21MB 133 // Default, can be increased and tuned as needed 134 // match sei-devnet-3 and atlantic-2 current values 135 MaxGas: 100000000, 136 } 137 } 138 139 // DefaultEvidenceParams returns a default EvidenceParams. 140 func DefaultEvidenceParams() EvidenceParams { 141 return EvidenceParams{ 142 MaxAgeNumBlocks: 100000, // 27.8 hrs at 1block/s 143 MaxAgeDuration: 48 * time.Hour, 144 MaxBytes: 1048576, // 1MB 145 } 146 } 147 148 // DefaultValidatorParams returns a default ValidatorParams, which allows 149 // only ed25519 pubkeys. 150 func DefaultValidatorParams() ValidatorParams { 151 return ValidatorParams{ 152 PubKeyTypes: []string{ABCIPubKeyTypeEd25519}, 153 } 154 } 155 156 func DefaultVersionParams() VersionParams { 157 return VersionParams{ 158 AppVersion: 0, 159 } 160 } 161 162 func DefaultSynchronyParams() SynchronyParams { 163 return SynchronyParams{ 164 // 505ms was selected as the default to enable chains that have validators in 165 // mixed leap-second handling environments. 166 // For more information, see: https://github.com/ari-anchor/sei-tendermint/issues/7724 167 Precision: 505 * time.Millisecond, 168 MessageDelay: 12 * time.Second, 169 } 170 } 171 172 // SynchronyParamsOrDefaults returns the SynchronyParams, filling in any zero values 173 // with the Tendermint defined default values. 174 func (s SynchronyParams) SynchronyParamsOrDefaults() SynchronyParams { 175 // TODO: Remove this method and all uses once development on v0.37 begins. 176 // See: https://github.com/ari-anchor/sei-tendermint/issues/8187 177 178 defaults := DefaultSynchronyParams() 179 if s.Precision == 0 { 180 s.Precision = defaults.Precision 181 } 182 if s.MessageDelay == 0 { 183 s.MessageDelay = defaults.MessageDelay 184 } 185 return s 186 } 187 188 func DefaultTimeoutParams() TimeoutParams { 189 return TimeoutParams{ 190 Propose: 1 * time.Second, 191 ProposeDelta: 500 * time.Millisecond, 192 Vote: 50 * time.Millisecond, 193 VoteDelta: 500 * time.Millisecond, 194 Commit: 50 * time.Millisecond, 195 BypassCommitTimeout: false, 196 } 197 } 198 199 func DefaultABCIParams() ABCIParams { 200 return ABCIParams{ 201 // When set to 0, vote extensions are not required. 202 VoteExtensionsEnableHeight: 0, 203 // When true, run CheckTx on each transaction in the mempool after each height. 204 RecheckTx: false, 205 } 206 } 207 208 // TimeoutParamsOrDefaults returns the SynchronyParams, filling in any zero values 209 // with the Tendermint defined default values. 210 func (t TimeoutParams) TimeoutParamsOrDefaults() TimeoutParams { 211 // TODO: Remove this method and all uses once development on v0.37 begins. 212 // See: https://github.com/ari-anchor/sei-tendermint/issues/8187 213 214 defaults := DefaultTimeoutParams() 215 if t.Propose == 0 { 216 t.Propose = defaults.Propose 217 } 218 if t.ProposeDelta == 0 { 219 t.ProposeDelta = defaults.ProposeDelta 220 } 221 if t.Vote == 0 { 222 t.Vote = defaults.Vote 223 } 224 if t.VoteDelta == 0 { 225 t.VoteDelta = defaults.VoteDelta 226 } 227 if t.Commit == 0 { 228 t.Commit = defaults.Commit 229 } 230 return t 231 } 232 233 // ProposeTimeout returns the amount of time to wait for a proposal. 234 func (t TimeoutParams) ProposeTimeout(round int32) time.Duration { 235 return time.Duration( 236 t.Propose.Nanoseconds()+t.ProposeDelta.Nanoseconds()*int64(round), 237 ) * time.Nanosecond 238 } 239 240 // VoteTimeout returns the amount of time to wait for remaining votes after receiving any +2/3 votes. 241 func (t TimeoutParams) VoteTimeout(round int32) time.Duration { 242 return time.Duration( 243 t.Vote.Nanoseconds()+t.VoteDelta.Nanoseconds()*int64(round), 244 ) * time.Nanosecond 245 } 246 247 // CommitTime accepts ti, the time at which the consensus engine received +2/3 248 // precommits for a block and returns the point in time at which the consensus 249 // engine should begin consensus on the next block. 250 func (t TimeoutParams) CommitTime(ti time.Time) time.Time { 251 return ti.Add(t.Commit) 252 } 253 254 func (val *ValidatorParams) IsValidPubkeyType(pubkeyType string) bool { 255 for i := 0; i < len(val.PubKeyTypes); i++ { 256 if val.PubKeyTypes[i] == pubkeyType { 257 return true 258 } 259 } 260 return false 261 } 262 263 func (params *ConsensusParams) Complete() { 264 if params.Synchrony == (SynchronyParams{}) { 265 params.Synchrony = DefaultSynchronyParams() 266 } 267 if params.Timeout == (TimeoutParams{}) { 268 params.Timeout = DefaultTimeoutParams() 269 } 270 } 271 272 // Validate validates the ConsensusParams to ensure all values are within their 273 // allowed limits, and returns an error if they are not. 274 func (params ConsensusParams) ValidateConsensusParams() error { 275 if params.Block.MaxBytes <= 0 { 276 return fmt.Errorf("block.MaxBytes must be greater than 0. Got %d", 277 params.Block.MaxBytes) 278 } 279 if params.Block.MaxBytes > MaxBlockSizeBytes { 280 return fmt.Errorf("block.MaxBytes is too big. %d > %d", 281 params.Block.MaxBytes, MaxBlockSizeBytes) 282 } 283 284 if params.Block.MaxGas < -1 { 285 return fmt.Errorf("block.MaxGas must be greater or equal to -1. Got %d", 286 params.Block.MaxGas) 287 } 288 289 if params.Evidence.MaxAgeNumBlocks <= 0 { 290 return fmt.Errorf("evidence.MaxAgeNumBlocks must be greater than 0. Got %d", 291 params.Evidence.MaxAgeNumBlocks) 292 } 293 294 if params.Evidence.MaxAgeDuration <= 0 { 295 return fmt.Errorf("evidence.MaxAgeDuration must be greater than 0 if provided, Got %v", 296 params.Evidence.MaxAgeDuration) 297 } 298 299 if params.Evidence.MaxBytes > params.Block.MaxBytes { 300 return fmt.Errorf("evidence.MaxBytesEvidence is greater than upper bound, %d > %d", 301 params.Evidence.MaxBytes, params.Block.MaxBytes) 302 } 303 304 if params.Evidence.MaxBytes < 0 { 305 return fmt.Errorf("evidence.MaxBytes must be non negative. Got: %d", 306 params.Evidence.MaxBytes) 307 } 308 309 if params.Synchrony.MessageDelay <= 0 { 310 return fmt.Errorf("synchrony.MessageDelay must be greater than 0. Got: %d", 311 params.Synchrony.MessageDelay) 312 } 313 314 if params.Synchrony.Precision <= 0 { 315 return fmt.Errorf("synchrony.Precision must be greater than 0. Got: %d", 316 params.Synchrony.Precision) 317 } 318 319 if params.Timeout.Propose <= 0 { 320 return fmt.Errorf("timeout.ProposeDelta must be greater than 0. Got: %d", params.Timeout.Propose) 321 } 322 323 if params.Timeout.ProposeDelta <= 0 { 324 return fmt.Errorf("timeout.ProposeDelta must be greater than 0. Got: %d", params.Timeout.ProposeDelta) 325 } 326 327 if params.Timeout.Vote <= 0 { 328 return fmt.Errorf("timeout.Vote must be greater than 0. Got: %d", params.Timeout.Vote) 329 } 330 331 if params.Timeout.VoteDelta <= 0 { 332 return fmt.Errorf("timeout.VoteDelta must be greater than 0. Got: %d", params.Timeout.VoteDelta) 333 } 334 335 if params.Timeout.Commit <= 0 { 336 return fmt.Errorf("timeout.Commit must be greater than 0. Got: %d", params.Timeout.Commit) 337 } 338 if params.ABCI.VoteExtensionsEnableHeight < 0 { 339 return fmt.Errorf("ABCI.VoteExtensionsEnableHeight cannot be negative. Got: %d", params.ABCI.VoteExtensionsEnableHeight) 340 } 341 342 if len(params.Validator.PubKeyTypes) == 0 { 343 return errors.New("len(Validator.PubKeyTypes) must be greater than 0") 344 } 345 346 // Check if keyType is a known ABCIPubKeyType 347 for i := 0; i < len(params.Validator.PubKeyTypes); i++ { 348 keyType := params.Validator.PubKeyTypes[i] 349 if _, ok := ABCIPubKeyTypesToNames[keyType]; !ok { 350 return fmt.Errorf("params.Validator.PubKeyTypes[%d], %s, is an unknown pubkey type", 351 i, keyType) 352 } 353 } 354 355 return nil 356 } 357 358 func (params ConsensusParams) ValidateUpdate(updated *tmproto.ConsensusParams, h int64) error { 359 if updated.Abci == nil { 360 return nil 361 } 362 if params.ABCI.VoteExtensionsEnableHeight == updated.Abci.VoteExtensionsEnableHeight { 363 return nil 364 } 365 if params.ABCI.VoteExtensionsEnableHeight != 0 && updated.Abci.VoteExtensionsEnableHeight == 0 { 366 return errors.New("vote extensions cannot be disabled once enabled") 367 } 368 if updated.Abci.VoteExtensionsEnableHeight <= h { 369 return fmt.Errorf("VoteExtensionsEnableHeight cannot be updated to a past height, "+ 370 "initial height: %d, current height %d", 371 params.ABCI.VoteExtensionsEnableHeight, h) 372 } 373 if params.ABCI.VoteExtensionsEnableHeight <= h { 374 return fmt.Errorf("VoteExtensionsEnableHeight cannot be updated modified once"+ 375 "the initial height has occurred, "+ 376 "initial height: %d, current height %d", 377 params.ABCI.VoteExtensionsEnableHeight, h) 378 } 379 return nil 380 } 381 382 // Hash returns a hash of a subset of the parameters to store in the block header. 383 // Only the Block.MaxBytes and Block.MaxGas are included in the hash. 384 // This allows the ConsensusParams to evolve more without breaking the block 385 // protocol. No need for a Merkle tree here, just a small struct to hash. 386 // TODO: We should hash the other parameters as well 387 func (params ConsensusParams) HashConsensusParams() []byte { 388 hp := tmproto.HashedParams{ 389 BlockMaxBytes: params.Block.MaxBytes, 390 BlockMaxGas: params.Block.MaxGas, 391 } 392 393 bz, err := hp.Marshal() 394 if err != nil { 395 panic(err) 396 } 397 398 sum := sha256.Sum256(bz) 399 400 return sum[:] 401 } 402 403 func (params *ConsensusParams) Equals(params2 *ConsensusParams) bool { 404 return params.Block == params2.Block && 405 params.Evidence == params2.Evidence && 406 params.Version == params2.Version && 407 params.Synchrony == params2.Synchrony && 408 params.Timeout == params2.Timeout && 409 params.ABCI == params2.ABCI && 410 tmstrings.StringSliceEqual(params.Validator.PubKeyTypes, params2.Validator.PubKeyTypes) 411 } 412 413 // Update returns a copy of the params with updates from the non-zero fields of p2. 414 // NOTE: note: must not modify the original 415 func (params ConsensusParams) UpdateConsensusParams(params2 *tmproto.ConsensusParams) ConsensusParams { 416 res := params // explicit copy 417 418 if params2 == nil { 419 return res 420 } 421 422 // we must defensively consider any structs may be nil 423 if params2.Block != nil { 424 res.Block.MaxBytes = params2.Block.MaxBytes 425 res.Block.MaxGas = params2.Block.MaxGas 426 } 427 if params2.Evidence != nil { 428 res.Evidence.MaxAgeNumBlocks = params2.Evidence.MaxAgeNumBlocks 429 res.Evidence.MaxAgeDuration = params2.Evidence.MaxAgeDuration 430 res.Evidence.MaxBytes = params2.Evidence.MaxBytes 431 } 432 if params2.Validator != nil { 433 // Copy params2.Validator.PubkeyTypes, and set result's value to the copy. 434 // This avoids having to initialize the slice to 0 values, and then write to it again. 435 res.Validator.PubKeyTypes = append([]string{}, params2.Validator.PubKeyTypes...) 436 } 437 if params2.Version != nil { 438 res.Version.AppVersion = params2.Version.AppVersion 439 } 440 if params2.Synchrony != nil { 441 if params2.Synchrony.MessageDelay != nil { 442 res.Synchrony.MessageDelay = *params2.Synchrony.GetMessageDelay() 443 } 444 if params2.Synchrony.Precision != nil { 445 res.Synchrony.Precision = *params2.Synchrony.GetPrecision() 446 } 447 } 448 if params2.Timeout != nil { 449 if params2.Timeout.Propose != nil { 450 res.Timeout.Propose = *params2.Timeout.GetPropose() 451 } 452 if params2.Timeout.ProposeDelta != nil { 453 res.Timeout.ProposeDelta = *params2.Timeout.GetProposeDelta() 454 } 455 if params2.Timeout.Vote != nil { 456 res.Timeout.Vote = *params2.Timeout.GetVote() 457 } 458 if params2.Timeout.VoteDelta != nil { 459 res.Timeout.VoteDelta = *params2.Timeout.GetVoteDelta() 460 } 461 if params2.Timeout.Commit != nil { 462 res.Timeout.Commit = *params2.Timeout.GetCommit() 463 } 464 res.Timeout.BypassCommitTimeout = params2.Timeout.GetBypassCommitTimeout() 465 } 466 if params2.Abci != nil { 467 res.ABCI.VoteExtensionsEnableHeight = params2.Abci.GetVoteExtensionsEnableHeight() 468 res.ABCI.RecheckTx = params2.Abci.GetRecheckTx() 469 } 470 return res 471 } 472 473 func (params *ConsensusParams) ToProto() tmproto.ConsensusParams { 474 return tmproto.ConsensusParams{ 475 Block: &tmproto.BlockParams{ 476 MaxBytes: params.Block.MaxBytes, 477 MaxGas: params.Block.MaxGas, 478 }, 479 Evidence: &tmproto.EvidenceParams{ 480 MaxAgeNumBlocks: params.Evidence.MaxAgeNumBlocks, 481 MaxAgeDuration: params.Evidence.MaxAgeDuration, 482 MaxBytes: params.Evidence.MaxBytes, 483 }, 484 Validator: &tmproto.ValidatorParams{ 485 PubKeyTypes: params.Validator.PubKeyTypes, 486 }, 487 Version: &tmproto.VersionParams{ 488 AppVersion: params.Version.AppVersion, 489 }, 490 Synchrony: &tmproto.SynchronyParams{ 491 MessageDelay: ¶ms.Synchrony.MessageDelay, 492 Precision: ¶ms.Synchrony.Precision, 493 }, 494 Timeout: &tmproto.TimeoutParams{ 495 Propose: ¶ms.Timeout.Propose, 496 ProposeDelta: ¶ms.Timeout.ProposeDelta, 497 Vote: ¶ms.Timeout.Vote, 498 VoteDelta: ¶ms.Timeout.VoteDelta, 499 Commit: ¶ms.Timeout.Commit, 500 BypassCommitTimeout: params.Timeout.BypassCommitTimeout, 501 }, 502 Abci: &tmproto.ABCIParams{ 503 VoteExtensionsEnableHeight: params.ABCI.VoteExtensionsEnableHeight, 504 RecheckTx: params.ABCI.RecheckTx, 505 }, 506 } 507 } 508 509 func ConsensusParamsFromProto(pbParams tmproto.ConsensusParams) ConsensusParams { 510 c := ConsensusParams{ 511 Block: BlockParams{ 512 MaxBytes: pbParams.Block.MaxBytes, 513 MaxGas: pbParams.Block.MaxGas, 514 }, 515 Evidence: EvidenceParams{ 516 MaxAgeNumBlocks: pbParams.Evidence.MaxAgeNumBlocks, 517 MaxAgeDuration: pbParams.Evidence.MaxAgeDuration, 518 MaxBytes: pbParams.Evidence.MaxBytes, 519 }, 520 Validator: ValidatorParams{ 521 PubKeyTypes: pbParams.Validator.PubKeyTypes, 522 }, 523 Version: VersionParams{ 524 AppVersion: pbParams.Version.AppVersion, 525 }, 526 } 527 if pbParams.Synchrony != nil { 528 if pbParams.Synchrony.MessageDelay != nil { 529 c.Synchrony.MessageDelay = *pbParams.Synchrony.GetMessageDelay() 530 } 531 if pbParams.Synchrony.Precision != nil { 532 c.Synchrony.Precision = *pbParams.Synchrony.GetPrecision() 533 } 534 } 535 if pbParams.Timeout != nil { 536 if pbParams.Timeout.Propose != nil { 537 c.Timeout.Propose = *pbParams.Timeout.GetPropose() 538 } 539 if pbParams.Timeout.ProposeDelta != nil { 540 c.Timeout.ProposeDelta = *pbParams.Timeout.GetProposeDelta() 541 } 542 if pbParams.Timeout.Vote != nil { 543 c.Timeout.Vote = *pbParams.Timeout.GetVote() 544 } 545 if pbParams.Timeout.VoteDelta != nil { 546 c.Timeout.VoteDelta = *pbParams.Timeout.GetVoteDelta() 547 } 548 if pbParams.Timeout.Commit != nil { 549 c.Timeout.Commit = *pbParams.Timeout.GetCommit() 550 } 551 c.Timeout.BypassCommitTimeout = pbParams.Timeout.BypassCommitTimeout 552 } 553 if pbParams.Abci != nil { 554 c.ABCI.VoteExtensionsEnableHeight = pbParams.Abci.GetVoteExtensionsEnableHeight() 555 c.ABCI.RecheckTx = pbParams.Abci.GetRecheckTx() 556 } 557 return c 558 }