github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/light/lightchain_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:41</date>
    10  //</624342645484818432>
    11  
    12  
    13  package light
    14  
    15  import (
    16  	"context"
    17  	"math/big"
    18  	"testing"
    19  
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/consensus/ethash"
    22  	"github.com/ethereum/go-ethereum/core"
    23  	"github.com/ethereum/go-ethereum/core/rawdb"
    24  	"github.com/ethereum/go-ethereum/core/types"
    25  	"github.com/ethereum/go-ethereum/ethdb"
    26  	"github.com/ethereum/go-ethereum/params"
    27  )
    28  
    29  //所以我们可以确定地植入不同的区块链
    30  var (
    31  	canonicalSeed = 1
    32  	forkSeed      = 2
    33  )
    34  
    35  //MakeHeaderChain创建一个以父级为根的具有确定性的头链。
    36  func makeHeaderChain(parent *types.Header, n int, db ethdb.Database, seed int) []*types.Header {
    37  	blocks, _ := core.GenerateChain(params.TestChainConfig, types.NewBlockWithHeader(parent), ethash.NewFaker(), db, n, func(i int, b *core.BlockGen) {
    38  		b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
    39  	})
    40  	headers := make([]*types.Header, len(blocks))
    41  	for i, block := range blocks {
    42  		headers[i] = block.Header()
    43  	}
    44  	return headers
    45  }
    46  
    47  //newcanonical创建一个链数据库,并注入一个确定性canonical
    48  //链。根据完整标志,如果创建完整的区块链或
    49  //仅限收割台链条。
    50  func newCanonical(n int) (ethdb.Database, *LightChain, error) {
    51  	db := ethdb.NewMemDatabase()
    52  	gspec := core.Genesis{Config: params.TestChainConfig}
    53  	genesis := gspec.MustCommit(db)
    54  	blockchain, _ := NewLightChain(&dummyOdr{db: db}, gspec.Config, ethash.NewFaker())
    55  
    56  //创建并注入请求的链
    57  	if n == 0 {
    58  		return db, blockchain, nil
    59  	}
    60  //仅请求头链
    61  	headers := makeHeaderChain(genesis.Header(), n, db, canonicalSeed)
    62  	_, err := blockchain.InsertHeaderChain(headers, 1)
    63  	return db, blockchain, err
    64  }
    65  
    66  //NewTestLightChain创建了一个不验证任何内容的LightChain。
    67  func newTestLightChain() *LightChain {
    68  	db := ethdb.NewMemDatabase()
    69  	gspec := &core.Genesis{
    70  		Difficulty: big.NewInt(1),
    71  		Config:     params.TestChainConfig,
    72  	}
    73  	gspec.MustCommit(db)
    74  	lc, err := NewLightChain(&dummyOdr{db: db}, gspec.Config, ethash.NewFullFaker())
    75  	if err != nil {
    76  		panic(err)
    77  	}
    78  	return lc
    79  }
    80  
    81  //从I区开始的长度为n的测试叉
    82  func testFork(t *testing.T, LightChain *LightChain, i, n int, comparator func(td1, td2 *big.Int)) {
    83  //将旧链复制到新数据库中
    84  	db, LightChain2, err := newCanonical(i)
    85  	if err != nil {
    86  		t.Fatal("could not make new canonical in testFork", err)
    87  	}
    88  //断言链在i处具有相同的头/块
    89  	var hash1, hash2 common.Hash
    90  	hash1 = LightChain.GetHeaderByNumber(uint64(i)).Hash()
    91  	hash2 = LightChain2.GetHeaderByNumber(uint64(i)).Hash()
    92  	if hash1 != hash2 {
    93  		t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1)
    94  	}
    95  //扩展新创建的链
    96  	headerChainB := makeHeaderChain(LightChain2.CurrentHeader(), n, db, forkSeed)
    97  	if _, err := LightChain2.InsertHeaderChain(headerChainB, 1); err != nil {
    98  		t.Fatalf("failed to insert forking chain: %v", err)
    99  	}
   100  //健全性检查叉链是否可以导入原始
   101  	var tdPre, tdPost *big.Int
   102  
   103  	tdPre = LightChain.GetTdByHash(LightChain.CurrentHeader().Hash())
   104  	if err := testHeaderChainImport(headerChainB, LightChain); err != nil {
   105  		t.Fatalf("failed to import forked header chain: %v", err)
   106  	}
   107  	tdPost = LightChain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash())
   108  //比较链条的总难度
   109  	comparator(tdPre, tdPost)
   110  }
   111  
   112  //testHeaderChainimport尝试处理一个头链,将其写入
   113  //如果成功,则返回数据库。
   114  func testHeaderChainImport(chain []*types.Header, lightchain *LightChain) error {
   115  	for _, header := range chain {
   116  //尝试验证标题
   117  		if err := lightchain.engine.VerifyHeader(lightchain.hc, header, true); err != nil {
   118  			return err
   119  		}
   120  //手动将头插入数据库,但不重新组织(允许后续测试)
   121  		lightchain.mu.Lock()
   122  		rawdb.WriteTd(lightchain.chainDb, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, lightchain.GetTdByHash(header.ParentHash)))
   123  		rawdb.WriteHeader(lightchain.chainDb, header)
   124  		lightchain.mu.Unlock()
   125  	}
   126  	return nil
   127  }
   128  
   129  //测试给定一个给定大小的起始规范链,它可以被扩展
   130  //有各种长度的链条。
   131  func TestExtendCanonicalHeaders(t *testing.T) {
   132  	length := 5
   133  
   134  //从创世纪开始制造第一条链条
   135  	_, processor, err := newCanonical(length)
   136  	if err != nil {
   137  		t.Fatalf("failed to make new canonical chain: %v", err)
   138  	}
   139  //定义难度比较器
   140  	better := func(td1, td2 *big.Int) {
   141  		if td2.Cmp(td1) <= 0 {
   142  			t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1)
   143  		}
   144  	}
   145  //从当前高度开始拨叉
   146  	testFork(t, processor, length, 1, better)
   147  	testFork(t, processor, length, 2, better)
   148  	testFork(t, processor, length, 5, better)
   149  	testFork(t, processor, length, 10, better)
   150  }
   151  
   152  //测试给定给定大小的起始规范链,创建较短的
   153  //forks不具有规范的所有权。
   154  func TestShorterForkHeaders(t *testing.T) {
   155  	length := 10
   156  
   157  //从创世纪开始制造第一条链条
   158  	_, processor, err := newCanonical(length)
   159  	if err != nil {
   160  		t.Fatalf("failed to make new canonical chain: %v", err)
   161  	}
   162  //定义难度比较器
   163  	worse := func(td1, td2 *big.Int) {
   164  		if td2.Cmp(td1) >= 0 {
   165  			t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1)
   166  		}
   167  	}
   168  //数字之和必须小于“length”,才能成为较短的分叉
   169  	testFork(t, processor, 0, 3, worse)
   170  	testFork(t, processor, 0, 7, worse)
   171  	testFork(t, processor, 1, 1, worse)
   172  	testFork(t, processor, 1, 7, worse)
   173  	testFork(t, processor, 5, 3, worse)
   174  	testFork(t, processor, 5, 4, worse)
   175  }
   176  
   177  //测试给定给定大小的起始规范链,创建更长的
   178  //forks确实拥有规范的所有权。
   179  func TestLongerForkHeaders(t *testing.T) {
   180  	length := 10
   181  
   182  //从创世纪开始制造第一条链条
   183  	_, processor, err := newCanonical(length)
   184  	if err != nil {
   185  		t.Fatalf("failed to make new canonical chain: %v", err)
   186  	}
   187  //定义难度比较器
   188  	better := func(td1, td2 *big.Int) {
   189  		if td2.Cmp(td1) <= 0 {
   190  			t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1)
   191  		}
   192  	}
   193  //数字之和必须大于“length”,才能成为较长的分叉
   194  	testFork(t, processor, 0, 11, better)
   195  	testFork(t, processor, 0, 15, better)
   196  	testFork(t, processor, 1, 10, better)
   197  	testFork(t, processor, 1, 12, better)
   198  	testFork(t, processor, 5, 6, better)
   199  	testFork(t, processor, 5, 8, better)
   200  }
   201  
   202  //测试给定给定大小的起始规范链,创建相等的
   203  //forks确实拥有规范的所有权。
   204  func TestEqualForkHeaders(t *testing.T) {
   205  	length := 10
   206  
   207  //从创世纪开始制造第一条链条
   208  	_, processor, err := newCanonical(length)
   209  	if err != nil {
   210  		t.Fatalf("failed to make new canonical chain: %v", err)
   211  	}
   212  //定义难度比较器
   213  	equal := func(td1, td2 *big.Int) {
   214  		if td2.Cmp(td1) != 0 {
   215  			t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1)
   216  		}
   217  	}
   218  //数字之和必须等于“length”,才能成为相等的叉
   219  	testFork(t, processor, 0, 10, equal)
   220  	testFork(t, processor, 1, 9, equal)
   221  	testFork(t, processor, 2, 8, equal)
   222  	testFork(t, processor, 5, 5, equal)
   223  	testFork(t, processor, 6, 4, equal)
   224  	testFork(t, processor, 9, 1, equal)
   225  }
   226  
   227  //处理器不接受链接缺失的测试。
   228  func TestBrokenHeaderChain(t *testing.T) {
   229  //从Genesis开始制作链条
   230  	db, LightChain, err := newCanonical(10)
   231  	if err != nil {
   232  		t.Fatalf("failed to make new canonical chain: %v", err)
   233  	}
   234  //创建分叉链,并尝试插入缺少的链接
   235  	chain := makeHeaderChain(LightChain.CurrentHeader(), 5, db, forkSeed)[1:]
   236  	if err := testHeaderChainImport(chain, LightChain); err == nil {
   237  		t.Errorf("broken header chain not reported")
   238  	}
   239  }
   240  
   241  func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Header {
   242  	var chain []*types.Header
   243  	for i, difficulty := range d {
   244  		header := &types.Header{
   245  			Coinbase:    common.Address{seed},
   246  			Number:      big.NewInt(int64(i + 1)),
   247  			Difficulty:  big.NewInt(int64(difficulty)),
   248  			UncleHash:   types.EmptyUncleHash,
   249  			TxHash:      types.EmptyRootHash,
   250  			ReceiptHash: types.EmptyRootHash,
   251  		}
   252  		if i == 0 {
   253  			header.ParentHash = genesis.Hash()
   254  		} else {
   255  			header.ParentHash = chain[i-1].Hash()
   256  		}
   257  		chain = append(chain, types.CopyHeader(header))
   258  	}
   259  	return chain
   260  }
   261  
   262  type dummyOdr struct {
   263  	OdrBackend
   264  	db ethdb.Database
   265  }
   266  
   267  func (odr *dummyOdr) Database() ethdb.Database {
   268  	return odr.db
   269  }
   270  
   271  func (odr *dummyOdr) Retrieve(ctx context.Context, req OdrRequest) error {
   272  	return nil
   273  }
   274  
   275  //在短而容易的链之后重新组织长而难的链的测试
   276  //覆盖数据库中的规范数字和链接。
   277  func TestReorgLongHeaders(t *testing.T) {
   278  	testReorg(t, []int{1, 2, 4}, []int{1, 2, 3, 4}, 10)
   279  }
   280  
   281  //在长而容易的链之后重新组织短而难的链的测试
   282  //覆盖数据库中的规范数字和链接。
   283  func TestReorgShortHeaders(t *testing.T) {
   284  	testReorg(t, []int{1, 2, 3, 4}, []int{1, 10}, 11)
   285  }
   286  
   287  func testReorg(t *testing.T, first, second []int, td int64) {
   288  	bc := newTestLightChain()
   289  
   290  //然后插入一个容易和困难的链条
   291  	bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, first, 11), 1)
   292  	bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, second, 22), 1)
   293  //检查链条是否为有效的数字和链接方式
   294  	prev := bc.CurrentHeader()
   295  	for header := bc.GetHeaderByNumber(bc.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, bc.GetHeaderByNumber(header.Number.Uint64()-1) {
   296  		if prev.ParentHash != header.Hash() {
   297  			t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash())
   298  		}
   299  	}
   300  //确保链条的总难度是正确的。
   301  	want := new(big.Int).Add(bc.genesisBlock.Difficulty(), big.NewInt(td))
   302  	if have := bc.GetTdByHash(bc.CurrentHeader().Hash()); have.Cmp(want) != 0 {
   303  		t.Errorf("total difficulty mismatch: have %v, want %v", have, want)
   304  	}
   305  }
   306  
   307  //测试插入函数是否检测禁止的哈希。
   308  func TestBadHeaderHashes(t *testing.T) {
   309  	bc := newTestLightChain()
   310  
   311  //创建链,禁止散列并尝试导入
   312  	var err error
   313  	headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10)
   314  	core.BadHashes[headers[2].Hash()] = true
   315  	if _, err = bc.InsertHeaderChain(headers, 1); err != core.ErrBlacklistedHash {
   316  		t.Errorf("error mismatch: have: %v, want %v", err, core.ErrBlacklistedHash)
   317  	}
   318  }
   319  
   320  //测试在引导时检测到错误的哈希值,并将chan回滚到
   321  //坏哈希前的良好状态。
   322  func TestReorgBadHeaderHashes(t *testing.T) {
   323  	bc := newTestLightChain()
   324  
   325  //创建一个链,然后导入和禁止
   326  	headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10)
   327  
   328  	if _, err := bc.InsertHeaderChain(headers, 1); err != nil {
   329  		t.Fatalf("failed to import headers: %v", err)
   330  	}
   331  	if bc.CurrentHeader().Hash() != headers[3].Hash() {
   332  		t.Errorf("last header hash mismatch: have: %x, want %x", bc.CurrentHeader().Hash(), headers[3].Hash())
   333  	}
   334  	core.BadHashes[headers[3].Hash()] = true
   335  	defer func() { delete(core.BadHashes, headers[3].Hash()) }()
   336  
   337  //创建一个新的lightchain并检查它是否回滚状态。
   338  	ncm, err := NewLightChain(&dummyOdr{db: bc.chainDb}, params.TestChainConfig, ethash.NewFaker())
   339  	if err != nil {
   340  		t.Fatalf("failed to create new chain manager: %v", err)
   341  	}
   342  	if ncm.CurrentHeader().Hash() != headers[2].Hash() {
   343  		t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash())
   344  	}
   345  }
   346