github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/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 19:16:39</date> 10 //</624450096402010112> 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, indexerConfig: TestClientIndexerConfig}, 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.chainmu.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.chainmu.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 indexerConfig *IndexerConfig 266 } 267 268 func (odr *dummyOdr) Database() ethdb.Database { 269 return odr.db 270 } 271 272 func (odr *dummyOdr) Retrieve(ctx context.Context, req OdrRequest) error { 273 return nil 274 } 275 276 func (odr *dummyOdr) IndexerConfig() *IndexerConfig { 277 return odr.indexerConfig 278 } 279 280 //在短而容易的链之后重新组织长而难的链的测试 281 //覆盖数据库中的规范数字和链接。 282 func TestReorgLongHeaders(t *testing.T) { 283 testReorg(t, []int{1, 2, 4}, []int{1, 2, 3, 4}, 10) 284 } 285 286 //在长而容易的链之后重新组织短而难的链的测试 287 //覆盖数据库中的规范数字和链接。 288 func TestReorgShortHeaders(t *testing.T) { 289 testReorg(t, []int{1, 2, 3, 4}, []int{1, 10}, 11) 290 } 291 292 func testReorg(t *testing.T, first, second []int, td int64) { 293 bc := newTestLightChain() 294 295 //然后插入一个容易和困难的链条 296 bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, first, 11), 1) 297 bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, second, 22), 1) 298 //检查链条是否为有效的数字和链接方式 299 prev := bc.CurrentHeader() 300 for header := bc.GetHeaderByNumber(bc.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, bc.GetHeaderByNumber(header.Number.Uint64()-1) { 301 if prev.ParentHash != header.Hash() { 302 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 303 } 304 } 305 //确保链条的总难度是正确的。 306 want := new(big.Int).Add(bc.genesisBlock.Difficulty(), big.NewInt(td)) 307 if have := bc.GetTdByHash(bc.CurrentHeader().Hash()); have.Cmp(want) != 0 { 308 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 309 } 310 } 311 312 //测试插入函数是否检测禁止的哈希。 313 func TestBadHeaderHashes(t *testing.T) { 314 bc := newTestLightChain() 315 316 //创建链,禁止散列并尝试导入 317 var err error 318 headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10) 319 core.BadHashes[headers[2].Hash()] = true 320 if _, err = bc.InsertHeaderChain(headers, 1); err != core.ErrBlacklistedHash { 321 t.Errorf("error mismatch: have: %v, want %v", err, core.ErrBlacklistedHash) 322 } 323 } 324 325 //测试在引导时检测到错误的哈希值,并将chan回滚到 326 //坏哈希前的良好状态。 327 func TestReorgBadHeaderHashes(t *testing.T) { 328 bc := newTestLightChain() 329 330 //创建一个链,然后导入和禁止 331 headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10) 332 333 if _, err := bc.InsertHeaderChain(headers, 1); err != nil { 334 t.Fatalf("failed to import headers: %v", err) 335 } 336 if bc.CurrentHeader().Hash() != headers[3].Hash() { 337 t.Errorf("last header hash mismatch: have: %x, want %x", bc.CurrentHeader().Hash(), headers[3].Hash()) 338 } 339 core.BadHashes[headers[3].Hash()] = true 340 defer func() { delete(core.BadHashes, headers[3].Hash()) }() 341 342 //创建一个新的lightchain并检查它是否回滚状态。 343 ncm, err := NewLightChain(&dummyOdr{db: bc.chainDb}, params.TestChainConfig, ethash.NewFaker()) 344 if err != nil { 345 t.Fatalf("failed to create new chain manager: %v", err) 346 } 347 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 348 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 349 } 350 } 351