github.com/klaytn/klaytn@v1.12.1/consensus/istanbul/backend/engine_test.go (about) 1 // Modifications Copyright 2020 The klaytn Authors 2 // Copyright 2017 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from quorum/consensus/istanbul/backend/engine_test.go (2020/04/16). 19 // Modified and improved for the klaytn development. 20 21 package backend 22 23 import ( 24 "bytes" 25 "crypto/ecdsa" 26 "math/big" 27 "reflect" 28 "sort" 29 "strings" 30 "testing" 31 "time" 32 33 "github.com/klaytn/klaytn/blockchain" 34 "github.com/klaytn/klaytn/blockchain/types" 35 "github.com/klaytn/klaytn/blockchain/vm" 36 "github.com/klaytn/klaytn/common" 37 "github.com/klaytn/klaytn/common/hexutil" 38 "github.com/klaytn/klaytn/consensus" 39 "github.com/klaytn/klaytn/consensus/istanbul" 40 "github.com/klaytn/klaytn/consensus/istanbul/core" 41 "github.com/klaytn/klaytn/crypto" 42 "github.com/klaytn/klaytn/params" 43 "github.com/klaytn/klaytn/reward" 44 "github.com/klaytn/klaytn/rlp" 45 "github.com/stretchr/testify/assert" 46 ) 47 48 // These variables are the global variables of the test blockchain. 49 var ( 50 nodeKeys []*ecdsa.PrivateKey 51 addrs []common.Address 52 ) 53 54 // These are the types in order to add a custom configuration of the test chain. 55 // You may need to create a configuration type if necessary. 56 type ( 57 istanbulCompatibleBlock *big.Int 58 LondonCompatibleBlock *big.Int 59 EthTxTypeCompatibleBlock *big.Int 60 magmaCompatibleBlock *big.Int 61 koreCompatibleBlock *big.Int 62 ) 63 64 type ( 65 minimumStake *big.Int 66 mintingAmount *big.Int 67 stakingUpdateInterval uint64 68 proposerUpdateInterval uint64 69 proposerPolicy uint64 70 governanceMode string 71 epoch uint64 72 subGroupSize uint64 73 blockPeriod uint64 74 ) 75 76 // makeCommittedSeals returns a list of committed seals for the global variable nodeKeys. 77 func makeCommittedSeals(hash common.Hash) [][]byte { 78 committedSeals := make([][]byte, len(nodeKeys)) 79 hashData := crypto.Keccak256(core.PrepareCommittedSeal(hash)) 80 for i, key := range nodeKeys { 81 sig, _ := crypto.Sign(hashData, key) 82 committedSeals[i] = make([]byte, types.IstanbulExtraSeal) 83 copy(committedSeals[i][:], sig) 84 } 85 return committedSeals 86 } 87 88 // Include a node from the global nodeKeys and addrs 89 func includeNode(addr common.Address, key *ecdsa.PrivateKey) { 90 for _, a := range addrs { 91 if a.String() == addr.String() { 92 // already exists 93 return 94 } 95 } 96 nodeKeys = append(nodeKeys, key) 97 addrs = append(addrs, addr) 98 } 99 100 // Exclude a node from the global nodeKeys and addrs 101 func excludeNodeByAddr(target common.Address) { 102 for i, a := range addrs { 103 if a.String() == target.String() { 104 nodeKeys = append(nodeKeys[:i], nodeKeys[i+1:]...) 105 addrs = append(addrs[:i], addrs[i+1:]...) 106 break 107 } 108 } 109 } 110 111 // in this test, we can set n to 1, and it means we can process Istanbul and commit a 112 // block by one node. Otherwise, if n is larger than 1, we have to generate 113 // other fake events to process Istanbul. 114 func newBlockChain(n int, items ...interface{}) (*blockchain.BlockChain, *backend) { 115 // generate a genesis block 116 genesis := blockchain.DefaultGenesisBlock() 117 genesis.Config = params.TestChainConfig.Copy() 118 genesis.Timestamp = uint64(time.Now().Unix()) 119 120 var ( 121 key *ecdsa.PrivateKey 122 period = istanbul.DefaultConfig.BlockPeriod 123 ) 124 // force enable Istanbul engine and governance 125 genesis.Config.Istanbul = params.GetDefaultIstanbulConfig() 126 genesis.Config.Governance = params.GetDefaultGovernanceConfig() 127 for _, item := range items { 128 switch v := item.(type) { 129 case istanbulCompatibleBlock: 130 genesis.Config.IstanbulCompatibleBlock = v 131 case LondonCompatibleBlock: 132 genesis.Config.LondonCompatibleBlock = v 133 case EthTxTypeCompatibleBlock: 134 genesis.Config.EthTxTypeCompatibleBlock = v 135 case magmaCompatibleBlock: 136 genesis.Config.MagmaCompatibleBlock = v 137 case koreCompatibleBlock: 138 genesis.Config.KoreCompatibleBlock = v 139 case proposerPolicy: 140 genesis.Config.Istanbul.ProposerPolicy = uint64(v) 141 case epoch: 142 genesis.Config.Istanbul.Epoch = uint64(v) 143 case subGroupSize: 144 genesis.Config.Istanbul.SubGroupSize = uint64(v) 145 case minimumStake: 146 genesis.Config.Governance.Reward.MinimumStake = v 147 case stakingUpdateInterval: 148 genesis.Config.Governance.Reward.StakingUpdateInterval = uint64(v) 149 case proposerUpdateInterval: 150 genesis.Config.Governance.Reward.ProposerUpdateInterval = uint64(v) 151 case mintingAmount: 152 genesis.Config.Governance.Reward.MintingAmount = v 153 case governanceMode: 154 genesis.Config.Governance.GovernanceMode = string(v) 155 case *ecdsa.PrivateKey: 156 key = v 157 case blockPeriod: 158 period = uint64(v) 159 } 160 } 161 nodeKeys = make([]*ecdsa.PrivateKey, n) 162 addrs = make([]common.Address, n) 163 164 var b *backend 165 if len(items) != 0 { 166 b = newTestBackendWithConfig(genesis.Config, period, key) 167 } else { 168 b = newTestBackend() 169 } 170 171 nodeKeys[0] = b.privateKey 172 addrs[0] = b.address // if governance mode is single, this address is the governing node address 173 for i := 1; i < n; i++ { 174 nodeKeys[i], _ = crypto.GenerateKey() 175 addrs[i] = crypto.PubkeyToAddress(nodeKeys[i].PublicKey) 176 } 177 178 appendValidators(genesis, addrs) 179 180 genesis.MustCommit(b.db) 181 182 bc, err := blockchain.NewBlockChain(b.db, nil, genesis.Config, b, vm.Config{}) 183 if err != nil { 184 panic(err) 185 } 186 b.governance.SetBlockchain(bc) 187 188 if b.Start(bc, bc.CurrentBlock, bc.HasBadBlock) != nil { 189 panic(err) 190 } 191 192 return bc, b 193 } 194 195 func appendValidators(genesis *blockchain.Genesis, addrs []common.Address) { 196 if len(genesis.ExtraData) < types.IstanbulExtraVanity { 197 genesis.ExtraData = append(genesis.ExtraData, bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity)...) 198 } 199 genesis.ExtraData = genesis.ExtraData[:types.IstanbulExtraVanity] 200 201 ist := &types.IstanbulExtra{ 202 Validators: addrs, 203 Seal: []byte{}, 204 CommittedSeal: [][]byte{}, 205 } 206 207 istPayload, err := rlp.EncodeToBytes(&ist) 208 if err != nil { 209 panic("failed to encode istanbul extra") 210 } 211 genesis.ExtraData = append(genesis.ExtraData, istPayload...) 212 } 213 214 func makeHeader(parent *types.Block, config *istanbul.Config) *types.Header { 215 header := &types.Header{ 216 ParentHash: parent.Hash(), 217 Number: parent.Number().Add(parent.Number(), common.Big1), 218 GasUsed: 0, 219 Extra: parent.Extra(), 220 Time: new(big.Int).Add(parent.Time(), new(big.Int).SetUint64(config.BlockPeriod)), 221 BlockScore: defaultBlockScore, 222 } 223 if parent.Header().BaseFee != nil { 224 // We don't have chainConfig so the BaseFee of the current block is set by parent's for test 225 header.BaseFee = parent.Header().BaseFee 226 } 227 return header 228 } 229 230 func makeBlock(chain *blockchain.BlockChain, engine *backend, parent *types.Block) *types.Block { 231 block := makeBlockWithoutSeal(chain, engine, parent) 232 stopCh := make(chan struct{}) 233 result, err := engine.Seal(chain, block, stopCh) 234 if err != nil { 235 panic(err) 236 } 237 return result 238 } 239 240 // makeBlockWithSeal creates a block with the proposer seal as well as all committed seals of validators. 241 func makeBlockWithSeal(chain *blockchain.BlockChain, engine *backend, parent *types.Block) *types.Block { 242 blockWithoutSeal := makeBlockWithoutSeal(chain, engine, parent) 243 244 // add proposer seal for the block 245 block, err := engine.updateBlock(blockWithoutSeal) 246 if err != nil { 247 panic(err) 248 } 249 250 // write validators committed seals to the block 251 header := block.Header() 252 committedSeals := makeCommittedSeals(block.Hash()) 253 err = writeCommittedSeals(header, committedSeals) 254 if err != nil { 255 panic(err) 256 } 257 block = block.WithSeal(header) 258 259 return block 260 } 261 262 func makeBlockWithoutSeal(chain *blockchain.BlockChain, engine *backend, parent *types.Block) *types.Block { 263 header := makeHeader(parent, engine.config) 264 if err := engine.Prepare(chain, header); err != nil { 265 panic(err) 266 } 267 state, _ := chain.StateAt(parent.Root()) 268 block, _ := engine.Finalize(chain, header, state, nil, nil) 269 return block 270 } 271 272 func TestPrepare(t *testing.T) { 273 chain, engine := newBlockChain(1) 274 defer engine.Stop() 275 276 header := makeHeader(chain.Genesis(), engine.config) 277 err := engine.Prepare(chain, header) 278 if err != nil { 279 t.Errorf("error mismatch: have %v, want nil", err) 280 } 281 282 header.ParentHash = common.HexToHash("0x1234567890") 283 err = engine.Prepare(chain, header) 284 if err != consensus.ErrUnknownAncestor { 285 t.Errorf("error mismatch: have %v, want %v", err, consensus.ErrUnknownAncestor) 286 } 287 } 288 289 func TestSealStopChannel(t *testing.T) { 290 chain, engine := newBlockChain(4) 291 defer engine.Stop() 292 oldStakingManager := setTestStakingInfo(nil) 293 defer reward.SetTestStakingManager(oldStakingManager) 294 295 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 296 stop := make(chan struct{}, 1) 297 eventSub := engine.EventMux().Subscribe(istanbul.RequestEvent{}) 298 eventLoop := func() { 299 select { 300 case ev := <-eventSub.Chan(): 301 _, ok := ev.Data.(istanbul.RequestEvent) 302 if !ok { 303 t.Errorf("unexpected event comes: %v", reflect.TypeOf(ev.Data)) 304 } 305 stop <- struct{}{} 306 } 307 eventSub.Unsubscribe() 308 } 309 go eventLoop() 310 311 finalBlock, err := engine.Seal(chain, block, stop) 312 if err != nil { 313 t.Errorf("error mismatch: have %v, want nil", err) 314 } 315 316 if finalBlock != nil { 317 t.Errorf("block mismatch: have %v, want nil", finalBlock) 318 } 319 } 320 321 func TestSealCommitted(t *testing.T) { 322 chain, engine := newBlockChain(1) 323 defer engine.Stop() 324 oldStakingManager := setTestStakingInfo(nil) 325 defer reward.SetTestStakingManager(oldStakingManager) 326 327 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 328 expectedBlock, _ := engine.updateBlock(block) 329 330 actualBlock, err := engine.Seal(chain, block, make(chan struct{})) 331 if err != nil { 332 t.Errorf("error mismatch: have %v, want %v", err, expectedBlock) 333 } 334 335 if actualBlock.Hash() != expectedBlock.Hash() { 336 t.Errorf("hash mismatch: have %v, want %v", actualBlock.Hash(), expectedBlock.Hash()) 337 } 338 } 339 340 func TestVerifyHeader(t *testing.T) { 341 var configItems []interface{} 342 configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0))) 343 configItems = append(configItems, LondonCompatibleBlock(new(big.Int).SetUint64(0))) 344 configItems = append(configItems, EthTxTypeCompatibleBlock(new(big.Int).SetUint64(0))) 345 configItems = append(configItems, magmaCompatibleBlock(new(big.Int).SetUint64(0))) 346 configItems = append(configItems, koreCompatibleBlock(new(big.Int).SetUint64(0))) 347 chain, engine := newBlockChain(1, configItems...) 348 defer engine.Stop() 349 350 // errEmptyCommittedSeals case 351 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 352 block, _ = engine.updateBlock(block) 353 err := engine.VerifyHeader(chain, block.Header(), false) 354 if err != errEmptyCommittedSeals { 355 t.Errorf("error mismatch: have %v, want %v", err, errEmptyCommittedSeals) 356 } 357 358 // short extra data 359 header := block.Header() 360 header.Extra = []byte{} 361 err = engine.VerifyHeader(chain, header, false) 362 if err != errInvalidExtraDataFormat { 363 t.Errorf("error mismatch: have %v, want %v", err, errInvalidExtraDataFormat) 364 } 365 // incorrect extra format 366 header.Extra = []byte("0000000000000000000000000000000012300000000000000000000000000000000000000000000000000000000000000000") 367 err = engine.VerifyHeader(chain, header, false) 368 if err != errInvalidExtraDataFormat { 369 t.Errorf("error mismatch: have %v, want %v", err, errInvalidExtraDataFormat) 370 } 371 372 // invalid difficulty 373 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 374 header = block.Header() 375 header.BlockScore = big.NewInt(2) 376 err = engine.VerifyHeader(chain, header, false) 377 if err != errInvalidBlockScore { 378 t.Errorf("error mismatch: have %v, want %v", err, errInvalidBlockScore) 379 } 380 381 // invalid timestamp 382 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 383 header = block.Header() 384 header.Time = new(big.Int).Add(chain.Genesis().Time(), new(big.Int).SetUint64(engine.config.BlockPeriod-1)) 385 err = engine.VerifyHeader(chain, header, false) 386 if err != errInvalidTimestamp { 387 t.Errorf("error mismatch: have %v, want %v", err, errInvalidTimestamp) 388 } 389 390 // future block 391 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 392 header = block.Header() 393 header.Time = new(big.Int).Add(big.NewInt(now().Unix()), new(big.Int).SetUint64(10)) 394 err = engine.VerifyHeader(chain, header, false) 395 if err != consensus.ErrFutureBlock { 396 t.Errorf("error mismatch: have %v, want %v", err, consensus.ErrFutureBlock) 397 } 398 399 // TODO-Klaytn: add more tests for header.Governance, header.Rewardbase, header.Vote 400 } 401 402 func TestVerifySeal(t *testing.T) { 403 chain, engine := newBlockChain(1) 404 defer engine.Stop() 405 oldStakingManager := setTestStakingInfo(nil) 406 defer reward.SetTestStakingManager(oldStakingManager) 407 408 genesis := chain.Genesis() 409 410 // cannot verify genesis 411 err := engine.VerifySeal(chain, genesis.Header()) 412 if err != errUnknownBlock { 413 t.Errorf("error mismatch: have %v, want %v", err, errUnknownBlock) 414 } 415 block := makeBlock(chain, engine, genesis) 416 417 // clean cache before testing 418 signatureAddresses.Purge() 419 420 // change block content 421 header := block.Header() 422 header.Number = big.NewInt(4) 423 block1 := block.WithSeal(header) 424 err = engine.VerifySeal(chain, block1.Header()) 425 if err != errUnauthorized { 426 t.Errorf("error mismatch: have %v, want %v", err, errUnauthorized) 427 } 428 429 // clean cache before testing 430 signatureAddresses.Purge() 431 432 // unauthorized users but still can get correct signer address 433 engine.privateKey, _ = crypto.GenerateKey() 434 err = engine.VerifySeal(chain, block.Header()) 435 if err != nil { 436 t.Errorf("error mismatch: have %v, want nil", err) 437 } 438 } 439 440 func TestVerifyHeaders(t *testing.T) { 441 chain, engine := newBlockChain(1) 442 defer engine.Stop() 443 444 oldStakingManager := setTestStakingInfo(nil) 445 defer reward.SetTestStakingManager(oldStakingManager) 446 447 genesis := chain.Genesis() 448 449 // success case 450 headers := []*types.Header{} 451 blocks := []*types.Block{} 452 size := 100 453 454 for i := 0; i < size; i++ { 455 var b *types.Block 456 if i == 0 { 457 b = makeBlockWithoutSeal(chain, engine, genesis) 458 b, _ = engine.updateBlock(b) 459 engine.db.WriteHeader(b.Header()) 460 } else { 461 b = makeBlockWithoutSeal(chain, engine, blocks[i-1]) 462 b, _ = engine.updateBlock(b) 463 engine.db.WriteHeader(b.Header()) 464 } 465 blocks = append(blocks, b) 466 headers = append(headers, blocks[i].Header()) 467 } 468 469 // proceed time to avoid future block errors 470 now = func() time.Time { 471 return time.Unix(headers[size-1].Time.Int64(), 0) 472 } 473 defer func() { 474 now = time.Now 475 }() 476 477 _, results := engine.VerifyHeaders(chain, headers, nil) 478 const timeoutDura = 2 * time.Second 479 timeout := time.NewTimer(timeoutDura) 480 index := 0 481 OUT1: 482 for { 483 select { 484 case err := <-results: 485 if err != nil { 486 if err != errEmptyCommittedSeals && err != errInvalidCommittedSeals { 487 t.Errorf("error mismatch: have %v, want errEmptyCommittedSeals|errInvalidCommittedSeals", err) 488 break OUT1 489 } 490 } 491 index++ 492 if index == size { 493 break OUT1 494 } 495 case <-timeout.C: 496 break OUT1 497 } 498 } 499 // abort cases 500 abort, results := engine.VerifyHeaders(chain, headers, nil) 501 timeout = time.NewTimer(timeoutDura) 502 index = 0 503 OUT2: 504 for { 505 select { 506 case err := <-results: 507 if err != nil { 508 if err != errEmptyCommittedSeals && err != errInvalidCommittedSeals { 509 t.Errorf("error mismatch: have %v, want errEmptyCommittedSeals|errInvalidCommittedSeals", err) 510 break OUT2 511 } 512 } 513 index++ 514 if index == 5 { 515 abort <- struct{}{} 516 } 517 if index >= size { 518 t.Errorf("verifyheaders should be aborted") 519 break OUT2 520 } 521 case <-timeout.C: 522 break OUT2 523 } 524 } 525 // error header cases 526 headers[2].Number = big.NewInt(100) 527 abort, results = engine.VerifyHeaders(chain, headers, nil) 528 timeout = time.NewTimer(timeoutDura) 529 index = 0 530 errors := 0 531 expectedErrors := 2 532 OUT3: 533 for { 534 select { 535 case err := <-results: 536 if err != nil { 537 if err != errEmptyCommittedSeals && err != errInvalidCommittedSeals { 538 errors++ 539 } 540 } 541 index++ 542 if index == size { 543 if errors != expectedErrors { 544 t.Errorf("error mismatch: have %v, want %v", err, expectedErrors) 545 } 546 break OUT3 547 } 548 case <-timeout.C: 549 break OUT3 550 } 551 } 552 } 553 554 func TestPrepareExtra(t *testing.T) { 555 validators := make([]common.Address, 4) 556 validators[0] = common.BytesToAddress(hexutil.MustDecode("0x44add0ec310f115a0e603b2d7db9f067778eaf8a")) 557 validators[1] = common.BytesToAddress(hexutil.MustDecode("0x294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212")) 558 validators[2] = common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6")) 559 validators[3] = common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440")) 560 561 vanity := make([]byte, types.IstanbulExtraVanity) 562 expectedResult := append(vanity, hexutil.MustDecode("0xf858f8549444add0ec310f115a0e603b2d7db9f067778eaf8a94294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212946beaaed781d2d2ab6350f5c4566a2c6eaac407a6948be76812f765c24641ec63dc2852b378aba2b44080c0")...) 563 564 h := &types.Header{ 565 Extra: vanity, 566 } 567 568 payload, err := prepareExtra(h, validators) 569 if err != nil { 570 t.Errorf("error mismatch: have %v, want: nil", err) 571 } 572 if !reflect.DeepEqual(payload, expectedResult) { 573 t.Errorf("payload mismatch: have %v, want %v", payload, expectedResult) 574 } 575 576 // append useless information to extra-data 577 h.Extra = append(vanity, make([]byte, 15)...) 578 579 payload, err = prepareExtra(h, validators) 580 if !reflect.DeepEqual(payload, expectedResult) { 581 t.Errorf("payload mismatch: have %v, want %v", payload, expectedResult) 582 } 583 } 584 585 func TestWriteSeal(t *testing.T) { 586 vanity := bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity) 587 istRawData := hexutil.MustDecode("0xf858f8549444add0ec310f115a0e603b2d7db9f067778eaf8a94294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212946beaaed781d2d2ab6350f5c4566a2c6eaac407a6948be76812f765c24641ec63dc2852b378aba2b44080c0") 588 expectedSeal := append([]byte{1, 2, 3}, bytes.Repeat([]byte{0x00}, types.IstanbulExtraSeal-3)...) 589 expectedIstExtra := &types.IstanbulExtra{ 590 Validators: []common.Address{ 591 common.BytesToAddress(hexutil.MustDecode("0x44add0ec310f115a0e603b2d7db9f067778eaf8a")), 592 common.BytesToAddress(hexutil.MustDecode("0x294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212")), 593 common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6")), 594 common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440")), 595 }, 596 Seal: expectedSeal, 597 CommittedSeal: [][]byte{}, 598 } 599 var expectedErr error 600 601 h := &types.Header{ 602 Extra: append(vanity, istRawData...), 603 } 604 605 // normal case 606 err := writeSeal(h, expectedSeal) 607 if err != expectedErr { 608 t.Errorf("error mismatch: have %v, want %v", err, expectedErr) 609 } 610 611 // verify istanbul extra-data 612 istExtra, err := types.ExtractIstanbulExtra(h) 613 if err != nil { 614 t.Errorf("error mismatch: have %v, want nil", err) 615 } 616 if !reflect.DeepEqual(istExtra, expectedIstExtra) { 617 t.Errorf("extra data mismatch: have %v, want %v", istExtra, expectedIstExtra) 618 } 619 620 // invalid seal 621 unexpectedSeal := append(expectedSeal, make([]byte, 1)...) 622 err = writeSeal(h, unexpectedSeal) 623 if err != errInvalidSignature { 624 t.Errorf("error mismatch: have %v, want %v", err, errInvalidSignature) 625 } 626 } 627 628 func TestWriteCommittedSeals(t *testing.T) { 629 vanity := bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity) 630 istRawData := hexutil.MustDecode("0xf858f8549444add0ec310f115a0e603b2d7db9f067778eaf8a94294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212946beaaed781d2d2ab6350f5c4566a2c6eaac407a6948be76812f765c24641ec63dc2852b378aba2b44080c0") 631 expectedCommittedSeal := append([]byte{1, 2, 3}, bytes.Repeat([]byte{0x00}, types.IstanbulExtraSeal-3)...) 632 expectedIstExtra := &types.IstanbulExtra{ 633 Validators: []common.Address{ 634 common.BytesToAddress(hexutil.MustDecode("0x44add0ec310f115a0e603b2d7db9f067778eaf8a")), 635 common.BytesToAddress(hexutil.MustDecode("0x294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212")), 636 common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6")), 637 common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440")), 638 }, 639 Seal: []byte{}, 640 CommittedSeal: [][]byte{expectedCommittedSeal}, 641 } 642 var expectedErr error 643 644 h := &types.Header{ 645 Extra: append(vanity, istRawData...), 646 } 647 648 // normal case 649 err := writeCommittedSeals(h, [][]byte{expectedCommittedSeal}) 650 if err != expectedErr { 651 t.Errorf("error mismatch: have %v, want %v", err, expectedErr) 652 } 653 654 // verify istanbul extra-data 655 istExtra, err := types.ExtractIstanbulExtra(h) 656 if err != nil { 657 t.Errorf("error mismatch: have %v, want nil", err) 658 } 659 if !reflect.DeepEqual(istExtra, expectedIstExtra) { 660 t.Errorf("extra data mismatch: have %v, want %v", istExtra, expectedIstExtra) 661 } 662 663 // invalid seal 664 unexpectedCommittedSeal := append(expectedCommittedSeal, make([]byte, 1)...) 665 err = writeCommittedSeals(h, [][]byte{unexpectedCommittedSeal}) 666 if err != errInvalidCommittedSeals { 667 t.Errorf("error mismatch: have %v, want %v", err, errInvalidCommittedSeals) 668 } 669 } 670 671 func TestRewardDistribution(t *testing.T) { 672 type vote = map[string]interface{} 673 type expected = map[int]uint64 674 type testcase struct { 675 length int // total number of blocks to simulate 676 votes map[int]vote 677 expected expected 678 } 679 680 mintAmount := uint64(1) 681 koreBlock := uint64(9) 682 testEpoch := 3 683 684 testcases := []testcase{ 685 { 686 12, 687 map[int]vote{ 688 1: {"reward.mintingamount": "2"}, // activated at block 7 (activation is before-Kore) 689 4: {"reward.mintingamount": "3"}, // activated at block 9 (activation is after-Kore) 690 }, 691 map[int]uint64{ 692 1: 1, 693 2: 2, 694 3: 3, 695 4: 4, 696 5: 5, 697 6: 6, 698 7: 8, // 2 is minted from now 699 8: 10, 700 9: 13, // 3 is minted from now 701 10: 16, 702 11: 19, 703 12: 22, 704 13: 25, 705 }, 706 }, 707 } 708 709 var configItems []interface{} 710 configItems = append(configItems, epoch(testEpoch)) 711 configItems = append(configItems, mintingAmount(new(big.Int).SetUint64(mintAmount))) 712 configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0))) 713 configItems = append(configItems, LondonCompatibleBlock(new(big.Int).SetUint64(0))) 714 configItems = append(configItems, EthTxTypeCompatibleBlock(new(big.Int).SetUint64(0))) 715 configItems = append(configItems, magmaCompatibleBlock(new(big.Int).SetUint64(0))) 716 configItems = append(configItems, koreCompatibleBlock(new(big.Int).SetUint64(koreBlock))) 717 configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block 718 719 chain, engine := newBlockChain(1, configItems...) 720 assert.Equal(t, uint64(testEpoch), engine.governance.CurrentParams().Epoch()) 721 assert.Equal(t, mintAmount, engine.governance.CurrentParams().MintingAmountBig().Uint64()) 722 723 var previousBlock, currentBlock *types.Block = nil, chain.Genesis() 724 725 for _, tc := range testcases { 726 // Place a vote if a vote is scheduled in upcoming block 727 // Note that we're building (head+1)'th block here. 728 for num := 0; num <= tc.length; num++ { 729 for k, v := range tc.votes[num+1] { 730 ok := engine.governance.AddVote(k, v) 731 assert.True(t, ok) 732 } 733 734 // Create a block 735 previousBlock = currentBlock 736 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 737 _, err := chain.InsertChain(types.Blocks{currentBlock}) 738 assert.NoError(t, err) 739 740 // check balance 741 addr := currentBlock.Rewardbase() 742 state, err := chain.State() 743 assert.NoError(t, err) 744 bal := state.GetBalance(addr) 745 746 assert.Equal(t, tc.expected[num+1], bal.Uint64(), "wrong at block %d", num+1) 747 } 748 } 749 } 750 751 func makeSnapshotTestConfigItems() []interface{} { 752 return []interface{}{ 753 stakingUpdateInterval(1), 754 proposerUpdateInterval(1), 755 proposerPolicy(params.WeightedRandom), 756 } 757 } 758 759 // Set StakingInfo with given amount for nodeKeys. If amounts == nil, set to 0 amounts. 760 // Returns the original (old) StakingManager. Call `reward.SetTestStakingManager(oldStakingManager)` 761 func setTestStakingInfo(amounts []uint64) *reward.StakingManager { 762 if amounts == nil { 763 amounts = make([]uint64, len(nodeKeys)) 764 } 765 766 stakingInfo := &reward.StakingInfo{ 767 BlockNum: 0, 768 } 769 for idx, key := range nodeKeys { 770 addr := crypto.PubkeyToAddress(key.PublicKey) 771 772 pk, _ := crypto.GenerateKey() 773 rewardAddr := crypto.PubkeyToAddress(pk.PublicKey) 774 775 stakingInfo.CouncilNodeAddrs = append(stakingInfo.CouncilNodeAddrs, addr) 776 stakingInfo.CouncilStakingAddrs = append(stakingInfo.CouncilStakingAddrs, addr) 777 stakingInfo.CouncilStakingAmounts = append(stakingInfo.CouncilStakingAmounts, amounts[idx]) 778 stakingInfo.CouncilRewardAddrs = append(stakingInfo.CouncilRewardAddrs, rewardAddr) 779 } 780 781 // Save old StakingManager, overwrite to the fake one. 782 oldStakingManager := reward.GetStakingManager() 783 reward.SetTestStakingManagerWithStakingInfoCache(stakingInfo) 784 return oldStakingManager 785 } 786 787 func toAddressList(validators []istanbul.Validator) []common.Address { 788 addresses := make([]common.Address, len(validators)) 789 for idx, val := range validators { 790 addresses[idx] = val.Address() 791 } 792 return addresses 793 } 794 795 func copyAndSortAddrs(addrs []common.Address) []common.Address { 796 copied := make([]common.Address, len(addrs)) 797 copy(copied, addrs) 798 799 sort.Slice(copied, func(i, j int) bool { 800 return strings.Compare(copied[i].String(), copied[j].String()) < 0 801 }) 802 803 return copied 804 } 805 806 func makeExpectedResult(indices []int, candidate []common.Address) []common.Address { 807 expected := make([]common.Address, len(indices)) 808 for eIdx, cIdx := range indices { 809 expected[eIdx] = candidate[cIdx] 810 } 811 return copyAndSortAddrs(expected) 812 } 813 814 // Asserts taht if all (key,value) pairs of `subset` exists in `set` 815 func assertMapSubset(t *testing.T, subset, set map[string]interface{}) { 816 for k, v := range subset { 817 assert.Equal(t, set[k], v) 818 } 819 } 820 821 func TestSnapshot_Validators_AfterMinimumStakingVotes(t *testing.T) { 822 type vote struct { 823 key string 824 value interface{} 825 } 826 type expected struct { 827 blocks []uint64 828 validators []int 829 demoted []int 830 } 831 type testcase struct { 832 stakingAmounts []uint64 833 votes []vote 834 expected []expected 835 } 836 837 testcases := []testcase{ 838 { 839 // test the validators are updated properly when minimum staking is changed in none mode 840 []uint64{8000000, 7000000, 6000000, 5000000}, 841 []vote{ 842 {"governance.governancemode", "none"}, // voted on epoch 1, applied from 6-8 843 {"reward.minimumstake", "5500000"}, // voted on epoch 2, applied from 9-11 844 {"reward.minimumstake", "6500000"}, // voted on epoch 3, applied from 12-14 845 {"reward.minimumstake", "7500000"}, // voted on epoch 4, applied from 15-17 846 {"reward.minimumstake", "8500000"}, // voted on epoch 5, applied from 18-20 847 {"reward.minimumstake", "7500000"}, // voted on epoch 6, applied from 21-23 848 {"reward.minimumstake", "6500000"}, // voted on epoch 7, applied from 24-26 849 {"reward.minimumstake", "5500000"}, // voted on epoch 8, applied from 27-29 850 {"reward.minimumstake", "4500000"}, // voted on epoch 9, applied from 30-32 851 }, 852 []expected{ 853 {[]uint64{0, 1, 2, 3, 4, 5, 6, 7, 8}, []int{0, 1, 2, 3}, []int{}}, 854 {[]uint64{9, 10, 11}, []int{0, 1, 2}, []int{3}}, 855 {[]uint64{12, 13, 14}, []int{0, 1}, []int{2, 3}}, 856 {[]uint64{15, 16, 17}, []int{0}, []int{1, 2, 3}}, 857 {[]uint64{18, 19, 20}, []int{0, 1, 2, 3}, []int{}}, 858 {[]uint64{21, 22, 23}, []int{0}, []int{1, 2, 3}}, 859 {[]uint64{24, 25, 26}, []int{0, 1}, []int{2, 3}}, 860 {[]uint64{27, 28, 29}, []int{0, 1, 2}, []int{3}}, 861 {[]uint64{30, 31, 32}, []int{0, 1, 2, 3}, []int{}}, 862 }, 863 }, 864 { 865 // test the validators (including governing node) are updated properly when minimum staking is changed in single mode 866 []uint64{5000000, 6000000, 7000000, 8000000}, 867 []vote{ 868 {"reward.minimumstake", "8500000"}, // voted on epoch 1, applied from 6-8 869 {"reward.minimumstake", "7500000"}, // voted on epoch 2, applied from 9-11 870 {"reward.minimumstake", "6500000"}, // voted on epoch 3, applied from 12-14 871 {"reward.minimumstake", "5500000"}, // voted on epoch 4, applied from 15-17 872 {"reward.minimumstake", "4500000"}, // voted on epoch 5, applied from 18-20 873 {"reward.minimumstake", "5500000"}, // voted on epoch 6, applied from 21-23 874 {"reward.minimumstake", "6500000"}, // voted on epoch 7, applied from 24-26 875 {"reward.minimumstake", "7500000"}, // voted on epoch 8, applied from 27-29 876 {"reward.minimumstake", "8500000"}, // voted on epoch 9, applied from 30-32 877 }, 878 []expected{ 879 // 0 is governing node, so it is included in the validators all the time 880 {[]uint64{0, 1, 2, 3, 4, 5, 6, 7, 8}, []int{0, 1, 2, 3}, []int{}}, 881 {[]uint64{9, 10, 11}, []int{0, 3}, []int{1, 2}}, 882 {[]uint64{12, 13, 14}, []int{0, 2, 3}, []int{1}}, 883 {[]uint64{15, 16, 17, 18, 19, 20, 21, 22, 23}, []int{0, 1, 2, 3}, []int{}}, 884 {[]uint64{24, 25, 26}, []int{0, 2, 3}, []int{1}}, 885 {[]uint64{27, 28, 29}, []int{0, 3}, []int{1, 2}}, 886 {[]uint64{30, 31, 32}, []int{0, 1, 2, 3}, []int{}}, 887 }, 888 }, 889 { 890 // test the validators are updated properly if governing node is changed 891 []uint64{6000000, 6000000, 5000000, 5000000}, 892 []vote{ 893 {"reward.minimumstake", "5500000"}, // voted on epoch 1, applied from 6-8 894 {"governance.governingnode", 2}, // voted on epoch 2, applied from 9-11 895 }, 896 []expected{ 897 // 0 is governing node, so it is included in the validators all the time 898 {[]uint64{0, 1, 2, 3, 4, 5}, []int{0, 1, 2, 3}, []int{}}, 899 {[]uint64{6, 7, 8}, []int{0, 1}, []int{2, 3}}, 900 {[]uint64{9, 10, 11}, []int{0, 1, 2}, []int{3}}, 901 }, 902 }, 903 } 904 905 testEpoch := 3 906 907 var configItems []interface{} 908 configItems = append(configItems, proposerPolicy(params.WeightedRandom)) 909 configItems = append(configItems, proposerUpdateInterval(1)) 910 configItems = append(configItems, epoch(testEpoch)) 911 configItems = append(configItems, governanceMode("single")) 912 configItems = append(configItems, minimumStake(new(big.Int).SetUint64(4000000))) 913 configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0))) 914 configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block 915 916 for _, tc := range testcases { 917 chain, engine := newBlockChain(4, configItems...) 918 oldStakingManager := setTestStakingInfo(tc.stakingAmounts) 919 920 var previousBlock, currentBlock *types.Block = nil, chain.Genesis() 921 922 for _, v := range tc.votes { 923 // vote a vote in each epoch 924 if v.key == "governance.governingnode" { 925 idx := v.value.(int) 926 v.value = addrs[idx].String() 927 } 928 engine.governance.AddVote(v.key, v.value) 929 930 for i := 0; i < testEpoch; i++ { 931 previousBlock = currentBlock 932 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 933 _, err := chain.InsertChain(types.Blocks{currentBlock}) 934 assert.NoError(t, err) 935 } 936 } 937 938 // insert blocks on extra epoch 939 for i := 0; i < 2*testEpoch; i++ { 940 previousBlock = currentBlock 941 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 942 _, err := chain.InsertChain(types.Blocks{currentBlock}) 943 assert.NoError(t, err) 944 } 945 946 for _, e := range tc.expected { 947 for _, num := range e.blocks { 948 block := chain.GetBlockByNumber(num) 949 snap, err := engine.snapshot(chain, block.NumberU64(), block.Hash(), nil, true) 950 assert.NoError(t, err) 951 952 validators := toAddressList(snap.ValSet.List()) 953 demoted := toAddressList(snap.ValSet.DemotedList()) 954 955 expectedValidators := makeExpectedResult(e.validators, addrs) 956 expectedDemoted := makeExpectedResult(e.demoted, addrs) 957 958 assert.Equal(t, expectedValidators, validators) 959 assert.Equal(t, expectedDemoted, demoted) 960 } 961 } 962 963 reward.SetTestStakingManager(oldStakingManager) 964 engine.Stop() 965 } 966 } 967 968 func TestSnapshot_Validators_BasedOnStaking(t *testing.T) { 969 type testcase struct { 970 stakingAmounts []uint64 // test staking amounts of each validator 971 isIstanbulCompatible bool // whether or not if the inserted block is istanbul compatible 972 isSingleMode bool // whether or not if the governance mode is single 973 expectedValidators []int // the indices of expected validators 974 expectedDemoted []int // the indices of expected demoted validators 975 } 976 977 testcases := []testcase{ 978 // The following testcases are the ones before istanbul incompatible change 979 { 980 []uint64{5000000, 5000000, 5000000, 5000000}, 981 false, 982 false, 983 []int{0, 1, 2, 3}, 984 []int{}, 985 }, 986 { 987 []uint64{5000000, 5000000, 5000000, 6000000}, 988 false, 989 false, 990 []int{0, 1, 2, 3}, 991 []int{}, 992 }, 993 { 994 []uint64{5000000, 5000000, 6000000, 6000000}, 995 false, 996 false, 997 []int{0, 1, 2, 3}, 998 []int{}, 999 }, 1000 { 1001 []uint64{5000000, 6000000, 6000000, 6000000}, 1002 false, 1003 false, 1004 []int{0, 1, 2, 3}, 1005 []int{}, 1006 }, 1007 { 1008 []uint64{6000000, 6000000, 6000000, 6000000}, 1009 false, 1010 false, 1011 []int{0, 1, 2, 3}, 1012 []int{}, 1013 }, 1014 // The following testcases are the ones after istanbul incompatible change 1015 { 1016 []uint64{5000000, 5000000, 5000000, 5000000}, 1017 true, 1018 false, 1019 []int{0, 1, 2, 3}, 1020 []int{}, 1021 }, 1022 { 1023 []uint64{5000000, 5000000, 5000000, 6000000}, 1024 true, 1025 false, 1026 []int{3}, 1027 []int{0, 1, 2}, 1028 }, 1029 { 1030 []uint64{5000000, 5000000, 6000000, 6000000}, 1031 true, 1032 false, 1033 []int{2, 3}, 1034 []int{0, 1}, 1035 }, 1036 { 1037 []uint64{5000000, 6000000, 6000000, 6000000}, 1038 true, 1039 false, 1040 []int{1, 2, 3}, 1041 []int{0}, 1042 }, 1043 { 1044 []uint64{6000000, 6000000, 6000000, 6000000}, 1045 true, 1046 false, 1047 []int{0, 1, 2, 3}, 1048 []int{}, 1049 }, 1050 { 1051 []uint64{5500001, 5500000, 5499999, 0}, 1052 true, 1053 false, 1054 []int{0, 1}, 1055 []int{2, 3}, 1056 }, 1057 // The following testcases are the ones for testing governing node in single mode 1058 // The first staking amount is of the governing node 1059 { 1060 []uint64{6000000, 6000000, 6000000, 6000000}, 1061 true, 1062 true, 1063 []int{0, 1, 2, 3}, 1064 []int{}, 1065 }, 1066 { 1067 []uint64{5000000, 6000000, 6000000, 6000000}, 1068 true, 1069 true, 1070 []int{0, 1, 2, 3}, 1071 []int{}, 1072 }, 1073 { 1074 []uint64{5000000, 5000000, 6000000, 6000000}, 1075 true, 1076 true, 1077 []int{0, 2, 3}, 1078 []int{1}, 1079 }, 1080 { 1081 []uint64{5000000, 5000000, 5000000, 6000000}, 1082 true, 1083 true, 1084 []int{0, 3}, 1085 []int{1, 2}, 1086 }, 1087 { 1088 []uint64{5000000, 5000000, 5000000, 5000000}, 1089 true, 1090 true, 1091 []int{0, 1, 2, 3}, 1092 []int{}, 1093 }, 1094 } 1095 1096 testNum := 4 1097 ms := uint64(5500000) 1098 configItems := makeSnapshotTestConfigItems() 1099 configItems = append(configItems, minimumStake(new(big.Int).SetUint64(ms))) 1100 for _, tc := range testcases { 1101 if tc.isIstanbulCompatible { 1102 configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0))) 1103 } 1104 if tc.isSingleMode { 1105 configItems = append(configItems, governanceMode("single")) 1106 } 1107 chain, engine := newBlockChain(testNum, configItems...) 1108 oldStakingManager := setTestStakingInfo(tc.stakingAmounts) 1109 1110 block := makeBlockWithSeal(chain, engine, chain.Genesis()) 1111 _, err := chain.InsertChain(types.Blocks{block}) 1112 assert.NoError(t, err) 1113 1114 snap, err := engine.snapshot(chain, block.NumberU64(), block.Hash(), nil, true) 1115 assert.NoError(t, err) 1116 1117 validators := toAddressList(snap.ValSet.List()) 1118 demoted := toAddressList(snap.ValSet.DemotedList()) 1119 1120 expectedValidators := makeExpectedResult(tc.expectedValidators, addrs) 1121 expectedDemoted := makeExpectedResult(tc.expectedDemoted, addrs) 1122 1123 assert.Equal(t, expectedValidators, validators) 1124 assert.Equal(t, expectedDemoted, demoted) 1125 1126 reward.SetTestStakingManager(oldStakingManager) 1127 engine.Stop() 1128 } 1129 } 1130 1131 func TestSnapshot_Validators_AddRemove(t *testing.T) { 1132 type vote struct { 1133 key string 1134 value interface{} 1135 } 1136 type expected struct { 1137 validators []int // expected validator indexes at given block 1138 } 1139 type testcase struct { 1140 length int // total number of blocks to simulate 1141 votes map[int]vote 1142 expected map[int]expected 1143 } 1144 1145 testcases := []testcase{ 1146 { // Singular change 1147 5, 1148 map[int]vote{ 1149 1: {"governance.removevalidator", 3}, 1150 3: {"governance.addvalidator", 3}, 1151 }, 1152 map[int]expected{ 1153 0: {[]int{0, 1, 2, 3}}, 1154 1: {[]int{0, 1, 2, 3}}, 1155 2: {[]int{0, 1, 2}}, 1156 3: {[]int{0, 1, 2}}, 1157 4: {[]int{0, 1, 2, 3}}, 1158 }, 1159 }, 1160 { // Plural change 1161 5, 1162 map[int]vote{ 1163 1: {"governance.removevalidator", []int{1, 2, 3}}, 1164 3: {"governance.addvalidator", []int{1, 2}}, 1165 }, 1166 map[int]expected{ 1167 0: {[]int{0, 1, 2, 3}}, 1168 1: {[]int{0, 1, 2, 3}}, 1169 2: {[]int{0}}, 1170 3: {[]int{0}}, 1171 4: {[]int{0, 1, 2}}, 1172 }, 1173 }, 1174 { // Around checkpoint interval (i.e. every 1024 block) 1175 params.CheckpointInterval + 10, 1176 map[int]vote{ 1177 params.CheckpointInterval - 5: {"governance.removevalidator", 3}, 1178 params.CheckpointInterval - 1: {"governance.removevalidator", 2}, 1179 params.CheckpointInterval + 0: {"governance.removevalidator", 1}, 1180 params.CheckpointInterval + 1: {"governance.addvalidator", 1}, 1181 params.CheckpointInterval + 2: {"governance.addvalidator", 2}, 1182 params.CheckpointInterval + 3: {"governance.addvalidator", 3}, 1183 }, 1184 map[int]expected{ 1185 0: {[]int{0, 1, 2, 3}}, 1186 1: {[]int{0, 1, 2, 3}}, 1187 params.CheckpointInterval - 4: {[]int{0, 1, 2}}, 1188 params.CheckpointInterval + 0: {[]int{0, 1}}, 1189 params.CheckpointInterval + 1: {[]int{0}}, 1190 params.CheckpointInterval + 2: {[]int{0, 1}}, 1191 params.CheckpointInterval + 3: {[]int{0, 1, 2}}, 1192 params.CheckpointInterval + 4: {[]int{0, 1, 2, 3}}, 1193 params.CheckpointInterval + 9: {[]int{0, 1, 2, 3}}, 1194 }, 1195 }, 1196 { // multiple addvalidator & removevalidator 1197 10, 1198 map[int]vote{ 1199 0: {"governance.removevalidator", 3}, 1200 2: {"governance.addvalidator", 3}, 1201 4: {"governance.addvalidator", 3}, 1202 6: {"governance.removevalidator", 3}, 1203 8: {"governance.removevalidator", 3}, 1204 }, 1205 map[int]expected{ 1206 1: {[]int{0, 1, 2}}, 1207 3: {[]int{0, 1, 2, 3}}, 1208 5: {[]int{0, 1, 2, 3}}, 1209 7: {[]int{0, 1, 2}}, 1210 9: {[]int{0, 1, 2}}, 1211 }, 1212 }, 1213 { // multiple removevalidator & addvalidator 1214 10, 1215 map[int]vote{ 1216 0: {"governance.removevalidator", 3}, 1217 2: {"governance.removevalidator", 3}, 1218 4: {"governance.addvalidator", 3}, 1219 6: {"governance.addvalidator", 3}, 1220 }, 1221 map[int]expected{ 1222 1: {[]int{0, 1, 2}}, 1223 3: {[]int{0, 1, 2}}, 1224 5: {[]int{0, 1, 2, 3}}, 1225 7: {[]int{0, 1, 2, 3}}, 1226 }, 1227 }, 1228 { // multiple addvalidators & removevalidators 1229 10, 1230 map[int]vote{ 1231 0: {"governance.removevalidator", []int{2, 3}}, 1232 2: {"governance.addvalidator", []int{2, 3}}, 1233 4: {"governance.addvalidator", []int{2, 3}}, 1234 6: {"governance.removevalidator", []int{2, 3}}, 1235 8: {"governance.removevalidator", []int{2, 3}}, 1236 }, 1237 map[int]expected{ 1238 1: {[]int{0, 1}}, 1239 3: {[]int{0, 1, 2, 3}}, 1240 5: {[]int{0, 1, 2, 3}}, 1241 7: {[]int{0, 1}}, 1242 9: {[]int{0, 1}}, 1243 }, 1244 }, 1245 { // multiple removevalidators & addvalidators 1246 10, 1247 map[int]vote{ 1248 0: {"governance.removevalidator", []int{2, 3}}, 1249 2: {"governance.removevalidator", []int{2, 3}}, 1250 4: {"governance.addvalidator", []int{2, 3}}, 1251 6: {"governance.addvalidator", []int{2, 3}}, 1252 }, 1253 map[int]expected{ 1254 1: {[]int{0, 1}}, 1255 3: {[]int{0, 1}}, 1256 5: {[]int{0, 1, 2, 3}}, 1257 7: {[]int{0, 1, 2, 3}}, 1258 }, 1259 }, 1260 } 1261 1262 var configItems []interface{} 1263 configItems = append(configItems, proposerPolicy(params.WeightedRandom)) 1264 configItems = append(configItems, proposerUpdateInterval(1)) 1265 configItems = append(configItems, epoch(3)) 1266 configItems = append(configItems, subGroupSize(4)) 1267 configItems = append(configItems, governanceMode("single")) 1268 configItems = append(configItems, minimumStake(new(big.Int).SetUint64(4000000))) 1269 configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0))) 1270 configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block 1271 stakes := []uint64{4000000, 4000000, 4000000, 4000000} 1272 1273 for _, tc := range testcases { 1274 // Create test blockchain 1275 chain, engine := newBlockChain(4, configItems...) 1276 oldStakingManager := setTestStakingInfo(stakes) 1277 1278 // Backup the globals. The globals `nodeKeys` and `addrs` will be 1279 // modified according to validator change votes. 1280 allNodeKeys := make([]*ecdsa.PrivateKey, len(nodeKeys)) 1281 allAddrs := make([]common.Address, len(addrs)) 1282 copy(allNodeKeys, nodeKeys) 1283 copy(allAddrs, addrs) 1284 1285 var previousBlock, currentBlock *types.Block = nil, chain.Genesis() 1286 1287 // Create blocks with votes 1288 for i := 0; i < tc.length; i++ { 1289 if v, ok := tc.votes[i]; ok { // If a vote is scheduled in this block, 1290 if idx, ok := v.value.(int); ok { 1291 addr := allAddrs[idx] 1292 engine.governance.AddVote(v.key, addr) 1293 } else { 1294 addrList := makeExpectedResult(v.value.([]int), allAddrs) 1295 engine.governance.AddVote(v.key, addrList) 1296 } 1297 // t.Logf("Voting at block #%d for %s, %v", i, v.key, v.value) 1298 } 1299 1300 previousBlock = currentBlock 1301 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 1302 _, err := chain.InsertChain(types.Blocks{currentBlock}) 1303 assert.NoError(t, err) 1304 1305 // After a voting, reflect the validator change to the globals 1306 if v, ok := tc.votes[i]; ok { 1307 var indices []int 1308 if idx, ok := v.value.(int); ok { 1309 indices = []int{idx} 1310 } else { 1311 indices = v.value.([]int) 1312 } 1313 if v.key == "governance.addvalidator" { 1314 for _, i := range indices { 1315 includeNode(allAddrs[i], allNodeKeys[i]) 1316 } 1317 } 1318 if v.key == "governance.removevalidator" { 1319 for _, i := range indices { 1320 excludeNodeByAddr(allAddrs[i]) 1321 } 1322 } 1323 } 1324 } 1325 1326 // Calculate historical validators using the snapshot. 1327 for i := 0; i < tc.length; i++ { 1328 if _, ok := tc.expected[i]; !ok { 1329 continue 1330 } 1331 block := chain.GetBlockByNumber(uint64(i)) 1332 snap, err := engine.snapshot(chain, block.NumberU64(), block.Hash(), nil, true) 1333 assert.NoError(t, err) 1334 validators := copyAndSortAddrs(toAddressList(snap.ValSet.List())) 1335 1336 expectedValidators := makeExpectedResult(tc.expected[i].validators, allAddrs) 1337 assert.Equal(t, expectedValidators, validators) 1338 // t.Logf("snap at block #%d: size %d", i, snap.ValSet.Size()) 1339 } 1340 1341 reward.SetTestStakingManager(oldStakingManager) 1342 engine.Stop() 1343 } 1344 } 1345 1346 func TestSnapshot_Writable(t *testing.T) { 1347 var configItems []interface{} 1348 configItems = append(configItems, proposerPolicy(params.WeightedRandom)) 1349 configItems = append(configItems, epoch(3)) 1350 configItems = append(configItems, governanceMode("single")) 1351 configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block 1352 chain, engine := newBlockChain(1, configItems...) 1353 defer engine.Stop() 1354 oldStakingManager := setTestStakingInfo(nil) 1355 defer reward.SetTestStakingManager(oldStakingManager) 1356 1357 // add votes and insert voted blocks 1358 var ( 1359 previousBlock, currentBlock *types.Block = nil, chain.Genesis() 1360 err error 1361 ) 1362 1363 // voteData is inserted at block 4, and current block is block 5. 1364 for i := 0; i < 5; i++ { 1365 if i == 4 { 1366 engine.governance.AddVote("governance.unitprice", uint64(2000000)) 1367 } 1368 previousBlock = currentBlock 1369 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 1370 _, err = chain.InsertChain(types.Blocks{currentBlock}) 1371 assert.NoError(t, err) 1372 } 1373 1374 // save current gov.changeSet's length for the expected value. 1375 currentChangeSetLength := len(engine.governance.GetGovernanceChange()) 1376 assert.Equal(t, 1, currentChangeSetLength) 1377 1378 // block 3 is the start block of an epoch. In this test, the cache of this block's snapshot is cleared. 1379 // If cache is not removed, it will just read the cache rather than making the snapshot itself. 1380 block := chain.GetBlockByNumber(uint64(3)) 1381 1382 // case [writable == false] 1383 // expected result: gov.changeSet should not be modified. 1384 engine.recents.Remove(block.Hash()) // assume node is restarted 1385 _, err = engine.snapshot(chain, block.NumberU64(), block.Hash(), nil, false) 1386 assert.Equal(t, currentChangeSetLength, len(engine.governance.GetGovernanceChange())) 1387 1388 // case [writable == true] 1389 // expected result: gov.changeSet is modified. 1390 engine.recents.Remove(block.Hash()) // assume node is restarted 1391 _, err = engine.snapshot(chain, block.NumberU64(), block.Hash(), nil, true) 1392 assert.Equal(t, 0, len(engine.governance.GetGovernanceChange())) 1393 } 1394 1395 func TestGovernance_Votes(t *testing.T) { 1396 type vote struct { 1397 key string 1398 value interface{} 1399 } 1400 type governanceItem struct { 1401 vote 1402 appliedBlockNumber uint64 // if applied block number is 0, then it checks the item on current block 1403 } 1404 type testcase struct { 1405 votes []vote 1406 expected []governanceItem 1407 } 1408 1409 testcases := []testcase{ 1410 { 1411 votes: []vote{ 1412 {"governance.governancemode", "none"}, // voted on block 1 1413 {"istanbul.committeesize", uint64(4)}, // voted on block 2 1414 {"governance.unitprice", uint64(2000000)}, // voted on block 3 1415 {"reward.mintingamount", "96000000000"}, // voted on block 4 1416 {"reward.ratio", "34/33/33"}, // voted on block 5 1417 {"reward.useginicoeff", true}, // voted on block 6 1418 {"reward.minimumstake", "5000000"}, // voted on block 7 1419 {"reward.kip82ratio", "50/50"}, // voted on block 8 1420 {"governance.deriveshaimpl", uint64(2)}, // voted on block 9 1421 }, 1422 expected: []governanceItem{ 1423 {vote{"governance.governancemode", "none"}, 6}, 1424 {vote{"istanbul.committeesize", uint64(4)}, 6}, 1425 {vote{"governance.unitprice", uint64(2000000)}, 9}, 1426 {vote{"reward.mintingamount", "96000000000"}, 9}, 1427 {vote{"reward.ratio", "34/33/33"}, 9}, 1428 {vote{"reward.useginicoeff", true}, 12}, 1429 {vote{"reward.minimumstake", "5000000"}, 12}, 1430 {vote{"reward.kip82ratio", "50/50"}, 12}, 1431 {vote{"governance.deriveshaimpl", uint64(2)}, 15}, 1432 // check governance items on current block 1433 {vote{"governance.governancemode", "none"}, 0}, 1434 {vote{"istanbul.committeesize", uint64(4)}, 0}, 1435 {vote{"governance.unitprice", uint64(2000000)}, 0}, 1436 {vote{"reward.mintingamount", "96000000000"}, 0}, 1437 {vote{"reward.ratio", "34/33/33"}, 0}, 1438 {vote{"reward.useginicoeff", true}, 0}, 1439 {vote{"reward.minimumstake", "5000000"}, 0}, 1440 {vote{"reward.kip82ratio", "50/50"}, 0}, 1441 {vote{"governance.deriveshaimpl", uint64(2)}, 0}, 1442 }, 1443 }, 1444 { 1445 votes: []vote{ 1446 {"governance.governancemode", "none"}, // voted on block 1 1447 {"governance.governancemode", "single"}, // voted on block 2 1448 {"governance.governancemode", "none"}, // voted on block 3 1449 {"governance.governancemode", "single"}, // voted on block 4 1450 {"governance.governancemode", "none"}, // voted on block 5 1451 {"governance.governancemode", "single"}, // voted on block 6 1452 {"governance.governancemode", "none"}, // voted on block 7 1453 {"governance.governancemode", "single"}, // voted on block 8 1454 {"governance.governancemode", "none"}, // voted on block 9 1455 }, 1456 expected: []governanceItem{ 1457 {vote{"governance.governancemode", "single"}, 6}, 1458 {vote{"governance.governancemode", "none"}, 9}, 1459 {vote{"governance.governancemode", "single"}, 12}, 1460 {vote{"governance.governancemode", "none"}, 15}, 1461 }, 1462 }, 1463 { 1464 votes: []vote{ 1465 {"governance.governancemode", "none"}, // voted on block 1 1466 {"istanbul.committeesize", uint64(4)}, // voted on block 2 1467 {"governance.unitprice", uint64(2000000)}, // voted on block 3 1468 {"governance.governancemode", "single"}, // voted on block 4 1469 {"istanbul.committeesize", uint64(22)}, // voted on block 5 1470 {"governance.unitprice", uint64(2)}, // voted on block 6 1471 {"governance.governancemode", "none"}, // voted on block 7 1472 }, 1473 expected: []governanceItem{ 1474 // governance mode for all blocks 1475 {vote{"governance.governancemode", "single"}, 1}, 1476 {vote{"governance.governancemode", "single"}, 2}, 1477 {vote{"governance.governancemode", "single"}, 3}, 1478 {vote{"governance.governancemode", "single"}, 4}, 1479 {vote{"governance.governancemode", "single"}, 5}, 1480 {vote{"governance.governancemode", "none"}, 6}, 1481 {vote{"governance.governancemode", "none"}, 7}, 1482 {vote{"governance.governancemode", "none"}, 8}, 1483 {vote{"governance.governancemode", "single"}, 9}, 1484 {vote{"governance.governancemode", "single"}, 10}, 1485 {vote{"governance.governancemode", "single"}, 11}, 1486 {vote{"governance.governancemode", "none"}, 12}, 1487 {vote{"governance.governancemode", "none"}, 13}, 1488 {vote{"governance.governancemode", "none"}, 14}, 1489 {vote{"governance.governancemode", "none"}, 0}, // check on current 1490 1491 // committee size for all blocks 1492 {vote{"istanbul.committeesize", uint64(21)}, 1}, 1493 {vote{"istanbul.committeesize", uint64(21)}, 2}, 1494 {vote{"istanbul.committeesize", uint64(21)}, 3}, 1495 {vote{"istanbul.committeesize", uint64(21)}, 4}, 1496 {vote{"istanbul.committeesize", uint64(21)}, 5}, 1497 {vote{"istanbul.committeesize", uint64(4)}, 6}, 1498 {vote{"istanbul.committeesize", uint64(4)}, 7}, 1499 {vote{"istanbul.committeesize", uint64(4)}, 8}, 1500 {vote{"istanbul.committeesize", uint64(22)}, 9}, 1501 {vote{"istanbul.committeesize", uint64(22)}, 10}, 1502 {vote{"istanbul.committeesize", uint64(22)}, 11}, 1503 {vote{"istanbul.committeesize", uint64(22)}, 12}, 1504 {vote{"istanbul.committeesize", uint64(22)}, 13}, 1505 {vote{"istanbul.committeesize", uint64(22)}, 14}, 1506 {vote{"istanbul.committeesize", uint64(22)}, 0}, // check on current 1507 1508 // unitprice for all blocks 1509 {vote{"governance.unitprice", uint64(1)}, 1}, 1510 {vote{"governance.unitprice", uint64(1)}, 2}, 1511 {vote{"governance.unitprice", uint64(1)}, 3}, 1512 {vote{"governance.unitprice", uint64(1)}, 4}, 1513 {vote{"governance.unitprice", uint64(1)}, 5}, 1514 {vote{"governance.unitprice", uint64(1)}, 6}, 1515 {vote{"governance.unitprice", uint64(1)}, 7}, 1516 {vote{"governance.unitprice", uint64(1)}, 8}, 1517 {vote{"governance.unitprice", uint64(2000000)}, 9}, 1518 {vote{"governance.unitprice", uint64(2000000)}, 10}, 1519 {vote{"governance.unitprice", uint64(2000000)}, 11}, 1520 {vote{"governance.unitprice", uint64(2)}, 12}, 1521 {vote{"governance.unitprice", uint64(2)}, 13}, 1522 {vote{"governance.unitprice", uint64(2)}, 14}, 1523 {vote{"governance.unitprice", uint64(2)}, 0}, // check on current 1524 }, 1525 }, 1526 { 1527 votes: []vote{ 1528 {}, // voted on block 1 1529 {"kip71.lowerboundbasefee", uint64(750000000000)}, // voted on block 2 1530 {}, // voted on block 3 1531 {}, // voted on block 4 1532 {"kip71.lowerboundbasefee", uint64(25000000000)}, // voted on block 5 1533 }, 1534 expected: []governanceItem{ 1535 {vote{"kip71.lowerboundbasefee", uint64(750000000000)}, 6}, 1536 {vote{"kip71.lowerboundbasefee", uint64(25000000000)}, 9}, 1537 }, 1538 }, 1539 { 1540 votes: []vote{ 1541 {}, // voted on block 1 1542 {"kip71.upperboundbasefee", uint64(750000000000)}, // voted on block 2 1543 {}, // voted on block 3 1544 {}, // voted on block 4 1545 {"kip71.upperboundbasefee", uint64(25000000000)}, // voted on block 5 1546 }, 1547 expected: []governanceItem{ 1548 {vote{"kip71.upperboundbasefee", uint64(750000000000)}, 6}, 1549 {vote{"kip71.upperboundbasefee", uint64(25000000000)}, 9}, 1550 }, 1551 }, 1552 { 1553 votes: []vote{ 1554 {}, // voted on block 1 1555 {"kip71.maxblockgasusedforbasefee", uint64(840000000)}, // voted on block 2 1556 {}, // voted on block 3 1557 {}, // voted on block 4 1558 {"kip71.maxblockgasusedforbasefee", uint64(84000000)}, // voted on block 5 1559 }, 1560 expected: []governanceItem{ 1561 {vote{"kip71.maxblockgasusedforbasefee", uint64(840000000)}, 6}, 1562 {vote{"kip71.maxblockgasusedforbasefee", uint64(84000000)}, 9}, 1563 }, 1564 }, 1565 { 1566 votes: []vote{ 1567 {}, // voted on block 1 1568 {"kip71.gastarget", uint64(50000000)}, // voted on block 2 1569 {}, // voted on block 3 1570 {}, // voted on block 4 1571 {"kip71.gastarget", uint64(30000000)}, // voted on block 5 1572 }, 1573 expected: []governanceItem{ 1574 {vote{"kip71.gastarget", uint64(50000000)}, 6}, 1575 {vote{"kip71.gastarget", uint64(30000000)}, 9}, 1576 }, 1577 }, 1578 { 1579 votes: []vote{ 1580 {}, // voted on block 1 1581 {"kip71.basefeedenominator", uint64(32)}, // voted on block 2 1582 {}, // voted on block 3 1583 {}, // voted on block 4 1584 {"kip71.basefeedenominator", uint64(64)}, // voted on block 5 1585 }, 1586 expected: []governanceItem{ 1587 {vote{"kip71.basefeedenominator", uint64(32)}, 6}, 1588 {vote{"kip71.basefeedenominator", uint64(64)}, 9}, 1589 }, 1590 }, 1591 { 1592 votes: []vote{ 1593 {}, // voted on block 1 1594 {"governance.govparamcontract", common.HexToAddress("0x0000000000000000000000000000000000000000")}, // voted on block 2 1595 {}, // voted on block 3 1596 {}, // voted on block 4 1597 {"governance.govparamcontract", common.HexToAddress("0x0000000000000000000000000000000000000400")}, // voted on block 5 1598 }, 1599 expected: []governanceItem{ 1600 {vote{"governance.govparamcontract", common.HexToAddress("0x0000000000000000000000000000000000000000")}, 6}, 1601 {vote{"governance.govparamcontract", common.HexToAddress("0x0000000000000000000000000000000000000400")}, 9}, 1602 }, 1603 }, 1604 } 1605 1606 var configItems []interface{} 1607 configItems = append(configItems, proposerPolicy(params.WeightedRandom)) 1608 configItems = append(configItems, epoch(3)) 1609 configItems = append(configItems, governanceMode("single")) 1610 configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block 1611 for _, tc := range testcases { 1612 chain, engine := newBlockChain(1, configItems...) 1613 oldStakingManager := setTestStakingInfo(nil) 1614 1615 // test initial governance items 1616 assert.Equal(t, uint64(3), engine.governance.CurrentParams().Epoch()) 1617 assert.Equal(t, "single", engine.governance.CurrentParams().GovernanceModeStr()) 1618 assert.Equal(t, uint64(21), engine.governance.CurrentParams().CommitteeSize()) 1619 assert.Equal(t, uint64(1), engine.governance.CurrentParams().UnitPrice()) 1620 assert.Equal(t, "0", engine.governance.CurrentParams().MintingAmountStr()) 1621 assert.Equal(t, "100/0/0", engine.governance.CurrentParams().Ratio()) 1622 assert.Equal(t, false, engine.governance.CurrentParams().UseGiniCoeff()) 1623 assert.Equal(t, "2000000", engine.governance.CurrentParams().MinimumStakeStr()) 1624 1625 // add votes and insert voted blocks 1626 var ( 1627 previousBlock, currentBlock *types.Block = nil, chain.Genesis() 1628 err error 1629 ) 1630 1631 for _, v := range tc.votes { 1632 engine.governance.AddVote(v.key, v.value) 1633 previousBlock = currentBlock 1634 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 1635 _, err = chain.InsertChain(types.Blocks{currentBlock}) 1636 assert.NoError(t, err) 1637 } 1638 1639 // insert blocks until the vote is applied 1640 for i := 0; i < 6; i++ { 1641 previousBlock = currentBlock 1642 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 1643 _, err = chain.InsertChain(types.Blocks{currentBlock}) 1644 assert.NoError(t, err) 1645 } 1646 1647 for _, item := range tc.expected { 1648 blockNumber := item.appliedBlockNumber 1649 if blockNumber == 0 { 1650 blockNumber = chain.CurrentBlock().NumberU64() 1651 } 1652 _, items, err := engine.governance.ReadGovernance(blockNumber) 1653 assert.NoError(t, err) 1654 assert.Equal(t, item.value, items[item.key]) 1655 } 1656 1657 reward.SetTestStakingManager(oldStakingManager) 1658 engine.Stop() 1659 } 1660 } 1661 1662 func TestGovernance_ReaderEngine(t *testing.T) { 1663 // Test that ReaderEngine (CurrentParams(), EffectiveParams(), UpdateParams()) works. 1664 type vote = map[string]interface{} 1665 type expected = map[string]interface{} // expected (subset of) governance items 1666 type testcase struct { 1667 length int // total number of blocks to simulate 1668 votes map[int]vote 1669 expected map[int]expected 1670 } 1671 1672 testcases := []testcase{ 1673 { 1674 8, 1675 map[int]vote{ 1676 1: {"governance.unitprice": uint64(17)}, 1677 }, 1678 map[int]expected{ 1679 0: {"governance.unitprice": uint64(1)}, 1680 1: {"governance.unitprice": uint64(1)}, 1681 2: {"governance.unitprice": uint64(1)}, 1682 3: {"governance.unitprice": uint64(1)}, 1683 4: {"governance.unitprice": uint64(1)}, 1684 5: {"governance.unitprice": uint64(1)}, 1685 6: {"governance.unitprice": uint64(1)}, 1686 7: {"governance.unitprice": uint64(17)}, 1687 8: {"governance.unitprice": uint64(17)}, 1688 }, 1689 }, 1690 } 1691 1692 var configItems []interface{} 1693 configItems = append(configItems, proposerPolicy(params.WeightedRandom)) 1694 configItems = append(configItems, proposerUpdateInterval(1)) 1695 configItems = append(configItems, epoch(3)) 1696 configItems = append(configItems, governanceMode("single")) 1697 configItems = append(configItems, minimumStake(new(big.Int).SetUint64(4000000))) 1698 configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0))) 1699 configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block 1700 stakes := []uint64{4000000, 4000000, 4000000, 4000000} 1701 1702 for _, tc := range testcases { 1703 // Create test blockchain 1704 chain, engine := newBlockChain(4, configItems...) 1705 oldStakingManager := setTestStakingInfo(stakes) 1706 1707 var previousBlock, currentBlock *types.Block = nil, chain.Genesis() 1708 1709 // Create blocks with votes 1710 for num := 0; num <= tc.length; num++ { 1711 // Validate current params with CurrentParams() and CurrentSetCopy(). 1712 // Check that both returns the expected result. 1713 assertMapSubset(t, tc.expected[num+1], engine.governance.CurrentParams().StrMap()) 1714 assertMapSubset(t, tc.expected[num+1], engine.governance.CurrentSetCopy()) 1715 1716 // Place a vote if a vote is scheduled in upcoming block 1717 // Note that we're building (head+1)'th block here. 1718 for k, v := range tc.votes[num+1] { 1719 ok := engine.governance.AddVote(k, v) 1720 assert.True(t, ok) 1721 } 1722 1723 // Create a block 1724 previousBlock = currentBlock 1725 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 1726 _, err := chain.InsertChain(types.Blocks{currentBlock}) 1727 assert.NoError(t, err) 1728 1729 // Load parameters for the next block 1730 err = engine.governance.UpdateParams(currentBlock.NumberU64()) 1731 assert.NoError(t, err) 1732 } 1733 1734 // Validate historic parameters with EffectiveParams() and ReadGovernance(). 1735 // Check that both returns the expected result. 1736 for num := 0; num <= tc.length; num++ { 1737 pset, err := engine.governance.EffectiveParams(uint64(num)) 1738 assert.NoError(t, err) 1739 assertMapSubset(t, tc.expected[num], pset.StrMap()) 1740 1741 _, items, err := engine.governance.ReadGovernance(uint64(num)) 1742 assert.NoError(t, err) 1743 assertMapSubset(t, tc.expected[num+1], items) 1744 } 1745 1746 reward.SetTestStakingManager(oldStakingManager) 1747 engine.Stop() 1748 } 1749 } 1750 1751 func TestChainConfig_UpdateAfterVotes(t *testing.T) { 1752 type vote struct { 1753 key string 1754 value interface{} 1755 } 1756 type testcase struct { 1757 voting vote 1758 expected vote 1759 } 1760 1761 testcases := []testcase{ 1762 { 1763 voting: vote{"kip71.lowerboundbasefee", uint64(20000000000)}, // voted on block 1 1764 expected: vote{"kip71.lowerboundbasefee", uint64(20000000000)}, 1765 }, 1766 { 1767 voting: vote{"kip71.upperboundbasefee", uint64(500000000000)}, // voted on block 1 1768 expected: vote{"kip71.upperboundbasefee", uint64(500000000000)}, 1769 }, 1770 { 1771 voting: vote{"kip71.maxblockgasusedforbasefee", uint64(100000000)}, // voted on block 1 1772 expected: vote{"kip71.maxblockgasusedforbasefee", uint64(100000000)}, 1773 }, 1774 { 1775 voting: vote{"kip71.gastarget", uint64(50000000)}, // voted on block 1 1776 expected: vote{"kip71.gastarget", uint64(50000000)}, 1777 }, 1778 { 1779 voting: vote{"kip71.basefeedenominator", uint64(32)}, // voted on block 1 1780 expected: vote{"kip71.basefeedenominator", uint64(32)}, 1781 }, 1782 } 1783 1784 var configItems []interface{} 1785 configItems = append(configItems, epoch(3)) 1786 configItems = append(configItems, governanceMode("single")) 1787 configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block 1788 for _, tc := range testcases { 1789 chain, engine := newBlockChain(1, configItems...) 1790 1791 // test initial governance items 1792 assert.Equal(t, uint64(25000000000), chain.Config().Governance.KIP71.LowerBoundBaseFee) 1793 assert.Equal(t, uint64(750000000000), chain.Config().Governance.KIP71.UpperBoundBaseFee) 1794 assert.Equal(t, uint64(20), chain.Config().Governance.KIP71.BaseFeeDenominator) 1795 assert.Equal(t, uint64(60000000), chain.Config().Governance.KIP71.MaxBlockGasUsedForBaseFee) 1796 assert.Equal(t, uint64(30000000), chain.Config().Governance.KIP71.GasTarget) 1797 1798 // add votes and insert voted blocks 1799 var ( 1800 previousBlock, currentBlock *types.Block = nil, chain.Genesis() 1801 err error 1802 ) 1803 1804 engine.governance.SetBlockchain(chain) 1805 engine.governance.AddVote(tc.voting.key, tc.voting.value) 1806 previousBlock = currentBlock 1807 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 1808 _, err = chain.InsertChain(types.Blocks{currentBlock}) 1809 assert.NoError(t, err) 1810 1811 // insert blocks until the vote is applied 1812 for i := 0; i < 6; i++ { 1813 previousBlock = currentBlock 1814 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 1815 _, err = chain.InsertChain(types.Blocks{currentBlock}) 1816 assert.NoError(t, err) 1817 } 1818 1819 govConfig := chain.Config().Governance 1820 switch tc.expected.key { 1821 case "kip71.lowerboundbasefee": 1822 assert.Equal(t, tc.expected.value, govConfig.KIP71.LowerBoundBaseFee) 1823 case "kip71.upperboundbasefee": 1824 assert.Equal(t, tc.expected.value, govConfig.KIP71.UpperBoundBaseFee) 1825 case "kip71.gastarget": 1826 assert.Equal(t, tc.expected.value, govConfig.KIP71.GasTarget) 1827 case "kip71.maxblockgasusedforbasefee": 1828 assert.Equal(t, tc.expected.value, govConfig.KIP71.MaxBlockGasUsedForBaseFee) 1829 case "kip71.basefeedenominator": 1830 assert.Equal(t, tc.expected.value, govConfig.KIP71.BaseFeeDenominator) 1831 default: 1832 assert.Error(t, nil) 1833 } 1834 } 1835 } 1836 1837 func TestChainConfig_ReadFromDBAfterVotes(t *testing.T) { 1838 type vote struct { 1839 key string 1840 value interface{} 1841 } 1842 type testcase struct { 1843 voting vote 1844 expected vote 1845 } 1846 1847 testcases := []testcase{ 1848 { 1849 voting: vote{"kip71.lowerboundbasefee", uint64(20000000000)}, // voted on block 1 1850 expected: vote{"kip71.lowerboundbasefee", uint64(20000000000)}, 1851 }, 1852 { 1853 voting: vote{"kip71.upperboundbasefee", uint64(500000000000)}, // voted on block 1 1854 expected: vote{"kip71.upperboundbasefee", uint64(500000000000)}, 1855 }, 1856 { 1857 voting: vote{"kip71.maxblockgasusedforbasefee", uint64(100000000)}, // voted on block 1 1858 expected: vote{"kip71.maxblockgasusedforbasefee", uint64(100000000)}, 1859 }, 1860 { 1861 voting: vote{"kip71.gastarget", uint64(50000000)}, // voted on block 1 1862 expected: vote{"kip71.gastarget", uint64(50000000)}, 1863 }, 1864 { 1865 voting: vote{"kip71.basefeedenominator", uint64(32)}, // voted on block 1 1866 expected: vote{"kip71.basefeedenominator", uint64(32)}, 1867 }, 1868 } 1869 1870 var configItems []interface{} 1871 configItems = append(configItems, proposerPolicy(params.WeightedRandom)) 1872 configItems = append(configItems, epoch(3)) 1873 configItems = append(configItems, governanceMode("single")) 1874 configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block 1875 for _, tc := range testcases { 1876 chain, engine := newBlockChain(1, configItems...) 1877 oldStakingManager := setTestStakingInfo(nil) 1878 1879 // test initial governance items 1880 assert.Equal(t, uint64(25000000000), chain.Config().Governance.KIP71.LowerBoundBaseFee) 1881 assert.Equal(t, uint64(750000000000), chain.Config().Governance.KIP71.UpperBoundBaseFee) 1882 assert.Equal(t, uint64(20), chain.Config().Governance.KIP71.BaseFeeDenominator) 1883 assert.Equal(t, uint64(60000000), chain.Config().Governance.KIP71.MaxBlockGasUsedForBaseFee) 1884 assert.Equal(t, uint64(30000000), chain.Config().Governance.KIP71.GasTarget) 1885 1886 // add votes and insert voted blocks 1887 var ( 1888 previousBlock, currentBlock *types.Block = nil, chain.Genesis() 1889 err error 1890 ) 1891 1892 engine.governance.SetBlockchain(chain) 1893 engine.governance.AddVote(tc.voting.key, tc.voting.value) 1894 previousBlock = currentBlock 1895 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 1896 _, err = chain.InsertChain(types.Blocks{currentBlock}) 1897 assert.NoError(t, err) 1898 1899 // insert blocks until the vote is applied 1900 for i := 0; i < params.CheckpointInterval; i++ { 1901 previousBlock = currentBlock 1902 currentBlock = makeBlockWithSeal(chain, engine, previousBlock) 1903 _, err = chain.InsertChain(types.Blocks{currentBlock}) 1904 assert.NoError(t, err) 1905 } 1906 1907 switch tc.expected.key { 1908 case "kip71.lowerboundbasefee": 1909 assert.Equal(t, tc.expected.value, chain.Config().Governance.KIP71.LowerBoundBaseFee) 1910 case "kip71.upperboundbasefee": 1911 assert.Equal(t, tc.expected.value, chain.Config().Governance.KIP71.UpperBoundBaseFee) 1912 case "kip71.gastarget": 1913 assert.Equal(t, tc.expected.value, chain.Config().Governance.KIP71.GasTarget) 1914 case "kip71.maxblockgasusedforbasefee": 1915 assert.Equal(t, tc.expected.value, chain.Config().Governance.KIP71.MaxBlockGasUsedForBaseFee) 1916 case "kip71.basefeedenominator": 1917 assert.Equal(t, tc.expected.value, chain.Config().Governance.KIP71.BaseFeeDenominator) 1918 default: 1919 assert.Error(t, nil) 1920 } 1921 1922 reward.SetTestStakingManager(oldStakingManager) 1923 engine.Stop() 1924 } 1925 }