diff --git a/server.go b/server.go index 320238ad..0f1d100f 100644 --- a/server.go +++ b/server.go @@ -385,6 +385,12 @@ func (sp *serverPeer) addBanScore(persistent, transient uint32, reason string) { } } +// hasServices returns whether or not the provided advertised service flags have +// all of the provided desired service flags set. +func hasServices(advertised, desired wire.ServiceFlag) bool { + return advertised&desired == desired +} + // OnVersion is invoked when a peer receives a version bitcoin message // and is used to negotiate the protocol version details as well as kick start // the communications. @@ -395,6 +401,18 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej return nil } + // Reject outbound peers that are not full nodes. + wantServices := wire.SFNodeNetwork + if !sp.Inbound() && !hasServices(msg.Services, wantServices) { + missingServices := wantServices & ^msg.Services + srvrLog.Debugf("Rejecting peer %s with services %v due to not "+ + "providing desired services %v", sp.Peer, msg.Services, + missingServices) + reason := fmt.Sprintf("required services %#x not offered", + uint64(missingServices)) + return wire.NewMsgReject(msg.Command(), wire.RejectNonstandard, reason) + } + // Add the remote peer time as a sample for creating an offset against // the local clock to keep the network time in sync. sp.server.timeSource.AddTimeSample(sp.Addr(), msg.Timestamp)