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