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  }