github.com/klaytn/klaytn@v1.12.1/governance/default_test.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/json" 21 "fmt" 22 "math/big" 23 "reflect" 24 "testing" 25 26 gotest_assert "gotest.tools/assert" 27 28 "github.com/klaytn/klaytn/blockchain" 29 "github.com/klaytn/klaytn/blockchain/types" 30 "github.com/klaytn/klaytn/common" 31 "github.com/klaytn/klaytn/consensus/istanbul" 32 "github.com/klaytn/klaytn/consensus/istanbul/validator" 33 "github.com/klaytn/klaytn/params" 34 "github.com/klaytn/klaytn/rlp" 35 "github.com/klaytn/klaytn/storage/database" 36 "github.com/stretchr/testify/assert" 37 ) 38 39 type voteValue struct { 40 k string 41 v interface{} 42 e bool 43 } 44 45 var tstData = []voteValue{ 46 {k: "istanbul.epoch", v: uint64(30000), e: true}, 47 {k: "istanbul.epoch", v: "bad", e: false}, 48 {k: "istanbul.epoch", v: float64(30000.00), e: true}, 49 {k: "istanbul.Epoch", v: float64(30000.10), e: false}, 50 {k: "istanbul.epoch", v: true, e: false}, 51 {k: "istanbul.committeesize", v: uint64(7), e: true}, 52 {k: "istanbul.committeesize", v: float64(7.0), e: true}, 53 {k: "istanbul.committeesize", v: float64(7.1), e: false}, 54 {k: "istanbul.committeesize", v: "7", e: false}, 55 {k: "istanbul.committeesize", v: true, e: false}, 56 {k: "istanbul.committeesize", v: float64(-7), e: false}, 57 {k: "istanbul.committeesize", v: uint64(0), e: false}, 58 {k: "istanbul.policy", v: "roundrobin", e: false}, 59 {k: "istanbul.policy", v: "RoundRobin", e: false}, 60 {k: "istanbul.policy", v: "sticky", e: false}, 61 {k: "istanbul.policy", v: "weightedrandom", e: false}, 62 {k: "istanbul.policy", v: "WeightedRandom", e: false}, 63 {k: "istanbul.policy", v: uint64(0), e: false}, 64 {k: "istanbul.policy", v: uint64(1), e: false}, 65 {k: "istanbul.policy", v: uint64(2), e: false}, 66 {k: "istanbul.policy", v: float64(1.2), e: false}, 67 {k: "istanbul.policy", v: float64(1.0), e: false}, 68 {k: "istanbul.policy", v: true, e: false}, 69 {k: "governance.governancemode", v: "none", e: true}, 70 {k: "governance.governancemode", v: "single", e: true}, 71 {k: "governance.governancemode", v: "ballot", e: true}, 72 {k: "governance.governancemode", v: 0, e: false}, 73 {k: "governance.governancemode", v: 1, e: false}, 74 {k: "governance.governancemode", v: 2, e: false}, 75 {k: "governance.governancemode", v: "unexpected", e: false}, 76 {k: "governance.governingnode", v: "0x00000000000000000000", e: false}, 77 {k: "governance.governingnode", v: "0x0000000000000000000000000000000000000000", e: true}, 78 {k: "governance.governingnode", v: "0x000000000000000000000000000abcd000000000", e: true}, 79 {k: "governance.governingnode", v: "000000000000000000000000000abcd000000000", e: true}, 80 {k: "governance.governingnode", v: common.HexToAddress("000000000000000000000000000abcd000000000"), e: true}, 81 {k: "governance.governingnode", v: "0x000000000000000000000000000xxxx000000000", e: false}, 82 {k: "governance.governingnode", v: "address", e: false}, 83 {k: "governance.governingnode", v: 0, e: false}, 84 {k: "governance.governingnode", v: true, e: false}, 85 {k: "governance.govparamcontract", v: "0x00000000000000000000", e: false}, 86 {k: "governance.govparamcontract", v: "0x0000000000000000000000000000000000000000", e: true}, 87 {k: "governance.govparamcontract", v: "0x000000000000000000000000000abcd000000000", e: true}, 88 {k: "governance.govparamcontract", v: "000000000000000000000000000abcd000000000", e: true}, 89 {k: "governance.govparamcontract", v: common.HexToAddress("000000000000000000000000000abcd000000000"), e: true}, 90 {k: "governance.govparamcontract", v: "0x000000000000000000000000000xxxx000000000", e: false}, 91 {k: "governance.govparamcontract", v: "address", e: false}, 92 {k: "governance.govparamcontract", v: 0, e: false}, 93 {k: "governance.govparamcontract", v: true, e: false}, 94 {k: "governance.unitprice", v: float64(0.0), e: true}, 95 {k: "governance.unitprice", v: float64(0.1), e: false}, 96 {k: "governance.unitprice", v: uint64(25000000000), e: true}, 97 {k: "governance.unitprice", v: float64(-10), e: false}, 98 {k: "governance.unitprice", v: "25000000000", e: false}, 99 {k: "governance.unitprice", v: true, e: false}, 100 {k: "governance.deriveshaimpl", v: float64(0.0), e: true}, 101 {k: "governance.deriveshaimpl", v: float64(0.1), e: false}, 102 {k: "governance.deriveshaimpl", v: uint64(2), e: true}, 103 {k: "governance.deriveshaimpl", v: float64(-1), e: false}, 104 {k: "governance.deriveshaimpl", v: "2", e: false}, 105 {k: "governance.deriveshaimpl", v: true, e: false}, 106 {k: "reward.useginicoeff", v: false, e: true}, 107 {k: "reward.useginicoeff", v: true, e: true}, 108 {k: "reward.useginicoeff", v: "true", e: false}, 109 {k: "reward.useginicoeff", v: 0, e: false}, 110 {k: "reward.useginicoeff", v: 1, e: false}, 111 {k: "reward.mintingamount", v: "9600000000000000000", e: true}, 112 {k: "reward.mintingamount", v: "0", e: true}, 113 {k: "reward.mintingamount", v: 96000, e: false}, 114 {k: "reward.mintingamount", v: "many", e: false}, 115 {k: "reward.mintingamount", v: true, e: false}, 116 {k: "reward.ratio", v: "30/40/30", e: true}, 117 {k: "reward.ratio", v: "10/10/80", e: true}, 118 {k: "reward.ratio", v: "30/70", e: false}, 119 {k: "reward.ratio", v: "30/40/31", e: false}, 120 {k: "reward.ratio", v: "30/40/29", e: false}, 121 {k: "reward.ratio", v: 30 / 40 / 30, e: false}, 122 {k: "reward.ratio", v: "0/0/100", e: true}, 123 {k: "reward.ratio", v: "0/100/0", e: true}, 124 {k: "reward.ratio", v: "100/0/0", e: true}, 125 {k: "reward.ratio", v: "0/0/0", e: false}, 126 {k: "reward.ratio", v: "30.5/40/29.5", e: false}, 127 {k: "reward.ratio", v: "30.5/40/30.5", e: false}, 128 {k: "reward.kip82ratio", v: "20/80", e: true}, 129 {k: "reward.kip82ratio", v: "10/90", e: true}, 130 {k: "reward.kip82ratio", v: "30/80", e: false}, 131 {k: "reward.kip82ratio", v: "30/30/40", e: false}, 132 {k: "reward.kip82ratio", v: "49.5/50.5", e: false}, 133 {k: "reward.kip82ratio", v: "50.5/50.5", e: false}, 134 {k: "kip71.lowerboundbasefee", v: uint64(25000000000), e: true}, 135 {k: "kip71.lowerboundbasefee", v: 25000000, e: false}, 136 {k: "kip71.lowerboundbasefee", v: "250000000", e: false}, 137 {k: "kip71.lowerboundbasefee", v: true, e: false}, 138 {k: "kip71.lowerboundbasefee", v: "test", e: false}, 139 {k: "kip71.upperboundbasefee", v: uint64(750000000000), e: true}, 140 {k: "kip71.upperboundbasefee", v: 7500000, e: false}, 141 {k: "kip71.upperboundbasefee", v: "750000", e: false}, 142 {k: "kip71.upperboundbasefee", v: true, e: false}, 143 {k: "kip71.upperboundbasefee", v: false, e: false}, 144 {k: "kip71.gastarget", v: uint64(30000000), e: true}, 145 {k: "kip71.gastarget", v: 3000, e: false}, 146 {k: "kip71.gastarget", v: "30000", e: false}, 147 {k: "kip71.gastarget", v: true, e: false}, 148 {k: "kip71.gastarget", v: false, e: false}, 149 {k: "kip71.maxblockgasusedforbasefee", v: uint64(84000000), e: true}, 150 {k: "kip71.maxblockgasusedforbasefee", v: 840000, e: false}, 151 {k: "kip71.maxblockgasusedforbasefee", v: true, e: false}, 152 {k: "kip71.maxblockgasusedforbasefee", v: "84000", e: false}, 153 {k: "kip71.maxblockgasusedforbasefee", v: 0, e: false}, 154 {k: "kip71.basefeedenominator", v: uint64(64), e: true}, 155 {k: "kip71.basefeedenominator", v: 64, e: false}, 156 {k: "kip71.basefeedenominator", v: "64", e: false}, 157 {k: "kip71.basefeedenominator", v: "sixtyfour", e: false}, 158 {k: "kip71.basefeedenominator", v: true, e: false}, 159 {k: "reward.deferredtxfee", v: true, e: true}, 160 {k: "reward.deferredtxfee", v: false, e: true}, 161 {k: "reward.deferredtxfee", v: 0, e: false}, 162 {k: "reward.deferredtxfee", v: 1, e: false}, 163 {k: "reward.deferredtxfee", v: "true", e: false}, 164 {k: "reward.minimumstake", v: "2000000000000000000000000", e: true}, 165 {k: "reward.minimumstake", v: 200000000000000, e: false}, 166 {k: "reward.minimumstake", v: "-1", e: false}, 167 {k: "reward.minimumstake", v: "0", e: true}, 168 {k: "reward.minimumstake", v: 0, e: false}, 169 {k: "reward.minimumstake", v: 1.1, e: false}, 170 {k: "reward.stakingupdateinterval", v: uint64(20), e: false}, 171 {k: "reward.stakingupdateinterval", v: float64(20.0), e: false}, 172 {k: "reward.stakingupdateinterval", v: float64(20.2), e: false}, 173 {k: "reward.stakingupdateinterval", v: "20", e: false}, 174 {k: "reward.proposerupdateinterval", v: uint64(20), e: false}, 175 {k: "reward.proposerupdateinterval", v: float64(20.0), e: false}, 176 {k: "reward.proposerupdateinterval", v: float64(20.2), e: false}, 177 {k: "reward.proposerupdateinterval", v: "20", e: false}, 178 {k: "istanbul.timeout", v: uint64(10000), e: true}, 179 {k: "istanbul.timeout", v: uint64(5000), e: true}, 180 {k: "istanbul.timeout", v: float64(-1000), e: false}, 181 {k: "istanbul.timeout", v: true, e: false}, 182 {k: "istanbul.timeout", v: "10", e: false}, 183 {k: "istanbul.timeout", v: 5.3, e: false}, 184 {k: "governance.addvalidator", v: "0x639e5ebfc483716fbac9810b230ff6ad487f366c", e: true}, 185 {k: "governance.addvalidator", v: " 0x639e5ebfc483716fbac9810b230ff6ad487f366c ", e: true}, 186 {k: "governance.addvalidator", v: "0x639e5ebfc483716fbac9810b230ff6ad487f366c,0x828880c5f09cc1cc6a58715e3fe2b4c4cf3c5869", e: true}, 187 {k: "governance.addvalidator", v: "0x639e5ebfc483716fbac9810b230ff6ad487f366c,0x828880c5f09cc1cc6a58715e3fe2b4c4cf3c58", e: false}, 188 {k: "governance.addvalidator", v: "0x639e5ebfc483716fbac9810b230ff6ad487f366c,0x639e5ebfc483716fbac9810b230ff6ad487f366c", e: false}, 189 {k: "governance.addvalidator", v: "0x639e5ebfc483716fbac9810b230ff6ad487f366c, 0x828880c5f09cc1cc6a58715e3fe2b4c4cf3c5869, ", e: false}, 190 {k: "governance.addvalidator", v: "0x639e5ebfc483716fbac9810b230ff6ad487f366c,, 0x828880c5f09cc1cc6a58715e3fe2b4c4cf3c5869, ", e: false}, 191 {k: "governance.addvalidator", v: "0x639e5ebfc483716fbac9810b230ff6ad487f366c, 0x828880c5f09cc1cc6a58715e3fe2b4c4cf3c5869 ", e: true}, 192 } 193 194 var goodVotes = []voteValue{ 195 {k: "istanbul.epoch", v: uint64(20000), e: true}, 196 {k: "istanbul.committeesize", v: uint64(7), e: true}, 197 {k: "governance.governancemode", v: "single", e: true}, 198 {k: "governance.governingnode", v: common.HexToAddress("0x0000000000000000000000000000000000000000"), e: true}, 199 {k: "governance.unitprice", v: uint64(25000000000), e: true}, 200 {k: "governance.deriveshaimpl", v: uint64(0), e: true}, 201 {k: "kip71.lowerboundbasefee", v: uint64(25000000000), e: true}, 202 {k: "kip71.upperboundbasefee", v: uint64(750000000000), e: true}, 203 {k: "kip71.gastarget", v: uint64(30000000), e: true}, 204 {k: "kip71.maxblockgasusedforbasefee", v: uint64(84000000), e: true}, 205 {k: "kip71.basefeedenominator", v: uint64(64), e: true}, 206 {k: "reward.useginicoeff", v: false, e: true}, 207 {k: "reward.mintingamount", v: "9600000000000000000", e: true}, 208 {k: "reward.ratio", v: "10/10/80", e: true}, 209 {k: "reward.kip82ratio", v: "20/80", e: true}, 210 {k: "istanbul.timeout", v: uint64(5000), e: true}, 211 {k: "governance.addvalidator", v: "0x639e5ebfc483716fbac9810b230ff6ad487f366c,0x828880c5f09cc1cc6a58715e3fe2b4c4cf3c5869", e: true}, 212 } 213 214 func getTestConfig() *params.ChainConfig { 215 config := params.TestChainConfig.Copy() 216 config.Governance = params.GetDefaultGovernanceConfig() 217 config.Istanbul = params.GetDefaultIstanbulConfig() 218 return config 219 } 220 221 func getGovernance() *Governance { 222 dbm := database.NewDBManager(&database.DBConfig{DBType: database.MemoryDB}) 223 config := getTestConfig() 224 return NewGovernanceInitialize(config, dbm) 225 } 226 227 func TestGetDefaultGovernanceConfig(t *testing.T) { 228 tstGovernance := params.GetDefaultGovernanceConfig() 229 230 want := []interface{}{ 231 params.DefaultUseGiniCoeff, 232 params.DefaultRatio, 233 common.HexToAddress(params.DefaultGoverningNode), 234 params.DefaultGovernanceMode, 235 params.DefaultDeferredTxFee, 236 } 237 238 got := []interface{}{ 239 tstGovernance.Reward.UseGiniCoeff, 240 tstGovernance.Reward.Ratio, 241 tstGovernance.GoverningNode, 242 tstGovernance.GovernanceMode, 243 tstGovernance.DeferredTxFee(), 244 } 245 246 if !reflect.DeepEqual(want, got) { 247 t.Fatalf("Want %v, got %v", want, got) 248 } 249 250 if tstGovernance.Reward.MintingAmount.Cmp(params.DefaultMintingAmount) != 0 { 251 t.Errorf("Default minting amount is not equal") 252 } 253 } 254 255 func TestGovernance_ValidateVote(t *testing.T) { 256 gov := getGovernance() 257 258 for _, val := range tstData { 259 vote := &GovernanceVote{ 260 Key: val.k, 261 Value: val.v, 262 } 263 _, ret := gov.ValidateVote(vote) 264 if ret != val.e { 265 if _, ok := GovernanceForbiddenKeyMap[val.k]; !ok && !ret { 266 t.Errorf("Want %v, got %v for %v and %v", val.e, ret, val.k, val.v) 267 } 268 } 269 } 270 } 271 272 func TestGovernance_AddVote(t *testing.T) { 273 gov := getGovernance() 274 275 for _, val := range tstData { 276 ret := gov.AddVote(val.k, val.v) 277 assert.Equal(t, val.e, ret, fmt.Sprintf("key %v, value %v", val.k, val.v)) 278 } 279 } 280 281 func TestGovernance_RemoveVote(t *testing.T) { 282 gov := getGovernance() 283 284 for _, val := range goodVotes { 285 ret := gov.AddVote(val.k, val.v) 286 if ret != val.e { 287 t.Errorf("Want %v, got %v for %v and %v", val.e, ret, val.k, val.v) 288 } 289 } 290 291 // Length check. Because []votes has all valid votes, length of voteMap and votes should be equal 292 if countUncastedVote(gov.voteMap) != len(goodVotes) { 293 t.Errorf("Length of voteMap should be %d, but %d\n", len(goodVotes), gov.voteMap.Size()) 294 } 295 296 // Remove unvoted vote. Length should still be same 297 gov.RemoveVote("istanbul.Epoch", uint64(10000), 0) 298 if countUncastedVote(gov.voteMap) != len(goodVotes) { 299 t.Errorf("Length of voteMap should be %d, but %d\n", len(goodVotes), gov.voteMap.Size()) 300 } 301 302 // Remove vote with wrong key. Length should still be same 303 gov.RemoveVote("istanbul.EpochEpoch", uint64(10000), 0) 304 if countUncastedVote(gov.voteMap) != len(goodVotes) { 305 t.Errorf("Length of voteMap should be %d, but %d\n", len(goodVotes), gov.voteMap.Size()) 306 } 307 308 // Removed a vote. Length should be len(goodVotes) -1 309 gov.RemoveVote("istanbul.epoch", uint64(20000), 0) 310 if countUncastedVote(gov.voteMap) != (len(goodVotes) - 1) { 311 t.Errorf("Length of voteMap should be %d, but %d\n", len(goodVotes)-1, gov.voteMap.Size()) 312 } 313 } 314 315 func countUncastedVote(data VoteMap) int { 316 size := 0 317 318 for _, v := range data.Copy() { 319 if v.Casted == false { 320 size++ 321 } 322 } 323 return size 324 } 325 326 func TestGovernance_ClearVotes(t *testing.T) { 327 gov := getGovernance() 328 329 for _, val := range tstData { 330 ret := gov.AddVote(val.k, val.v) 331 if ret != val.e { 332 t.Errorf("Want %v, got %v for %v and %v", val.e, ret, val.k, val.v) 333 } 334 avt := gov.adjustValueType(val.k, val.v) 335 gov.RemoveVote(val.k, avt, 0) 336 } 337 gov.ClearVotes(0) 338 if gov.voteMap.Size() != 0 { 339 t.Errorf("Want 0, got %v after clearing votes", gov.voteMap.Size()) 340 } 341 } 342 343 func TestGovernance_GetEncodedVote(t *testing.T) { 344 gov := getGovernance() 345 346 for _, val := range goodVotes { 347 _ = gov.AddVote(val.k, val.v) 348 } 349 350 l := gov.voteMap.Size() 351 for i := 0; i < l; i++ { 352 voteData := gov.GetEncodedVote(common.HexToAddress("0x1234567890123456789012345678901234567890"), 1000) 353 v := new(GovernanceVote) 354 rlp.DecodeBytes(voteData, &v) 355 356 v, err := gov.ParseVoteValue(v) 357 assert.Equal(t, nil, err) 358 gotest_assert.DeepEqual(t, gov.voteMap.GetValue(v.Key).Value, v.Value) 359 } 360 } 361 362 func TestGovernance_ParseVoteValue(t *testing.T) { 363 gov := getGovernance() 364 365 addr := common.HexToAddress("0x1234567890123456789012345678901234567890") 366 for _, val := range goodVotes { 367 v := &GovernanceVote{ 368 Key: val.k, 369 Value: gov.adjustValueType(val.k, val.v), 370 Validator: addr, 371 } 372 373 b, _ := rlp.EncodeToBytes(v) 374 375 d := new(GovernanceVote) 376 rlp.DecodeBytes(b, d) 377 378 d, err := gov.ParseVoteValue(d) 379 assert.Equal(t, nil, err) 380 gotest_assert.DeepEqual(t, v, d) 381 } 382 } 383 384 var testGovernanceMap = map[string]interface{}{ 385 "governance.governancemode": "none", 386 "governance.governingnode": common.HexToAddress("0x1234567890123456789012345678901234567890"), 387 "governance.unitprice": uint64(25000000000), 388 "reward.ratio": "30/40/30", 389 "reward.useginicoeff": true, 390 "reward.deferredtxfee": true, 391 "reward.minimumstake": 2000000, 392 } 393 394 func copyMap(src map[string]interface{}) map[string]interface{} { 395 dst := make(map[string]interface{}) 396 for k, v := range src { 397 dst[k] = v 398 } 399 return dst 400 } 401 402 func TestGovernancePersistence(t *testing.T) { 403 gov := getGovernance() 404 405 MAXITEMS := int(10) 406 407 // Write Test 408 // WriteGovernance() and WriteGovernanceIdx() 409 for i := 1; i < MAXITEMS; i++ { 410 blockNum := params.DefaultEpoch * uint64(i) 411 tstMap := copyMap(testGovernanceMap) 412 413 // Make every stored governance map has a difference 414 tstMap["governance.unitprice"] = tstMap["governance.unitprice"].(uint64) + blockNum 415 if gov.CanWriteGovernanceState(blockNum) { 416 if err := gov.db.WriteGovernance(tstMap, blockNum); err != nil { 417 t.Errorf("Write governance failed: %v", err) 418 } 419 } 420 } 421 422 // Read Test 423 // ReadRecentGovernanceIdx() ReadGovernance() 424 tstIdx, _ := gov.db.ReadRecentGovernanceIdx(MAXITEMS) 425 length := len(tstIdx) 426 for i := 1; i < length; i++ { 427 num := tstIdx[i] 428 compMap, _ := gov.db.ReadGovernance(num) 429 430 expected := testGovernanceMap["governance.unitprice"].(uint64) + uint64(i)*params.DefaultEpoch 431 if uint64(compMap["governance.unitprice"].(float64)) != expected { 432 t.Errorf("Retrieved %v, Expected %v", compMap["governance.unitprice"], expected) 433 } 434 } 435 436 tstIdx2, _ := gov.db.ReadRecentGovernanceIdx(0) 437 438 if len(tstIdx2) != MAXITEMS { 439 t.Errorf("ReadRecentGovernanceIdx with 0 failure. want %v have %v", MAXITEMS, len(tstIdx2)) 440 } 441 442 // ReadGovernanceAtNumber 443 444 for i := 0; i < MAXITEMS; i++ { 445 num := params.DefaultEpoch*uint64(i) + 123 446 idx, _, err := gov.db.ReadGovernanceAtNumber(num, params.DefaultEpoch) 447 if err != nil { 448 t.Errorf("Failed to get the governance information for block %d", num) 449 } 450 tValue := num - (num % params.DefaultEpoch) 451 if tValue >= params.DefaultEpoch { 452 tValue -= params.DefaultEpoch 453 } 454 if idx != tValue { 455 t.Errorf("Wrong block number, Want %v, have %v", tValue, idx) 456 } 457 } 458 } 459 460 type governanceData struct { 461 n uint64 462 e uint64 463 } 464 465 var tstGovernanceInfo = []governanceData{ 466 {n: 1, e: 25000000000}, 467 {n: 1209600, e: 25001209600}, 468 {n: 2419200, e: 25002419200}, 469 {n: 3628800, e: 25003628800}, 470 {n: 4838400, e: 25004838400}, 471 } 472 473 var tstGovernanceData = []governanceData{ 474 {n: 123, e: 1}, // 1 is set at params.TestChainConfig 475 {n: 604923, e: 1}, 476 {n: 1209723, e: 25000000000}, 477 {n: 1814523, e: 25001209600}, 478 {n: 2419323, e: 25001209600}, 479 {n: 3024123, e: 25002419200}, 480 {n: 3628923, e: 25002419200}, 481 {n: 4233723, e: 25003628800}, 482 {n: 4838523, e: 25003628800}, 483 {n: 5443323, e: 25004838400}, 484 } 485 486 func TestSaveGovernance(t *testing.T) { 487 gov := getGovernance() 488 489 MAXITEMS := int(10) 490 491 // Set Data 492 for i := 0; i < len(tstGovernanceInfo); i++ { 493 blockNum := tstGovernanceInfo[i].n 494 tstMap := copyMap(testGovernanceMap) 495 496 // Make every stored governance map has a difference 497 tstMap["governance.unitprice"] = tstGovernanceInfo[i].e 498 src := NewGovernanceSet() 499 delta := NewGovernanceSet() 500 src.Import(tstMap) 501 if err := gov.WriteGovernance(blockNum, src, delta); err != nil { 502 t.Errorf("Error in storing governance: %v", err) 503 } 504 } 505 506 // retrieve governance information. some will come from cache, others will be searched 507 for i := 0; i < MAXITEMS; i++ { 508 blockNum := tstGovernanceData[i].n 509 _, data, err := gov.ReadGovernance(blockNum) 510 if err == nil { 511 if data["governance.unitprice"] != tstGovernanceData[i].e { 512 t.Errorf("Data mismatch want %v, have %v for block %d", tstGovernanceData[i].e, data["governance.unitprice"], tstGovernanceData[i].n) 513 } 514 } 515 } 516 } 517 518 type epochTest struct { 519 v uint64 520 e uint64 521 } 522 523 // Assume epoch is 30 524 var epochTestData = []epochTest{ 525 {0, 0}, 526 {30, 0}, 527 {60, 30}, 528 {90, 60}, 529 {120, 90}, 530 {150, 120}, 531 {180, 150}, 532 {210, 180}, 533 {240, 210}, 534 {270, 240}, 535 {300, 270}, 536 {330, 300}, 537 {360, 330}, 538 } 539 540 func TestCalcGovernanceInfoBlock(t *testing.T) { 541 for _, v := range epochTestData { 542 res := CalcGovernanceInfoBlock(v.v, 30) 543 if res != v.e { 544 t.Errorf("Governance Block Number Mismatch: want %v, have %v", v.e, res) 545 } 546 } 547 } 548 549 func TestVoteValueNilInterface(t *testing.T) { 550 gov := getGovernance() 551 gVote := new(GovernanceVote) 552 var test []byte 553 554 gVote.Key = "istanbul.policy" 555 // gVote.Value is an interface list 556 { 557 gVote.Value = []interface{}{[]byte{1, 2}} 558 test, _ = rlp.EncodeToBytes(gVote) 559 if err := rlp.DecodeBytes(test, gVote); err != nil { 560 t.Fatal("RLP decode error") 561 } 562 563 // Parse vote.Value and make it has appropriate type 564 _, err := gov.ParseVoteValue(gVote) 565 assert.Equal(t, ErrValueTypeMismatch, err) 566 } 567 568 // gVote.Value is an empty interface list 569 { 570 gVote.Value = []interface{}{[]byte{}} 571 test, _ = rlp.EncodeToBytes(gVote) 572 if err := rlp.DecodeBytes(test, gVote); err != nil { 573 t.Fatal("RLP decode error") 574 } 575 576 // Parse vote.Value and make it has appropriate type 577 _, err := gov.ParseVoteValue(gVote) 578 assert.Equal(t, ErrValueTypeMismatch, err) 579 } 580 581 // gVote.Value is nil 582 { 583 gVote.Value = nil 584 test, _ = rlp.EncodeToBytes(gVote) 585 if err := rlp.DecodeBytes(test, gVote); err != nil { 586 t.Fatal("RLP decode error") 587 } 588 589 // Parse vote.Value and make it has appropriate type 590 _, err := gov.ParseVoteValue(gVote) 591 assert.Equal(t, ErrValueTypeMismatch, err) 592 } 593 594 // gVote.Value is uint8 list 595 { 596 gVote.Value = []uint8{0x11} 597 test, _ = rlp.EncodeToBytes(gVote) 598 if err := rlp.DecodeBytes(test, gVote); err != nil { 599 t.Fatal("RLP decode error") 600 } 601 602 // Parse vote.Value and make it has appropriate type 603 _, err := gov.ParseVoteValue(gVote) 604 assert.NoError(t, err) 605 } 606 607 gVote.Key = "governance.addvalidator" 608 { 609 gVote.Value = [][]uint8{{0x3, 0x4}, {0x5, 0x6}} 610 test, _ = rlp.EncodeToBytes(gVote) 611 if err := rlp.DecodeBytes(test, gVote); err != nil { 612 t.Fatal("RLP decode error") 613 } 614 // Parse vote.Value and make it has appropriate type 615 _, err := gov.ParseVoteValue(gVote) 616 assert.Equal(t, ErrValueTypeMismatch, err) 617 } 618 619 { 620 gVote.Value = []uint8{0x1, 0x2, 0x3} 621 test, _ = rlp.EncodeToBytes(gVote) 622 if err := rlp.DecodeBytes(test, gVote); err != nil { 623 t.Fatal("RLP decode error") 624 } 625 626 // Parse vote.Value and make it has appropriate type 627 _, err := gov.ParseVoteValue(gVote) 628 assert.NoError(t, err) 629 } 630 } 631 632 func TestBaoBabGenesisHash(t *testing.T) { 633 baobabHash := params.BaobabGenesisHash 634 genesis := blockchain.DefaultBaobabGenesisBlock() 635 genesis.Governance = blockchain.SetGenesisGovernance(genesis) 636 blockchain.InitDeriveSha(genesis.Config) 637 638 db := database.NewMemoryDBManager() 639 block, _ := genesis.Commit(common.Hash{}, db) 640 if block.Hash() != baobabHash { 641 t.Errorf("Generated hash is not equal to Baobab's hash. Want %v, Have %v", baobabHash.String(), block.Hash().String()) 642 } 643 } 644 645 func TestCypressGenesisHash(t *testing.T) { 646 cypressHash := params.CypressGenesisHash 647 genesis := blockchain.DefaultGenesisBlock() 648 genesis.Governance = blockchain.SetGenesisGovernance(genesis) 649 blockchain.InitDeriveSha(genesis.Config) 650 651 db := database.NewMemoryDBManager() 652 block, _ := genesis.Commit(common.Hash{}, db) 653 if block.Hash() != cypressHash { 654 t.Errorf("Generated hash is not equal to Cypress's hash. Want %v, Have %v", cypressHash.String(), block.Hash().String()) 655 } 656 } 657 658 func TestGovernance_initializeCache(t *testing.T) { 659 dbm := database.NewDBManager(&database.DBConfig{DBType: database.MemoryDB}) 660 config := getTestConfig() 661 config.Istanbul.Epoch = 30 662 663 gov := NewGovernanceInitialize(config, dbm) 664 665 testData := []struct { 666 // test input 667 governanceUpdateNum int 668 blockNums []uint64 669 unitPrices []uint64 670 currentBlockNum int64 671 // expected result 672 unitPriceInCurrentSet uint64 673 actualGovernanceBlock uint64 674 }{ 675 {0, []uint64{0}, []uint64{1}, 20, 1, 0}, 676 {0, []uint64{0}, []uint64{1}, 50, 1, 0}, 677 {0, []uint64{0}, []uint64{1}, 80, 1, 0}, 678 {3, []uint64{0, 30, 60, 90}, []uint64{1, 2, 3, 4}, 90, 3, 60}, 679 {3, []uint64{0, 30, 60, 90}, []uint64{1, 2, 3, 4}, 110, 3, 60}, 680 {3, []uint64{0, 30, 60, 90}, []uint64{1, 2, 3, 4}, 130, 4, 90}, 681 } 682 683 for _, tc := range testData { 684 // 1. initializing 685 686 // store governance items to the governance db for 'tc.governanceUpdateNum' times 687 for idx := 1; idx <= tc.governanceUpdateNum; idx++ { 688 config.UnitPrice = tc.unitPrices[idx] 689 690 src := GetGovernanceItemsFromChainConfig(config) 691 delta := NewGovernanceSet() 692 693 if ret := gov.WriteGovernance(tc.blockNums[idx], src, delta); ret != nil { 694 t.Errorf("Error in testing WriteGovernance, %v", ret) 695 } 696 } 697 // store head block (fake block, it only contains block number) to the headerDB 698 header := &types.Header{Number: big.NewInt(tc.currentBlockNum)} 699 gov.db.WriteHeadBlockHash(header.Hash()) 700 gov.db.WriteHeader(header) 701 702 // reset idxCache and itemCache. purpose - reproduce the environment of the restarted node 703 gov.idxCache = nil 704 gov.itemCache.Purge() 705 706 // 2. call initializeCache 707 err := gov.initializeCache(config) 708 709 // 3. check the affected values with expected results 710 assert.NoError(t, err) 711 712 v, ok := gov.currentSet.GetValue(GovernanceKeyMap["governance.unitprice"]) 713 assert.True(t, ok) 714 assert.Equal(t, tc.unitPriceInCurrentSet, v) 715 716 assert.Equal(t, tc.blockNums, gov.idxCache) // the order should be same 717 assert.True(t, gov.itemCache.Contains(getGovernanceCacheKey(tc.blockNums[tc.governanceUpdateNum]))) 718 assert.Equal(t, tc.actualGovernanceBlock, gov.actualGovernanceBlock.Load().(uint64)) 719 } 720 } 721 722 func TestGovernance_ReadGovernanceState(t *testing.T) { 723 dbm := database.NewDBManager(&database.DBConfig{DBType: database.MemoryDB}) 724 config := getTestConfig() 725 bn := uint64(1024) 726 727 gjson := &governanceJSON{ 728 BlockNumber: bn, 729 ChainConfig: config, 730 VoteMap: map[string]VoteStatus{ 731 "governance.unitprice": { 732 Value: float64(0), 733 Casted: true, 734 Num: 304, 735 }, 736 }, 737 NodeAddress: common.StringToAddress("0x0000000000000000000000000000000000000000"), 738 GovernanceVotes: []GovernanceVote{ 739 { 740 Validator: common.StringToAddress("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 741 Key: "governance.unitprice", 742 Value: float64(50000000000), 743 }, 744 }, 745 GovernanceTally: []GovernanceTallyItem{ 746 { 747 Key: "governance.unitprice", 748 Value: float64(50000000000), 749 Votes: 3, 750 }, 751 }, 752 CurrentSet: map[string]interface{}{ 753 "reward.stakingupdateinterval": config.Governance.Reward.StakingUpdateInterval, 754 "reward.proposerupdateinterval": config.Governance.Reward.ProposerUpdateInterval, 755 }, 756 ChangeSet: map[string]interface{}{ 757 "governance.unitprice": uint64(50000000000), 758 }, 759 } 760 761 b, err := json.Marshal(gjson) 762 assert.Nil(t, err) 763 764 dbm.WriteGovernanceState(b) 765 gov := NewGovernanceInitialize(config, dbm) 766 gov.ReadGovernanceState() 767 768 assert.Equal(t, bn, gov.lastGovernanceStateBlock) 769 assert.Equal(t, gjson.VoteMap, gov.voteMap.items) 770 assert.Equal(t, gjson.NodeAddress, gov.nodeAddress.Load()) 771 assert.Equal(t, gjson.GovernanceVotes, gov.GovernanceVotes.items) 772 assert.Equal(t, gjson.GovernanceTally, gov.GovernanceTallies.items) 773 assert.Equal(t, gjson.CurrentSet, gov.currentSet.items) 774 assert.Equal(t, gjson.ChangeSet, gov.changeSet.items) 775 776 assert.Equal(t, config.Governance.Reward.StakingUpdateInterval, gov.stakingUpdateInterval()) 777 assert.Equal(t, config.Governance.Reward.ProposerUpdateInterval, gov.proposerUpdateInterval()) 778 } 779 780 func TestWriteGovernance_idxCache(t *testing.T) { 781 gov := getGovernance() 782 783 tstMap := copyMap(testGovernanceMap) 784 785 src := NewGovernanceSet() 786 delta := NewGovernanceSet() 787 src.Import(tstMap) 788 789 blockNum := []uint64{30, 30, 60, 60, 50} 790 791 for _, num := range blockNum { 792 if ret := gov.WriteGovernance(num, src, delta); ret != nil { 793 t.Errorf("Error in testing WriteGovernance, %v", ret) 794 } 795 } 796 797 // idxCache should have 0, 30 and 60 798 if len(gov.idxCache) != 3 || gov.idxCache[len(gov.idxCache)-1] != 60 { 799 t.Errorf("idxCache has wrong value") 800 } 801 } 802 803 func getTestValidators() []common.Address { 804 return []common.Address{ 805 common.HexToAddress("0x414790CA82C14A8B975cEBd66098c3dA590bf969"), // Node Address for test 806 common.HexToAddress("0x604973C51f6389dF2782E018000c3AC1257dee90"), 807 common.HexToAddress("0x5Ac1689ae5F521B05145C5Cd15a3E8F6ab39Af19"), 808 common.HexToAddress("0x0688CaC68bbF7c1a0faedA109c668a868BEd855E"), 809 } 810 } 811 812 func getTestDemotedValidators() []common.Address { 813 return []common.Address{ 814 common.HexToAddress("0x3BB17a8A4f915cC9A8CAAcdC062Ef9b903511Ffa"), 815 common.HexToAddress("0x82588D33A48e6Bda012714f1C680d254ff607472"), 816 common.HexToAddress("0xceB7ADDFBa9665d8767173D47dE4453D7b7B900D"), 817 common.HexToAddress("0x38Ea854792EB956620E53090E8bc4e5C5C917123"), 818 } 819 } 820 821 func getTestRewards() []common.Address { 822 return []common.Address{ 823 common.HexToAddress("0x2A35FE72F847aa0B509e4055883aE90c87558AaD"), 824 common.HexToAddress("0xF91B8EBa583C7fa603B400BE17fBaB7629568A4a"), 825 common.HexToAddress("0x240ed27c8bDc9Bb6cA08fa3D239699Fba525d05a"), 826 common.HexToAddress("0x3B980293396Fb0e827929D573e3e42d2EA902502"), 827 } 828 } 829 830 func getTestVotingPowers(num int) []uint64 { 831 vps := make([]uint64, 0, num) 832 for i := 0; i < num; i++ { 833 vps = append(vps, 1000) 834 } 835 return vps 836 } 837 838 const ( 839 GovernanceModeBallot = "ballot" 840 ) 841 842 func TestGovernance_HandleGovernanceVote_None_mode(t *testing.T) { 843 // Create ValidatorSet 844 validators := getTestValidators() 845 demotedValidators := getTestDemotedValidators() 846 rewards := getTestRewards() 847 848 blockCounter := big.NewInt(0) 849 valSet := validator.NewWeightedCouncil(validators, demotedValidators, rewards, getTestVotingPowers(len(validators)), nil, istanbul.WeightedRandom, 21, 0, 0, nil) 850 gov := getGovernance() 851 gov.nodeAddress.Store(validators[len(validators)-1]) 852 853 votes := make([]GovernanceVote, 0) 854 tally := make([]GovernanceTallyItem, 0) 855 856 proposer := validators[0] 857 self := validators[len(validators)-1] 858 header := &types.Header{} 859 860 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 861 // Test for "none" mode 862 header.Number = blockCounter.Add(blockCounter, common.Big1) 863 header.BlockScore = common.Big1 864 gov.AddVote("governance.unitprice", uint64(22000)) 865 header.Vote = gov.GetEncodedVote(proposer, blockCounter.Uint64()) 866 867 gov.HandleGovernanceVote(valSet, votes, tally, header, proposer, self, true) 868 gov.RemoveVote("governance.unitprice", uint64(22000), 0) 869 870 if _, ok := gov.changeSet.items["governance.unitprice"]; !ok { 871 t.Errorf("Vote had to be applied but it wasn't") 872 } 873 gov.voteMap.Clear() 874 875 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 876 // Test for "istanbul.timeout" in "none" mode 877 header.Number = blockCounter.Add(blockCounter, common.Big1) 878 header.BlockScore = common.Big1 879 880 newValue := istanbul.DefaultConfig.Timeout + uint64(10000) 881 gov.AddVote("istanbul.timeout", newValue) 882 header.Vote = gov.GetEncodedVote(proposer, blockCounter.Uint64()) 883 884 gov.HandleGovernanceVote(valSet, votes, tally, header, proposer, self, true) 885 gov.RemoveVote("istanbul.timeout", newValue, 0) 886 assert.Equal(t, istanbul.DefaultConfig.Timeout, newValue, "Vote had to be applied but it wasn't") 887 888 gov.voteMap.Clear() 889 890 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 891 // Test removing a validator 892 header.Number = blockCounter.Add(blockCounter, common.Big1) 893 gov.AddVote("governance.removevalidator", validators[1].String()) 894 header.Vote = gov.GetEncodedVote(proposer, blockCounter.Uint64()) 895 896 gov.HandleGovernanceVote(valSet, votes, tally, header, proposer, self, true) 897 gov.RemoveVote("governance.removevalidator", validators[1], 0) 898 if i, _ := valSet.GetByAddress(validators[1]); i != -1 { 899 t.Errorf("Validator removal failed, %d validators remains", valSet.Size()) 900 } 901 gov.voteMap.Clear() 902 903 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 904 // Test removing a non-existing validator 905 header.Number = blockCounter.Add(blockCounter, common.Big1) 906 gov.AddVote("governance.removevalidator", validators[1].String()) 907 header.Vote = gov.GetEncodedVote(proposer, blockCounter.Uint64()) 908 909 gov.HandleGovernanceVote(valSet, votes, tally, header, proposer, proposer, true) // self = proposer 910 // check if casted 911 if !gov.voteMap.items["governance.removevalidator"].Casted { 912 t.Errorf("Removing a non-existing validator failed") 913 } 914 gov.RemoveVote("governance.removevalidator", validators[1], 0) 915 if i, _ := valSet.GetByAddress(validators[1]); i != -1 { 916 t.Errorf("Removing a non-existing validator failed, %d validators remains", valSet.Size()) 917 } 918 gov.voteMap.Clear() 919 920 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 921 // Test adding a validator 922 header.Number = blockCounter.Add(blockCounter, common.Big1) 923 gov.AddVote("governance.addvalidator", validators[1].String()) 924 header.Vote = gov.GetEncodedVote(proposer, blockCounter.Uint64()) 925 926 gov.HandleGovernanceVote(valSet, votes, tally, header, proposer, self, true) 927 gov.RemoveVote("governance.addvalidator", validators[1], 0) 928 if i, _ := valSet.GetByAddress(validators[1]); i == -1 { 929 t.Errorf("Validator addition failed, %d validators remains", valSet.Size()) 930 } 931 gov.voteMap.Clear() 932 933 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 934 // Test adding an existing validator 935 header.Number = blockCounter.Add(blockCounter, common.Big1) 936 gov.AddVote("governance.addvalidator", validators[1].String()) 937 header.Vote = gov.GetEncodedVote(proposer, blockCounter.Uint64()) 938 939 gov.HandleGovernanceVote(valSet, votes, tally, header, proposer, proposer, true) // self = proposer 940 // check if casted 941 if !gov.voteMap.items["governance.addvalidator"].Casted { 942 t.Errorf("Adding an existing validator failed") 943 } 944 gov.RemoveVote("governance.addvalidator", validators[1], 0) 945 if i, _ := valSet.GetByAddress(validators[1]); i == -1 { 946 t.Errorf("Validator addition failed, %d validators remains", valSet.Size()) 947 } 948 gov.voteMap.Clear() 949 950 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 951 // Test removing a demoted validator 952 header.Number = blockCounter.Add(blockCounter, common.Big1) 953 gov.AddVote("governance.removevalidator", demotedValidators[1].String()) 954 header.Vote = gov.GetEncodedVote(proposer, blockCounter.Uint64()) 955 956 gov.HandleGovernanceVote(valSet, votes, tally, header, proposer, self, true) 957 gov.RemoveVote("governance.removevalidator", demotedValidators[1], 0) 958 if i, _ := valSet.GetDemotedByAddress(demotedValidators[1]); i != -1 { 959 t.Errorf("Demoted validator removal failed, %d demoted validators remains", len(valSet.DemotedList())) 960 } 961 gov.voteMap.Clear() 962 963 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 964 // Test adding a demoted validator 965 header.Number = blockCounter.Add(blockCounter, common.Big1) 966 gov.AddVote("governance.addvalidator", demotedValidators[1].String()) 967 header.Vote = gov.GetEncodedVote(proposer, blockCounter.Uint64()) 968 969 gov.HandleGovernanceVote(valSet, votes, tally, header, proposer, self, true) 970 gov.RemoveVote("governance.addvalidator", demotedValidators[1], 0) 971 // At first, demoted validator is added to the validators, but it will be refreshed right after 972 // So, we here check only if the adding demoted validator to validators 973 if i, _ := valSet.GetByAddress(demotedValidators[1]); i == -1 { 974 t.Errorf("Demoted validator addition failed, %d demoted validators remains", len(valSet.DemotedList())) 975 } 976 gov.voteMap.Clear() 977 } 978 979 func TestGovernance_HandleGovernanceVote_Ballot_mode(t *testing.T) { 980 // Create ValidatorSet 981 validators := getTestValidators() 982 demotedValidators := getTestDemotedValidators() 983 rewards := getTestRewards() 984 985 blockCounter := big.NewInt(0) 986 var valSet istanbul.ValidatorSet 987 valSet = validator.NewWeightedCouncil(validators, demotedValidators, rewards, getTestVotingPowers(len(validators)), nil, istanbul.WeightedRandom, 21, 0, 0, nil) 988 989 config := getTestConfig() 990 config.Governance.GovernanceMode = GovernanceModeBallot 991 dbm := database.NewDBManager(&database.DBConfig{DBType: database.MemoryDB}) 992 gov := NewGovernanceInitialize(config, dbm) 993 gov.nodeAddress.Store(validators[len(validators)-1]) 994 995 votes := make([]GovernanceVote, 0) 996 tally := make([]GovernanceTallyItem, 0) 997 998 self := validators[len(validators)-1] 999 header := &types.Header{} 1000 1001 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 1002 // Test for "ballot" mode 1003 header.Number = blockCounter.Add(blockCounter, common.Big1) 1004 header.BlockScore = common.Big1 1005 gov.AddVote("governance.unitprice", uint64(22000)) 1006 1007 header.Vote = gov.GetEncodedVote(validators[0], blockCounter.Uint64()) 1008 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[0], self, true) 1009 1010 header.Vote = gov.GetEncodedVote(validators[1], blockCounter.Uint64()) 1011 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[1], self, true) 1012 1013 if _, ok := gov.changeSet.items["governance.unitprice"]; ok { 1014 t.Errorf("Vote shouldn't be applied yet but it was applied") 1015 } 1016 1017 header.Vote = gov.GetEncodedVote(validators[2], blockCounter.Uint64()) 1018 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[2], self, true) 1019 if _, ok := gov.changeSet.items["governance.unitprice"]; !ok { 1020 t.Errorf("Vote should be applied but it was not") 1021 } 1022 1023 gov.RemoveVote("governance.unitprice", uint64(22000), blockCounter.Uint64()) 1024 gov.voteMap.Clear() 1025 1026 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 1027 // Test for "istanbul.timeout" in "ballot" mode 1028 header.Number = blockCounter.Add(blockCounter, common.Big1) 1029 header.BlockScore = common.Big1 1030 newValue := istanbul.DefaultConfig.Timeout + uint64(10000) 1031 gov.AddVote("istanbul.timeout", newValue) 1032 1033 header.Vote = gov.GetEncodedVote(validators[0], blockCounter.Uint64()) 1034 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[0], self, true) 1035 1036 header.Vote = gov.GetEncodedVote(validators[1], blockCounter.Uint64()) 1037 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[1], self, true) 1038 1039 assert.NotEqual(t, istanbul.DefaultConfig.Timeout, newValue, "Vote shouldn't be applied yet but it was applied") 1040 1041 header.Vote = gov.GetEncodedVote(validators[2], blockCounter.Uint64()) 1042 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[2], self, true) 1043 1044 assert.Equal(t, istanbul.DefaultConfig.Timeout, newValue, "Vote should be applied but it was not") 1045 gov.RemoveVote("istanbul.timeout", newValue, blockCounter.Uint64()) 1046 gov.voteMap.Clear() 1047 1048 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 1049 // Test removing a validator, because there are 4 nodes 3 votes are required to remove a validator 1050 gov.AddVote("governance.removevalidator", validators[1].String()) 1051 1052 header.Number = blockCounter.Add(blockCounter, common.Big1) 1053 header.Vote = gov.GetEncodedVote(validators[0], blockCounter.Uint64()) 1054 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[0], self, true) 1055 1056 header.Number = blockCounter.Add(blockCounter, common.Big1) 1057 header.Vote = gov.GetEncodedVote(validators[2], blockCounter.Uint64()) 1058 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[2], self, true) 1059 if i, _ := valSet.GetByAddress(validators[1]); i == -1 { 1060 t.Errorf("Validator removal shouldn't be done yet, %d validators remains", valSet.Size()) 1061 } 1062 1063 header.Number = blockCounter.Add(blockCounter, common.Big1) 1064 header.Vote = gov.GetEncodedVote(validators[3], blockCounter.Uint64()) 1065 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[3], self, true) 1066 1067 if i, _ := valSet.GetByAddress(validators[1]); i != -1 { 1068 t.Errorf("Validator removal failed, %d validators remains", valSet.Size()) 1069 } 1070 gov.RemoveVote("governance.removevalidator", validators[1], blockCounter.Uint64()) 1071 gov.voteMap.Clear() 1072 1073 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 1074 // Test removing a non-existing validator. Because there are 3 nodes, 2 votes are required to remove a validator 1075 gov.AddVote("governance.removevalidator", validators[1].String()) 1076 1077 header.Number = blockCounter.Add(blockCounter, common.Big1) 1078 header.Vote = gov.GetEncodedVote(validators[0], blockCounter.Uint64()) 1079 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[0], validators[0], true) 1080 // check if casted 1081 if !gov.voteMap.items["governance.removevalidator"].Casted { 1082 t.Errorf("Removing a non-existing validator failed") 1083 } 1084 1085 header.Number = blockCounter.Add(blockCounter, common.Big1) 1086 header.Vote = gov.GetEncodedVote(validators[2], blockCounter.Uint64()) 1087 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[2], validators[2], true) 1088 // check if casted 1089 if !gov.voteMap.items["governance.removevalidator"].Casted { 1090 t.Errorf("Removing a non-existing validator failed") 1091 } 1092 1093 gov.RemoveVote("governance.removevalidator", validators[1], blockCounter.Uint64()) 1094 gov.voteMap.Clear() 1095 1096 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 1097 // Test adding a validator, because there are 3 nodes 2 plus votes are required to add a new validator 1098 gov.AddVote("governance.addvalidator", validators[1].String()) 1099 1100 header.Number = blockCounter.Add(blockCounter, common.Big1) 1101 header.Vote = gov.GetEncodedVote(validators[0], blockCounter.Uint64()) 1102 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[0], self, true) 1103 if i, _ := valSet.GetByAddress(validators[1]); i != -1 { 1104 t.Errorf("Validator addition shouldn't be done yet, %d validators remains", valSet.Size()) 1105 } 1106 1107 header.Number = blockCounter.Add(blockCounter, common.Big1) 1108 header.Vote = gov.GetEncodedVote(validators[2], blockCounter.Uint64()) 1109 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[2], self, true) 1110 1111 if i, _ := valSet.GetByAddress(validators[1]); i == -1 { 1112 t.Errorf("Validator addition failed, %d validators remains", valSet.Size()) 1113 } 1114 gov.RemoveVote("governance.addvalidator", validators[1], blockCounter.Uint64()) 1115 gov.voteMap.Clear() 1116 1117 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 1118 // Test adding an existing validator, because there are 3 nodes 2 plus votes are required to add a new validator 1119 gov.AddVote("governance.addvalidator", validators[1].String()) 1120 1121 header.Number = blockCounter.Add(blockCounter, common.Big1) 1122 header.Vote = gov.GetEncodedVote(validators[0], blockCounter.Uint64()) 1123 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[0], validators[0], true) 1124 // check if casted 1125 if !gov.voteMap.items["governance.addvalidator"].Casted { 1126 t.Errorf("Adding an existing validator failed") 1127 } 1128 1129 header.Number = blockCounter.Add(blockCounter, common.Big1) 1130 header.Vote = gov.GetEncodedVote(validators[2], blockCounter.Uint64()) 1131 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[2], validators[2], true) 1132 // check if casted 1133 if !gov.voteMap.items["governance.addvalidator"].Casted { 1134 t.Errorf("Adding an existing validator failed") 1135 } 1136 1137 gov.RemoveVote("governance.addvalidator", validators[1], blockCounter.Uint64()) 1138 gov.voteMap.Clear() 1139 1140 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 1141 // Test removing a demoted validator, because there are 4 nodes 3 votes are required to remove a demoted validator 1142 gov.AddVote("governance.removevalidator", demotedValidators[1].String()) 1143 1144 header.Number = blockCounter.Add(blockCounter, common.Big1) 1145 header.Vote = gov.GetEncodedVote(validators[0], blockCounter.Uint64()) 1146 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[0], self, true) 1147 1148 header.Number = blockCounter.Add(blockCounter, common.Big1) 1149 header.Vote = gov.GetEncodedVote(validators[2], blockCounter.Uint64()) 1150 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[2], self, true) 1151 if i, _ := valSet.GetDemotedByAddress(demotedValidators[1]); i == -1 { 1152 t.Errorf("Demoted validator removal shouldn't be done yet, %d validators remains", len(valSet.DemotedList())) 1153 } 1154 1155 header.Number = blockCounter.Add(blockCounter, common.Big1) 1156 header.Vote = gov.GetEncodedVote(validators[3], blockCounter.Uint64()) 1157 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[3], self, true) 1158 1159 if i, _ := valSet.GetDemotedByAddress(demotedValidators[1]); i != -1 { 1160 t.Errorf("Demoted validator removal failed, %d validators remains", len(valSet.DemotedList())) 1161 } 1162 gov.voteMap.Clear() 1163 1164 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 1165 // Test adding a demoted validator, because there are 4 nodes 3 votes are required to add a demoted validator 1166 gov.AddVote("governance.addvalidator", demotedValidators[1].String()) 1167 1168 header.Number = blockCounter.Add(blockCounter, common.Big1) 1169 header.Vote = gov.GetEncodedVote(validators[0], blockCounter.Uint64()) 1170 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[0], self, true) 1171 if i, _ := valSet.GetByAddress(demotedValidators[1]); i != -1 { 1172 t.Errorf("Validator addition shouldn't be done yet, %d validators remains", len(valSet.DemotedList())) 1173 } 1174 1175 header.Number = blockCounter.Add(blockCounter, common.Big1) 1176 header.Vote = gov.GetEncodedVote(validators[2], blockCounter.Uint64()) 1177 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[2], self, true) 1178 1179 header.Number = blockCounter.Add(blockCounter, common.Big1) 1180 header.Vote = gov.GetEncodedVote(validators[3], blockCounter.Uint64()) 1181 valSet, votes, tally = gov.HandleGovernanceVote(valSet, votes, tally, header, validators[3], self, true) 1182 1183 // At first, demoted validator is added to the validators, but it will be refreshed right after 1184 // So, we here check only if the adding demoted validator to validators 1185 if i, _ := valSet.GetByAddress(demotedValidators[1]); i == -1 { 1186 t.Errorf("Demoted validator addition failed, %d validators remains", len(valSet.DemotedList())) 1187 } 1188 gov.voteMap.Clear() 1189 } 1190 1191 func TestGovernance_checkVote(t *testing.T) { 1192 // Create ValidatorSet 1193 council := getTestValidators() 1194 validators := []common.Address{council[0], council[1]} 1195 demotedValidators := []common.Address{council[2], council[3]} 1196 1197 valSet := validator.NewWeightedCouncil(validators, demotedValidators, nil, getTestVotingPowers(len(validators)), nil, istanbul.WeightedRandom, 21, 0, 0, nil) 1198 1199 config := getTestConfig() 1200 dbm := database.NewDBManager(&database.DBConfig{DBType: database.MemoryDB}) 1201 gov := NewGovernanceInitialize(config, dbm) 1202 1203 unknown := common.HexToAddress("0xa") 1204 1205 // for adding validator 1206 assert.True(t, gov.checkVote(unknown, true, valSet)) 1207 assert.True(t, gov.checkVote(validators[0], false, valSet)) 1208 assert.True(t, gov.checkVote(demotedValidators[0], false, valSet)) 1209 1210 // for removing validator 1211 assert.False(t, gov.checkVote(unknown, false, valSet)) 1212 assert.False(t, gov.checkVote(validators[1], true, valSet)) 1213 assert.False(t, gov.checkVote(demotedValidators[1], true, valSet)) 1214 } 1215 1216 func TestGovernance_VerifyGovernance(t *testing.T) { 1217 gov := getGovernance() 1218 vote := GovernanceVote{ 1219 Key: "governance.governingnode", 1220 Value: common.HexToAddress("000000000000000000000000000abcd000000000"), 1221 } 1222 gov.updateChangeSet(vote) 1223 1224 // consensus/istanbul/backend/engine.go:Prepare() 1225 // Correct case 1226 g := gov.GetGovernanceChange() 1227 j, err := json.Marshal(g) 1228 assert.Nil(t, err) 1229 r, err := rlp.EncodeToBytes(j) 1230 assert.Nil(t, err) 1231 err = gov.VerifyGovernance(r) 1232 assert.Nil(t, err) 1233 1234 // Value mismatch 1235 g = gov.GetGovernanceChange() 1236 g["governance.governingnode"] = "000000000000000000000000000abcd000001111" 1237 j, err = json.Marshal(g) 1238 assert.Nil(t, err) 1239 r, err = rlp.EncodeToBytes(j) 1240 assert.Nil(t, err) 1241 err = gov.VerifyGovernance(r) 1242 assert.Equal(t, ErrVoteValueMismatch, err) 1243 1244 // Type mismatch 1245 g = gov.GetGovernanceChange() 1246 g["governance.governingnode"] = 123 1247 j, err = json.Marshal(g) 1248 assert.Nil(t, err) 1249 r, err = rlp.EncodeToBytes(j) 1250 assert.Nil(t, err) 1251 err = gov.VerifyGovernance(r) 1252 assert.Equal(t, ErrVoteValueMismatch, err) 1253 1254 // Length mismatch 1255 g = gov.GetGovernanceChange() 1256 g["governance.governingnode"] = 123 1257 g["istanbul.epoch"] = uint64(10000) 1258 j, err = json.Marshal(g) 1259 assert.Nil(t, err) 1260 r, err = rlp.EncodeToBytes(j) 1261 assert.Nil(t, err) 1262 err = gov.VerifyGovernance(r) 1263 assert.Equal(t, ErrVoteValueMismatch, err) 1264 } 1265 1266 func TestGovernance_ParamsAt(t *testing.T) { 1267 valueA := uint64(0x11) 1268 valueB := uint64(0x22) 1269 valueC := uint64(0x33) 1270 koreBlock := uint64(100) 1271 1272 dbm := database.NewDBManager(&database.DBConfig{DBType: database.MemoryDB}) 1273 config := getTestConfig() 1274 config.Istanbul.Epoch = 30 1275 config.Istanbul.SubGroupSize = valueA 1276 config.KoreCompatibleBlock = new(big.Int).SetUint64(koreBlock) 1277 gov := NewGovernanceInitialize(config, dbm) 1278 1279 // Write to database. Note that we must use gov.WriteGovernance(), not db.WriteGovernance() 1280 // The reason is that gov.ReadGovernance() depends on the caches, and that 1281 // gov.WriteGovernance() sets idxCache accordingly, whereas db.WriteGovernance don't 1282 items := gov.CurrentParams().StrMap() 1283 gset := NewGovernanceSet() 1284 1285 items["istanbul.committeesize"] = valueB 1286 gset.Import(items) 1287 gov.WriteGovernance(30, NewGovernanceSet(), gset) 1288 1289 items["istanbul.committeesize"] = valueC 1290 gset.Import(items) 1291 gov.WriteGovernance(120, NewGovernanceSet(), gset) 1292 1293 testcases := []struct { 1294 num uint64 1295 value uint64 1296 }{ 1297 {59, valueA}, 1298 {60, valueA}, 1299 {61, valueB}, 1300 {149, valueB}, 1301 {150, valueC}, 1302 {151, valueC}, 1303 } 1304 for _, tc := range testcases { 1305 // Check that e.EffectiveParams() == tc 1306 pset, err := gov.EffectiveParams(tc.num) 1307 assert.Nil(t, err) 1308 assert.Equal(t, tc.value, pset.CommitteeSize(), "Wrong at %d", tc.num) 1309 } 1310 }