8 "github.com/bytom/consensus"
9 "github.com/bytom/errors"
10 "github.com/bytom/protocol/bc"
11 "github.com/bytom/protocol/bc/types"
12 "github.com/bytom/test/mock"
13 "github.com/bytom/testutil"
16 func TestAppendHeaderList(t *testing.T) {
17 blocks := mockBlocks(nil, 7)
19 originalHeaders []*types.BlockHeader
20 inputHeaders []*types.BlockHeader
21 wantHeaders []*types.BlockHeader
25 originalHeaders: []*types.BlockHeader{&blocks[0].BlockHeader},
26 inputHeaders: []*types.BlockHeader{&blocks[1].BlockHeader, &blocks[2].BlockHeader},
27 wantHeaders: []*types.BlockHeader{&blocks[0].BlockHeader, &blocks[1].BlockHeader, &blocks[2].BlockHeader},
31 originalHeaders: []*types.BlockHeader{&blocks[5].BlockHeader},
32 inputHeaders: []*types.BlockHeader{&blocks[6].BlockHeader},
33 wantHeaders: []*types.BlockHeader{&blocks[5].BlockHeader, &blocks[6].BlockHeader},
37 originalHeaders: []*types.BlockHeader{&blocks[5].BlockHeader},
38 inputHeaders: []*types.BlockHeader{&blocks[7].BlockHeader},
39 wantHeaders: []*types.BlockHeader{&blocks[5].BlockHeader},
40 err: errAppendHeaders,
43 originalHeaders: []*types.BlockHeader{&blocks[5].BlockHeader},
44 inputHeaders: []*types.BlockHeader{&blocks[7].BlockHeader, &blocks[6].BlockHeader},
45 wantHeaders: []*types.BlockHeader{&blocks[5].BlockHeader},
46 err: errAppendHeaders,
49 originalHeaders: []*types.BlockHeader{&blocks[2].BlockHeader},
50 inputHeaders: []*types.BlockHeader{&blocks[3].BlockHeader, &blocks[4].BlockHeader, &blocks[6].BlockHeader},
51 wantHeaders: []*types.BlockHeader{&blocks[2].BlockHeader, &blocks[3].BlockHeader, &blocks[4].BlockHeader},
52 err: errAppendHeaders,
56 for i, c := range cases {
57 bk := &blockKeeper{headerList: list.New()}
58 for _, header := range c.originalHeaders {
59 bk.headerList.PushBack(header)
62 if err := bk.appendHeaderList(c.inputHeaders); err != c.err {
63 t.Errorf("case %d: got error %v want error %v", i, err, c.err)
66 gotHeaders := []*types.BlockHeader{}
67 for e := bk.headerList.Front(); e != nil; e = e.Next() {
68 gotHeaders = append(gotHeaders, e.Value.(*types.BlockHeader))
71 if !testutil.DeepEqual(gotHeaders, c.wantHeaders) {
72 t.Errorf("case %d: got %v want %v", i, gotHeaders, c.wantHeaders)
77 func TestBlockLocator(t *testing.T) {
78 blocks := mockBlocks(nil, 500)
85 wantHeight: []uint64{0},
89 wantHeight: []uint64{1, 0},
93 wantHeight: []uint64{7, 6, 5, 4, 3, 2, 1, 0},
97 wantHeight: []uint64{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
101 wantHeight: []uint64{100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 89, 85, 77, 61, 29, 0},
105 wantHeight: []uint64{500, 499, 498, 497, 496, 495, 494, 493, 492, 491, 489, 485, 477, 461, 429, 365, 237, 0},
109 for i, c := range cases {
110 mockChain := mock.NewChain()
111 bk := &blockKeeper{chain: mockChain}
112 mockChain.SetBestBlockHeader(&blocks[c.bestHeight].BlockHeader)
113 for i := uint64(0); i <= c.bestHeight; i++ {
114 mockChain.SetBlockByHeight(i, blocks[i])
118 for _, i := range c.wantHeight {
119 hash := blocks[i].Hash()
120 want = append(want, &hash)
123 if got := bk.blockLocator(); !testutil.DeepEqual(got, want) {
124 t.Errorf("case %d: got %v want %v", i, got, want)
129 func TestFastBlockSync(t *testing.T) {
131 maxBlockHeadersPerMsg = 10
132 baseChain := mockBlocks(nil, 300)
135 syncTimeout time.Duration
136 aBlocks []*types.Block
137 bBlocks []*types.Block
138 checkPoint *consensus.Checkpoint
143 syncTimeout: 30 * time.Second,
144 aBlocks: baseChain[:100],
145 bBlocks: baseChain[:301],
146 checkPoint: &consensus.Checkpoint{
147 Height: baseChain[250].Height,
148 Hash: baseChain[250].Hash(),
150 want: baseChain[:251],
154 syncTimeout: 30 * time.Second,
155 aBlocks: baseChain[:100],
156 bBlocks: baseChain[:301],
157 checkPoint: &consensus.Checkpoint{
158 Height: baseChain[100].Height,
159 Hash: baseChain[100].Hash(),
161 want: baseChain[:101],
165 syncTimeout: 1 * time.Millisecond,
166 aBlocks: baseChain[:100],
167 bBlocks: baseChain[:100],
168 checkPoint: &consensus.Checkpoint{
169 Height: baseChain[200].Height,
170 Hash: baseChain[200].Hash(),
172 want: baseChain[:100],
173 err: errRequestTimeout,
177 for i, c := range cases {
178 syncTimeout = c.syncTimeout
179 a := mockSync(c.aBlocks)
180 b := mockSync(c.bBlocks)
181 netWork := NewNetWork()
182 netWork.Register(a, "192.168.0.1", "test node A", consensus.SFFullNode)
183 netWork.Register(b, "192.168.0.2", "test node B", consensus.SFFullNode)
184 if err := netWork.HandsShake(a, b); err != nil {
185 t.Errorf("fail on peer hands shake %v", err)
188 a.blockKeeper.syncPeer = a.peers.getPeer("test node B")
189 if err := a.blockKeeper.fastBlockSync(c.checkPoint); errors.Root(err) != c.err {
190 t.Errorf("case %d: got %v want %v", i, err, c.err)
193 got := []*types.Block{}
194 for i := uint64(0); i <= a.chain.BestBlockHeight(); i++ {
195 block, err := a.chain.GetBlockByHeight(i)
197 t.Errorf("case %d got err %v", i, err)
199 got = append(got, block)
202 if !testutil.DeepEqual(got, c.want) {
203 t.Errorf("case %d: got %v want %v", i, got, c.want)
208 func TestLocateBlocks(t *testing.T) {
210 blocks := mockBlocks(nil, 100)
217 locator: []uint64{20},
218 stopHash: blocks[100].Hash(),
219 wantHeight: []uint64{21, 22, 23, 24, 25},
223 mockChain := mock.NewChain()
224 bk := &blockKeeper{chain: mockChain}
225 for _, block := range blocks {
226 mockChain.SetBlockByHeight(block.Height, block)
229 for i, c := range cases {
230 locator := []*bc.Hash{}
231 for _, i := range c.locator {
232 hash := blocks[i].Hash()
233 locator = append(locator, &hash)
236 want := []*types.Block{}
237 for _, i := range c.wantHeight {
238 want = append(want, blocks[i])
241 got, _ := bk.locateBlocks(locator, &c.stopHash)
242 if !testutil.DeepEqual(got, want) {
243 t.Errorf("case %d: got %v want %v", i, got, want)
248 func TestLocateHeaders(t *testing.T) {
249 maxBlockHeadersPerMsg = 10
250 blocks := mockBlocks(nil, 150)
261 stopHash: blocks[100].Hash(),
262 wantHeight: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
267 locator: []uint64{20},
268 stopHash: blocks[100].Hash(),
269 wantHeight: []uint64{21, 22, 23, 24, 25, 26, 27, 28, 29, 30},
274 locator: []uint64{20},
275 stopHash: blocks[24].Hash(),
276 wantHeight: []uint64{21, 22, 23, 24},
281 locator: []uint64{20},
282 stopHash: blocks[20].Hash(),
283 wantHeight: []uint64{},
288 locator: []uint64{20},
290 wantHeight: []uint64{},
295 locator: []uint64{120, 70},
296 stopHash: blocks[78].Hash(),
297 wantHeight: []uint64{71, 72, 73, 74, 75, 76, 77, 78},
302 for i, c := range cases {
303 mockChain := mock.NewChain()
304 bk := &blockKeeper{chain: mockChain}
305 for i := uint64(0); i <= c.chainHeight; i++ {
306 mockChain.SetBlockByHeight(i, blocks[i])
309 locator := []*bc.Hash{}
310 for _, i := range c.locator {
311 hash := blocks[i].Hash()
312 locator = append(locator, &hash)
315 want := []*types.BlockHeader{}
316 for _, i := range c.wantHeight {
317 want = append(want, &blocks[i].BlockHeader)
320 got, err := bk.locateHeaders(locator, &c.stopHash)
321 if err != nil != c.err {
322 t.Errorf("case %d: got %v want err = %v", i, err, c.err)
324 if !testutil.DeepEqual(got, want) {
325 t.Errorf("case %d: got %v want %v", i, got, want)
330 func TestNextCheckpoint(t *testing.T) {
332 checkPoints []consensus.Checkpoint
334 want *consensus.Checkpoint
337 checkPoints: []consensus.Checkpoint{},
342 checkPoints: []consensus.Checkpoint{
343 {10000, bc.Hash{V0: 1}},
346 want: &consensus.Checkpoint{10000, bc.Hash{V0: 1}},
349 checkPoints: []consensus.Checkpoint{
350 {10000, bc.Hash{V0: 1}},
351 {20000, bc.Hash{V0: 2}},
352 {30000, bc.Hash{V0: 3}},
355 want: &consensus.Checkpoint{20000, bc.Hash{V0: 2}},
358 checkPoints: []consensus.Checkpoint{
359 {10000, bc.Hash{V0: 1}},
360 {20000, bc.Hash{V0: 2}},
361 {30000, bc.Hash{V0: 3}},
364 want: &consensus.Checkpoint{20000, bc.Hash{V0: 2}},
367 checkPoints: []consensus.Checkpoint{
368 {10000, bc.Hash{V0: 1}},
369 {20000, bc.Hash{V0: 2}},
370 {30000, bc.Hash{V0: 3}},
377 mockChain := mock.NewChain()
378 for i, c := range cases {
379 consensus.ActiveNetParams.Checkpoints = c.checkPoints
380 mockChain.SetBestBlockHeader(&types.BlockHeader{Height: c.bestHeight})
381 bk := &blockKeeper{chain: mockChain}
383 if got := bk.nextCheckpoint(); !testutil.DeepEqual(got, c.want) {
384 t.Errorf("case %d: got %v want %v", i, got, c.want)
389 func TestRegularBlockSync(t *testing.T) {
390 baseChain := mockBlocks(nil, 50)
391 chainX := append(baseChain, mockBlocks(baseChain[50], 60)...)
392 chainY := append(baseChain, mockBlocks(baseChain[50], 70)...)
394 syncTimeout time.Duration
395 aBlocks []*types.Block
396 bBlocks []*types.Block
402 syncTimeout: 30 * time.Second,
403 aBlocks: baseChain[:20],
404 bBlocks: baseChain[:50],
406 want: baseChain[:46],
410 syncTimeout: 30 * time.Second,
418 syncTimeout: 30 * time.Second,
419 aBlocks: chainX[:52],
420 bBlocks: chainY[:53],
426 syncTimeout: 1 * time.Millisecond,
431 err: errRequestTimeout,
435 for i, c := range cases {
436 syncTimeout = c.syncTimeout
437 a := mockSync(c.aBlocks)
438 b := mockSync(c.bBlocks)
439 netWork := NewNetWork()
440 netWork.Register(a, "192.168.0.1", "test node A", consensus.SFFullNode)
441 netWork.Register(b, "192.168.0.2", "test node B", consensus.SFFullNode)
442 if err := netWork.HandsShake(a, b); err != nil {
443 t.Errorf("fail on peer hands shake %v", err)
446 a.blockKeeper.syncPeer = a.peers.getPeer("test node B")
447 if err := a.blockKeeper.regularBlockSync(c.syncHeight); errors.Root(err) != c.err {
448 t.Errorf("case %d: got %v want %v", i, err, c.err)
451 got := []*types.Block{}
452 for i := uint64(0); i <= a.chain.BestBlockHeight(); i++ {
453 block, err := a.chain.GetBlockByHeight(i)
455 t.Errorf("case %d got err %v", i, err)
457 got = append(got, block)
460 if !testutil.DeepEqual(got, c.want) {
461 t.Errorf("case %d: got %v want %v", i, got, c.want)
466 func TestRequireBlock(t *testing.T) {
467 blocks := mockBlocks(nil, 5)
468 a := mockSync(blocks[:1])
469 b := mockSync(blocks[:5])
470 netWork := NewNetWork()
471 netWork.Register(a, "192.168.0.1", "test node A", consensus.SFFullNode)
472 netWork.Register(b, "192.168.0.2", "test node B", consensus.SFFullNode)
473 if err := netWork.HandsShake(a, b); err != nil {
474 t.Errorf("fail on peer hands shake %v", err)
477 a.blockKeeper.syncPeer = a.peers.getPeer("test node B")
478 b.blockKeeper.syncPeer = b.peers.getPeer("test node A")
480 syncTimeout time.Duration
481 testNode *SyncManager
487 syncTimeout: 30 * time.Second,
494 syncTimeout: 1 * time.Millisecond,
498 err: errRequestTimeout,
502 for i, c := range cases {
503 syncTimeout = c.syncTimeout
504 got, err := c.testNode.blockKeeper.requireBlock(c.requireHeight)
505 if !testutil.DeepEqual(got, c.want) {
506 t.Errorf("case %d: got %v want %v", i, got, c.want)
508 if errors.Root(err) != c.err {
509 t.Errorf("case %d: got %v want %v", i, err, c.err)