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