github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/rpcwebsocket.go (about)

     1  // Copyright (c) 2013-2016 The btcsuite developers
     2  // Copyright (c) 2016 The Dash developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package main
     7  
     8  import (
     9  	"bytes"
    10  	"container/list"
    11  	"crypto/subtle"
    12  	"encoding/base64"
    13  	"encoding/hex"
    14  	"encoding/json"
    15  	"errors"
    16  	"fmt"
    17  	"io"
    18  	"math"
    19  	"sync"
    20  	"time"
    21  
    22  	"github.com/btcsuite/fastsha256"
    23  	"github.com/btcsuite/golangcrypto/ripemd160"
    24  	"github.com/btcsuite/websocket"
    25  	"github.com/dashpay/godash/blockchain"
    26  	"github.com/dashpay/godash/btcjson"
    27  	"github.com/dashpay/godash/database"
    28  	"github.com/dashpay/godash/txscript"
    29  	"github.com/dashpay/godash/wire"
    30  	"github.com/dashpay/godashutil"
    31  )
    32  
    33  const (
    34  	// websocketSendBufferSize is the number of elements the send channel
    35  	// can queue before blocking.  Note that this only applies to requests
    36  	// handled directly in the websocket client input handler or the async
    37  	// handler since notifications have their own queuing mechanism
    38  	// independent of the send channel buffer.
    39  	websocketSendBufferSize = 50
    40  )
    41  
    42  // timeZeroVal is simply the zero value for a time.Time and is used to avoid
    43  // creating multiple instances.
    44  var timeZeroVal time.Time
    45  
    46  // wsCommandHandler describes a callback function used to handle a specific
    47  // command.
    48  type wsCommandHandler func(*wsClient, interface{}) (interface{}, error)
    49  
    50  // wsHandlers maps RPC command strings to appropriate websocket handler
    51  // functions.  This is set by init because help references wsHandlers and thus
    52  // causes a dependency loop.
    53  var wsHandlers map[string]wsCommandHandler
    54  var wsHandlersBeforeInit = map[string]wsCommandHandler{
    55  	"help":                      handleWebsocketHelp,
    56  	"notifyblocks":              handleNotifyBlocks,
    57  	"notifynewtransactions":     handleNotifyNewTransactions,
    58  	"notifyreceived":            handleNotifyReceived,
    59  	"notifyspent":               handleNotifySpent,
    60  	"session":                   handleSession,
    61  	"stopnotifyblocks":          handleStopNotifyBlocks,
    62  	"stopnotifynewtransactions": handleStopNotifyNewTransactions,
    63  	"stopnotifyspent":           handleStopNotifySpent,
    64  	"stopnotifyreceived":        handleStopNotifyReceived,
    65  	"rescan":                    handleRescan,
    66  }
    67  
    68  // wsAsyncHandlers holds the websocket commands which should be run
    69  // asynchronously to the main input handler goroutine.  This allows long-running
    70  // operations to run concurrently (and one at a time) while still responding
    71  // to the majority of normal requests which can be answered quickly.
    72  var wsAsyncHandlers = map[string]struct{}{
    73  	"rescan": {},
    74  }
    75  
    76  // WebsocketHandler handles a new websocket client by creating a new wsClient,
    77  // starting it, and blocking until the connection closes.  Since it blocks, it
    78  // must be run in a separate goroutine.  It should be invoked from the websocket
    79  // server handler which runs each new connection in a new goroutine thereby
    80  // satisfying the requirement.
    81  func (s *rpcServer) WebsocketHandler(conn *websocket.Conn, remoteAddr string,
    82  	authenticated bool, isAdmin bool) {
    83  
    84  	// Clear the read deadline that was set before the websocket hijacked
    85  	// the connection.
    86  	conn.SetReadDeadline(timeZeroVal)
    87  
    88  	// Limit max number of websocket clients.
    89  	rpcsLog.Infof("New websocket client %s", remoteAddr)
    90  	if s.ntfnMgr.NumClients()+1 > cfg.RPCMaxWebsockets {
    91  		rpcsLog.Infof("Max websocket clients exceeded [%d] - "+
    92  			"disconnecting client %s", cfg.RPCMaxWebsockets,
    93  			remoteAddr)
    94  		conn.Close()
    95  		return
    96  	}
    97  
    98  	// Create a new websocket client to handle the new websocket connection
    99  	// and wait for it to shutdown.  Once it has shutdown (and hence
   100  	// disconnected), remove it and any notifications it registered for.
   101  	client, err := newWebsocketClient(s, conn, remoteAddr, authenticated, isAdmin)
   102  	if err != nil {
   103  		rpcsLog.Errorf("Failed to serve client %s: %v", remoteAddr, err)
   104  		conn.Close()
   105  		return
   106  	}
   107  	s.ntfnMgr.AddClient(client)
   108  	client.Start()
   109  	client.WaitForShutdown()
   110  	s.ntfnMgr.RemoveClient(client)
   111  	rpcsLog.Infof("Disconnected websocket client %s", remoteAddr)
   112  }
   113  
   114  // wsNotificationManager is a connection and notification manager used for
   115  // websockets.  It allows websocket clients to register for notifications they
   116  // are interested in.  When an event happens elsewhere in the code such as
   117  // transactions being added to the memory pool or block connects/disconnects,
   118  // the notification manager is provided with the relevant details needed to
   119  // figure out which websocket clients need to be notified based on what they
   120  // have registered for and notifies them accordingly.  It is also used to keep
   121  // track of all connected websocket clients.
   122  type wsNotificationManager struct {
   123  	// server is the RPC server the notification manager is associated with.
   124  	server *rpcServer
   125  
   126  	// queueNotification queues a notification for handling.
   127  	queueNotification chan interface{}
   128  
   129  	// notificationMsgs feeds notificationHandler with notifications
   130  	// and client (un)registeration requests from a queue as well as
   131  	// registeration and unregisteration requests from clients.
   132  	notificationMsgs chan interface{}
   133  
   134  	// Access channel for current number of connected clients.
   135  	numClients chan int
   136  
   137  	// Shutdown handling
   138  	wg   sync.WaitGroup
   139  	quit chan struct{}
   140  }
   141  
   142  // queueHandler manages a queue of empty interfaces, reading from in and
   143  // sending the oldest unsent to out.  This handler stops when either of the
   144  // in or quit channels are closed, and closes out before returning, without
   145  // waiting to send any variables still remaining in the queue.
   146  func queueHandler(in <-chan interface{}, out chan<- interface{}, quit <-chan struct{}) {
   147  	var q []interface{}
   148  	var dequeue chan<- interface{}
   149  	skipQueue := out
   150  	var next interface{}
   151  out:
   152  	for {
   153  		select {
   154  		case n, ok := <-in:
   155  			if !ok {
   156  				// Sender closed input channel.
   157  				break out
   158  			}
   159  
   160  			// Either send to out immediately if skipQueue is
   161  			// non-nil (queue is empty) and reader is ready,
   162  			// or append to the queue and send later.
   163  			select {
   164  			case skipQueue <- n:
   165  			default:
   166  				q = append(q, n)
   167  				dequeue = out
   168  				skipQueue = nil
   169  				next = q[0]
   170  			}
   171  
   172  		case dequeue <- next:
   173  			copy(q, q[1:])
   174  			q[len(q)-1] = nil // avoid leak
   175  			q = q[:len(q)-1]
   176  			if len(q) == 0 {
   177  				dequeue = nil
   178  				skipQueue = out
   179  			} else {
   180  				next = q[0]
   181  			}
   182  
   183  		case <-quit:
   184  			break out
   185  		}
   186  	}
   187  	close(out)
   188  }
   189  
   190  // queueHandler maintains a queue of notifications and notification handler
   191  // control messages.
   192  func (m *wsNotificationManager) queueHandler() {
   193  	queueHandler(m.queueNotification, m.notificationMsgs, m.quit)
   194  	m.wg.Done()
   195  }
   196  
   197  // NotifyBlockConnected passes a block newly-connected to the best chain
   198  // to the notification manager for block and transaction notification
   199  // processing.
   200  func (m *wsNotificationManager) NotifyBlockConnected(block *godashutil.Block) {
   201  	// As NotifyBlockConnected will be called by the block manager
   202  	// and the RPC server may no longer be running, use a select
   203  	// statement to unblock enqueuing the notification once the RPC
   204  	// server has begun shutting down.
   205  	select {
   206  	case m.queueNotification <- (*notificationBlockConnected)(block):
   207  	case <-m.quit:
   208  	}
   209  }
   210  
   211  // NotifyBlockDisconnected passes a block disconnected from the best chain
   212  // to the notification manager for block notification processing.
   213  func (m *wsNotificationManager) NotifyBlockDisconnected(block *godashutil.Block) {
   214  	// As NotifyBlockDisconnected will be called by the block manager
   215  	// and the RPC server may no longer be running, use a select
   216  	// statement to unblock enqueuing the notification once the RPC
   217  	// server has begun shutting down.
   218  	select {
   219  	case m.queueNotification <- (*notificationBlockDisconnected)(block):
   220  	case <-m.quit:
   221  	}
   222  }
   223  
   224  // NotifyMempoolTx passes a transaction accepted by mempool to the
   225  // notification manager for transaction notification processing.  If
   226  // isNew is true, the tx is is a new transaction, rather than one
   227  // added to the mempool during a reorg.
   228  func (m *wsNotificationManager) NotifyMempoolTx(tx *godashutil.Tx, isNew bool) {
   229  	n := &notificationTxAcceptedByMempool{
   230  		isNew: isNew,
   231  		tx:    tx,
   232  	}
   233  
   234  	// As NotifyMempoolTx will be called by mempool and the RPC server
   235  	// may no longer be running, use a select statement to unblock
   236  	// enqueuing the notification once the RPC server has begun
   237  	// shutting down.
   238  	select {
   239  	case m.queueNotification <- n:
   240  	case <-m.quit:
   241  	}
   242  }
   243  
   244  // Notification types
   245  type notificationBlockConnected godashutil.Block
   246  type notificationBlockDisconnected godashutil.Block
   247  type notificationTxAcceptedByMempool struct {
   248  	isNew bool
   249  	tx    *godashutil.Tx
   250  }
   251  
   252  // Notification control requests
   253  type notificationRegisterClient wsClient
   254  type notificationUnregisterClient wsClient
   255  type notificationRegisterBlocks wsClient
   256  type notificationUnregisterBlocks wsClient
   257  type notificationRegisterNewMempoolTxs wsClient
   258  type notificationUnregisterNewMempoolTxs wsClient
   259  type notificationRegisterSpent struct {
   260  	wsc *wsClient
   261  	ops []*wire.OutPoint
   262  }
   263  type notificationUnregisterSpent struct {
   264  	wsc *wsClient
   265  	op  *wire.OutPoint
   266  }
   267  type notificationRegisterAddr struct {
   268  	wsc   *wsClient
   269  	addrs []string
   270  }
   271  type notificationUnregisterAddr struct {
   272  	wsc  *wsClient
   273  	addr string
   274  }
   275  
   276  // notificationHandler reads notifications and control messages from the queue
   277  // handler and processes one at a time.
   278  func (m *wsNotificationManager) notificationHandler() {
   279  	// clients is a map of all currently connected websocket clients.
   280  	clients := make(map[chan struct{}]*wsClient)
   281  
   282  	// Maps used to hold lists of websocket clients to be notified on
   283  	// certain events.  Each websocket client also keeps maps for the events
   284  	// which have multiple triggers to make removal from these lists on
   285  	// connection close less horrendously expensive.
   286  	//
   287  	// Where possible, the quit channel is used as the unique id for a client
   288  	// since it is quite a bit more efficient than using the entire struct.
   289  	blockNotifications := make(map[chan struct{}]*wsClient)
   290  	txNotifications := make(map[chan struct{}]*wsClient)
   291  	watchedOutPoints := make(map[wire.OutPoint]map[chan struct{}]*wsClient)
   292  	watchedAddrs := make(map[string]map[chan struct{}]*wsClient)
   293  
   294  out:
   295  	for {
   296  		select {
   297  		case n, ok := <-m.notificationMsgs:
   298  			if !ok {
   299  				// queueHandler quit.
   300  				break out
   301  			}
   302  			switch n := n.(type) {
   303  			case *notificationBlockConnected:
   304  				block := (*godashutil.Block)(n)
   305  
   306  				// Skip iterating through all txs if no
   307  				// tx notification requests exist.
   308  				if len(watchedOutPoints) != 0 || len(watchedAddrs) != 0 {
   309  					for _, tx := range block.Transactions() {
   310  						m.notifyForTx(watchedOutPoints,
   311  							watchedAddrs, tx, block)
   312  					}
   313  				}
   314  
   315  				if len(blockNotifications) != 0 {
   316  					m.notifyBlockConnected(blockNotifications,
   317  						block)
   318  				}
   319  
   320  			case *notificationBlockDisconnected:
   321  				m.notifyBlockDisconnected(blockNotifications,
   322  					(*godashutil.Block)(n))
   323  
   324  			case *notificationTxAcceptedByMempool:
   325  				if n.isNew && len(txNotifications) != 0 {
   326  					m.notifyForNewTx(txNotifications, n.tx)
   327  				}
   328  				m.notifyForTx(watchedOutPoints, watchedAddrs, n.tx, nil)
   329  
   330  			case *notificationRegisterBlocks:
   331  				wsc := (*wsClient)(n)
   332  				blockNotifications[wsc.quit] = wsc
   333  
   334  			case *notificationUnregisterBlocks:
   335  				wsc := (*wsClient)(n)
   336  				delete(blockNotifications, wsc.quit)
   337  
   338  			case *notificationRegisterClient:
   339  				wsc := (*wsClient)(n)
   340  				clients[wsc.quit] = wsc
   341  
   342  			case *notificationUnregisterClient:
   343  				wsc := (*wsClient)(n)
   344  				// Remove any requests made by the client as well as
   345  				// the client itself.
   346  				delete(blockNotifications, wsc.quit)
   347  				delete(txNotifications, wsc.quit)
   348  				for k := range wsc.spentRequests {
   349  					op := k
   350  					m.removeSpentRequest(watchedOutPoints, wsc, &op)
   351  				}
   352  				for addr := range wsc.addrRequests {
   353  					m.removeAddrRequest(watchedAddrs, wsc, addr)
   354  				}
   355  				delete(clients, wsc.quit)
   356  
   357  			case *notificationRegisterSpent:
   358  				m.addSpentRequests(watchedOutPoints, n.wsc, n.ops)
   359  
   360  			case *notificationUnregisterSpent:
   361  				m.removeSpentRequest(watchedOutPoints, n.wsc, n.op)
   362  
   363  			case *notificationRegisterAddr:
   364  				m.addAddrRequests(watchedAddrs, n.wsc, n.addrs)
   365  
   366  			case *notificationUnregisterAddr:
   367  				m.removeAddrRequest(watchedAddrs, n.wsc, n.addr)
   368  
   369  			case *notificationRegisterNewMempoolTxs:
   370  				wsc := (*wsClient)(n)
   371  				txNotifications[wsc.quit] = wsc
   372  
   373  			case *notificationUnregisterNewMempoolTxs:
   374  				wsc := (*wsClient)(n)
   375  				delete(txNotifications, wsc.quit)
   376  
   377  			default:
   378  				rpcsLog.Warn("Unhandled notification type")
   379  			}
   380  
   381  		case m.numClients <- len(clients):
   382  
   383  		case <-m.quit:
   384  			// RPC server shutting down.
   385  			break out
   386  		}
   387  	}
   388  
   389  	for _, c := range clients {
   390  		c.Disconnect()
   391  	}
   392  	m.wg.Done()
   393  }
   394  
   395  // NumClients returns the number of clients actively being served.
   396  func (m *wsNotificationManager) NumClients() (n int) {
   397  	select {
   398  	case n = <-m.numClients:
   399  	case <-m.quit: // Use default n (0) if server has shut down.
   400  	}
   401  	return
   402  }
   403  
   404  // RegisterBlockUpdates requests block update notifications to the passed
   405  // websocket client.
   406  func (m *wsNotificationManager) RegisterBlockUpdates(wsc *wsClient) {
   407  	m.queueNotification <- (*notificationRegisterBlocks)(wsc)
   408  }
   409  
   410  // UnregisterBlockUpdates removes block update notifications for the passed
   411  // websocket client.
   412  func (m *wsNotificationManager) UnregisterBlockUpdates(wsc *wsClient) {
   413  	m.queueNotification <- (*notificationUnregisterBlocks)(wsc)
   414  }
   415  
   416  // notifyBlockConnected notifies websocket clients that have registered for
   417  // block updates when a block is connected to the main chain.
   418  func (*wsNotificationManager) notifyBlockConnected(clients map[chan struct{}]*wsClient,
   419  	block *godashutil.Block) {
   420  
   421  	// Notify interested websocket clients about the connected block.
   422  	ntfn := btcjson.NewBlockConnectedNtfn(block.Sha().String(),
   423  		int32(block.Height()), block.MsgBlock().Header.Timestamp.Unix())
   424  	marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn)
   425  	if err != nil {
   426  		rpcsLog.Error("Failed to marshal block connected notification: "+
   427  			"%v", err)
   428  		return
   429  	}
   430  	for _, wsc := range clients {
   431  		wsc.QueueNotification(marshalledJSON)
   432  	}
   433  }
   434  
   435  // notifyBlockDisconnected notifies websocket clients that have registered for
   436  // block updates when a block is disconnected from the main chain (due to a
   437  // reorganize).
   438  func (*wsNotificationManager) notifyBlockDisconnected(clients map[chan struct{}]*wsClient, block *godashutil.Block) {
   439  	// Skip notification creation if no clients have requested block
   440  	// connected/disconnected notifications.
   441  	if len(clients) == 0 {
   442  		return
   443  	}
   444  
   445  	// Notify interested websocket clients about the disconnected block.
   446  	ntfn := btcjson.NewBlockDisconnectedNtfn(block.Sha().String(),
   447  		int32(block.Height()), block.MsgBlock().Header.Timestamp.Unix())
   448  	marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn)
   449  	if err != nil {
   450  		rpcsLog.Error("Failed to marshal block disconnected "+
   451  			"notification: %v", err)
   452  		return
   453  	}
   454  	for _, wsc := range clients {
   455  		wsc.QueueNotification(marshalledJSON)
   456  	}
   457  }
   458  
   459  // RegisterNewMempoolTxsUpdates requests notifications to the passed websocket
   460  // client when new transactions are added to the memory pool.
   461  func (m *wsNotificationManager) RegisterNewMempoolTxsUpdates(wsc *wsClient) {
   462  	m.queueNotification <- (*notificationRegisterNewMempoolTxs)(wsc)
   463  }
   464  
   465  // UnregisterNewMempoolTxsUpdates removes notifications to the passed websocket
   466  // client when new transaction are added to the memory pool.
   467  func (m *wsNotificationManager) UnregisterNewMempoolTxsUpdates(wsc *wsClient) {
   468  	m.queueNotification <- (*notificationUnregisterNewMempoolTxs)(wsc)
   469  }
   470  
   471  // notifyForNewTx notifies websocket clients that have registered for updates
   472  // when a new transaction is added to the memory pool.
   473  func (m *wsNotificationManager) notifyForNewTx(clients map[chan struct{}]*wsClient, tx *godashutil.Tx) {
   474  	txShaStr := tx.Sha().String()
   475  	mtx := tx.MsgTx()
   476  
   477  	var amount int64
   478  	for _, txOut := range mtx.TxOut {
   479  		amount += txOut.Value
   480  	}
   481  
   482  	ntfn := btcjson.NewTxAcceptedNtfn(txShaStr, godashutil.Amount(amount).ToBTC())
   483  	marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn)
   484  	if err != nil {
   485  		rpcsLog.Errorf("Failed to marshal tx notification: %s", err.Error())
   486  		return
   487  	}
   488  
   489  	var verboseNtfn *btcjson.TxAcceptedVerboseNtfn
   490  	var marshalledJSONVerbose []byte
   491  	for _, wsc := range clients {
   492  		if wsc.verboseTxUpdates {
   493  			if marshalledJSONVerbose != nil {
   494  				wsc.QueueNotification(marshalledJSONVerbose)
   495  				continue
   496  			}
   497  
   498  			net := m.server.server.chainParams
   499  			rawTx, err := createTxRawResult(net, mtx, txShaStr, nil,
   500  				"", 0, 0)
   501  			if err != nil {
   502  				return
   503  			}
   504  
   505  			verboseNtfn = btcjson.NewTxAcceptedVerboseNtfn(*rawTx)
   506  			marshalledJSONVerbose, err = btcjson.MarshalCmd(nil,
   507  				verboseNtfn)
   508  			if err != nil {
   509  				rpcsLog.Errorf("Failed to marshal verbose tx "+
   510  					"notification: %s", err.Error())
   511  				return
   512  			}
   513  			wsc.QueueNotification(marshalledJSONVerbose)
   514  		} else {
   515  			wsc.QueueNotification(marshalledJSON)
   516  		}
   517  	}
   518  }
   519  
   520  // RegisterSpentRequests requests a notification when each of the passed
   521  // outpoints is confirmed spent (contained in a block connected to the main
   522  // chain) for the passed websocket client.  The request is automatically
   523  // removed once the notification has been sent.
   524  func (m *wsNotificationManager) RegisterSpentRequests(wsc *wsClient, ops []*wire.OutPoint) {
   525  	m.queueNotification <- &notificationRegisterSpent{
   526  		wsc: wsc,
   527  		ops: ops,
   528  	}
   529  }
   530  
   531  // addSpentRequests modifies a map of watched outpoints to sets of websocket
   532  // clients to add a new request watch all of the outpoints in ops and create
   533  // and send a notification when spent to the websocket client wsc.
   534  func (*wsNotificationManager) addSpentRequests(opMap map[wire.OutPoint]map[chan struct{}]*wsClient,
   535  	wsc *wsClient, ops []*wire.OutPoint) {
   536  
   537  	for _, op := range ops {
   538  		// Track the request in the client as well so it can be quickly
   539  		// be removed on disconnect.
   540  		wsc.spentRequests[*op] = struct{}{}
   541  
   542  		// Add the client to the list to notify when the outpoint is seen.
   543  		// Create the list as needed.
   544  		cmap, ok := opMap[*op]
   545  		if !ok {
   546  			cmap = make(map[chan struct{}]*wsClient)
   547  			opMap[*op] = cmap
   548  		}
   549  		cmap[wsc.quit] = wsc
   550  	}
   551  }
   552  
   553  // UnregisterSpentRequest removes a request from the passed websocket client
   554  // to be notified when the passed outpoint is confirmed spent (contained in a
   555  // block connected to the main chain).
   556  func (m *wsNotificationManager) UnregisterSpentRequest(wsc *wsClient, op *wire.OutPoint) {
   557  	m.queueNotification <- &notificationUnregisterSpent{
   558  		wsc: wsc,
   559  		op:  op,
   560  	}
   561  }
   562  
   563  // removeSpentRequest modifies a map of watched outpoints to remove the
   564  // websocket client wsc from the set of clients to be notified when a
   565  // watched outpoint is spent.  If wsc is the last client, the outpoint
   566  // key is removed from the map.
   567  func (*wsNotificationManager) removeSpentRequest(ops map[wire.OutPoint]map[chan struct{}]*wsClient,
   568  	wsc *wsClient, op *wire.OutPoint) {
   569  
   570  	// Remove the request tracking from the client.
   571  	delete(wsc.spentRequests, *op)
   572  
   573  	// Remove the client from the list to notify.
   574  	notifyMap, ok := ops[*op]
   575  	if !ok {
   576  		rpcsLog.Warnf("Attempt to remove nonexistent spent request "+
   577  			"for websocket client %s", wsc.addr)
   578  		return
   579  	}
   580  	delete(notifyMap, wsc.quit)
   581  
   582  	// Remove the map entry altogether if there are
   583  	// no more clients interested in it.
   584  	if len(notifyMap) == 0 {
   585  		delete(ops, *op)
   586  	}
   587  }
   588  
   589  // txHexString returns the serialized transaction encoded in hexadecimal.
   590  func txHexString(tx *godashutil.Tx) string {
   591  	buf := bytes.NewBuffer(make([]byte, 0, tx.MsgTx().SerializeSize()))
   592  	// Ignore Serialize's error, as writing to a bytes.buffer cannot fail.
   593  	tx.MsgTx().Serialize(buf)
   594  	return hex.EncodeToString(buf.Bytes())
   595  }
   596  
   597  // blockDetails creates a BlockDetails struct to include in btcws notifications
   598  // from a block and a transaction's block index.
   599  func blockDetails(block *godashutil.Block, txIndex int) *btcjson.BlockDetails {
   600  	if block == nil {
   601  		return nil
   602  	}
   603  	return &btcjson.BlockDetails{
   604  		Height: int32(block.Height()),
   605  		Hash:   block.Sha().String(),
   606  		Index:  txIndex,
   607  		Time:   block.MsgBlock().Header.Timestamp.Unix(),
   608  	}
   609  }
   610  
   611  // newRedeemingTxNotification returns a new marshalled redeemingtx notification
   612  // with the passed parameters.
   613  func newRedeemingTxNotification(txHex string, index int, block *godashutil.Block) ([]byte, error) {
   614  	// Create and marshal the notification.
   615  	ntfn := btcjson.NewRedeemingTxNtfn(txHex, blockDetails(block, index))
   616  	return btcjson.MarshalCmd(nil, ntfn)
   617  }
   618  
   619  // notifyForTxOuts examines each transaction output, notifying interested
   620  // websocket clients of the transaction if an output spends to a watched
   621  // address.  A spent notification request is automatically registered for
   622  // the client for each matching output.
   623  func (m *wsNotificationManager) notifyForTxOuts(ops map[wire.OutPoint]map[chan struct{}]*wsClient,
   624  	addrs map[string]map[chan struct{}]*wsClient, tx *godashutil.Tx, block *godashutil.Block) {
   625  
   626  	// Nothing to do if nobody is listening for address notifications.
   627  	if len(addrs) == 0 {
   628  		return
   629  	}
   630  
   631  	txHex := ""
   632  	wscNotified := make(map[chan struct{}]struct{})
   633  	for i, txOut := range tx.MsgTx().TxOut {
   634  		_, txAddrs, _, err := txscript.ExtractPkScriptAddrs(
   635  			txOut.PkScript, m.server.server.chainParams)
   636  		if err != nil {
   637  			continue
   638  		}
   639  
   640  		for _, txAddr := range txAddrs {
   641  			cmap, ok := addrs[txAddr.EncodeAddress()]
   642  			if !ok {
   643  				continue
   644  			}
   645  
   646  			if txHex == "" {
   647  				txHex = txHexString(tx)
   648  			}
   649  			ntfn := btcjson.NewRecvTxNtfn(txHex, blockDetails(block,
   650  				tx.Index()))
   651  
   652  			marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn)
   653  			if err != nil {
   654  				rpcsLog.Errorf("Failed to marshal processedtx notification: %v", err)
   655  				continue
   656  			}
   657  
   658  			op := []*wire.OutPoint{wire.NewOutPoint(tx.Sha(), uint32(i))}
   659  			for wscQuit, wsc := range cmap {
   660  				m.addSpentRequests(ops, wsc, op)
   661  
   662  				if _, ok := wscNotified[wscQuit]; !ok {
   663  					wscNotified[wscQuit] = struct{}{}
   664  					wsc.QueueNotification(marshalledJSON)
   665  				}
   666  			}
   667  		}
   668  	}
   669  }
   670  
   671  // notifyForTx examines the inputs and outputs of the passed transaction,
   672  // notifying websocket clients of outputs spending to a watched address
   673  // and inputs spending a watched outpoint.
   674  func (m *wsNotificationManager) notifyForTx(ops map[wire.OutPoint]map[chan struct{}]*wsClient,
   675  	addrs map[string]map[chan struct{}]*wsClient, tx *godashutil.Tx, block *godashutil.Block) {
   676  
   677  	if len(ops) != 0 {
   678  		m.notifyForTxIns(ops, tx, block)
   679  	}
   680  	if len(addrs) != 0 {
   681  		m.notifyForTxOuts(ops, addrs, tx, block)
   682  	}
   683  }
   684  
   685  // notifyForTxIns examines the inputs of the passed transaction and sends
   686  // interested websocket clients a redeemingtx notification if any inputs
   687  // spend a watched output.  If block is non-nil, any matching spent
   688  // requests are removed.
   689  func (m *wsNotificationManager) notifyForTxIns(ops map[wire.OutPoint]map[chan struct{}]*wsClient,
   690  	tx *godashutil.Tx, block *godashutil.Block) {
   691  
   692  	// Nothing to do if nobody is watching outpoints.
   693  	if len(ops) == 0 {
   694  		return
   695  	}
   696  
   697  	txHex := ""
   698  	wscNotified := make(map[chan struct{}]struct{})
   699  	for _, txIn := range tx.MsgTx().TxIn {
   700  		prevOut := &txIn.PreviousOutPoint
   701  		if cmap, ok := ops[*prevOut]; ok {
   702  			if txHex == "" {
   703  				txHex = txHexString(tx)
   704  			}
   705  			marshalledJSON, err := newRedeemingTxNotification(txHex, tx.Index(), block)
   706  			if err != nil {
   707  				rpcsLog.Warnf("Failed to marshal redeemingtx notification: %v", err)
   708  				continue
   709  			}
   710  			for wscQuit, wsc := range cmap {
   711  				if block != nil {
   712  					m.removeSpentRequest(ops, wsc, prevOut)
   713  				}
   714  
   715  				if _, ok := wscNotified[wscQuit]; !ok {
   716  					wscNotified[wscQuit] = struct{}{}
   717  					wsc.QueueNotification(marshalledJSON)
   718  				}
   719  			}
   720  		}
   721  	}
   722  }
   723  
   724  // RegisterTxOutAddressRequests requests notifications to the passed websocket
   725  // client when a transaction output spends to the passed address.
   726  func (m *wsNotificationManager) RegisterTxOutAddressRequests(wsc *wsClient, addrs []string) {
   727  	m.queueNotification <- &notificationRegisterAddr{
   728  		wsc:   wsc,
   729  		addrs: addrs,
   730  	}
   731  }
   732  
   733  // addAddrRequests adds the websocket client wsc to the address to client set
   734  // addrMap so wsc will be notified for any mempool or block transaction outputs
   735  // spending to any of the addresses in addrs.
   736  func (*wsNotificationManager) addAddrRequests(addrMap map[string]map[chan struct{}]*wsClient,
   737  	wsc *wsClient, addrs []string) {
   738  
   739  	for _, addr := range addrs {
   740  		// Track the request in the client as well so it can be quickly be
   741  		// removed on disconnect.
   742  		wsc.addrRequests[addr] = struct{}{}
   743  
   744  		// Add the client to the set of clients to notify when the
   745  		// outpoint is seen.  Create map as needed.
   746  		cmap, ok := addrMap[addr]
   747  		if !ok {
   748  			cmap = make(map[chan struct{}]*wsClient)
   749  			addrMap[addr] = cmap
   750  		}
   751  		cmap[wsc.quit] = wsc
   752  	}
   753  }
   754  
   755  // UnregisterTxOutAddressRequest removes a request from the passed websocket
   756  // client to be notified when a transaction spends to the passed address.
   757  func (m *wsNotificationManager) UnregisterTxOutAddressRequest(wsc *wsClient, addr string) {
   758  	m.queueNotification <- &notificationUnregisterAddr{
   759  		wsc:  wsc,
   760  		addr: addr,
   761  	}
   762  }
   763  
   764  // removeAddrRequest removes the websocket client wsc from the address to
   765  // client set addrs so it will no longer receive notification updates for
   766  // any transaction outputs send to addr.
   767  func (*wsNotificationManager) removeAddrRequest(addrs map[string]map[chan struct{}]*wsClient,
   768  	wsc *wsClient, addr string) {
   769  
   770  	// Remove the request tracking from the client.
   771  	delete(wsc.addrRequests, addr)
   772  
   773  	// Remove the client from the list to notify.
   774  	cmap, ok := addrs[addr]
   775  	if !ok {
   776  		rpcsLog.Warnf("Attempt to remove nonexistent addr request "+
   777  			"<%s> for websocket client %s", addr, wsc.addr)
   778  		return
   779  	}
   780  	delete(cmap, wsc.quit)
   781  
   782  	// Remove the map entry altogether if there are no more clients
   783  	// interested in it.
   784  	if len(cmap) == 0 {
   785  		delete(addrs, addr)
   786  	}
   787  }
   788  
   789  // AddClient adds the passed websocket client to the notification manager.
   790  func (m *wsNotificationManager) AddClient(wsc *wsClient) {
   791  	m.queueNotification <- (*notificationRegisterClient)(wsc)
   792  }
   793  
   794  // RemoveClient removes the passed websocket client and all notifications
   795  // registered for it.
   796  func (m *wsNotificationManager) RemoveClient(wsc *wsClient) {
   797  	select {
   798  	case m.queueNotification <- (*notificationUnregisterClient)(wsc):
   799  	case <-m.quit:
   800  	}
   801  }
   802  
   803  // Start starts the goroutines required for the manager to queue and process
   804  // websocket client notifications.
   805  func (m *wsNotificationManager) Start() {
   806  	m.wg.Add(2)
   807  	go m.queueHandler()
   808  	go m.notificationHandler()
   809  }
   810  
   811  // WaitForShutdown blocks until all notification manager goroutines have
   812  // finished.
   813  func (m *wsNotificationManager) WaitForShutdown() {
   814  	m.wg.Wait()
   815  }
   816  
   817  // Shutdown shuts down the manager, stopping the notification queue and
   818  // notification handler goroutines.
   819  func (m *wsNotificationManager) Shutdown() {
   820  	close(m.quit)
   821  }
   822  
   823  // newWsNotificationManager returns a new notification manager ready for use.
   824  // See wsNotificationManager for more details.
   825  func newWsNotificationManager(server *rpcServer) *wsNotificationManager {
   826  	return &wsNotificationManager{
   827  		server:            server,
   828  		queueNotification: make(chan interface{}),
   829  		notificationMsgs:  make(chan interface{}),
   830  		numClients:        make(chan int),
   831  		quit:              make(chan struct{}),
   832  	}
   833  }
   834  
   835  // wsResponse houses a message to send to a connected websocket client as
   836  // well as a channel to reply on when the message is sent.
   837  type wsResponse struct {
   838  	msg      []byte
   839  	doneChan chan bool
   840  }
   841  
   842  // wsClient provides an abstraction for handling a websocket client.  The
   843  // overall data flow is split into 3 main goroutines, a possible 4th goroutine
   844  // for long-running operations (only started if request is made), and a
   845  // websocket manager which is used to allow things such as broadcasting
   846  // requested notifications to all connected websocket clients.   Inbound
   847  // messages are read via the inHandler goroutine and generally dispatched to
   848  // their own handler.  However, certain potentially long-running operations such
   849  // as rescans, are sent to the asyncHander goroutine and are limited to one at a
   850  // time.  There are two outbound message types - one for responding to client
   851  // requests and another for async notifications.  Responses to client requests
   852  // use SendMessage which employs a buffered channel thereby limiting the number
   853  // of outstanding requests that can be made.  Notifications are sent via
   854  // QueueNotification which implements a queue via notificationQueueHandler to
   855  // ensure sending notifications from other subsystems can't block.  Ultimately,
   856  // all messages are sent via the outHandler.
   857  type wsClient struct {
   858  	sync.Mutex
   859  
   860  	// server is the RPC server that is servicing the client.
   861  	server *rpcServer
   862  
   863  	// conn is the underlying websocket connection.
   864  	conn *websocket.Conn
   865  
   866  	// disconnected indicated whether or not the websocket client is
   867  	// disconnected.
   868  	disconnected bool
   869  
   870  	// addr is the remote address of the client.
   871  	addr string
   872  
   873  	// authenticated specifies whether a client has been authenticated
   874  	// and therefore is allowed to communicated over the websocket.
   875  	authenticated bool
   876  
   877  	// isAdmin specifies whether a client may change the state of the server;
   878  	// false means its access is only to the limited set of RPC calls.
   879  	isAdmin bool
   880  
   881  	// sessionID is a random ID generated for each client when connected.
   882  	// These IDs may be queried by a client using the session RPC.  A change
   883  	// to the session ID indicates that the client reconnected.
   884  	sessionID uint64
   885  
   886  	// verboseTxUpdates specifies whether a client has requested verbose
   887  	// information about all new transactions.
   888  	verboseTxUpdates bool
   889  
   890  	// addrRequests is a set of addresses the caller has requested to be
   891  	// notified about.  It is maintained here so all requests can be removed
   892  	// when a wallet disconnects.  Owned by the notification manager.
   893  	addrRequests map[string]struct{}
   894  
   895  	// spentRequests is a set of unspent Outpoints a wallet has requested
   896  	// notifications for when they are spent by a processed transaction.
   897  	// Owned by the notification manager.
   898  	spentRequests map[wire.OutPoint]struct{}
   899  
   900  	// Networking infrastructure.
   901  	asyncStarted bool
   902  	asyncChan    chan *parsedRPCCmd
   903  	ntfnChan     chan []byte
   904  	sendChan     chan wsResponse
   905  	quit         chan struct{}
   906  	wg           sync.WaitGroup
   907  }
   908  
   909  // handleMessage is the main handler for incoming requests.  It enforces
   910  // authentication, parses the incoming json, looks up and executes handlers
   911  // (including pass through for standard RPC commands), and sends the appropriate
   912  // response.  It also detects commands which are marked as long-running and
   913  // sends them off to the asyncHander for processing.
   914  func (c *wsClient) handleMessage(msg []byte) {
   915  	if !c.authenticated {
   916  		// Disconnect immediately if the provided command fails to
   917  		// parse when the client is not already authenticated.
   918  		var request btcjson.Request
   919  		if err := json.Unmarshal(msg, &request); err != nil {
   920  			c.Disconnect()
   921  			return
   922  		}
   923  		parsedCmd := parseCmd(&request)
   924  		if parsedCmd.err != nil {
   925  			c.Disconnect()
   926  			return
   927  		}
   928  
   929  		// Disconnect immediately if the first command is not
   930  		// authenticate when not already authenticated.
   931  		authCmd, ok := parsedCmd.cmd.(*btcjson.AuthenticateCmd)
   932  		if !ok {
   933  			rpcsLog.Warnf("Unauthenticated websocket message " +
   934  				"received")
   935  			c.Disconnect()
   936  			return
   937  		}
   938  
   939  		// Check credentials.
   940  		login := authCmd.Username + ":" + authCmd.Passphrase
   941  		auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login))
   942  		authSha := fastsha256.Sum256([]byte(auth))
   943  		cmp := subtle.ConstantTimeCompare(authSha[:], c.server.authsha[:])
   944  		limitcmp := subtle.ConstantTimeCompare(authSha[:], c.server.limitauthsha[:])
   945  		if cmp != 1 && limitcmp != 1 {
   946  			rpcsLog.Warnf("Auth failure.")
   947  			c.Disconnect()
   948  			return
   949  		}
   950  		c.authenticated = true
   951  		c.isAdmin = cmp == 1
   952  
   953  		// Marshal and send response.
   954  		reply, err := createMarshalledReply(parsedCmd.id, nil, nil)
   955  		if err != nil {
   956  			rpcsLog.Errorf("Failed to marshal authenticate reply: "+
   957  				"%v", err.Error())
   958  			return
   959  		}
   960  		c.SendMessage(reply, nil)
   961  		return
   962  	}
   963  
   964  	// Attempt to parse the raw message into a JSON-RPC request.
   965  	var request btcjson.Request
   966  	if err := json.Unmarshal(msg, &request); err != nil {
   967  		jsonErr := &btcjson.RPCError{
   968  			Code:    btcjson.ErrRPCParse.Code,
   969  			Message: "Failed to parse request: " + err.Error(),
   970  		}
   971  
   972  		// Marshal and send response.
   973  		reply, err := createMarshalledReply(nil, nil, jsonErr)
   974  		if err != nil {
   975  			rpcsLog.Errorf("Failed to marshal parse failure "+
   976  				"reply: %v", err)
   977  			return
   978  		}
   979  		c.SendMessage(reply, nil)
   980  		return
   981  	}
   982  	// Requests with no ID (notifications) must not have a response per the
   983  	// JSON-RPC spec.
   984  	if request.ID == nil {
   985  		return
   986  	}
   987  
   988  	// Check if the user is limited and disconnect client if unauthorized
   989  	if !c.isAdmin {
   990  		if _, ok := rpcLimited[request.Method]; !ok {
   991  			jsonErr := &btcjson.RPCError{
   992  				Code:    btcjson.ErrRPCInvalidParams.Code,
   993  				Message: "limited user not authorized for this method",
   994  			}
   995  			// Marshal and send response.
   996  			reply, err := createMarshalledReply(request.ID, nil, jsonErr)
   997  			if err != nil {
   998  				rpcsLog.Errorf("Failed to marshal parse failure "+
   999  					"reply: %v", err)
  1000  				return
  1001  			}
  1002  			c.SendMessage(reply, nil)
  1003  			return
  1004  		}
  1005  	}
  1006  
  1007  	// Attempt to parse the JSON-RPC request into a known concrete command.
  1008  	cmd := parseCmd(&request)
  1009  	if cmd.err != nil {
  1010  		// Marshal and send response.
  1011  		reply, err := createMarshalledReply(cmd.id, nil, cmd.err)
  1012  		if err != nil {
  1013  			rpcsLog.Errorf("Failed to marshal parse failure "+
  1014  				"reply: %v", err)
  1015  			return
  1016  		}
  1017  		c.SendMessage(reply, nil)
  1018  		return
  1019  	}
  1020  	rpcsLog.Debugf("Received command <%s> from %s", cmd.method, c.addr)
  1021  
  1022  	// Disconnect if already authenticated and another authenticate command
  1023  	// is received.
  1024  	if _, ok := cmd.cmd.(*btcjson.AuthenticateCmd); ok {
  1025  		rpcsLog.Warnf("Websocket client %s is already authenticated",
  1026  			c.addr)
  1027  		c.Disconnect()
  1028  		return
  1029  	}
  1030  
  1031  	// When the command is marked as a long-running command, send it off
  1032  	// to the asyncHander goroutine for processing.
  1033  	if _, ok := wsAsyncHandlers[cmd.method]; ok {
  1034  		// Start up the async goroutine for handling long-running
  1035  		// requests asynchonrously if needed.
  1036  		if !c.asyncStarted {
  1037  			rpcsLog.Tracef("Starting async handler for %s", c.addr)
  1038  			c.wg.Add(1)
  1039  			go c.asyncHandler()
  1040  			c.asyncStarted = true
  1041  		}
  1042  		c.asyncChan <- cmd
  1043  		return
  1044  	}
  1045  
  1046  	// Lookup the websocket extension for the command and if it doesn't
  1047  	// exist fallback to handling the command as a standard command.
  1048  	wsHandler, ok := wsHandlers[cmd.method]
  1049  	if !ok {
  1050  		// No websocket-specific handler so handle like a legacy
  1051  		// RPC connection.
  1052  		result, jsonErr := c.server.standardCmdResult(cmd, nil)
  1053  		reply, err := createMarshalledReply(cmd.id, result, jsonErr)
  1054  		if err != nil {
  1055  			rpcsLog.Errorf("Failed to marshal reply for <%s> "+
  1056  				"command: %v", cmd.method, err)
  1057  			return
  1058  		}
  1059  
  1060  		c.SendMessage(reply, nil)
  1061  		return
  1062  	}
  1063  
  1064  	// Invoke the handler and marshal and send response.
  1065  	result, jsonErr := wsHandler(c, cmd.cmd)
  1066  	reply, err := createMarshalledReply(cmd.id, result, jsonErr)
  1067  	if err != nil {
  1068  		rpcsLog.Errorf("Failed to marshal reply for <%s> command: %v",
  1069  			cmd.method, err)
  1070  		return
  1071  	}
  1072  	c.SendMessage(reply, nil)
  1073  }
  1074  
  1075  // inHandler handles all incoming messages for the websocket connection.  It
  1076  // must be run as a goroutine.
  1077  func (c *wsClient) inHandler() {
  1078  out:
  1079  	for {
  1080  		// Break out of the loop once the quit channel has been closed.
  1081  		// Use a non-blocking select here so we fall through otherwise.
  1082  		select {
  1083  		case <-c.quit:
  1084  			break out
  1085  		default:
  1086  		}
  1087  
  1088  		_, msg, err := c.conn.ReadMessage()
  1089  		if err != nil {
  1090  			// Log the error if it's not due to disconnecting.
  1091  			if err != io.EOF {
  1092  				rpcsLog.Errorf("Websocket receive error from "+
  1093  					"%s: %v", c.addr, err)
  1094  			}
  1095  			break out
  1096  		}
  1097  		c.handleMessage(msg)
  1098  	}
  1099  
  1100  	// Ensure the connection is closed.
  1101  	c.Disconnect()
  1102  	c.wg.Done()
  1103  	rpcsLog.Tracef("Websocket client input handler done for %s", c.addr)
  1104  }
  1105  
  1106  // notificationQueueHandler handles the queuing of outgoing notifications for
  1107  // the websocket client.  This runs as a muxer for various sources of input to
  1108  // ensure that queuing up notifications to be sent will not block.  Otherwise,
  1109  // slow clients could bog down the other systems (such as the mempool or block
  1110  // manager) which are queuing the data.  The data is passed on to outHandler to
  1111  // actually be written.  It must be run as a goroutine.
  1112  func (c *wsClient) notificationQueueHandler() {
  1113  	ntfnSentChan := make(chan bool, 1) // nonblocking sync
  1114  
  1115  	// pendingNtfns is used as a queue for notifications that are ready to
  1116  	// be sent once there are no outstanding notifications currently being
  1117  	// sent.  The waiting flag is used over simply checking for items in the
  1118  	// pending list to ensure cleanup knows what has and hasn't been sent
  1119  	// to the outHandler.  Currently no special cleanup is needed, however
  1120  	// if something like a done channel is added to notifications in the
  1121  	// future, not knowing what has and hasn't been sent to the outHandler
  1122  	// (and thus who should respond to the done channel) would be
  1123  	// problematic without using this approach.
  1124  	pendingNtfns := list.New()
  1125  	waiting := false
  1126  out:
  1127  	for {
  1128  		select {
  1129  		// This channel is notified when a message is being queued to
  1130  		// be sent across the network socket.  It will either send the
  1131  		// message immediately if a send is not already in progress, or
  1132  		// queue the message to be sent once the other pending messages
  1133  		// are sent.
  1134  		case msg := <-c.ntfnChan:
  1135  			if !waiting {
  1136  				c.SendMessage(msg, ntfnSentChan)
  1137  			} else {
  1138  				pendingNtfns.PushBack(msg)
  1139  			}
  1140  			waiting = true
  1141  
  1142  		// This channel is notified when a notification has been sent
  1143  		// across the network socket.
  1144  		case <-ntfnSentChan:
  1145  			// No longer waiting if there are no more messages in
  1146  			// the pending messages queue.
  1147  			next := pendingNtfns.Front()
  1148  			if next == nil {
  1149  				waiting = false
  1150  				continue
  1151  			}
  1152  
  1153  			// Notify the outHandler about the next item to
  1154  			// asynchronously send.
  1155  			msg := pendingNtfns.Remove(next).([]byte)
  1156  			c.SendMessage(msg, ntfnSentChan)
  1157  
  1158  		case <-c.quit:
  1159  			break out
  1160  		}
  1161  	}
  1162  
  1163  	// Drain any wait channels before exiting so nothing is left waiting
  1164  	// around to send.
  1165  cleanup:
  1166  	for {
  1167  		select {
  1168  		case <-c.ntfnChan:
  1169  		case <-ntfnSentChan:
  1170  		default:
  1171  			break cleanup
  1172  		}
  1173  	}
  1174  	c.wg.Done()
  1175  	rpcsLog.Tracef("Websocket client notification queue handler done "+
  1176  		"for %s", c.addr)
  1177  }
  1178  
  1179  // outHandler handles all outgoing messages for the websocket connection.  It
  1180  // must be run as a goroutine.  It uses a buffered channel to serialize output
  1181  // messages while allowing the sender to continue running asynchronously.  It
  1182  // must be run as a goroutine.
  1183  func (c *wsClient) outHandler() {
  1184  out:
  1185  	for {
  1186  		// Send any messages ready for send until the quit channel is
  1187  		// closed.
  1188  		select {
  1189  		case r := <-c.sendChan:
  1190  			err := c.conn.WriteMessage(websocket.TextMessage, r.msg)
  1191  			if err != nil {
  1192  				c.Disconnect()
  1193  				break out
  1194  			}
  1195  			if r.doneChan != nil {
  1196  				r.doneChan <- true
  1197  			}
  1198  
  1199  		case <-c.quit:
  1200  			break out
  1201  		}
  1202  	}
  1203  
  1204  	// Drain any wait channels before exiting so nothing is left waiting
  1205  	// around to send.
  1206  cleanup:
  1207  	for {
  1208  		select {
  1209  		case r := <-c.sendChan:
  1210  			if r.doneChan != nil {
  1211  				r.doneChan <- false
  1212  			}
  1213  		default:
  1214  			break cleanup
  1215  		}
  1216  	}
  1217  	c.wg.Done()
  1218  	rpcsLog.Tracef("Websocket client output handler done for %s", c.addr)
  1219  }
  1220  
  1221  // asyncHandler handles all long-running requests such as rescans which are
  1222  // not run directly in the inHandler routine unlike most requests.  This allows
  1223  // normal quick requests to continue to be processed and responded to even while
  1224  // lengthy operations are underway.  Only one long-running operation is
  1225  // permitted at a time, so multiple long-running requests are queued and
  1226  // serialized.  It must be run as a goroutine.  Also, this goroutine is not
  1227  // started until/if the first long-running request is made.
  1228  func (c *wsClient) asyncHandler() {
  1229  	asyncHandlerDoneChan := make(chan struct{}, 1) // nonblocking sync
  1230  	pendingCmds := list.New()
  1231  	waiting := false
  1232  
  1233  	// runHandler runs the handler for the passed command and sends the
  1234  	// reply.
  1235  	runHandler := func(parsedCmd *parsedRPCCmd) {
  1236  		wsHandler, ok := wsHandlers[parsedCmd.method]
  1237  		if !ok {
  1238  			rpcsLog.Warnf("No handler for command <%s>",
  1239  				parsedCmd.method)
  1240  			return
  1241  		}
  1242  
  1243  		// Invoke the handler and marshal and send response.
  1244  		result, jsonErr := wsHandler(c, parsedCmd.cmd)
  1245  		reply, err := createMarshalledReply(parsedCmd.id, result,
  1246  			jsonErr)
  1247  		if err != nil {
  1248  			rpcsLog.Errorf("Failed to marshal reply for <%s> "+
  1249  				"command: %v", parsedCmd.method, err)
  1250  			return
  1251  		}
  1252  		c.SendMessage(reply, nil)
  1253  	}
  1254  
  1255  out:
  1256  	for {
  1257  		select {
  1258  		case cmd := <-c.asyncChan:
  1259  			if !waiting {
  1260  				c.wg.Add(1)
  1261  				go func(cmd *parsedRPCCmd) {
  1262  					runHandler(cmd)
  1263  					asyncHandlerDoneChan <- struct{}{}
  1264  					c.wg.Done()
  1265  				}(cmd)
  1266  			} else {
  1267  				pendingCmds.PushBack(cmd)
  1268  			}
  1269  			waiting = true
  1270  
  1271  		case <-asyncHandlerDoneChan:
  1272  			// No longer waiting if there are no more messages in
  1273  			// the pending messages queue.
  1274  			next := pendingCmds.Front()
  1275  			if next == nil {
  1276  				waiting = false
  1277  				continue
  1278  			}
  1279  
  1280  			// Notify the outHandler about the next item to
  1281  			// asynchronously send.
  1282  			element := pendingCmds.Remove(next)
  1283  			c.wg.Add(1)
  1284  			go func(cmd *parsedRPCCmd) {
  1285  				runHandler(cmd)
  1286  				asyncHandlerDoneChan <- struct{}{}
  1287  				c.wg.Done()
  1288  			}(element.(*parsedRPCCmd))
  1289  
  1290  		case <-c.quit:
  1291  			break out
  1292  		}
  1293  	}
  1294  
  1295  	// Drain any wait channels before exiting so nothing is left waiting
  1296  	// around to send.
  1297  cleanup:
  1298  	for {
  1299  		select {
  1300  		case <-c.asyncChan:
  1301  		case <-asyncHandlerDoneChan:
  1302  		default:
  1303  			break cleanup
  1304  		}
  1305  	}
  1306  
  1307  	c.wg.Done()
  1308  	rpcsLog.Tracef("Websocket client async handler done for %s", c.addr)
  1309  }
  1310  
  1311  // SendMessage sends the passed json to the websocket client.  It is backed
  1312  // by a buffered channel, so it will not block until the send channel is full.
  1313  // Note however that QueueNotification must be used for sending async
  1314  // notifications instead of the this function.  This approach allows a limit to
  1315  // the number of outstanding requests a client can make without preventing or
  1316  // blocking on async notifications.
  1317  func (c *wsClient) SendMessage(marshalledJSON []byte, doneChan chan bool) {
  1318  	// Don't send the message if disconnected.
  1319  	if c.Disconnected() {
  1320  		if doneChan != nil {
  1321  			doneChan <- false
  1322  		}
  1323  		return
  1324  	}
  1325  
  1326  	c.sendChan <- wsResponse{msg: marshalledJSON, doneChan: doneChan}
  1327  }
  1328  
  1329  // ErrClientQuit describes the error where a client send is not processed due
  1330  // to the client having already been disconnected or dropped.
  1331  var ErrClientQuit = errors.New("client quit")
  1332  
  1333  // QueueNotification queues the passed notification to be sent to the websocket
  1334  // client.  This function, as the name implies, is only intended for
  1335  // notifications since it has additional logic to prevent other subsystems, such
  1336  // as the memory pool and block manager, from blocking even when the send
  1337  // channel is full.
  1338  //
  1339  // If the client is in the process of shutting down, this function returns
  1340  // ErrClientQuit.  This is intended to be checked by long-running notification
  1341  // handlers to stop processing if there is no more work needed to be done.
  1342  func (c *wsClient) QueueNotification(marshalledJSON []byte) error {
  1343  	// Don't queue the message if disconnected.
  1344  	if c.Disconnected() {
  1345  		return ErrClientQuit
  1346  	}
  1347  
  1348  	c.ntfnChan <- marshalledJSON
  1349  	return nil
  1350  }
  1351  
  1352  // Disconnected returns whether or not the websocket client is disconnected.
  1353  func (c *wsClient) Disconnected() bool {
  1354  	c.Lock()
  1355  	defer c.Unlock()
  1356  
  1357  	return c.disconnected
  1358  }
  1359  
  1360  // Disconnect disconnects the websocket client.
  1361  func (c *wsClient) Disconnect() {
  1362  	c.Lock()
  1363  	defer c.Unlock()
  1364  
  1365  	// Nothing to do if already disconnected.
  1366  	if c.disconnected {
  1367  		return
  1368  	}
  1369  
  1370  	rpcsLog.Tracef("Disconnecting websocket client %s", c.addr)
  1371  	close(c.quit)
  1372  	c.conn.Close()
  1373  	c.disconnected = true
  1374  }
  1375  
  1376  // Start begins processing input and output messages.
  1377  func (c *wsClient) Start() {
  1378  	rpcsLog.Tracef("Starting websocket client %s", c.addr)
  1379  
  1380  	// Start processing input and output.
  1381  	c.wg.Add(3)
  1382  	go c.inHandler()
  1383  	go c.notificationQueueHandler()
  1384  	go c.outHandler()
  1385  }
  1386  
  1387  // WaitForShutdown blocks until the websocket client goroutines are stopped
  1388  // and the connection is closed.
  1389  func (c *wsClient) WaitForShutdown() {
  1390  	c.wg.Wait()
  1391  }
  1392  
  1393  // newWebsocketClient returns a new websocket client given the notification
  1394  // manager, websocket connection, remote address, and whether or not the client
  1395  // has already been authenticated (via HTTP Basic access authentication).  The
  1396  // returned client is ready to start.  Once started, the client will process
  1397  // incoming and outgoing messages in separate goroutines complete with queuing
  1398  // and asynchrous handling for long-running operations.
  1399  func newWebsocketClient(server *rpcServer, conn *websocket.Conn,
  1400  	remoteAddr string, authenticated bool, isAdmin bool) (*wsClient, error) {
  1401  
  1402  	sessionID, err := wire.RandomUint64()
  1403  	if err != nil {
  1404  		return nil, err
  1405  	}
  1406  
  1407  	client := &wsClient{
  1408  		conn:          conn,
  1409  		addr:          remoteAddr,
  1410  		authenticated: authenticated,
  1411  		isAdmin:       isAdmin,
  1412  		sessionID:     sessionID,
  1413  		server:        server,
  1414  		addrRequests:  make(map[string]struct{}),
  1415  		spentRequests: make(map[wire.OutPoint]struct{}),
  1416  		ntfnChan:      make(chan []byte, 1),        // nonblocking sync
  1417  		asyncChan:     make(chan *parsedRPCCmd, 1), // nonblocking sync
  1418  		sendChan:      make(chan wsResponse, websocketSendBufferSize),
  1419  		quit:          make(chan struct{}),
  1420  	}
  1421  	return client, nil
  1422  }
  1423  
  1424  // handleWebsocketHelp implements the help command for websocket connections.
  1425  func handleWebsocketHelp(wsc *wsClient, icmd interface{}) (interface{}, error) {
  1426  	cmd, ok := icmd.(*btcjson.HelpCmd)
  1427  	if !ok {
  1428  		return nil, btcjson.ErrRPCInternal
  1429  	}
  1430  
  1431  	// Provide a usage overview of all commands when no specific command
  1432  	// was specified.
  1433  	var command string
  1434  	if cmd.Command != nil {
  1435  		command = *cmd.Command
  1436  	}
  1437  	if command == "" {
  1438  		usage, err := wsc.server.helpCacher.rpcUsage(true)
  1439  		if err != nil {
  1440  			context := "Failed to generate RPC usage"
  1441  			return nil, internalRPCError(err.Error(), context)
  1442  		}
  1443  		return usage, nil
  1444  	}
  1445  
  1446  	// Check that the command asked for is supported and implemented.
  1447  	// Search the list of websocket handlers as well as the main list of
  1448  	// handlers since help should only be provided for those cases.
  1449  	valid := true
  1450  	if _, ok := rpcHandlers[command]; !ok {
  1451  		if _, ok := wsHandlers[command]; !ok {
  1452  			valid = false
  1453  		}
  1454  	}
  1455  	if !valid {
  1456  		return nil, &btcjson.RPCError{
  1457  			Code:    btcjson.ErrRPCInvalidParameter,
  1458  			Message: "Unknown command: " + command,
  1459  		}
  1460  	}
  1461  
  1462  	// Get the help for the command.
  1463  	help, err := wsc.server.helpCacher.rpcMethodHelp(command)
  1464  	if err != nil {
  1465  		context := "Failed to generate help"
  1466  		return nil, internalRPCError(err.Error(), context)
  1467  	}
  1468  	return help, nil
  1469  }
  1470  
  1471  // handleNotifyBlocks implements the notifyblocks command extension for
  1472  // websocket connections.
  1473  func handleNotifyBlocks(wsc *wsClient, icmd interface{}) (interface{}, error) {
  1474  	wsc.server.ntfnMgr.RegisterBlockUpdates(wsc)
  1475  	return nil, nil
  1476  }
  1477  
  1478  // handleSession implements the session command extension for websocket
  1479  // connections.
  1480  func handleSession(wsc *wsClient, icmd interface{}) (interface{}, error) {
  1481  	return &btcjson.SessionResult{SessionID: wsc.sessionID}, nil
  1482  }
  1483  
  1484  // handleStopNotifyBlocks implements the stopnotifyblocks command extension for
  1485  // websocket connections.
  1486  func handleStopNotifyBlocks(wsc *wsClient, icmd interface{}) (interface{}, error) {
  1487  	wsc.server.ntfnMgr.UnregisterBlockUpdates(wsc)
  1488  	return nil, nil
  1489  }
  1490  
  1491  // handleNotifySpent implements the notifyspent command extension for
  1492  // websocket connections.
  1493  func handleNotifySpent(wsc *wsClient, icmd interface{}) (interface{}, error) {
  1494  	cmd, ok := icmd.(*btcjson.NotifySpentCmd)
  1495  	if !ok {
  1496  		return nil, btcjson.ErrRPCInternal
  1497  	}
  1498  
  1499  	outpoints, err := deserializeOutpoints(cmd.OutPoints)
  1500  	if err != nil {
  1501  		return nil, err
  1502  	}
  1503  
  1504  	wsc.server.ntfnMgr.RegisterSpentRequests(wsc, outpoints)
  1505  	return nil, nil
  1506  }
  1507  
  1508  // handleNotifyNewTransations implements the notifynewtransactions command
  1509  // extension for websocket connections.
  1510  func handleNotifyNewTransactions(wsc *wsClient, icmd interface{}) (interface{}, error) {
  1511  	cmd, ok := icmd.(*btcjson.NotifyNewTransactionsCmd)
  1512  	if !ok {
  1513  		return nil, btcjson.ErrRPCInternal
  1514  	}
  1515  
  1516  	wsc.verboseTxUpdates = cmd.Verbose != nil && *cmd.Verbose
  1517  	wsc.server.ntfnMgr.RegisterNewMempoolTxsUpdates(wsc)
  1518  	return nil, nil
  1519  }
  1520  
  1521  // handleStopNotifyNewTransations implements the stopnotifynewtransactions
  1522  // command extension for websocket connections.
  1523  func handleStopNotifyNewTransactions(wsc *wsClient, icmd interface{}) (interface{}, error) {
  1524  	wsc.server.ntfnMgr.UnregisterNewMempoolTxsUpdates(wsc)
  1525  	return nil, nil
  1526  }
  1527  
  1528  // handleNotifyReceived implements the notifyreceived command extension for
  1529  // websocket connections.
  1530  func handleNotifyReceived(wsc *wsClient, icmd interface{}) (interface{}, error) {
  1531  	cmd, ok := icmd.(*btcjson.NotifyReceivedCmd)
  1532  	if !ok {
  1533  		return nil, btcjson.ErrRPCInternal
  1534  	}
  1535  
  1536  	// Decode addresses to validate input, but the strings slice is used
  1537  	// directly if these are all ok.
  1538  	err := checkAddressValidity(cmd.Addresses)
  1539  	if err != nil {
  1540  		return nil, err
  1541  	}
  1542  
  1543  	wsc.server.ntfnMgr.RegisterTxOutAddressRequests(wsc, cmd.Addresses)
  1544  	return nil, nil
  1545  }
  1546  
  1547  // handleStopNotifySpent implements the stopnotifyspent command extension for
  1548  // websocket connections.
  1549  func handleStopNotifySpent(wsc *wsClient, icmd interface{}) (interface{}, error) {
  1550  	cmd, ok := icmd.(*btcjson.StopNotifySpentCmd)
  1551  	if !ok {
  1552  		return nil, btcjson.ErrRPCInternal
  1553  	}
  1554  
  1555  	outpoints, err := deserializeOutpoints(cmd.OutPoints)
  1556  	if err != nil {
  1557  		return nil, err
  1558  	}
  1559  
  1560  	for _, outpoint := range outpoints {
  1561  		wsc.server.ntfnMgr.UnregisterSpentRequest(wsc, outpoint)
  1562  	}
  1563  
  1564  	return nil, nil
  1565  }
  1566  
  1567  // handleStopNotifyReceived implements the stopnotifyreceived command extension
  1568  // for websocket connections.
  1569  func handleStopNotifyReceived(wsc *wsClient, icmd interface{}) (interface{}, error) {
  1570  	cmd, ok := icmd.(*btcjson.StopNotifyReceivedCmd)
  1571  	if !ok {
  1572  		return nil, btcjson.ErrRPCInternal
  1573  	}
  1574  
  1575  	// Decode addresses to validate input, but the strings slice is used
  1576  	// directly if these are all ok.
  1577  	err := checkAddressValidity(cmd.Addresses)
  1578  	if err != nil {
  1579  		return nil, err
  1580  	}
  1581  
  1582  	for _, addr := range cmd.Addresses {
  1583  		wsc.server.ntfnMgr.UnregisterTxOutAddressRequest(wsc, addr)
  1584  	}
  1585  
  1586  	return nil, nil
  1587  }
  1588  
  1589  // checkAddressValidity checks the validity of each address in the passed
  1590  // string slice. It does this by attempting to decode each address using the
  1591  // current active network parameters. If any single address fails to decode
  1592  // properly, the function returns an error. Otherwise, nil is returned.
  1593  func checkAddressValidity(addrs []string) error {
  1594  	for _, addr := range addrs {
  1595  		_, err := godashutil.DecodeAddress(addr, activeNetParams.Params)
  1596  		if err != nil {
  1597  			return &btcjson.RPCError{
  1598  				Code: btcjson.ErrRPCInvalidAddressOrKey,
  1599  				Message: fmt.Sprintf("Invalid address or key: %v",
  1600  					addr),
  1601  			}
  1602  		}
  1603  	}
  1604  	return nil
  1605  }
  1606  
  1607  // deserializeOutpoints deserializes each serialized outpoint.
  1608  func deserializeOutpoints(serializedOuts []btcjson.OutPoint) ([]*wire.OutPoint, error) {
  1609  	outpoints := make([]*wire.OutPoint, 0, len(serializedOuts))
  1610  	for i := range serializedOuts {
  1611  		blockHash, err := wire.NewShaHashFromStr(serializedOuts[i].Hash)
  1612  		if err != nil {
  1613  			return nil, rpcDecodeHexError(serializedOuts[i].Hash)
  1614  		}
  1615  		index := serializedOuts[i].Index
  1616  		outpoints = append(outpoints, wire.NewOutPoint(blockHash, index))
  1617  	}
  1618  
  1619  	return outpoints, nil
  1620  }
  1621  
  1622  type rescanKeys struct {
  1623  	fallbacks           map[string]struct{}
  1624  	pubKeyHashes        map[[ripemd160.Size]byte]struct{}
  1625  	scriptHashes        map[[ripemd160.Size]byte]struct{}
  1626  	compressedPubKeys   map[[33]byte]struct{}
  1627  	uncompressedPubKeys map[[65]byte]struct{}
  1628  	unspent             map[wire.OutPoint]struct{}
  1629  }
  1630  
  1631  // unspentSlice returns a slice of currently-unspent outpoints for the rescan
  1632  // lookup keys.  This is primarily intended to be used to register outpoints
  1633  // for continuous notifications after a rescan has completed.
  1634  func (r *rescanKeys) unspentSlice() []*wire.OutPoint {
  1635  	ops := make([]*wire.OutPoint, 0, len(r.unspent))
  1636  	for op := range r.unspent {
  1637  		opCopy := op
  1638  		ops = append(ops, &opCopy)
  1639  	}
  1640  	return ops
  1641  }
  1642  
  1643  // ErrRescanReorg defines the error that is returned when an unrecoverable
  1644  // reorganize is detected during a rescan.
  1645  var ErrRescanReorg = btcjson.RPCError{
  1646  	Code:    btcjson.ErrRPCDatabase,
  1647  	Message: "Reorganize",
  1648  }
  1649  
  1650  // rescanBlock rescans all transactions in a single block.  This is a helper
  1651  // function for handleRescan.
  1652  func rescanBlock(wsc *wsClient, lookups *rescanKeys, blk *godashutil.Block) {
  1653  	for _, tx := range blk.Transactions() {
  1654  		// Hexadecimal representation of this tx.  Only created if
  1655  		// needed, and reused for later notifications if already made.
  1656  		var txHex string
  1657  
  1658  		// All inputs and outputs must be iterated through to correctly
  1659  		// modify the unspent map, however, just a single notification
  1660  		// for any matching transaction inputs or outputs should be
  1661  		// created and sent.
  1662  		spentNotified := false
  1663  		recvNotified := false
  1664  
  1665  		for _, txin := range tx.MsgTx().TxIn {
  1666  			if _, ok := lookups.unspent[txin.PreviousOutPoint]; ok {
  1667  				delete(lookups.unspent, txin.PreviousOutPoint)
  1668  
  1669  				if spentNotified {
  1670  					continue
  1671  				}
  1672  
  1673  				if txHex == "" {
  1674  					txHex = txHexString(tx)
  1675  				}
  1676  				marshalledJSON, err := newRedeemingTxNotification(txHex, tx.Index(), blk)
  1677  				if err != nil {
  1678  					rpcsLog.Errorf("Failed to marshal redeemingtx notification: %v", err)
  1679  					continue
  1680  				}
  1681  
  1682  				err = wsc.QueueNotification(marshalledJSON)
  1683  				// Stop the rescan early if the websocket client
  1684  				// disconnected.
  1685  				if err == ErrClientQuit {
  1686  					return
  1687  				}
  1688  				spentNotified = true
  1689  			}
  1690  		}
  1691  
  1692  		for txOutIdx, txout := range tx.MsgTx().TxOut {
  1693  			_, addrs, _, _ := txscript.ExtractPkScriptAddrs(
  1694  				txout.PkScript, wsc.server.server.chainParams)
  1695  
  1696  			for _, addr := range addrs {
  1697  				switch a := addr.(type) {
  1698  				case *godashutil.AddressPubKeyHash:
  1699  					if _, ok := lookups.pubKeyHashes[*a.Hash160()]; !ok {
  1700  						continue
  1701  					}
  1702  
  1703  				case *godashutil.AddressScriptHash:
  1704  					if _, ok := lookups.scriptHashes[*a.Hash160()]; !ok {
  1705  						continue
  1706  					}
  1707  
  1708  				case *godashutil.AddressPubKey:
  1709  					found := false
  1710  					switch sa := a.ScriptAddress(); len(sa) {
  1711  					case 33: // Compressed
  1712  						var key [33]byte
  1713  						copy(key[:], sa)
  1714  						if _, ok := lookups.compressedPubKeys[key]; ok {
  1715  							found = true
  1716  						}
  1717  
  1718  					case 65: // Uncompressed
  1719  						var key [65]byte
  1720  						copy(key[:], sa)
  1721  						if _, ok := lookups.uncompressedPubKeys[key]; ok {
  1722  							found = true
  1723  						}
  1724  
  1725  					default:
  1726  						rpcsLog.Warnf("Skipping rescanned pubkey of unknown "+
  1727  							"serialized length %d", len(sa))
  1728  						continue
  1729  					}
  1730  
  1731  					// If the transaction output pays to the pubkey of
  1732  					// a rescanned P2PKH address, include it as well.
  1733  					if !found {
  1734  						pkh := a.AddressPubKeyHash()
  1735  						if _, ok := lookups.pubKeyHashes[*pkh.Hash160()]; !ok {
  1736  							continue
  1737  						}
  1738  					}
  1739  
  1740  				default:
  1741  					// A new address type must have been added.  Encode as a
  1742  					// payment address string and check the fallback map.
  1743  					addrStr := addr.EncodeAddress()
  1744  					_, ok := lookups.fallbacks[addrStr]
  1745  					if !ok {
  1746  						continue
  1747  					}
  1748  				}
  1749  
  1750  				outpoint := wire.OutPoint{
  1751  					Hash:  *tx.Sha(),
  1752  					Index: uint32(txOutIdx),
  1753  				}
  1754  				lookups.unspent[outpoint] = struct{}{}
  1755  
  1756  				if recvNotified {
  1757  					continue
  1758  				}
  1759  
  1760  				if txHex == "" {
  1761  					txHex = txHexString(tx)
  1762  				}
  1763  				ntfn := btcjson.NewRecvTxNtfn(txHex,
  1764  					blockDetails(blk, tx.Index()))
  1765  
  1766  				marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn)
  1767  				if err != nil {
  1768  					rpcsLog.Errorf("Failed to marshal recvtx notification: %v", err)
  1769  					return
  1770  				}
  1771  
  1772  				err = wsc.QueueNotification(marshalledJSON)
  1773  				// Stop the rescan early if the websocket client
  1774  				// disconnected.
  1775  				if err == ErrClientQuit {
  1776  					return
  1777  				}
  1778  				recvNotified = true
  1779  			}
  1780  		}
  1781  	}
  1782  }
  1783  
  1784  // recoverFromReorg attempts to recover from a detected reorganize during a
  1785  // rescan.  It fetches a new range of block shas from the database and
  1786  // verifies that the new range of blocks is on the same fork as a previous
  1787  // range of blocks.  If this condition does not hold true, the JSON-RPC error
  1788  // for an unrecoverable reorganize is returned.
  1789  func recoverFromReorg(chain *blockchain.BlockChain, minBlock, maxBlock int32,
  1790  	lastBlock *wire.ShaHash) ([]wire.ShaHash, error) {
  1791  
  1792  	hashList, err := chain.HeightRange(minBlock, maxBlock)
  1793  	if err != nil {
  1794  		rpcsLog.Errorf("Error looking up block range: %v", err)
  1795  		return nil, &btcjson.RPCError{
  1796  			Code:    btcjson.ErrRPCDatabase,
  1797  			Message: "Database error: " + err.Error(),
  1798  		}
  1799  	}
  1800  	if lastBlock == nil || len(hashList) == 0 {
  1801  		return hashList, nil
  1802  	}
  1803  
  1804  	blk, err := chain.BlockByHash(&hashList[0])
  1805  	if err != nil {
  1806  		rpcsLog.Errorf("Error looking up possibly reorged block: %v",
  1807  			err)
  1808  		return nil, &btcjson.RPCError{
  1809  			Code:    btcjson.ErrRPCDatabase,
  1810  			Message: "Database error: " + err.Error(),
  1811  		}
  1812  	}
  1813  	jsonErr := descendantBlock(lastBlock, blk)
  1814  	if jsonErr != nil {
  1815  		return nil, jsonErr
  1816  	}
  1817  	return hashList, nil
  1818  }
  1819  
  1820  // descendantBlock returns the appropriate JSON-RPC error if a current block
  1821  // fetched during a reorganize is not a direct child of the parent block hash.
  1822  func descendantBlock(prevHash *wire.ShaHash, curBlock *godashutil.Block) error {
  1823  	curHash := &curBlock.MsgBlock().Header.PrevBlock
  1824  	if !prevHash.IsEqual(curHash) {
  1825  		rpcsLog.Errorf("Stopping rescan for reorged block %v "+
  1826  			"(replaced by block %v)", prevHash, curHash)
  1827  		return &ErrRescanReorg
  1828  	}
  1829  	return nil
  1830  }
  1831  
  1832  // handleRescan implements the rescan command extension for websocket
  1833  // connections.
  1834  //
  1835  // NOTE: This does not smartly handle reorgs, and fixing requires database
  1836  // changes (for safe, concurrent access to full block ranges, and support
  1837  // for other chains than the best chain).  It will, however, detect whether
  1838  // a reorg removed a block that was previously processed, and result in the
  1839  // handler erroring.  Clients must handle this by finding a block still in
  1840  // the chain (perhaps from a rescanprogress notification) to resume their
  1841  // rescan.
  1842  func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) {
  1843  	cmd, ok := icmd.(*btcjson.RescanCmd)
  1844  	if !ok {
  1845  		return nil, btcjson.ErrRPCInternal
  1846  	}
  1847  
  1848  	outpoints := make([]*wire.OutPoint, 0, len(cmd.OutPoints))
  1849  	for i := range cmd.OutPoints {
  1850  		cmdOutpoint := &cmd.OutPoints[i]
  1851  		blockHash, err := wire.NewShaHashFromStr(cmdOutpoint.Hash)
  1852  		if err != nil {
  1853  			return nil, rpcDecodeHexError(cmdOutpoint.Hash)
  1854  		}
  1855  		outpoint := wire.NewOutPoint(blockHash, cmdOutpoint.Index)
  1856  		outpoints = append(outpoints, outpoint)
  1857  	}
  1858  
  1859  	numAddrs := len(cmd.Addresses)
  1860  	if numAddrs == 1 {
  1861  		rpcsLog.Info("Beginning rescan for 1 address")
  1862  	} else {
  1863  		rpcsLog.Infof("Beginning rescan for %d addresses", numAddrs)
  1864  	}
  1865  
  1866  	// Build lookup maps.
  1867  	lookups := rescanKeys{
  1868  		fallbacks:           map[string]struct{}{},
  1869  		pubKeyHashes:        map[[ripemd160.Size]byte]struct{}{},
  1870  		scriptHashes:        map[[ripemd160.Size]byte]struct{}{},
  1871  		compressedPubKeys:   map[[33]byte]struct{}{},
  1872  		uncompressedPubKeys: map[[65]byte]struct{}{},
  1873  		unspent:             map[wire.OutPoint]struct{}{},
  1874  	}
  1875  	var compressedPubkey [33]byte
  1876  	var uncompressedPubkey [65]byte
  1877  	for _, addrStr := range cmd.Addresses {
  1878  		addr, err := godashutil.DecodeAddress(addrStr, activeNetParams.Params)
  1879  		if err != nil {
  1880  			jsonErr := btcjson.RPCError{
  1881  				Code: btcjson.ErrRPCInvalidAddressOrKey,
  1882  				Message: "Rescan address " + addrStr + ": " +
  1883  					err.Error(),
  1884  			}
  1885  			return nil, &jsonErr
  1886  		}
  1887  		switch a := addr.(type) {
  1888  		case *godashutil.AddressPubKeyHash:
  1889  			lookups.pubKeyHashes[*a.Hash160()] = struct{}{}
  1890  
  1891  		case *godashutil.AddressScriptHash:
  1892  			lookups.scriptHashes[*a.Hash160()] = struct{}{}
  1893  
  1894  		case *godashutil.AddressPubKey:
  1895  			pubkeyBytes := a.ScriptAddress()
  1896  			switch len(pubkeyBytes) {
  1897  			case 33: // Compressed
  1898  				copy(compressedPubkey[:], pubkeyBytes)
  1899  				lookups.compressedPubKeys[compressedPubkey] = struct{}{}
  1900  
  1901  			case 65: // Uncompressed
  1902  				copy(uncompressedPubkey[:], pubkeyBytes)
  1903  				lookups.uncompressedPubKeys[uncompressedPubkey] = struct{}{}
  1904  
  1905  			default:
  1906  				jsonErr := btcjson.RPCError{
  1907  					Code:    btcjson.ErrRPCInvalidAddressOrKey,
  1908  					Message: "Pubkey " + addrStr + " is of unknown length",
  1909  				}
  1910  				return nil, &jsonErr
  1911  			}
  1912  
  1913  		default:
  1914  			// A new address type must have been added.  Use encoded
  1915  			// payment address string as a fallback until a fast path
  1916  			// is added.
  1917  			lookups.fallbacks[addrStr] = struct{}{}
  1918  		}
  1919  	}
  1920  	for _, outpoint := range outpoints {
  1921  		lookups.unspent[*outpoint] = struct{}{}
  1922  	}
  1923  
  1924  	chain := wsc.server.chain
  1925  
  1926  	minBlockHash, err := wire.NewShaHashFromStr(cmd.BeginBlock)
  1927  	if err != nil {
  1928  		return nil, rpcDecodeHexError(cmd.BeginBlock)
  1929  	}
  1930  	minBlock, err := chain.BlockHeightByHash(minBlockHash)
  1931  	if err != nil {
  1932  		return nil, &btcjson.RPCError{
  1933  			Code:    btcjson.ErrRPCBlockNotFound,
  1934  			Message: "Error getting block: " + err.Error(),
  1935  		}
  1936  	}
  1937  
  1938  	maxBlock := int32(math.MaxInt32)
  1939  	if cmd.EndBlock != nil {
  1940  		maxBlockHash, err := wire.NewShaHashFromStr(*cmd.EndBlock)
  1941  		if err != nil {
  1942  			return nil, rpcDecodeHexError(*cmd.EndBlock)
  1943  		}
  1944  		maxBlock, err = chain.BlockHeightByHash(maxBlockHash)
  1945  		if err != nil {
  1946  			return nil, &btcjson.RPCError{
  1947  				Code:    btcjson.ErrRPCBlockNotFound,
  1948  				Message: "Error getting block: " + err.Error(),
  1949  			}
  1950  		}
  1951  	}
  1952  
  1953  	// lastBlock and lastBlockHash track the previously-rescanned block.
  1954  	// They equal nil when no previous blocks have been rescanned.
  1955  	var lastBlock *godashutil.Block
  1956  	var lastBlockHash *wire.ShaHash
  1957  
  1958  	// A ticker is created to wait at least 10 seconds before notifying the
  1959  	// websocket client of the current progress completed by the rescan.
  1960  	ticker := time.NewTicker(10 * time.Second)
  1961  	defer ticker.Stop()
  1962  
  1963  	// Instead of fetching all block shas at once, fetch in smaller chunks
  1964  	// to ensure large rescans consume a limited amount of memory.
  1965  fetchRange:
  1966  	for minBlock < maxBlock {
  1967  		// Limit the max number of hashes to fetch at once to the
  1968  		// maximum number of items allowed in a single inventory.
  1969  		// This value could be higher since it's not creating inventory
  1970  		// messages, but this mirrors the limiting logic used in the
  1971  		// peer-to-peer protocol.
  1972  		maxLoopBlock := maxBlock
  1973  		if maxLoopBlock-minBlock > wire.MaxInvPerMsg {
  1974  			maxLoopBlock = minBlock + wire.MaxInvPerMsg
  1975  		}
  1976  		hashList, err := chain.HeightRange(minBlock, maxLoopBlock)
  1977  		if err != nil {
  1978  			rpcsLog.Errorf("Error looking up block range: %v", err)
  1979  			return nil, &btcjson.RPCError{
  1980  				Code:    btcjson.ErrRPCDatabase,
  1981  				Message: "Database error: " + err.Error(),
  1982  			}
  1983  		}
  1984  		if len(hashList) == 0 {
  1985  			// The rescan is finished if no blocks hashes for this
  1986  			// range were successfully fetched and a stop block
  1987  			// was provided.
  1988  			if maxBlock != math.MaxInt32 {
  1989  				break
  1990  			}
  1991  
  1992  			// If the rescan is through the current block, set up
  1993  			// the client to continue to receive notifications
  1994  			// regarding all rescanned addresses and the current set
  1995  			// of unspent outputs.
  1996  			//
  1997  			// This is done safely by temporarily grabbing exclusive
  1998  			// access of the block manager.  If no more blocks have
  1999  			// been attached between this pause and the fetch above,
  2000  			// then it is safe to register the websocket client for
  2001  			// continuous notifications if necessary.  Otherwise,
  2002  			// continue the fetch loop again to rescan the new
  2003  			// blocks (or error due to an irrecoverable reorganize).
  2004  			blockManager := wsc.server.server.blockManager
  2005  			pauseGuard := blockManager.Pause()
  2006  			best := blockManager.chain.BestSnapshot()
  2007  			curHash := best.Hash
  2008  			again := true
  2009  			if lastBlockHash == nil || *lastBlockHash == *curHash {
  2010  				again = false
  2011  				n := wsc.server.ntfnMgr
  2012  				n.RegisterSpentRequests(wsc, lookups.unspentSlice())
  2013  				n.RegisterTxOutAddressRequests(wsc, cmd.Addresses)
  2014  			}
  2015  			close(pauseGuard)
  2016  			if err != nil {
  2017  				rpcsLog.Errorf("Error fetching best block "+
  2018  					"hash: %v", err)
  2019  				return nil, &btcjson.RPCError{
  2020  					Code: btcjson.ErrRPCDatabase,
  2021  					Message: "Database error: " +
  2022  						err.Error(),
  2023  				}
  2024  			}
  2025  			if again {
  2026  				continue
  2027  			}
  2028  			break
  2029  		}
  2030  
  2031  	loopHashList:
  2032  		for i := range hashList {
  2033  			blk, err := chain.BlockByHash(&hashList[i])
  2034  			if err != nil {
  2035  				// Only handle reorgs if a block could not be
  2036  				// found for the hash.
  2037  				if dbErr, ok := err.(database.Error); !ok ||
  2038  					dbErr.ErrorCode != database.ErrBlockNotFound {
  2039  
  2040  					rpcsLog.Errorf("Error looking up "+
  2041  						"block: %v", err)
  2042  					return nil, &btcjson.RPCError{
  2043  						Code: btcjson.ErrRPCDatabase,
  2044  						Message: "Database error: " +
  2045  							err.Error(),
  2046  					}
  2047  				}
  2048  
  2049  				// If an absolute max block was specified, don't
  2050  				// attempt to handle the reorg.
  2051  				if maxBlock != math.MaxInt32 {
  2052  					rpcsLog.Errorf("Stopping rescan for "+
  2053  						"reorged block %v",
  2054  						cmd.EndBlock)
  2055  					return nil, &ErrRescanReorg
  2056  				}
  2057  
  2058  				// If the lookup for the previously valid block
  2059  				// hash failed, there may have been a reorg.
  2060  				// Fetch a new range of block hashes and verify
  2061  				// that the previously processed block (if there
  2062  				// was any) still exists in the database.  If it
  2063  				// doesn't, we error.
  2064  				//
  2065  				// A goto is used to branch executation back to
  2066  				// before the range was evaluated, as it must be
  2067  				// reevaluated for the new hashList.
  2068  				minBlock += int32(i)
  2069  				hashList, err = recoverFromReorg(chain,
  2070  					minBlock, maxBlock, lastBlockHash)
  2071  				if err != nil {
  2072  					return nil, err
  2073  				}
  2074  				if len(hashList) == 0 {
  2075  					break fetchRange
  2076  				}
  2077  				goto loopHashList
  2078  			}
  2079  			if i == 0 && lastBlockHash != nil {
  2080  				// Ensure the new hashList is on the same fork
  2081  				// as the last block from the old hashList.
  2082  				jsonErr := descendantBlock(lastBlockHash, blk)
  2083  				if jsonErr != nil {
  2084  					return nil, jsonErr
  2085  				}
  2086  			}
  2087  
  2088  			// A select statement is used to stop rescans if the
  2089  			// client requesting the rescan has disconnected.
  2090  			select {
  2091  			case <-wsc.quit:
  2092  				rpcsLog.Debugf("Stopped rescan at height %v "+
  2093  					"for disconnected client", blk.Height())
  2094  				return nil, nil
  2095  			default:
  2096  				rescanBlock(wsc, &lookups, blk)
  2097  				lastBlock = blk
  2098  				lastBlockHash = blk.Sha()
  2099  			}
  2100  
  2101  			// Periodically notify the client of the progress
  2102  			// completed.  Continue with next block if no progress
  2103  			// notification is needed yet.
  2104  			select {
  2105  			case <-ticker.C: // fallthrough
  2106  			default:
  2107  				continue
  2108  			}
  2109  
  2110  			n := btcjson.NewRescanProgressNtfn(hashList[i].String(),
  2111  				int32(blk.Height()),
  2112  				blk.MsgBlock().Header.Timestamp.Unix())
  2113  			mn, err := btcjson.MarshalCmd(nil, n)
  2114  			if err != nil {
  2115  				rpcsLog.Errorf("Failed to marshal rescan "+
  2116  					"progress notification: %v", err)
  2117  				continue
  2118  			}
  2119  
  2120  			if err = wsc.QueueNotification(mn); err == ErrClientQuit {
  2121  				// Finished if the client disconnected.
  2122  				rpcsLog.Debugf("Stopped rescan at height %v "+
  2123  					"for disconnected client", blk.Height())
  2124  				return nil, nil
  2125  			}
  2126  		}
  2127  
  2128  		minBlock += int32(len(hashList))
  2129  	}
  2130  
  2131  	// Notify websocket client of the finished rescan.  Due to how btcd
  2132  	// asynchronously queues notifications to not block calling code,
  2133  	// there is no guarantee that any of the notifications created during
  2134  	// rescan (such as rescanprogress, recvtx and redeemingtx) will be
  2135  	// received before the rescan RPC returns.  Therefore, another method
  2136  	// is needed to safely inform clients that all rescan notifications have
  2137  	// been sent.
  2138  	n := btcjson.NewRescanFinishedNtfn(lastBlockHash.String(),
  2139  		lastBlock.Height(),
  2140  		lastBlock.MsgBlock().Header.Timestamp.Unix())
  2141  	if mn, err := btcjson.MarshalCmd(nil, n); err != nil {
  2142  		rpcsLog.Errorf("Failed to marshal rescan finished "+
  2143  			"notification: %v", err)
  2144  	} else {
  2145  		// The rescan is finished, so we don't care whether the client
  2146  		// has disconnected at this point, so discard error.
  2147  		_ = wsc.QueueNotification(mn)
  2148  	}
  2149  
  2150  	rpcsLog.Info("Finished rescan")
  2151  	return nil, nil
  2152  }
  2153  
  2154  func init() {
  2155  	wsHandlers = wsHandlersBeforeInit
  2156  }