github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/core/blockchain_test.go (about) 1 // Copyright 2014 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 core 18 19 import ( 20 "fmt" 21 "math/big" 22 "math/rand" 23 "sync" 24 "testing" 25 "time" 26 27 "github.com/vntchain/go-vnt/common" 28 "github.com/vntchain/go-vnt/consensus/mock" 29 "github.com/vntchain/go-vnt/core/rawdb" 30 "github.com/vntchain/go-vnt/core/state" 31 "github.com/vntchain/go-vnt/core/types" 32 "github.com/vntchain/go-vnt/core/vm" 33 "github.com/vntchain/go-vnt/crypto" 34 "github.com/vntchain/go-vnt/params" 35 "github.com/vntchain/go-vnt/vntdb" 36 ) 37 38 // Test fork of length N starting from block i 39 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { 40 // Copy old chain up to #i into a new db 41 db, blockchain2, err := newCanonical(mock.NewMock(), i, full) 42 if err != nil { 43 t.Fatal("could not make new canonical in testFork", err) 44 } 45 defer blockchain2.Stop() 46 47 // Assert the chains have the same header/block at #i 48 var hash1, hash2 common.Hash 49 if full { 50 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 51 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 52 } else { 53 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 54 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 55 } 56 if hash1 != hash2 { 57 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 58 } 59 // Extend the newly created chain 60 var ( 61 blockChainB []*types.Block 62 headerChainB []*types.Header 63 ) 64 if full { 65 blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, mock.NewMock(), db, forkSeed) 66 if _, err := blockchain2.InsertChain(blockChainB); err != nil { 67 t.Fatalf("failed to insert forking chain: %v", err) 68 } 69 } else { 70 headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, mock.NewMock(), db, forkSeed) 71 if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { 72 t.Fatalf("failed to insert forking chain: %v", err) 73 } 74 } 75 // Sanity check that the forked chain can be imported into the original 76 var tdPre, tdPost *big.Int 77 78 if full { 79 tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) 80 if err := testBlockChainImport(blockChainB, blockchain); err != nil { 81 t.Fatalf("failed to import forked block chain: %v", err) 82 } 83 tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) 84 } else { 85 tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) 86 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 87 t.Fatalf("failed to import forked header chain: %v", err) 88 } 89 tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) 90 } 91 // Compare the total difficulties of the chains 92 comparator(tdPre, tdPost) 93 } 94 95 func printChain(bc *BlockChain) { 96 for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- { 97 b := bc.GetBlockByNumber(uint64(i)) 98 fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty()) 99 } 100 } 101 102 // testBlockChainImport tries to process a chain of blocks, writing them into 103 // the database if successful. 104 func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { 105 for _, block := range chain { 106 // Try and process the block 107 err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) 108 if err == nil { 109 err = blockchain.validator.ValidateBody(block) 110 } 111 if err != nil { 112 if err == ErrKnownBlock { 113 continue 114 } 115 return err 116 } 117 statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache) 118 if err != nil { 119 return err 120 } 121 receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{}) 122 if err != nil { 123 blockchain.reportBlock(block, receipts, err) 124 return err 125 } 126 err = blockchain.validator.ValidateState(block, blockchain.GetBlockByHash(block.ParentHash()), statedb, receipts, usedGas) 127 if err != nil { 128 blockchain.reportBlock(block, receipts, err) 129 return err 130 } 131 blockchain.mu.Lock() 132 rawdb.WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash()))) 133 rawdb.WriteBlock(blockchain.db, block) 134 statedb.Commit(false) 135 blockchain.mu.Unlock() 136 } 137 return nil 138 } 139 140 // testHeaderChainImport tries to process a chain of header, writing them into 141 // the database if successful. 142 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 143 for _, header := range chain { 144 // Try and validate the header 145 if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { 146 return err 147 } 148 // Manually insert the header into the database, but don't reorganise (allows subsequent testing) 149 blockchain.mu.Lock() 150 rawdb.WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash))) 151 rawdb.WriteHeader(blockchain.db, header) 152 blockchain.mu.Unlock() 153 } 154 return nil 155 } 156 157 func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) { 158 _, err := blockchain.InsertChain(chain) 159 if err != nil { 160 fmt.Println(err) 161 t.FailNow() 162 } 163 done <- true 164 } 165 166 func TestLastBlock(t *testing.T) { 167 _, blockchain, err := newCanonical(mock.NewMock(), 0, true) 168 if err != nil { 169 t.Fatalf("failed to create pristine chain: %v", err) 170 } 171 defer blockchain.Stop() 172 173 blocks := makeBlockChain(blockchain.CurrentBlock(), 1, mock.NewMock(), blockchain.db, 0) 174 if _, err := blockchain.InsertChain(blocks); err != nil { 175 t.Fatalf("Failed to insert block: %v", err) 176 } 177 if blocks[len(blocks)-1].Hash() != rawdb.ReadHeadBlockHash(blockchain.db) { 178 t.Fatalf("Write/Get HeadBlockHash failed") 179 } 180 } 181 182 // Tests that given a starting canonical chain of a given size, it can be extended 183 // with various length chains. 184 func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } 185 func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } 186 187 func testExtendCanonical(t *testing.T, full bool) { 188 length := 5 189 190 // Make first chain starting from genesis 191 _, processor, err := newCanonical(mock.NewMock(), length, full) 192 if err != nil { 193 t.Fatalf("failed to make new canonical chain: %v", err) 194 } 195 defer processor.Stop() 196 197 // Define the difficulty comparator 198 better := func(td1, td2 *big.Int) { 199 if td2.Cmp(td1) <= 0 { 200 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 201 } 202 } 203 // Start fork from current height 204 testFork(t, processor, length, 1, full, better) 205 testFork(t, processor, length, 2, full, better) 206 testFork(t, processor, length, 5, full, better) 207 testFork(t, processor, length, 10, full, better) 208 } 209 210 // Tests that given a starting canonical chain of a given size, creating shorter 211 // forks do not take canonical ownership. 212 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } 213 func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } 214 215 func testShorterFork(t *testing.T, full bool) { 216 length := 10 217 218 // Make first chain starting from genesis 219 _, processor, err := newCanonical(mock.NewMock(), length, full) 220 if err != nil { 221 t.Fatalf("failed to make new canonical chain: %v", err) 222 } 223 defer processor.Stop() 224 225 // Define the difficulty comparator 226 worse := func(td1, td2 *big.Int) { 227 if td2.Cmp(td1) >= 0 { 228 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 229 } 230 } 231 // Sum of numbers must be less than `length` for this to be a shorter fork 232 testFork(t, processor, 0, 3, full, worse) 233 testFork(t, processor, 0, 7, full, worse) 234 testFork(t, processor, 1, 1, full, worse) 235 testFork(t, processor, 1, 7, full, worse) 236 testFork(t, processor, 5, 3, full, worse) 237 testFork(t, processor, 5, 4, full, worse) 238 } 239 240 // Tests that given a starting canonical chain of a given size, creating longer 241 // forks do take canonical ownership. 242 func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } 243 func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } 244 245 func testLongerFork(t *testing.T, full bool) { 246 length := 10 247 248 // Make first chain starting from genesis 249 _, processor, err := newCanonical(mock.NewMock(), length, full) 250 if err != nil { 251 t.Fatalf("failed to make new canonical chain: %v", err) 252 } 253 defer processor.Stop() 254 255 // Define the difficulty comparator 256 better := func(td1, td2 *big.Int) { 257 if td2.Cmp(td1) <= 0 { 258 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 259 } 260 } 261 // Sum of numbers must be greater than `length` for this to be a longer fork 262 testFork(t, processor, 0, 11, full, better) 263 testFork(t, processor, 0, 15, full, better) 264 testFork(t, processor, 1, 10, full, better) 265 testFork(t, processor, 1, 12, full, better) 266 testFork(t, processor, 5, 6, full, better) 267 testFork(t, processor, 5, 8, full, better) 268 } 269 270 // Tests that given a starting canonical chain of a given size, creating equal 271 // forks do take canonical ownership. 272 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } 273 func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } 274 275 func testEqualFork(t *testing.T, full bool) { 276 length := 10 277 278 // Make first chain starting from genesis 279 _, processor, err := newCanonical(mock.NewMock(), length, full) 280 if err != nil { 281 t.Fatalf("failed to make new canonical chain: %v", err) 282 } 283 defer processor.Stop() 284 285 // Define the difficulty comparator 286 equal := func(td1, td2 *big.Int) { 287 if td2.Cmp(td1) != 0 { 288 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 289 } 290 } 291 // Sum of numbers must be equal to `length` for this to be an equal fork 292 testFork(t, processor, 0, 10, full, equal) 293 testFork(t, processor, 1, 9, full, equal) 294 testFork(t, processor, 2, 8, full, equal) 295 testFork(t, processor, 5, 5, full, equal) 296 testFork(t, processor, 6, 4, full, equal) 297 testFork(t, processor, 9, 1, full, equal) 298 } 299 300 // Tests that chains missing links do not get accepted by the processor. 301 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } 302 func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } 303 304 func testBrokenChain(t *testing.T, full bool) { 305 // Make chain starting from genesis 306 db, blockchain, err := newCanonical(mock.NewMock(), 10, full) 307 if err != nil { 308 t.Fatalf("failed to make new canonical chain: %v", err) 309 } 310 defer blockchain.Stop() 311 312 // Create a forked chain, and try to insert with a missing link 313 if full { 314 chain := makeBlockChain(blockchain.CurrentBlock(), 5, mock.NewMock(), db, forkSeed)[1:] 315 if err := testBlockChainImport(chain, blockchain); err == nil { 316 t.Errorf("broken block chain not reported") 317 } 318 } else { 319 chain := makeHeaderChain(blockchain.CurrentHeader(), 5, mock.NewMock(), db, forkSeed)[1:] 320 if err := testHeaderChainImport(chain, blockchain); err == nil { 321 t.Errorf("broken header chain not reported") 322 } 323 } 324 } 325 326 // 正常产块情况,在当前主链后产生新区块,当前新区块应当成为头区块 327 // Header chain测试 328 func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) } 329 330 // Block chain测试 331 func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) } 332 333 func testReorgLong(t *testing.T, full bool) { 334 testReorg(t, []int64{0, 0, 0}, []int64{0, 0, 0, 0}, 4, full, true, false) 335 } 336 337 // 测试攻击链的场景,填充过去某个时间点缺失的区块,创造更长的链 338 // Test some block producers make up fake chain by filling skipped blocks. 339 // first : A -> -> B -> C 340 // second: A -> B' -> C' -> D' 341 func TestReorgFakeChainFillMissTimeAndLongHeaders(t *testing.T) { 342 testReorgFakeChainFillMissTimeAndLong(t, false) 343 } 344 func TestReorgFakeChainFillMissTimeAndLongBlocks(t *testing.T) { 345 testReorgFakeChainFillMissTimeAndLong(t, true) 346 } 347 func testReorgFakeChainFillMissTimeAndLong(t *testing.T, full bool) { 348 mainChain := []int64{0, 2, 0, 0} 349 fakeChain := []int64{0, 0, 0, 0, 0} // LIB之前的区块插入失败 350 testReorg(t, mainChain, fakeChain, 4, full, false, true) 351 } 352 353 // 临时分叉情况,网络突然中断,然后下一轮结束前恢复 354 // Case 1.1 two blocks in the same height for bad network 355 // first: A -> B, 代表本地链 356 // second: A -> -> C, 代表远端链 357 // first is still main chain 358 func TestReorgSameHeightFirstIsEarlyHeader(t *testing.T) { 359 testReorgSameHeightFirstIsEarly(t, false) 360 } 361 func TestReorgSameHeightFirstIsEarlyBlock(t *testing.T) { 362 testReorgSameHeightFirstIsEarly(t, true) 363 } 364 func testReorgSameHeightFirstIsEarly(t *testing.T, full bool) { 365 first := []int64{0, 0} 366 second := []int64{0, 2} 367 testReorg(t, first, second, 2, full, true, true) 368 } 369 370 // 临时分叉情况,网络突然中断,然后下一轮结束前恢复 371 // Case 1.2 two blocks in the same height for bad network 372 // 与Case 1.1相反的过程,但都应当选择`A -> B` 373 // first: A -> -> C 374 // second: A -> B 375 func TestReorgSameHeightSecondIsEarlyHeader(t *testing.T) { 376 testReorgSameHeightSecondIsEarly(t, false) 377 } 378 func TestReorgSameHeightSecondIsEarlyBlock(t *testing.T) { 379 testReorgSameHeightSecondIsEarly(t, true) 380 } 381 func testReorgSameHeightSecondIsEarly(t *testing.T, full bool) { 382 first := []int64{0, 2} 383 second := []int64{0, 0} 384 testReorg(t, first, second, 2, full, true, false) 385 } 386 387 // 临时分叉情况,网络在第N轮突然中断,然后在N+2轮结束恢复 388 // Case 2.1 389 // first: A -> B 390 // second: A -> -> C -> D 391 func TestReorgFirstIsEarlyButShortHeader(t *testing.T) { 392 testReorgFirstIsEarlyButShort(t, false) 393 } 394 func TestReorgFirstIsEarlyButShortBlock(t *testing.T) { 395 testReorgFirstIsEarlyButShort(t, true) 396 } 397 func testReorgFirstIsEarlyButShort(t *testing.T, full bool) { 398 first := []int64{0, 0} 399 second := []int64{0, 2, 0} 400 testReorg(t, first, second, 3, full, true, false) 401 } 402 403 // 临时分叉情况,网络在第N轮突然中断,然后在N+2轮结束恢复 404 // Case 2.2 405 // first: A -> -> C -> D 406 // second: A -> B 407 func TestReorgSecondIsEarlyButShortHeader(t *testing.T) { 408 testReorgSecondIsEarlyButShort(t, false) 409 } 410 func TestReorgSecondIsEarlyButShortBlock(t *testing.T) { 411 testReorgSecondIsEarlyButShort(t, true) 412 } 413 func testReorgSecondIsEarlyButShort(t *testing.T, full bool) { 414 first := []int64{0, 2, 0} 415 second := []int64{0, 0} 416 testReorg(t, first, second, 3, full, false, true) 417 } 418 419 // 临时分叉情况,络在第N轮突然中断,然后在N+1轮结束恢复,然后在N+2轮产生了新区块, 420 // 在N+1轮产生区块的少数节点,如果没再case 1.1切回到first,在first生成新区块后切回first 421 // Case 3.1 422 // first: A -> B -> -> D 423 // second: A -> -> C 424 func TestReorgFirstIsEarlyAndLongHeader(t *testing.T) { 425 testReorgFirstIsEarlyAndLong(t, false) 426 } 427 func TestReorgFirstIsEarlyAndLongBlock(t *testing.T) { 428 testReorgFirstIsEarlyAndLong(t, true) 429 } 430 func testReorgFirstIsEarlyAndLong(t *testing.T, full bool) { 431 first := []int64{0, 0, 2} 432 second := []int64{0, 2} 433 testReorg(t, first, second, 3, full, false, true) 434 } 435 436 // 临时分叉情况,络在第N轮突然中断,然后在N+1轮结束恢复,然后在N+2轮产生了新区块, 437 // 在N+1轮产生区块的少数节点,如果没再case 1.1切回到first,在first生成新区块后切回first 438 // Case 3.2 439 // first: A -> -> C 440 // second: A -> B -> -> D 441 func TestReorgSecondIsEarlyAndLongHeader(t *testing.T) { 442 testReorgSecondIsEarlyAndLong(t, false) 443 } 444 func TestReorgSecondIsEarlyAndLongBlock(t *testing.T) { 445 testReorgSecondIsEarlyAndLong(t, true) 446 } 447 func testReorgSecondIsEarlyAndLong(t *testing.T, full bool) { 448 first := []int64{0, 2} 449 second := []int64{0, 0, 2} 450 testReorg(t, first, second, 3, full, true, false) 451 } 452 453 // first: 第一条链,是当前主链的时间戳偏移,在当前生成的区块上进一步做时间戳偏移 454 // second: 第二条链,分叉链、攻击链的时间戳偏移 455 // td: reorg后成为主链的区块的总高度 456 // full: 是否是header chain测试 457 // firstIsMain: reorg后,第一条链是主链 458 func testReorg(t *testing.T, first, second []int64, td int64, full, secondInsertSuccess, firstIsMain bool) { 459 // Create a pristine chain and database 460 db, blockchain, err := newCanonical(mock.NewMock(), 0, full) 461 if err != nil { 462 t.Fatalf("failed to create pristine chain: %v", err) 463 } 464 defer blockchain.Stop() 465 466 // 生成区块 467 firstBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), mock.NewMock(), db, len(first), func(i int, b *BlockGen) { 468 b.OffsetTime(first[i]) 469 }) 470 secondBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), mock.NewMock(), db, len(second), func(i int, b *BlockGen) { 471 b.OffsetTime(second[i]) 472 }) 473 474 printBlocks(t, "first blocks:", firstBlocks) 475 printBlocks(t, "second blocks:", secondBlocks) 476 477 // 调用测试函数 478 testFun := testReorgBlock 479 if !full { 480 testFun = testReorgHeader 481 } 482 testFun(t, blockchain, firstBlocks, secondBlocks, td, secondInsertSuccess, firstIsMain) 483 } 484 485 // testReorgBlock block chain的reorg测试 486 func testReorgBlock(t *testing.T, blockchain *BlockChain, firstBlocks, secondBlocks types.Blocks, td int64, secondInsertSuccess, firstIsMain bool) { 487 // 插入的区块链,first代表当前主链,必须成功 488 if _, err := blockchain.InsertChain(firstBlocks); err != nil { 489 t.Fatalf("failed to insert first chain: %v", err) 490 } 491 // second是攻击链或临时分叉,按要求执行,可能成功,可能失败 492 { 493 _, err := blockchain.InsertChain(secondBlocks) 494 if secondInsertSuccess { 495 if err != nil { 496 t.Logf("failed to insert second chain: %v", err) 497 } 498 } else { 499 if err == nil { 500 t.Logf("insert second chain successed, want failed") 501 } 502 } 503 } 504 505 // 检查链是否是连接正确的 506 block := blockchain.CurrentBlock() 507 for prev := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); prev.NumberU64() != 0; block, prev = prev, blockchain.GetBlockByNumber(prev.NumberU64()-1) { 508 // t.Logf("block hash: %s\n", block.Hash().String()) 509 if block.ParentHash() != prev.Hash() { 510 t.Errorf("parent block hash mismatch: have %x, want %x", block.ParentHash(), prev.Hash()) 511 } 512 } 513 514 // 链难度检查 515 wantTd := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) 516 if have := blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()); have.Cmp(wantTd) != 0 { 517 t.Errorf("total difficulty mismatch: have %v, want %v", have, wantTd) 518 } 519 520 // 检查主链的区块是否匹配 521 targetChain := firstBlocks 522 if !firstIsMain { 523 targetChain = secondBlocks 524 } 525 blocks := make([]*types.Block, 0) 526 blk := blockchain.CurrentBlock() 527 for prev := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); blk.NumberU64() != 0; blk, prev = prev, blockchain.GetBlockByNumber(prev.NumberU64()-1) { 528 blocks = append(blocks, blk) 529 } 530 // 反序,高度从低到高 531 for i, j := 0, len(blocks)-1; i < j; i, j = i+1, j-1 { 532 blocks[i], blocks[j] = blocks[j], blocks[i] 533 } 534 printBlocks(t, "main chain:", blocks) 535 536 // 打印难度日志 537 genesis := blockchain.genesisBlock 538 td0 := blockchain.GetTdByHash(genesis.Hash()) 539 t.Logf("genesis block %s, total diff: %v\n", genesis.Hash().String(), td0.String()) 540 for i, b := range blocks { 541 td := blockchain.GetTdByHash(b.Hash()) 542 t.Logf("block [%d] %s, total diff: %v\n", i, b.Hash().String(), td.String()) 543 } 544 545 if len(blocks) != len(targetChain) { 546 t.Fatalf("total length mismatch: have %v, want %v", len(blocks), len(targetChain)) 547 } 548 for i, b := range targetChain { 549 bc := blocks[i] 550 if b.Hash() != bc.Hash() { 551 t.Errorf("block [%d] mismatch: have %v, want: %v", i, bc.Hash().String(), b.Hash().String()) 552 } 553 } 554 } 555 556 // testReorgBlock header chain的reorg测试 557 func testReorgHeader(t *testing.T, blockchain *BlockChain, firstBlocks, secondBlocks types.Blocks, td int64, secondInsertSuccess, firstIsMain bool) { 558 firstHeaders := make([]*types.Header, len(firstBlocks)) 559 for i, block := range firstBlocks { 560 firstHeaders[i] = block.Header() 561 } 562 secondHeaders := make([]*types.Header, len(secondBlocks)) 563 for i, block := range secondBlocks { 564 secondHeaders[i] = block.Header() 565 } 566 567 // first是主链的header chain,必须成功 568 if _, err := blockchain.InsertHeaderChain(firstHeaders, 1); err != nil { 569 t.Fatalf("failed to insert first header chain: %v", err) 570 } 571 // second是攻击链或临时分叉的header chain,按要求觉得成功与否 572 { 573 _, err := blockchain.InsertHeaderChain(secondHeaders, 1) 574 if secondInsertSuccess { 575 if err != nil { 576 t.Fatalf("failed to insert second header chain: %v", err) 577 } 578 } else { 579 if err == nil { 580 t.Fatalf("insert second header chain successed, want failed") 581 } 582 } 583 } 584 585 // Check that the chain is valid number and link wise 586 header := blockchain.CurrentHeader() 587 for prev := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); prev.Number.Uint64() != 0; header, prev = prev, blockchain.GetHeaderByNumber(prev.Number.Uint64()-1) { 588 if header.ParentHash != prev.Hash() { 589 t.Errorf("parent header hash mismatch: have %x, want %x", header.ParentHash, prev.Hash()) 590 } 591 } 592 593 // Make sure the chain total difficulty is the correct one 594 wantTd := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) 595 if have := blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()); have.Cmp(wantTd) != 0 { 596 t.Errorf("total difficulty mismatch: have %v, want %v", have, wantTd) 597 } 598 599 // 检查主链是否匹配 600 targetHeader := firstHeaders 601 if !firstIsMain { 602 targetHeader = secondHeaders 603 } 604 chainHeader := make([]*types.Header, 0) 605 header = blockchain.CurrentHeader() 606 for prev := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; header, prev = prev, blockchain.GetHeaderByNumber(prev.Number.Uint64()-1) { 607 chainHeader = append(chainHeader, header) 608 } 609 for i, j := 0, len(chainHeader)-1; i < j; i, j = i+1, j-1 { 610 chainHeader[i], chainHeader[j] = chainHeader[j], chainHeader[i] 611 } 612 printHeaders(t, "header chain", chainHeader) 613 614 if len(targetHeader) != len(chainHeader) { 615 t.Fatalf("header chain lengeth mismatch, have: %d, want: %d", len(chainHeader), len(targetHeader)) 616 } 617 for i := 0; i < len(targetHeader); i++ { 618 if targetHeader[i].Hash() != chainHeader[i].Hash() { 619 t.Errorf("header chain mismatch %d, have: %s, want: %s\n", i, chainHeader[i].Hash(), targetHeader[i].Hash()) 620 } 621 } 622 } 623 624 func printBlocks(t *testing.T, tag string, blocks []*types.Block) { 625 t.Logf("%s\n", tag) 626 for i, b := range blocks { 627 t.Logf("b [%d], h: %s, time: %s, diff: %s, hash: %s\n", i, b.Number().String(), b.Time().String(), b.Difficulty().String(), b.Hash().String()) 628 } 629 } 630 631 func printHeaders(t *testing.T, tag string, headers []*types.Header) { 632 t.Logf("%s\n", tag) 633 for i, h := range headers { 634 t.Logf("header [%d], h: %s, time: %s, diff: %s, hash: %s\n", i, h.Number.String(), h.Time.String(), h.Difficulty.String(), h.Hash().String()) 635 } 636 } 637 638 // Tests that the insertion functions detect banned hashes. 639 func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) } 640 func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) } 641 642 func testBadHashes(t *testing.T, full bool) { 643 // Create a pristine chain and database 644 db, blockchain, err := newCanonical(mock.NewMock(), 0, full) 645 if err != nil { 646 t.Fatalf("failed to create pristine chain: %v", err) 647 } 648 defer blockchain.Stop() 649 650 // Create a chain, ban a hash and try to import 651 if full { 652 blocks := makeBlockChain(blockchain.CurrentBlock(), 3, mock.NewMock(), db, 10) 653 654 BadHashes[blocks[2].Header().Hash()] = true 655 defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() 656 657 _, err = blockchain.InsertChain(blocks) 658 } else { 659 headers := makeHeaderChain(blockchain.CurrentHeader(), 3, mock.NewMock(), db, 10) 660 661 BadHashes[headers[2].Hash()] = true 662 defer func() { delete(BadHashes, headers[2].Hash()) }() 663 664 _, err = blockchain.InsertHeaderChain(headers, 1) 665 } 666 if err != ErrBlacklistedHash { 667 t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash) 668 } 669 } 670 671 // Tests that bad hashes are detected on boot, and the chain rolled back to a 672 // good state prior to the bad hash. 673 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } 674 func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } 675 676 func testReorgBadHashes(t *testing.T, full bool) { 677 // Create a pristine chain and database 678 db, blockchain, err := newCanonical(mock.NewMock(), 0, full) 679 if err != nil { 680 t.Fatalf("failed to create pristine chain: %v", err) 681 } 682 // Create a chain, import and ban afterwards 683 headers := makeHeaderChain(blockchain.CurrentHeader(), 4, mock.NewMock(), db, 10) 684 blocks := makeBlockChain(blockchain.CurrentBlock(), 4, mock.NewMock(), db, 10) 685 686 if full { 687 if _, err = blockchain.InsertChain(blocks); err != nil { 688 t.Errorf("failed to import blocks: %v", err) 689 } 690 if blockchain.CurrentBlock().Hash() != blocks[3].Hash() { 691 t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash()) 692 } 693 BadHashes[blocks[3].Header().Hash()] = true 694 defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() 695 } else { 696 if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil { 697 t.Errorf("failed to import headers: %v", err) 698 } 699 if blockchain.CurrentHeader().Hash() != headers[3].Hash() { 700 t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash()) 701 } 702 BadHashes[headers[3].Hash()] = true 703 defer func() { delete(BadHashes, headers[3].Hash()) }() 704 } 705 blockchain.Stop() 706 707 // Create a new BlockChain and check that it rolled back the state. 708 ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, mock.NewMock(), vm.Config{}) 709 if err != nil { 710 t.Fatalf("failed to create new chain manager: %v", err) 711 } 712 if full { 713 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 714 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 715 } 716 if blocks[2].Header().GasLimit != ncm.GasLimit() { 717 t.Errorf("last block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit) 718 } 719 } else { 720 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 721 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 722 } 723 } 724 ncm.Stop() 725 } 726 727 // Tests chain insertions in the face of one entity containing an invalid nonce. 728 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } 729 func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } 730 731 func testInsertNonceError(t *testing.T, full bool) { 732 for i := 1; i < 25 && !t.Failed(); i++ { 733 // Create a pristine chain and database 734 db, blockchain, err := newCanonical(mock.NewMock(), 0, full) 735 if err != nil { 736 t.Fatalf("failed to create pristine chain: %v", err) 737 } 738 defer blockchain.Stop() 739 740 // Create and insert a chain with a failing nonce 741 var ( 742 failAt int 743 failRes int 744 failNum uint64 745 ) 746 if full { 747 blocks := makeBlockChain(blockchain.CurrentBlock(), i, mock.NewMock(), db, 0) 748 fmt.Println(blocks) 749 failAt = rand.Int() % len(blocks) 750 failNum = blocks[failAt].NumberU64() 751 752 blockchain.engine = mock.NewMockFail(failNum) 753 failRes, err = blockchain.InsertChain(blocks) 754 } else { 755 headers := makeHeaderChain(blockchain.CurrentHeader(), i, mock.NewMock(), db, 0) 756 757 failAt = rand.Int() % len(headers) 758 failNum = headers[failAt].Number.Uint64() 759 760 blockchain.engine = mock.NewMockFail(failNum) 761 blockchain.hc.engine = blockchain.engine 762 failRes, err = blockchain.InsertHeaderChain(headers, 1) 763 } 764 // Check that the returned error indicates the failure. 765 if failRes != failAt { 766 t.Errorf("test %d: failure index mismatch: have %d, want %d", i, failRes, failAt) 767 } 768 // Check that all no blocks after the failing block have been inserted. 769 for j := 0; j < i-failAt; j++ { 770 if full { 771 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 772 t.Errorf("test %d: invalid block in chain: %v", i, block) 773 } 774 } else { 775 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 776 t.Errorf("test %d: invalid header in chain: %v", i, header) 777 } 778 } 779 } 780 } 781 } 782 783 // Tests that fast importing a block chain produces the same chain data as the 784 // classical full block processing. 785 func TestFastVsFullChains(t *testing.T) { 786 // Configure and generate a sample block chain 787 var ( 788 gendb = vntdb.NewMemDatabase() 789 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 790 address = crypto.PubkeyToAddress(key.PublicKey) 791 funds = big.NewInt(1000000000) 792 gspec = &Genesis{ 793 Config: params.TestChainConfig, 794 Alloc: GenesisAlloc{address: {Balance: funds}}, 795 } 796 genesis = gspec.MustCommit(gendb) 797 signer = types.NewHubbleSigner(gspec.Config.ChainID) 798 ) 799 blocks, receipts := GenerateChain(gspec.Config, genesis, mock.NewMock(), gendb, 1024, func(i int, block *BlockGen) { 800 block.SetCoinbase(common.Address{0x00}) 801 802 // If the block number is multiple of 3, send a few bonus transactions to the producer 803 if i%3 == 2 { 804 for j := 0; j < i%4+1; j++ { 805 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key) 806 if err != nil { 807 panic(err) 808 } 809 block.AddTx(tx) 810 } 811 } 812 }) 813 // Import the chain as an archive node for the comparison baseline 814 archiveDb := vntdb.NewMemDatabase() 815 gspec.MustCommit(archiveDb) 816 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, mock.NewMock(), vm.Config{}) 817 defer archive.Stop() 818 819 if n, err := archive.InsertChain(blocks); err != nil { 820 t.Fatalf("failed to process block %d: %v", n, err) 821 } 822 // Fast import the chain as a non-archive node to test 823 fastDb := vntdb.NewMemDatabase() 824 gspec.MustCommit(fastDb) 825 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, mock.NewMock(), vm.Config{}) 826 defer fast.Stop() 827 828 headers := make([]*types.Header, len(blocks)) 829 for i, block := range blocks { 830 headers[i] = block.Header() 831 } 832 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 833 t.Fatalf("failed to insert header %d: %v", n, err) 834 } 835 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 836 t.Fatalf("failed to insert receipt %d: %v", n, err) 837 } 838 // Iterate over all chain data components, and cross reference 839 for i := 0; i < len(blocks); i++ { 840 num, hash := blocks[i].NumberU64(), blocks[i].Hash() 841 842 if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 { 843 t.Errorf("block #%d [%x]: td mismatch: have %v, want %v", num, hash, ftd, atd) 844 } 845 if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { 846 t.Errorf("block #%d [%x]: header mismatch: have %v, want %v", num, hash, fheader, aheader) 847 } 848 if fblock, ablock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash); fblock.Hash() != ablock.Hash() { 849 t.Errorf("block #%d [%x]: block mismatch: have %v, want %v", num, hash, fblock, ablock) 850 } else if types.DeriveSha(fblock.Transactions()) != types.DeriveSha(ablock.Transactions()) { 851 t.Errorf("block #%d [%x]: transactions mismatch: have %v, want %v", num, hash, fblock.Transactions(), ablock.Transactions()) 852 } 853 if freceipts, areceipts := rawdb.ReadReceipts(fastDb, hash, *rawdb.ReadHeaderNumber(fastDb, hash)), rawdb.ReadReceipts(archiveDb, hash, *rawdb.ReadHeaderNumber(archiveDb, hash)); types.DeriveSha(freceipts) != types.DeriveSha(areceipts) { 854 t.Errorf("block #%d [%x]: receipts mismatch: have %v, want %v", num, hash, freceipts, areceipts) 855 } 856 } 857 // Check that the canonical chains are the same between the databases 858 for i := 0; i < len(blocks)+1; i++ { 859 if fhash, ahash := rawdb.ReadCanonicalHash(fastDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); fhash != ahash { 860 t.Errorf("block #%d: canonical hash mismatch: have %v, want %v", i, fhash, ahash) 861 } 862 } 863 } 864 865 // Tests that various import methods move the chain head pointers to the correct 866 // positions. 867 func TestLightVsFastVsFullChainHeads(t *testing.T) { 868 // Configure and generate a sample block chain 869 var ( 870 gendb = vntdb.NewMemDatabase() 871 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 872 address = crypto.PubkeyToAddress(key.PublicKey) 873 funds = big.NewInt(1000000000) 874 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 875 genesis = gspec.MustCommit(gendb) 876 ) 877 height := uint64(1024) 878 blocks, receipts := GenerateChain(gspec.Config, genesis, mock.NewMock(), gendb, int(height), nil) 879 880 // Configure a subchain to roll back 881 remove := []common.Hash{} 882 for _, block := range blocks[height/2:] { 883 remove = append(remove, block.Hash()) 884 } 885 // Create a small assertion method to check the three heads 886 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 887 if num := chain.CurrentBlock().NumberU64(); num != block { 888 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 889 } 890 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 891 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 892 } 893 if num := chain.CurrentHeader().Number.Uint64(); num != header { 894 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 895 } 896 } 897 // Import the chain as an archive node and ensure all pointers are updated 898 archiveDb := vntdb.NewMemDatabase() 899 gspec.MustCommit(archiveDb) 900 901 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, mock.NewMock(), vm.Config{}) 902 if n, err := archive.InsertChain(blocks); err != nil { 903 t.Fatalf("failed to process block %d: %v", n, err) 904 } 905 defer archive.Stop() 906 907 assert(t, "archive", archive, height, height, height) 908 archive.Rollback(remove) 909 assert(t, "archive", archive, height/2, height/2, height/2) 910 911 // Import the chain as a non-archive node and ensure all pointers are updated 912 fastDb := vntdb.NewMemDatabase() 913 gspec.MustCommit(fastDb) 914 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, mock.NewMock(), vm.Config{}) 915 defer fast.Stop() 916 917 headers := make([]*types.Header, len(blocks)) 918 for i, block := range blocks { 919 headers[i] = block.Header() 920 } 921 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 922 t.Fatalf("failed to insert header %d: %v", n, err) 923 } 924 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 925 t.Fatalf("failed to insert receipt %d: %v", n, err) 926 } 927 assert(t, "fast", fast, height, height, 0) 928 fast.Rollback(remove) 929 assert(t, "fast", fast, height/2, height/2, 0) 930 931 // Import the chain as a light node and ensure all pointers are updated 932 lightDb := vntdb.NewMemDatabase() 933 gspec.MustCommit(lightDb) 934 935 light, _ := NewBlockChain(lightDb, nil, gspec.Config, mock.NewMock(), vm.Config{}) 936 if n, err := light.InsertHeaderChain(headers, 1); err != nil { 937 t.Fatalf("failed to insert header %d: %v", n, err) 938 } 939 defer light.Stop() 940 941 assert(t, "light", light, height, 0, 0) 942 light.Rollback(remove) 943 assert(t, "light", light, height/2, 0, 0) 944 } 945 946 // Tests that chain reorganisations handle transaction removals and reinsertions. 947 func TestChainTxReorgs(t *testing.T) { 948 var ( 949 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 950 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 951 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 952 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 953 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 954 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 955 db = vntdb.NewMemDatabase() 956 gspec = &Genesis{ 957 Config: params.TestChainConfig, 958 GasLimit: 3141592, 959 Alloc: GenesisAlloc{ 960 addr1: {Balance: big.NewInt(1000000)}, 961 addr2: {Balance: big.NewInt(1000000)}, 962 addr3: {Balance: big.NewInt(1000000)}, 963 }, 964 } 965 genesis = gspec.MustCommit(db) 966 signer = types.NewHubbleSigner(gspec.Config.ChainID) 967 ) 968 969 // Create three transactions shared between the chains: 970 // - shared: transaction included at both chain 971 // - removed: transaction included at the forked chain, will be removed 972 // - added : transaction included at the main chain 973 shared, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 974 removed, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 975 added, _ := types.SignTx(types.NewTransaction(0, addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 976 977 chain, _ := GenerateChain(gspec.Config, genesis, mock.NewMock(), db, 3, func(i int, gen *BlockGen) { 978 switch i { 979 case 2: 980 gen.AddTx(shared) 981 gen.AddTx(removed) 982 983 gen.OffsetTime(2) // Later block timestamp to make it a forked chain 984 } 985 }) 986 // Import the chain. This runs all block validation rules. 987 blockchain, _ := NewBlockChain(db, nil, gspec.Config, mock.NewMock(), vm.Config{}) 988 if i, err := blockchain.InsertChain(chain); err != nil { 989 t.Fatalf("failed to insert original fork chain[%d]: %v", i, err) 990 } 991 defer blockchain.Stop() 992 993 // generate main chain, overwrite the old chain 994 chain, _ = GenerateChain(gspec.Config, genesis, mock.NewMock(), db, 3, func(i int, gen *BlockGen) { 995 switch i { 996 case 2: 997 gen.AddTx(shared) 998 gen.AddTx(added) 999 } 1000 }) 1001 if _, err := blockchain.InsertChain(chain); err != nil { 1002 t.Fatalf("failed to insert main chain: %v", err) 1003 } 1004 1005 // removed tx 1006 for i, tx := range (types.Transactions{removed}) { 1007 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil { 1008 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 1009 } 1010 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt != nil { 1011 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 1012 } 1013 } 1014 // added tx 1015 for i, tx := range (types.Transactions{added}) { 1016 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 1017 t.Errorf("add %d: expected tx to be found", i) 1018 } 1019 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil { 1020 t.Errorf("add %d: expected receipt to be found", i) 1021 } 1022 } 1023 // shared tx 1024 for i, tx := range (types.Transactions{shared}) { 1025 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 1026 t.Errorf("share %d: expected tx to be found", i) 1027 } 1028 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil { 1029 t.Errorf("share %d: expected receipt to be found", i) 1030 } 1031 } 1032 } 1033 1034 func TestLogReorgs(t *testing.T) { 1035 var ( 1036 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1037 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1038 db = vntdb.NewMemDatabase() 1039 // this code generates a log 1040 code = common.Hex2Bytes("0161736db9052f0100789c9c56db6f145518ff9d397ba6ed0eddeeb260b90418168818ebf6226db0722b21624d480c589110b29ddd39dd8eccced499d94221ddaec5101e7df4c542bcbc181f8cf1414a4cfc177cf1091e144d4c88461a0c2185c47c33b317290fc47998effb7ee7fbfdbe739b39e75157f966e71730fc0a03c0328949a556c324ab611298640b500cc1a5339b3eed59813c6d05d36fbb9613480f20b8e7a434cc35a83a669ac70d1f8c82ecb8630596615b97e4bb866719455bfa50a84578d2f5cae03cc11545490836c318139c415137f20536f6f1b584b68086b9daa9751c116a45565c6f4e8156284c4b63a650347cc959b250308dc02848c7e44ada9425dbf0a4f946d5290596eb401527c3521dc9fd5c81b61d477114e97abd5e8fbc0f232fbd4856db80f41572c6ead7ea75a43f0a41ad9b61acdea9a951a7f1806b795316abe582e54cb9bf3120017a12348f58875d881e37b60300146acb003801804fd06b32e40800db01fc486b70577c42e61c536f84d606a07e13ba3e65777c154a75d600dc2478a0eb0ac1df511e4b528de3007ea2a67bb719a06e634d776bd3d57690fb27b9eba83fc3007a88f357d429844a53007e2774a5a5b4d2525a6929fdd354ea059022ce83b631862def346a3c6caf4195ef13badaaab1daaa11badd27e279644f626a8aa847003c21148cb27a426eec6f6df9e9b0874ae86748691371388ba5c235530074314049247603d8006023856a38d177883004a453f1aa578c122d3c709575c790673865e9d3fa6601ec00f0325a4f1f803c80210087da70aabd1e00ed815d71fc666ccbb11d89ed586c3900eae4fe361d3c6e76c428163d39cb326c4f2a2b782addbb35956113bd80926719b65e1dcc025c804c220f42786a547b5d3bbc19107916052f6e3ebc59d700552002c6b340c76ef0d4214dd380ce17309e8d5a80ae1e507332d26f088c674951dbd726b06e1b1bcc52ce7bda190de8a670a2370a526d6cd160f7c4e505b1d3fbda824c934b53876f138d0fd2b61c9953e883fc8ce68bb1d554371916cd1eeb9ff0a5e7f75f90966f5897a60da7dc7fcc2d552bd209fcfea21b04b67c25907ed05f729dc0334a818fe7a614ab966db61131eb04b655cc4f53e5f0275498f164c9adcc58b6cc97c25d0711fe18f81d30d191dc29c4b4caaf2f2c0aa6f2bbd01506c620141a24bf4b3fc8e499eb57042b371a42ee3dc6444ff2a0d06e893dea8a183c20f62e890e95dfaf2d0a7188f4960557f9df4c57781b6d8531a1250f0a5dedd429fd5e4d1762204ad754fe90e94257df123d6a9fd06f88017551f42e096d8a52ffa84db52b3f7a4a793554de29b6a83f53f6af355d24f97596175c5de28b5446e5bf80c04f19092cfd673875a5399c2deab2d075b12b2f869649e9764d179c7fc9f22a7f3c7fa021c3f9e76c39ec40428945360a96dc19aa86107d2f9b044be684280b762b2af7b5928c378d1f7825db70cafaacf47ccb75f4fdf981fc80be37f0aace79fdd57d83af8d0cbcf4bff741ff3396fe79b570527e50b53c8992eb9856789e158ebaae8d8a5f4669daf0e0079ee594b1e6d89b181a1e39654cc913551b55cb098686479ad8316bb6e99faa169bfe9869e2bc9c9b9b7582f787e766a23d8b395cc425e072c2312a92059d58731f604f5f0594f816c09f7501484467bfc8140a170cbf522819b65d2805aee7ab6b4eef8ee8f0fefe87b39773543e379a0b815c5faee43a7e6038416e74cab07dd997b39c996ae0e746cf9eebcbb9d5a015047333440c095e952ae5e6fb9a7a5eac6738ae335771abfe5ac1666ec5a7cc582f9af91ce599f2a23463de7caba29c954e909b3f57ff170000ffff") 1041 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18))}}} 1042 genesis = gspec.MustCommit(db) 1043 signer = types.NewHubbleSigner(gspec.Config.ChainID) 1044 ) 1045 1046 blockchain, _ := NewBlockChain(db, nil, gspec.Config, mock.NewMock(), vm.Config{}) 1047 defer blockchain.Stop() 1048 1049 rmLogsCh := make(chan RemovedLogsEvent) 1050 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 1051 chain, _ := GenerateChain(params.TestChainConfig, genesis, mock.NewMock(), db, 3, func(i int, gen *BlockGen) { 1052 if i == 2 { 1053 gen.OffsetTime(2) 1054 1055 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 1056 if err != nil { 1057 t.Fatalf("failed to create tx: %v", err) 1058 } 1059 gen.AddTx(tx) 1060 } 1061 }) 1062 if _, err := blockchain.InsertChain(chain); err != nil { 1063 t.Fatalf("failed to insert chain: %v", err) 1064 } 1065 1066 // fork chain should to be canonical chain 1067 chain, _ = GenerateChain(params.TestChainConfig, genesis, mock.NewMock(), db, 3, func(i int, gen *BlockGen) {}) 1068 if _, err := blockchain.InsertChain(chain); err != nil { 1069 t.Fatalf("failed to insert forked chain: %v", err) 1070 } 1071 1072 timeout := time.NewTimer(1 * time.Second) 1073 select { 1074 case ev := <-rmLogsCh: 1075 if len(ev.Logs) == 0 { 1076 t.Error("expected logs") 1077 } 1078 case <-timeout.C: 1079 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 1080 } 1081 } 1082 1083 // Tests if the canonical block can be fetched from the database during chain insertion. 1084 func TestCanonicalBlockRetrieval(t *testing.T) { 1085 _, blockchain, err := newCanonical(mock.NewMock(), 0, true) 1086 if err != nil { 1087 t.Fatalf("failed to create pristine chain: %v", err) 1088 } 1089 defer blockchain.Stop() 1090 1091 chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, mock.NewMock(), blockchain.db, 10, func(i int, gen *BlockGen) {}) 1092 1093 var pend sync.WaitGroup 1094 pend.Add(len(chain)) 1095 1096 for i := range chain { 1097 go func(block *types.Block) { 1098 defer pend.Done() 1099 1100 // try to retrieve a block by its canonical hash and see if the block data can be retrieved. 1101 for { 1102 ch := rawdb.ReadCanonicalHash(blockchain.db, block.NumberU64()) 1103 if ch == (common.Hash{}) { 1104 continue // busy wait for canonical hash to be written 1105 } 1106 if ch != block.Hash() { 1107 t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1108 } 1109 fb := rawdb.ReadBlock(blockchain.db, ch, block.NumberU64()) 1110 if fb == nil { 1111 t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1112 } 1113 if fb.Hash() != block.Hash() { 1114 t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1115 } 1116 return 1117 } 1118 }(chain[i]) 1119 1120 if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { 1121 t.Fatalf("failed to insert block %d: %v", i, err) 1122 } 1123 } 1124 pend.Wait() 1125 } 1126 1127 func TestEIP155Transition(t *testing.T) { 1128 // Configure and generate a sample block chain 1129 var ( 1130 db = vntdb.NewMemDatabase() 1131 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1132 address = crypto.PubkeyToAddress(key.PublicKey) 1133 funds = big.NewInt(1000000000) 1134 deleteAddr = common.Address{1} 1135 gspec = &Genesis{ 1136 Config: ¶ms.ChainConfig{ChainID: big.NewInt(1), HubbleBlock: new(big.Int)}, 1137 Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 1138 } 1139 genesis = gspec.MustCommit(db) 1140 ) 1141 1142 blockchain, _ := NewBlockChain(db, nil, gspec.Config, mock.NewMock(), vm.Config{}) 1143 defer blockchain.Stop() 1144 1145 blocks, _ := GenerateChain(gspec.Config, genesis, mock.NewMock(), db, 4, func(i int, block *BlockGen) { 1146 var ( 1147 tx *types.Transaction 1148 err error 1149 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1150 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1151 } 1152 ) 1153 switch i { 1154 case 0: 1155 tx, err = basicTx(types.NewHubbleSigner(gspec.Config.ChainID)) 1156 if err != nil { 1157 t.Fatal(err) 1158 } 1159 block.AddTx(tx) 1160 case 2: 1161 tx, err = basicTx(types.NewHubbleSigner(gspec.Config.ChainID)) 1162 if err != nil { 1163 t.Fatal(err) 1164 } 1165 block.AddTx(tx) 1166 1167 tx, err = basicTx(types.NewHubbleSigner(gspec.Config.ChainID)) 1168 if err != nil { 1169 t.Fatal(err) 1170 } 1171 block.AddTx(tx) 1172 case 3: 1173 tx, err = basicTx(types.NewHubbleSigner(gspec.Config.ChainID)) 1174 if err != nil { 1175 t.Fatal(err) 1176 } 1177 block.AddTx(tx) 1178 1179 tx, err = basicTx(types.NewHubbleSigner(gspec.Config.ChainID)) 1180 if err != nil { 1181 t.Fatal(err) 1182 } 1183 block.AddTx(tx) 1184 } 1185 }) 1186 1187 if _, err := blockchain.InsertChain(blocks); err != nil { 1188 t.Fatal(err) 1189 } 1190 block := blockchain.GetBlockByNumber(1) 1191 if !block.Transactions()[0].Protected() { 1192 t.Error("Expected block[0].txs[0] to be replay protected") 1193 } 1194 1195 block = blockchain.GetBlockByNumber(3) 1196 if !block.Transactions()[0].Protected() { 1197 t.Error("Expected block[3].txs[0] to be replay protected") 1198 } 1199 if !block.Transactions()[1].Protected() { 1200 t.Error("Expected block[3].txs[1] to be replay protected") 1201 } 1202 if _, err := blockchain.InsertChain(blocks[4:]); err != nil { 1203 t.Fatal(err) 1204 } 1205 1206 // generate an invalid chain id transaction 1207 config := ¶ms.ChainConfig{ChainID: big.NewInt(2), HubbleBlock: new(big.Int)} 1208 blocks, _ = GenerateChain(config, blocks[len(blocks)-1], mock.NewMock(), db, 4, func(i int, block *BlockGen) { 1209 var ( 1210 tx *types.Transaction 1211 err error 1212 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1213 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1214 } 1215 ) 1216 switch i { 1217 case 0: 1218 tx, err = basicTx(types.NewHubbleSigner(big.NewInt(2))) 1219 if err != nil { 1220 t.Fatal(err) 1221 } 1222 block.AddTx(tx) 1223 } 1224 }) 1225 _, err := blockchain.InsertChain(blocks) 1226 if err != types.ErrInvalidChainId { 1227 t.Error("expected error:", types.ErrInvalidChainId) 1228 } 1229 } 1230 1231 func TestEIP161AccountRemoval(t *testing.T) { 1232 // Configure and generate a sample block chain 1233 var ( 1234 db = vntdb.NewMemDatabase() 1235 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1236 address = crypto.PubkeyToAddress(key.PublicKey) 1237 funds = big.NewInt(1000000000) 1238 theAddr = common.Address{1} 1239 gspec = &Genesis{ 1240 Config: ¶ms.ChainConfig{ 1241 ChainID: big.NewInt(1), 1242 HubbleBlock: new(big.Int), 1243 }, 1244 Alloc: GenesisAlloc{address: {Balance: funds}}, 1245 } 1246 genesis = gspec.MustCommit(db) 1247 ) 1248 blockchain, _ := NewBlockChain(db, nil, gspec.Config, mock.NewMock(), vm.Config{}) 1249 defer blockchain.Stop() 1250 1251 blocks, _ := GenerateChain(gspec.Config, genesis, mock.NewMock(), db, 3, func(i int, block *BlockGen) { 1252 var ( 1253 tx *types.Transaction 1254 err error 1255 signer = types.NewHubbleSigner(gspec.Config.ChainID) 1256 ) 1257 switch i { 1258 case 0: 1259 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1260 case 1: 1261 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1262 case 2: 1263 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1264 } 1265 if err != nil { 1266 t.Fatal(err) 1267 } 1268 block.AddTx(tx) 1269 }) 1270 1271 // account must exist pre eip 161 1272 if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1273 t.Fatal(err) 1274 } 1275 if st, _ := blockchain.State(); st.Exist(theAddr) { 1276 t.Error("account should not exist") 1277 } 1278 1279 // account needs to be deleted post eip 161 1280 if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1281 t.Fatal(err) 1282 } 1283 if st, _ := blockchain.State(); st.Exist(theAddr) { 1284 t.Error("account should not exist") 1285 } 1286 1287 // account musn't be created post eip 161 1288 if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1289 t.Fatal(err) 1290 } 1291 if st, _ := blockchain.State(); st.Exist(theAddr) { 1292 t.Error("account should not exist") 1293 } 1294 } 1295 1296 // Benchmarks large blocks with value transfers to non-existing accounts 1297 func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) { 1298 var ( 1299 signer = types.HubbleSigner{} 1300 testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1301 testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) 1302 bankFunds = big.NewInt(100000000000000000) 1303 gspec = Genesis{ 1304 Config: params.TestChainConfig, 1305 Alloc: GenesisAlloc{ 1306 testBankAddress: {Balance: bankFunds}, 1307 common.HexToAddress("0xc0de"): { 1308 Code: []byte{0x60, 0x01, 0x50}, 1309 Balance: big.NewInt(0), 1310 }, // push 1, pop 1311 }, 1312 GasLimit: 100e6, // 100 M 1313 } 1314 ) 1315 // Generate the original common chain segment and the two competing forks 1316 engine := mock.NewMock() 1317 db := vntdb.NewMemDatabase() 1318 genesis := gspec.MustCommit(db) 1319 1320 blockGenerator := func(i int, block *BlockGen) { 1321 block.SetCoinbase(common.Address{1}) 1322 for txi := 0; txi < numTxs; txi++ { 1323 uniq := uint64(i*numTxs + txi) 1324 recipient := recipientFn(uniq) 1325 //recipient := common.BigToAddress(big.NewInt(0).SetUint64(1337 + uniq)) 1326 tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey) 1327 if err != nil { 1328 b.Error(err) 1329 } 1330 block.AddTx(tx) 1331 } 1332 } 1333 1334 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator) 1335 b.StopTimer() 1336 b.ResetTimer() 1337 for i := 0; i < b.N; i++ { 1338 // Import the shared chain and the original canonical one 1339 diskdb := vntdb.NewMemDatabase() 1340 gspec.MustCommit(diskdb) 1341 1342 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1343 if err != nil { 1344 b.Fatalf("failed to create tester chain: %v", err) 1345 } 1346 b.StartTimer() 1347 if _, err := chain.InsertChain(shared); err != nil { 1348 b.Fatalf("failed to insert shared chain: %v", err) 1349 } 1350 b.StopTimer() 1351 if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { 1352 b.Fatalf("Transactions were not included, expected %d, got %d", (numTxs * numBlocks), got) 1353 1354 } 1355 } 1356 } 1357 func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) { 1358 var ( 1359 numTxs = 1000 1360 numBlocks = 1 1361 ) 1362 1363 recipientFn := func(nonce uint64) common.Address { 1364 return common.BigToAddress(big.NewInt(0).SetUint64(1337 + nonce)) 1365 } 1366 dataFn := func(nonce uint64) []byte { 1367 return nil 1368 } 1369 1370 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1371 } 1372 func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) { 1373 var ( 1374 numTxs = 1000 1375 numBlocks = 1 1376 ) 1377 b.StopTimer() 1378 b.ResetTimer() 1379 1380 recipientFn := func(nonce uint64) common.Address { 1381 return common.BigToAddress(big.NewInt(0).SetUint64(1337)) 1382 } 1383 dataFn := func(nonce uint64) []byte { 1384 return nil 1385 } 1386 1387 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1388 } 1389 func BenchmarkBlockChain_1x1000Executions(b *testing.B) { 1390 var ( 1391 numTxs = 1000 1392 numBlocks = 1 1393 ) 1394 b.StopTimer() 1395 b.ResetTimer() 1396 1397 recipientFn := func(nonce uint64) common.Address { 1398 return common.BigToAddress(big.NewInt(0).SetUint64(0xc0de)) 1399 } 1400 dataFn := func(nonce uint64) []byte { 1401 return nil 1402 } 1403 1404 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1405 }