Repository: decred/dcrd
Pull request #2257 (2020-07-11 12:32:13)

 rpcserver: Rework default configs for tests.
This updates the rpcserver handler tests to use a reasonable default
rpcserverConfig.  This allows for less of a need to provide mocks in
every test and instead only override where necessary.  It also reduces
the likelihood of the tests panicking if code is added to rpcserver
where an assumption of a non-nil value is being made.

This is broken up into a few commits to make it easier to review:
- Rework default configs for tests.
- Update tests to use default configs
- Run tests in parallel.


Patch:
diff --git a/connmgr/connmanager.go b/connmgr/connmanager.go
index 4b15e258..7efbcb14 100644
--- a/connmgr/connmanager.go
+++ b/connmgr/connmanager.go
@@ -250,24 +250,26 @@ func (cm *ConnManager) handleFailedConn(ctx context.Context, c *ConnReq) {
 			d = maxRetryDuration
 		}
 		log.Debugf("Retrying connection to %v in %v", c, d)
-		select {
-		case <-time.After(d):
-			go cm.Connect(ctx, c)
-		case <-cm.quit:
-			return
-		}
+		go func() {
+			select {
+			case <-time.After(d):
+				cm.Connect(ctx, c)
+			case <-cm.quit:
+			}
+		}()
 	} else if cm.cfg.GetNewAddress != nil {
 		cm.failedAttempts++
 		if cm.failedAttempts >= maxFailedAttempts {
 			log.Debugf("Max failed connection attempts reached: [%d] "+
 				"-- retrying connection in: %v", maxFailedAttempts,
 				cm.cfg.RetryDuration)
-			select {
-			case <-time.After(cm.cfg.RetryDuration):
-				go cm.newConnReq(ctx)
-			case <-cm.quit:
-				return
-			}
+			go func() {
+				select {
+				case <-time.After(cm.cfg.RetryDuration):
+					cm.newConnReq(ctx)
+				case <-cm.quit:
+				}
+			}()
 		} else {
 			go cm.newConnReq(ctx)
 		}
diff --git a/server.go b/server.go
index b51c8521..9ec45fa1 100644
--- a/server.go
+++ b/server.go
@@ -2024,6 +2024,7 @@ func (s *server) handleQuery(state *peerState, querymsg interface{}) {
 				Permanent: msg.permanent,
 			})
 		msg.reply <- nil
