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  */