github.com/klaytn/klaytn@v1.12.1/governance/default.go (about) 1 // Copyright 2019 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The klaytn library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package governance 18 19 import ( 20 "encoding/binary" 21 "encoding/json" 22 "fmt" 23 "math/big" 24 "reflect" 25 "strings" 26 "sync" 27 "sync/atomic" 28 29 "github.com/klaytn/klaytn/common" 30 "github.com/klaytn/klaytn/log" 31 "github.com/klaytn/klaytn/params" 32 "github.com/klaytn/klaytn/rlp" 33 "github.com/klaytn/klaytn/storage/database" 34 "github.com/pkg/errors" 35 ) 36 37 var ( 38 ErrValueTypeMismatch = errors.New("Value's type mismatch") 39 ErrDecodeGovChange = errors.New("Failed to decode received governance changes") 40 ErrUnmarshalGovChange = errors.New("Failed to unmarshal received governance changes") 41 ErrVoteValueMismatch = errors.New("Received change mismatches with the value this node has!!") 42 ErrNotInitialized = errors.New("Cache not initialized") 43 ErrItemNotFound = errors.New("Failed to find governance item") 44 ErrItemNil = errors.New("Governance Item is nil") 45 ErrUnknownKey = errors.New("Governnace value of the given key not found") 46 ) 47 48 var ( 49 GovernanceKeyMap = map[string]int{ 50 "governance.governancemode": params.GovernanceMode, 51 "governance.governingnode": params.GoverningNode, 52 "governance.govparamcontract": params.GovParamContract, 53 "istanbul.epoch": params.Epoch, 54 "istanbul.policy": params.Policy, 55 "istanbul.committeesize": params.CommitteeSize, 56 "governance.unitprice": params.UnitPrice, 57 "governance.deriveshaimpl": params.DeriveShaImpl, 58 "kip71.lowerboundbasefee": params.LowerBoundBaseFee, 59 "kip71.gastarget": params.GasTarget, 60 "kip71.maxblockgasusedforbasefee": params.MaxBlockGasUsedForBaseFee, 61 "kip71.basefeedenominator": params.BaseFeeDenominator, 62 "kip71.upperboundbasefee": params.UpperBoundBaseFee, 63 "reward.mintingamount": params.MintingAmount, 64 "reward.ratio": params.Ratio, 65 "reward.kip82ratio": params.Kip82Ratio, 66 "reward.useginicoeff": params.UseGiniCoeff, 67 "reward.deferredtxfee": params.DeferredTxFee, 68 "reward.minimumstake": params.MinimumStake, 69 "reward.stakingupdateinterval": params.StakeUpdateInterval, 70 "reward.proposerupdateinterval": params.ProposerRefreshInterval, 71 "governance.addvalidator": params.AddValidator, 72 "governance.removevalidator": params.RemoveValidator, 73 "param.txgashumanreadable": params.ConstTxGasHumanReadable, 74 "istanbul.timeout": params.Timeout, 75 } 76 77 GovernanceForbiddenKeyMap = map[string]int{ 78 "istanbul.policy": params.Policy, 79 "reward.stakingupdateinterval": params.StakeUpdateInterval, 80 "reward.proposerupdateinterval": params.ProposerRefreshInterval, 81 } 82 83 GovernanceKeyMapReverse = map[int]string{ 84 params.GovernanceMode: "governance.governancemode", 85 params.GoverningNode: "governance.governingnode", 86 params.GovParamContract: "governance.govparamcontract", 87 params.Epoch: "istanbul.epoch", 88 params.CliqueEpoch: "clique.epoch", 89 params.Policy: "istanbul.policy", 90 params.CommitteeSize: "istanbul.committeesize", 91 params.UnitPrice: "governance.unitprice", 92 params.DeriveShaImpl: "governance.deriveshaimpl", 93 params.LowerBoundBaseFee: "kip71.lowerboundbasefee", 94 params.UpperBoundBaseFee: "kip71.upperboundbasefee", 95 params.GasTarget: "kip71.gastarget", 96 params.MaxBlockGasUsedForBaseFee: "kip71.maxblockgasusedforbasefee", 97 params.BaseFeeDenominator: "kip71.basefeedenominator", 98 params.MintingAmount: "reward.mintingamount", 99 params.Ratio: "reward.ratio", 100 params.UseGiniCoeff: "reward.useginicoeff", 101 params.DeferredTxFee: "reward.deferredtxfee", 102 params.MinimumStake: "reward.minimumstake", 103 params.StakeUpdateInterval: "reward.stakingupdateinterval", 104 params.ProposerRefreshInterval: "reward.proposerupdateinterval", 105 params.AddValidator: "governance.addvalidator", 106 params.RemoveValidator: "governance.removevalidator", 107 params.ConstTxGasHumanReadable: "param.txgashumanreadable", 108 params.Timeout: "istanbul.timeout", 109 params.Kip82Ratio: "reward.kip82ratio", 110 } 111 112 ProposerPolicyMap = map[string]int{ 113 "roundrobin": params.RoundRobin, 114 "sticky": params.Sticky, 115 "weightedrandom": params.WeightedRandom, 116 } 117 118 ProposerPolicyMapReverse = map[int]string{ 119 params.RoundRobin: "roundrobin", 120 params.Sticky: "sticky", 121 params.WeightedRandom: "weightedrandom", 122 } 123 124 GovernanceModeMap = map[string]int{ 125 "none": params.GovernanceMode_None, 126 "single": params.GovernanceMode_Single, 127 "ballot": params.GovernanceMode_Ballot, 128 } 129 ) 130 131 var logger = log.NewModuleLogger(log.Governance) 132 133 // GovernanceSet contains an item set for governance 134 type GovernanceSet struct { 135 items map[string]interface{} 136 mu *sync.RWMutex 137 } 138 139 // GovernanceVote represents vote information given from istanbul.vote() 140 type GovernanceVote struct { 141 Validator common.Address `json:"validator"` 142 Key string `json:"key"` 143 Value interface{} `json:"value"` 144 } 145 146 // GovernanceTallyItem represents a tally for each governance item 147 type GovernanceTallyItem struct { 148 Key string `json:"key"` 149 Value interface{} `json:"value"` 150 Votes uint64 `json:"votes"` 151 } 152 153 type GovernanceTallyList struct { 154 items []GovernanceTallyItem 155 mu *sync.RWMutex 156 } 157 158 type GovernanceVotes struct { 159 items []GovernanceVote 160 mu *sync.RWMutex 161 } 162 163 type VoteStatus struct { 164 Value interface{} `json:"value"` 165 Casted bool `json:"casted"` 166 Num uint64 `json:"num"` 167 } 168 169 type VoteMap struct { 170 items map[string]VoteStatus 171 mu *sync.RWMutex 172 } 173 174 // txPool is an interface for blockchain.TxPool used in governance package. 175 type txPool interface { 176 SetGasPrice(price *big.Int) 177 GasPrice() *big.Int 178 } 179 180 type Governance struct { 181 ChainConfig *params.ChainConfig // Only exists to keep DB backward compatibility in WriteGovernanceState() 182 // Map used to keep multiple types of votes 183 voteMap VoteMap 184 185 nodeAddress atomic.Value // common.Address 186 totalVotingPower uint64 187 votingPower uint64 188 189 GovernanceVotes GovernanceVotes 190 GovernanceTallies GovernanceTallyList 191 192 db database.DBManager 193 itemCache common.Cache 194 idxCache []uint64 // elements should be in ascending order 195 idxCacheLock *sync.RWMutex 196 197 // The block number when current governance information was changed 198 actualGovernanceBlock atomic.Value // uint64 199 200 // The last block number at governance state was stored (used not to replay old votes) 201 lastGovernanceStateBlock uint64 202 203 currentSet GovernanceSet 204 changeSet GovernanceSet 205 currentParams *params.GovParamSet // equals to currentSet 206 initialParams *params.GovParamSet // equals to initial ChainConfig 207 208 TxPool txPool 209 210 blockChain blockChain 211 } 212 213 func NewVoteMap() VoteMap { 214 return VoteMap{ 215 items: make(map[string]VoteStatus), 216 mu: new(sync.RWMutex), 217 } 218 } 219 220 func NewGovernanceTallies() GovernanceTallyList { 221 return GovernanceTallyList{ 222 items: []GovernanceTallyItem{}, 223 mu: new(sync.RWMutex), 224 } 225 } 226 227 func NewGovernanceVotes() GovernanceVotes { 228 return GovernanceVotes{ 229 items: []GovernanceVote{}, 230 mu: new(sync.RWMutex), 231 } 232 } 233 234 func (gt *GovernanceTallyList) Clear() { 235 gt.mu.Lock() 236 defer gt.mu.Unlock() 237 238 gt.items = make([]GovernanceTallyItem, 0) 239 } 240 241 func (vl *VoteMap) Copy() map[string]VoteStatus { 242 vl.mu.RLock() 243 defer vl.mu.RUnlock() 244 245 ret := make(map[string]VoteStatus) 246 for k, v := range vl.items { 247 ret[k] = v 248 } 249 250 return ret 251 } 252 253 func (vl *VoteMap) GetValue(key string) VoteStatus { 254 vl.mu.RLock() 255 defer vl.mu.RUnlock() 256 257 return vl.items[key] 258 } 259 260 func (vl *VoteMap) SetValue(key string, val VoteStatus) { 261 vl.mu.Lock() 262 defer vl.mu.Unlock() 263 264 vl.items[key] = val 265 } 266 267 func (vl *VoteMap) Import(src map[string]VoteStatus) { 268 vl.mu.Lock() 269 defer vl.mu.Unlock() 270 271 for k, v := range src { 272 vl.items[k] = v 273 } 274 } 275 276 func (vl *VoteMap) Clear() { 277 vl.mu.Lock() 278 defer vl.mu.Unlock() 279 280 // TODO-Governance if vote is not casted, it can remain forever. So, it would be better to add expiration. 281 newItems := make(map[string]VoteStatus) 282 for k, v := range vl.items { 283 if !v.Casted { 284 newItems[k] = v 285 } 286 } 287 vl.items = newItems 288 } 289 290 func (vl *VoteMap) Size() int { 291 vl.mu.RLock() 292 defer vl.mu.RUnlock() 293 294 return len(vl.items) 295 } 296 297 func (gt *GovernanceTallyList) Copy() []GovernanceTallyItem { 298 gt.mu.RLock() 299 defer gt.mu.RUnlock() 300 301 ret := make([]GovernanceTallyItem, len(gt.items)) 302 copy(ret, gt.items) 303 304 return ret 305 } 306 307 func (gt *GovernanceTallyList) Import(src []GovernanceTallyItem) { 308 gt.mu.Lock() 309 defer gt.mu.Unlock() 310 311 gt.items = make([]GovernanceTallyItem, len(src)) 312 copy(gt.items, src) 313 } 314 315 func (gv *GovernanceVotes) Clear() { 316 gv.mu.Lock() 317 defer gv.mu.Unlock() 318 gv.items = make([]GovernanceVote, 0) 319 } 320 321 func (gv *GovernanceVotes) Copy() []GovernanceVote { 322 gv.mu.RLock() 323 defer gv.mu.RUnlock() 324 325 ret := make([]GovernanceVote, len(gv.items)) 326 copy(ret, gv.items) 327 328 return ret 329 } 330 331 func (gv *GovernanceVotes) Import(src []GovernanceVote) { 332 gv.mu.Lock() 333 defer gv.mu.Unlock() 334 335 gv.items = make([]GovernanceVote, len(src)) 336 copy(gv.items, src) 337 } 338 339 func NewGovernanceSet() GovernanceSet { 340 return GovernanceSet{ 341 items: map[string]interface{}{}, 342 mu: new(sync.RWMutex), 343 } 344 } 345 346 func (gs *GovernanceSet) Clear() { 347 gs.mu.Lock() 348 defer gs.mu.Unlock() 349 350 gs.items = make(map[string]interface{}) 351 } 352 353 func (gs *GovernanceSet) SetValue(itemType int, value interface{}) error { 354 gs.mu.Lock() 355 defer gs.mu.Unlock() 356 357 key := GovernanceKeyMapReverse[itemType] 358 if !checkValueType(value, GovernanceItems[itemType].t) { 359 return ErrValueTypeMismatch 360 } 361 gs.items[key] = value 362 return nil 363 } 364 365 func (gs *GovernanceSet) GetValue(key int) (interface{}, bool) { 366 sKey, ok := GovernanceKeyMapReverse[key] 367 if !ok { 368 return nil, false 369 } 370 371 gs.mu.RLock() 372 defer gs.mu.RUnlock() 373 ret, ok := gs.items[sKey] 374 return ret, ok 375 } 376 377 func (gs *GovernanceSet) RemoveItem(key string) { 378 gs.mu.Lock() 379 defer gs.mu.Unlock() 380 381 delete(gs.items, key) 382 } 383 384 func (gs *GovernanceSet) Size() int { 385 gs.mu.RLock() 386 defer gs.mu.RUnlock() 387 388 return len(gs.items) 389 } 390 391 func (gs *GovernanceSet) Import(src map[string]interface{}) { 392 gs.mu.Lock() 393 defer gs.mu.Unlock() 394 395 gs.items = make(map[string]interface{}) 396 for k, v := range src { 397 gs.items[k] = v 398 } 399 } 400 401 func (gs *GovernanceSet) Items() map[string]interface{} { 402 gs.mu.Lock() 403 defer gs.mu.Unlock() 404 405 ret := make(map[string]interface{}) 406 for k, v := range gs.items { 407 ret[k] = v 408 } 409 return ret 410 } 411 412 func (gs *GovernanceSet) Merge(change map[string]interface{}) { 413 gs.mu.Lock() 414 defer gs.mu.Unlock() 415 416 for k, v := range change { 417 gs.items[k] = v 418 } 419 } 420 421 // NewGovernance creates Governance with the given configuration. 422 func NewGovernance(chainConfig *params.ChainConfig, dbm database.DBManager) *Governance { 423 return &Governance{ 424 ChainConfig: chainConfig, 425 voteMap: NewVoteMap(), 426 db: dbm, 427 itemCache: newGovernanceCache(), 428 currentSet: NewGovernanceSet(), 429 changeSet: NewGovernanceSet(), 430 currentParams: params.NewGovParamSet(), 431 initialParams: params.NewGovParamSet(), 432 lastGovernanceStateBlock: 0, 433 GovernanceTallies: NewGovernanceTallies(), 434 GovernanceVotes: NewGovernanceVotes(), 435 idxCacheLock: new(sync.RWMutex), 436 } 437 } 438 439 // NewGovernanceInitialize creates Governance with the given configuration and read governance state from DB. 440 // If any items are not stored in DB, it stores governance items of the genesis block to DB. 441 func NewGovernanceInitialize(chainConfig *params.ChainConfig, dbm database.DBManager) *Governance { 442 ret := NewGovernance(chainConfig, dbm) 443 // nil is for testing or simple function usage 444 if dbm != nil { 445 ret.ReadGovernanceState() 446 if err := ret.initializeCache(chainConfig); err != nil { 447 // If this is the first time to run, store governance information for genesis block on database 448 cfg := GetGovernanceItemsFromChainConfig(chainConfig) 449 if err := ret.WriteGovernance(0, cfg, NewGovernanceSet()); err != nil { 450 logger.Crit("Error in writing governance information", "err", err) 451 } 452 // If failed again after writing governance, stop booting up 453 if err = ret.initializeCache(chainConfig); err != nil { 454 logger.Crit("No governance cache index found in a database", "err", err) 455 } 456 } 457 } 458 return ret 459 } 460 461 func (g *Governance) updateGovernanceParams() { 462 params.SetStakingUpdateInterval(g.stakingUpdateInterval()) 463 params.SetProposerUpdateInterval(g.proposerUpdateInterval()) 464 465 // NOTE: HumanReadable related functions are inactivated now 466 if txGasHumanReadable, ok := g.currentSet.GetValue(params.ConstTxGasHumanReadable); ok { 467 params.TxGasHumanReadable = txGasHumanReadable.(uint64) 468 } 469 } 470 471 func (g *Governance) SetNodeAddress(addr common.Address) { 472 g.nodeAddress.Store(addr) 473 } 474 475 func (g *Governance) SetTotalVotingPower(t uint64) { 476 atomic.StoreUint64(&g.totalVotingPower, t) 477 } 478 479 func (g *Governance) SetMyVotingPower(t uint64) { 480 atomic.StoreUint64(&g.votingPower, t) 481 } 482 483 func (g *Governance) NodeAddress() common.Address { 484 return g.nodeAddress.Load().(common.Address) 485 } 486 487 func (g *Governance) TotalVotingPower() uint64 { 488 return atomic.LoadUint64(&g.totalVotingPower) 489 } 490 491 func (g *Governance) MyVotingPower() uint64 { 492 return atomic.LoadUint64(&g.votingPower) 493 } 494 495 func (gov *Governance) BlockChain() blockChain { 496 return gov.blockChain 497 } 498 499 func (gov *Governance) DB() database.DBManager { 500 return gov.db 501 } 502 503 func (g *Governance) GetEncodedVote(addr common.Address, number uint64) []byte { 504 // TODO-Klaytn-Governance Change this part to add all votes to the header at once 505 for key, val := range g.voteMap.Copy() { 506 if val.Casted == false { 507 vote := new(GovernanceVote) 508 vote.Validator = addr 509 vote.Key = key 510 vote.Value = val.Value 511 encoded, err := rlp.EncodeToBytes(vote) 512 if err != nil { 513 logger.Error("Failed to RLP Encode a vote", "vote", vote) 514 g.RemoveVote(key, val, number) 515 continue 516 } 517 return encoded 518 } 519 } 520 return nil 521 } 522 523 func (g *Governance) getKey(k string) string { 524 return strings.Trim(strings.ToLower(k), " ") 525 } 526 527 // RemoveVote removes a vote from the voteMap to prevent repetitive addition of same vote 528 func (g *Governance) RemoveVote(key string, value interface{}, number uint64) { 529 k := GovernanceKeyMap[key] 530 if isEqualValue(k, g.voteMap.GetValue(key).Value, value) { 531 g.voteMap.SetValue(key, VoteStatus{ 532 Value: value, 533 Casted: true, 534 Num: number, 535 }) 536 } 537 if g.CanWriteGovernanceState(number) { 538 g.WriteGovernanceState(number, false) 539 } 540 } 541 542 func (g *Governance) ClearVotes(num uint64) { 543 g.GovernanceVotes.Clear() 544 g.GovernanceTallies.Clear() 545 g.changeSet.Clear() 546 g.voteMap.Clear() 547 logger.Info("Governance votes are cleared", "num", num) 548 } 549 550 // ParseVoteValue parses vote.Value from []uint8, [][]uint8 to appropriate type 551 func (g *Governance) ParseVoteValue(gVote *GovernanceVote) (*GovernanceVote, error) { 552 var val interface{} 553 k, ok := GovernanceKeyMap[gVote.Key] 554 if !ok { 555 logger.Warn("Unknown key was given", "key", k) 556 return nil, ErrUnknownKey 557 } 558 559 switch k { 560 case params.GovernanceMode, params.MintingAmount, params.MinimumStake, params.Ratio, params.Kip82Ratio: 561 v, ok := gVote.Value.([]uint8) 562 if !ok { 563 return nil, ErrValueTypeMismatch 564 } 565 val = string(v) 566 case params.GoverningNode, params.GovParamContract: 567 v, ok := gVote.Value.([]uint8) 568 if !ok { 569 return nil, ErrValueTypeMismatch 570 } 571 val = common.BytesToAddress(v) 572 case params.AddValidator, params.RemoveValidator: 573 if v, ok := gVote.Value.([]uint8); ok { 574 // if value contains single address, gVote.Value type should be []uint8{} 575 val = common.BytesToAddress(v) 576 } else if addresses, ok := gVote.Value.([]interface{}); ok { 577 // if value contains multiple addresses, gVote.Value type should be [][]uint8{} 578 if len(addresses) == 0 { 579 return nil, ErrValueTypeMismatch 580 } 581 var nodeAddresses []common.Address 582 for _, item := range addresses { 583 if in, ok := item.([]uint8); !ok || len(in) != common.AddressLength { 584 return nil, ErrValueTypeMismatch 585 } 586 nodeAddresses = append(nodeAddresses, common.BytesToAddress(item.([]uint8))) 587 } 588 val = nodeAddresses 589 } else { 590 return nil, ErrValueTypeMismatch 591 } 592 case params.Epoch, params.CommitteeSize, params.UnitPrice, params.DeriveShaImpl, params.StakeUpdateInterval, 593 params.ProposerRefreshInterval, params.ConstTxGasHumanReadable, params.Policy, params.Timeout, 594 params.LowerBoundBaseFee, params.UpperBoundBaseFee, params.GasTarget, params.MaxBlockGasUsedForBaseFee, params.BaseFeeDenominator: 595 v, ok := gVote.Value.([]uint8) 596 if !ok { 597 return nil, ErrValueTypeMismatch 598 } 599 v = append(make([]byte, 8-len(v)), v...) 600 val = binary.BigEndian.Uint64(v) 601 case params.UseGiniCoeff, params.DeferredTxFee: 602 v, ok := gVote.Value.([]uint8) 603 if !ok { 604 return nil, ErrValueTypeMismatch 605 } 606 v = append(make([]byte, 8-len(v)), v...) 607 if binary.BigEndian.Uint64(v) != uint64(0) { 608 val = true 609 } else { 610 val = false 611 } 612 } 613 gVote.Value = val 614 return gVote, nil 615 } 616 617 func (gov *Governance) ReflectVotes(vote GovernanceVote) { 618 if ok := gov.updateChangeSet(vote); !ok { 619 logger.Error("Failed to reflect Governance Config", "Key", vote.Key, "Value", vote.Value) 620 } 621 } 622 623 func (gov *Governance) updateChangeSet(vote GovernanceVote) bool { 624 switch GovernanceKeyMap[vote.Key] { 625 case params.GoverningNode, params.GovParamContract: 626 gov.changeSet.SetValue(GovernanceKeyMap[vote.Key], vote.Value.(common.Address)) 627 return true 628 case params.GovernanceMode, params.Ratio, params.Kip82Ratio: 629 gov.changeSet.SetValue(GovernanceKeyMap[vote.Key], vote.Value.(string)) 630 return true 631 case params.Epoch, params.StakeUpdateInterval, params.ProposerRefreshInterval, params.CommitteeSize, 632 params.UnitPrice, params.DeriveShaImpl, params.ConstTxGasHumanReadable, params.Policy, params.Timeout, 633 params.LowerBoundBaseFee, params.UpperBoundBaseFee, params.GasTarget, params.MaxBlockGasUsedForBaseFee, params.BaseFeeDenominator: 634 gov.changeSet.SetValue(GovernanceKeyMap[vote.Key], vote.Value.(uint64)) 635 return true 636 case params.MintingAmount, params.MinimumStake: 637 gov.changeSet.SetValue(GovernanceKeyMap[vote.Key], vote.Value.(string)) 638 return true 639 case params.UseGiniCoeff, params.DeferredTxFee: 640 gov.changeSet.SetValue(GovernanceKeyMap[vote.Key], vote.Value.(bool)) 641 return true 642 default: 643 logger.Warn("Unknown key was given", "key", vote.Key) 644 } 645 return false 646 } 647 648 func CheckGenesisValues(c *params.ChainConfig) error { 649 gov := NewGovernanceInitialize(c, nil) 650 651 tstMap := map[string]interface{}{ 652 "istanbul.epoch": c.Istanbul.Epoch, 653 "istanbul.committeesize": c.Istanbul.SubGroupSize, 654 "istanbul.policy": uint64(c.Istanbul.ProposerPolicy), 655 "governance.governancemode": c.Governance.GovernanceMode, 656 "governance.governingnode": c.Governance.GoverningNode, 657 "governance.unitprice": c.UnitPrice, 658 "reward.ratio": c.Governance.Reward.Ratio, 659 "reward.useginicoeff": c.Governance.Reward.UseGiniCoeff, 660 "reward.deferredtxfee": c.Governance.Reward.DeferredTxFee, 661 "reward.mintingamount": c.Governance.Reward.MintingAmount.String(), 662 "reward.minimumstake": c.Governance.Reward.MinimumStake.String(), 663 "reward.stakingupdateinterval": c.Governance.Reward.StakingUpdateInterval, 664 "reward.proposerupdateinterval": c.Governance.Reward.ProposerUpdateInterval, 665 } 666 667 for k, v := range tstMap { 668 if _, ok := gov.ValidateVote(&GovernanceVote{Key: k, Value: v}); !ok { 669 return errors.New(k + " value is wrong") 670 } 671 } 672 return nil 673 } 674 675 func newGovernanceCache() common.Cache { 676 cache := common.NewCache(common.LRUConfig{CacheSize: params.GovernanceCacheLimit}) 677 return cache 678 } 679 680 // initializeCache reads governance item data from database and updates Governance.itemCache. 681 // It also initializes currentSet and actualGovernanceBlock according to head block number. 682 func (g *Governance) initializeCache(chainConfig *params.ChainConfig) error { 683 // get last n governance change block number 684 indices, err := g.db.ReadRecentGovernanceIdx(params.GovernanceIdxCacheLimit) 685 if err != nil { 686 return ErrNotInitialized 687 } 688 g.idxCache = indices 689 690 // Put governance items into the itemCache 691 for _, v := range indices { 692 if data, err := g.db.ReadGovernance(v); err == nil { 693 data = adjustDecodedSet(data) 694 g.itemCache.Add(getGovernanceCacheKey(v), data) 695 } else { 696 logger.Crit("Couldn't read governance cache from database. Check database consistency", "index", v, "err", err) 697 } 698 } 699 700 // g.db.ReadGovernance(N) returns the governance data stored in block 'N'. If the data is not exists, it simply returns an error. 701 // On the other hand, g.ReadGovernance(N) returns the governance data viewed by block 'N' and the block number at the time the governance data is stored. 702 // Since g.currentSet means the governance data viewed by the head block number of the node 703 // and g.actualGovernanceBlock means the block number at the time the governance data is stored, 704 // So those two variables are initialized by using the return values of the g.ReadGovernance(headBlockNum). 705 706 // head block number is used to get the appropriate g.currentSet and g.actualGovernanceBlock 707 headBlockNumber := uint64(0) 708 if headBlockHash := g.db.ReadHeadBlockHash(); !common.EmptyHash(headBlockHash) { 709 if num := g.db.ReadHeaderNumber(headBlockHash); num != nil { 710 headBlockNumber = *num 711 } else if headBlockHash := g.db.ReadHeadBlockBackupHash(); !common.EmptyHash(headBlockHash) { 712 if num := g.db.ReadHeaderNumber(headBlockHash); num != nil { 713 headBlockNumber = *num 714 } 715 } 716 } 717 newBlockNumber, newGovernanceSet, err := g.ReadGovernance(headBlockNumber) 718 if err != nil { 719 return err 720 } 721 // g.actualGovernanceBlock and currentSet is set 722 g.actualGovernanceBlock.Store(newBlockNumber) 723 g.currentSet.Import(newGovernanceSet) 724 725 // g.lastGovernanceStateBlock contains the last block number when voting data is included. 726 // we check the order between g.actualGovernanceBlock and g.lastGovernanceStateBlock, so make sure that voting is not missed. 727 governanceBlock, governanceStateBlock := g.actualGovernanceBlock.Load().(uint64), atomic.LoadUint64(&g.lastGovernanceStateBlock) 728 if governanceBlock >= governanceStateBlock { 729 ret, ok := g.itemCache.Get(getGovernanceCacheKey(governanceBlock)) 730 if !ok || ret == nil { 731 logger.Error("cannot get governance data at actualGovernanceBlock", "actualGovernanceBlock", governanceBlock) 732 return errors.New("Currentset initialization failed") 733 } 734 g.currentSet.Import(ret.(map[string]interface{})) 735 } 736 737 // Reflect CurrentSet -> g.initialParams 738 if pset, err := params.NewGovParamSetChainConfig(chainConfig); err == nil { 739 g.initialParams = pset 740 } else { 741 logger.Crit("Error parsing initial ChainConfig", "err", err) 742 } 743 // Reflect g.currentSet -> g.currentParams (for g.CurrentParams()) 744 // Outside initializeCache, istanbul.CreateSnapshot() will trigger UpdateParams(). 745 g.UpdateParams(headBlockNumber) 746 // Reflect g.currentSet -> global params in params/governance_params.go 747 // Outside initializeCache, GovernanceItems[].trigger will reflect changes to globals. 748 g.updateGovernanceParams() 749 750 return nil 751 } 752 753 // getGovernanceCache returns cached governance config as a byte slice 754 func (g *Governance) getGovernanceCache(num uint64) (map[string]interface{}, bool) { 755 cKey := getGovernanceCacheKey(num) 756 757 if ret, ok := g.itemCache.Get(cKey); ok && ret != nil { 758 return ret.(map[string]interface{}), true 759 } 760 return nil, false 761 } 762 763 func (g *Governance) addGovernanceCache(num uint64, data GovernanceSet) { 764 // Don't update cache if num (block number) is smaller than the biggest number of cached block number 765 g.idxCacheLock.Lock() 766 defer g.idxCacheLock.Unlock() 767 768 if len(g.idxCache) > 0 && num <= g.idxCache[len(g.idxCache)-1] { 769 logger.Error("The same or more recent governance index exist. Skip updating governance cache", 770 "newIdx", num, "govIdxes", g.idxCache) 771 return 772 } 773 cKey := getGovernanceCacheKey(num) 774 g.itemCache.Add(cKey, data.Items()) 775 776 g.idxCache = append(g.idxCache, num) 777 if len(g.idxCache) > params.GovernanceIdxCacheLimit { 778 g.idxCache = g.idxCache[len(g.idxCache)-params.GovernanceIdxCacheLimit:] 779 } 780 } 781 782 // getGovernanceCacheKey returns cache key of the given block number 783 func getGovernanceCacheKey(num uint64) common.GovernanceCacheKey { 784 v := fmt.Sprintf("%v", num) 785 return common.GovernanceCacheKey(params.GovernanceCachePrefix + "_" + v) 786 } 787 788 // Store new governance data on DB. This updates Governance cache too. 789 func (g *Governance) WriteGovernance(num uint64, data GovernanceSet, delta GovernanceSet) error { 790 g.idxCacheLock.RLock() 791 indices := make([]uint64, len(g.idxCache)) 792 copy(indices, g.idxCache) 793 g.idxCacheLock.RUnlock() 794 795 if len(indices) > 0 && num <= indices[len(indices)-1] { 796 logger.Error("The same or more recent governance index exist. Skip writing governance", 797 "newIdx", num, "govIdxes", indices) 798 return nil 799 } 800 801 new := NewGovernanceSet() 802 new.Import(data.Items()) 803 804 // merge delta into data 805 if delta.Size() > 0 { 806 new.Merge(delta.Items()) 807 } 808 g.addGovernanceCache(num, new) 809 return g.db.WriteGovernance(new.Items(), num) 810 } 811 812 func (g *Governance) searchCache(num uint64) (uint64, bool) { 813 g.idxCacheLock.RLock() 814 defer g.idxCacheLock.RUnlock() 815 816 for i := len(g.idxCache) - 1; i >= 0; i-- { 817 if g.idxCache[i] <= num { 818 return g.idxCache[i], true 819 } 820 } 821 return 0, false 822 } 823 824 func (g *Governance) ReadGovernance(num uint64) (uint64, map[string]interface{}, error) { 825 // epochWithFallback() falls back to Default before initializeCache() 826 epoch := g.epochWithFallback() 827 blockNum := CalcGovernanceInfoBlock(num, epoch) 828 829 // Check cache first 830 if gBlockNum, ok := g.searchCache(blockNum); ok { 831 if data, okay := g.getGovernanceCache(gBlockNum); okay { 832 return gBlockNum, data, nil 833 } 834 } 835 if g.db != nil { 836 bn, result, err := g.db.ReadGovernanceAtNumber(num, epoch) 837 result = adjustDecodedSet(result) 838 return bn, result, err 839 } else { 840 // For CI tests which don't have a database 841 return 0, nil, nil 842 } 843 } 844 845 func CalcGovernanceInfoBlock(num uint64, epoch uint64) uint64 { 846 governanceInfoBlock := num - (num % epoch) 847 if governanceInfoBlock >= epoch { 848 governanceInfoBlock -= epoch 849 } 850 return governanceInfoBlock 851 } 852 853 func (g *Governance) GetGovernanceChange() map[string]interface{} { 854 if g.changeSet.Size() > 0 { 855 return g.changeSet.Items() 856 } 857 return nil 858 } 859 860 // WriteGovernanceForNextEpoch creates governance items for next epoch and writes them to the database. 861 // The governance items on next epoch will be the given `governance` items applied on the top of past epoch items. 862 func (gov *Governance) WriteGovernanceForNextEpoch(number uint64, governance []byte) { 863 var epoch uint64 864 var ok bool 865 866 if epoch, ok = gov.GetGovernanceValue(params.Epoch).(uint64); !ok { 867 if epoch, ok = gov.GetGovernanceValue(params.CliqueEpoch).(uint64); !ok { 868 logger.Error("Couldn't find epoch from governance items") 869 return 870 } 871 } 872 873 // Store updated governance information if exist 874 if number%epoch == 0 { 875 if len(governance) > 0 { 876 tempData := []byte("") 877 tempItems := make(map[string]interface{}) 878 tempSet := NewGovernanceSet() 879 if err := rlp.DecodeBytes(governance, &tempData); err != nil { 880 logger.Error("Failed to decode governance data", "number", number, "err", err, "data", governance) 881 return 882 } 883 if err := json.Unmarshal(tempData, &tempItems); err != nil { 884 logger.Error("Failed to unmarshal governance data", "number", number, "err", err, "data", tempData) 885 return 886 887 } 888 tempItems = adjustDecodedSet(tempItems) 889 tempSet.Import(tempItems) 890 891 _, govItems, err := gov.ReadGovernance(number) 892 if err != nil { 893 logger.Error("Failed to read governance", "number", number, "err", err) 894 return 895 } 896 govSet := NewGovernanceSet() 897 govSet.Import(govItems) 898 899 // Store new governance items for next epoch to governance database 900 if err := gov.WriteGovernance(number, govSet, tempSet); err != nil { 901 logger.Crit("Failed to store new governance data", "number", number, "err", err) 902 } 903 } 904 } 905 } 906 907 func (gov *Governance) removeDuplicatedVote(vote *GovernanceVote, number uint64) { 908 gov.RemoveVote(vote.Key, vote.Value, number) 909 } 910 911 func (gov *Governance) UpdateCurrentSet(num uint64) { 912 newNumber, newGovernanceSet, _ := gov.ReadGovernance(num) 913 // Do the change only when the governance actually changed 914 if newGovernanceSet != nil && newNumber > gov.actualGovernanceBlock.Load().(uint64) { 915 gov.actualGovernanceBlock.Store(newNumber) 916 gov.currentSet.Import(newGovernanceSet) 917 gov.triggerChange(newGovernanceSet) 918 } 919 } 920 921 func (gov *Governance) triggerChange(src map[string]interface{}) { 922 for k, v := range src { 923 if f := GovernanceItems[GovernanceKeyMap[k]].trigger; f != nil { 924 f(gov, k, v) 925 } 926 } 927 } 928 929 func adjustDecodedSet(src map[string]interface{}) map[string]interface{} { 930 for k, v := range src { 931 x := reflect.ValueOf(v) 932 if x.Kind() == reflect.Float64 { 933 src[k] = uint64(v.(float64)) 934 } 935 if GovernanceKeyMap[k] == params.GoverningNode || 936 GovernanceKeyMap[k] == params.GovParamContract { 937 if reflect.TypeOf(v) == stringT { 938 src[k] = common.HexToAddress(v.(string)) 939 } else { 940 src[k] = v 941 } 942 } 943 } 944 return src 945 } 946 947 func (gov *Governance) GetGovernanceValue(key int) interface{} { 948 if v, ok := gov.currentSet.GetValue(key); !ok { 949 return nil 950 } else { 951 return v 952 } 953 } 954 955 func (gov *Governance) VerifyGovernance(received []byte) error { 956 change := []byte{} 957 if rlp.DecodeBytes(received, &change) != nil { 958 return ErrDecodeGovChange 959 } 960 961 rChangeSet := make(map[string]interface{}) 962 if json.Unmarshal(change, &rChangeSet) != nil { 963 return ErrUnmarshalGovChange 964 } 965 rChangeSet = adjustDecodedSet(rChangeSet) 966 967 if len(rChangeSet) != gov.changeSet.Size() { 968 logger.Error("Verification Error", "len(receivedChangeSet)", len(rChangeSet), "len(changeSet)", gov.changeSet.Size()) 969 } 970 971 for k, v := range rChangeSet { 972 if GovernanceKeyMap[k] == params.GoverningNode || 973 GovernanceKeyMap[k] == params.GovParamContract { 974 if reflect.TypeOf(v) == stringT { 975 v = common.HexToAddress(v.(string)) 976 } 977 } 978 979 have, _ := gov.changeSet.GetValue(GovernanceKeyMap[k]) 980 if have != v { 981 logger.Error("Verification Error", "key", k, "received", rChangeSet[k], "have", have, "receivedType", reflect.TypeOf(rChangeSet[k]), "haveType", reflect.TypeOf(have)) 982 return ErrVoteValueMismatch 983 } 984 } 985 return nil 986 } 987 988 type governanceJSON struct { 989 BlockNumber uint64 `json:"blockNumber"` 990 ChainConfig *params.ChainConfig `json:"chainConfig"` 991 VoteMap map[string]VoteStatus `json:"voteMap"` 992 NodeAddress common.Address `json:"nodeAddress"` 993 GovernanceVotes []GovernanceVote `json:"governanceVotes"` 994 GovernanceTally []GovernanceTallyItem `json:"governanceTally"` 995 CurrentSet map[string]interface{} `json:"currentSet"` 996 ChangeSet map[string]interface{} `json:"changeSet"` 997 } 998 999 func (gov *Governance) toJSON(num uint64) ([]byte, error) { 1000 ret := &governanceJSON{ 1001 BlockNumber: num, 1002 ChainConfig: gov.ChainConfig, 1003 VoteMap: gov.voteMap.Copy(), 1004 NodeAddress: gov.nodeAddress.Load().(common.Address), 1005 GovernanceVotes: gov.GovernanceVotes.Copy(), 1006 GovernanceTally: gov.GovernanceTallies.Copy(), 1007 CurrentSet: gov.currentSet.Items(), 1008 ChangeSet: gov.changeSet.Items(), 1009 } 1010 j, _ := json.Marshal(ret) 1011 return j, nil 1012 } 1013 1014 func (gov *Governance) UnmarshalJSON(b []byte) error { 1015 var j governanceJSON 1016 if err := json.Unmarshal(b, &j); err != nil { 1017 return err 1018 } 1019 // gov.ChainConfig is to be updated in MixedEngine. Do not overwrite it here. 1020 gov.voteMap.Import(j.VoteMap) 1021 gov.nodeAddress.Store(j.NodeAddress) 1022 gov.GovernanceVotes.Import(j.GovernanceVotes) 1023 gov.GovernanceTallies.Import(j.GovernanceTally) 1024 gov.currentSet.Import(adjustDecodedSet(j.CurrentSet)) 1025 gov.changeSet.Import(adjustDecodedSet(j.ChangeSet)) 1026 atomic.StoreUint64(&gov.lastGovernanceStateBlock, j.BlockNumber) 1027 1028 return nil 1029 } 1030 1031 func (gov *Governance) InitGovCache() { 1032 gov.initializeCache(gov.ChainConfig) 1033 } 1034 1035 func (gov *Governance) InitLastGovStateBlkNum() { 1036 atomic.StoreUint64(&gov.lastGovernanceStateBlock, 0) 1037 } 1038 1039 func (gov *Governance) CanWriteGovernanceState(num uint64) bool { 1040 if num <= atomic.LoadUint64(&gov.lastGovernanceStateBlock) { 1041 return false 1042 } 1043 return true 1044 } 1045 1046 func (gov *Governance) WriteGovernanceState(num uint64, isCheckpoint bool) error { 1047 if b, err := gov.toJSON(num); err != nil { 1048 logger.Error("Error in marshaling governance state", "err", err) 1049 return err 1050 } else { 1051 if err = gov.db.WriteGovernanceState(b); err != nil { 1052 logger.Error("Error in writing governance state", "err", err) 1053 return err 1054 } else { 1055 if isCheckpoint { 1056 atomic.StoreUint64(&gov.lastGovernanceStateBlock, num) 1057 } 1058 logger.Info("Successfully stored governance state", "num", num) 1059 return nil 1060 } 1061 } 1062 } 1063 1064 // ReadGovernanceState reads field values of the Governance struct from database. 1065 // It also updates params.stakingUpdateInterval and params.proposerUpdateInterval with the retrieved value. 1066 func (gov *Governance) ReadGovernanceState() { 1067 b, err := gov.db.ReadGovernanceState() 1068 if err != nil { 1069 logger.Info("No governance state found in a database") 1070 return 1071 } 1072 gov.UnmarshalJSON(b) 1073 gov.updateGovernanceParams() 1074 1075 logger.Info("Successfully loaded governance state from database", "blockNumber", atomic.LoadUint64(&gov.lastGovernanceStateBlock)) 1076 } 1077 1078 func (gov *Governance) SetBlockchain(bc blockChain) { 1079 gov.blockChain = bc 1080 } 1081 1082 func (gov *Governance) SetTxPool(txpool txPool) { 1083 gov.TxPool = txpool 1084 } 1085 1086 func (gov *Governance) GetTxPool() txPool { 1087 return gov.TxPool 1088 } 1089 1090 // GetGovernanceItemsFromChainConfig returns governance set 1091 // that is effective at the genesis block 1092 func GetGovernanceItemsFromChainConfig(config *params.ChainConfig) GovernanceSet { 1093 govSet := NewGovernanceSet() 1094 1095 // append to the return value `govSet` 1096 appendGovSet := func(govmap map[int]interface{}) { 1097 for k, v := range govmap { 1098 if err := govSet.SetValue(k, v); err != nil { 1099 writeFailLog(k, err) 1100 } 1101 } 1102 } 1103 1104 // original cypress params 1105 if config.Governance != nil { 1106 governance := config.Governance 1107 governanceMap := map[int]interface{}{ 1108 params.GovernanceMode: governance.GovernanceMode, 1109 params.GoverningNode: governance.GoverningNode, 1110 params.UnitPrice: config.UnitPrice, 1111 params.MintingAmount: governance.Reward.MintingAmount.String(), 1112 params.Ratio: governance.Reward.Ratio, 1113 params.UseGiniCoeff: governance.Reward.UseGiniCoeff, 1114 params.DeferredTxFee: governance.Reward.DeferredTxFee, 1115 params.MinimumStake: governance.Reward.MinimumStake.String(), 1116 params.StakeUpdateInterval: governance.Reward.StakingUpdateInterval, 1117 params.ProposerRefreshInterval: governance.Reward.ProposerUpdateInterval, 1118 } 1119 appendGovSet(governanceMap) 1120 } 1121 1122 if config.Istanbul != nil { 1123 istanbul := config.Istanbul 1124 istanbulMap := map[int]interface{}{ 1125 params.Epoch: istanbul.Epoch, 1126 params.Policy: istanbul.ProposerPolicy, 1127 params.CommitteeSize: istanbul.SubGroupSize, 1128 } 1129 appendGovSet(istanbulMap) 1130 } 1131 1132 // magma params 1133 if config.IsMagmaForkEnabled(common.Big0) && 1134 config.Governance.KIP71 != nil { 1135 kip71 := config.Governance.KIP71 1136 governanceMap := map[int]interface{}{ 1137 params.LowerBoundBaseFee: kip71.LowerBoundBaseFee, 1138 params.UpperBoundBaseFee: kip71.UpperBoundBaseFee, 1139 params.GasTarget: kip71.GasTarget, 1140 params.MaxBlockGasUsedForBaseFee: kip71.MaxBlockGasUsedForBaseFee, 1141 params.BaseFeeDenominator: kip71.BaseFeeDenominator, 1142 } 1143 appendGovSet(governanceMap) 1144 } 1145 1146 // kore params 1147 if config.IsKoreForkEnabled(common.Big0) && 1148 config.Governance != nil { 1149 governanceMap := map[int]interface{}{ 1150 params.DeriveShaImpl: uint64(config.DeriveShaImpl), // checkValueType expects uint64 1151 } 1152 if !common.EmptyAddress(config.Governance.GovParamContract) { 1153 governanceMap[params.GovParamContract] = config.Governance.GovParamContract 1154 } 1155 if config.Governance.Reward != nil && 1156 config.Governance.Reward.Kip82Ratio != "" { 1157 governanceMap[params.Kip82Ratio] = config.Governance.Reward.Kip82Ratio 1158 } 1159 appendGovSet(governanceMap) 1160 } 1161 1162 return govSet 1163 } 1164 1165 func writeFailLog(key int, err error) { 1166 msg := "Failed to set " + GovernanceKeyMapReverse[key] 1167 logger.Crit(msg, "err", err) 1168 } 1169 1170 func AddGovernanceCacheForTest(e HeaderEngine, num uint64, config *params.ChainConfig) { 1171 // addGovernanceCache only exists and relevant in *Governance. 1172 if g, ok := e.(*Governance); ok { 1173 data := GetGovernanceItemsFromChainConfig(config) 1174 g.addGovernanceCache(num, data) 1175 } 1176 } 1177 1178 func (gov *Governance) proposerUpdateInterval() uint64 { 1179 return gov.GetGovernanceValue(params.ProposerRefreshInterval).(uint64) 1180 } 1181 1182 func (gov *Governance) stakingUpdateInterval() uint64 { 1183 return gov.GetGovernanceValue(params.StakeUpdateInterval).(uint64) 1184 } 1185 1186 func (g *Governance) GetVoteMapCopy() map[string]VoteStatus { 1187 return g.voteMap.Copy() 1188 } 1189 1190 func (g *Governance) GetGovernanceTalliesCopy() []GovernanceTallyItem { 1191 return g.GovernanceTallies.Copy() 1192 } 1193 1194 func (gov *Governance) CurrentSetCopy() map[string]interface{} { 1195 return gov.currentSet.Items() 1196 } 1197 1198 func (gov *Governance) PendingChanges() map[string]interface{} { 1199 return gov.changeSet.Items() 1200 } 1201 1202 func (gov *Governance) Votes() []GovernanceVote { 1203 return gov.GovernanceVotes.Copy() 1204 } 1205 1206 func (gov *Governance) IdxCache() []uint64 { 1207 gov.idxCacheLock.RLock() 1208 defer gov.idxCacheLock.RUnlock() 1209 1210 copiedCache := make([]uint64, len(gov.idxCache)) 1211 copy(copiedCache, gov.idxCache) 1212 return copiedCache 1213 } 1214 1215 func (gov *Governance) IdxCacheFromDb() []uint64 { 1216 res, _ := gov.db.ReadRecentGovernanceIdx(0) 1217 return res 1218 } 1219 1220 // epochWithFallback returns the istanbul epoch. This function works even before loading any params 1221 // from database. We need epoch to load any param from database. 1222 func (gov *Governance) epochWithFallback() uint64 { 1223 // After UpdateParams() is called at least once, CurrentParams() should contain the Epoch 1224 if v, ok := gov.CurrentParams().Get(params.Epoch); ok { 1225 return v.(uint64) 1226 } 1227 // Otherwise after initializeCache() is called, initialParams should contain the Epoch 1228 if v, ok := gov.initialParams.Get(params.Epoch); ok { 1229 return v.(uint64) 1230 } 1231 1232 // Otherwise fallback to ChainConfig that is supplied to NewGovernance() 1233 if gov.ChainConfig.Istanbul != nil { 1234 return gov.ChainConfig.Istanbul.Epoch 1235 } 1236 // We shouldn't reach here because Governance is only relevant with Istanbul engine. 1237 logger.Crit("Failed to read governance. ChainConfig.Istanbul == nil") 1238 return params.DefaultEpoch // unreachable. just satisfying compiler. 1239 } 1240 1241 func (gov *Governance) CurrentParams() *params.GovParamSet { 1242 return gov.currentParams 1243 } 1244 1245 // EffectiveParams returns the parameter set used for generating the block `num` 1246 func (gov *Governance) EffectiveParams(num uint64) (*params.GovParamSet, error) { 1247 // TODO-Klaytn: Either handle epoch change, or permanently forbid epoch change. 1248 epoch := gov.epochWithFallback() 1249 1250 bignum := new(big.Int).SetUint64(num) 1251 1252 // Before Kore, ReadGovernance(num - 1) is used to generate block num 1253 if !gov.ChainConfig.IsKoreForkEnabled(bignum) && num != 0 { 1254 num -= 1 1255 } 1256 // Should be equivalent to Governance.ReadGovernance(), but without in-memory caches. 1257 // Not using in-memory caches to make it stateless, hence less error-prone. 1258 _, strMap, err := gov.db.ReadGovernanceAtNumber(num, epoch) 1259 if err != nil { 1260 logger.Error("ReadGovernanceAtNumber failed", "num", num, "err", err) 1261 return nil, err 1262 } 1263 pset, err := params.NewGovParamSetStrMap(strMap) 1264 if err != nil { 1265 logger.Error("NewGovParamSetStrMap failed", "num", num, "err", err) 1266 return nil, err 1267 } 1268 return pset, nil 1269 } 1270 1271 func (gov *Governance) UpdateParams(num uint64) error { 1272 pset, err := gov.EffectiveParams(num + 1) 1273 if err != nil { 1274 return err 1275 } 1276 gov.currentParams = pset 1277 return nil 1278 }