server: ensure we only fetch filters we know of

This commit is contained in:
Olaoluwa Osuntokun 2018-07-14 12:20:20 -07:00
parent fdfc19097e
commit f7366fb51b
No known key found for this signature in database
GPG Key ID: 964EA263DD637C21

111
server.go
View File

@ -762,8 +762,21 @@ func (sp *serverPeer) OnGetCFilters(_ *peer.Peer, msg *wire.MsgGetCFilters) {
return return
} }
hashes, err := sp.server.chain.HeightToHashRange(int32(msg.StartHeight), // We'll also ensure that the remote party is requesting a set of
&msg.StopHash, wire.MaxGetCFiltersReqRange) // filters that we actually currently maintain.
switch msg.FilterType {
case wire.GCSFilterRegular:
break
default:
peerLog.Debug("Filter request for unknown filter: %v",
msg.FilterType)
return
}
hashes, err := sp.server.chain.HeightToHashRange(
int32(msg.StartHeight), &msg.StopHash, wire.MaxGetCFiltersReqRange,
)
if err != nil { if err != nil {
peerLog.Debugf("Invalid getcfilters request: %v", err) peerLog.Debugf("Invalid getcfilters request: %v", err)
return return
@ -776,8 +789,9 @@ func (sp *serverPeer) OnGetCFilters(_ *peer.Peer, msg *wire.MsgGetCFilters) {
hashPtrs[i] = &hashes[i] hashPtrs[i] = &hashes[i]
} }
filters, err := sp.server.cfIndex.FiltersByBlockHashes(hashPtrs, filters, err := sp.server.cfIndex.FiltersByBlockHashes(
msg.FilterType) hashPtrs, msg.FilterType,
)
if err != nil { if err != nil {
peerLog.Errorf("Error retrieving cfilters: %v", err) peerLog.Errorf("Error retrieving cfilters: %v", err)
return return
@ -785,10 +799,14 @@ func (sp *serverPeer) OnGetCFilters(_ *peer.Peer, msg *wire.MsgGetCFilters) {
for i, filterBytes := range filters { for i, filterBytes := range filters {
if len(filterBytes) == 0 { if len(filterBytes) == 0 {
peerLog.Warnf("Could not obtain cfilter for %v", hashes[i]) peerLog.Warnf("Could not obtain cfilter for %v",
hashes[i])
return return
} }
filterMsg := wire.NewMsgCFilter(msg.FilterType, &hashes[i], filterBytes)
filterMsg := wire.NewMsgCFilter(
msg.FilterType, &hashes[i], filterBytes,
)
sp.QueueMessage(filterMsg, nil) sp.QueueMessage(filterMsg, nil)
} }
} }
@ -800,19 +818,32 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) {
return return
} }
// We'll also ensure that the remote party is requesting a set of
// headers for filters that we actually currently maintain.
switch msg.FilterType {
case wire.GCSFilterRegular:
break
default:
peerLog.Debug("Filter request for unknown headers for "+
"filter: %v", msg.FilterType)
return
}
startHeight := int32(msg.StartHeight) startHeight := int32(msg.StartHeight)
maxResults := wire.MaxCFHeadersPerMsg maxResults := wire.MaxCFHeadersPerMsg
// If StartHeight is positive, fetch the predecessor block hash so we can // If StartHeight is positive, fetch the predecessor block hash so we
// populate the PrevFilterHeader field. // can populate the PrevFilterHeader field.
if msg.StartHeight > 0 { if msg.StartHeight > 0 {
startHeight-- startHeight--
maxResults++ maxResults++
} }
// Fetch the hashes from the block index. // Fetch the hashes from the block index.
hashList, err := sp.server.chain.HeightToHashRange(startHeight, hashList, err := sp.server.chain.HeightToHashRange(
&msg.StopHash, maxResults) startHeight, &msg.StopHash, maxResults,
)
if err != nil { if err != nil {
peerLog.Debugf("Invalid getcfheaders request: %v", err) peerLog.Debugf("Invalid getcfheaders request: %v", err)
} }
@ -833,8 +864,9 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) {
} }
// Fetch the raw filter hash bytes from the database for all blocks. // Fetch the raw filter hash bytes from the database for all blocks.
filterHashes, err := sp.server.cfIndex.FilterHashesByBlockHashes(hashPtrs, filterHashes, err := sp.server.cfIndex.FilterHashesByBlockHashes(
msg.FilterType) hashPtrs, msg.FilterType,
)
if err != nil { if err != nil {
peerLog.Errorf("Error retrieving cfilter hashes: %v", err) peerLog.Errorf("Error retrieving cfilter hashes: %v", err)
return return
@ -892,6 +924,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) {
headersMsg.FilterType = msg.FilterType headersMsg.FilterType = msg.FilterType
headersMsg.StopHash = msg.StopHash headersMsg.StopHash = msg.StopHash
sp.QueueMessage(headersMsg, nil) sp.QueueMessage(headersMsg, nil)
} }
@ -902,21 +935,38 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) {
return return
} }
blockHashes, err := sp.server.chain.IntervalBlockHashes(&msg.StopHash, // We'll also ensure that the remote party is requesting a set of
wire.CFCheckptInterval) // checkpoints for filters that we actually currently maintain.
switch msg.FilterType {
case wire.GCSFilterRegular:
break
default:
peerLog.Debug("Filter request for unknown checkpoints for "+
"filter: %v", msg.FilterType)
return
}
blockHashes, err := sp.server.chain.IntervalBlockHashes(
&msg.StopHash, wire.CFCheckptInterval,
)
if err != nil { if err != nil {
peerLog.Debugf("Invalid getcfilters request: %v", err) peerLog.Debugf("Invalid getcfilters request: %v", err)
return return
} }
var updateCache bool var (
var checkptCache []cfHeaderKV updateCache bool
checkptCache []cfHeaderKV
)
// If the set of check points requested goes back further than what
// we've already generated in our cache, then we'll need to update it.
if len(blockHashes) > len(checkptCache) { if len(blockHashes) > len(checkptCache) {
// Update the cache if the checkpoint chain is longer than the cached // Update the cache if the checkpoint chain is longer than the
// one. This ensures that the cache is relatively stable and mostly // cached one. This ensures that the cache is relatively stable
// overlaps with the best chain, since it follows the longest chain // and mostly overlaps with the best chain, since it follows
// heuristic. // the longest chain heuristic.
updateCache = true updateCache = true
// Take write lock because we are going to update cache. // Take write lock because we are going to update cache.
@ -925,9 +975,13 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) {
// Grow the checkptCache to be the length of blockHashes. // Grow the checkptCache to be the length of blockHashes.
additionalLength := len(blockHashes) - len(checkptCache) additionalLength := len(blockHashes) - len(checkptCache)
checkptCache = append(sp.server.cfCheckptCaches[msg.FilterType], checkptCache = append(
make([]cfHeaderKV, additionalLength)...) sp.server.cfCheckptCaches[msg.FilterType],
make([]cfHeaderKV, additionalLength)...,
)
} else { } else {
// Otherwise, we don't need to update the cache as we already
// have enough headers pre-generated.
updateCache = false updateCache = false
// Take reader lock because we are not going to update cache. // Take reader lock because we are not going to update cache.
@ -946,8 +1000,9 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) {
} }
// Populate results with cached checkpoints. // Populate results with cached checkpoints.
checkptMsg := wire.NewMsgCFCheckpt(msg.FilterType, &msg.StopHash, checkptMsg := wire.NewMsgCFCheckpt(
len(blockHashes)) msg.FilterType, &msg.StopHash, len(blockHashes),
)
for i := 0; i < forkIdx; i++ { for i := 0; i < forkIdx; i++ {
checkptMsg.AddCFHeader(&checkptCache[i].filterHeader) checkptMsg.AddCFHeader(&checkptCache[i].filterHeader)
} }
@ -958,8 +1013,9 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) {
blockHashPtrs = append(blockHashPtrs, &blockHashes[i]) blockHashPtrs = append(blockHashPtrs, &blockHashes[i])
} }
filterHeaders, err := sp.server.cfIndex.FilterHeadersByBlockHashes(blockHashPtrs, filterHeaders, err := sp.server.cfIndex.FilterHeadersByBlockHashes(
msg.FilterType) blockHashPtrs, msg.FilterType,
)
if err != nil { if err != nil {
peerLog.Errorf("Error retrieving cfilter headers: %v", err) peerLog.Errorf("Error retrieving cfilter headers: %v", err)
return return
@ -967,7 +1023,8 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) {
for i, filterHeaderBytes := range filterHeaders { for i, filterHeaderBytes := range filterHeaders {
if len(filterHeaderBytes) == 0 { if len(filterHeaderBytes) == 0 {
peerLog.Warnf("Could not obtain CF header for %v", blockHashPtrs[i]) peerLog.Warnf("Could not obtain CF header for %v",
blockHashPtrs[i])
return return
} }