github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/consensus/istanbul/backend/engine_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 "fmt" 23 "math/big" 24 "reflect" 25 "testing" 26 "time" 27 28 bls "github.com/celo-org/bls-zexe/go" 29 "github.com/ethereum/go-ethereum/accounts" 30 "github.com/ethereum/go-ethereum/common" 31 "github.com/ethereum/go-ethereum/common/hexutil" 32 "github.com/ethereum/go-ethereum/consensus" 33 "github.com/ethereum/go-ethereum/consensus/consensustest" 34 "github.com/ethereum/go-ethereum/consensus/istanbul" 35 "github.com/ethereum/go-ethereum/contract_comm" 36 "github.com/ethereum/go-ethereum/core" 37 "github.com/ethereum/go-ethereum/core/state" 38 "github.com/ethereum/go-ethereum/core/types" 39 "github.com/ethereum/go-ethereum/core/vm" 40 "github.com/ethereum/go-ethereum/crypto" 41 blscrypto "github.com/ethereum/go-ethereum/crypto/bls" 42 "github.com/ethereum/go-ethereum/ethdb" 43 "github.com/ethereum/go-ethereum/params" 44 "github.com/ethereum/go-ethereum/rlp" 45 ) 46 47 // in this test, we can set n to 1, and it means we can process Istanbul and commit a 48 // block by one node. Otherwise, if n is larger than 1, we have to generate 49 // other fake events to process Istanbul. 50 func newBlockChain(n int, isFullChain bool) (*core.BlockChain, *Backend) { 51 genesis, nodeKeys := getGenesisAndKeys(n, isFullChain) 52 memDB := ethdb.NewMemDatabase() 53 config := istanbul.DefaultConfig 54 config.ValidatorEnodeDBPath = "" 55 config.RoundStateDBPath = "" 56 // Use the first key as private key 57 address := crypto.PubkeyToAddress(nodeKeys[0].PublicKey) 58 signerFn := func(_ accounts.Account, data []byte) ([]byte, error) { 59 return crypto.Sign(data, nodeKeys[0]) 60 } 61 62 signerBLSHashFn := func(_ accounts.Account, data []byte) (blscrypto.SerializedSignature, error) { 63 key := nodeKeys[0] 64 privateKeyBytes, err := blscrypto.ECDSAToBLS(key) 65 if err != nil { 66 return blscrypto.SerializedSignature{}, err 67 } 68 69 privateKey, err := bls.DeserializePrivateKey(privateKeyBytes) 70 if err != nil { 71 return blscrypto.SerializedSignature{}, err 72 } 73 defer privateKey.Destroy() 74 75 signature, err := privateKey.SignMessage(data, []byte{}, false) 76 if err != nil { 77 return blscrypto.SerializedSignature{}, err 78 } 79 defer signature.Destroy() 80 signatureBytes, err := signature.Serialize() 81 if err != nil { 82 return blscrypto.SerializedSignature{}, err 83 } 84 85 return blscrypto.SerializedSignatureFromBytes(signatureBytes) 86 } 87 88 signerBLSMessageFn := func(_ accounts.Account, data []byte, extraData []byte) (blscrypto.SerializedSignature, error) { 89 key := nodeKeys[0] 90 privateKeyBytes, err := blscrypto.ECDSAToBLS(key) 91 if err != nil { 92 return blscrypto.SerializedSignature{}, err 93 } 94 95 privateKey, err := bls.DeserializePrivateKey(privateKeyBytes) 96 if err != nil { 97 return blscrypto.SerializedSignature{}, err 98 } 99 defer privateKey.Destroy() 100 101 signature, err := privateKey.SignMessage(data, extraData, true) 102 if err != nil { 103 return blscrypto.SerializedSignature{}, err 104 } 105 defer signature.Destroy() 106 signatureBytes, err := signature.Serialize() 107 if err != nil { 108 return blscrypto.SerializedSignature{}, err 109 } 110 111 return blscrypto.SerializedSignatureFromBytes(signatureBytes) 112 } 113 114 b, _ := New(config, memDB).(*Backend) 115 b.Authorize(address, signerFn, signerBLSHashFn, signerBLSMessageFn) 116 117 genesis.MustCommit(memDB) 118 119 blockchain, err := core.NewBlockChain(memDB, nil, genesis.Config, b, vm.Config{}, nil) 120 if err != nil { 121 panic(err) 122 } 123 124 b.SetChain(blockchain, blockchain.CurrentBlock) 125 b.SetBroadcaster(&consensustest.MockBroadcaster{}) 126 b.SetP2PServer(consensustest.NewMockP2PServer()) 127 128 b.Start(blockchain.HasBadBlock, 129 func(parentHash common.Hash) (*state.StateDB, error) { 130 parentStateRoot := blockchain.GetHeaderByHash(parentHash).Root 131 return blockchain.StateAt(parentStateRoot) 132 }, 133 func(block *types.Block, state *state.StateDB) (types.Receipts, []*types.Log, uint64, error) { 134 return blockchain.Processor().Process(block, state, *blockchain.GetVMConfig()) 135 }, 136 func(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error { 137 return blockchain.Validator().ValidateState(block, nil, state, receipts, usedGas) 138 }) 139 snap, err := b.snapshot(blockchain, 0, common.Hash{}, nil) 140 if err != nil { 141 panic(err) 142 } 143 if snap == nil { 144 panic("failed to get snapshot") 145 } 146 proposerAddr := b.AuthorForBlock(snap.Number) 147 // proposerAddr := snap.ValSet.GetProposer().Address() 148 149 // find proposer key 150 for _, key := range nodeKeys { 151 addr := crypto.PubkeyToAddress(key.PublicKey) 152 if addr.String() == proposerAddr.String() { 153 signerFn := func(_ accounts.Account, data []byte) ([]byte, error) { 154 return crypto.Sign(data, key) 155 } 156 signerBLSHashFn := func(_ accounts.Account, data []byte) (blscrypto.SerializedSignature, error) { 157 privateKeyBytes, err := blscrypto.ECDSAToBLS(key) 158 if err != nil { 159 return blscrypto.SerializedSignature{}, err 160 } 161 162 privateKey, err := bls.DeserializePrivateKey(privateKeyBytes) 163 if err != nil { 164 return blscrypto.SerializedSignature{}, err 165 } 166 defer privateKey.Destroy() 167 168 signature, err := privateKey.SignMessage(data, []byte{}, false) 169 if err != nil { 170 return blscrypto.SerializedSignature{}, err 171 } 172 defer signature.Destroy() 173 signatureBytes, err := signature.Serialize() 174 if err != nil { 175 return blscrypto.SerializedSignature{}, err 176 } 177 178 return blscrypto.SerializedSignatureFromBytes(signatureBytes) 179 } 180 181 signerBLSMessageFn := func(_ accounts.Account, data []byte, extraData []byte) (blscrypto.SerializedSignature, error) { 182 privateKeyBytes, err := blscrypto.ECDSAToBLS(key) 183 if err != nil { 184 return blscrypto.SerializedSignature{}, err 185 } 186 187 privateKey, err := bls.DeserializePrivateKey(privateKeyBytes) 188 if err != nil { 189 return blscrypto.SerializedSignature{}, err 190 } 191 defer privateKey.Destroy() 192 193 signature, err := privateKey.SignMessage(data, extraData, true) 194 if err != nil { 195 return blscrypto.SerializedSignature{}, err 196 } 197 defer signature.Destroy() 198 signatureBytes, err := signature.Serialize() 199 if err != nil { 200 return blscrypto.SerializedSignature{}, err 201 } 202 203 return blscrypto.SerializedSignatureFromBytes(signatureBytes) 204 } 205 206 b.Authorize(address, signerFn, signerBLSHashFn, signerBLSMessageFn) 207 break 208 } 209 } 210 211 contract_comm.SetInternalEVMHandler(blockchain) 212 213 return blockchain, b 214 } 215 216 func getGenesisAndKeys(n int, isFullChain bool) (*core.Genesis, []*ecdsa.PrivateKey) { 217 // Setup validators 218 var nodeKeys = make([]*ecdsa.PrivateKey, n) 219 validators := make([]istanbul.ValidatorData, n) 220 for i := 0; i < n; i++ { 221 var addr common.Address 222 if i == 1 { 223 nodeKeys[i], _ = generatePrivateKey() 224 addr = getAddress() 225 } else { 226 nodeKeys[i], _ = crypto.GenerateKey() 227 addr = crypto.PubkeyToAddress(nodeKeys[i].PublicKey) 228 } 229 blsPrivateKey, _ := blscrypto.ECDSAToBLS(nodeKeys[i]) 230 blsPublicKey, _ := blscrypto.PrivateToPublic(blsPrivateKey) 231 validators[i] = istanbul.ValidatorData{ 232 addr, 233 blsPublicKey, 234 } 235 236 } 237 238 // generate genesis block 239 genesis := core.DefaultGenesisBlock() 240 genesis.Config = params.TestChainConfig 241 if !isFullChain { 242 genesis.Config.FullHeaderChainAvailable = false 243 } 244 // force enable Istanbul engine 245 genesis.Config.Istanbul = ¶ms.IstanbulConfig{ 246 Epoch: 10, 247 LookbackWindow: 2, 248 } 249 genesis.Config.Ethash = nil 250 genesis.Difficulty = defaultDifficulty 251 genesis.Nonce = emptyNonce.Uint64() 252 genesis.Mixhash = types.IstanbulDigest 253 254 AppendValidatorsToGenesisBlock(genesis, validators) 255 return genesis, nodeKeys 256 } 257 258 func makeHeader(parent *types.Block, config *istanbul.Config) *types.Header { 259 header := &types.Header{ 260 ParentHash: parent.Hash(), 261 Number: parent.Number().Add(parent.Number(), common.Big1), 262 GasLimit: core.CalcGasLimit(parent, nil), 263 GasUsed: 0, 264 Extra: parent.Extra(), 265 Time: new(big.Int).Add(parent.Time(), new(big.Int).SetUint64(config.BlockPeriod)), 266 Difficulty: defaultDifficulty, 267 } 268 return header 269 } 270 271 func makeBlock(chain *core.BlockChain, engine *Backend, parent *types.Block) *types.Block { 272 block := makeBlockWithoutSeal(chain, engine, parent) 273 results := make(chan *types.Block) 274 go func() { engine.Seal(chain, block, results, nil) }() 275 block = <-results 276 return block 277 } 278 279 func makeBlockWithoutSeal(chain *core.BlockChain, engine *Backend, parent *types.Block) *types.Block { 280 header := makeHeader(parent, engine.config) 281 engine.Prepare(chain, header) 282 state, err := chain.StateAt(parent.Root()) 283 if err != nil { 284 fmt.Printf("Error!! %v\n", err) 285 } 286 block, err := engine.Finalize(chain, header, state, nil, nil, nil, nil) 287 if err != nil { 288 fmt.Printf("Error!! %v\n", err) 289 } 290 return block 291 } 292 293 func TestPrepare(t *testing.T) { 294 chain, engine := newBlockChain(1, true) 295 header := makeHeader(chain.Genesis(), engine.config) 296 err := engine.Prepare(chain, header) 297 if err != nil { 298 t.Errorf("error mismatch: have %v, want nil", err) 299 } 300 header.ParentHash = common.BytesToHash([]byte("1234567890")) 301 err = engine.Prepare(chain, header) 302 if err != consensus.ErrUnknownAncestor { 303 t.Errorf("error mismatch: have %v, want %v", err, consensus.ErrUnknownAncestor) 304 } 305 } 306 307 func TestSealReturns(t *testing.T) { 308 chain, engine := newBlockChain(2, true) 309 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 310 stop := make(chan struct{}, 1) 311 results := make(chan *types.Block) 312 returns := make(chan struct{}, 1) 313 go func() { 314 err := engine.Seal(chain, block, results, stop) 315 if err != nil { 316 t.Errorf("error mismatch: have %v, want nil", err) 317 } 318 returns <- struct{}{} 319 }() 320 321 select { 322 case <-returns: 323 case <-time.After(time.Second): 324 t.Errorf("Never returned from seal") 325 } 326 327 } 328 func TestSealStopChannel(t *testing.T) { 329 chain, engine := newBlockChain(1, true) 330 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 331 stop := make(chan struct{}, 1) 332 eventSub := engine.EventMux().Subscribe(istanbul.RequestEvent{}) 333 eventLoop := func() { 334 ev := <-eventSub.Chan() 335 _, ok := ev.Data.(istanbul.RequestEvent) 336 if !ok { 337 t.Errorf("unexpected event comes: %v", reflect.TypeOf(ev.Data)) 338 } 339 stop <- struct{}{} 340 eventSub.Unsubscribe() 341 } 342 go eventLoop() 343 results := make(chan *types.Block) 344 345 err := engine.Seal(chain, block, results, stop) 346 if err != nil { 347 t.Errorf("error mismatch: have %v, want nil", err) 348 } 349 350 select { 351 case <-results: 352 t.Errorf("Did not expect a block") 353 case <-time.After(time.Second): 354 } 355 } 356 357 // TestSealCommittedOtherHash checks that when Seal() ask for a commit, if we send a 358 // different block hash, it will abort 359 func TestSealCommittedOtherHash(t *testing.T) { 360 chain, engine := newBlockChain(4, true) 361 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 362 363 // create a second block which will have a different hash 364 otherBlock := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 365 eventSub := engine.EventMux().Subscribe(istanbul.RequestEvent{}) 366 eventLoop := func() { 367 ev := <-eventSub.Chan() 368 _, ok := ev.Data.(istanbul.RequestEvent) 369 if !ok { 370 t.Errorf("unexpected event comes: %v", reflect.TypeOf(ev.Data)) 371 } 372 engine.Commit(otherBlock, types.IstanbulAggregatedSeal{}, types.IstanbulEpochValidatorSetSeal{}) 373 eventSub.Unsubscribe() 374 } 375 go eventLoop() 376 results := make(chan *types.Block) 377 378 go func() { engine.Seal(chain, block, results, nil) }() 379 select { 380 case <-results: 381 t.Error("seal should not be completed") 382 case <-time.After(2 * time.Second): 383 } 384 } 385 386 func TestSealCommitted(t *testing.T) { 387 chain, engine := newBlockChain(1, true) 388 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 389 expectedBlock, _ := engine.updateBlock(engine.chain.GetHeader(block.ParentHash(), block.NumberU64()-1), block) 390 391 results := make(chan *types.Block) 392 go func() { 393 err := engine.Seal(chain, block, results, nil) 394 if err != nil { 395 t.Errorf("error mismatch: have %v, want nil", err) 396 } 397 }() 398 399 finalBlock := <-results 400 if finalBlock.Hash() != expectedBlock.Hash() { 401 t.Errorf("hash mismatch: have %v, want %v", finalBlock.Hash(), expectedBlock.Hash()) 402 } 403 } 404 405 func TestVerifyHeader(t *testing.T) { 406 chain, engine := newBlockChain(1, true) 407 408 // errEmptyAggregatedSeal case 409 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 410 block, _ = engine.updateBlock(chain.Genesis().Header(), block) 411 err := engine.VerifyHeader(chain, block.Header(), false) 412 if err != errEmptyAggregatedSeal { 413 t.Errorf("error mismatch: have %v, want %v", err, errEmptyAggregatedSeal) 414 } 415 416 // short extra data 417 header := block.Header() 418 header.Extra = []byte{} 419 err = engine.VerifyHeader(chain, header, false) 420 if err != errInvalidExtraDataFormat { 421 t.Errorf("error mismatch: have %v, want %v", err, errInvalidExtraDataFormat) 422 } 423 // incorrect extra format 424 header.Extra = []byte("0000000000000000000000000000000012300000000000000000000000000000000000000000000000000000000000000000") 425 err = engine.VerifyHeader(chain, header, false) 426 if err != errInvalidExtraDataFormat { 427 t.Errorf("error mismatch: have %v, want %v", err, errInvalidExtraDataFormat) 428 } 429 430 // non zero MixDigest 431 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 432 header = block.Header() 433 header.MixDigest = common.BytesToHash([]byte("123456789")) 434 err = engine.VerifyHeader(chain, header, false) 435 if err != errInvalidMixDigest { 436 t.Errorf("error mismatch: have %v, want %v", err, errInvalidMixDigest) 437 } 438 439 // invalid uncles hash 440 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 441 header = block.Header() 442 header.UncleHash = common.BytesToHash([]byte("123456789")) 443 err = engine.VerifyHeader(chain, header, false) 444 if err != errInvalidUncleHash { 445 t.Errorf("error mismatch: have %v, want %v", err, errInvalidUncleHash) 446 } 447 448 // invalid difficulty 449 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 450 header = block.Header() 451 header.Difficulty = big.NewInt(2) 452 err = engine.VerifyHeader(chain, header, false) 453 if err != errInvalidDifficulty { 454 t.Errorf("error mismatch: have %v, want %v", err, errInvalidDifficulty) 455 } 456 457 // invalid timestamp 458 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 459 header = block.Header() 460 header.Time = new(big.Int).Add(chain.Genesis().Time(), new(big.Int).SetUint64(engine.config.BlockPeriod-1)) 461 err = engine.VerifyHeader(chain, header, false) 462 if err != errInvalidTimestamp { 463 t.Errorf("error mismatch: have %v, want %v", err, errInvalidTimestamp) 464 } 465 466 // future block 467 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 468 header = block.Header() 469 header.Time = new(big.Int).Add(big.NewInt(now().Unix()), new(big.Int).SetUint64(10)) 470 err = engine.VerifyHeader(chain, header, false) 471 if err != consensus.ErrFutureBlock { 472 t.Errorf("error mismatch: have %v, want %v", err, consensus.ErrFutureBlock) 473 } 474 475 // invalid nonce 476 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 477 header = block.Header() 478 copy(header.Nonce[:], hexutil.MustDecode("0x111111111111")) 479 header.Number = big.NewInt(int64(engine.config.Epoch)) 480 err = engine.VerifyHeader(chain, header, false) 481 if err != errInvalidNonce { 482 t.Errorf("error mismatch: have %v, want %v", err, errInvalidNonce) 483 } 484 } 485 486 func TestVerifySeal(t *testing.T) { 487 chain, engine := newBlockChain(1, true) 488 genesis := chain.Genesis() 489 // cannot verify genesis 490 err := engine.VerifySeal(chain, genesis.Header()) 491 if err != errUnknownBlock { 492 t.Errorf("error mismatch: have %v, want %v", err, errUnknownBlock) 493 } 494 495 block := makeBlock(chain, engine, genesis) 496 497 // change header content and expect to invalidate signature 498 header := block.Header() 499 header.Number = big.NewInt(4) 500 err = engine.VerifySeal(chain, header) 501 if err != errInvalidSignature { 502 t.Errorf("error mismatch: have %v, want %v", err, errInvalidSignature) 503 } 504 505 // delete istanbul extra data and expect invalid extra data format 506 header = block.Header() 507 header.Extra = nil 508 err = engine.VerifySeal(chain, header) 509 if err != errInvalidExtraDataFormat { 510 t.Errorf("error mismatch: have %v, want %v", err, errInvalidExtraDataFormat) 511 } 512 513 // modify seal bitmap and expect to fail the quorum check 514 header = block.Header() 515 extra, err := types.ExtractIstanbulExtra(header) 516 if err != nil { 517 t.Fatalf("failed to extract istanbul data: %v", err) 518 } 519 extra.AggregatedSeal.Bitmap = big.NewInt(0) 520 encoded, err := rlp.EncodeToBytes(extra) 521 if err != nil { 522 t.Fatalf("failed to encode istanbul data: %v", err) 523 } 524 header.Extra = append(header.Extra[:types.IstanbulExtraVanity], encoded...) 525 err = engine.VerifySeal(chain, header) 526 if err != errInsufficientSeals { 527 t.Errorf("error mismatch: have %v, want %v", err, errInsufficientSeals) 528 } 529 530 // verifiy the seal on the unmodified block. 531 err = engine.VerifySeal(chain, block.Header()) 532 if err != nil { 533 t.Errorf("error mismatch: have %v, want nil", err) 534 } 535 } 536 537 func TestVerifyHeaders(t *testing.T) { 538 chain, engine := newBlockChain(1, true) 539 genesis := chain.Genesis() 540 541 // success case 542 headers := []*types.Header{} 543 blocks := []*types.Block{} 544 size := 100 545 546 for i := 0; i < size; i++ { 547 var b *types.Block 548 if i == 0 { 549 b = makeBlockWithoutSeal(chain, engine, genesis) 550 b, _ = engine.updateBlock(genesis.Header(), b) 551 } else { 552 b = makeBlockWithoutSeal(chain, engine, blocks[i-1]) 553 b, _ = engine.updateBlock(blocks[i-1].Header(), b) 554 } 555 556 blocks = append(blocks, b) 557 headers = append(headers, blocks[i].Header()) 558 } 559 now = func() time.Time { 560 return time.Unix(headers[size-1].Time.Int64(), 0) 561 } 562 _, results := engine.VerifyHeaders(chain, headers, nil) 563 const timeoutDura = 2 * time.Second 564 timeout := time.NewTimer(timeoutDura) 565 index := 0 566 OUT1: 567 for { 568 select { 569 case err := <-results: 570 if err != nil { 571 if err != errEmptyAggregatedSeal && err != errInvalidAggregatedSeal { 572 t.Errorf("error mismatch: have %v, want errEmptyAggregatedSeal|errInvalidAggregatedSeal", err) 573 break OUT1 574 } 575 } 576 index++ 577 if index == size { 578 break OUT1 579 } 580 case <-timeout.C: 581 break OUT1 582 } 583 } 584 // abort cases 585 abort, results := engine.VerifyHeaders(chain, headers, nil) 586 timeout = time.NewTimer(timeoutDura) 587 index = 0 588 OUT2: 589 for { 590 select { 591 case err := <-results: 592 if err != nil { 593 if err != errEmptyAggregatedSeal && err != errInvalidAggregatedSeal { 594 t.Errorf("error mismatch: have %v, want errEmptyAggregatedSeal|errInvalidAggregatedSeal", err) 595 break OUT2 596 } 597 } 598 index++ 599 if index == 5 { 600 abort <- struct{}{} 601 } 602 if index >= size { 603 t.Errorf("verifyheaders should be aborted") 604 break OUT2 605 } 606 case <-timeout.C: 607 break OUT2 608 } 609 } 610 // error header cases 611 headers[2].Number = big.NewInt(100) 612 abort, results = engine.VerifyHeaders(chain, headers, nil) 613 timeout = time.NewTimer(timeoutDura) 614 index = 0 615 errors := 0 616 expectedErrors := 2 617 OUT3: 618 for { 619 select { 620 case err := <-results: 621 if err != nil { 622 if err != errEmptyAggregatedSeal && err != errInvalidAggregatedSeal { 623 errors++ 624 } 625 } 626 index++ 627 if index == size { 628 if errors != expectedErrors { 629 t.Errorf("error mismatch: have %v, want %v", err, expectedErrors) 630 } 631 break OUT3 632 } 633 case <-timeout.C: 634 break OUT3 635 } 636 } 637 } 638 639 func TestVerifyHeaderWithoutFullChain(t *testing.T) { 640 chain, engine := newBlockChain(1, false) 641 642 // allow future block without full chain available 643 block := makeBlockWithoutSeal(chain, engine, chain.Genesis()) 644 header := block.Header() 645 header.Time = new(big.Int).Add(big.NewInt(now().Unix()), new(big.Int).SetUint64(3)) 646 err := engine.VerifyHeader(chain, header, false) 647 if err != errEmptyAggregatedSeal { 648 t.Errorf("error mismatch: have %v, want %v", err, errEmptyAggregatedSeal) 649 } 650 651 // reject future block without full chain available 652 block = makeBlockWithoutSeal(chain, engine, chain.Genesis()) 653 header = block.Header() 654 header.Time = new(big.Int).Add(big.NewInt(now().Unix()), new(big.Int).SetUint64(10)) 655 err = engine.VerifyHeader(chain, header, false) 656 if err != consensus.ErrFutureBlock { 657 t.Errorf("error mismatch: have %v, want %v", err, consensus.ErrFutureBlock) 658 } 659 } 660 661 func TestPrepareExtra(t *testing.T) { 662 oldValidators := make([]istanbul.ValidatorData, 2) 663 oldValidators[0] = istanbul.ValidatorData{ 664 common.BytesToAddress(hexutil.MustDecode("0x44add0ec310f115a0e603b2d7db9f067778eaf8a")), 665 blscrypto.SerializedPublicKey{}, 666 } 667 oldValidators[1] = istanbul.ValidatorData{ 668 common.BytesToAddress(hexutil.MustDecode("0x294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212")), 669 blscrypto.SerializedPublicKey{}, 670 } 671 672 newValidators := make([]istanbul.ValidatorData, 2) 673 newValidators[0] = istanbul.ValidatorData{ 674 common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6")), 675 blscrypto.SerializedPublicKey{}, 676 } 677 newValidators[1] = istanbul.ValidatorData{ 678 common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440")), 679 blscrypto.SerializedPublicKey{}, 680 } 681 682 extra, err := rlp.EncodeToBytes(&types.IstanbulExtra{ 683 AddedValidators: []common.Address{}, 684 AddedValidatorsPublicKeys: []blscrypto.SerializedPublicKey{}, 685 RemovedValidators: big.NewInt(0), 686 Seal: []byte{}, 687 AggregatedSeal: types.IstanbulAggregatedSeal{}, 688 ParentAggregatedSeal: types.IstanbulAggregatedSeal{}, 689 }) 690 h := &types.Header{ 691 Extra: append(make([]byte, types.IstanbulExtraVanity), extra...), 692 } 693 694 err = writeValidatorSetDiff(h, oldValidators, newValidators) 695 if err != nil { 696 t.Errorf("error mismatch: have %v, want: nil", err) 697 } 698 699 // the header must have the updated extra data 700 updatedExtra, err := types.ExtractIstanbulExtra(h) 701 if err != nil { 702 t.Errorf("error mismatch: have %v, want: nil", err) 703 } 704 705 var updatedExtraVals []istanbul.ValidatorData 706 for i := range updatedExtra.AddedValidators { 707 updatedExtraVals = append(updatedExtraVals, istanbul.ValidatorData{ 708 Address: updatedExtra.AddedValidators[i], 709 BLSPublicKey: updatedExtra.AddedValidatorsPublicKeys[i], 710 }) 711 } 712 713 if !reflect.DeepEqual(updatedExtraVals, newValidators) { 714 t.Errorf("validators were not properly updated") 715 } 716 717 // the validators which were removed were 2, so the bitmap is 11, meaning it 718 // should be 3 719 if updatedExtra.RemovedValidators.Cmp(big.NewInt(3)) != 0 { 720 t.Errorf("Invalid removed validators bitmap, got %v, want %v", updatedExtra.RemovedValidators, big.NewInt(3)) 721 } 722 723 } 724 725 func TestWriteSeal(t *testing.T) { 726 vanity := bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity) 727 istExtra := &types.IstanbulExtra{ 728 AddedValidators: []common.Address{ 729 common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6")), 730 common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440")), 731 }, 732 AddedValidatorsPublicKeys: []blscrypto.SerializedPublicKey{}, 733 RemovedValidators: big.NewInt(12), // 1100, remove third and fourth validators 734 Seal: []byte{}, 735 AggregatedSeal: types.IstanbulAggregatedSeal{big.NewInt(0), []byte{}, big.NewInt(0)}, 736 ParentAggregatedSeal: types.IstanbulAggregatedSeal{big.NewInt(0), []byte{}, big.NewInt(0)}, 737 } 738 istExtraRaw, err := rlp.EncodeToBytes(&istExtra) 739 740 expectedSeal := hexutil.MustDecode("0x29fe2612266a3965321c23a2e0382cd819e992f293d9a0032439728e41201d2c387cc9de5914a734873d79addb76c59ce73c1085a98b968384811b4ad050dddc56") 741 if len(expectedSeal) != types.IstanbulExtraSeal { 742 t.Errorf("incorrect length for seal: have %v, want %v", len(expectedSeal), types.IstanbulExtraSeal) 743 } 744 expectedIstExtra := istExtra 745 expectedIstExtra.Seal = expectedSeal 746 747 var expectedErr error 748 749 h := &types.Header{ 750 Extra: append(vanity, istExtraRaw...), 751 } 752 753 // normal case 754 err = writeSeal(h, expectedSeal) 755 if err != expectedErr { 756 t.Errorf("error mismatch: have %v, want %v", err, expectedErr) 757 } 758 759 // verify istanbul extra-data 760 actualIstExtra, err := types.ExtractIstanbulExtra(h) 761 if err != nil { 762 t.Errorf("error mismatch: have %v, want nil", err) 763 } 764 if !reflect.DeepEqual(actualIstExtra, expectedIstExtra) { 765 t.Errorf("extra data mismatch: have %v, want %v", actualIstExtra, expectedIstExtra) 766 } 767 768 // invalid seal 769 unexpectedSeal := append(expectedSeal, make([]byte, 1)...) 770 err = writeSeal(h, unexpectedSeal) 771 if err != errInvalidSignature { 772 t.Errorf("error mismatch: have %v, want %v", err, errInvalidSignature) 773 } 774 } 775 776 func TestWriteAggregatedSeal(t *testing.T) { 777 vanity := bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity) 778 istExtra := &types.IstanbulExtra{ 779 AddedValidators: []common.Address{ 780 common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6")), 781 common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440")), 782 }, 783 AddedValidatorsPublicKeys: []blscrypto.SerializedPublicKey{}, 784 RemovedValidators: big.NewInt(12), // 1100, remove third and fourth validators 785 Seal: []byte{}, 786 AggregatedSeal: types.IstanbulAggregatedSeal{}, 787 ParentAggregatedSeal: types.IstanbulAggregatedSeal{}, 788 } 789 istExtraRaw, err := rlp.EncodeToBytes(&istExtra) 790 791 aggregatedSeal := types.IstanbulAggregatedSeal{ 792 Round: big.NewInt(2), 793 Bitmap: big.NewInt(3), 794 Signature: append([]byte{1, 2, 3}, bytes.Repeat([]byte{0x00}, types.IstanbulExtraBlsSignature-3)...), 795 } 796 797 expectedIstExtra := istExtra 798 expectedIstExtra.AggregatedSeal = aggregatedSeal 799 expectedIstExtra.ParentAggregatedSeal = aggregatedSeal 800 801 h := &types.Header{ 802 Extra: append(vanity, istExtraRaw...), 803 } 804 805 // normal case 806 err = writeAggregatedSeal(h, aggregatedSeal, false) 807 if err != nil { 808 t.Errorf("error mismatch: have %v, want nil", err) 809 } 810 811 err = writeAggregatedSeal(h, aggregatedSeal, true) 812 if err != nil { 813 t.Errorf("error mismatch: have %v, want nil", err) 814 } 815 816 // verify istanbul extra-data 817 actualIstExtra, err := types.ExtractIstanbulExtra(h) 818 if err != nil { 819 t.Errorf("error mismatch: have %v, want nil", err) 820 } 821 if !reflect.DeepEqual(actualIstExtra, expectedIstExtra) { 822 t.Errorf("extra data mismatch: have %v, want %v", actualIstExtra, expectedIstExtra) 823 } 824 825 // try to write an invalid length seal to the CommitedSeal or ParentCommit field 826 invalidAggregatedSeal := types.IstanbulAggregatedSeal{ 827 Round: big.NewInt(3), 828 Bitmap: big.NewInt(3), 829 Signature: append(aggregatedSeal.Signature, make([]byte, 1)...), 830 } 831 err = writeAggregatedSeal(h, invalidAggregatedSeal, false) 832 if err != errInvalidAggregatedSeal { 833 t.Errorf("error mismatch: have %v, want %v", err, errInvalidAggregatedSeal) 834 } 835 836 err = writeAggregatedSeal(h, invalidAggregatedSeal, true) 837 if err != errInvalidAggregatedSeal { 838 t.Errorf("error mismatch: have %v, want %v", err, errInvalidAggregatedSeal) 839 } 840 }