kaspad/server/p2p/on_get_cf_headers.go

103 lines
2.7 KiB
Go

package p2p
import (
"github.com/daglabs/btcd/peer"
"github.com/daglabs/btcd/util/daghash"
"github.com/daglabs/btcd/wire"
)
// OnGetCFHeaders is invoked when a peer receives a getcfheader bitcoin message.
func (sp *Peer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) {
// Ignore getcfilterheader requests if not in sync.
if !sp.server.SyncManager.IsCurrent() {
return
}
startHeight := msg.StartHeight
maxResults := wire.MaxCFHeadersPerMsg
// If StartHeight is positive, fetch the predecessor block hash so we can
// populate the PrevFilterHeader field.
if msg.StartHeight > 0 {
startHeight--
maxResults++
}
// Fetch the hashes from the block index.
hashList, err := sp.server.DAG.HeightToHashRange(startHeight,
msg.StopHash, maxResults)
if err != nil {
peerLog.Debugf("Invalid getcfheaders request: %s", err)
}
// This is possible if StartHeight is one greater that the height of
// StopHash, and we pull a valid range of hashes including the previous
// filter header.
if len(hashList) == 0 || (msg.StartHeight > 0 && len(hashList) == 1) {
peerLog.Debug("No results for getcfheaders request")
return
}
// Fetch the raw filter hash bytes from the database for all blocks.
filterHashes, err := sp.server.CfIndex.FilterHashesByBlockHashes(hashList,
msg.FilterType)
if err != nil {
peerLog.Errorf("Error retrieving cfilter hashes: %s", err)
return
}
// Generate cfheaders message and send it.
headersMsg := wire.NewMsgCFHeaders()
// Populate the PrevFilterHeader field.
if msg.StartHeight > 0 {
parentHash := hashList[0]
// Fetch the raw committed filter header bytes from the
// database.
headerBytes, err := sp.server.CfIndex.FilterHeaderByBlockHash(
parentHash, msg.FilterType)
if err != nil {
peerLog.Errorf("Error retrieving CF header: %s", err)
return
}
if len(headerBytes) == 0 {
peerLog.Warnf("Could not obtain CF header for %s", parentHash)
return
}
// Deserialize the hash into PrevFilterHeader.
err = headersMsg.PrevFilterHeader.SetBytes(headerBytes)
if err != nil {
peerLog.Warnf("Committed filter header deserialize "+
"failed: %s", err)
return
}
hashList = hashList[1:]
filterHashes = filterHashes[1:]
}
// Populate HeaderHashes.
for i, hashBytes := range filterHashes {
if len(hashBytes) == 0 {
peerLog.Warnf("Could not obtain CF hash for %s", hashList[i])
return
}
// Deserialize the hash.
filterHash, err := daghash.NewHash(hashBytes)
if err != nil {
peerLog.Warnf("Committed filter hash deserialize "+
"failed: %s", err)
return
}
headersMsg.AddCFHash(filterHash)
}
headersMsg.FilterType = msg.FilterType
headersMsg.StopHash = msg.StopHash
sp.QueueMessage(headersMsg, nil)
}