+
 	case removeNodeMsg:
 		found := disconnectPeer(state.persistentPeers, msg.cmp, func(sp *serverPeer) {
 			// Keep group counts ok since we remove from
@@ -2045,6 +2046,7 @@ func (s *server) handleQuery(state *peerState, querymsg interface{}) {
 		} else {
 			msg.reply <- errors.New("peer not found")
 		}
+
 	case cancelPendingMsg:
 		netAddr, err := addrStringToNetAddr(msg.addr)
 		if err != nil {
@@ -2052,6 +2054,7 @@ func (s *server) handleQuery(state *peerState, querymsg interface{}) {
 			return
 		}
 		msg.reply <- s.connManager.CancelPending(netAddr)
+
 	case getOutboundGroup:
 		count, ok := state.outboundGroups[msg.key]
 		if ok {
@@ -2059,7 +2062,7 @@ func (s *server) handleQuery(state *peerState, querymsg interface{}) {
 		} else {
 			msg.reply <- 0
 		}
-	// Request a list of the persistent (added) peers.
+
 	case getAddedNodesMsg:
 		// Respond with a slice of the relevant peers.
 		peers := make([]*serverPeer, 0, len(state.persistentPeers))
@@ -2067,6 +2070,7 @@ func (s *server) handleQuery(state *peerState, querymsg interface{}) {
 			peers = append(peers, sp)
 		}
 		msg.reply <- peers
+
 	case disconnectNodeMsg:
 		// Check inbound peers. We pass a nil callback since we don't
 		// require any additional actions on disconnect for inbound peers.


Test patch:
diff --git a/connmgr/connmanager_test.go b/connmgr/connmanager_test.go
index beb2d8c5..db705c32 100644
--- a/connmgr/connmanager_test.go
+++ b/connmgr/connmanager_test.go
@@ -8,6 +8,7 @@ package connmgr
 import (
 	"context"
 	"errors"
+	"fmt"
 	"io"
 	"net"
 	"sync"
@@ -99,7 +100,7 @@ func mockDialerAddr(ctx context.Context, addr net.Addr) (net.Conn, error) {
 func TestNewConfig(t *testing.T) {
 	_, err := New(&Config{})
 	if err == nil {
-		t.Fatalf("New expected error: 'Dial can't be nil', got nil")
+		t.Fatal("New expected error: 'Dial can't be nil', got nil")
 	}
 	_, err = New(&Config{
 		Dial: mockDialer,
@@ -113,7 +114,7 @@ func TestNewConfig(t *testing.T) {
 		DialAddr: mockDialerAddr,
 	})
 	if err == nil {
-		t.Fatalf("New expected error: 'Dial and DialAddr can't be both nil', got nil")
+		t.Fatal("New expected error: 'Dial and DialAddr can't be both nil', got nil")
 	}
 
 	_, err = New(&Config{
@@ -269,13 +270,13 @@ func TestPassAddrAlongDialAddr(t *testing.T) {
 	case c := <-connected:
 		receivedMock, isMockAddr := c.Addr.(mockAddr)
 		if !isMockAddr {
-			t.Fatalf("connected to an address that was not a mockAddr")
+			t.Fatal("connected to an address that was not a mockAddr")
 		}
 		if receivedMock != targetAddr {
-			t.Fatalf("connected to an address different than the expected target")
+			t.Fatal("connected to an address different than the expected target")
 		}
 	case <-time.After(time.Millisecond * 5):
-		t.Fatalf("did not get connection to target address before timeout")
+		t.Fatal("did not get connection to target address before timeout")
 	}
 
 	// Ensure clean shutdown of connection manager.
@@ -390,7 +391,7 @@ func TestMaxRetryDuration(t *testing.T) {
 	select {
 	case <-connected:
 	case <-time.After(20 * time.Millisecond):
-		t.Fatalf("max retry duration: connection timeout")
+		t.Fatal("max retry duration: connection timeout")
 	}
 
 	// Ensure clean shutdown of connection manager.
@@ -454,6 +455,77 @@ func TestNetworkFailure(t *testing.T) {
 	}
 }
 
+// TestMultipleFailedConns ensures that the connection manager remains
+// responsive when there are multiple simultaneous failed connections for
+// persistent peers in the retry state.
+func TestMultipleFailedConns(t *testing.T) {
+	// Override the max retry duration for this test since it relies on having
+	// multiple connections in the retry state.
+	curMaxRetryDuration := maxRetryDuration
+	maxRetryDuration = 500 * time.Millisecond
+	defer func() {
+		maxRetryDuration = curMaxRetryDuration
+	}()
+
+	const targetFailed = 5
+	var dials uint32
+	var closeOnce sync.Once
+	hitTargetFailed := make(chan struct{})
+	errDialer := func(ctx context.Context, network, addr string) (net.Conn, error) {
+		totalDials := atomic.AddUint32(&dials, 1)
+		if totalDials >= targetFailed {
+			closeOnce.Do(func() { close(hitTargetFailed) })
+		}
+		return nil, errors.New("network down")
+	}
+	cmgr, err := New(&Config{
+		RetryDuration: maxRetryDuration,
+		Dial:          errDialer,
+	})
+	if err != nil {
+		t.Fatalf("New error: %v", err)
+	}
+	ctx, shutdown, wg := runConnMgrAsync(context.Background(), cmgr)
+
+	// Establish several connection requests to localhost IPs.
+	for i := 0; i < targetFailed; i++ {
+		cr := &ConnReq{
+			Addr: &net.TCPAddr{
+				IP:   net.ParseIP(fmt.Sprintf("127.0.0.%d", i+1)),
+				Port: 18555,
+			},
+			Permanent: true,
+		}
+		go cmgr.Connect(ctx, cr)
+	}
+
+	// Wait for the target number of dials and ensure they happen simultaneously
+	// by checking it happens before the retry timeout.
+	select {
+	case <-hitTargetFailed:
+	case <-time.After(20 * time.Millisecond):
+		t.Fatal("did not reach target number of dials before timeout")
+	}
+
+	// Ensure that the connection manager still responds to requests while the
+	// failed connections are still retrying.
+	disconnected := make(chan struct{})
+	go func() {
+		const badID = ^uint64(0)
+		cmgr.Disconnect(badID)
+		close(disconnected)
+	}()
+	select {
+	case <-disconnected:
+	case <-time.After(20 * time.Millisecond):
+		t.Fatal("timeout servicing connmgr requests")
+	}
+
+	// Ensure clean shutdown of connection manager.
+	shutdown()
+	wg.Wait()
+}
+
 // TestShutdownFailedConns tests that failed connections are ignored after
 // connmgr is shutdown.
 //
@@ -619,7 +691,7 @@ func TestCancelIgnoreDelayedConnection(t *testing.T) {
 	// allowed to properly elapse.
 	select {
 	case <-connected:
-		t.Fatalf("on-connect should not be called for canceled req")
+		t.Fatal("on-connect should not be called for canceled req")
 	case <-time.After(5 * retryTimeout):
 	}
 
diff --git a/rpcserverhandlers_test.go b/rpcserverhandlers_test.go
index b959339c..abba8891 100644
--- a/rpcserverhandlers_test.go
+++ b/rpcserverhandlers_test.go
@@ -18,6 +18,7 @@ import (
 	"path/filepath"
 	"reflect"
 	"strconv"
+	"sync"
 	"testing"
 	"time"
 
@@ -634,6 +635,18 @@ func mustParseHash(s string) *chainhash.Hash {
 	return hash
 }
 
+// hexToBytes converts the passed hex string into bytes and will panic if there
+// is an error.  This is only provided for the hard-coded constants so errors in
+// the source code can be detected. It will only (and must only) be called with
+// hard-coded values.
+func hexToBytes(s string) []byte {
+	b, err := hex.DecodeString(s)
+	if err != nil {
+		panic("invalid hex in source file: " + s)
+	}
+	return b
+}
+
 // cloneParams returns a deep copy of the provided parameters so the caller is
 // free to modify them without worrying about interfering with other tests.
 func cloneParams(params *chaincfg.Params) *chaincfg.Params {
@@ -677,81 +690,345 @@ type rpcTest struct {
 	mockSyncManager *testSyncManager
 	mockConnManager *testConnManager
 	mockClock       *testClock
-	mockCfg         *config
 	result          interface{}
 	wantErr         bool
 	errCode         dcrjson.RPCErrorCode
 }
 
-// Provide default configurations that can be overridden by tests as needed.
-var defaultCfg = &config{}
-var defaultChainParams = chaincfg.MainNetParams()
-var defaultRPCChain = &testRPCChain{
-	bestSnapshot: &blockchain.BestState{
-		Height: 463073,
-		Bits:   404696953,
-		Hash: *mustParseHash("00000000000000001e6ec1501c858506de1de4703d1be8bab4061" +
-			"126e8f61480"),
-		PrevHash: *mustParseHash("00000000000000001a1ec2becd0dd90bfbd0c65f42fdaf608" +
-			"dd9ceac2a3aee1d"),
-	},
-}
-var defaultAddrManager = &testAddrManager{}
-var defaultSyncManager = &testSyncManager{}
-var defaultConnManager = &testConnManager{}
-var defaultClock = &testClock{}
+// setCfgOnce is used to set cfg once safely.
+var setCfgOnce sync.Once
+
+// defaultCfg provides a default config that is used throughout the tests.
+func defaultCfg() *config {
+	return &config{
+		ipv4NetInfo: types.NetworksResult{
+			Name:                      "IPV4",
+			Limited:                   false,
+			Reachable:                 true,
+			Proxy:                     "",
+			ProxyRandomizeCredentials: false,
+		},
+		ipv6NetInfo: types.NetworksResult{
+			Name:                      "IPV6",
+			Limited:                   false,
+			Reachable:                 true,
+			Proxy:                     "",
+			ProxyRandomizeCredentials: false,
+		},
+		onionNetInfo: types.NetworksResult{
+			Name:                      "Onion",
+			Limited:                   false,
+			Reachable:                 false,
+			Proxy:                     "",
+			ProxyRandomizeCredentials: false,
+		},
+		lookup: func(host string) ([]net.IP, error) {
+			if host == "mydomain.org" {
+				return []net.IP{net.ParseIP("127.0.0.211")}, nil
+			}
+			return nil, errors.New("host not found")
+		},
+		minRelayTxFee: dcrutil.Amount(int64(10000)),
+	}
+}
+
+// defaultChainParams provides a default chaincfg.Params to be used throughout
+// the tests.  It should be cloned using cloneParams, updated as necessary, and
+// then assigned to rpcTest.mockChainParams if it needs to be overridden by a
+// test.
+var defaultChainParams = func() *chaincfg.Params {
+	testChainParams := cloneParams(chaincfg.MainNetParams())
+	testChainParams.Name = "mainnet"
+	testChainParams.Deployments = map[uint32][]chaincfg.ConsensusDeployment{
+		7: {{
+			Vote: chaincfg.Vote{
+				Id:          chaincfg.VoteIDHeaderCommitments,
+				Description: "Enable header commitments as defined in DCP0005",
+				Mask:        0x0006, // Bits 1 and 2
+				Choices: []chaincfg.Choice{{
+					Id:          "abstain",
+					Description: "abstain voting for change",
+					Bits:        0x0000,
+					IsAbstain:   true,
+					IsNo:        false,
+				}, {
+					Id:          "no",
+					Description: "keep the existing consensus rules",
+					Bits:        0x0002, // Bit 1
+					IsAbstain:   false,
+					IsNo:        true,
+				}, {
+					Id:          "yes",
+					Description: "change to the new consensus rules",
+					Bits:        0x0004, // Bit 2
+					IsAbstain:   false,
+					IsNo:        false,
+				}},
+			},
+			StartTime:  1567641600, // Sep 5th, 2019
+			ExpireTime: 1599264000, // Sep 5th, 2020
+		}},
+	}
+	testChainParams.PowLimitBits = 0x1d00ffff
+	return testChainParams
+}()
+
+// defaultMockRPCChain provides a default mock chain to be used throughout
+// the tests.  Tests can override these defaults by calling defaultMockRPCChain,
+// updating fields as necessary on the returned *testRPCChain, and then setting
+// rpcTest.mockChain as that *testRPCChain.
+func defaultMockRPCChain() *testRPCChain {
+	// Define variables related to block432100 to be used as default values for the
+	// mock chain.
+	blk := dcrutil.NewBlock(&block432100)
+	blkHeader := block432100.Header
+	blkHash := blk.Hash()
+	blkHeight := blk.Height()
+	chainWork, _ := new(big.Int).SetString("0e805fb85284503581c57c", 16)
+	filter, _ := gcs.FromBytesV2(20, 1<<20, nil)
+
+	return &testRPCChain{
+		bestSnapshot: &blockchain.BestState{
+			Hash:           *blkHash,
+			PrevHash:       blkHeader.PrevBlock,
+			Height:         blkHeight,
+			Bits:           blkHeader.Bits,
+			NextPoolSize:   41135,
+			NextStakeDiff:  14428162590,
+			BlockSize:      uint64(blkHeader.Size),
+			NumTxns:        7,
+			TotalTxns:      7478697,
+			MedianTime:     time.Unix(1584246683, 0), // 2020-03-15 04:31:23 UTC
+			TotalSubsidy:   1122503888072909,
+			NextFinalState: [6]byte{0xdc, 0x2a, 0x4f, 0x6e, 0x60, 0xb3},
+		},
+		blockByHash:                     blk,
+		blockByHeight:                   blk,
+		blockHashByHeight:               blkHash,
+		blockHeightByHash:               blkHeight,
+		calcNextRequiredStakeDifficulty: 14428162590,
+		calcWantHeight:                  431487,
+		chainTips: []blockchain.ChainTipInfo{{
+			Height:    blkHeight,
+			Hash:      *blkHash,
+			BranchLen: 500,
+			Status:    "active",
+		}},
+		chainWork: chainWork,
+		convertUtxosToMinimalOutputs: []*stake.MinimalOutput{{
+			PkScript: hexToBytes("baa914780239ea1231ba67b0c5b82e786b51e21072522187"),
+			Value:    100000000,
+			Version:  0,
+		}, {
+			PkScript: hexToBytes("6a1e355c96f48612d57509140e9a049981d5f9970f945c770d00000000000058"),
+			Value:    0,
+			Version:  0,
+		}, {
+			PkScript: hexToBytes("bd76a914000000000000000000000000000000000000000088ac"),
+			Value:    0,
+			Version:  0,
+		}},
+		estimateNextStakeDifficulty: 14336790201,
+		fetchUtxoEntry: &testRPCUtxoEntry{
+			hasExpiry: true,
+			height:    100000,
+			txType:    stake.TxTypeSStx,
+			txVersion: 1,
+		},
+		fetchUtxoStats: &blockchain.UtxoStats{
+			Utxos:          1593879,
+			Transactions:   689819,
+			Size:           36441617,
+			Total:          1154067750680149,
+			SerializedHash: *mustParseHash("fe7b32aa188800f07268b17f3bead5f3d8a1b6d18654182066436efce6effa86"),
+		},
+		filterByBlockHash: filter,
+		getStakeVersions: []blockchain.StakeVersions{{
+			Hash:         *blkHash,
+			Height:       blkHeight,
+			BlockVersion: blkHeader.Version,
+			StakeVersion: blkHeader.StakeVersion,
+			Votes: []stake.VoteVersionTuple{{
+				Version: 7,
+				Bits:    1,
+			}},
+		}},
+		getVoteInfo: &blockchain.VoteInfo{
+			Agendas: defaultChainParams.Deployments[0],
+			AgendaStatus: []blockchain.ThresholdStateTuple{{
+				State:  blockchain.ThresholdStarted,
+				Choice: uint32(0xffffffff),
+			}},
+		},
+		headerByHash:      blkHeader,
+		headerByHeight:    blkHeader,
+		isCurrent:         true,
+		mainChainHasBlock: true,
+		maxBlockSize:      int64(393216),
+		nextThresholdState: blockchain.ThresholdStateTuple{
+			State:  blockchain.ThresholdStarted,
+			Choice: uint32(0xffffffff),
+		},
+		ticketPoolValue: 570678298669222,
+	}
+}
+
+// defaultMockAddrManager provides a default mock address manager to be used
+// throughout the tests. Tests can override these defaults by calling
+// defaultMockAddrManager, updating fields as necessary on the returned
+// *testAddrManager, and then setting rpcTest.mockAddrManager as that
+// *testAddrManager.
+func defaultMockAddrManager() *testAddrManager {
+	return &testAddrManager{
+		localAddresses: []addrmgr.LocalAddr{{
+			Address: "127.0.0.184",
+			Port:    uint16(19108),
+			Score:   int32(0),
+		}},
+	}
+}
+
+// defaultMockSyncManager provides a default mock sync manager to be used
+// throughout the tests. Tests can override these defaults by calling
+// defaultMockSyncManager, updating fields as necessary on the returned
+// *testSyncManager, and then setting rpcTest.mockSyncManager as that
+// *testSyncManager.
+func defaultMockSyncManager() *testSyncManager {
+	return &testSyncManager{
+		submitBlock: true,
+		syncHeight:  463074,
+	}
+}
+
+// defaultMockConnManager provides a default mock connection manager to be used
+// throughout the tests. Tests can override these defaults by calling
+// defaultMockConnManager, updating fields as necessary on the returned
+// *testConnManager, and then setting rpcTest.mockConnManager as that
+// *testConnManager.
+func defaultMockConnManager() *testConnManager {
+	testPeer1 := &testPeer{
+		addr:      "127.0.0.210:9108",
+		connected: true,
+		inbound:   true,
+		id:        28,
+	}
+	testPeer2 := &testPeer{
+		addr:      "127.0.0.211:9108",
+		connected: true,
+		inbound:   false,
+		id:        29,
+	}
+	testPeer3 := &testPeer{
+		addr:      "mydomain.org:9108",
+		connected: true,
+		inbound:   false,
+		id:        30,
+	}
+	testPeer4 := &testPeer{
+		addr:      "nonexistentdomain.org:9108",
+		connected: true,
+		inbound:   false,
+		id:        31,
+	}
+	return &testConnManager{
+		connectedCount:   4,
+		netTotalReceived: 9598159,
+		netTotalSent:     4783802,
+		connectedPeers: []rpcserver.Peer{
+			testPeer1,
+			testPeer2,
+			testPeer3,
+			testPeer4,
+		},
+		persistentPeers: []rpcserver.Peer{
+			testPeer1,
+			testPeer2,
+			testPeer3,
+			testPeer4,
+		},
+		addedNodeInfo: []rpcserver.Peer{
+			testPeer1,
+			testPeer2,
+			testPeer3,
+			testPeer4,
+		},
+	}
+}
+
+// defaultMockConfig provides a default rpcserverConfig that is used throughout
+// the tests.  Defaults can be overridden by tests through the rpcTest struct.
+func defaultMockConfig(chainParams *chaincfg.Params) *rpcserverConfig {
+	return &rpcserverConfig{
+		ChainParams:  chainParams,
+		Chain:        defaultMockRPCChain(),
+		AddrManager:  defaultMockAddrManager(),
+		SyncMgr:      defaultMockSyncManager(),
+		ConnMgr:      defaultMockConnManager(),
+		Clock:        &testClock{},
+		TimeSource:   blockchain.NewMedianTime(),
+		Services:     wire.SFNodeNetwork | wire.SFNodeCF,
+		SubsidyCache: standalone.NewSubsidyCache(chainParams),
+	}
+}
 
 func TestHandleAddNode(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleAddNode: ok",
 		handler: handleAddNode,
 		cmd: &types.AddNodeCmd{
-			Addr:   "160.221.215.210:9108",
+			Addr:   "127.0.0.210:9108",
 			SubCmd: "add",
 		},
-		mockConnManager: &testConnManager{},
-		result:          nil,
+		result: nil,
 	}, {
 		name:    "handleAddNode: 'add' subcommand error",
 		handler: handleAddNode,
 		cmd: &types.AddNodeCmd{
-			Addr:   "160.221.215.210:9108",
+			Addr:   "127.0.0.210:9108",
 			SubCmd: "add",
 		},
-		mockConnManager: &testConnManager{
-			connectErr: errors.New("peer already connected"),
-		},
+		mockConnManager: func() *testConnManager {
+			connManager := defaultMockConnManager()
+			connManager.connectErr = errors.New("peer already connected")
+			return connManager
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
 		name:    "handleAddNode: 'remove' subcommand error",
 		handler: handleAddNode,
 		cmd: &types.AddNodeCmd{
-			Addr:   "160.221.215.210:9108",
+			Addr:   "127.0.0.210:9108",
 			SubCmd: "remove",
 		},
-		mockConnManager: &testConnManager{
-			removeByAddrErr: errors.New("peer not found"),
-		},
+		mockConnManager: func() *testConnManager {
+			connManager := defaultMockConnManager()
+			connManager.removeByAddrErr = errors.New("peer not found")
+			return connManager
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
 		name:    "handleAddNode: 'onetry' subcommand error",
 		handler: handleAddNode,
 		cmd: &types.AddNodeCmd{
-			Addr:   "160.221.215.210:9108",
+			Addr:   "127.0.0.210:9108",
 			SubCmd: "onetry",
 		},
-		mockConnManager: &testConnManager{
-			connectErr: errors.New("peer already connected"),
-		},
+		mockConnManager: func() *testConnManager {
+			connManager := defaultMockConnManager()
+			connManager.connectErr = errors.New("peer already connected")
+			return connManager
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
 		name:    "handleAddNode: invalid subcommand",
 		handler: handleAddNode,
 		cmd: &types.AddNodeCmd{
-			Addr:   "160.221.215.210:9108",
+			Addr:   "127.0.0.210:9108",
 			SubCmd: "",
 		},
 		wantErr: true,
@@ -760,6 +1037,8 @@ func TestHandleAddNode(t *testing.T) {
 }
 
 func TestHandleCreateRawSStx(t *testing.T) {
+	t.Parallel()
+
 	defaultCmdInputs := []types.SStxInput{{
 		Txid: "e02f03a25a57afdd402818fe5b13985a0731502ad8a8c93d1874900e84d3330d",
 		Vout: 0,
@@ -1053,6 +1332,8 @@ func TestHandleCreateRawSStx(t *testing.T) {
 }
 
 func TestHandleCreateRawSSRtx(t *testing.T) {
+	t.Parallel()
+
 	defaultCmdInputs := []types.TransactionInput{{
 		Amount: 100,
 		Txid:   "1189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
@@ -1060,15 +1341,6 @@ func TestHandleCreateRawSSRtx(t *testing.T) {
 		Tree:   1,
 	}}
 	defaultFee := dcrjson.Float64(1)
-	defaultMockFetchUtxoEntry := &testRPCUtxoEntry{
-		txType:     stake.TxTypeSStx,
-		height:     100000,
-		index:      0,
-		txVersion:  1,
-		isCoinBase: false,
-		hasExpiry:  true,
-		modified:   false,
-	}
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleCreateRawSSRtx: ok",
 		handler: handleCreateRawSSRtx,
@@ -1076,37 +1348,6 @@ func TestHandleCreateRawSSRtx(t *testing.T) {
 			Inputs: defaultCmdInputs,
 			Fee:    defaultFee,
 		},
-		mockChain: &testRPCChain{
-			fetchUtxoEntry: defaultMockFetchUtxoEntry,
-			convertUtxosToMinimalOutputs: []*stake.MinimalOutput{{
-				PkScript: []byte{
-					0xBA, 0xA9, 0x14, 0x78, 0x02, 0x39, 0xEA, 0x12,
-					0x31, 0xBA, 0x67, 0xB0, 0xC5, 0xB8, 0x2E, 0x78,
-					0x6B, 0x51, 0xE2, 0x10, 0x72, 0x52, 0x21, 0x87,
-				},
-				Value:   100000000,
-				Version: 0,
-			}, {
-				PkScript: []byte{
-					0x6A, 0x1E, 0x35, 0x5C, 0x96, 0xF4, 0x86, 0x12,
-					0xD5, 0x75, 0x09, 0x14, 0x0E, 0x9A, 0x04, 0x99,
-					0x81, 0xD5, 0xF9, 0x97, 0x0F, 0x94,
-					0x5C, 0x77, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, // commitamt
-					0x00, 0x58,
-				},
-				Value:   0,
-				Version: 0,
-			}, {
-				PkScript: []byte{
-					0xBD, 0x76, 0xA9, 0x14, 0x00, 0x00, 0x00, 0x00,
-					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-					0x88, 0xAC,
-				},
-				Value:   0,
-				Version: 0,
-			}},
-		},
 		result: "0100000001395ebc9af44c4a696fa8e6287bdbf0a89a4d6207f191cb0f1eefc25" +
 			"6e6cb89110000000001ffffffff0100e1f5050000000000001abc76a914355c96" +
 			"f48612d57509140e9a049981d5f9970f9488ac00000000000000000100e40b540" +
@@ -1118,9 +1359,9 @@ func TestHandleCreateRawSSRtx(t *testing.T) {
 			Inputs: defaultCmdInputs,
 			Fee:    defaultFee,
 		},
-		mockChain: &testRPCChain{
-			fetchUtxoEntry: defaultMockFetchUtxoEntry,
-			convertUtxosToMinimalOutputs: []*stake.MinimalOutput{{
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.convertUtxosToMinimalOutputs = []*stake.MinimalOutput{{
 				PkScript: []byte{
 					0xBA, 0xA9, 0x14, 0x78, 0x02, 0x39, 0xEA, 0x12,
 					0x31, 0xBA, 0x67, 0xB0, 0xC5, 0xB8, 0x2E, 0x78,
@@ -1147,8 +1388,9 @@ func TestHandleCreateRawSSRtx(t *testing.T) {
 				},
 				Value:   0,
 				Version: 0,
-			}},
-		},
+			}}
+			return chain
+		}(),
 		result: "0100000001395ebc9af44c4a696fa8e6287bdbf0a89a4d6207f191cb0f1eefc25" +
 			"6e6cb89110000000001ffffffff0100e1f50500000000000018bca914355c96f4" +
 			"8612d57509140e9a049981d5f9970f948700000000000000000100e40b5402000" +
@@ -1192,9 +1434,11 @@ func TestHandleCreateRawSSRtx(t *testing.T) {
 			Inputs: defaultCmdInputs,
 			Fee:    defaultFee,
 		},
-		mockChain: &testRPCChain{
-			fetchUtxoEntry: nil,
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.fetchUtxoEntry = nil
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCNoTxInfo,
 	}, {
@@ -1204,8 +1448,9 @@ func TestHandleCreateRawSSRtx(t *testing.T) {
 			Inputs: defaultCmdInputs,
 			Fee:    defaultFee,
 		},
-		mockChain: &testRPCChain{
-			fetchUtxoEntry: &testRPCUtxoEntry{
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.fetchUtxoEntry = &testRPCUtxoEntry{
 				txType:     stake.TxTypeRegular,
 				height:     100000,
 				index:      0,
@@ -1213,8 +1458,9 @@ func TestHandleCreateRawSSRtx(t *testing.T) {
 				isCoinBase: false,
 				hasExpiry:  true,
 				modified:   false,
-			},
-		},
+			}
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCDeserialization,
 	}, {
@@ -1229,9 +1475,6 @@ func TestHandleCreateRawSSRtx(t *testing.T) {
 			}},
 			Fee: defaultFee,
 		},
-		mockChain: &testRPCChain{
-			fetchUtxoEntry: defaultMockFetchUtxoEntry,
-		},
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
@@ -1246,9 +1489,6 @@ func TestHandleCreateRawSSRtx(t *testing.T) {
 			}},
 			Fee: defaultFee,
 		},
-		mockChain: &testRPCChain{
-			fetchUtxoEntry: defaultMockFetchUtxoEntry,
-		},
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
@@ -1258,9 +1498,9 @@ func TestHandleCreateRawSSRtx(t *testing.T) {
 			Inputs: defaultCmdInputs,
 			Fee:    defaultFee,
 		},
-		mockChain: &testRPCChain{
-			fetchUtxoEntry: defaultMockFetchUtxoEntry,
-			convertUtxosToMinimalOutputs: []*stake.MinimalOutput{{
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.convertUtxosToMinimalOutputs = []*stake.MinimalOutput{{
 				PkScript: []byte{
 					0xBA, 0xA9, 0x14, 0x78, 0x02, 0x39, 0xEA, 0x12,
 					0x31, 0xBA, 0x67, 0xB0, 0xC5, 0xB8, 0x2E, 0x78,
@@ -1287,14 +1527,17 @@ func TestHandleCreateRawSSRtx(t *testing.T) {
 				},
 				Value:   0,
 				Version: 0,
-			}},
-		},
+			}}
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}})
 }
 
 func TestHandleCreateRawTransaction(t *testing.T) {
+	t.Parallel()
+
 	defaultCmdInputs := []types.TransactionInput{{
 		Amount: 1,
 		Txid:   "e02f03a25a57afdd402818fe5b13985a0731502ad8a8c93d1874900e84d3330d",
@@ -1417,6 +1660,8 @@ func TestHandleCreateRawTransaction(t *testing.T) {
 }
 
 func TestHandleDebugLevel(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleDebugLevel: show",
 		handler: handleDebugLevel,
@@ -1443,6 +1688,8 @@ func TestHandleDebugLevel(t *testing.T) {
 }
 
 func TestHandleDecodeRawTransaction(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleDecodeRawTransaction: ok",
 		handler: handleDecodeRawTransaction,
@@ -1553,6 +1800,8 @@ func TestHandleDecodeRawTransaction(t *testing.T) {
 }
 
 func TestHandleDecodeScript(t *testing.T) {
+	t.Parallel()
+
 	// This is a pay to stake submission script hash script.
 	p2sstxsh := "ba76a914000000000000000000000000000000000000000088ac"
 	p2sstxshRes := types.DecodeScriptResult{
@@ -1649,18 +1898,19 @@ func TestHandleDecodeScript(t *testing.T) {
 }
 
 func TestHandleEstimateFee(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleEstimateFee: ok",
 		handler: handleEstimateFee,
 		cmd:     &types.EstimateFeeCmd{},
-		mockCfg: &config{
-			minRelayTxFee: dcrutil.Amount(int64(10000)),
-		},
-		result: float64(0.0001),
+		result:  float64(0.0001),
 	}})
 }
 
 func TestHandleExistsExpiredTickets(t *testing.T) {
+	t.Parallel()
+
 	defaultCmdTxHashes := []string{
 		"1189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
 		"2189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
@@ -1671,9 +1921,11 @@ func TestHandleExistsExpiredTickets(t *testing.T) {
 		cmd: &types.ExistsExpiredTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkExpiredTickets: []bool{true, true},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkExpiredTickets = []bool{true, true}
+			return chain
+		}(),
 		result: "03",
 	}, {
 		name:    "handleExistsExpiredTickets: only first ticket exists",
@@ -1681,9 +1933,11 @@ func TestHandleExistsExpiredTickets(t *testing.T) {
 		cmd: &types.ExistsExpiredTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkExpiredTickets: []bool{true, false},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkExpiredTickets = []bool{true, false}
+			return chain
+		}(),
 		result: "01",
 	}, {
 		name:    "handleExistsExpiredTickets: only second ticket exists",
@@ -1691,9 +1945,11 @@ func TestHandleExistsExpiredTickets(t *testing.T) {
 		cmd: &types.ExistsExpiredTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkExpiredTickets: []bool{false, true},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkExpiredTickets = []bool{false, true}
+			return chain
+		}(),
 		result: "02",
 	}, {
 		name:    "handleExistsExpiredTickets: none of the tickets exist",
@@ -1701,9 +1957,11 @@ func TestHandleExistsExpiredTickets(t *testing.T) {
 		cmd: &types.ExistsExpiredTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkExpiredTickets: []bool{false, false},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkExpiredTickets = []bool{false, false}
+			return chain
+		}(),
 		result: "00",
 	}, {
 		name:    "handleExistsExpiredTickets: invalid hash",
@@ -1713,9 +1971,11 @@ func TestHandleExistsExpiredTickets(t *testing.T) {
 				"g189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
 			},
 		},
-		mockChain: &testRPCChain{
-			checkExpiredTickets: []bool{true, true},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkExpiredTickets = []bool{true, true}
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCDecodeHexString,
 	}, {
@@ -1726,24 +1986,30 @@ func TestHandleExistsExpiredTickets(t *testing.T) {
 				"1189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
 			},
 		},
-		mockChain: &testRPCChain{
-			checkExpiredTickets: []bool{true, true},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkExpiredTickets = []bool{true, true}
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}})
 }
 
 func TestHandleExistsLiveTicket(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleExistsLiveTicket: ticket exists",
 		handler: handleExistsLiveTicket,
 		cmd: &types.ExistsLiveTicketCmd{
 			TxHash: "1189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
 		},
-		mockChain: &testRPCChain{
-			checkLiveTicket: true,
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkLiveTicket = true
+			return chain
+		}(),
 		result: true,
 	}, {
 		name:    "handleExistsLiveTicket: ticket does not exist",
@@ -1751,9 +2017,6 @@ func TestHandleExistsLiveTicket(t *testing.T) {
 		cmd: &types.ExistsLiveTicketCmd{
 			TxHash: "1189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
 		},
-		mockChain: &testRPCChain{
-			checkLiveTicket: false,
-		},
 		result: false,
 	}, {
 		name:    "handleExistsLiveTicket: invalid hash",
@@ -1767,6 +2030,8 @@ func TestHandleExistsLiveTicket(t *testing.T) {
 }
 
 func TestHandleExistsLiveTickets(t *testing.T) {
+	t.Parallel()
+
 	defaultCmdTxHashes := []string{
 		"1189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
 		"2189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
@@ -1777,9 +2042,11 @@ func TestHandleExistsLiveTickets(t *testing.T) {
 		cmd: &types.ExistsLiveTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkLiveTickets: []bool{true, true},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkLiveTickets = []bool{true, true}
+			return chain
+		}(),
 		result: "03",
 	}, {
 		name:    "handleExistsLiveTickets: only first ticket exists",
@@ -1787,9 +2054,11 @@ func TestHandleExistsLiveTickets(t *testing.T) {
 		cmd: &types.ExistsLiveTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkLiveTickets: []bool{true, false},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkLiveTickets = []bool{true, false}
+			return chain
+		}(),
 		result: "01",
 	}, {
 		name:    "handleExistsLiveTickets: only second ticket exists",
@@ -1797,9 +2066,11 @@ func TestHandleExistsLiveTickets(t *testing.T) {
 		cmd: &types.ExistsLiveTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkLiveTickets: []bool{false, true},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkLiveTickets = []bool{false, true}
+			return chain
+		}(),
 		result: "02",
 	}, {
 		name:    "handleExistsLiveTickets: none of the tickets exist",
@@ -1807,9 +2078,11 @@ func TestHandleExistsLiveTickets(t *testing.T) {
 		cmd: &types.ExistsLiveTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkLiveTickets: []bool{false, false},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkLiveTickets = []bool{false, false}
+			return chain
+		}(),
 		result: "00",
 	}, {
 		name:    "handleExistsLiveTickets: invalid hash",
@@ -1829,15 +2102,19 @@ func TestHandleExistsLiveTickets(t *testing.T) {
 				"1189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
 			},
 		},
-		mockChain: &testRPCChain{
-			checkLiveTickets: []bool{true, true},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkLiveTickets = []bool{true, true}
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}})
 }
 
 func TestHandleExistsMissedTickets(t *testing.T) {
+	t.Parallel()
+
 	defaultCmdTxHashes := []string{
 		"1189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
 		"2189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
@@ -1848,9 +2125,11 @@ func TestHandleExistsMissedTickets(t *testing.T) {
 		cmd: &types.ExistsMissedTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkMissedTickets: []bool{true, true},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkMissedTickets = []bool{true, true}
+			return chain
+		}(),
 		result: "03",
 	}, {
 		name:    "handleExistsMissedTickets: only first ticket exists",
@@ -1858,9 +2137,11 @@ func TestHandleExistsMissedTickets(t *testing.T) {
 		cmd: &types.ExistsMissedTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkMissedTickets: []bool{true, false},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkMissedTickets = []bool{true, false}
+			return chain
+		}(),
 		result: "01",
 	}, {
 		name:    "handleExistsMissedTickets: only second ticket exists",
@@ -1868,9 +2149,11 @@ func TestHandleExistsMissedTickets(t *testing.T) {
 		cmd: &types.ExistsMissedTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkMissedTickets: []bool{false, true},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkMissedTickets = []bool{false, true}
+			return chain
+		}(),
 		result: "02",
 	}, {
 		name:    "handleExistsMissedTickets: none of the tickets exist",
@@ -1878,9 +2161,11 @@ func TestHandleExistsMissedTickets(t *testing.T) {
 		cmd: &types.ExistsMissedTicketsCmd{
 			TxHashes: defaultCmdTxHashes,
 		},
-		mockChain: &testRPCChain{
-			checkMissedTickets: []bool{false, false},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkMissedTickets = []bool{false, false}
+			return chain
+		}(),
 		result: "00",
 	}, {
 		name:    "handleExistsMissedTickets: invalid hash",
@@ -1900,69 +2185,41 @@ func TestHandleExistsMissedTickets(t *testing.T) {
 				"1189cbe656c2ef1e0fcb91f107624d9aa8f0db7b28e6a86f694a4cf49abc5e39",
 			},
 		},
-		mockChain: &testRPCChain{
-			checkMissedTickets: []bool{true, true},
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.checkMissedTickets = []bool{true, true}
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}})
 }
 
 func TestHandleGetAddedNodeInfo(t *testing.T) {
-	testPeer1 := &testPeer{
-		addr:      "160.221.215.210",
-		connected: true,
-		inbound:   true,
-	}
-	testPeer2 := &testPeer{
-		addr:      "160.221.215.211:9108",
-		connected: true,
-		inbound:   false,
-	}
-	testPeer3 := &testPeer{
-		addr:      "mydomain.org:9108",
-		connected: true,
-		inbound:   false,
-	}
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetAddedNodeInfo: ok without DNS and without address filter",
 		handler: handleGetAddedNodeInfo,
 		cmd: &types.GetAddedNodeInfoCmd{
 			DNS: false,
 		},
-		mockConnManager: &testConnManager{
-			addedNodeInfo: []rpcserver.Peer{
-				testPeer1,
-				testPeer2,
-			},
-		},
-		result: []string{"160.221.215.210", "160.221.215.211:9108"},
+		result: []string{"127.0.0.210:9108", "127.0.0.211:9108",
+			"mydomain.org:9108", "nonexistentdomain.org:9108"},
 	}, {
 		name:    "handleGetAddedNodeInfo: found without DNS and with address filter",
 		handler: handleGetAddedNodeInfo,
 		cmd: &types.GetAddedNodeInfoCmd{
 			DNS:  false,
-			Node: dcrjson.String("160.221.215.211:9108"),
+			Node: dcrjson.String("127.0.0.211:9108"),
 		},
-		mockConnManager: &testConnManager{
-			addedNodeInfo: []rpcserver.Peer{
-				testPeer1,
-				testPeer2,
-			},
-		},
-		result: []string{"160.221.215.211:9108"},
+		result: []string{"127.0.0.211:9108"},
 	}, {
 		name:    "handleGetAddedNodeInfo: node not found",
 		handler: handleGetAddedNodeInfo,
 		cmd: &types.GetAddedNodeInfoCmd{
 			DNS:  false,
-			Node: dcrjson.String("160.221.215.212:9108"),
-		},
-		mockConnManager: &testConnManager{
-			addedNodeInfo: []rpcserver.Peer{
-				testPeer1,
-				testPeer2,
-			},
+			Node: dcrjson.String("127.0.0.212:9108"),
 		},
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInternal.Code,
@@ -1972,34 +2229,34 @@ func TestHandleGetAddedNodeInfo(t *testing.T) {
 		cmd: &types.GetAddedNodeInfoCmd{
 			DNS: true,
 		},
-		mockCfg: &config{
-			lookup: func(host string) ([]net.IP, error) {
-				if host == "mydomain.org" {
-					return []net.IP{net.ParseIP("160.221.215.211")}, nil
-				}
-				return nil, errors.New("host not found")
-			},
-		},
-		mockConnManager: &testConnManager{
-			addedNodeInfo: []rpcserver.Peer{
-				testPeer1,
-				testPeer3,
-			},
-		},
 		result: []*types.GetAddedNodeInfoResult{{
-			AddedNode: "160.221.215.210",
+			AddedNode: "127.0.0.210:9108",
 			Connected: dcrjson.Bool(true),
 			Addresses: &[]types.GetAddedNodeInfoResultAddr{{
-				Address:   "160.221.215.210",
+				Address:   "127.0.0.210",
 				Connected: "inbound",
 			}},
+		}, {
+			AddedNode: "127.0.0.211:9108",
+			Connected: dcrjson.Bool(true),
+			Addresses: &[]types.GetAddedNodeInfoResultAddr{{
+				Address:   "127.0.0.211",
+				Connected: "outbound",
+			}},
 		}, {
 			AddedNode: "mydomain.org:9108",
 			Connected: dcrjson.Bool(true),
 			Addresses: &[]types.GetAddedNodeInfoResultAddr{{
-				Address:   "160.221.215.211",
+				Address:   "127.0.0.211",
 				Connected: "false",
 			}},
+		}, {
+			AddedNode: "nonexistentdomain.org:9108",
+			Connected: dcrjson.Bool(true),
+			Addresses: &[]types.GetAddedNodeInfoResultAddr{{
+				Address:   "nonexistentdomain.org",
+				Connected: "outbound",
+			}},
 		}},
 	}, {
 		name:    "handleGetAddedNodeInfo: found with DNS and with address filter",
@@ -2008,164 +2265,68 @@ func TestHandleGetAddedNodeInfo(t *testing.T) {
 			DNS:  true,
 			Node: dcrjson.String("mydomain.org:9108"),
 		},
-		mockCfg: &config{
-			lookup: func(host string) ([]net.IP, error) {
-				if host == "mydomain.org" {
-					return []net.IP{net.ParseIP("160.221.215.211")}, nil
-				}
-				return nil, errors.New("host not found")
-			},
-		},
-		mockConnManager: &testConnManager{
-			addedNodeInfo: []rpcserver.Peer{
-				testPeer1,
-				testPeer3,
-			},
-		},
 		result: []*types.GetAddedNodeInfoResult{{
 			AddedNode: "mydomain.org:9108",
 			Connected: dcrjson.Bool(true),
 			Addresses: &[]types.GetAddedNodeInfoResultAddr{{
-				Address:   "160.221.215.211",
+				Address:   "127.0.0.211",
 				Connected: "false",
 			}},
 		}},
-	}, {
-		name:    "handleGetAddedNodeInfo: ok with DNS lookup failed",
-		handler: handleGetAddedNodeInfo,
-		cmd: &types.GetAddedNodeInfoCmd{
-			DNS: true,
-		},
-		mockCfg: &config{
-			lookup: func(host string) ([]net.IP, error) {
-				return nil, errors.New("host not found")
-			},
-		},
-		mockConnManager: &testConnManager{
-			addedNodeInfo: []rpcserver.Peer{
-				testPeer1,
-				testPeer3,
-			},
-		},
-		result: []*types.GetAddedNodeInfoResult{{
-			AddedNode: "160.221.215.210",
-			Connected: dcrjson.Bool(true),
-			Addresses: &[]types.GetAddedNodeInfoResultAddr{{
-				Address:   "160.221.215.210",
-				Connected: "inbound",
-			}},
-		}, {
-			AddedNode: "mydomain.org:9108",
-			Connected: dcrjson.Bool(true),
-			Addresses: &[]types.GetAddedNodeInfoResultAddr{{
-				Address:   "mydomain.org",
-				Connected: "outbound",
-			}},
-		}},
 	}})
 }
 
 func TestHandleGetBestBlock(t *testing.T) {
-	hash := mustParseHash("000000000000000019e76d2f52f39f9245db35eab21741a61ed5bded310f0c87")
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetBestBlock: ok",
 		handler: handleGetBestBlock,
 		cmd:     &types.GetBestBlockCmd{},
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
-				Hash:   *hash,
-				Height: 451802,
-			},
-		},
 		result: &types.GetBestBlockResult{
-			Hash:   "000000000000000019e76d2f52f39f9245db35eab21741a61ed5bded310f0c87",
-			Height: 451802,
+			Hash:   block432100.BlockHash().String(),
+			Height: int64(block432100.Header.Height),
 		},
 	}})
 }
 
 func TestHandleGetBestBlockHash(t *testing.T) {
-	hash := mustParseHash("000000000000000019e76d2f52f39f9245db35eab21741a61ed5bded310f0c87")
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetBestBlockHash: ok",
 		handler: handleGetBestBlockHash,
 		cmd:     &types.GetBestBlockHashCmd{},
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
-				Hash: *hash,
-			},
-		},
-		result: "000000000000000019e76d2f52f39f9245db35eab21741a61ed5bded310f0c87",
+		result:  block432100.BlockHash().String(),
 	}})
 }
 
 func TestHandleGetBlockchainInfo(t *testing.T) {
+	t.Parallel()
+
 	hash := mustParseHash("00000000000000001e6ec1501c858506de1de4703d1be8bab4061126e8f61480")
 	prevHash := mustParseHash("00000000000000001a1ec2becd0dd90bfbd0c65f42fdaf608dd9ceac2a3aee1d")
 	genesisHash := mustParseHash("298e5cc3d985bfe7f81dc135f360abe089edd4396b86d2de66b0cef42b21d980")
 	genesisPrevHash := mustParseHash("0000000000000000000000000000000000000000000000000000000000000000")
-
-	// Explicitly define the params that handleGetBlockchainInfo depends on so that
-	// the tests don't break when the values for these change.
-	testChainParams := cloneParams(chaincfg.MainNetParams())
-	testChainParams.Name = "mainnet"
-	testChainParams.Deployments = map[uint32][]chaincfg.ConsensusDeployment{
-		7: {{
-			Vote: chaincfg.Vote{
-				Id:          chaincfg.VoteIDHeaderCommitments,
-				Description: "Enable header commitments as defined in DCP0005",
-				Mask:        0x0006, // Bits 1 and 2
-				Choices: []chaincfg.Choice{{
-					Id:          "abstain",
-					Description: "abstain voting for change",
-					Bits:        0x0000,
-					IsAbstain:   true,
-					IsNo:        false,
-				}, {
-					Id:          "no",
-					Description: "keep the existing consensus rules",
-					Bits:        0x0002, // Bit 1
-					IsAbstain:   false,
-					IsNo:        true,
-				}, {
-					Id:          "yes",
-					Description: "change to the new consensus rules",
-					Bits:        0x0004, // Bit 2
-					IsAbstain:   false,
-					IsNo:        false,
-				}},
-			},
-			StartTime:  1567641600, // Sep 5th, 2019
-			ExpireTime: 1599264000, // Sep 5th, 2020
-		}},
-	}
-	testChainParams.PowLimitBits = 0x1d00ffff
-
 	testRPCServerHandler(t, []rpcTest{{
-		name:            "handleGetBlockchainInfo: ok",
-		handler:         handleGetBlockchainInfo,
-		cmd:             &types.GetBlockChainInfoCmd{},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
+		name:    "handleGetBlockchainInfo: ok",
+		handler: handleGetBlockchainInfo,
+		cmd:     &types.GetBlockChainInfoCmd{},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.bestSnapshot = &blockchain.BestState{
 				Height:   463073,
 				Bits:     404696953,
 				Hash:     *hash,
 				PrevHash: *prevHash,
-			},
-			chainWork: big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
-				0x90, 0x90, 0xb0, 0x02, 0x65, 0x06}),
-			isCurrent:    false,
-			maxBlockSize: 393216,
-			nextThresholdState: blockchain.ThresholdStateTuple{
-				State:  blockchain.ThresholdStarted,
-				Choice: uint32(0xffffffff),
-			},
-			stateLastChangedHeight: int64(149248),
-		},
-		mockSyncManager: &testSyncManager{
-			syncHeight: 463074,
-		},
+			}
+			chain.chainWork = big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
+				0x90, 0x90, 0xb0, 0x02, 0x65, 0x06})
+			chain.isCurrent = false
+			chain.maxBlockSize = 393216
+			chain.stateLastChangedHeight = int64(149248)
+			return chain
+		}(),
 		result: types.GetBlockChainInfoResult{
 			Chain:                "mainnet",
 			Blocks:               int64(463073),
@@ -2188,30 +2349,33 @@ func TestHandleGetBlockchainInfo(t *testing.T) {
 			},
 		},
 	}, {
-		name:            "handleGetBlockchainInfo: ok with empty blockchain",
-		handler:         handleGetBlockchainInfo,
-		cmd:             &types.GetBlockChainInfoCmd{},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
+		name:    "handleGetBlockchainInfo: ok with empty blockchain",
+		handler: handleGetBlockchainInfo,
+		cmd:     &types.GetBlockChainInfoCmd{},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.bestSnapshot = &blockchain.BestState{
 				Height:   0,
 				Bits:     453115903,
 				Hash:     *genesisHash,
 				PrevHash: *genesisPrevHash,
-			},
-			chainWork: big.NewInt(0).SetBytes([]byte{0x80, 0x00, 0x40, 0x00, 0x20,
-				0x00}),
-			isCurrent:    false,
-			maxBlockSize: 393216,
-			nextThresholdState: blockchain.ThresholdStateTuple{
+			}
+			chain.chainWork = big.NewInt(0).SetBytes([]byte{0x80, 0x00, 0x40, 0x00, 0x20,
+				0x00})
+			chain.isCurrent = false
+			chain.maxBlockSize = 393216
+			chain.nextThresholdState = blockchain.ThresholdStateTuple{
 				State:  blockchain.ThresholdDefined,
 				Choice: uint32(0xffffffff),
-			},
-			stateLastChangedHeight: int64(0),
-		},
-		mockSyncManager: &testSyncManager{
-			syncHeight: 0,
-		},
+			}
+			chain.stateLastChangedHeight = int64(0)
+			return chain
+		}(),
+		mockSyncManager: func() *testSyncManager {
+			syncManager := defaultMockSyncManager()
+			syncManager.syncHeight = 0
+			return syncManager
+		}(),
 		result: types.GetBlockChainInfoResult{
 			Chain:                "mainnet",
 			Blocks:               int64(0),
@@ -2234,88 +2398,82 @@ func TestHandleGetBlockchainInfo(t *testing.T) {
 			},
 		},
 	}, {
-		name:            "handleGetBlockchainInfo: could not fetch chain work",
-		handler:         handleGetBlockchainInfo,
-		cmd:             &types.GetBlockChainInfoCmd{},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
+		name:    "handleGetBlockchainInfo: could not fetch chain work",
+		handler: handleGetBlockchainInfo,
+		cmd:     &types.GetBlockChainInfoCmd{},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.bestSnapshot = &blockchain.BestState{
 				Hash: *hash,
-			},
-			chainWorkErr: errors.New("could not fetch chain work"),
-		},
+			}
+			chain.chainWorkErr = errors.New("could not fetch chain work")
+			chain.stateLastChangedHeight = int64(149248)
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInternal.Code,
 	}, {
-		name:            "handleGetBlockchainInfo: could not fetch max block size",
-		handler:         handleGetBlockchainInfo,
-		cmd:             &types.GetBlockChainInfoCmd{},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
+		name:    "handleGetBlockchainInfo: could not fetch max block size",
+		handler: handleGetBlockchainInfo,
+		cmd:     &types.GetBlockChainInfoCmd{},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.bestSnapshot = &blockchain.BestState{
 				Hash: *hash,
-			},
-			chainWork: big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
-				0x90, 0x90, 0xb0, 0x02, 0x65, 0x06}),
-			maxBlockSizeErr: errors.New("could not fetch max block size"),
-		},
-		mockSyncManager: &testSyncManager{
-			syncHeight: 463074,
-		},
+			}
+			chain.chainWork = big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
+				0x90, 0x90, 0xb0, 0x02, 0x65, 0x06})
+			chain.maxBlockSizeErr = errors.New("could not fetch max block size")
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInternal.Code,
 	}, {
-		name:            "handleGetBlockchainInfo: could not fetch threshold state",
-		handler:         handleGetBlockchainInfo,
-		cmd:             &types.GetBlockChainInfoCmd{},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
+		name:    "handleGetBlockchainInfo: could not fetch threshold state",
+		handler: handleGetBlockchainInfo,
+		cmd:     &types.GetBlockChainInfoCmd{},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.bestSnapshot = &blockchain.BestState{
 				Height:   463073,
 				Bits:     404696953,
 				Hash:     *hash,
 				PrevHash: *prevHash,
-			},
-			chainWork: big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
-				0x90, 0x90, 0xb0, 0x02, 0x65, 0x06}),
-			maxBlockSize:          393216,
-			nextThresholdStateErr: errors.New("could not fetch threshold state"),
-		},
-		mockSyncManager: &testSyncManager{
-			syncHeight: 463074,
-		},
+			}
+			chain.chainWork = big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
+				0x90, 0x90, 0xb0, 0x02, 0x65, 0x06})
+			chain.maxBlockSize = 393216
+			chain.nextThresholdStateErr = errors.New("could not fetch threshold state")
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInternal.Code,
 	}, {
-		name:            "handleGetBlockchainInfo: could not fetch state last changed",
-		handler:         handleGetBlockchainInfo,
-		cmd:             &types.GetBlockChainInfoCmd{},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
+		name:    "handleGetBlockchainInfo: could not fetch state last changed",
+		handler: handleGetBlockchainInfo,
+		cmd:     &types.GetBlockChainInfoCmd{},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.bestSnapshot = &blockchain.BestState{
 				Height:   463073,
 				Bits:     404696953,
 				Hash:     *hash,
 				PrevHash: *prevHash,
-			},
-			chainWork: big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
-				0x90, 0x90, 0xb0, 0x02, 0x65, 0x06}),
-			maxBlockSize: 393216,
-			nextThresholdState: blockchain.ThresholdStateTuple{
-				State:  blockchain.ThresholdStarted,
-				Choice: uint32(0xffffffff),
-			},
-			stateLastChangedHeightErr: errors.New("could not fetch state last changed"),
-		},
-		mockSyncManager: &testSyncManager{
-			syncHeight: 463074,
-		},
+			}
+			chain.chainWork = big.NewInt(0).SetBytes([]byte{0x11, 0x5d, 0x28, 0x33, 0x84,
+				0x90, 0x90, 0xb0, 0x02, 0x65, 0x06})
+			chain.maxBlockSize = 393216
+			chain.stateLastChangedHeightErr = errors.New("could not fetch state last changed")
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInternal.Code,
 	}})
 }
 
 func TestHandleGetBlock(t *testing.T) {
+	t.Parallel()
+
 	// Define variables related to block432100 to be used throughout the
 	// handleGetBlock tests.
 	blkHeader := block432100.Header
@@ -2332,17 +2490,12 @@ func TestHandleGetBlock(t *testing.T) {
 	nextHash := mustParseHash("000000000000000002e63055e402c823cb86c8258806508d84d6dc2a0790bd49")
 	chainWork, _ := new(big.Int).SetString("0e805fb85284503581c57c", 16)
 
-	// Explicitly define the params that handleGetBlock depends on so that the
-	// tests don't break when the values for these change.
-	testChainParams := cloneParams(chaincfg.MainNetParams())
-	testChainParams.PowLimitBits = 0x1d00ffff
-
 	// Create raw transaction results. This uses createTxRawResult, so ideally
 	// createTxRawResult should be tested independently as well.
 	txns := blk.Transactions()
 	rawTxns := make([]types.TxRawResult, len(txns))
 	for i, tx := range txns {
-		rawTxn, err := createTxRawResult(testChainParams, tx.MsgTx(),
+		rawTxn, err := createTxRawResult(defaultChainParams, tx.MsgTx(),
 			tx.Hash().String(), uint32(i), &blkHeader, blk.Hash().String(),
 			int64(blkHeader.Height), confirmations)
 		if err != nil {
@@ -2353,7 +2506,7 @@ func TestHandleGetBlock(t *testing.T) {
 	stxns := blk.STransactions()
 	rawSTxns := make([]types.TxRawResult, len(stxns))
 	for i, tx := range stxns {
-		rawSTxn, err := createTxRawResult(testChainParams, tx.MsgTx(),
+		rawSTxn, err := createTxRawResult(defaultChainParams, tx.MsgTx(),
 			tx.Hash().String(), uint32(i), &blkHeader, blk.Hash().String(),
 			int64(blkHeader.Height), confirmations)
 		if err != nil {
@@ -2370,10 +2523,6 @@ func TestHandleGetBlock(t *testing.T) {
 			Verbose:   dcrjson.Bool(false),
 			VerboseTx: dcrjson.Bool(false),
 		},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			blockByHash: blk,
-		},
 		result: blkHexString,
 	}, {
 		name:    "handleGetBlock: ok verbose",
@@ -2383,16 +2532,15 @@ func TestHandleGetBlock(t *testing.T) {
 			Verbose:   dcrjson.Bool(true),
 			VerboseTx: dcrjson.Bool(false),
 		},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.bestSnapshot = &blockchain.BestState{
 				Height: bestHeight,
-			},
-			blockByHash:       blk,
-			blockHashByHeight: nextHash,
-			chainWork:         chainWork,
-			mainChainHasBlock: true,
-		},
+			}
+			chain.blockByHash = blk
+			chain.blockHashByHeight = nextHash
+			return chain
+		}(),
 		result: types.GetBlockVerboseResult{
 			Hash:          blkHashString,
 			Version:       blkHeader.Version,
@@ -2437,16 +2585,15 @@ func TestHandleGetBlock(t *testing.T) {
 			Verbose:   dcrjson.Bool(true),
 			VerboseTx: dcrjson.Bool(true),
 		},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.bestSnapshot = &blockchain.BestState{
 				Height: bestHeight,
-			},
-			blockByHash:       blk,
-			blockHashByHeight: nextHash,
-			chainWork:         chainWork,
-			mainChainHasBlock: true,
-		},
+			}
+			chain.blockByHash = blk
+			chain.blockHashByHeight = nextHash
+			return chain
+		}(),
 		result: types.GetBlockVerboseResult{
 			Hash:          blkHashString,
 			Version:       blkHeader.Version,
@@ -2482,9 +2629,8 @@ func TestHandleGetBlock(t *testing.T) {
 			Verbose:   dcrjson.Bool(false),
 			VerboseTx: dcrjson.Bool(false),
 		},
-		mockChainParams: testChainParams,
-		wantErr:         true,
-		errCode:         dcrjson.ErrRPCDecodeHexString,
+		wantErr: true,
+		errCode: dcrjson.ErrRPCDecodeHexString,
 	}, {
 		name:    "handleGetBlock: block not found",
 		handler: handleGetBlock,
@@ -2493,10 +2639,11 @@ func TestHandleGetBlock(t *testing.T) {
 			Verbose:   dcrjson.Bool(false),
 			VerboseTx: dcrjson.Bool(false),
 		},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			blockByHashErr: errors.New("block not found"),
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.blockByHashErr = errors.New("block not found")
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCBlockNotFound,
 	}, {
@@ -2507,11 +2654,11 @@ func TestHandleGetBlock(t *testing.T) {
 			Verbose:   dcrjson.Bool(true),
 			VerboseTx: dcrjson.Bool(false),
 		},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			blockByHash:  blk,
-			chainWorkErr: errors.New("could not fetch chain work"),
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.chainWorkErr = errors.New("could not fetch chain work")
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInternal.Code,
 	}, {
@@ -2522,64 +2669,59 @@ func TestHandleGetBlock(t *testing.T) {
 			Verbose:   dcrjson.Bool(true),
 			VerboseTx: dcrjson.Bool(false),
 		},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.bestSnapshot = &blockchain.BestState{
 				Height: bestHeight,
-			},
-			blockByHash:          blk,
-			blockHashByHeightErr: errors.New("no next block"),
-			chainWork:            chainWork,
-			mainChainHasBlock:    true,
-		},
+			}
+			chain.blockHashByHeightErr = errors.New("no next block")
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInternal.Code,
 	}})
 }
 
 func TestHandleGetBlockCount(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetBlockCount: ok",
 		handler: handleGetBlockCount,
 		cmd:     &types.GetBlockCountCmd{},
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
-				Height: 451802,
-			},
-		},
-		result: int64(451802),
+		result:  int64(block432100.Header.Height),
 	}})
 }
 
 func TestHandleGetBlockHash(t *testing.T) {
-	blk := dcrutil.NewBlock(&block432100)
-	blkHash := blk.Hash()
-	blkHashString := blkHash.String()
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetBlockHash: ok",
 		handler: handleGetBlockHash,
 		cmd: &types.GetBlockHashCmd{
-			Index: blk.Height(),
-		},
-		mockChain: &testRPCChain{
-			blockHashByHeight: blkHash,
+			Index: int64(block432100.Header.Height),
 		},
-		result: blkHashString,
+		result: block432100.BlockHash().String(),
 	}, {
 		name:    "handleGetBlockHash: block number out of range",
 		handler: handleGetBlockHash,
 		cmd: &types.GetBlockHashCmd{
 			Index: -1,
 		},
-		mockChain: &testRPCChain{
-			blockHashByHeightErr: errors.New("block number out of range"),
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.blockHashByHeightErr = errors.New("block number out of range")
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCOutOfRange,
 	}})
 }
 
 func TestHandleGetBlockHeader(t *testing.T) {
+	t.Parallel()
+
 	// Define variables related to block432100 to be used throughout the
 	// handleGetBlockHeader tests.
 	blkHeader := block432100.Header
@@ -2596,11 +2738,6 @@ func TestHandleGetBlockHeader(t *testing.T) {
 	nextHash := mustParseHash("000000000000000002e63055e402c823cb86c8258806508d84d6dc2a0790bd49")
 	chainWork, _ := new(big.Int).SetString("0e805fb85284503581c57c", 16)
 
-	// Explicitly define the params that handleGetBlockHeader depends on so that
-	// the tests don't break when the values for these change.
-	testChainParams := cloneParams(chaincfg.MainNetParams())
-	testChainParams.PowLimitBits = 0x1d00ffff
-
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetBlockHeader: ok",
 		handler: handleGetBlockHeader,
@@ -2608,10 +2745,6 @@ func TestHandleGetBlockHeader(t *testing.T) {
 			Hash:    blkHashString,
 			Verbose: dcrjson.Bool(false),
 		},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			headerByHash: blkHeader,
-		},
 		result: blkHeaderHexString,
 	}, {
 		name:    "handleGetBlockHeader: ok verbose",
@@ -2620,16 +2753,14 @@ func TestHandleGetBlockHeader(t *testing.T) {
 			Hash:    blkHashString,
 			Verbose: dcrjson.Bool(true),
 		},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.bestSnapshot = &blockchain.BestState{
 				Height: bestHeight,
-			},
-			blockHashByHeight: nextHash,
-			chainWork:         chainWork,
-			headerByHash:      blkHeader,
-			mainChainHasBlock: true,
-		},
+			}
+			chain.blockHashByHeight = nextHash
+			return chain
+		}(),
 		result: types.GetBlockHeaderVerboseResult{
 			Hash:          blkHashString,
 			Confirmations: confirmations,
@@ -2662,9 +2793,8 @@ func TestHandleGetBlockHeader(t *testing.T) {
 			Hash:    "invalid",
 			Verbose: dcrjson.Bool(false),
 		},
-		mockChainParams: testChainParams,
-		wantErr:         true,
-		errCode:         dcrjson.ErrRPCDecodeHexString,
+		wantErr: true,
+		errCode: dcrjson.ErrRPCDecodeHexString,
 	}, {
 		name:    "handleGetBlockHeader: block not found",
 		handler: handleGetBlockHeader,
@@ -2672,10 +2802,11 @@ func TestHandleGetBlockHeader(t *testing.T) {
 			Hash:    blkHashString,
 			Verbose: dcrjson.Bool(false),
 		},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			headerByHashErr: errors.New("block not found"),
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.headerByHashErr = errors.New("block not found")
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCBlockNotFound,
 	}, {
@@ -2685,11 +2816,11 @@ func TestHandleGetBlockHeader(t *testing.T) {
 			Hash:    blkHashString,
 			Verbose: dcrjson.Bool(true),
 		},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			chainWorkErr: errors.New("could not fetch chain work"),
-			headerByHash: blkHeader,
-		},
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.chainWorkErr = errors.New("could not fetch chain work")
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInternal.Code,
 	}, {
@@ -2699,22 +2830,22 @@ func TestHandleGetBlockHeader(t *testing.T) {
 			Hash:    blkHashString,
 			Verbose: dcrjson.Bool(true),
 		},
-		mockChainParams: testChainParams,
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
+		mockChain: func() *testRPCChain {
+			chain := defaultMockRPCChain()
+			chain.bestSnapshot = &blockchain.BestState{
 				Height: bestHeight,
-			},
-			blockHashByHeightErr: errors.New("no next block"),
-			chainWork:            chainWork,
-			headerByHash:         blkHeader,
-			mainChainHasBlock:    true,
-		},
+			}
+			chain.blockHashByHeightErr = errors.New("no next block")
+			return chain
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInternal.Code,
 	}})
 }
 
 func TestHandleGetBlockSubsidy(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetBlockSubsidy: ok",
 		handler: handleGetBlockSubsidy,
@@ -2732,77 +2863,46 @@ func TestHandleGetBlockSubsidy(t *testing.T) {
 }
 
 func TestHandleGetChainTips(t *testing.T) {
-	h1 := mustParseHash("000000000000000002e4e275720a511cc4c6e881ac7aa94f6786e496d0901e5c")
-	h2 := mustParseHash("00000000000000000cc40fe6f2fe9a0c482281d79f1b49c3c77b976859edd963")
-	h3 := mustParseHash("00000000000000000afa4a9c11c4106aac0c73f595182227e78688218f3516f1")
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetChainTips: ok",
 		handler: handleGetChainTips,
 		cmd:     &types.GetChainTipsCmd{},
-		mockChain: &testRPCChain{
-			chainTips: []blockchain.ChainTipInfo{{
-				Height:    453336,
-				Hash:      *h1,
-				BranchLen: 0,
-				Status:    "active",
-			}, {
-				Height:    450576,
-				Hash:      *h2,
-				BranchLen: 1,
-				Status:    "valid-headers",
-			}, {
-				Height:    449982,
-				Hash:      *h3,
-				BranchLen: 1,
-				Status:    "valid-headers",
-			}},
-		},
 		result: []types.GetChainTipsResult{{
-			Height:    453336,
-			Hash:      "000000000000000002e4e275720a511cc4c6e881ac7aa94f6786e496d0901e5c",
-			BranchLen: 0,
+			Height:    int64(block432100.Header.Height),
+			Hash:      block432100.BlockHash().String(),
+			BranchLen: 500,
 			Status:    "active",
-		}, {
-			Height:    450576,
-			Hash:      "00000000000000000cc40fe6f2fe9a0c482281d79f1b49c3c77b976859edd963",
-			BranchLen: 1,
-			Status:    "valid-headers",
-		}, {
-			Height:    449982,
-			Hash:      "00000000000000000afa4a9c11c4106aac0c73f595182227e78688218f3516f1",
-			BranchLen: 1,
-			Status:    "valid-headers",
 		}},
 	}})
 }
 
 func TestHandleGetCoinSupply(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetCoinSupply: ok",
 		handler: handleGetCoinSupply,
 		cmd:     &types.GetCoinSupplyCmd{},
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
-				TotalSubsidy: 1152286647709751,
-			},
-		},
-		result: int64(1152286647709751),
+		result:  int64(1122503888072909),
 	}})
 }
 
 func TestHandleGetConnectionCount(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetConnectionCount: ok",
 		handler: handleGetConnectionCount,
 		cmd:     &types.GetConnectionCountCmd{},
-		mockConnManager: &testConnManager{
-			connectedCount: 7,
-		},
-		result: int32(7),
+		result:  int32(4),
 	}})
 }
 
 func TestHandleGetCurrentNet(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetCurrentNet: ok",
 		handler: handleGetCurrentNet,
@@ -2812,35 +2912,21 @@ func TestHandleGetCurrentNet(t *testing.T) {
 }
 
 func TestHandleGetInfo(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetInfo: ok",
 		handler: handleGetInfo,
 		cmd:     &types.GetInfoCmd{},
-		mockConnManager: &testConnManager{
-			connectedCount: 7,
-		},
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
-				Bits:   493007795,
-				Height: 449708,
-			},
-		},
-		mockCfg: &config{
-			AddrIndex:     false,
-			Proxy:         "",
-			TestNet:       false,
-			TxIndex:       false,
-			minRelayTxFee: dcrutil.Amount(int64(10000)),
-		},
 		result: &types.InfoChainResult{
 			Version: int32(1000000*version.Major + 10000*version.Minor +
 				100*version.Patch),
 			ProtocolVersion: int32(maxProtocolVersion),
-			Blocks:          int64(449708),
+			Blocks:          int64(block432100.Header.Height),
 			TimeOffset:      int64(0),
-			Connections:     int32(7),
+			Connections:     int32(4),
 			Proxy:           "",
-			Difficulty:      float64(0.01013136),
+			Difficulty:      float64(28147398026.656624),
 			TestNet:         false,
 			RelayFee:        float64(0.0001),
 			AddrIndex:       false,
@@ -2850,14 +2936,12 @@ func TestHandleGetInfo(t *testing.T) {
 }
 
 func TestHandleGetNetTotals(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetNetTotals: ok",
 		handler: handleGetNetTotals,
 		cmd:     &types.GetNetTotalsCmd{},
-		mockConnManager: &testConnManager{
-			netTotalReceived: uint64(9598159),
-			netTotalSent:     uint64(4783802),
-		},
 		mockClock: &testClock{
 			now: time.Unix(1592931302, 0),
 		},
@@ -2870,51 +2954,19 @@ func TestHandleGetNetTotals(t *testing.T) {
 }
 
 func TestHandleGetNetworkInfo(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetNetworkInfo: ok",
 		handler: handleGetNetworkInfo,
 		cmd:     &types.GetNetworkInfoCmd{},
-		mockAddrManager: &testAddrManager{
-			localAddresses: []addrmgr.LocalAddr{{
-				Address: "45.56.142.184",
-				Port:    uint16(19108),
-				Score:   int32(0),
-			}},
-		},
-		mockConnManager: &testConnManager{
-			connectedCount: 7,
-		},
-		mockCfg: &config{
-			minRelayTxFee: dcrutil.Amount(int64(10000)),
-			ipv4NetInfo: types.NetworksResult{
-				Name:                      "IPV4",
-				Limited:                   false,
-				Reachable:                 true,
-				Proxy:                     "",
-				ProxyRandomizeCredentials: false,
-			},
-			ipv6NetInfo: types.NetworksResult{
-				Name:                      "IPV6",
-				Limited:                   false,
-				Reachable:                 true,
-				Proxy:                     "",
-				ProxyRandomizeCredentials: false,
-			},
-			onionNetInfo: types.NetworksResult{
-				Name:                      "Onion",
-				Limited:                   false,
-				Reachable:                 false,
-				Proxy:                     "",
-				ProxyRandomizeCredentials: false,
-			},
-		},
 		result: types.GetNetworkInfoResult{
 			Version: int32(1000000*version.Major + 10000*version.Minor +
 				100*version.Patch),
 			SubVersion:      userAgentVersion,
 			ProtocolVersion: int32(maxProtocolVersion),
 			TimeOffset:      int64(0),
-			Connections:     int32(7),
+			Connections:     int32(4),
 			Networks: []types.NetworksResult{{
 				Name:                      "IPV4",
 				Limited:                   false,
@@ -2936,7 +2988,7 @@ func TestHandleGetNetworkInfo(t *testing.T) {
 			}},
 			RelayFee: float64(0.0001),
 			LocalAddresses: []types.LocalAddressesResult{{
-				Address: "45.56.142.184",
+				Address: "127.0.0.184",
 				Port:    uint16(19108),
 				Score:   int32(0),
 			}},
@@ -2946,13 +2998,15 @@ func TestHandleGetNetworkInfo(t *testing.T) {
 }
 
 func TestHandleGetPeerInfo(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
-		name:            "handleGetPeerInfo: ok",
-		handler:         handleGetPeerInfo,
-		cmd:             &types.GetPeerInfoCmd{},
-		mockSyncManager: &testSyncManager{},
-		mockConnManager: &testConnManager{
-			connectedPeers: []rpcserver.Peer{
+		name:    "handleGetPeerInfo: ok",
+		handler: handleGetPeerInfo,
+		cmd:     &types.GetPeerInfoCmd{},
+		mockConnManager: func() *testConnManager {
+			connManager := defaultMockConnManager()
+			connManager.connectedPeers = []rpcserver.Peer{
 				&testPeer{
 					localAddr: testAddr{
 						net:  "tcp",
@@ -2983,8 +3037,9 @@ func TestHandleGetPeerInfo(t *testing.T) {
 						LastPingMicros: int64(0),
 					},
 				},
-			},
-		},
+			}
+			return connManager
+		}(),
 		mockClock: &testClock{
 			since: time.Duration(2000),
 		},
@@ -3014,28 +3069,15 @@ func TestHandleGetPeerInfo(t *testing.T) {
 }
 
 func TestHandleGetTxOutSetInfo(t *testing.T) {
-	hash := mustParseHash("000000000000000019e76d2f52f39f9245db35eab21741a61ed5bded310f0c87")
-	sHash := mustParseHash("fe7b32aa188800f07268b17f3bead5f3d8a1b6d18654182066436efce6effa86")
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleGetTxOutSetInfo: ok",
 		handler: handleGetTxOutSetInfo,
 		cmd:     &types.GetTxOutSetInfoCmd{},
-		mockChain: &testRPCChain{
-			bestSnapshot: &blockchain.BestState{
-				Hash:   *hash,
-				Height: 451802,
-			},
-			fetchUtxoStats: &blockchain.UtxoStats{
-				Utxos:          1593879,
-				Transactions:   689819,
-				Size:           36441617,
-				Total:          1154067750680149,
-				SerializedHash: *sHash,
-			},
-		},
 		result: types.GetTxOutSetInfoResult{
-			Height:         451802,
-			BestBlock:      "000000000000000019e76d2f52f39f9245db35eab21741a61ed5bded310f0c87",
+			Height:         int64(block432100.Header.Height),
+			BestBlock:      block432100.BlockHash().String(),
 			Transactions:   689819,
 			TxOuts:         1593879,
 			SerializedHash: "fe7b32aa188800f07268b17f3bead5f3d8a1b6d18654182066436efce6effa86",
@@ -3046,25 +3088,28 @@ func TestHandleGetTxOutSetInfo(t *testing.T) {
 }
 
 func TestHandleNode(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
 		name:    "handleNode: ok with disconnect by address",
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd: "disconnect",
-			Target: "160.221.215.210:9108",
+			Target: "127.0.0.210:9108",
 		},
-		mockConnManager: &testConnManager{},
-		result:          nil,
+		result: nil,
 	}, {
 		name:    "handleNode: disconnect by address peer not found",
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd: "disconnect",
-			Target: "160.221.215.210:9108",
-		},
-		mockConnManager: &testConnManager{
-			disconnectByAddrErr: errors.New("peer not found"),
+			Target: "127.0.0.299:9108",
 		},
+		mockConnManager: func() *testConnManager {
+			connManager := defaultMockConnManager()
+			connManager.disconnectByAddrErr = errors.New("peer not found")
+			return connManager
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
@@ -3074,18 +3119,19 @@ func TestHandleNode(t *testing.T) {
 			SubCmd: "disconnect",
 			Target: "28",
 		},
-		mockConnManager: &testConnManager{},
-		result:          nil,
+		result: nil,
 	}, {
 		name:    "handleNode: disconnect by id peer not found",
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd: "disconnect",
-			Target: "28",
-		},
-		mockConnManager: &testConnManager{
-			disconnectByIDErr: errors.New("peer not found"),
+			Target: "99",
 		},
+		mockConnManager: func() *testConnManager {
+			connManager := defaultMockConnManager()
+			connManager.disconnectByIDErr = errors.New("peer not found")
+			return connManager
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
@@ -3095,25 +3141,20 @@ func TestHandleNode(t *testing.T) {
 			SubCmd: "disconnect",
 			Target: "invalid_address",
 		},
-		mockConnManager: &testConnManager{},
-		wantErr:         true,
-		errCode:         dcrjson.ErrRPCInvalidParameter,
+		wantErr: true,
+		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
 		name:    "handleNode: can't disconnect a permanent peer",
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd: "disconnect",
-			Target: "160.221.215.210:9108",
-		},
-		mockConnManager: &testConnManager{
-			disconnectByAddrErr: errors.New("peer not found"),
-			connectedPeers: []rpcserver.Peer{
-				&testPeer{
-					id:   28,
-					addr: "160.221.215.210:9108",
-				},
-			},
+			Target: "127.0.0.210:9108",
 		},
+		mockConnManager: func() *testConnManager {
+			connManager := defaultMockConnManager()
+			connManager.disconnectByAddrErr = errors.New("peer not found")
+			return connManager
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCMisc,
 	}, {
@@ -3121,20 +3162,21 @@ func TestHandleNode(t *testing.T) {
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd: "remove",
-			Target: "160.221.215.210:9108",
+			Target: "127.0.0.210:9108",
 		},
-		mockConnManager: &testConnManager{},
-		result:          nil,
+		result: nil,
 	}, {
 		name:    "handleNode: remove by address peer not found",
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd: "remove",
-			Target: "160.221.215.210:9108",
-		},
-		mockConnManager: &testConnManager{
-			removeByAddrErr: errors.New("peer not found"),
+			Target: "127.0.0.299:9108",
 		},
+		mockConnManager: func() *testConnManager {
+			connManager := defaultMockConnManager()
+			connManager.removeByAddrErr = errors.New("peer not found")
+			return connManager
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
@@ -3144,18 +3186,19 @@ func TestHandleNode(t *testing.T) {
 			SubCmd: "remove",
 			Target: "28",
 		},
-		mockConnManager: &testConnManager{},
-		result:          nil,
+		result: nil,
 	}, {
 		name:    "handleNode: remove by id peer not found",
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd: "remove",
-			Target: "28",
-		},
-		mockConnManager: &testConnManager{
-			removeByIDErr: errors.New("peer not found"),
+			Target: "99",
 		},
+		mockConnManager: func() *testConnManager {
+			connManager := defaultMockConnManager()
+			connManager.removeByIDErr = errors.New("peer not found")
+			return connManager
+		}(),
 		wantErr: true,
 		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
@@ -3165,25 +3208,21 @@ func TestHandleNode(t *testing.T) {
 			SubCmd: "remove",
 			Target: "invalid_address",
 		},
-		mockConnManager: &testConnManager{},
-		wantErr:         true,
-		errCode:         dcrjson.ErrRPCInvalidParameter,
+		wantErr: true,
+		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
 		name:    "handleNode: can't remove a temporary peer",
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd: "remove",
-			Target: "160.221.215.210:9108",
-		},
-		mockConnManager: &testConnManager{
-			removeByAddrErr: errors.New("peer not found"),
-			connectedPeers: []rpcserver.Peer{
-				&testPeer{
-					id:   28,
-					addr: "160.221.215.210:9108",
-				},
-			},
+			Target: "127.0.0.210:9108",
 		},
+		mockConnManager: func() *testConnManager {
+			connManager := defaultMockConnManager()
+			connManager.removeByAddrErr = errors.New("peer not found")
+			return connManager
+		}(),
+
 		wantErr: true,
 		errCode: dcrjson.ErrRPCMisc,
 	}, {
@@ -3191,56 +3230,55 @@ func TestHandleNode(t *testing.T) {
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd:        "connect",
-			Target:        "160.221.215.210:9108",
+			Target:        "127.0.0.210:9108",
 			ConnectSubCmd: dcrjson.String("perm"),
 		},
-		mockConnManager: &testConnManager{},
-		result:          nil,
+		result: nil,
 	}, {
 		name:    "handleNode: ok with connect temp",
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd:        "connect",
-			Target:        "160.221.215.210:9108",
+			Target:        "127.0.0.210:9108",
 			ConnectSubCmd: dcrjson.String("temp"),
 		},
-		mockConnManager: &testConnManager{},
-		result:          nil,
+		result: nil,
 	}, {
 		name:    "handleNode: invalid connect sub cmd",
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd:        "connect",
-			Target:        "160.221.215.210:9108",
+			Target:        "127.0.0.210:9108",
 			ConnectSubCmd: dcrjson.String("invalid"),
 		},
-		mockConnManager: &testConnManager{},
-		wantErr:         true,
-		errCode:         dcrjson.ErrRPCInvalidParameter,
+		wantErr: true,
+		errCode: dcrjson.ErrRPCInvalidParameter,
 	}, {
 		name:    "handleNode: invalid sub cmd",
 		handler: handleNode,
 		cmd: &types.NodeCmd{
 			SubCmd: "invalid",
-			Target: "160.221.215.210:9108",
+			Target: "127.0.0.210:9108",
 		},
-		mockConnManager: &testConnManager{},
-		wantErr:         true,
-		errCode:         dcrjson.ErrRPCInvalidParameter,
+		wantErr: true,
+		errCode: dcrjson.ErrRPCInvalidParameter,
 	}})
 }
 
 func TestHandlePing(t *testing.T) {
+	t.Parallel()
+
 	testRPCServerHandler(t, []rpcTest{{
-		name:            "handlePing: ok",
-		handler:         handlePing,
-		cmd:             &types.PingCmd{},
-		mockConnManager: &testConnManager{},
-		result:          nil,
+		name:    "handlePing: ok",
+		handler: handlePing,
+		cmd:     &types.PingCmd{},
+		result:  nil,
 	}})
 }
 
 func TestHandleSubmitBlock(t *testing.T) {
+	t.Parallel()
+
 	blk := dcrutil.NewBlock(&block432100)
 	blkBytes, err := blk.Bytes()
 	if err != nil {
@@ -3253,9 +3291,6 @@ func TestHandleSubmitBlock(t *testing.T) {
 		cmd: &types.SubmitBlockCmd{
 			HexBlock: blkHexString,
 		},
-		mockSyncManager: &testSyncManager{
-			submitBlock: true,
-		},
 		result: nil,
 	}, {
 		name:    "handleSubmitBlock: ok with odd length hex",
@@ -3263,9 +3298,6 @@ func TestHandleSubmitBlock(t *testing.T) {
 		cmd: &types.SubmitBlockCmd{
 			HexBlock: blkHexString[1:],
 		},
-		mockSyncManager: &testSyncManager{
-			submitBlock: true,
-		},
 		result: nil,
 	}, {
 		name:    "handleSubmitBlock: invalid hex",
@@ -3289,9 +3321,11 @@ func TestHandleSubmitBlock(t *testing.T) {
 		cmd: &types.SubmitBlockCmd{
 			HexBlock: blkHexString,
 		},
-		mockSyncManager: &testSyncManager{
-			submitBlockErr: errors.New("block rejected"),
-		},
+		mockSyncManager: func() *testSyncManager {
+			syncManager := defaultMockSyncManager()
+			syncManager.submitBlockErr = errors.New("block rejected")
+			return syncManager
+		}(),
 		result: "rejected: block rejected",
 	}})
 }
@@ -3299,58 +3333,57 @@ func TestHandleSubmitBlock(t *testing.T) {
 func testRPCServerHandler(t *testing.T, tests []rpcTest) {
 	t.Helper()
 
-	for _, test := range tests {
-		cfg = defaultCfg
-		if test.mockCfg != nil {
-			cfg = test.mockCfg
-		}
+	setCfgOnce.Do(func() {
+		cfg = defaultCfg()
+	})
 
-		// Create a default rpcserverConfig and override any configurations that are
-		// provided by the test.
-		rpcserverConfig := rpcserverConfig{
-			ChainParams:  defaultChainParams,
-			Chain:        defaultRPCChain,
-			AddrManager:  defaultAddrManager,
-			SyncMgr:      defaultSyncManager,
-			ConnMgr:      defaultConnManager,
-			Clock:        defaultClock,
-			TimeSource:   blockchain.NewMedianTime(),
-			Services:     wire.SFNodeNetwork | wire.SFNodeCF,
-			SubsidyCache: standalone.NewSubsidyCache(defaultChainParams),
-		}
-		if test.mockChainParams != nil {
-			rpcserverConfig.ChainParams = test.mockChainParams
-		}
-		if test.mockChain != nil {
-			rpcserverConfig.Chain = test.mockChain
-		}
-		if test.mockAddrManager != nil {
-			rpcserverConfig.AddrManager = test.mockAddrManager
-		}
-		if test.mockSyncManager != nil {
-			rpcserverConfig.SyncMgr = test.mockSyncManager
-		}
-		if test.mockConnManager != nil {
-			rpcserverConfig.ConnMgr = test.mockConnManager
-		}
-		if test.mockClock != nil {
-			rpcserverConfig.Clock = test.mockClock
-		}
+	for _, test := range tests {
+		test := test // capture range variable
+		t.Run(test.name, func(t *testing.T) {
+			t.Parallel()
+
+			// Create a default rpcserverConfig and override any configurations that are
+			// provided by the test.
+			chainParams := defaultChainParams
+			if test.mockChainParams != nil {
+				chainParams = test.mockChainParams
+			}
+			rpcserverConfig := defaultMockConfig(chainParams)
+			if test.mockChain != nil {
+				rpcserverConfig.Chain = test.mockChain
+			}
+			if test.mockAddrManager != nil {
+				rpcserverConfig.AddrManager = test.mockAddrManager
+			}
+			if test.mockSyncManager != nil {
+				rpcserverConfig.SyncMgr = test.mockSyncManager
+			}
+			if test.mockConnManager != nil {
+				rpcserverConfig.ConnMgr = test.mockConnManager
+			}
+			if test.mockClock != nil {
+				rpcserverConfig.Clock = test.mockClock
+			}
 
-		testServer := &rpcServer{cfg: rpcserverConfig}
-		result, err := test.handler(nil, testServer, test.cmd)
-		if test.wantErr {
-			var rpcErr *dcrjson.RPCError
-			if !errors.As(err, &rpcErr) || rpcErr.Code != test.errCode {
-				t.Errorf("%s\nwant: %+v\n got: %+v\n", test.name, test.errCode, rpcErr.Code)
+			testServer := &rpcServer{cfg: *rpcserverConfig}
+			result, err := test.handler(nil, testServer, test.cmd)
+			if test.wantErr {
+				var rpcErr *dcrjson.RPCError
+				if !errors.As(err, &rpcErr) || rpcErr.Code != test.errCode {
+					if rpcErr != nil {
+						t.Errorf("%s\nwant: %+v\n got: %+v\n", test.name, test.errCode, rpcErr.Code)
+					} else {
+						t.Errorf("%s\nwant: %+v\n got: nil\n", test.name, test.errCode)
+					}
+				}
+				return
 			}
-			continue
-		}
-		if err != nil {
-			t.Errorf("%s\nunexpected error: %+v\n", test.name, err)
-		}
-		if !reflect.DeepEqual(result, test.result) {
-			t.Errorf("%s\nwant: %+v\n got: %+v\n", test.name, test.result, result)
-		}
+			if err != nil {
+				t.Errorf("%s\nunexpected error: %+v\n", test.name, err)
+			}
+			if !reflect.DeepEqual(result, test.result) {
+				t.Errorf("%s\nwant: %+v\n got: %+v\n", test.name, test.result, result)
+			}
+		})
 	}
 }