github.com/klaytn/klaytn@v1.12.1/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, checkBigInt, 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 checkUint64andBool(k string, v interface{}) bool { 249 // for Uint64 and Bool, no more check is needed 250 if reflect.TypeOf(v) == uint64T || reflect.TypeOf(v) == boolT { 251 return true 252 } 253 return false 254 } 255 256 func checkProposerPolicy(k string, v interface{}) bool { 257 if _, ok := ProposerPolicyMap[v.(string)]; ok { 258 return true 259 } 260 return false 261 } 262 263 func checkBigInt(k string, v interface{}) bool { 264 if v, ok := new(big.Int).SetString(v.(string), 10); !ok || v.Cmp(common.Big0) < 0 { 265 return false 266 } 267 return true 268 } 269 270 func checkAddress(k string, v interface{}) bool { 271 if _, ok := v.(common.Address); ok { 272 return true 273 } 274 return false 275 } 276 277 func checkAddressOrListOfUniqueAddresses(k string, v interface{}) bool { 278 if checkAddress(k, v) { 279 return true 280 } 281 if _, ok := v.([]common.Address); !ok { 282 return false 283 } 284 285 // there should not be duplicated addresses, if value contains multiple addresses 286 addressExists := make(map[common.Address]bool) 287 for _, address := range v.([]common.Address) { 288 if _, ok := addressExists[address]; ok { 289 return false 290 } else { 291 addressExists[address] = true 292 } 293 } 294 return true 295 } 296 297 func isEqualValue(k int, v1 interface{}, v2 interface{}) bool { 298 if reflect.TypeOf(v1) != reflect.TypeOf(v2) { 299 return false 300 } 301 302 if GovernanceItems[k].t == addressT && reflect.TypeOf(v1) != addressT { 303 value1, ok1 := v1.([]common.Address) 304 value2, ok2 := v2.([]common.Address) 305 if ok1 == false || ok2 == false { 306 return false 307 } 308 return reflect.DeepEqual(value1, value2) 309 } 310 311 return v1 == v2 312 } 313 314 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) { 315 gVote := new(GovernanceVote) 316 317 if len(header.Vote) > 0 { 318 var err error 319 320 if err = rlp.DecodeBytes(header.Vote, gVote); err != nil { 321 logger.Error("Failed to decode a vote. This vote will be ignored", "number", header.Number) 322 return valset, votes, tally 323 } 324 if gVote, err = gov.ParseVoteValue(gVote); err != nil { 325 logger.Error("Failed to parse a vote value. This vote will be ignored", "number", header.Number) 326 return valset, votes, tally 327 } 328 329 // If the given key is forbidden, stop processing 330 if _, ok := GovernanceForbiddenKeyMap[gVote.Key]; ok { 331 logger.Warn("Forbidden vote key was received", "key", gVote.Key, "value", gVote.Value, "from", gVote.Validator) 332 return valset, votes, tally 333 } 334 335 key := GovernanceKeyMap[gVote.Key] 336 switch key { 337 case params.GoverningNode: 338 v, ok := gVote.Value.(common.Address) 339 if !ok { 340 logger.Warn("Invalid value Type", "number", header.Number, "Validator", gVote.Validator, "key", gVote.Key, "value", gVote.Value) 341 return valset, votes, tally 342 } 343 _, addr := valset.GetByAddress(v) 344 if addr == nil { 345 logger.Warn("Invalid governing node address", "number", header.Number, "Validator", gVote.Validator, "key", gVote.Key, "value", gVote.Value) 346 return valset, votes, tally 347 } 348 case params.AddValidator, params.RemoveValidator: 349 var addresses []common.Address 350 351 if addr, ok := gVote.Value.(common.Address); ok { 352 addresses = append(addresses, addr) 353 } else if addrs, ok := gVote.Value.([]common.Address); ok { 354 addresses = addrs 355 } else { 356 logger.Warn("Invalid value Type", "number", header.Number, "Validator", gVote.Validator, "key", gVote.Key, "value", gVote.Value) 357 } 358 359 for _, address := range addresses { 360 if !gov.checkVote(address, key == params.AddValidator, valset) { 361 if writable && proposer == self { 362 logger.Warn("A meaningless vote has been proposed. It is being removed without further handling", "key", gVote.Key, "value", gVote.Value) 363 gov.removeDuplicatedVote(gVote, header.Number.Uint64()) 364 } 365 return valset, votes, tally 366 } 367 } 368 } 369 370 number := header.Number.Uint64() 371 // Check vote's validity 372 if gVote, ok := gov.ValidateVote(gVote); ok { 373 pset, err := gov.EffectiveParams(number) 374 if err != nil { 375 logger.Error("EffectiveParams failed", "number", number) 376 return valset, votes, tally 377 } 378 governanceMode := pset.GovernanceModeInt() 379 governingNode := pset.GoverningNode() 380 381 // Remove old vote with same validator and key 382 votes, tally = gov.removePreviousVote(valset, votes, tally, proposer, gVote, governanceMode, governingNode, writable) 383 384 // Add new Vote to snapshot.GovernanceVotes 385 votes = append(votes, *gVote) 386 387 // Tally up the new vote. This will be cleared when Epoch ends. 388 // Add to GovernanceTallies if it doesn't exist 389 valset, votes, tally = gov.addNewVote(valset, votes, tally, gVote, governanceMode, governingNode, number, writable) 390 391 // If this vote was casted by this node, remove it 392 if writable && self == proposer { 393 gov.removeDuplicatedVote(gVote, header.Number.Uint64()) 394 } 395 } else { 396 logger.Warn("Received Vote was invalid", "number", header.Number, "Validator", gVote.Validator, "key", gVote.Key, "value", gVote.Value) 397 } 398 if writable && number > atomic.LoadUint64(&gov.lastGovernanceStateBlock) { 399 gov.GovernanceVotes.Import(votes) 400 gov.GovernanceTallies.Import(tally) 401 } 402 } 403 return valset, votes, tally 404 } 405 406 func (gov *Governance) checkVote(address common.Address, isKeyAddValidator bool, valset istanbul.ValidatorSet) bool { 407 _, validator := valset.GetByAddress(address) 408 if validator == nil { 409 _, validator = valset.GetDemotedByAddress(address) 410 } 411 return (validator != nil && !isKeyAddValidator) || (validator == nil && isKeyAddValidator) 412 } 413 414 func (gov *Governance) isGovernanceModeSingleOrNone(governanceMode int, governingNode common.Address, voter common.Address) bool { 415 return governanceMode == params.GovernanceMode_None || (governanceMode == params.GovernanceMode_Single && voter == governingNode) 416 } 417 418 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) { 419 ret := make([]GovernanceVote, len(votes)) 420 copy(ret, votes) 421 422 // Removing duplicated previous GovernanceVotes 423 for idx, vote := range votes { 424 // Check if previous vote from same validator exists 425 if vote.Validator == validator && vote.Key == gVote.Key { 426 // Reduce Tally 427 _, v := valset.GetByAddress(vote.Validator) 428 vp := v.VotingPower() 429 var currentVotes uint64 430 currentVotes, tally = gov.changeGovernanceTally(tally, vote.Key, vote.Value, vp, false) 431 432 // Remove the old vote from GovernanceVotes 433 ret = append(votes[:idx], votes[idx+1:]...) 434 if writable { 435 if gov.isGovernanceModeSingleOrNone(governanceMode, governingNode, gVote.Validator) || 436 (governanceMode == params.GovernanceMode_Ballot && currentVotes <= valset.TotalVotingPower()/2) { 437 if v, ok := gov.changeSet.GetValue(GovernanceKeyMap[vote.Key]); ok && v == vote.Value { 438 gov.changeSet.RemoveItem(vote.Key) 439 } 440 } 441 } 442 break 443 } 444 } 445 return ret, tally 446 } 447 448 // changeGovernanceTally updates snapshot's tally for governance votes. 449 func (gov *Governance) changeGovernanceTally(tally []GovernanceTallyItem, key string, value interface{}, vp uint64, isAdd bool) (uint64, []GovernanceTallyItem) { 450 found := false 451 var currentVote uint64 452 ret := make([]GovernanceTallyItem, len(tally)) 453 copy(ret, tally) 454 455 for idx, v := range tally { 456 if v.Key == key && isEqualValue(GovernanceKeyMap[key], v.Value, value) { 457 if isAdd { 458 ret[idx].Votes += vp 459 } else { 460 if ret[idx].Votes > vp { 461 ret[idx].Votes -= vp 462 } else { 463 ret[idx].Votes = uint64(0) 464 } 465 } 466 467 currentVote = ret[idx].Votes 468 469 if currentVote == 0 { 470 ret = append(tally[:idx], tally[idx+1:]...) 471 } 472 found = true 473 break 474 } 475 } 476 477 if !found && isAdd { 478 ret = append(ret, GovernanceTallyItem{Key: key, Value: value, Votes: vp}) 479 return vp, ret 480 } else { 481 return currentVote, ret 482 } 483 } 484 485 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) { 486 _, v := valset.GetByAddress(gVote.Validator) 487 if v != nil { 488 vp := v.VotingPower() 489 var currentVotes uint64 490 currentVotes, tally = gov.changeGovernanceTally(tally, gVote.Key, gVote.Value, vp, true) 491 if gov.isGovernanceModeSingleOrNone(governanceMode, governingNode, gVote.Validator) || 492 (governanceMode == params.GovernanceMode_Ballot && currentVotes > valset.TotalVotingPower()/2) { 493 switch GovernanceKeyMap[gVote.Key] { 494 case params.AddValidator: 495 if addr, ok := gVote.Value.(common.Address); ok { 496 valset.AddValidator(addr) 497 } else { 498 for _, address := range gVote.Value.([]common.Address) { 499 valset.AddValidator(address) 500 } 501 } 502 case params.RemoveValidator: 503 if addr, ok := gVote.Value.(common.Address); ok { 504 valset.RemoveValidator(addr) 505 } else { 506 for _, target := range gVote.Value.([]common.Address) { 507 valset.RemoveValidator(target) 508 votes = gov.removeVotesFromRemovedNode(votes, target) 509 } 510 } 511 case params.Timeout: 512 timeout := gVote.Value.(uint64) 513 atomic.StoreUint64(&istanbul.DefaultConfig.Timeout, timeout) 514 fallthrough 515 default: 516 if writable && blockNum >= atomic.LoadUint64(&gov.lastGovernanceStateBlock) { 517 logger.Info("Reflecting parameter vote", "num", blockNum, "key", gVote.Key, "value", gVote.Value) 518 gov.ReflectVotes(*gVote) 519 } 520 } 521 } 522 } 523 return valset, votes, tally 524 } 525 526 func (gov *Governance) removeVotesFromRemovedNode(votes []GovernanceVote, addr common.Address) []GovernanceVote { 527 ret := make([]GovernanceVote, len(votes)) 528 copy(ret, votes) 529 530 for i := 0; i < len(votes); i++ { 531 if votes[i].Validator == addr { 532 // Uncast the vote from the chronological list 533 ret = append(votes[:i], votes[i+1:]...) 534 i-- 535 } 536 } 537 return ret 538 }