// TestGetData tests the MsgGetData API. func TestGetData(t *testing.T) { pver := wire.ProtocolVersion // Ensure the command is expected value. wantCmd := "getdata" msg := wire.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 := wire.ShaHash{} iv := wire.NewInvVect(wire.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 < wire.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 = wire.NewMsgGetDataSizeHint(wire.MaxInvPerMsg + 1) wantCap := wire.MaxInvPerMsg if cap(msg.InvList) != wantCap { t.Errorf("NewMsgGetDataSizeHint: wrong cap for size hint - "+ "got %v, want %v", cap(msg.InvList), wantCap) } return }
// 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 wire.MaxInvPerMsg by // the function, so no need to double check it here. gdmsg := wire.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 := wire.NewInvVect(wire.InvTypeBlock, node.sha) haveInv, err := b.haveInventory(iv) if err != nil { bmgrLog.Warnf("Unexpected failure when checking for "+ "existing inventory during header block "+ "fetch: %v", err) } if !haveInv { b.requestedBlocks[*node.sha] = struct{}{} b.syncPeer.requestedBlocks[*node.sha] = struct{}{} gdmsg.AddInvVect(iv) numRequested++ } b.startHeader = e.Next() if numRequested >= wire.MaxInvPerMsg { break } } if len(gdmsg.InvList) > 0 { b.syncPeer.QueueMessage(gdmsg, nil) } }