github.com/klaytn/klaytn@v1.10.2/governance/handler.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 "math/big" 21 "reflect" 22 "strconv" 23 "strings" 24 "sync/atomic" 25 26 "github.com/klaytn/klaytn/blockchain/types" 27 "github.com/klaytn/klaytn/common" 28 "github.com/klaytn/klaytn/consensus/istanbul" 29 "github.com/klaytn/klaytn/params" 30 "github.com/klaytn/klaytn/rlp" 31 ) 32 33 type check struct { 34 t reflect.Type 35 validator func(k string, v interface{}) bool 36 trigger func(g *Governance, k string, v interface{}) 37 } 38 39 var ( 40 stringT = reflect.TypeOf("") 41 uint64T = reflect.TypeOf(uint64(0)) 42 addressT = reflect.TypeOf(common.StringToAddress("0x0")) 43 boolT = reflect.TypeOf(true) 44 float64T = reflect.TypeOf(float64(0.0)) 45 ) 46 47 var GovernanceItems = map[int]check{ 48 params.GovernanceMode: {stringT, checkGovernanceMode, nil}, 49 params.GoverningNode: {addressT, checkAddress, nil}, 50 params.GovParamContract: {addressT, checkAddress, nil}, 51 params.UnitPrice: {uint64T, checkUint64andBool, nil}, 52 params.DeriveShaImpl: {uint64T, checkUint64andBool, nil}, 53 params.LowerBoundBaseFee: {uint64T, checkUint64andBool, nil}, 54 params.UpperBoundBaseFee: {uint64T, checkUint64andBool, nil}, 55 params.GasTarget: {uint64T, checkUint64andBool, nil}, 56 params.MaxBlockGasUsedForBaseFee: {uint64T, checkUint64andBool, nil}, 57 params.BaseFeeDenominator: {uint64T, checkUint64andBool, nil}, 58 params.AddValidator: {addressT, checkAddressOrListOfUniqueAddresses, nil}, 59 params.RemoveValidator: {addressT, checkAddressOrListOfUniqueAddresses, nil}, 60 params.MintingAmount: {stringT, checkBigInt, nil}, 61 params.Ratio: {stringT, checkRatio, nil}, 62 params.UseGiniCoeff: {boolT, checkUint64andBool, nil}, 63 params.Kip82Ratio: {stringT, checkKip82Ratio, nil}, 64 params.DeferredTxFee: {boolT, checkUint64andBool, nil}, 65 params.MinimumStake: {stringT, checkRewardMinimumStake, nil}, 66 params.StakeUpdateInterval: {uint64T, checkUint64andBool, nil}, 67 params.ProposerRefreshInterval: {uint64T, checkUint64andBool, nil}, 68 params.Epoch: {uint64T, checkUint64andBool, nil}, 69 params.Policy: {uint64T, checkUint64andBool, nil}, 70 params.CommitteeSize: {uint64T, checkCommitteeSize, nil}, 71 params.ConstTxGasHumanReadable: {uint64T, checkUint64andBool, updateTxGasHumanReadable}, 72 params.Timeout: {uint64T, checkUint64andBool, nil}, 73 } 74 75 func updateTxGasHumanReadable(g *Governance, k string, v interface{}) { 76 params.TxGasHumanReadable = v.(uint64) 77 logger.Info("TxGasHumanReadable changed", "New value", params.TxGasHumanReadable) 78 } 79 80 // AddVote adds a vote to the voteMap 81 func (g *Governance) AddVote(key string, val interface{}) bool { 82 key = g.getKey(key) 83 84 // If the key is forbidden, stop processing it 85 if _, ok := GovernanceForbiddenKeyMap[key]; ok { 86 return false 87 } 88 89 vote := &GovernanceVote{Key: key, Value: val} 90 var ok bool 91 if vote, ok = g.ValidateVote(vote); ok { 92 g.voteMap.SetValue(key, VoteStatus{ 93 Value: vote.Value, 94 Casted: false, 95 Num: 0, 96 }) 97 return true 98 } 99 return false 100 } 101 102 func (g *Governance) adjustValueType(key string, val interface{}) interface{} { 103 k := GovernanceKeyMap[key] 104 105 // When an int value comes from JS console, it comes as a float64 106 if GovernanceItems[k].t == uint64T { 107 v, ok := val.(float64) 108 if !ok { 109 return val 110 } 111 if float64(uint64(v)) == v { 112 return uint64(v) 113 } 114 return val 115 } 116 117 // Otherwise, it comes as a string 118 v, ok := val.(string) 119 if !ok { 120 return val 121 } 122 if GovernanceItems[k].t == addressT { 123 addresses := strings.Split(v, ",") 124 switch len(addresses) { 125 case 0: 126 return val 127 case 1: 128 str := strings.Trim(v, " ") 129 if common.IsHexAddress(str) { 130 return common.HexToAddress(str) 131 } else { 132 return val 133 } 134 default: 135 var nodeAddresses []common.Address 136 for _, str := range addresses { 137 str = strings.Trim(str, " ") 138 if common.IsHexAddress(str) { 139 nodeAddresses = append(nodeAddresses, common.HexToAddress(str)) 140 } else { 141 return val 142 } 143 } 144 return nodeAddresses 145 } 146 } else { 147 // If a string text come as uppercase, make it into lowercase 148 return strings.ToLower(v) 149 } 150 } 151 152 func checkValueType(v interface{}, expectType reflect.Type) bool { 153 var ok bool 154 switch expectType { 155 case uint64T: 156 _, ok = v.(uint64) 157 case stringT: 158 _, ok = v.(string) 159 case addressT: 160 _, ok = v.(common.Address) 161 if !ok { 162 _, ok = v.([]common.Address) 163 } 164 case boolT: 165 _, ok = v.(bool) 166 default: 167 ok = false 168 } 169 return ok 170 } 171 172 func checkKey(k string) bool { 173 key := GovernanceKeyMap[k] 174 if _, ok := GovernanceItems[key]; ok { 175 return true 176 } 177 return false 178 } 179 180 func (gov *Governance) ValidateVote(vote *GovernanceVote) (*GovernanceVote, bool) { 181 vote.Key = gov.getKey(vote.Key) 182 key := GovernanceKeyMap[vote.Key] 183 vote.Value = gov.adjustValueType(vote.Key, vote.Value) 184 185 if checkKey(vote.Key) && checkValueType(vote.Value, GovernanceItems[key].t) { 186 return vote, GovernanceItems[key].validator(vote.Key, vote.Value) 187 } 188 return vote, false 189 } 190 191 func checkRatio(k string, v interface{}) bool { 192 x := strings.Split(v.(string), "/") 193 if len(x) != params.RewardSliceCount { 194 return false 195 } 196 var sum uint64 197 for _, item := range x { 198 v, err := strconv.ParseUint(item, 10, 64) 199 if err != nil { 200 return false 201 } 202 sum += v 203 } 204 if sum == 100 { 205 return true 206 } else { 207 return false 208 } 209 } 210 211 func checkKip82Ratio(k string, v interface{}) bool { 212 x := strings.Split(v.(string), "/") 213 if len(x) != params.RewardKip82SliceCount { 214 return false 215 } 216 var sum uint64 217 for _, item := range x { 218 v, err := strconv.ParseUint(item, 10, 64) 219 if err != nil { 220 return false 221 } 222 sum += v 223 } 224 if sum == 100 { 225 return true 226 } else { 227 return false 228 } 229 } 230 231 func checkGovernanceMode(k string, v interface{}) bool { 232 if _, ok := GovernanceModeMap[v.(string)]; ok { 233 return true 234 } 235 return false 236 } 237 238 func checkCommitteeSize(k string, v interface{}) bool { 239 if !checkUint64andBool(k, v) { 240 return false 241 } 242 if v == uint64(0) { 243 return false 244 } 245 return true 246 } 247 248 func checkRewardMinimumStake(k string, v interface{}) bool { 249 if !checkBigInt(k, v) { 250 return false 251 } 252 if v, ok := new(big.Int).SetString(v.(string), 10); ok { 253 if v.Cmp(common.Big0) < 0 { 254 return false 255 } 256 } 257 return true 258 } 259 260 func checkUint64andBool(k string, v interface{}) bool { 261 // for Uint64 and Bool, no more check is needed 262 if reflect.TypeOf(v) == uint64T || reflect.TypeOf(v) == boolT { 263 return true 264 } 265 return false 266 } 267 268 func checkProposerPolicy(k string, v interface{}) bool { 269 if _, ok := ProposerPolicyMap[v.(string)]; ok { 270 return true 271 } 272 return false 273 } 274 275 func checkBigInt(k string, v interface{}) bool { 276 x := new(big.Int) 277 if _, ok := x.SetString(v.(string), 10); ok { 278 return true 279 } 280 return false 281 } 282 283 func checkAddress(k string, v interface{}) bool { 284 if _, ok := v.(common.Address); ok { 285 return true 286 } 287 return false 288 } 289 290 func checkAddressOrListOfUniqueAddresses(k string, v interface{}) bool { 291 if checkAddress(k, v) { 292 return true 293 } 294 if _, ok := v.([]common.Address); !ok { 295 return false 296 } 297 298 // there should not be duplicated addresses, if value contains multiple addresses 299 addressExists := make(map[common.Address]bool) 300 for _, address := range v.([]common.Address) { 301 if _, ok := addressExists[address]; ok { 302 return false 303 } else { 304 addressExists[address] = true 305 } 306 } 307 return true 308 } 309 310 func isEqualValue(k int, v1 interface{}, v2 interface{}) bool { 311 if reflect.TypeOf(v1) != reflect.TypeOf(v2) { 312 return false 313 } 314 315 if GovernanceItems[k].t == addressT && reflect.TypeOf(v1) != addressT { 316 value1, ok1 := v1.([]common.Address) 317 value2, ok2 := v2.([]common.Address) 318 if ok1 == false || ok2 == false { 319 return false 320 } 321 return reflect.DeepEqual(value1, value2) 322 } 323 324 return v1 == v2 325 } 326 327 func (gov *Governance) HandleGovernanceVote(valset istanbul.ValidatorSet, votes []GovernanceVote, tally []GovernanceTallyItem, header *types.Header, proposer common.Address, self common.Address, writable bool) (istanbul.ValidatorSet, []GovernanceVote, []GovernanceTallyItem) { 328 gVote := new(GovernanceVote) 329 330 if len(header.Vote) > 0 { 331 var err error 332 333 if err = rlp.DecodeBytes(header.Vote, gVote); err != nil { 334 logger.Error("Failed to decode a vote. This vote will be ignored", "number", header.Number) 335 return valset, votes, tally 336 } 337 if gVote, err = gov.ParseVoteValue(gVote); err != nil { 338 logger.Error("Failed to parse a vote value. This vote will be ignored", "number", header.Number) 339 return valset, votes, tally 340 } 341 342 // If the given key is forbidden, stop processing 343 if _, ok := GovernanceForbiddenKeyMap[gVote.Key]; ok { 344 logger.Warn("Forbidden vote key was received", "key", gVote.Key, "value", gVote.Value, "from", gVote.Validator) 345 return valset, votes, tally 346 } 347 348 key := GovernanceKeyMap[gVote.Key] 349 switch key { 350 case params.GoverningNode: 351 v, ok := gVote.Value.(common.Address) 352 if !ok { 353 logger.Warn("Invalid value Type", "number", header.Number, "Validator", gVote.Validator, "key", gVote.Key, "value", gVote.Value) 354 return valset, votes, tally 355 } 356 _, addr := valset.GetByAddress(v) 357 if addr == nil { 358 logger.Warn("Invalid governing node address", "number", header.Number, "Validator", gVote.Validator, "key", gVote.Key, "value", gVote.Value) 359 return valset, votes, tally 360 } 361 case params.AddValidator, params.RemoveValidator: 362 var addresses []common.Address 363 364 if addr, ok := gVote.Value.(common.Address); ok { 365 addresses = append(addresses, addr) 366 } else if addrs, ok := gVote.Value.([]common.Address); ok { 367 addresses = addrs 368 } else { 369 logger.Warn("Invalid value Type", "number", header.Number, "Validator", gVote.Validator, "key", gVote.Key, "value", gVote.Value) 370 } 371 372 for _, address := range addresses { 373 if !gov.checkVote(address, key == params.AddValidator, valset) { 374 if writable && proposer == self { 375 logger.Warn("A meaningless vote has been proposed. It is being removed without further handling", "key", gVote.Key, "value", gVote.Value) 376 gov.removeDuplicatedVote(gVote, header.Number.Uint64()) 377 } 378 return valset, votes, tally 379 } 380 } 381 } 382 383 number := header.Number.Uint64() 384 // Check vote's validity 385 if gVote, ok := gov.ValidateVote(gVote); ok { 386 pset, err := gov.EffectiveParams(number) 387 if err != nil { 388 logger.Error("EffectiveParams failed", "number", number) 389 return valset, votes, tally 390 } 391 governanceMode := pset.GovernanceModeInt() 392 governingNode := pset.GoverningNode() 393 394 // Remove old vote with same validator and key 395 votes, tally = gov.removePreviousVote(valset, votes, tally, proposer, gVote, governanceMode, governingNode, writable) 396 397 // Add new Vote to snapshot.GovernanceVotes 398 votes = append(votes, *gVote) 399 400 // Tally up the new vote. This will be cleared when Epoch ends. 401 // Add to GovernanceTallies if it doesn't exist 402 valset, votes, tally = gov.addNewVote(valset, votes, tally, gVote, governanceMode, governingNode, number, writable) 403 404 // If this vote was casted by this node, remove it 405 if writable && self == proposer { 406 gov.removeDuplicatedVote(gVote, header.Number.Uint64()) 407 } 408 } else { 409 logger.Warn("Received Vote was invalid", "number", header.Number, "Validator", gVote.Validator, "key", gVote.Key, "value", gVote.Value) 410 } 411 if writable && number > atomic.LoadUint64(&gov.lastGovernanceStateBlock) { 412 gov.GovernanceVotes.Import(votes) 413 gov.GovernanceTallies.Import(tally) 414 } 415 } 416 return valset, votes, tally 417 } 418 419 func (gov *Governance) checkVote(address common.Address, isKeyAddValidator bool, valset istanbul.ValidatorSet) bool { 420 _, validator := valset.GetByAddress(address) 421 if validator == nil { 422 _, validator = valset.GetDemotedByAddress(address) 423 } 424 return (validator != nil && !isKeyAddValidator) || (validator == nil && isKeyAddValidator) 425 } 426 427 func (gov *Governance) isGovernanceModeSingleOrNone(governanceMode int, governingNode common.Address, voter common.Address) bool { 428 return governanceMode == params.GovernanceMode_None || (governanceMode == params.GovernanceMode_Single && voter == governingNode) 429 } 430 431 func (gov *Governance) removePreviousVote(valset istanbul.ValidatorSet, votes []GovernanceVote, tally []GovernanceTallyItem, validator common.Address, gVote *GovernanceVote, governanceMode int, governingNode common.Address, writable bool) ([]GovernanceVote, []GovernanceTallyItem) { 432 ret := make([]GovernanceVote, len(votes)) 433 copy(ret, votes) 434 435 // Removing duplicated previous GovernanceVotes 436 for idx, vote := range votes { 437 // Check if previous vote from same validator exists 438 if vote.Validator == validator && vote.Key == gVote.Key { 439 // Reduce Tally 440 _, v := valset.GetByAddress(vote.Validator) 441 vp := v.VotingPower() 442 var currentVotes uint64 443 currentVotes, tally = gov.changeGovernanceTally(tally, vote.Key, vote.Value, vp, false) 444 445 // Remove the old vote from GovernanceVotes 446 ret = append(votes[:idx], votes[idx+1:]...) 447 if writable { 448 if gov.isGovernanceModeSingleOrNone(governanceMode, governingNode, gVote.Validator) || 449 (governanceMode == params.GovernanceMode_Ballot && currentVotes <= valset.TotalVotingPower()/2) { 450 if v, ok := gov.changeSet.GetValue(GovernanceKeyMap[vote.Key]); ok && v == vote.Value { 451 gov.changeSet.RemoveItem(vote.Key) 452 } 453 } 454 } 455 break 456 } 457 } 458 return ret, tally 459 } 460 461 // changeGovernanceTally updates snapshot's tally for governance votes. 462 func (gov *Governance) changeGovernanceTally(tally []GovernanceTallyItem, key string, value interface{}, vp uint64, isAdd bool) (uint64, []GovernanceTallyItem) { 463 found := false 464 var currentVote uint64 465 ret := make([]GovernanceTallyItem, len(tally)) 466 copy(ret, tally) 467 468 for idx, v := range tally { 469 if v.Key == key && isEqualValue(GovernanceKeyMap[key], v.Value, value) { 470 if isAdd { 471 ret[idx].Votes += vp 472 } else { 473 if ret[idx].Votes > vp { 474 ret[idx].Votes -= vp 475 } else { 476 ret[idx].Votes = uint64(0) 477 } 478 } 479 480 currentVote = ret[idx].Votes 481 482 if currentVote == 0 { 483 ret = append(tally[:idx], tally[idx+1:]...) 484 } 485 found = true 486 break 487 } 488 } 489 490 if !found && isAdd { 491 ret = append(ret, GovernanceTallyItem{Key: key, Value: value, Votes: vp}) 492 return vp, ret 493 } else { 494 return currentVote, ret 495 } 496 } 497 498 func (gov *Governance) addNewVote(valset istanbul.ValidatorSet, votes []GovernanceVote, tally []GovernanceTallyItem, gVote *GovernanceVote, governanceMode int, governingNode common.Address, blockNum uint64, writable bool) (istanbul.ValidatorSet, []GovernanceVote, []GovernanceTallyItem) { 499 _, v := valset.GetByAddress(gVote.Validator) 500 if v != nil { 501 vp := v.VotingPower() 502 var currentVotes uint64 503 currentVotes, tally = gov.changeGovernanceTally(tally, gVote.Key, gVote.Value, vp, true) 504 if gov.isGovernanceModeSingleOrNone(governanceMode, governingNode, gVote.Validator) || 505 (governanceMode == params.GovernanceMode_Ballot && currentVotes > valset.TotalVotingPower()/2) { 506 switch GovernanceKeyMap[gVote.Key] { 507 case params.AddValidator: 508 // reward.GetStakingInfo() 509 if addr, ok := gVote.Value.(common.Address); ok { 510 valset.AddValidator(addr) 511 } else { 512 for _, address := range gVote.Value.([]common.Address) { 513 valset.AddValidator(address) 514 } 515 } 516 case params.RemoveValidator: 517 if addr, ok := gVote.Value.(common.Address); ok { 518 valset.RemoveValidator(addr) 519 } else { 520 for _, target := range gVote.Value.([]common.Address) { 521 valset.RemoveValidator(target) 522 votes = gov.removeVotesFromRemovedNode(votes, target) 523 } 524 } 525 case params.Timeout: 526 timeout := gVote.Value.(uint64) 527 atomic.StoreUint64(&istanbul.DefaultConfig.Timeout, timeout) 528 fallthrough 529 default: 530 if writable && blockNum > atomic.LoadUint64(&gov.lastGovernanceStateBlock) { 531 logger.Info("Reflecting parameter vote", "num", blockNum, "key", gVote.Key, "value", gVote.Value) 532 gov.ReflectVotes(*gVote) 533 } 534 } 535 } 536 } 537 return valset, votes, tally 538 } 539 540 func (gov *Governance) removeVotesFromRemovedNode(votes []GovernanceVote, addr common.Address) []GovernanceVote { 541 ret := make([]GovernanceVote, len(votes)) 542 copy(ret, votes) 543 544 for i := 0; i < len(votes); i++ { 545 if votes[i].Validator == addr { 546 // Uncast the vote from the chronological list 547 ret = append(votes[:i], votes[i+1:]...) 548 i-- 549 } 550 } 551 return ret 552 }