10 "github.com/vapor/consensus"
11 dbm "github.com/vapor/database/leveldb"
12 "github.com/vapor/errors"
13 msgs "github.com/vapor/netsync/messages"
14 "github.com/vapor/protocol/bc"
15 "github.com/vapor/protocol/bc/types"
16 "github.com/vapor/test/mock"
17 "github.com/vapor/testutil"
20 func TestRegularBlockSync(t *testing.T) {
21 baseChain := mockBlocks(nil, 50)
22 chainX := append(baseChain, mockBlocks(baseChain[50], 60)...)
23 chainY := append(baseChain, mockBlocks(baseChain[50], 70)...)
24 chainZ := append(baseChain, mockBlocks(baseChain[50], 200)...)
27 syncTimeout time.Duration
28 aBlocks []*types.Block
29 bBlocks []*types.Block
34 syncTimeout: 30 * time.Second,
35 aBlocks: baseChain[:20],
36 bBlocks: baseChain[:50],
41 syncTimeout: 30 * time.Second,
48 syncTimeout: 30 * time.Second,
55 syncTimeout: 30 * time.Second,
62 tmp, err := ioutil.TempDir(".", "")
64 t.Fatalf("failed to create temporary data folder: %v", err)
66 testDBA := dbm.NewDB("testdba", "leveldb", tmp)
67 testDBB := dbm.NewDB("testdbb", "leveldb", tmp)
74 for i, c := range cases {
75 a := mockSync(c.aBlocks, nil, testDBA)
76 b := mockSync(c.bBlocks, nil, testDBB)
77 netWork := NewNetWork()
78 netWork.Register(a, "192.168.0.1", "test node A", consensus.SFFullNode)
79 netWork.Register(b, "192.168.0.2", "test node B", consensus.SFFullNode)
80 if B2A, A2B, err := netWork.HandsShake(a, b); err != nil {
81 t.Errorf("fail on peer hands shake %v", err)
87 a.blockKeeper.syncPeer = a.peers.GetPeer("test node B")
88 if err := a.blockKeeper.regularBlockSync(); errors.Root(err) != c.err {
89 t.Errorf("case %d: got %v want %v", i, err, c.err)
92 got := []*types.Block{}
93 for i := uint64(0); i <= a.chain.BestBlockHeight(); i++ {
94 block, err := a.chain.GetBlockByHeight(i)
96 t.Errorf("case %d got err %v", i, err)
98 got = append(got, block)
101 if !testutil.DeepEqual(got, c.want) {
102 t.Errorf("case %d: got %v want %v", i, got, c.want)
107 func TestRequireBlock(t *testing.T) {
108 tmp, err := ioutil.TempDir(".", "")
110 t.Fatalf("failed to create temporary data folder: %v", err)
112 testDBA := dbm.NewDB("testdba", "leveldb", tmp)
113 testDBB := dbm.NewDB("testdbb", "leveldb", tmp)
120 blocks := mockBlocks(nil, 5)
121 a := mockSync(blocks[:1], nil, testDBA)
122 b := mockSync(blocks[:5], nil, testDBB)
123 netWork := NewNetWork()
124 netWork.Register(a, "192.168.0.1", "test node A", consensus.SFFullNode)
125 netWork.Register(b, "192.168.0.2", "test node B", consensus.SFFullNode)
126 if B2A, A2B, err := netWork.HandsShake(a, b); err != nil {
127 t.Errorf("fail on peer hands shake %v", err)
133 a.blockKeeper.syncPeer = a.peers.GetPeer("test node B")
134 b.blockKeeper.syncPeer = b.peers.GetPeer("test node A")
136 syncTimeout time.Duration
143 syncTimeout: 30 * time.Second,
150 syncTimeout: 1 * time.Millisecond,
154 err: errRequestTimeout,
159 requireBlockTimeout = 20 * time.Second
162 for i, c := range cases {
163 requireBlockTimeout = c.syncTimeout
164 got, err := c.testNode.blockKeeper.msgFetcher.requireBlock(c.testNode.blockKeeper.syncPeer.ID(), c.requireHeight)
165 if !testutil.DeepEqual(got, c.want) {
166 t.Errorf("case %d: got %v want %v", i, got, c.want)
168 if errors.Root(err) != c.err {
169 t.Errorf("case %d: got %v want %v", i, err, c.err)
174 func TestSendMerkleBlock(t *testing.T) {
175 tmp, err := ioutil.TempDir(".", "")
177 t.Fatalf("failed to create temporary data folder: %v", err)
180 testDBA := dbm.NewDB("testdba", "leveldb", tmp)
181 testDBB := dbm.NewDB("testdbb", "leveldb", tmp)
194 relatedTxIndex: []int{0, 2, 5},
198 relatedTxIndex: []int{},
202 relatedTxIndex: []int{},
206 relatedTxIndex: []int{0, 1, 2, 3, 4},
210 relatedTxIndex: []int{1, 6, 3, 9, 10, 19},
214 for _, c := range cases {
215 blocks := mockBlocks(nil, 2)
216 targetBlock := blocks[1]
217 txs, bcTxs := mockTxs(c.txCount)
220 targetBlock.Transactions = txs
221 if targetBlock.TransactionsMerkleRoot, err = types.TxMerkleRoot(bcTxs); err != nil {
225 spvNode := mockSync(blocks, nil, testDBA)
226 blockHash := targetBlock.Hash()
227 var statusResult *bc.TransactionStatus
228 if statusResult, err = spvNode.chain.GetTransactionStatus(&blockHash); err != nil {
232 if targetBlock.TransactionStatusHash, err = types.TxStatusMerkleRoot(statusResult.VerifyStatus); err != nil {
236 fullNode := mockSync(blocks, nil, testDBB)
237 netWork := NewNetWork()
238 netWork.Register(spvNode, "192.168.0.1", "spv_node", consensus.SFFastSync)
239 netWork.Register(fullNode, "192.168.0.2", "full_node", consensus.DefaultServices)
242 if F2S, _, err = netWork.HandsShake(spvNode, fullNode); err != nil {
243 t.Errorf("fail on peer hands shake %v", err)
246 completed := make(chan error)
248 msgBytes := <-F2S.msgCh
249 _, msg, _ := decodeMessage(msgBytes)
250 switch m := msg.(type) {
251 case *msgs.MerkleBlockMessage:
252 var relatedTxIDs []*bc.Hash
253 for _, rawTx := range m.RawTxDatas {
255 if err := tx.UnmarshalText(rawTx); err != nil {
259 relatedTxIDs = append(relatedTxIDs, &tx.ID)
261 var txHashes []*bc.Hash
262 for _, hashByte := range m.TxHashes {
263 hash := bc.NewHash(hashByte)
264 txHashes = append(txHashes, &hash)
266 if ok := types.ValidateTxMerkleTreeProof(txHashes, m.Flags, relatedTxIDs, targetBlock.TransactionsMerkleRoot); !ok {
267 completed <- errors.New("validate tx fail")
270 var statusHashes []*bc.Hash
271 for _, statusByte := range m.StatusHashes {
272 hash := bc.NewHash(statusByte)
273 statusHashes = append(statusHashes, &hash)
275 var relatedStatuses []*bc.TxVerifyResult
276 for _, statusByte := range m.RawTxStatuses {
277 status := &bc.TxVerifyResult{}
278 err := json.Unmarshal(statusByte, status)
282 relatedStatuses = append(relatedStatuses, status)
284 if ok := types.ValidateStatusMerkleTreeProof(statusHashes, m.Flags, relatedStatuses, targetBlock.TransactionStatusHash); !ok {
285 completed <- errors.New("validate status fail")
292 spvPeer := fullNode.peers.GetPeer("spv_node")
293 for i := 0; i < len(c.relatedTxIndex); i++ {
294 spvPeer.AddFilterAddress(txs[c.relatedTxIndex[i]].Outputs[0].ControlProgram())
296 msg := &msgs.GetMerkleBlockMessage{RawHash: targetBlock.Hash().Byte32()}
297 fullNode.handleGetMerkleBlockMsg(spvPeer, msg)
298 if err := <-completed; err != nil {
304 func TestLocateBlocks(t *testing.T) {
305 maxNumOfBlocksPerMsg = 5
306 blocks := mockBlocks(nil, 100)
313 locator: []uint64{20},
314 stopHash: blocks[100].Hash(),
315 wantHeight: []uint64{20, 21, 22, 23, 24},
319 mockChain := mock.NewChain(nil)
320 bk := &blockKeeper{chain: mockChain}
321 for _, block := range blocks {
322 mockChain.SetBlockByHeight(block.Height, block)
325 for i, c := range cases {
326 locator := []*bc.Hash{}
327 for _, i := range c.locator {
328 hash := blocks[i].Hash()
329 locator = append(locator, &hash)
332 want := []*types.Block{}
333 for _, i := range c.wantHeight {
334 want = append(want, blocks[i])
337 got, _ := bk.locateBlocks(locator, &c.stopHash)
338 if !testutil.DeepEqual(got, want) {
339 t.Errorf("case %d: got %v want %v", i, got, want)
344 func TestLocateHeaders(t *testing.T) {
346 maxNumOfHeadersPerMsg = 1000
348 maxNumOfHeadersPerMsg = 10
349 blocks := mockBlocks(nil, 150)
350 blocksHash := []bc.Hash{}
351 for _, block := range blocks {
352 blocksHash = append(blocksHash, block.Hash())
365 locator: []uint64{90},
366 stopHash: &blocksHash[100],
368 wantHeight: []uint64{90, 91, 92, 93, 94, 95, 96, 97, 98, 99},
373 locator: []uint64{20},
374 stopHash: &blocksHash[24],
376 wantHeight: []uint64{20, 21, 22, 23, 24},
381 locator: []uint64{20},
382 stopHash: &blocksHash[20],
383 wantHeight: []uint64{20},
388 locator: []uint64{20},
389 stopHash: &blocksHash[120],
390 wantHeight: []uint64{},
395 locator: []uint64{120, 70},
396 stopHash: &blocksHash[78],
397 wantHeight: []uint64{70, 71, 72, 73, 74, 75, 76, 77, 78},
402 locator: []uint64{15},
403 stopHash: &blocksHash[10],
405 wantHeight: []uint64{},
410 locator: []uint64{15},
411 stopHash: &blocksHash[80],
413 wantHeight: []uint64{15, 26, 37, 48, 59, 70, 80},
418 locator: []uint64{0},
419 stopHash: &blocksHash[100],
421 wantHeight: []uint64{0, 10, 20, 30, 40, 50, 60, 70, 80, 90},
426 for i, c := range cases {
427 mockChain := mock.NewChain(nil)
428 bk := &blockKeeper{chain: mockChain}
429 for i := uint64(0); i <= c.chainHeight; i++ {
430 mockChain.SetBlockByHeight(i, blocks[i])
433 locator := []*bc.Hash{}
434 for _, i := range c.locator {
435 hash := blocks[i].Hash()
436 locator = append(locator, &hash)
439 want := []*types.BlockHeader{}
440 for _, i := range c.wantHeight {
441 want = append(want, &blocks[i].BlockHeader)
444 got, err := bk.locateHeaders(locator, c.stopHash, c.skip, maxNumOfHeadersPerMsg)
445 if err != nil != c.err {
446 t.Errorf("case %d: got %v want err = %v", i, err, c.err)
448 if !testutil.DeepEqual(got, want) {
449 t.Errorf("case %d: got %v want %v", i, got, want)