Example #1
0
// 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)
	}
}
Example #2
0
// 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
}
Example #3
0
// 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)
	}
}