Skip to content

Commit

Permalink
wire: Implement SFNodeBloom (BIP0111).
Browse files Browse the repository at this point in the history
SFNodeBloom is a new service flag that a node is required to use to
indicate that it supports bloom filtering.  This includes a protocol
version bump to 70011 and a wire version bump to 0.3.0.

btcd:
The SFNodeBloom flag is set by default.  A new configuration option
--nopeerbloomfilters has been added to to disable bloom filtering.

Any node advertising a version greater than or equal to 70011 that
attempts to use bloom filtering will be disconnected if bloom
filtering is disabled.

This mimics Bitcoin Core commit afb0ccaf9c9e4e8fac7db3564c4e19c9218c6b03
  • Loading branch information
dajohi committed Sep 28, 2015
1 parent 064cc8e commit c9ee3d9
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 98 deletions.
1 change: 1 addition & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ type config struct {
GetWorkKeys []string `long:"getworkkey" description:"DEPRECATED -- Use the --miningaddr option instead"`
AddrIndex bool `long:"addrindex" description:"Build and maintain a full address index. Currently only supported by leveldb."`
DropAddrIndex bool `long:"dropaddrindex" description:"Deletes the address-based transaction index from the database on start up, and the exits."`
NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support."`
onionlookup func(string) ([]net.IP, error)
lookup func(string) ([]net.IP, error)
oniondial func(string, string) (net.Conn, error)
Expand Down
165 changes: 85 additions & 80 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,86 +21,91 @@ Usage:
btcd [OPTIONS]
Application Options:
-V, --version Display version information and exit
-C, --configfile= Path to configuration file
-b, --datadir= Directory to store data
-a, --addpeer= Add a peer to connect with at startup
--connect= Connect only to the specified peers at startup
--nolisten Disable listening for incoming connections -- NOTE:
Listening is automatically disabled if the --connect
or --proxy options are used without also specifying
listen interfaces via --listen
--listen= Add an interface/port to listen for connections
(default all interfaces port: 8333, testnet: 18333)
--maxpeers= Max number of inbound and outbound peers (125)
--banduration= How long to ban misbehaving peers. Valid time units
are {s, m, h}. Minimum 1 second (24h0m0s)
-u, --rpcuser= Username for RPC connections
-P, --rpcpass= Password for RPC connections
--rpclimituser= Username for limited RPC connections
--rpclimitpass= Password for limited RPC connections
--rpclisten= Add an interface/port to listen for RPC connections
(default port: 8334, testnet: 18334)
--rpccert= File containing the certificate file
--rpckey= File containing the certificate key
--rpcmaxclients= Max number of RPC clients for standard connections
(10)
--rpcmaxwebsockets= Max number of RPC clients for standard connections
(25)
--norpc Disable built-in RPC server -- NOTE: The RPC server
is disabled by default if no rpcuser/rpcpass is
specified
--notls Disable TLS for the RPC server -- NOTE: This is only
allowed if the RPC server is bound to localhost
--nodnsseed Disable DNS seeding for peers
--externalip: Add an ip to the list of local addresses we claim to
listen on to peers
--proxy= Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)
--proxyuser= Username for proxy server
--proxypass= Password for proxy server
--onion= Connect to tor hidden services via SOCKS5 proxy (eg.
127.0.0.1:9050)
--onionuser= Username for onion proxy server
--onionpass= Password for onion proxy server
--noonion= Disable connecting to tor hidden services
--torisolation Enable Tor stream isolation by randomizing user
credentials for each connection.
--testnet= Use the test network
--regtest= Use the regression test network
--nocheckpoints= Disable built-in checkpoints. Don't do this unless
you know what you're doing.
--dbtype= Database backend to use for the Block Chain (leveldb)
--profile= Enable HTTP profiling on given port -- NOTE port must
be between 1024 and 65536 (6060)
--cpuprofile= Write CPU profile to the specified file
-d, --debuglevel: Logging level for all subsystems {trace, debug, info,
warn, error, critical} -- You may also specify
<subsystem>=<level>,<subsystem2>=<level>,... to set
the log level for individual subsystems -- Use show
to list available subsystems (info)
--upnp Use UPnP to map our listening port outside of NAT
--limitfreerelay= Limit relay of transactions with no transaction fee
to the given amount in thousands of bytes per minute
(15)
--norelaypriority Do not require free or low-fee transactions to have
high priority for relaying
--maxorphantx= Max number of orphan transactions to keep in memory
(1000)
--generate= Generate (mine) bitcoins using the CPU
--miningaddr= Add the specified payment address to the list of
addresses to use for generated blocks -- At least
one address is required if the generate option is set
--blockminsize= Mininum block size in bytes to be used when creating
a block
--blockmaxsize= Maximum block size in bytes to be used when creating
a block (750000)
--blockprioritysize= Size in bytes for high-priority/low-fee transactions
when creating a block (50000)
--getworkkey= DEPRECATED -- Use the --miningaddr option instead
--addrindex= Build and maintain a full address index. Currently
only supported by leveldb.
--dropaddrindex= Deletes the address-based transaction index from the
database on start up, and the exits.
-V, --version Display version information and exit
-C, --configfile= Path to configuration file
-b, --datadir= Directory to store data
--logdir= Directory to log output.
-a, --addpeer= Add a peer to connect with at startup
--connect= Connect only to the specified peers at startup
--nolisten Disable listening for incoming connections -- NOTE:
Listening is automatically disabled if the --connect
or --proxy options are used without also specifying
listen interfaces via --listen
--listen= Add an interface/port to listen for connections
(default all interfaces port: 8333, testnet: 18333)
--maxpeers= Max number of inbound and outbound peers (125)
--banduration= How long to ban misbehaving peers. Valid time units
are {s, m, h}. Minimum 1 second (24h0m0s)
-u, --rpcuser= Username for RPC connections
-P, --rpcpass= Password for RPC connections
--rpclimituser= Username for limited RPC connections
--rpclimitpass= Password for limited RPC connections
--rpclisten= Add an interface/port to listen for RPC connections
(default port: 8334, testnet: 18334)
--rpccert= File containing the certificate file
--rpckey= File containing the certificate key
--rpcmaxclients= Max number of RPC clients for standard connections
(10)
--rpcmaxwebsockets= Max number of RPC websocket connections (25)
--norpc Disable built-in RPC server -- NOTE: The RPC server
is disabled by default if no rpcuser/rpcpass or
rpclimituser/rpclimitpass is specified
--notls Disable TLS for the RPC server -- NOTE: This is only
allowed if the RPC server is bound to localhost
--nodnsseed Disable DNS seeding for peers
--externalip= Add an ip to the list of local addresses we claim to
listen on to peers
--proxy= Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)
--proxyuser= Username for proxy server
--proxypass= Password for proxy server
--onion= Connect to tor hidden services via SOCKS5 proxy
(eg. 127.0.0.1:9050)
--onionuser= Username for onion proxy server
--onionpass= Password for onion proxy server
--noonion Disable connecting to tor hidden services
--torisolation Enable Tor stream isolation by randomizing user
credentials for each connection.
--testnet Use the test network
--regtest Use the regression test network
--simnet Use the simulation test network
--nocheckpoints Disable built-in checkpoints. Don't do this unless
you know what you're doing.
--dbtype= Database backend to use for the Block Chain
(leveldb)
--profile= Enable HTTP profiling on given port -- NOTE port
must be between 1024 and 65536
--cpuprofile= Write CPU profile to the specified file
-d, --debuglevel= Logging level for all subsystems {trace, debug,
info, warn, error, critical} -- You may also specify
<subsystem>=<level>,<subsystem2>=<level>,... to set
the log level for individual subsystems -- Use show
to list available subsystems (info)
--upnp Use UPnP to map our listening port outside of NAT
--limitfreerelay= Limit relay of transactions with no transaction fee
to the given amount in thousands of bytes per
minute (15)
--norelaypriority Do not require free or low-fee transactions to have
high priority for relaying
--maxorphantx= Max number of orphan transactions to keep in memory
(1000)
--generate Generate (mine) bitcoins using the CPU
--miningaddr= Add the specified payment address to the list of
addresses to use for generated blocks -- At least
one address is required if the generate option is
set
--blockminsize= Mininum block size in bytes to be used when creating
a block
--blockmaxsize= Maximum block size in bytes to be used when creating
a block (750000)
--blockprioritysize= Size in bytes for high-priority/low-fee transactions
when creating a block (50000)
--getworkkey= DEPRECATED -- Use the --miningaddr option instead
--addrindex Build and maintain a full address index. Currently
only supported by leveldb.
--dropaddrindex Deletes the address-based transaction index from the
database on start up, and the exits.
--nopeerbloomfilters Disable bloom filtering support.
Help Options:
-h, --help Show this help message
Expand Down
37 changes: 34 additions & 3 deletions peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (

const (
// maxProtocolVersion is the max protocol version the peer supports.
maxProtocolVersion = 70002
maxProtocolVersion = 70011

// outputBufferSize is the number of elements the output channels use.
outputBufferSize = 50
Expand Down Expand Up @@ -335,8 +335,8 @@ func (p *peer) pushVersionMsg() error {
// by the remote peer in its version message
msg.AddrYou.Services = wire.SFNodeNetwork

// Advertise that we're a full node.
msg.Services = wire.SFNodeNetwork
// Advertise our supported services.
msg.Services = p.server.services

// Advertise our max supported protocol version.
msg.ProtocolVersion = maxProtocolVersion
Expand Down Expand Up @@ -1088,11 +1088,33 @@ func (p *peer) handleGetHeadersMsg(msg *wire.MsgGetHeaders) {
p.QueueMessage(headersMsg, nil)
}

// isValidBIP0111 is a helper function for the bloom filter commands to check
// BIP0111 compliance.
func (p *peer) isValidBIP0111(cmd string) bool {
if p.server.services&wire.SFNodeBloom != wire.SFNodeBloom {
if p.ProtocolVersion() >= wire.BIP0111Version {
peerLog.Debugf("%s sent an unsupported %s "+
"request -- disconnecting", p, cmd)
p.Disconnect()
} else {
peerLog.Debugf("Ignoring %s request from %s -- bloom "+
"support is disabled", cmd, p)
}
return false
}

return true
}

// handleFilterAddMsg is invoked when a peer receives a filteradd bitcoin
// message and is used by remote peers to add data to an already loaded bloom
// filter. The peer will be disconnected if a filter is not loaded when this
// message is received.
func (p *peer) handleFilterAddMsg(msg *wire.MsgFilterAdd) {
if !p.isValidBIP0111(msg.Command()) {
return
}

if !p.filter.IsLoaded() {
peerLog.Debugf("%s sent a filteradd request with no filter "+
"loaded -- disconnecting", p)
Expand All @@ -1108,19 +1130,28 @@ func (p *peer) handleFilterAddMsg(msg *wire.MsgFilterAdd) {
// The peer will be disconnected if a filter is not loaded when this message is
// received.
func (p *peer) handleFilterClearMsg(msg *wire.MsgFilterClear) {
if !p.isValidBIP0111(msg.Command()) {
return
}

if !p.filter.IsLoaded() {
peerLog.Debugf("%s sent a filterclear request with no "+
"filter loaded -- disconnecting", p)
p.Disconnect()
return
}

p.filter.Unload()
}

// handleFilterLoadMsg is invoked when a peer receives a filterload bitcoin
// message and it used to load a bloom filter that should be used for delivering
// merkle blocks and associated transactions that match the filter.
func (p *peer) handleFilterLoadMsg(msg *wire.MsgFilterLoad) {
if !p.isValidBIP0111(msg.Command()) {
return
}

// Transaction relay is no longer disabled once a filterload message is
// received regardless of its original state.
p.relayMtx.Lock()
Expand Down
2 changes: 2 additions & 0 deletions sample-btcd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@
; Disable listening for incoming connections. This will override all listeners.
; nolisten=1

; Disable peer bloom filtering. See BIP0111.
; nopeerbloomfilters=1

; ------------------------------------------------------------------------------
; RPC server options - The following options control the built-in RPC server
Expand Down
23 changes: 15 additions & 8 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ import (
)

const (
// These constants are used by the DNS seed code to pick a random last seen
// time.
// These constants are used by the DNS seed code to pick a random last
// seen time.
secondsIn3Days int32 = 24 * 60 * 60 * 3
secondsIn4Days int32 = 24 * 60 * 60 * 4
)

const (
// supportedServices describes which services are supported by the
// server.
supportedServices = wire.SFNodeNetwork
// defaultServices describes the default services that are supported by
// the server.
defaultServices = wire.SFNodeNetwork | wire.SFNodeBloom

// defaultMaxOutbound is the default number of max outbound peers.
defaultMaxOutbound = 8
Expand Down Expand Up @@ -109,6 +109,7 @@ type server struct {
nat NAT
db database.Db
timeSource blockchain.MedianTimeSource
services wire.ServiceFlag
}

type peerState struct {
Expand Down Expand Up @@ -1216,7 +1217,7 @@ out:
continue out
}
na := wire.NewNetAddressIPPort(externalip, uint16(listenPort),
wire.SFNodeNetwork)
s.services)
err = s.addrManager.AddLocalAddress(na, addrmgr.UpnpPrio)
if err != nil {
// XXX DeletePortMapping?
Expand Down Expand Up @@ -1250,6 +1251,11 @@ func newServer(listenAddrs []string, db database.Db, chainParams *chaincfg.Param
return nil, err
}

services := defaultServices
if cfg.NoPeerBloomFilters {
services &^= wire.SFNodeBloom
}

amgr := addrmgr.New(cfg.DataDir, btcdLookup)

var listeners []net.Listener
Expand Down Expand Up @@ -1287,7 +1293,7 @@ func newServer(listenAddrs []string, db database.Db, chainParams *chaincfg.Param
eport = uint16(port)
}
na, err := amgr.HostToNetAddress(host, eport,
wire.SFNodeNetwork)
services)
if err != nil {
srvrLog.Warnf("Not adding %s as "+
"externalip: %v", sip, err)
Expand Down Expand Up @@ -1323,7 +1329,7 @@ func newServer(listenAddrs []string, db database.Db, chainParams *chaincfg.Param
continue
}
na := wire.NewNetAddressIPPort(ip,
uint16(port), wire.SFNodeNetwork)
uint16(port), services)
if discover {
err = amgr.AddLocalAddress(na, addrmgr.InterfacePrio)
if err != nil {
Expand Down Expand Up @@ -1394,6 +1400,7 @@ func newServer(listenAddrs []string, db database.Db, chainParams *chaincfg.Param
nat: nat,
db: db,
timeSource: blockchain.NewMedianTime(),
services: services,
}
bm, err := newBlockManager(&s)
if err != nil {
Expand Down
9 changes: 5 additions & 4 deletions wire/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,10 @@ Bitcoin Improvement Proposals
This package includes spec changes outlined by the following BIPs:
BIP0014 (https://en.bitcoin.it/wiki/BIP_0014)
BIP0031 (https://en.bitcoin.it/wiki/BIP_0031)
BIP0035 (https://en.bitcoin.it/wiki/BIP_0035)
BIP0037 (https://en.bitcoin.it/wiki/BIP_0037)
BIP0014 (https://github.com/bitcoin/bips/blob/master/bip-0014.mediawiki)
BIP0031 (https://github.com/bitcoin/bips/blob/master/bip-0031.mediawiki)
BIP0035 (https://github.com/bitcoin/bips/blob/master/bip-0035.mediawiki)
BIP0037 (https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki)
BIP0111 (https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki)
*/
package wire
2 changes: 1 addition & 1 deletion wire/msgversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
const MaxUserAgentLen = 2000

// DefaultUserAgent for wire in the stack
const DefaultUserAgent = "/btcwire:0.2.1/"
const DefaultUserAgent = "/btcwire:0.3.0/"

// MsgVersion implements the Message interface and represents a bitcoin version
// message. It is used for a peer to advertise itself as soon as an outbound
Expand Down
Loading

0 comments on commit c9ee3d9

Please sign in to comment.