// fetchHeaderBlocks creates and sends a request to the syncPeer for the next // list of blocks to be downloaded based on the current list of headers. func (b *blockManager) fetchHeaderBlocks() { // Nothing to do if there is no start header. if b.startHeader == nil { bmgrLog.Warnf("fetchHeaderBlocks called with no start header") return } // Build up a getdata request for the list of blocks the headers // describe. The size hint will be limited to btcwire.MaxInvPerMsg by // the function, so no need to double check it here. gdmsg := btcwire.NewMsgGetDataSizeHint(uint(b.headerList.Len())) numRequested := 0 for e := b.startHeader; e != nil; e = e.Next() { node, ok := e.Value.(*headerNode) if !ok { bmgrLog.Warn("Header list node type is not a headerNode") continue } iv := btcwire.NewInvVect(btcwire.InvTypeBlock, node.sha) if !b.haveInventory(iv) { b.requestedBlocks[*node.sha] = true b.syncPeer.requestedBlocks[*node.sha] = true gdmsg.AddInvVect(iv) numRequested++ } b.startHeader = e.Next() if numRequested >= btcwire.MaxInvPerMsg { break } } if len(gdmsg.InvList) > 0 { b.syncPeer.QueueMessage(gdmsg, nil) } }
// TestGetData tests the MsgGetData API. func TestGetData(t *testing.T) { pver := btcwire.ProtocolVersion // Ensure the command is expected value. wantCmd := "getdata" msg := btcwire.NewMsgGetData() if cmd := msg.Command(); cmd != wantCmd { t.Errorf("NewMsgGetData: wrong command - got %v want %v", cmd, wantCmd) } // Ensure max payload is expected value for latest protocol version. // Num inventory vectors (varInt) + max allowed inventory vectors. wantPayload := uint32(1800009) maxPayload := msg.MaxPayloadLength(pver) if maxPayload != wantPayload { t.Errorf("MaxPayloadLength: wrong max payload length for "+ "protocol version %d - got %v, want %v", pver, maxPayload, wantPayload) } // Ensure inventory vectors are added properly. hash := btcwire.ShaHash{} iv := btcwire.NewInvVect(btcwire.InvTypeBlock, &hash) err := msg.AddInvVect(iv) if err != nil { t.Errorf("AddInvVect: %v", err) } if msg.InvList[0] != iv { t.Errorf("AddInvVect: wrong invvect added - got %v, want %v", spew.Sprint(msg.InvList[0]), spew.Sprint(iv)) } // Ensure adding more than the max allowed inventory vectors per // message returns an error. for i := 0; i < btcwire.MaxInvPerMsg; i++ { err = msg.AddInvVect(iv) } if err == nil { t.Errorf("AddInvVect: expected error on too many inventory " + "vectors not received") } // Ensure creating the message with a size hint larger than the max // works as expected. msg = btcwire.NewMsgGetDataSizeHint(btcwire.MaxInvPerMsg + 1) wantCap := btcwire.MaxInvPerMsg if cap(msg.InvList) != wantCap { t.Errorf("NewMsgGetDataSizeHint: wrong cap for size hint - "+ "got %v, want %v", cap(msg.InvList), wantCap) } return }
// fetchHeaderBlocks is creates and sends a request to the syncPeer for // the next list of blocks to downloaded. func (b *blockManager) fetchHeaderBlocks() { gdmsg := btcwire.NewMsgGetDataSizeHint(btcwire.MaxInvPerMsg) numRequested := 0 startBlock := b.startBlock for { if b.startBlock == nil { break } blockhash := b.startBlock firstblock, ok := b.headerPool[*blockhash] if !ok { bmgrLog.Warnf("current fetch block %v missing from headerPool", blockhash) break } var iv btcwire.InvVect iv.Hash = *blockhash iv.Type = btcwire.InvTypeBlock if !b.haveInventory(&iv) { b.requestedBlocks[*blockhash] = true b.syncPeer.requestedBlocks[*blockhash] = true gdmsg.AddInvVect(&iv) numRequested++ } if b.fetchBlock == nil { b.fetchBlock = b.startBlock } if firstblock.next == nil { b.startBlock = nil break } else { b.startBlock = &firstblock.next.sha } if numRequested >= btcwire.MaxInvPerMsg { break } } if len(gdmsg.InvList) > 0 { bmgrLog.Debugf("requesting block %v len %v\n", startBlock, len(gdmsg.InvList)) b.syncPeer.QueueMessage(gdmsg, nil) } }