From d1e493f4ee492f838a4ebb17b2183dc7ec3a530c Mon Sep 17 00:00:00 2001
From: David Hill <dhill@mindcry.org>
Date: Thu, 7 Apr 2016 19:16:46 -0400
Subject: [PATCH] config: New option --blocksonly (#553)

The --blocksonly configuration option disables accepting transactions
from remote peers.  It will still accept, relay, and rebroadcast
valid transactions sent via RPC or websockets.
---
 config.go        |  1 +
 doc.go           |  1 +
 peer/peer.go     |  4 ++--
 sample-btcd.conf |  3 +++
 server.go        | 39 +++++++++++++++++++++++++++++++++++++--
 5 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/config.go b/config.go
index f63acb28..92b9798d 100644
--- a/config.go
+++ b/config.go
@@ -132,6 +132,7 @@ type config struct {
 	DropAddrIndex      bool          `long:"dropaddrindex" description:"Deletes the address-based transaction index from the database on start up, and then exits."`
 	NoPeerBloomFilters bool          `long:"nopeerbloomfilters" description:"Disable bloom filtering support."`
 	SigCacheMaxSize    uint          `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache."`
+	BlocksOnly         bool          `long:"blocksonly" description:"Do not accept transactions from remote peers."`
 	onionlookup        func(string) ([]net.IP, error)
 	lookup             func(string) ([]net.IP, error)
 	oniondial          func(string, string) (net.Conn, error)
diff --git a/doc.go b/doc.go
index d15b4f10..05fd4c31 100644
--- a/doc.go
+++ b/doc.go
@@ -112,6 +112,7 @@ Application Options:
       --nopeerbloomfilters  Disable bloom filtering support.
       --sigcachemaxsize=    The maximum number of entries in the signature
                             verification cache.
+      --blocksonly          Do not accept transactions from remote peers.
 
 Help Options:
   -h, --help           Show this help message
diff --git a/peer/peer.go b/peer/peer.go
index 98e9f008..cf773c94 100644
--- a/peer/peer.go
+++ b/peer/peer.go
@@ -1660,8 +1660,8 @@ out:
 			}
 
 		default:
-			log.Debugf("Received unhandled message of type %v:",
-				rmsg.Command())
+			log.Debugf("Received unhandled message of type %v "+
+				"from %v", rmsg.Command(), p)
 		}
 		p.stallControl <- stallControlMsg{sccHandlerDone, rmsg}
 
diff --git a/sample-btcd.conf b/sample-btcd.conf
index b0ab0bc0..ecb3fac9 100644
--- a/sample-btcd.conf
+++ b/sample-btcd.conf
@@ -233,6 +233,9 @@
 ; Limit orphan transaction pool to 1000 transactions.
 ; maxorphantx=1000
 
+; Do not accept transactions from remote peers.
+; blocksonly=1
+
 ; ------------------------------------------------------------------------------
 ; Optional Transaction Indexes
 ; ------------------------------------------------------------------------------
diff --git a/server.go b/server.go
index 195794b0..e1c08537 100644
--- a/server.go
+++ b/server.go
@@ -440,6 +440,12 @@ func (sp *serverPeer) OnMemPool(p *peer.Peer, msg *wire.MsgMemPool) {
 // handler this does not serialize all transactions through a single thread
 // transactions don't rely on the previous one in a linear fashion like blocks.
 func (sp *serverPeer) OnTx(p *peer.Peer, msg *wire.MsgTx) {
+	if cfg.BlocksOnly {
+		peerLog.Tracef("Ignoring tx %v from %v - blocksonly enabled",
+			msg.TxSha(), p)
+		return
+	}
+
 	// Add the transaction to the known inventory for the peer.
 	// Convert the raw MsgTx to a btcutil.Tx which provides some convenience
 	// methods and things such as hash caching.
@@ -487,7 +493,36 @@ func (sp *serverPeer) OnBlock(p *peer.Peer, msg *wire.MsgBlock, buf []byte) {
 // accordingly.  We pass the message down to blockmanager which will call
 // QueueMessage with any appropriate responses.
 func (sp *serverPeer) OnInv(p *peer.Peer, msg *wire.MsgInv) {
-	sp.server.blockManager.QueueInv(msg, sp)
+	if !cfg.BlocksOnly {
+		if len(msg.InvList) > 0 {
+			sp.server.blockManager.QueueInv(msg, sp)
+		}
+		return
+	}
+
+	newInv := wire.NewMsgInvSizeHint(uint(len(msg.InvList)))
+	for _, invVect := range msg.InvList {
+		if invVect.Type == wire.InvTypeTx {
+			peerLog.Tracef("Ignoring tx %v in inv from %v -- "+
+				"blocksonly enabled", invVect.Hash, p)
+			if p.ProtocolVersion() >= wire.BIP0037Version {
+				peerLog.Infof("Peer %v is announcing "+
+					"transactions -- disconnecting", p)
+				p.Disconnect()
+				return
+			}
+			continue
+		}
+		err := newInv.AddInvVect(invVect)
+		if err != nil {
+			peerLog.Errorf("Failed to add inventory vector: %v", err)
+			break
+		}
+	}
+
+	if len(newInv.InvList) > 0 {
+		sp.server.blockManager.QueueInv(newInv, sp)
+	}
 }
 
 // OnHeaders is invoked when a peer receives a headers bitcoin
@@ -1450,7 +1485,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config {
 		UserAgentVersion: userAgentVersion,
 		ChainParams:      sp.server.chainParams,
 		Services:         sp.server.services,
-		DisableRelayTx:   false,
+		DisableRelayTx:   cfg.BlocksOnly,
 		ProtocolVersion:  70011,
 	}
 }