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  }