github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/light/lightchain_test.go (about) 1 // Copyright 2016 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 light 18 19 import ( 20 "context" 21 "github.com/PlatONnetwork/PlatON-Go/consensus/cbft" 22 "math/big" 23 "testing" 24 25 "github.com/PlatONnetwork/PlatON-Go/common" 26 "github.com/PlatONnetwork/PlatON-Go/core" 27 "github.com/PlatONnetwork/PlatON-Go/core/rawdb" 28 "github.com/PlatONnetwork/PlatON-Go/core/types" 29 "github.com/PlatONnetwork/PlatON-Go/ethdb" 30 "github.com/PlatONnetwork/PlatON-Go/params" 31 ) 32 33 // So we can deterministically seed different blockchains 34 var ( 35 canonicalSeed = 1 36 forkSeed = 2 37 ) 38 39 // makeHeaderChain creates a deterministic chain of headers rooted at parent. 40 func makeHeaderChain(parent *types.Header, n int, db ethdb.Database, seed int) []*types.Header { 41 blocks, _ := core.GenerateChain(params.TestChainConfig, types.NewBlockWithHeader(parent), cbft.NewFaker(), db, n, func(i int, b *core.BlockGen) { 42 b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) 43 }) 44 headers := make([]*types.Header, len(blocks)) 45 for i, block := range blocks { 46 headers[i] = block.Header() 47 } 48 return headers 49 } 50 51 // newCanonical creates a chain database, and injects a deterministic canonical 52 // chain. Depending on the full flag, if creates either a full block chain or a 53 // header only chain. 54 func newCanonical(n int) (ethdb.Database, *LightChain, error) { 55 db := ethdb.NewMemDatabase() 56 gspec := core.Genesis{Config: params.TestChainConfig} 57 genesis := gspec.MustCommit(db) 58 blockchain, _ := NewLightChain(&dummyOdr{db: db, indexerConfig: TestClientIndexerConfig}, gspec.Config, cbft.NewFaker()) 59 60 // Create and inject the requested chain 61 if n == 0 { 62 return db, blockchain, nil 63 } 64 // Header-only chain requested 65 headers := makeHeaderChain(genesis.Header(), n, db, canonicalSeed) 66 _, err := blockchain.InsertHeaderChain(headers, 1) 67 return db, blockchain, err 68 } 69 70 // newTestLightChain creates a LightChain that doesn't validate anything. 71 func newTestLightChain() *LightChain { 72 db := ethdb.NewMemDatabase() 73 gspec := &core.Genesis{ 74 Config: params.TestChainConfig, 75 } 76 gspec.MustCommit(db) 77 lc, err := NewLightChain(&dummyOdr{db: db}, gspec.Config, cbft.NewFaker()) 78 if err != nil { 79 panic(err) 80 } 81 return lc 82 } 83 84 // Test fork of length N starting from block i 85 func testFork(t *testing.T, LightChain *LightChain, i, n int, comparator func(td1, td2 *big.Int)) { 86 // Copy old chain up to #i into a new db 87 db, LightChain2, err := newCanonical(i) 88 if err != nil { 89 t.Fatal("could not make new canonical in testFork", err) 90 } 91 // Assert the chains have the same header/block at #i 92 var hash1, hash2 common.Hash 93 hash1 = LightChain.GetHeaderByNumber(uint64(i)).Hash() 94 hash2 = LightChain2.GetHeaderByNumber(uint64(i)).Hash() 95 if hash1 != hash2 { 96 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 97 } 98 // Extend the newly created chain 99 headerChainB := makeHeaderChain(LightChain2.CurrentHeader(), n, db, forkSeed) 100 if _, err := LightChain2.InsertHeaderChain(headerChainB, 1); err != nil { 101 t.Fatalf("failed to insert forking chain: %v", err) 102 } 103 } 104 105 // testHeaderChainImport tries to process a chain of header, writing them into 106 // the database if successful. 107 func testHeaderChainImport(chain []*types.Header, lightchain *LightChain) error { 108 for _, header := range chain { 109 // Try and validate the header 110 if err := lightchain.engine.VerifyHeader(lightchain.hc, header, true); err != nil { 111 return err 112 } 113 // Manually insert the header into the database, but don't reorganize (allows subsequent testing) 114 lightchain.mu.Lock() 115 116 rawdb.WriteHeader(lightchain.chainDb, header) 117 lightchain.mu.Unlock() 118 } 119 return nil 120 } 121 122 // Tests that given a starting canonical chain of a given size, it can be extended 123 // with various length chains. 124 /*func TestExtendCanonicalHeaders(t *testing.T) { 125 length := 5 126 127 // Make first chain starting from genesis 128 _, processor, err := newCanonical(length) 129 if err != nil { 130 t.Fatalf("failed to make new canonical chain: %v", err) 131 } 132 // Define the difficulty comparator 133 better := func(td1, td2 *big.Int) { 134 if td2.Cmp(td1) <= 0 { 135 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 136 } 137 } 138 // Start fork from current height 139 testFork(t, processor, length, 1, better) 140 testFork(t, processor, length, 2, better) 141 testFork(t, processor, length, 5, better) 142 testFork(t, processor, length, 10, better) 143 }*/ 144 145 // Tests that given a starting canonical chain of a given size, creating shorter 146 // forks do not take canonical ownership. 147 /*func TestShorterForkHeaders(t *testing.T) { 148 length := 10 149 150 // Make first chain starting from genesis 151 _, processor, err := newCanonical(length) 152 if err != nil { 153 t.Fatalf("failed to make new canonical chain: %v", err) 154 } 155 // Define the difficulty comparator 156 worse := func(td1, td2 *big.Int) { 157 if td2.Cmp(td1) >= 0 { 158 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 159 } 160 } 161 // Sum of numbers must be less than `length` for this to be a shorter fork 162 testFork(t, processor, 0, 3, worse) 163 testFork(t, processor, 0, 7, worse) 164 testFork(t, processor, 1, 1, worse) 165 testFork(t, processor, 1, 7, worse) 166 testFork(t, processor, 5, 3, worse) 167 testFork(t, processor, 5, 4, worse) 168 }*/ 169 170 // Tests that given a starting canonical chain of a given size, creating longer 171 // forks do take canonical ownership. 172 /*func TestLongerForkHeaders(t *testing.T) { 173 length := 10 174 175 // Make first chain starting from genesis 176 _, processor, err := newCanonical(length) 177 if err != nil { 178 t.Fatalf("failed to make new canonical chain: %v", err) 179 } 180 // Define the difficulty comparator 181 better := func(td1, td2 *big.Int) { 182 if td2.Cmp(td1) <= 0 { 183 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 184 } 185 } 186 // Sum of numbers must be greater than `length` for this to be a longer fork 187 testFork(t, processor, 0, 11, better) 188 testFork(t, processor, 0, 15, better) 189 testFork(t, processor, 1, 10, better) 190 testFork(t, processor, 1, 12, better) 191 testFork(t, processor, 5, 6, better) 192 testFork(t, processor, 5, 8, better) 193 }*/ 194 195 // Tests that given a starting canonical chain of a given size, creating equal 196 // forks do take canonical ownership. 197 /*func TestEqualForkHeaders(t *testing.T) { 198 length := 10 199 200 // Make first chain starting from genesis 201 _, processor, err := newCanonical(length) 202 if err != nil { 203 t.Fatalf("failed to make new canonical chain: %v", err) 204 } 205 // Define the difficulty comparator 206 equal := func(td1, td2 *big.Int) { 207 if td2.Cmp(td1) != 0 { 208 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 209 } 210 } 211 // Sum of numbers must be equal to `length` for this to be an equal fork 212 testFork(t, processor, 0, 10, equal) 213 testFork(t, processor, 1, 9, equal) 214 testFork(t, processor, 2, 8, equal) 215 testFork(t, processor, 5, 5, equal) 216 testFork(t, processor, 6, 4, equal) 217 testFork(t, processor, 9, 1, equal) 218 }*/ 219 220 // Tests that chains missing links do not get accepted by the processor. 221 /*func TestBrokenHeaderChain(t *testing.T) { 222 // Make chain starting from genesis 223 db, LightChain, err := newCanonical(10) 224 if err != nil { 225 t.Fatalf("failed to make new canonical chain: %v", err) 226 } 227 // Create a forked chain, and try to insert with a missing link 228 chain := makeHeaderChain(LightChain.CurrentHeader(), 5, db, forkSeed)[1:] 229 if err := testHeaderChainImport(chain, LightChain); err == nil { 230 t.Errorf("broken header chain not reported") 231 } 232 }*/ 233 234 func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Header { 235 var chain []*types.Header 236 for i, _ := range d { 237 header := &types.Header{ 238 Coinbase: common.Address{seed}, 239 Number: big.NewInt(int64(i + 1)), 240 UncleHash: types.EmptyUncleHash, 241 TxHash: types.EmptyRootHash, 242 ReceiptHash: types.EmptyRootHash, 243 } 244 if i == 0 { 245 header.ParentHash = genesis.Hash() 246 } else { 247 header.ParentHash = chain[i-1].Hash() 248 } 249 chain = append(chain, types.CopyHeader(header)) 250 } 251 return chain 252 } 253 254 type dummyOdr struct { 255 OdrBackend 256 db ethdb.Database 257 indexerConfig *IndexerConfig 258 } 259 260 func (odr *dummyOdr) Database() ethdb.Database { 261 return odr.db 262 } 263 264 func (odr *dummyOdr) Retrieve(ctx context.Context, req OdrRequest) error { 265 return nil 266 } 267 268 func (odr *dummyOdr) IndexerConfig() *IndexerConfig { 269 return odr.indexerConfig 270 } 271 272 // Tests that reorganizing a long difficult chain after a short easy one 273 // overwrites the canonical numbers and links in the database. 274 /*func TestReorgLongHeaders(t *testing.T) { 275 testReorg(t, []int{1, 2, 4}, []int{1, 2, 3, 4}, 10) 276 }*/ 277 278 // Tests that reorganizing a short difficult chain after a long easy one 279 // overwrites the canonical numbers and links in the database. 280 /*func TestReorgShortHeaders(t *testing.T) { 281 testReorg(t, []int{1, 2, 3, 4}, []int{1, 10}, 11) 282 }*/ 283 284 func testReorg(t *testing.T, first, second []int, td int64) { 285 bc := newTestLightChain() 286 287 // Insert an easy and a difficult chain afterwards 288 bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, first, 11), 1) 289 bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, second, 22), 1) 290 // Check that the chain is valid number and link wise 291 prev := bc.CurrentHeader() 292 for header := bc.GetHeaderByNumber(bc.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, bc.GetHeaderByNumber(header.Number.Uint64()-1) { 293 if prev.ParentHash != header.Hash() { 294 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 295 } 296 } 297 298 } 299 300 // Tests that the insertion functions detect banned hashes. 301 /*func TestBadHeaderHashes(t *testing.T) { 302 bc := newTestLightChain() 303 304 // Create a chain, ban a hash and try to import 305 var err error 306 headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10) 307 core.BadHashes[headers[2].Hash()] = true 308 if _, err = bc.InsertHeaderChain(headers, 1); err != core.ErrBlacklistedHash { 309 t.Errorf("error mismatch: have: %v, want %v", err, core.ErrBlacklistedHash) 310 } 311 }*/ 312 313 // Tests that bad hashes are detected on boot, and the chan rolled back to a 314 // good state prior to the bad hash. 315 /*func TestReorgBadHeaderHashes(t *testing.T) { 316 bc := newTestLightChain() 317 318 // Create a chain, import and ban afterwards 319 headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10) 320 321 if _, err := bc.InsertHeaderChain(headers, 1); err != nil { 322 t.Fatalf("failed to import headers: %v", err) 323 } 324 if bc.CurrentHeader().Hash() != headers[3].Hash() { 325 t.Errorf("last header hash mismatch: have: %x, want %x", bc.CurrentHeader().Hash(), headers[3].Hash()) 326 } 327 core.BadHashes[headers[3].Hash()] = true 328 defer func() { delete(core.BadHashes, headers[3].Hash()) }() 329 330 // Create a new LightChain and check that it rolled back the state. 331 ncm, err := NewLightChain(&dummyOdr{db: bc.chainDb}, params.TestChainConfig, cbft.NewFaker()) 332 if err != nil { 333 t.Fatalf("failed to create new chain manager: %v", err) 334 } 335 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 336 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 337 } 338 } 339 */