peer: Implement sendheaders support (BIP0130).

This modifies the peer package to add support for the sendheaders
protocol message introduced by BIP0030.

NOTE: This does not add support to btcd itself. That requires the server
and sync code to make use of the new functionality exposed by these
changes.  As a result, btcd will still be using protocol version 70011.
This commit is contained in:
David Hill 2016-04-06 17:56:48 -04:00 committed by Dave Collins
parent c1861bc8fa
commit 8a58f8cf3a
3 changed files with 44 additions and 11 deletions

View file

@ -26,7 +26,7 @@ import (
const ( const (
// MaxProtocolVersion is the max protocol version the peer supports. // MaxProtocolVersion is the max protocol version the peer supports.
MaxProtocolVersion = 70011 MaxProtocolVersion = wire.SendHeadersVersion
// outputBufferSize is the number of elements the output channels use. // outputBufferSize is the number of elements the output channels use.
outputBufferSize = 50 outputBufferSize = 50
@ -175,6 +175,10 @@ type MessageListeners struct {
// OnReject is invoked when a peer receives a reject bitcoin message. // OnReject is invoked when a peer receives a reject bitcoin message.
OnReject func(p *Peer, msg *wire.MsgReject) OnReject func(p *Peer, msg *wire.MsgReject)
// OnSendHeaders is invoked when a peer receives a sendheaders bitcoin
// message.
OnSendHeaders func(p *Peer, msg *wire.MsgSendHeaders)
// OnRead is invoked when a peer receives a bitcoin message. It // OnRead is invoked when a peer receives a bitcoin message. It
// consists of the number of bytes read, the message, and whether or not // consists of the number of bytes read, the message, and whether or not
// an error in the read occurred. Typically, callers will opt to use // an error in the read occurred. Typically, callers will opt to use
@ -401,15 +405,16 @@ type Peer struct {
cfg Config cfg Config
inbound bool inbound bool
flagsMtx sync.Mutex // protects the peer flags below flagsMtx sync.Mutex // protects the peer flags below
na *wire.NetAddress na *wire.NetAddress
id int32 id int32
userAgent string userAgent string
services wire.ServiceFlag services wire.ServiceFlag
versionKnown bool versionKnown bool
protocolVersion uint32 protocolVersion uint32
versionSent bool sendHeadersPreferred bool // peer sent a sendheaders message
verAckReceived bool versionSent bool
verAckReceived bool
knownInventory *mruInventoryMap knownInventory *mruInventoryMap
prevGetBlocksMtx sync.Mutex prevGetBlocksMtx sync.Mutex
@ -725,6 +730,17 @@ func (p *Peer) StartingHeight() int32 {
return p.startingHeight return p.startingHeight
} }
// WantsHeaders returns if the peer wants header messages instead of
// inventory vectors for blocks.
//
// This function is safe for concurrent access.
func (p *Peer) WantsHeaders() bool {
p.flagsMtx.Lock()
defer p.flagsMtx.Unlock()
return p.sendHeadersPreferred
}
// pushVersionMsg sends a version message to the connected peer using the // pushVersionMsg sends a version message to the connected peer using the
// current state. // current state.
func (p *Peer) pushVersionMsg() error { func (p *Peer) pushVersionMsg() error {
@ -1634,6 +1650,15 @@ out:
p.cfg.Listeners.OnReject(p, msg) p.cfg.Listeners.OnReject(p, msg)
} }
case *wire.MsgSendHeaders:
p.flagsMtx.Lock()
p.sendHeadersPreferred = true
p.flagsMtx.Unlock()
if p.cfg.Listeners.OnSendHeaders != nil {
p.cfg.Listeners.OnSendHeaders(p, msg)
}
default: default:
log.Debugf("Received unhandled message of type %v:", log.Debugf("Received unhandled message of type %v:",
rmsg.Command()) rmsg.Command())

View file

@ -379,6 +379,9 @@ func TestPeerListeners(t *testing.T) {
OnReject: func(p *peer.Peer, msg *wire.MsgReject) { OnReject: func(p *peer.Peer, msg *wire.MsgReject) {
ok <- msg ok <- msg
}, },
OnSendHeaders: func(p *peer.Peer, msg *wire.MsgSendHeaders) {
ok <- msg
},
}, },
UserAgentName: "peer", UserAgentName: "peer",
UserAgentVersion: "1.0", UserAgentVersion: "1.0",
@ -496,9 +499,13 @@ func TestPeerListeners(t *testing.T) {
// only one version message is allowed // only one version message is allowed
// only one verack message is allowed // only one verack message is allowed
{ {
"OnMsgReject", "OnReject",
wire.NewMsgReject("block", wire.RejectDuplicate, "dupe block"), wire.NewMsgReject("block", wire.RejectDuplicate, "dupe block"),
}, },
{
"OnSendHeaders",
wire.NewMsgSendHeaders(),
},
} }
t.Logf("Running %d tests", len(tests)) t.Logf("Running %d tests", len(tests))
for _, test := range tests { for _, test := range tests {

View file

@ -1453,6 +1453,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config {
ChainParams: sp.server.chainParams, ChainParams: sp.server.chainParams,
Services: sp.server.services, Services: sp.server.services,
DisableRelayTx: false, DisableRelayTx: false,
ProtocolVersion: 70011,
} }
} }