github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/pbft/backend/pbft_test.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package backend 18 19 import ( 20 "bytes" 21 "crypto/ecdsa" 22 "math/big" 23 "reflect" 24 "testing" 25 "time" 26 27 "github.com/bigzoro/my_simplechain/common" 28 "github.com/bigzoro/my_simplechain/common/hexutil" 29 "github.com/bigzoro/my_simplechain/consensus" 30 "github.com/bigzoro/my_simplechain/consensus/pbft" 31 "github.com/bigzoro/my_simplechain/core" 32 "github.com/bigzoro/my_simplechain/core/rawdb" 33 "github.com/bigzoro/my_simplechain/core/types" 34 "github.com/bigzoro/my_simplechain/core/vm" 35 "github.com/bigzoro/my_simplechain/crypto" 36 "github.com/bigzoro/my_simplechain/params" 37 "github.com/bigzoro/my_simplechain/rlp" 38 ) 39 40 // in this test, we can set n to 1, and it means we can process Istanbul and commit a 41 // block by one node. Otherwise, if n is larger than 1, we have to generate 42 // other fake events to process Istanbul. 43 func newBlockChain(n int) (*core.BlockChain, *backend) { 44 genesis, nodeKeys := getGenesisAndKeys(n) 45 memDB := rawdb.NewMemoryDatabase() 46 config := pbft.DefaultConfig 47 // Use the first key as private key 48 b, _ := New(config, nodeKeys[0], memDB).(*backend) 49 genesis.MustCommit(memDB) 50 blockchain, err := core.NewBlockChain(memDB, nil, genesis.Config, b, vm.Config{}, nil) 51 if err != nil { 52 panic(err) 53 } 54 b.Start(blockchain, blockchain.CurrentBlock, blockchain.HasBadBlock) 55 snap, err := b.snapshot(blockchain, 0, common.Hash{}, nil) 56 if err != nil { 57 panic(err) 58 } 59 if snap == nil { 60 panic("failed to get snapshot") 61 } 62 proposerAddr := snap.ValSet.GetProposer().Address() 63 64 // find proposer key 65 for _, key := range nodeKeys { 66 addr := crypto.PubkeyToAddress(key.PublicKey) 67 if addr.String() == proposerAddr.String() { 68 b.privateKey = key 69 b.address = addr 70 } 71 } 72 73 b.SetSealer(testSealer{}) 74 75 return blockchain, b 76 } 77 78 func getGenesisAndKeys(n int) (*core.Genesis, []*ecdsa.PrivateKey) { 79 // Setup validators 80 var nodeKeys = make([]*ecdsa.PrivateKey, n) 81 var addrs = make([]common.Address, n) 82 for i := 0; i < n; i++ { 83 nodeKeys[i], _ = crypto.GenerateKey() 84 addrs[i] = crypto.PubkeyToAddress(nodeKeys[i].PublicKey) 85 } 86 87 // generate genesis block 88 genesis := core.DefaultGenesisBlock() 89 genesis.Config = params.TestChainConfig 90 // force enable Istanbul engine 91 genesis.Config.Istanbul = ¶ms.IstanbulConfig{} 92 genesis.Config.Ethash = nil 93 genesis.Difficulty = defaultDifficulty 94 genesis.Nonce = emptyNonce.Uint64() 95 genesis.Mixhash = types.PbftDigest 96 97 appendValidators(genesis, addrs) 98 return genesis, nodeKeys 99 } 100 101 func appendValidators(genesis *core.Genesis, addrs []common.Address) { 102 103 if len(genesis.ExtraData) < types.ByzantineExtraVanity { 104 genesis.ExtraData = append(genesis.ExtraData, bytes.Repeat([]byte{0x00}, types.ByzantineExtraVanity)...) 105 } 106 genesis.ExtraData = genesis.ExtraData[:types.ByzantineExtraVanity] 107 108 ist := &types.ByzantineExtra{ 109 Validators: addrs, 110 Seal: []byte{}, 111 CommittedSeal: [][]byte{}, 112 } 113 114 istPayload, err := rlp.EncodeToBytes(&ist) 115 if err != nil { 116 panic("failed to encode istanbul extra") 117 } 118 genesis.ExtraData = append(genesis.ExtraData, istPayload...) 119 } 120 121 func makeHeader(parent *types.Block, config *pbft.Config) *types.Header { 122 header := &types.Header{ 123 ParentHash: parent.Hash(), 124 Number: parent.Number().Add(parent.Number(), common.Big1), 125 GasLimit: core.CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit()), 126 GasUsed: 0, 127 Extra: parent.Extra(), 128 Time: parent.Time() + config.BlockPeriod, 129 Difficulty: defaultDifficulty, 130 } 131 return header 132 } 133 134 func makeBlock(chain *core.BlockChain, engine *backend, parent *types.Block) *types.Block { 135 block := makeBlockWithoutSeal(chain, engine, parent) 136 stopCh := make(chan struct{}) 137 resultCh := make(chan *types.Block, 10) 138 go engine.Seal(chain, block, resultCh, stopCh) 139 blk := <-resultCh 140 return blk 141 } 142 143 func makeBlockWithoutSeal(chain *core.BlockChain, engine *backend, parent *types.Block) *types.Block { 144 header := makeHeader(parent, engine.config) 145 engine.Prepare(chain, header) 146 state, _ := chain.StateAt(parent.Root()) 147 block, _ := engine.FinalizeAndAssemble(chain, header, state, nil, nil, nil) 148 return block 149 } 150 151 func TestPrepare(t *testing.T) { 152 chain, engine := newBlockChain(1) 153 header := makeHeader(chain.Genesis(), engine.config) 154 err := engine.Prepare(chain, header) 155 if err != nil { 156 t.Errorf("error mismatch: have %v, want nil", err) 157 } 158 header.ParentHash = common.BytesToHash([]byte("1234567890")) 159 err = engine.Prepare(chain, header) 160 if err != consensus.ErrUnknownAncestor { 161 t.Errorf("error mismatch: have %v, want %v", err, consensus.ErrUnknownAncestor) 162 } 163 } 164 165 func TestSealStopChannel(t *testing.T) { 166 chain, engine := newBlockChain(4) 167 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 168 stop := make(chan struct{}, 1) 169 eventSub := engine.EventMux().Subscribe(pbft.RequestEvent{}) 170 eventLoop := func() { 171 ev := <-eventSub.Chan() 172 _, ok := ev.Data.(pbft.RequestEvent) 173 if !ok { 174 t.Errorf("unexpected event comes: %v", reflect.TypeOf(ev.Data)) 175 } 176 stop <- struct{}{} 177 eventSub.Unsubscribe() 178 } 179 go eventLoop() 180 resultCh := make(chan *types.Block, 10) 181 go func() { 182 err := engine.Seal(chain, block, resultCh, stop) 183 if err != nil { 184 t.Errorf("error mismatch: have %v, want nil", err) 185 } 186 }() 187 188 finalBlock := <-resultCh 189 if finalBlock != nil { 190 t.Errorf("block mismatch: have %v, want nil", finalBlock) 191 } 192 } 193 194 func TestSealCommittedOtherHash(t *testing.T) { 195 chain, engine := newBlockChain(4) 196 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 197 otherBlock := makeBlockWithoutSeal(chain, engine, block) 198 expectedCommittedSeal := append([]byte{1, 2, 3}, bytes.Repeat([]byte{0x00}, types.ByzantineExtraSeal-3)...) 199 200 eventSub := engine.EventMux().Subscribe(pbft.RequestEvent{}) 201 blockOutputChannel := make(chan *types.Block) 202 stopChannel := make(chan struct{}) 203 204 go func() { 205 ev := <-eventSub.Chan() 206 if _, ok := ev.Data.(pbft.RequestEvent); !ok { 207 t.Errorf("unexpected event comes: %v", reflect.TypeOf(ev.Data)) 208 } 209 if err := engine.Commit(otherBlock, [][]byte{expectedCommittedSeal}); err != nil { 210 t.Error(err.Error()) 211 } 212 eventSub.Unsubscribe() 213 }() 214 215 go func() { 216 if err := engine.Seal(chain, block, blockOutputChannel, stopChannel); err != nil { 217 t.Error(err.Error()) 218 } 219 }() 220 221 select { 222 case <-blockOutputChannel: 223 t.Error("Wrong block found!") 224 default: 225 //no block found, stop the sealing 226 close(stopChannel) 227 } 228 229 output := <-blockOutputChannel 230 if output != nil { 231 t.Error("Block not nil!") 232 } 233 } 234 235 func TestSealCommitted(t *testing.T) { 236 chain, engine := newBlockChain(1) 237 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 238 expectedBlock, _ := engine.signBlock(engine.chain.GetHeader(block.ParentHash(), block.NumberU64()-1), block) 239 resultCh := make(chan *types.Block, 10) 240 go func() { 241 err := engine.Seal(chain, block, resultCh, make(chan struct{})) 242 243 if err != nil { 244 t.Errorf("error mismatch: have %v, want %v", err, expectedBlock) 245 } 246 }() 247 248 finalBlock := <-resultCh 249 if finalBlock.Hash() != expectedBlock.Hash() { 250 t.Errorf("hash mismatch: have %v, want %v", finalBlock.Hash(), expectedBlock.Hash()) 251 } 252 } 253 254 func TestVerifyHeader(t *testing.T) { 255 chain, engine := newBlockChain(1) 256 257 // errEmptyCommittedSeals case 258 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 259 block, _ = engine.signBlock(chain.Genesis().Header(), block) 260 err := engine.VerifyHeader(chain, block.Header(), true) 261 if err != errEmptyCommittedSeals { 262 t.Errorf("error mismatch: have %v, want %v", err, errEmptyCommittedSeals) 263 } 264 265 // short extra data 266 header := block.Header() 267 header.Extra = []byte{} 268 err = engine.VerifyHeader(chain, header, false) 269 if err != errInvalidExtraDataFormat { 270 t.Errorf("error mismatch: have %v, want %v", err, errInvalidExtraDataFormat) 271 } 272 // incorrect extra format 273 header.Extra = []byte("0000000000000000000000000000000012300000000000000000000000000000000000000000000000000000000000000000") 274 err = engine.VerifyHeader(chain, header, false) 275 if err != errInvalidExtraDataFormat { 276 t.Errorf("error mismatch: have %v, want %v", err, errInvalidExtraDataFormat) 277 } 278 279 // non zero MixDigest 280 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 281 header = block.Header() 282 header.MixDigest = common.BytesToHash([]byte("123456789")) 283 err = engine.VerifyHeader(chain, header, false) 284 if err != errInvalidMixDigest { 285 t.Errorf("error mismatch: have %v, want %v", err, errInvalidMixDigest) 286 } 287 288 // invalid uncles hash 289 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 290 header = block.Header() 291 header.UncleHash = common.BytesToHash([]byte("123456789")) 292 err = engine.VerifyHeader(chain, header, false) 293 if err != errInvalidUncleHash { 294 t.Errorf("error mismatch: have %v, want %v", err, errInvalidUncleHash) 295 } 296 297 // invalid difficulty 298 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 299 header = block.Header() 300 header.Difficulty = big.NewInt(2) 301 err = engine.VerifyHeader(chain, header, false) 302 if err != errInvalidDifficulty { 303 t.Errorf("error mismatch: have %v, want %v", err, errInvalidDifficulty) 304 } 305 306 // invalid timestamp 307 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 308 header = block.Header() 309 header.Time = chain.Genesis().Time() + engine.config.BlockPeriod - 1 310 err = engine.VerifyHeader(chain, header, false) 311 if err != errInvalidTimestamp { 312 t.Errorf("error mismatch: have %v, want %v", err, errInvalidTimestamp) 313 } 314 315 // future block 316 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 317 header = block.Header() 318 header.Time = uint64(now().Unix()) + 10 319 err = engine.VerifyHeader(chain, header, false) 320 if err != consensus.ErrFutureBlock { 321 t.Errorf("error mismatch: have %v, want %v", err, consensus.ErrFutureBlock) 322 } 323 324 // invalid nonce 325 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 326 header = block.Header() 327 copy(header.Nonce[:], hexutil.MustDecode("0x111111111111")) 328 header.Number = big.NewInt(int64(engine.config.Epoch)) 329 err = engine.VerifyHeader(chain, header, false) 330 if err != errInvalidNonce { 331 t.Errorf("error mismatch: have %v, want %v", err, errInvalidNonce) 332 } 333 } 334 335 func TestVerifySeal(t *testing.T) { 336 chain, engine := newBlockChain(1) 337 genesis := chain.Genesis() 338 // cannot verify genesis 339 err := engine.VerifySeal(chain, genesis.Header()) 340 if err != errUnknownBlock { 341 t.Errorf("error mismatch: have %v, want %v", err, errUnknownBlock) 342 } 343 344 block := makeBlock(chain, engine, genesis) 345 // change block content 346 header := block.Header() 347 header.Number = big.NewInt(4) 348 block1 := block.WithSeal(header) 349 err = engine.VerifySeal(chain, block1.Header()) 350 if err != errUnauthorized { 351 t.Errorf("error mismatch: have %v, want %v", err, errUnauthorized) 352 } 353 354 // unauthorized users but still can get correct signer address 355 engine.privateKey, _ = crypto.GenerateKey() 356 err = engine.VerifySeal(chain, block.Header()) 357 if err != nil { 358 t.Errorf("error mismatch: have %v, want nil", err) 359 } 360 } 361 362 func TestVerifyHeaders(t *testing.T) { 363 chain, engine := newBlockChain(1) 364 genesis := chain.Genesis() 365 366 // success case 367 headers := []*types.Header{} 368 blocks := []*types.Block{} 369 size := 100 370 371 for i := 0; i < size; i++ { 372 var b *types.Block 373 if i == 0 { 374 b = makeBlockWithoutSeal(chain, engine, genesis) 375 b, _ = engine.signBlock(genesis.Header(), b) 376 } else { 377 b = makeBlockWithoutSeal(chain, engine, blocks[i-1]) 378 b, _ = engine.signBlock(blocks[i-1].Header(), b) 379 } 380 blocks = append(blocks, b) 381 headers = append(headers, blocks[i].Header()) 382 } 383 now = func() time.Time { 384 return time.Unix(int64(headers[size-1].Time), 0) 385 } 386 _, results := engine.VerifyHeaders(chain, headers, nil) 387 const timeoutDura = 2 * time.Second 388 timeout := time.NewTimer(timeoutDura) 389 index := 0 390 OUT1: 391 for { 392 select { 393 case err := <-results: 394 if err != nil { 395 if err != errEmptyCommittedSeals && err != errInvalidCommittedSeals && err != consensus.ErrUnknownAncestor { 396 t.Errorf("error mismatch: have %v, want errEmptyCommittedSeals|errInvalidCommittedSeals|ErrUnknownAncestor", err) 397 break OUT1 398 } 399 } 400 index++ 401 if index == size { 402 break OUT1 403 } 404 case <-timeout.C: 405 break OUT1 406 } 407 } 408 // abort cases 409 _, results = engine.VerifyHeaders(chain, headers, nil) 410 timeout = time.NewTimer(timeoutDura) 411 OUT2: 412 for { 413 select { 414 case err := <-results: 415 if err != nil { 416 if err != errEmptyCommittedSeals && err != errInvalidCommittedSeals && err != consensus.ErrUnknownAncestor { 417 t.Errorf("error mismatch: have %v, want errEmptyCommittedSeals|errInvalidCommittedSeals|ErrUnknownAncestor", err) 418 break OUT2 419 } 420 } 421 case <-timeout.C: 422 break OUT2 423 } 424 } 425 // error header cases 426 headers[2].Number = big.NewInt(100) 427 _, results = engine.VerifyHeaders(chain, headers, nil) 428 timeout = time.NewTimer(timeoutDura) 429 index = 0 430 errors := 0 431 expectedErrors := 0 432 OUT3: 433 for { 434 select { 435 case err := <-results: 436 if err != nil { 437 if err != errEmptyCommittedSeals && err != errInvalidCommittedSeals && err != consensus.ErrUnknownAncestor { 438 errors++ 439 } 440 } 441 index++ 442 if index == size { 443 if errors != expectedErrors { 444 t.Errorf("error mismatch: have %v, want %v", errors, expectedErrors) 445 } 446 break OUT3 447 } 448 case <-timeout.C: 449 break OUT3 450 } 451 } 452 } 453 454 func TestPrepareExtra(t *testing.T) { 455 validators := make([]common.Address, 4) 456 validators[0] = common.BytesToAddress(hexutil.MustDecode("0x44add0ec310f115a0e603b2d7db9f067778eaf8a")) 457 validators[1] = common.BytesToAddress(hexutil.MustDecode("0x294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212")) 458 validators[2] = common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6")) 459 validators[3] = common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440")) 460 461 vanity := make([]byte, types.ByzantineExtraVanity) 462 expectedResult := append(vanity, hexutil.MustDecode("0xf858f8549444add0ec310f115a0e603b2d7db9f067778eaf8a94294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212946beaaed781d2d2ab6350f5c4566a2c6eaac407a6948be76812f765c24641ec63dc2852b378aba2b44080c0")...) 463 464 h := &types.Header{ 465 Extra: vanity, 466 } 467 468 payload, err := prepareExtra(h, validators) 469 if err != nil { 470 t.Errorf("error mismatch: have %v, want: nil", err) 471 } 472 if !reflect.DeepEqual(payload, expectedResult) { 473 t.Errorf("payload mismatch: have %v, want %v", payload, expectedResult) 474 } 475 476 // append useless information to extra-data 477 h.Extra = append(vanity, make([]byte, 15)...) 478 479 payload, _ = prepareExtra(h, validators) 480 if !reflect.DeepEqual(payload, expectedResult) { 481 t.Errorf("payload mismatch: have %v, want %v", payload, expectedResult) 482 } 483 } 484 485 func TestWriteSeal(t *testing.T) { 486 vanity := bytes.Repeat([]byte{0x00}, types.ByzantineExtraVanity) 487 istRawData := hexutil.MustDecode("0xf858f8549444add0ec310f115a0e603b2d7db9f067778eaf8a94294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212946beaaed781d2d2ab6350f5c4566a2c6eaac407a6948be76812f765c24641ec63dc2852b378aba2b44080c0") 488 expectedSeal := append([]byte{1, 2, 3}, bytes.Repeat([]byte{0x00}, types.ByzantineExtraSeal-3)...) 489 expectedIstExtra := &types.ByzantineExtra{ 490 Validators: []common.Address{ 491 common.BytesToAddress(hexutil.MustDecode("0x44add0ec310f115a0e603b2d7db9f067778eaf8a")), 492 common.BytesToAddress(hexutil.MustDecode("0x294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212")), 493 common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6")), 494 common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440")), 495 }, 496 Seal: expectedSeal, 497 CommittedSeal: [][]byte{}, 498 } 499 var expectedErr error 500 501 h := &types.Header{ 502 Extra: append(vanity, istRawData...), 503 } 504 505 // normal case 506 err := writeSeal(h, expectedSeal) 507 if err != expectedErr { 508 t.Errorf("error mismatch: have %v, want %v", err, expectedErr) 509 } 510 511 // verify istanbul extra-data 512 istExtra, err := types.ExtractByzantineExtra(h) 513 if err != nil { 514 t.Errorf("error mismatch: have %v, want nil", err) 515 } 516 if !reflect.DeepEqual(istExtra, expectedIstExtra) { 517 t.Errorf("extra data mismatch: have %v, want %v", istExtra, expectedIstExtra) 518 } 519 520 // invalid seal 521 unexpectedSeal := append(expectedSeal, make([]byte, 1)...) 522 err = writeSeal(h, unexpectedSeal) 523 if err != errInvalidSignature { 524 t.Errorf("error mismatch: have %v, want %v", err, errInvalidSignature) 525 } 526 } 527 528 func TestWriteCommittedSeals(t *testing.T) { 529 vanity := bytes.Repeat([]byte{0x00}, types.ByzantineExtraVanity) 530 istRawData := hexutil.MustDecode("0xf858f8549444add0ec310f115a0e603b2d7db9f067778eaf8a94294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212946beaaed781d2d2ab6350f5c4566a2c6eaac407a6948be76812f765c24641ec63dc2852b378aba2b44080c0") 531 expectedCommittedSeal := append([]byte{1, 2, 3}, bytes.Repeat([]byte{0x00}, types.ByzantineExtraSeal-3)...) 532 expectedIstExtra := &types.ByzantineExtra{ 533 Validators: []common.Address{ 534 common.BytesToAddress(hexutil.MustDecode("0x44add0ec310f115a0e603b2d7db9f067778eaf8a")), 535 common.BytesToAddress(hexutil.MustDecode("0x294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212")), 536 common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6")), 537 common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440")), 538 }, 539 Seal: []byte{}, 540 CommittedSeal: [][]byte{expectedCommittedSeal}, 541 } 542 var expectedErr error 543 544 h := &types.Header{ 545 Extra: append(vanity, istRawData...), 546 } 547 548 // normal case 549 err := writeCommittedSeals(h, [][]byte{expectedCommittedSeal}) 550 if err != expectedErr { 551 t.Errorf("error mismatch: have %v, want %v", err, expectedErr) 552 } 553 554 // verify istanbul extra-data 555 istExtra, err := types.ExtractByzantineExtra(h) 556 if err != nil { 557 t.Errorf("error mismatch: have %v, want nil", err) 558 } 559 if !reflect.DeepEqual(istExtra, expectedIstExtra) { 560 t.Errorf("extra data mismatch: have %v, want %v", istExtra, expectedIstExtra) 561 } 562 563 // invalid seal 564 unexpectedCommittedSeal := append(expectedCommittedSeal, make([]byte, 1)...) 565 err = writeCommittedSeals(h, [][]byte{unexpectedCommittedSeal}) 566 if err != errInvalidCommittedSeals { 567 t.Errorf("error mismatch: have %v, want %v", err, errInvalidCommittedSeals) 568 } 569 }