// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"crypto/subtle"
	"crypto/tls"
	"encoding/base64"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math/big"
	"math/rand"
	"net"
	"net/http"
	"os"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/btcsuite/btcchain"
	"github.com/btcsuite/btcd/database"
	"github.com/btcsuite/btcec"
	"github.com/btcsuite/btcjson"
	"github.com/btcsuite/btcnet"
	"github.com/btcsuite/btcscript"
	"github.com/btcsuite/btcutil"
	"github.com/btcsuite/btcwire"
	"github.com/btcsuite/btcws"
	"github.com/btcsuite/fastsha256"
	"github.com/btcsuite/websocket"
)

const (
	// rpcAuthTimeoutSeconds is the number of seconds a connection to the
	// RPC server is allowed to stay open without authenticating before it
	// is closed.
	rpcAuthTimeoutSeconds = 10

	// uint256Size is the number of bytes needed to represent an unsigned
	// 256-bit integer.
	uint256Size = 32

	// getworkDataLen is the length of the data field of the getwork RPC.
	// It consists of the serialized block header plus the internal sha256
	// padding.  The internal sha256 padding consists of a single 1 bit
	// followed by enough zeros to pad the message out to 56 bytes followed
	// by length of the message in bits encoded as a big-endian uint64
	// (8 bytes).  Thus, the resulting length is a multiple of the sha256
	// block size (64 bytes).
	getworkDataLen = (1 + ((btcwire.MaxBlockHeaderPayload + 8) /
		fastsha256.BlockSize)) * fastsha256.BlockSize

	// hash1Len is the length of the hash1 field of the getwork RPC.  It
	// consists of a zero hash plus the internal sha256 padding.  See
	// the getworkDataLen comment for details about the internal sha256
	// padding format.
	hash1Len = (1 + ((btcwire.HashSize + 8) / fastsha256.BlockSize)) *
		fastsha256.BlockSize

	// gbtNonceRange is two 32-bit big-endian hexadecimal integers which
	// represent the valid ranges of nonces returned by the getblocktemplate
	// RPC.
	gbtNonceRange = "00000000ffffffff"

	// gbtRegenerateSeconds is the number of seconds that must pass before
	// a new template is generated when the previous block hash has not
	// changed and there have been changes to the available transactions
	// in the memory pool.
	gbtRegenerateSeconds = 60
)

var (
	// gbtMutableFields are the manipulations the server allows to be made
	// to block templates generated by the getblocktemplate RPC.  It is
	// declared here to avoid the overhead of creating the slice on every
	// invocation for constant data.
	gbtMutableFields = []string{
		"time", "transactions/add", "prevblock", "coinbase/append",
	}

	// gbtCoinbaseAux describes additional data that miners should include
	// in the coinbase signature script.  It is declared here to avoid the
	// overhead of creating a new object on every invocation for constant
	// data.
	gbtCoinbaseAux = &btcjson.GetBlockTemplateResultAux{
		Flags: hex.EncodeToString(builderScript(btcscript.
			NewScriptBuilder().AddData([]byte(coinbaseFlags)))),
	}

	// gbtCapabilities describes additional capabilities returned with a
	// block template generated by the getblocktemplate RPC.    It is
	// declared here to avoid the overhead of creating the slice on every
	// invocation for constant data.
	gbtCapabilities = []string{"proposal"}
)

// Errors
var (
	// ErrBadParamsField describes an error where the parameters JSON
	// field cannot be properly parsed.
	ErrBadParamsField = errors.New("bad params field")
)

type commandHandler func(*rpcServer, btcjson.Cmd, <-chan struct{}) (interface{}, error)

// handlers maps RPC command strings to appropriate handler functions.
// this is copied by init because help references rpcHandlers and thus causes
// a dependancy loop.
var rpcHandlers map[string]commandHandler
var rpcHandlersBeforeInit = map[string]commandHandler{
	"addnode":              handleAddNode,
	"createrawtransaction": handleCreateRawTransaction,
	"debuglevel":           handleDebugLevel,
	"decoderawtransaction": handleDecodeRawTransaction,
	"decodescript":         handleDecodeScript,
	"estimatefee":          handleUnimplemented,
	"estimatepriority":     handleUnimplemented,
	"getaddednodeinfo":     handleGetAddedNodeInfo,
	"getbestblock":         handleGetBestBlock,
	"getbestblockhash":     handleGetBestBlockHash,
	"getblock":             handleGetBlock,
	"getblockchaininfo":    handleUnimplemented,
	"getblockcount":        handleGetBlockCount,
	"getblockhash":         handleGetBlockHash,
	"getblocktemplate":     handleGetBlockTemplate,
	"getchaintips":         handleUnimplemented,
	"getconnectioncount":   handleGetConnectionCount,
	"getcurrentnet":        handleGetCurrentNet,
	"getdifficulty":        handleGetDifficulty,
	"getgenerate":          handleGetGenerate,
	"gethashespersec":      handleGetHashesPerSec,
	"getinfo":              handleGetInfo,
	"getmininginfo":        handleGetMiningInfo,
	"getnettotals":         handleGetNetTotals,
	"getnetworkhashps":     handleGetNetworkHashPS,
	"getnetworkinfo":       handleUnimplemented,
	"getpeerinfo":          handleGetPeerInfo,
	"getrawmempool":        handleGetRawMempool,
	"getrawtransaction":    handleGetRawTransaction,
	"gettxout":             handleGetTxOut,
	"getwork":              handleGetWork,
	"help":                 handleHelp,
	"ping":                 handlePing,
	"sendrawtransaction":   handleSendRawTransaction,
	"setgenerate":          handleSetGenerate,
	"stop":                 handleStop,
	"submitblock":          handleSubmitBlock,
	"validateaddress":      handleValidateAddress,
	"verifychain":          handleVerifyChain,
	"verifymessage":        handleVerifyMessage,
}

// list of commands that we recognise, but for which btcd has no support because
// it lacks support for wallet functionality. For these commands the user
// should ask a connected instance of btcwallet.
var rpcAskWallet = map[string]struct{}{
	"addmultisigaddress":     struct{}{},
	"backupwallet":           struct{}{},
	"createencryptedwallet":  struct{}{},
	"createmultisig":         struct{}{},
	"dumpprivkey":            struct{}{},
	"dumpwallet":             struct{}{},
	"encryptwallet":          struct{}{},
	"getaccount":             struct{}{},
	"getaccountaddress":      struct{}{},
	"getaddressesbyaccount":  struct{}{},
	"getbalance":             struct{}{},
	"getnewaddress":          struct{}{},
	"getrawchangeaddress":    struct{}{},
	"getreceivedbyaccount":   struct{}{},
	"getreceivedbyaddress":   struct{}{},
	"gettransaction":         struct{}{},
	"gettxoutsetinfo":        struct{}{},
	"getunconfirmedbalance":  struct{}{},
	"getwalletinfo":          struct{}{},
	"importprivkey":          struct{}{},
	"importwallet":           struct{}{},
	"keypoolrefill":          struct{}{},
	"listaccounts":           struct{}{},
	"listaddressgroupings":   struct{}{},
	"listlockunspent":        struct{}{},
	"listreceivedbyaccount":  struct{}{},
	"listreceivedbyaddress":  struct{}{},
	"listsinceblock":         struct{}{},
	"listtransactions":       struct{}{},
	"listunspent":            struct{}{},
	"lockunspent":            struct{}{},
	"move":                   struct{}{},
	"sendfrom":               struct{}{},
	"sendmany":               struct{}{},
	"sendtoaddress":          struct{}{},
	"setaccount":             struct{}{},
	"settxfee":               struct{}{},
	"signmessage":            struct{}{},
	"signrawtransaction":     struct{}{},
	"walletlock":             struct{}{},
	"walletpassphrase":       struct{}{},
	"walletpassphrasechange": struct{}{},
}

// Commands that are temporarily unimplemented.
var rpcUnimplemented = map[string]struct{}{}

// builderScript is a convenience function which is used to for hard-coded
// scripts built with the script builder.   Any errors are converted to a panic
// since it is only, and must only, be used with hard-coded, and therefore,
// known good, scripts.
func builderScript(builder *btcscript.ScriptBuilder) []byte {
	script, err := builder.Script()
	if err != nil {
		panic(err)
	}
	return script
}

// workStateBlockInfo houses information about how to reconstruct a block given
// its template and signature script.
type workStateBlockInfo struct {
	msgBlock        *btcwire.MsgBlock
	signatureScript []byte
}

// workState houses state that is used in between multiple RPC invocations to
// getwork.
type workState struct {
	sync.Mutex
	lastTxUpdate  time.Time
	lastGenerated time.Time
	prevHash      *btcwire.ShaHash
	msgBlock      *btcwire.MsgBlock
	extraNonce    uint64
	blockInfo     map[btcwire.ShaHash]*workStateBlockInfo
}

// newWorkState returns a new instance of a workState with all internal fields
// initialized and ready to use.
func newWorkState() *workState {
	return &workState{
		blockInfo: make(map[btcwire.ShaHash]*workStateBlockInfo),
	}
}

// gbtWorkState houses state that is used in between multiple RPC invocations to
// getblocktemplate.
type gbtWorkState struct {
	sync.Mutex
	lastTxUpdate  time.Time
	lastGenerated time.Time
	prevHash      *btcwire.ShaHash
	minTimestamp  time.Time
	template      *BlockTemplate
	notifyMap     map[btcwire.ShaHash]map[int64]chan struct{}
	timeSource    btcchain.MedianTimeSource
}

// newGbtWorkState returns a new instance of a gbtWorkState with all internal
// fields initialized and ready to use.
func newGbtWorkState(timeSource btcchain.MedianTimeSource) *gbtWorkState {
	return &gbtWorkState{
		notifyMap:  make(map[btcwire.ShaHash]map[int64]chan struct{}),
		timeSource: timeSource,
	}
}

// rpcServer holds the items the rpc server may need to access (config,
// shutdown, main server, etc.)
type rpcServer struct {
	started      int32
	shutdown     int32
	server       *server
	authsha      [fastsha256.Size]byte
	ntfnMgr      *wsNotificationManager
	numClients   int32
	statusLines  map[int]string
	statusLock   sync.RWMutex
	wg           sync.WaitGroup
	listeners    []net.Listener
	workState    *workState
	gbtWorkState *gbtWorkState
	quit         chan int
}

// Start is used by server.go to start the rpc listener.
func (s *rpcServer) Start() {
	if atomic.AddInt32(&s.started, 1) != 1 {
		return
	}

	rpcsLog.Trace("Starting RPC server")
	rpcServeMux := http.NewServeMux()
	httpServer := &http.Server{
		Handler: rpcServeMux,

		// Timeout connections which don't complete the initial
		// handshake within the allowed timeframe.
		ReadTimeout: time.Second * rpcAuthTimeoutSeconds,
	}
	rpcServeMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Connection", "close")
		w.Header().Set("Content-Type", "application/json")
		r.Close = true

		// Limit the number of connections to max allowed.
		if s.limitConnections(w, r.RemoteAddr) {
			return
		}

		// Keep track of the number of connected clients.
		s.incrementClients()
		defer s.decrementClients()
		if _, err := s.checkAuth(r, true); err != nil {
			jsonAuthFail(w, r, s)
			return
		}
		jsonRPCRead(w, r, s)
	})

	// Websocket endpoint.
	rpcServeMux.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
		authenticated, err := s.checkAuth(r, false)
		if err != nil {
			http.Error(w, "401 Unauthorized.", http.StatusUnauthorized)
			return
		}

		// Attempt to upgrade the connection to a websocket connection
		// using the default size for read/write buffers.
		ws, err := websocket.Upgrade(w, r, nil, 0, 0)
		if err != nil {
			if _, ok := err.(websocket.HandshakeError); !ok {
				rpcsLog.Errorf("Unexpected websocket error: %v",
					err)
			}
			return
		}
		s.WebsocketHandler(ws, r.RemoteAddr, authenticated)
	})

	for _, listener := range s.listeners {
		s.wg.Add(1)
		go func(listener net.Listener) {
			rpcsLog.Infof("RPC server listening on %s", listener.Addr())
			httpServer.Serve(listener)
			rpcsLog.Tracef("RPC listener done for %s", listener.Addr())
			s.wg.Done()
		}(listener)
	}

	s.ntfnMgr.Start()
}

// httpStatusLine returns a response Status-Line (RFC 2616 Section 6.1)
// for the given request and response status code.  This function was lifted and
// adapted from the standard library HTTP server code since it's not exported.
func (s *rpcServer) httpStatusLine(req *http.Request, code int) string {
	// Fast path:
	key := code
	proto11 := req.ProtoAtLeast(1, 1)
	if !proto11 {
		key = -key
	}
	s.statusLock.RLock()
	line, ok := s.statusLines[key]
	s.statusLock.RUnlock()
	if ok {
		return line
	}

	// Slow path:
	proto := "HTTP/1.0"
	if proto11 {
		proto = "HTTP/1.1"
	}
	codeStr := strconv.Itoa(code)
	text := http.StatusText(code)
	if text != "" {
		line = proto + " " + codeStr + " " + text + "\r\n"
		s.statusLock.Lock()
		s.statusLines[key] = line
		s.statusLock.Unlock()
	} else {
		text = "status code " + codeStr
		line = proto + " " + codeStr + " " + text + "\r\n"
	}

	return line
}

// writeHTTPResponseHeaders writes the necessary response headers prior to
// writing an HTTP body given a request to use for protocol negotiation, headers
// to write, a status code, and a writer.
func (s *rpcServer) writeHTTPResponseHeaders(req *http.Request, headers http.Header, code int, w io.Writer) error {
	_, err := io.WriteString(w, s.httpStatusLine(req, code))
	if err != nil {
		return err
	}

	err = headers.Write(w)
	if err != nil {
		return err
	}

	_, err = io.WriteString(w, "\r\n")
	if err != nil {
		return err
	}

	return nil
}

// limitConnections responds with a 503 service unavailable and returns true if
// adding another client would exceed the maximum allow RPC clients.
//
// This function is safe for concurrent access.
func (s *rpcServer) limitConnections(w http.ResponseWriter, remoteAddr string) bool {
	if int(atomic.LoadInt32(&s.numClients)+1) > cfg.RPCMaxClients {
		rpcsLog.Infof("Max RPC clients exceeded [%d] - "+
			"disconnecting client %s", cfg.RPCMaxClients,
			remoteAddr)
		http.Error(w, "503 Too busy.  Try again later.",
			http.StatusServiceUnavailable)
		return true
	}
	return false
}

// incrementClients adds one to the number of connected RPC clients.  Note
// this only applies to standard clients.  Websocket clients have their own
// limits and are tracked separately.
//
// This function is safe for concurrent access.
func (s *rpcServer) incrementClients() {
	atomic.AddInt32(&s.numClients, 1)
}

// decrementClients subtracts one from the number of connected RPC clients.
// Note this only applies to standard clients.  Websocket clients have their own
// limits and are tracked separately.
//
// This function is safe for concurrent access.
func (s *rpcServer) decrementClients() {
	atomic.AddInt32(&s.numClients, -1)
}

// checkAuth checks the HTTP Basic authentication supplied by a wallet
// or RPC client in the HTTP request r.  If the supplied authentication
// does not match the username and password expected, a non-nil error is
// returned.
//
// This check is time-constant.
func (s *rpcServer) checkAuth(r *http.Request, require bool) (bool, error) {
	authhdr := r.Header["Authorization"]
	if len(authhdr) <= 0 {
		if require {
			rpcsLog.Warnf("RPC authentication failure from %s",
				r.RemoteAddr)
			return false, errors.New("auth failure")
		}

		return false, nil
	}

	authsha := fastsha256.Sum256([]byte(authhdr[0]))
	cmp := subtle.ConstantTimeCompare(authsha[:], s.authsha[:])
	if cmp != 1 {
		rpcsLog.Warnf("RPC authentication failure from %s", r.RemoteAddr)
		return false, errors.New("auth failure")
	}
	return true, nil
}

// Stop is used by server.go to stop the rpc listener.
func (s *rpcServer) Stop() error {
	if atomic.AddInt32(&s.shutdown, 1) != 1 {
		rpcsLog.Infof("RPC server is already in the process of shutting down")
		return nil
	}
	rpcsLog.Warnf("RPC server shutting down")
	for _, listener := range s.listeners {
		err := listener.Close()
		if err != nil {
			rpcsLog.Errorf("Problem shutting down rpc: %v", err)
			return err
		}
	}
	s.ntfnMgr.Shutdown()
	s.ntfnMgr.WaitForShutdown()
	close(s.quit)
	s.wg.Wait()
	rpcsLog.Infof("RPC server shutdown complete")
	return nil
}

// genCertPair generates a key/cert pair to the paths provided.
func genCertPair(certFile, keyFile string) error {
	rpcsLog.Infof("Generating TLS certificates...")

	org := "btcd autogenerated cert"
	validUntil := time.Now().Add(10 * 365 * 24 * time.Hour)
	cert, key, err := btcutil.NewTLSCertPair(org, validUntil, nil)
	if err != nil {
		return err
	}

	// Write cert and key files.
	if err = ioutil.WriteFile(certFile, cert, 0666); err != nil {
		return err
	}
	if err = ioutil.WriteFile(keyFile, key, 0600); err != nil {
		os.Remove(certFile)
		return err
	}

	rpcsLog.Infof("Done generating TLS certificates")
	return nil
}

// newRPCServer returns a new instance of the rpcServer struct.
func newRPCServer(listenAddrs []string, s *server) (*rpcServer, error) {
	login := cfg.RPCUser + ":" + cfg.RPCPass
	auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login))
	rpc := rpcServer{
		authsha:      fastsha256.Sum256([]byte(auth)),
		server:       s,
		statusLines:  make(map[int]string),
		workState:    newWorkState(),
		gbtWorkState: newGbtWorkState(s.timeSource),
		quit:         make(chan int),
	}
	rpc.ntfnMgr = newWsNotificationManager(&rpc)

	// Setup TLS if not disabled.
	listenFunc := net.Listen
	if !cfg.DisableTLS {
		// Generate the TLS cert and key file if both don't already
		// exist.
		if !fileExists(cfg.RPCKey) && !fileExists(cfg.RPCCert) {
			err := genCertPair(cfg.RPCCert, cfg.RPCKey)
			if err != nil {
				return nil, err
			}
		}
		keypair, err := tls.LoadX509KeyPair(cfg.RPCCert, cfg.RPCKey)
		if err != nil {
			return nil, err
		}

		tlsConfig := tls.Config{
			Certificates: []tls.Certificate{keypair},
			MinVersion:   tls.VersionTLS12,
		}

		// Change the standard net.Listen function to the tls one.
		listenFunc = func(net string, laddr string) (net.Listener, error) {
			return tls.Listen(net, laddr, &tlsConfig)
		}
	}

	// TODO(oga) this code is similar to that in server, should be
	// factored into something shared.
	ipv4ListenAddrs, ipv6ListenAddrs, _, err := parseListeners(listenAddrs)
	if err != nil {
		return nil, err
	}
	listeners := make([]net.Listener, 0,
		len(ipv6ListenAddrs)+len(ipv4ListenAddrs))
	for _, addr := range ipv4ListenAddrs {
		listener, err := listenFunc("tcp4", addr)
		if err != nil {
			rpcsLog.Warnf("Can't listen on %s: %v", addr, err)
			continue
		}
		listeners = append(listeners, listener)
	}

	for _, addr := range ipv6ListenAddrs {
		listener, err := listenFunc("tcp6", addr)
		if err != nil {
			rpcsLog.Warnf("Can't listen on %s: %v", addr, err)
			continue
		}
		listeners = append(listeners, listener)
	}
	if len(listeners) == 0 {
		return nil, errors.New("RPCS: No valid listen address")
	}

	rpc.listeners = listeners

	return &rpc, nil
}

// jsonAuthFail sends a message back to the client if the http auth is rejected.
func jsonAuthFail(w http.ResponseWriter, r *http.Request, s *rpcServer) {
	w.Header().Add("WWW-Authenticate", `Basic realm="btcd RPC"`)
	http.Error(w, "401 Unauthorized.", http.StatusUnauthorized)
}

// jsonRPCRead is the RPC wrapper around the jsonRead function to handle reading
// and responding to RPC messages.
func jsonRPCRead(w http.ResponseWriter, r *http.Request, s *rpcServer) {
	if atomic.LoadInt32(&s.shutdown) != 0 {
		return
	}
	body, err := btcjson.GetRaw(r.Body)
	if err != nil {
		rpcsLog.Errorf("Error getting json message: %v", err)
		return
	}

	// Unfortunately, the http server doesn't provide the ability to
	// change the read deadline for the new connection and having one breaks
	// long polling.  However, not having a read deadline on the initial
	// connection would mean clients can connect and idle forever.  Thus,
	// hijack the connecton from the HTTP server, clear the read deadline,
	// and handle writing the response manually.
	hj, ok := w.(http.Hijacker)
	if !ok {
		errMsg := "webserver doesn't support hijacking"
		rpcsLog.Warnf(errMsg)
		errCode := http.StatusInternalServerError
		http.Error(w, strconv.FormatInt(int64(errCode), 10)+" "+errMsg,
			errCode)
		return
	}
	conn, buf, err := hj.Hijack()
	if err != nil {
		rpcsLog.Warnf("Failed to hijack HTTP connection: %v", err)
		errCode := http.StatusInternalServerError
		http.Error(w, strconv.FormatInt(int64(errCode), 10)+" "+
			err.Error(), errCode)
		return
	}
	defer conn.Close()
	defer buf.Flush()
	conn.SetReadDeadline(timeZeroVal)

	var reply btcjson.Reply
	cmd, jsonErr := parseCmd(body)
	if cmd != nil {
		// Unmarshaling at least a valid JSON-RPC message succeeded.
		// Use the provided id for errors.
		id := cmd.Id()
		reply.Id = &id
	}
	if jsonErr != nil {
		reply.Error = jsonErr
	} else {
		// Setup a close notifier.  Since the connection is hijacked,
		// the CloseNotifer on the ResponseWriter is not available.
		closeChan := make(chan struct{}, 1)
		go func() {
			_, err := conn.Read(make([]byte, 1))
			if err != nil {
				close(closeChan)
			}
		}()

		reply = standardCmdReply(cmd, s, closeChan)
	}

	rpcsLog.Tracef("reply: %v", reply)

	err = s.writeHTTPResponseHeaders(r, w.Header(), http.StatusOK, buf)
	if err != nil {
		rpcsLog.Error(err)
		return
	}

	msg, err := btcjson.MarshallAndSend(reply, buf)
	if err != nil {
		rpcsLog.Error(err)
		return
	}
	rpcsLog.Tracef(msg)
}

// handleUnimplemented is a temporary handler for commands that we should
// support but do not.
func handleUnimplemented(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	return nil, btcjson.ErrUnimplemented
}

// handleAskWallet is the handler for commands that we do recognise as valid
// but that we can not answer correctly since it involves wallet state.
// These commands will be implemented in btcwallet.
func handleAskWallet(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	return nil, btcjson.ErrNoWallet
}

// handleAddNode handles addnode commands.
func handleAddNode(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.AddNodeCmd)

	addr := normalizeAddress(c.Addr, activeNetParams.DefaultPort)
	var err error
	switch c.SubCmd {
	case "add":
		err = s.server.AddAddr(addr, true)
	case "remove":
		err = s.server.RemoveAddr(addr)
	case "onetry":
		err = s.server.AddAddr(addr, false)
	default:
		err = errors.New("invalid subcommand for addnode")
	}

	if err != nil {
		return nil, btcjson.Error{
			Code:    btcjson.ErrInternal.Code,
			Message: err.Error(),
		}
	}

	// no data returned unless an error.
	return nil, nil
}

// messageToHex serializes a message to the wire protocol encoding using the
// latest protocol version and returns a hex-encoded string of the result.
func messageToHex(msg btcwire.Message) (string, error) {
	var buf bytes.Buffer
	err := msg.BtcEncode(&buf, maxProtocolVersion)
	if err != nil {
		return "", btcjson.Error{
			Code:    btcjson.ErrInternal.Code,
			Message: err.Error(),
		}
	}
	return hex.EncodeToString(buf.Bytes()), nil
}

// handleCreateRawTransaction handles createrawtransaction commands.
func handleCreateRawTransaction(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.CreateRawTransactionCmd)

	// Add all transaction inputs to a new transaction after performing
	// some validity checks.
	mtx := btcwire.NewMsgTx()
	for _, input := range c.Inputs {
		txHash, err := btcwire.NewShaHashFromStr(input.Txid)
		if err != nil {
			return nil, btcjson.ErrDecodeHexString
		}

		if input.Vout < 0 {
			return nil, btcjson.Error{
				Code:    btcjson.ErrInvalidParameter.Code,
				Message: "Invalid parameter, vout must be positive",
			}
		}

		prevOut := btcwire.NewOutPoint(txHash, uint32(input.Vout))
		txIn := btcwire.NewTxIn(prevOut, []byte{})
		mtx.AddTxIn(txIn)
	}

	// Add all transaction outputs to the transaction after performing
	// some validity checks.
	for encodedAddr, amount := range c.Amounts {
		// Ensure amount is in the valid range for monetary amounts.
		if amount <= 0 || amount > btcutil.MaxSatoshi {
			return nil, btcjson.Error{
				Code:    btcjson.ErrType.Code,
				Message: "Invalid amount",
			}
		}

		// Decode the provided address.
		addr, err := btcutil.DecodeAddress(encodedAddr,
			activeNetParams.Params)
		if err != nil {
			return nil, btcjson.Error{
				Code: btcjson.ErrInvalidAddressOrKey.Code,
				Message: btcjson.ErrInvalidAddressOrKey.Message +
					": " + err.Error(),
			}
		}

		// Ensure the address is one of the supported types and that
		// the network encoded with the address matches the network the
		// server is currently on.
		switch addr.(type) {
		case *btcutil.AddressPubKeyHash:
		case *btcutil.AddressScriptHash:
		default:
			return nil, btcjson.ErrInvalidAddressOrKey
		}
		if !addr.IsForNet(s.server.netParams) {
			return nil, btcjson.Error{
				Code: btcjson.ErrInvalidAddressOrKey.Code,
				Message: fmt.Sprintf("%s: %q",
					btcjson.ErrInvalidAddressOrKey.Message,
					encodedAddr),
			}
		}

		// Create a new script which pays to the provided address.
		pkScript, err := btcscript.PayToAddrScript(addr)
		if err != nil {
			return nil, btcjson.Error{
				Code:    btcjson.ErrInternal.Code,
				Message: err.Error(),
			}
		}

		txOut := btcwire.NewTxOut(amount, pkScript)
		mtx.AddTxOut(txOut)
	}

	// Return the serialized and hex-encoded transaction.
	mtxHex, err := messageToHex(mtx)
	if err != nil {
		return nil, err
	}
	return mtxHex, nil
}

// handleDebugLevel handles debuglevel commands.
func handleDebugLevel(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.DebugLevelCmd)

	// Special show command to list supported subsystems.
	if c.LevelSpec == "show" {
		return fmt.Sprintf("Supported subsystems %v",
			supportedSubsystems()), nil
	}

	err := parseAndSetDebugLevels(c.LevelSpec)
	if err != nil {
		return nil, btcjson.Error{
			Code:    btcjson.ErrInvalidParams.Code,
			Message: err.Error(),
		}
	}

	return "Done.", nil
}

// createVinList returns a slice of JSON objects for the inputs of the passed
// transaction.
func createVinList(mtx *btcwire.MsgTx) []btcjson.Vin {
	tx := btcutil.NewTx(mtx)
	vinList := make([]btcjson.Vin, len(mtx.TxIn))
	for i, v := range mtx.TxIn {
		if btcchain.IsCoinBase(tx) {
			vinList[i].Coinbase = hex.EncodeToString(v.SignatureScript)
		} else {
			vinList[i].Txid = v.PreviousOutPoint.Hash.String()
			vinList[i].Vout = v.PreviousOutPoint.Index

			// The disassembled string will contain [error] inline
			// if the script doesn't fully parse, so ignore the
			// error here.
			disbuf, _ := btcscript.DisasmString(v.SignatureScript)
			vinList[i].ScriptSig = new(btcjson.ScriptSig)
			vinList[i].ScriptSig.Asm = disbuf
			vinList[i].ScriptSig.Hex = hex.EncodeToString(v.SignatureScript)
		}
		vinList[i].Sequence = v.Sequence
	}

	return vinList
}

// createVoutList returns a slice of JSON objects for the outputs of the passed
// transaction.
func createVoutList(mtx *btcwire.MsgTx, net *btcnet.Params) []btcjson.Vout {
	voutList := make([]btcjson.Vout, len(mtx.TxOut))
	for i, v := range mtx.TxOut {
		voutList[i].N = uint32(i)
		voutList[i].Value = float64(v.Value) / btcutil.SatoshiPerBitcoin

		// The disassembled string will contain [error] inline if the
		// script doesn't fully parse, so ignore the error here.
		disbuf, _ := btcscript.DisasmString(v.PkScript)
		voutList[i].ScriptPubKey.Asm = disbuf
		voutList[i].ScriptPubKey.Hex = hex.EncodeToString(v.PkScript)

		// Ignore the error here since an error means the script
		// couldn't parse and there is no additional information about
		// it anyways.
		scriptClass, addrs, reqSigs, _ := btcscript.ExtractPkScriptAddrs(v.PkScript, net)
		voutList[i].ScriptPubKey.Type = scriptClass.String()
		voutList[i].ScriptPubKey.ReqSigs = int32(reqSigs)

		if addrs == nil {
			voutList[i].ScriptPubKey.Addresses = nil
		} else {
			voutList[i].ScriptPubKey.Addresses = make([]string, len(addrs))
			for j, addr := range addrs {
				voutList[i].ScriptPubKey.Addresses[j] = addr.EncodeAddress()
			}
		}
	}

	return voutList
}

// createTxRawResult converts the passed transaction and associated parameters
// to a raw transaction JSON object.
func createTxRawResult(net *btcnet.Params, txSha string, mtx *btcwire.MsgTx,
	blk *btcutil.Block, maxidx int64,
	blksha *btcwire.ShaHash) (*btcjson.TxRawResult, error) {

	mtxHex, err := messageToHex(mtx)
	if err != nil {
		return nil, err
	}

	txReply := &btcjson.TxRawResult{
		Hex:      mtxHex,
		Txid:     txSha,
		Vout:     createVoutList(mtx, net),
		Vin:      createVinList(mtx),
		Version:  mtx.Version,
		LockTime: mtx.LockTime,
	}

	if blk != nil {
		blockHeader := &blk.MsgBlock().Header
		idx := blk.Height()

		// This is not a typo, they are identical in bitcoind as well.
		txReply.Time = blockHeader.Timestamp.Unix()
		txReply.Blocktime = blockHeader.Timestamp.Unix()
		txReply.BlockHash = blksha.String()
		txReply.Confirmations = uint64(1 + maxidx - idx)
	}

	return txReply, nil
}

// handleDecodeRawTransaction handles decoderawtransaction commands.
func handleDecodeRawTransaction(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.DecodeRawTransactionCmd)

	// Deserialize the transaction.
	hexStr := c.HexTx
	if len(hexStr)%2 != 0 {
		hexStr = "0" + hexStr
	}
	serializedTx, err := hex.DecodeString(hexStr)
	if err != nil {
		return nil, btcjson.Error{
			Code: btcjson.ErrDecodeHexString.Code,
			Message: fmt.Sprintf("argument must be hexadecimal "+
				"string (not %q)", hexStr),
		}
	}
	var mtx btcwire.MsgTx
	err = mtx.Deserialize(bytes.NewReader(serializedTx))
	if err != nil {
		return nil, btcjson.Error{
			Code:    btcjson.ErrDeserialization.Code,
			Message: "TX decode failed",
		}
	}
	txSha, _ := mtx.TxSha()

	// Create and return the result.
	txReply := btcjson.TxRawDecodeResult{
		Txid:     txSha.String(),
		Version:  mtx.Version,
		Locktime: mtx.LockTime,
		Vin:      createVinList(&mtx),
		Vout:     createVoutList(&mtx, s.server.netParams),
	}
	return txReply, nil
}

// handleDecodeScript handles decodescript commands.
func handleDecodeScript(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.DecodeScriptCmd)

	// Convert the hex script to bytes.
	hexStr := c.HexScript
	if len(hexStr)%2 != 0 {
		hexStr = "0" + hexStr
	}
	script, err := hex.DecodeString(hexStr)
	if err != nil {
		return nil, btcjson.Error{
			Code: btcjson.ErrDecodeHexString.Code,
			Message: fmt.Sprintf("argument must be hexadecimal "+
				"string (not %q)", hexStr),
		}
	}

	// The disassembled string will contain [error] inline if the script
	// doesn't fully parse, so ignore the error here.
	disbuf, _ := btcscript.DisasmString(script)

	// Get information about the script.
	// Ignore the error here since an error means the script couldn't parse
	// and there is no additinal information about it anyways.
	net := s.server.netParams
	scriptClass, addrs, reqSigs, _ := btcscript.ExtractPkScriptAddrs(script, net)
	addresses := make([]string, len(addrs))
	for i, addr := range addrs {
		addresses[i] = addr.EncodeAddress()
	}

	// Convert the script itself to a pay-to-script-hash address.
	p2sh, err := btcutil.NewAddressScriptHash(script, net)
	if err != nil {
		return nil, btcjson.Error{
			Code:    btcjson.ErrInternal.Code,
			Message: err.Error(),
		}
	}

	// Generate and return the reply.
	reply := btcjson.DecodeScriptResult{
		Asm:       disbuf,
		ReqSigs:   int32(reqSigs),
		Type:      scriptClass.String(),
		Addresses: addresses,
		P2sh:      p2sh.EncodeAddress(),
	}
	return reply, nil
}

// handleGetAddedNodeInfo handles getaddednodeinfo commands.
func handleGetAddedNodeInfo(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.GetAddedNodeInfoCmd)

	// Retrieve a list of persistent (added) peers from the bitcoin server
	// and filter the list of peer per the specified address (if any).
	peers := s.server.AddedNodeInfo()
	if c.Node != "" {
		found := false
		for i, peer := range peers {
			if peer.addr == c.Node {
				peers = peers[i : i+1]
				found = true
			}
		}
		if !found {
			return nil, btcjson.Error{
				Code:    -24,
				Message: "Node has not been added.",
			}
		}
	}

	// Without the dns flag, the result is just a slice of the addresses as
	// strings.
	if !c.Dns {
		results := make([]string, 0, len(peers))
		for _, peer := range peers {
			results = append(results, peer.addr)
		}
		return results, nil
	}

	// With the dns flag, the result is an array of JSON objects which
	// include the result of DNS lookups for each peer.
	results := make([]*btcjson.GetAddedNodeInfoResult, 0, len(peers))
	for _, peer := range peers {
		// Set the "address" of the peer which could be an ip address
		// or a domain name.
		var result btcjson.GetAddedNodeInfoResult
		result.AddedNode = peer.addr
		isConnected := peer.Connected()
		result.Connected = &isConnected

		// Split the address into host and port portions so we can do
		// a DNS lookup against the host.  When no port is specified in
		// the address, just use the address as the host.
		host, _, err := net.SplitHostPort(peer.addr)
		if err != nil {
			host = peer.addr
		}

		// Do a DNS lookup for the address.  If the lookup fails, just
		// use the host.
		var ipList []string
		ips, err := btcdLookup(host)
		if err == nil {
			ipList = make([]string, 0, len(ips))
			for _, ip := range ips {
				ipList = append(ipList, ip.String())
			}
		} else {
			ipList = make([]string, 1)
			ipList[0] = host
		}

		// Add the addresses and connection info to the result.
		addrs := make([]btcjson.GetAddedNodeInfoResultAddr, 0, len(ipList))
		for _, ip := range ipList {
			var addr btcjson.GetAddedNodeInfoResultAddr
			addr.Address = ip
			addr.Connected = "false"
			if ip == host && peer.Connected() {
				addr.Connected = directionString(peer.inbound)
			}
			addrs = append(addrs, addr)
		}
		result.Addresses = &addrs
		results = append(results, &result)
	}
	return results, nil
}

// handleGetBestBlock implements the getbestblock command.
func handleGetBestBlock(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	// All other "get block" commands give either the height, the
	// hash, or both but require the block SHA.  This gets both for
	// the best block.
	sha, height, err := s.server.db.NewestSha()
	if err != nil {
		return nil, btcjson.ErrBestBlockHash
	}

	result := &btcws.GetBestBlockResult{
		Hash:   sha.String(),
		Height: int32(height),
	}
	return result, nil
}

// handleGetBestBlockHash implements the getbestblockhash command.
func handleGetBestBlockHash(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	sha, _, err := s.server.db.NewestSha()
	if err != nil {
		rpcsLog.Errorf("Error getting newest sha: %v", err)
		return nil, btcjson.ErrBestBlockHash
	}

	return sha.String(), nil
}

// handleGetBlock implements the getblock command.
func handleGetBlock(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.GetBlockCmd)
	sha, err := btcwire.NewShaHashFromStr(c.Hash)
	if err != nil {
		rpcsLog.Errorf("Error generating sha: %v", err)
		return nil, btcjson.ErrBlockNotFound
	}
	blk, err := s.server.db.FetchBlockBySha(sha)
	if err != nil {
		rpcsLog.Errorf("Error fetching sha: %v", err)
		return nil, btcjson.ErrBlockNotFound
	}

	// When the verbose flag isn't set, simply return the network-serialized
	// block as a hex-encoded string.
	if !c.Verbose {
		blkHex, err := messageToHex(blk.MsgBlock())
		if err != nil {
			return nil, err
		}
		return blkHex, nil
	}

	// The verbose flag is set, so generate the JSON object and return it.
	buf, err := blk.Bytes()
	if err != nil {
		rpcsLog.Errorf("Error fetching block: %v", err)
		return nil, btcjson.Error{
			Code:    btcjson.ErrInternal.Code,
			Message: err.Error(),
		}
	}
	idx := blk.Height()
	_, maxidx, err := s.server.db.NewestSha()
	if err != nil {
		rpcsLog.Errorf("Cannot get newest sha: %v", err)
		return nil, btcjson.ErrBlockNotFound
	}

	blockHeader := &blk.MsgBlock().Header
	blockReply := btcjson.BlockResult{
		Hash:          c.Hash,
		Version:       blockHeader.Version,
		MerkleRoot:    blockHeader.MerkleRoot.String(),
		PreviousHash:  blockHeader.PrevBlock.String(),
		Nonce:         blockHeader.Nonce,
		Time:          blockHeader.Timestamp.Unix(),
		Confirmations: uint64(1 + maxidx - idx),
		Height:        idx,
		Size:          int32(len(buf)),
		Bits:          strconv.FormatInt(int64(blockHeader.Bits), 16),
		Difficulty:    getDifficultyRatio(blockHeader.Bits),
	}

	if !c.VerboseTx {
		transactions := blk.Transactions()
		txNames := make([]string, len(transactions))
		for i, tx := range transactions {
			txNames[i] = tx.Sha().String()
		}

		blockReply.Tx = txNames
	} else {
		txns := blk.Transactions()
		rawTxns := make([]btcjson.TxRawResult, len(txns))
		for i, tx := range txns {
			txSha := tx.Sha().String()
			mtx := tx.MsgTx()

			rawTxn, err := createTxRawResult(s.server.netParams,
				txSha, mtx, blk, maxidx, sha)
			if err != nil {
				rpcsLog.Errorf("Cannot create TxRawResult for "+
					"transaction %s: %v", txSha, err)
				return nil, err
			}
			rawTxns[i] = *rawTxn
		}
		blockReply.RawTx = rawTxns
	}

	// Get next block unless we are already at the top.
	if idx < maxidx {
		var shaNext *btcwire.ShaHash
		shaNext, err = s.server.db.FetchBlockShaByHeight(int64(idx + 1))
		if err != nil {
			rpcsLog.Errorf("No next block: %v", err)
			return nil, btcjson.ErrBlockNotFound
		}
		blockReply.NextHash = shaNext.String()
	}

	return blockReply, nil
}

// handleGetBlockCount implements the getblockcount command.
func handleGetBlockCount(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	_, maxidx, err := s.server.db.NewestSha()
	if err != nil {
		rpcsLog.Errorf("Error getting newest sha: %v", err)
		return nil, btcjson.ErrBlockCount
	}

	return maxidx, nil
}

// handleGetBlockHash implements the getblockhash command.
func handleGetBlockHash(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.GetBlockHashCmd)
	sha, err := s.server.db.FetchBlockShaByHeight(c.Index)
	if err != nil {
		rpcsLog.Errorf("Error getting block: %v", err)
		return nil, btcjson.ErrOutOfRange
	}

	return sha.String(), nil
}

// encodeTemplateID encodes the passed details into an ID that can be used to
// uniquely identify a block template.
func encodeTemplateID(prevHash *btcwire.ShaHash, lastGenerated time.Time) string {
	return fmt.Sprintf("%s-%d", prevHash.String(), lastGenerated.Unix())
}

// decodeTemplateID decodes an ID that is used to uniquely identify a block
// template.  This is mainly used as a mechanism to track when to update clients
// that are using long polling for block templates.  The ID consists of the
// previous block hash for the associated template and the time the associated
// template was generated.
func decodeTemplateID(templateID string) (*btcwire.ShaHash, int64, error) {
	fields := strings.Split(templateID, "-")
	if len(fields) != 2 {
		return nil, 0, errors.New("invalid longpollid format")
	}

	prevHash, err := btcwire.NewShaHashFromStr(fields[0])
	if err != nil {
		return nil, 0, errors.New("invalid longpollid format")
	}
	lastGenerated, err := strconv.ParseInt(fields[1], 10, 64)
	if err != nil {
		return nil, 0, errors.New("invalid longpollid format")
	}

	return prevHash, lastGenerated, nil
}

// notifyLongPollers notifies any channels that have been registered to be
// notified when block templates are stale.
//
// This function MUST be called with the state locked.
func (state *gbtWorkState) notifyLongPollers(latestHash *btcwire.ShaHash, lastGenerated time.Time) {
	// Notify anything that is waiting for a block template update from a
	// hash which is not the hash of the tip of the best chain since their
	// work is now invalid.
	for hash, channels := range state.notifyMap {
		if !hash.IsEqual(latestHash) {
			for _, c := range channels {
				close(c)
			}
			delete(state.notifyMap, hash)
		}
	}

	// Return now if the provided last generated timestamp has not been
	// initialized.
	if lastGenerated.IsZero() {
		return
	}

	// Return now if there is nothing registered for updates to the current
	// best block hash.
	channels, ok := state.notifyMap[*latestHash]
	if !ok {
		return
	}

	// Notify anything that is waiting for a block template update from a
	// block template generated before the most recently generated block
	// template.
	lastGeneratedUnix := lastGenerated.Unix()
	for lastGen, c := range channels {
		if lastGen < lastGeneratedUnix {
			close(c)
			delete(channels, lastGen)
		}
	}

	// Remove the entry altogether if there are no more registered
	// channels.
	if len(channels) == 0 {
		delete(state.notifyMap, *latestHash)
	}
}

// NotifyBlockConnected uses the newly-connected block to notify any long poll
// clients with a new block template when their existing block template is
// stale due to the newly connected block.
func (state *gbtWorkState) NotifyBlockConnected(blockSha *btcwire.ShaHash) {
	go func() {
		state.Lock()
		defer state.Unlock()

		state.notifyLongPollers(blockSha, state.lastTxUpdate)
	}()
}

// NotifyMempoolTx uses the new last updated time for the transaction memory
// pool to notify any long poll clients with a new block template when their
// existing block template is stale due to enough time passing and the contents
// of the memory pool changing.
func (state *gbtWorkState) NotifyMempoolTx(lastUpdated time.Time) {
	go func() {
		state.Lock()
		defer state.Unlock()

		// No need to notify anything if no block templates have been generated
		// yet.
		if state.prevHash == nil || state.lastGenerated.IsZero() {
			return
		}

		if time.Now().After(state.lastGenerated.Add(time.Second *
			gbtRegenerateSeconds)) {

			state.notifyLongPollers(state.prevHash, lastUpdated)
		}
	}()
}

// templateUpdateChan returns a channel that will be closed once the block
// template associated with the passed previous hash and last generated time
// is stale.  The function will return existing channels for duplicate
// parameters which allows multiple clients to wait for the same block template
// without requiring a different channel for each client.
//
// This function MUST be called with the state locked.
func (state *gbtWorkState) templateUpdateChan(prevHash *btcwire.ShaHash, lastGenerated int64) chan struct{} {
	// Either get the current list of channels waiting for updates about
	// changes to block template for the previous hash or create a new one.
	channels, ok := state.notifyMap[*prevHash]
	if !ok {
		m := make(map[int64]chan struct{})
		state.notifyMap[*prevHash] = m
		channels = m
	}

	// Get the current channel associated with the time the block template
	// was last generated or create a new one.
	c, ok := channels[lastGenerated]
	if !ok {
		c = make(chan struct{})
		channels[lastGenerated] = c
	}

	return c
}

// updateBlockTemplate creates or updates a block template for the work state.
// A new block template will be generated when the current best block has
// changed or the transactions in the memory pool have been updated and it has
// been some time has passed since the last template was generated.  Otherwise,
// the timestamp for the existing block template is updated (and possibly the
// difficulty on testnet per the consesus rules).  Finally, if the
// useCoinbaseValue flag is flase and the existing block template does not
// already contain a valid payment address, the block template will be updated
// with a randomly selected payment address from the list of configured
// addresses.
//
// This function MUST be called with the state locked.
func (state *gbtWorkState) updateBlockTemplate(s *rpcServer, useCoinbaseValue bool) error {
	lastTxUpdate := s.server.txMemPool.LastUpdated()
	if lastTxUpdate.IsZero() {
		lastTxUpdate = time.Now()
	}

	// Generate a new block template when the current best block has
	// changed or the transactions in the memory pool have been updated and
	// it has been at least gbtRegenerateSecond since the last template was
	// generated.
	var msgBlock *btcwire.MsgBlock
	var targetDifficulty string
	latestHash, _ := s.server.blockManager.chainState.Best()
	template := state.template
	if template == nil || state.prevHash == nil ||
		!state.prevHash.IsEqual(latestHash) ||
		(state.lastTxUpdate != lastTxUpdate &&
			time.Now().After(state.lastGenerated.Add(time.Second*
				gbtRegenerateSeconds))) {

		// Reset the previous best hash the block template was generated
		// against so any errors below cause the next invocation to try
		// again.
		state.prevHash = nil

		// Choose a payment address at random if the caller requests a
		// full coinbase as opposed to only the pertinent details needed
		// to create their own coinbase.
		var payAddr btcutil.Address
		if !useCoinbaseValue {
			payAddr = cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))]
		}

		// Create a new block template that has a coinbase which anyone
		// can redeem.  This is only acceptable because the returned
		// block template doesn't include the coinbase, so the caller
		// will ultimately create their own coinbase which pays to the
		// appropriate address(es).
		blkTemplate, err := NewBlockTemplate(s.server.txMemPool, payAddr)
		if err != nil {
			errStr := fmt.Sprintf("Failed to create new block "+
				"template: %v", err)
			rpcsLog.Error(errStr)
			return btcjson.Error{
				Code:    btcjson.ErrInternal.Code,
				Message: errStr,
			}
		}
		template = blkTemplate
		msgBlock = template.block
		targetDifficulty = fmt.Sprintf("%064x",
			btcchain.CompactToBig(msgBlock.Header.Bits))

		// Find the minimum allowed timestamp for the block based on the
		// median timestamp of the last several blocks per the chain
		// consensus rules.
		chainState := &s.server.blockManager.chainState
		minTimestamp, err := minimumMedianTime(chainState)
		if err != nil {
			return btcjson.Error{
				Code:    btcjson.ErrInternal.Code,
				Message: err.Error(),
			}
		}

		// Update work state to ensure another block template isn't
		// generated until needed.
		state.template = template
		state.lastGenerated = time.Now()
		state.lastTxUpdate = lastTxUpdate
		state.prevHash = latestHash
		state.minTimestamp = minTimestamp

		rpcsLog.Debugf("Generated block template (timestamp %v, "+
			"target %s, merkle root %s)",
			msgBlock.Header.Timestamp, targetDifficulty,
			msgBlock.Header.MerkleRoot)

		// Notify any clients that are long polling about the new
		// template.
		state.notifyLongPollers(latestHash, lastTxUpdate)
	} else {
		// At this point, there is a saved block template and another
		// request for a template was made, but either the available
		// transactions haven't change or it hasn't been long enough to
		// trigger a new block template to be generated.  So, update the
		// existing block template.

		// When the caller requires a full coinbase as opposed to only
		// the pertinent details needed to create their own coinbase,
		// add a payment address to the output of the coinbase of the
		// template if it doesn't already have one.  Since this requires
		// mining addresses to be specified via the config, an error is
		// returned if none have been specified.
		if !useCoinbaseValue && !template.validPayAddress {
			// Choose a payment address at random.
			payToAddr := cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))]

			// Update the block coinbase output of the template to
			// pay to the randomly selected payment address.
			pkScript, err := btcscript.PayToAddrScript(payToAddr)
			if err != nil {
				return btcjson.Error{
					Code:    btcjson.ErrInternal.Code,
					Message: err.Error(),
				}
			}
			template.block.Transactions[0].TxOut[0].PkScript = pkScript
			template.validPayAddress = true

			// Update the merkle root.
			block := btcutil.NewBlock(template.block)
			merkles := btcchain.BuildMerkleTreeStore(block.Transactions())
			template.block.Header.MerkleRoot = *merkles[len(merkles)-1]
		}

		// Set locals for convenience.
		msgBlock = template.block
		targetDifficulty = fmt.Sprintf("%064x",
			btcchain.CompactToBig(msgBlock.Header.Bits))

		// Update the time of the block template to the current time
		// while accounting for the median time of the past several
		// blocks per the chain consensus rules.
		UpdateBlockTime(msgBlock, s.server.blockManager)
		msgBlock.Header.Nonce = 0

		rpcsLog.Debugf("Updated block template (timestamp %v, "+
			"target %s)", msgBlock.Header.Timestamp,
			targetDifficulty)
	}

	return nil
}

// blockTemplateResult returns the current block template associated with the
// state as a btcjson.GetBlockTemplateResult that is ready to be encoded to JSON
// and returned to the caller.
//
// This function MUST be called with the state locked.
func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld *bool) (*btcjson.GetBlockTemplateResult, error) {
	// Ensure the timestamps are still in valid range for the template.
	// This should really only ever happen if the local clock is changed
	// after the template is generated, but it's important to avoid serving
	// invalid block templates.
	template := state.template
	msgBlock := template.block
	header := &msgBlock.Header
	adjustedTime := state.timeSource.AdjustedTime()
	maxTime := adjustedTime.Add(time.Second * btcchain.MaxTimeOffsetSeconds)
	if header.Timestamp.After(maxTime) {
		return nil, btcjson.Error{
			Code: btcjson.ErrOutOfRange.Code,
			Message: fmt.Sprintf("The template time is after the "+
				"maximum allowed time for a block - template "+
				"time %v, maximum time %v", adjustedTime,
				maxTime),
		}
	}

	// Convert each transaction in the block template to a template result
	// transaction.  The result does not include the coinbase, so notice
	// the adjustments to the various lengths and indices.
	numTx := len(msgBlock.Transactions)
	transactions := make([]btcjson.GetBlockTemplateResultTx, 0, numTx-1)
	txIndex := make(map[btcwire.ShaHash]int64, numTx)
	for i, tx := range msgBlock.Transactions {
		txHash, _ := tx.TxSha()
		txIndex[txHash] = int64(i)

		// Skip the coinbase transaction.
		if i == 0 {
			continue
		}

		// Create an array of 1-based indices to transactions that come
		// before this one in the transactions list which this one
		// depends on.  This is necessary since the created block must
		// ensure proper ordering of the dependencies.  A map is used
		// before creating the final array to prevent duplicate entries
		// when mutiple inputs reference the same transaction.
		dependsMap := make(map[int64]struct{})
		for _, txIn := range tx.TxIn {
			if idx, ok := txIndex[txIn.PreviousOutPoint.Hash]; ok {
				dependsMap[idx] = struct{}{}
			}
		}
		depends := make([]int64, 0, len(dependsMap))
		for idx := range dependsMap {
			depends = append(depends, idx)
		}

		// Serialize the transaction for later conversion to hex.
		txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
		if err := tx.Serialize(txBuf); err != nil {
			return nil, btcjson.Error{
				Code:    btcjson.ErrInternal.Code,
				Message: err.Error(),
			}
		}

		resultTx := btcjson.GetBlockTemplateResultTx{
			Data:    hex.EncodeToString(txBuf.Bytes()),
			Hash:    txHash.String(),
			Depends: depends,
			Fee:     template.fees[i],
			SigOps:  template.sigOpCounts[i],
		}
		transactions = append(transactions, resultTx)
	}

	// Generate the block template reply.  Note that following mutations are
	// implied by the included or omission of fields:
	//  Including MinTime -> time/decrement
	//  Omitting CoinbaseTxn -> coinbase, generation
	targetDifficulty := fmt.Sprintf("%064x", btcchain.CompactToBig(header.Bits))
	templateID := encodeTemplateID(state.prevHash, state.lastGenerated)
	reply := btcjson.GetBlockTemplateResult{
		Bits:         strconv.FormatInt(int64(header.Bits), 16),
		CurTime:      header.Timestamp.Unix(),
		Height:       template.height,
		PreviousHash: header.PrevBlock.String(),
		SigOpLimit:   btcchain.MaxSigOpsPerBlock,
		SizeLimit:    btcwire.MaxBlockPayload,
		Transactions: transactions,
		Version:      header.Version,
		LongPollID:   templateID,
		SubmitOld:    submitOld,
		Target:       targetDifficulty,
		MinTime:      state.minTimestamp.Unix(),
		MaxTime:      maxTime.Unix(),
		Mutable:      gbtMutableFields,
		NonceRange:   gbtNonceRange,
		Capabilities: gbtCapabilities,
	}
	if useCoinbaseValue {
		reply.CoinbaseAux = gbtCoinbaseAux
		reply.CoinbaseValue = &msgBlock.Transactions[0].TxOut[0].Value
	} else {
		// Ensure the template has a valid payment address associated
		// with it when a full coinbase is requested.
		if !template.validPayAddress {
			return nil, btcjson.Error{
				Code: btcjson.ErrInternal.Code,
				Message: "A coinbase transaction has been " +
					"requested, but the server has not " +
					"been configured with any payment " +
					"addresses via --miningaddr",
			}
		}

		// Serialize the transaction for conversion to hex.
		tx := msgBlock.Transactions[0]
		txHash, _ := tx.TxSha()
		txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
		if err := tx.Serialize(txBuf); err != nil {
			return nil, btcjson.Error{
				Code:    btcjson.ErrInternal.Code,
				Message: err.Error(),
			}
		}

		resultTx := btcjson.GetBlockTemplateResultTx{
			Data:    hex.EncodeToString(txBuf.Bytes()),
			Hash:    txHash.String(),
			Depends: []int64{},
			Fee:     template.fees[0],
			SigOps:  template.sigOpCounts[0],
		}

		reply.CoinbaseTxn = &resultTx
	}

	return &reply, nil
}

// handleGetBlockTemplateLongPoll a helper for handleGetBlockTemplateRequest
// which deals with handling long polling for block templates.  When a caller
// sends a request with a long poll ID that was previously returned, a response
// is not sent until the caller should stop working on the previous block
// template in favor of the new one.  In particular, this is the case when the
// old block template is no longer valid due to a solution already being found
// and added to the block chain, or new transactions have shown up and some time
// has passed without finding a solution.
//
// See https://en.bitcoin.it/wiki/BIP_0022 for more details.
func handleGetBlockTemplateLongPoll(s *rpcServer, longPollID string, useCoinbaseValue bool, closeChan <-chan struct{}) (interface{}, error) {
	state := s.gbtWorkState
	state.Lock()
	// The state unlock is intentionally not deferred here since it needs to
	// be manually unlocked before waiting for a notification about block
	// template changes.

	if err := state.updateBlockTemplate(s, useCoinbaseValue); err != nil {
		state.Unlock()
		return nil, err
	}

	// Just return the current block template if the the long poll ID
	// provided by the caller is invalid.
	prevHash, lastGenerated, err := decodeTemplateID(longPollID)
	if err != nil {
		result, err := state.blockTemplateResult(useCoinbaseValue, nil)
		if err != nil {
			state.Unlock()
			return nil, err
		}

		state.Unlock()
		return result, nil
	}

	// Return the block template now if the specific block template
	// identified by the long poll ID no longer matches the current block
	// template as this means the provided template is stale.
	prevTemplateHash := &state.template.block.Header.PrevBlock
	if !prevHash.IsEqual(prevTemplateHash) ||
		lastGenerated != state.lastGenerated.Unix() {

		// Include whether or not it is valid to submit work against the
		// old block template depending on whether or not a solution has
		// already been found and added to the block chain.
		submitOld := prevHash.IsEqual(prevTemplateHash)
		result, err := state.blockTemplateResult(useCoinbaseValue,
			&submitOld)
		if err != nil {
			state.Unlock()
			return nil, err
		}

		state.Unlock()
		return result, nil
	}

	// Register the previous hash and last generated time for notifications
	// Get a channel that will be notified when the template associated with
	// the provided ID is is stale and a new block template should be
	// returned to the caller.
	longPollChan := state.templateUpdateChan(prevHash, lastGenerated)
	state.Unlock()

	select {
	// When the client closes before it's time to send a reply, just return
	// now so the goroutine doesn't hang around.
	case <-closeChan:
		return nil, ErrClientQuit

	// Wait until signal received to send the reply.
	case <-longPollChan:
		// Fallthrough
	}

	// Get the lastest block template
	state.Lock()
	defer state.Unlock()

	if err := state.updateBlockTemplate(s, useCoinbaseValue); err != nil {
		return nil, err
	}

	// Include whether or not it is valid to submit work against the old
	// block template depending on whether or not a solution has already
	// been found and added to the block chain.
	submitOld := prevHash.IsEqual(&state.template.block.Header.PrevBlock)
	result, err := state.blockTemplateResult(useCoinbaseValue, &submitOld)
	if err != nil {
		return nil, err
	}

	return result, nil
}

// handleGetBlockTemplateRequest is a helper for handleGetBlockTemplate which
// deals with generating and returning block templates to the caller.  It
// handles both long poll requests as specified by BIP 0022 as well as regular
// requests.  In addition, it detects the capabilities reported by the caller
// in regards to whether or not it supports creating its own coinbase (the
// coinbasetxn and coinbasevalue capabilities) and modifies the returned block
// template accordingly.
func handleGetBlockTemplateRequest(s *rpcServer, request *btcjson.TemplateRequest, closeChan <-chan struct{}) (interface{}, error) {
	// Extract the relevant passed capabilities and restrict the result to
	// either a coinbase value or a coinbase transaction object depending on
	// the request.  Default to only providing a coinbase value.
	useCoinbaseValue := true
	if request != nil {
		var hasCoinbaseValue, hasCoinbaseTxn bool
		for _, capability := range request.Capabilities {
			switch capability {
			case "coinbasetxn":
				hasCoinbaseTxn = true
			case "coinbasevalue":
				hasCoinbaseValue = true
			}
		}

		if hasCoinbaseTxn && !hasCoinbaseValue {
			useCoinbaseValue = false
		}
	}

	// When a coinbase transaction has been requested, respond with an error
	// if there are no addresses to pay the created block template to.
	if !useCoinbaseValue && len(cfg.miningAddrs) == 0 {
		return nil, btcjson.Error{
			Code: btcjson.ErrInternal.Code,
			Message: "A coinbase transaction has been requested, " +
				"but the server has not been configured with " +
				"any payment addresses via --miningaddr",
		}
	}

	// Return an error if there are no peers connected since there is no
	// way to relay a found block or receive transactions to work on.
	// However, allow this state when running in the regression test or
	// simulation test mode.
	if !(cfg.RegressionTest || cfg.SimNet) && s.server.ConnectedCount() == 0 {
		return nil, btcjson.ErrClientNotConnected
	}

	// No point in generating or accepting work before the chain is synced.
	_, currentHeight := s.server.blockManager.chainState.Best()
	if currentHeight != 0 && !s.server.blockManager.IsCurrent() {
		return nil, btcjson.ErrClientInInitialDownload
	}

	// When a long poll ID was provided, this is a long poll request by the
	// client to be notified when block template referenced by the ID should
	// be replaced with a new one.
	if request != nil && request.LongPollID != "" {
		return handleGetBlockTemplateLongPoll(s, request.LongPollID,
			useCoinbaseValue, closeChan)
	}

	// Protect concurrent access when updating block templates.
	state := s.gbtWorkState
	state.Lock()
	defer state.Unlock()

	// Get and return a block template.  A new block template will be
	// generated when the current best block has changed or the transactions
	// in the memory pool have been updated and it has been at least five
	// seconds since the last template was generated.  Otherwise, the
	// timestamp for the existing block template is updated (and possibly
	// the difficulty on testnet per the consesus rules).
	if err := state.updateBlockTemplate(s, useCoinbaseValue); err != nil {
		return nil, err
	}
	return state.blockTemplateResult(useCoinbaseValue, nil)
}

// chainErrToGBTErrString converts an error returned from btcchain to a string
// which matches the reasons and format described in BIP0022 for rejection
// reasons.
func chainErrToGBTErrString(err error) string {
	// When the passed error is not a RuleError, just return a generic
	// rejected string with the error text.
	ruleErr, ok := err.(btcchain.RuleError)
	if !ok {
		return "rejected: " + err.Error()
	}

	switch ruleErr.ErrorCode {
	case btcchain.ErrDuplicateBlock:
		return "duplicate"
	case btcchain.ErrBlockTooBig:
		return "bad-block-size"
	case btcchain.ErrBlockVersionTooOld:
		return "bad-version"
	case btcchain.ErrInvalidTime:
		return "bad-time"
	case btcchain.ErrTimeTooOld:
		return "time-too-old"
	case btcchain.ErrTimeTooNew:
		return "time-too-new"
	case btcchain.ErrDifficultyTooLow:
		return "bad-diffbits"
	case btcchain.ErrUnexpectedDifficulty:
		return "bad-diffbits"
	case btcchain.ErrHighHash:
		return "high-hash"
	case btcchain.ErrBadMerkleRoot:
		return "bad-txnmrklroot"
	case btcchain.ErrBadCheckpoint:
		return "bad-checkpoint"
	case btcchain.ErrForkTooOld:
		return "fork-too-old"
	case btcchain.ErrCheckpointTimeTooOld:
		return "checkpoint-time-too-old"
	case btcchain.ErrNoTransactions:
		return "bad-txns-none"
	case btcchain.ErrTooManyTransactions:
		return "bad-txns-toomany"
	case btcchain.ErrNoTxInputs:
		return "bad-txns-noinputs"
	case btcchain.ErrNoTxOutputs:
		return "bad-txns-nooutputs"
	case btcchain.ErrTxTooBig:
		return "bad-txns-size"
	case btcchain.ErrBadTxOutValue:
		return "bad-txns-outputvalue"
	case btcchain.ErrDuplicateTxInputs:
		return "bad-txns-dupinputs"
	case btcchain.ErrBadTxInput:
		return "bad-txns-badinput"
	case btcchain.ErrMissingTx:
		return "bad-txns-missinginput"
	case btcchain.ErrUnfinalizedTx:
		return "bad-txns-unfinalizedtx"
	case btcchain.ErrDuplicateTx:
		return "bad-txns-duplicate"
	case btcchain.ErrOverwriteTx:
		return "bad-txns-overwrite"
	case btcchain.ErrImmatureSpend:
		return "bad-txns-maturity"
	case btcchain.ErrDoubleSpend:
		return "bad-txns-dblspend"
	case btcchain.ErrSpendTooHigh:
		return "bad-txns-highspend"
	case btcchain.ErrBadFees:
		return "bad-txns-fees"
	case btcchain.ErrTooManySigOps:
		return "high-sigops"
	case btcchain.ErrFirstTxNotCoinbase:
		return "bad-txns-nocoinbase"
	case btcchain.ErrMultipleCoinbases:
		return "bad-txns-multicoinbase"
	case btcchain.ErrBadCoinbaseScriptLen:
		return "bad-cb-length"
	case btcchain.ErrBadCoinbaseValue:
		return "bad-cb-value"
	case btcchain.ErrMissingCoinbaseHeight:
		return "bad-cb-height"
	case btcchain.ErrBadCoinbaseHeight:
		return "bad-cb-height"
	case btcchain.ErrScriptMalformed:
		return "bad-script-malformed"
	case btcchain.ErrScriptValidation:
		return "bad-script-validate"
	}

	return "rejected: " + err.Error()
}

// handleGetBlockTemplateProposal is a helper for handleGetBlockTemplate which
// deals with block proposals.
//
// See https://en.bitcoin.it/wiki/BIP_0023 for more details.
func handleGetBlockTemplateProposal(s *rpcServer, request *btcjson.TemplateRequest) (interface{}, error) {
	hexData := request.Data
	if hexData == "" {
		return false, btcjson.Error{
			Code: btcjson.ErrType.Code,
			Message: fmt.Sprintf("data must contain the " +
				"hex-encoded serialized block that is being " +
				"proposed"),
		}
	}

	// Ensure the provided data is sane and deserialize the proposed block.
	if len(hexData)%2 != 0 {
		hexData = "0" + hexData
	}
	dataBytes, err := hex.DecodeString(hexData)
	if err != nil {
		return false, btcjson.Error{
			Code: btcjson.ErrDeserialization.Code,
			Message: fmt.Sprintf("data must be "+
				"hexadecimal string (not %q)", hexData),
		}
	}
	var msgBlock btcwire.MsgBlock
	if err := msgBlock.Deserialize(bytes.NewReader(dataBytes)); err != nil {
		return nil, btcjson.Error{
			Code:    btcjson.ErrDeserialization.Code,
			Message: "Block decode failed: " + err.Error(),
		}
	}
	block := btcutil.NewBlock(&msgBlock)

	// Ensure the block is building from the expected previous block.
	expectedPrevHash, _ := s.server.blockManager.chainState.Best()
	prevHash := &block.MsgBlock().Header.PrevBlock
	if expectedPrevHash == nil || !expectedPrevHash.IsEqual(prevHash) {
		return "bad-prevblk", nil
	}

	flags := btcchain.BFDryRun | btcchain.BFNoPoWCheck
	isOrphan, err := s.server.blockManager.ProcessBlock(block, flags)
	if err != nil {
		if _, ok := err.(btcchain.RuleError); !ok {
			rpcsLog.Errorf("Failed to process block proposal: %v",
				err)
			return nil, btcjson.Error{
				Code:    -25, // ErrRpcVerify
				Message: err.Error(),
			}
		}

		rpcsLog.Infof("Rejected block proposal: %v", err)
		return chainErrToGBTErrString(err), nil
	}
	if isOrphan {
		return "orphan", nil
	}

	return nil, nil
}

// handleGetBlockTemplate implements the getblocktemplate command.
//
// See https://en.bitcoin.it/wiki/BIP_0022 and
// https://en.bitcoin.it/wiki/BIP_0023 for more details.
func handleGetBlockTemplate(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.GetBlockTemplateCmd)
	request := c.Request

	// Set the default mode and override it if supplied.
	mode := "template"
	if request != nil && request.Mode != "" {
		mode = request.Mode
	}

	switch mode {
	case "template":
		return handleGetBlockTemplateRequest(s, request, closeChan)
	case "proposal":
		return handleGetBlockTemplateProposal(s, request)
	}

	return nil, btcjson.Error{
		Code:    btcjson.ErrInvalidParameter.Code,
		Message: "Invalid mode",
	}
}

// handleGetConnectionCount implements the getconnectioncount command.
func handleGetConnectionCount(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	return s.server.ConnectedCount(), nil
}

// handleGetCurrentNet implements the getcurrentnet command.
func handleGetCurrentNet(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	return s.server.netParams.Net, nil
}

// handleGetDifficulty implements the getdifficulty command.
func handleGetDifficulty(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	sha, _, err := s.server.db.NewestSha()
	if err != nil {
		rpcsLog.Errorf("Error getting sha: %v", err)
		return nil, btcjson.ErrDifficulty
	}
	blockHeader, err := s.server.db.FetchBlockHeaderBySha(sha)
	if err != nil {
		rpcsLog.Errorf("Error getting block: %v", err)
		return nil, btcjson.ErrDifficulty
	}
	return getDifficultyRatio(blockHeader.Bits), nil
}

// handleGetGenerate implements the getgenerate command.
func handleGetGenerate(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	return s.server.cpuMiner.IsMining(), nil
}

// handleGetHashesPerSec implements the gethashespersec command.
func handleGetHashesPerSec(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	return int64(s.server.cpuMiner.HashesPerSecond()), nil
}

// handleGetInfo implements the getinfo command. We only return the fields
// that are not related to wallet functionality.
func handleGetInfo(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	// We require the current block height and sha.
	sha, height, err := s.server.db.NewestSha()
	if err != nil {
		rpcsLog.Errorf("Error getting sha: %v", err)
		return nil, btcjson.ErrBlockCount
	}
	blkHeader, err := s.server.db.FetchBlockHeaderBySha(sha)
	if err != nil {
		rpcsLog.Errorf("Error getting block: %v", err)
		return nil, btcjson.ErrDifficulty
	}

	ret := &btcjson.InfoResult{
		Version:         int32(1000000*appMajor + 10000*appMinor + 100*appPatch),
		ProtocolVersion: int32(maxProtocolVersion),
		Blocks:          int32(height),
		TimeOffset:      int64(s.server.timeSource.Offset().Seconds()),
		Connections:     s.server.ConnectedCount(),
		Proxy:           cfg.Proxy,
		Difficulty:      getDifficultyRatio(blkHeader.Bits),
		TestNet:         cfg.TestNet3,
		RelayFee:        float64(minTxRelayFee) / btcutil.SatoshiPerBitcoin,
	}

	return ret, nil
}

// handleGetMiningInfo implements the getmininginfo command. We only return the
// fields that are not related to wallet functionality.
func handleGetMiningInfo(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	sha, height, err := s.server.db.NewestSha()
	if err != nil {
		rpcsLog.Errorf("Error getting sha: %v", err)
		return nil, btcjson.ErrBlockCount
	}
	block, err := s.server.db.FetchBlockBySha(sha)
	if err != nil {
		rpcsLog.Errorf("Error getting block: %v", err)
		return nil, btcjson.ErrBlockNotFound
	}
	blockBytes, err := block.Bytes()
	if err != nil {
		rpcsLog.Errorf("Error getting block: %v", err)
		return nil, btcjson.Error{
			Code:    btcjson.ErrInternal.Code,
			Message: err.Error(),
		}
	}

	// Create a default getnetworkhashps command to use defaults and make
	// use of the existing getnetworkhashps handler.
	gnhpsCmd, err := btcjson.NewGetNetworkHashPSCmd(0)
	if err != nil {
		return nil, btcjson.Error{
			Code:    btcjson.ErrInternal.Code,
			Message: err.Error(),
		}
	}
	networkHashesPerSecIface, err := handleGetNetworkHashPS(s, gnhpsCmd,
		closeChan)
	if err != nil {
		// This is already a btcjson.Error from the handler.
		return nil, err
	}
	networkHashesPerSec, ok := networkHashesPerSecIface.(int64)
	if !ok {
		return nil, btcjson.Error{
			Code:    btcjson.ErrInternal.Code,
			Message: "networkHashesPerSec is not an int64",
		}
	}

	result := btcjson.GetMiningInfoResult{
		Blocks:           height,
		CurrentBlockSize: uint64(len(blockBytes)),
		CurrentBlockTx:   uint64(len(block.MsgBlock().Transactions)),
		Difficulty:       getDifficultyRatio(block.MsgBlock().Header.Bits),
		Generate:         s.server.cpuMiner.IsMining(),
		GenProcLimit:     s.server.cpuMiner.NumWorkers(),
		HashesPerSec:     int64(s.server.cpuMiner.HashesPerSecond()),
		NetworkHashPS:    networkHashesPerSec,
		PooledTx:         uint64(s.server.txMemPool.Count()),
		TestNet:          cfg.TestNet3,
	}
	return &result, nil
}

// handleGetNetTotals implements the getnettotals command.
func handleGetNetTotals(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	totalBytesRecv, totalBytesSent := s.server.NetTotals()
	reply := &btcjson.GetNetTotalsResult{
		TotalBytesRecv: totalBytesRecv,
		TotalBytesSent: totalBytesSent,
		TimeMillis:     time.Now().UTC().UnixNano() / int64(time.Millisecond),
	}
	return reply, nil
}

// handleGetNetworkHashPS implements the getnetworkhashps command.
func handleGetNetworkHashPS(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.GetNetworkHashPSCmd)

	_, newestHeight, err := s.server.db.NewestSha()
	if err != nil {
		return nil, btcjson.Error{
			Code:    btcjson.ErrInternal.Code,
			Message: err.Error(),
		}
	}

	// When the passed height is too high or zero, just return 0 now
	// since we can't reasonably calculate the number of network hashes
	// per second from invalid values.  When it's negative, use the current
	// best block height.
	endHeight := int64(c.Height)
	if endHeight > newestHeight || endHeight == 0 {
		return 0, nil
	}
	if endHeight < 0 {
		endHeight = newestHeight
	}

	// Calculate the starting block height based on the passed number of
	// blocks.  When the passed value is negative, use the last block the
	// difficulty changed as the starting height.  Also make sure the
	// starting height is not before the beginning of the chain.
	var startHeight int64
	if c.Blocks <= 0 {
		startHeight = endHeight - ((endHeight % btcchain.BlocksPerRetarget) + 1)
	} else {
		startHeight = endHeight - int64(c.Blocks)
	}
	if startHeight < 0 {
		startHeight = 0
	}
	rpcsLog.Debugf("Calculating network hashes per second from %d to %d",
		startHeight, endHeight)

	// Find the min and max block timestamps as well as calculate the total
	// amount of work that happened between the start and end blocks.
	var minTimestamp, maxTimestamp time.Time
	totalWork := big.NewInt(0)
	for curHeight := startHeight; curHeight <= endHeight; curHeight++ {
		hash, err := s.server.db.FetchBlockShaByHeight(curHeight)
		if err != nil {
			return nil, btcjson.Error{
				Code:    btcjson.ErrInternal.Code,
				Message: err.Error(),
			}
		}

		header, err := s.server.db.FetchBlockHeaderBySha(hash)
		if err != nil {
			return nil, btcjson.Error{
				Code:    btcjson.ErrInternal.Code,
				Message: err.Error(),
			}
		}

		if curHeight == startHeight {
			minTimestamp = header.Timestamp
			maxTimestamp = minTimestamp
		} else {
			totalWork.Add(totalWork, btcchain.CalcWork(header.Bits))

			if minTimestamp.After(header.Timestamp) {
				minTimestamp = header.Timestamp
			}
			if maxTimestamp.Before(header.Timestamp) {
				maxTimestamp = header.Timestamp
			}
		}
	}

	// Calculate the difference in seconds between the min and max block
	// timestamps and avoid division by zero in the case where there is no
	// time difference.
	timeDiff := int64(maxTimestamp.Sub(minTimestamp) / time.Second)
	if timeDiff == 0 {
		return 0, nil
	}

	hashesPerSec := new(big.Int).Div(totalWork, big.NewInt(timeDiff))
	return hashesPerSec.Int64(), nil
}

// handleGetPeerInfo implements the getpeerinfo command.
func handleGetPeerInfo(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	return s.server.PeerInfo(), nil
}

// handleGetRawMempool implements the getrawmempool command.
func handleGetRawMempool(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.GetRawMempoolCmd)
	mp := s.server.txMemPool
	descs := mp.TxDescs()

	if c.Verbose {
		result := make(map[string]*btcjson.GetRawMempoolResult, len(descs))

		_, newestHeight, err := s.server.db.NewestSha()
		if err != nil {
			rpcsLog.Errorf("Cannot get newest sha: %v", err)
			return nil, btcjson.ErrBlockNotFound
		}

		mp.RLock()
		defer mp.RUnlock()
		for _, desc := range descs {
			// Calculate the starting and current priority from the
			// the tx's inputs.  Use zeros if one or more of the
			// input transactions can't be found for some reason.
			var startingPriority, currentPriority float64
			inputTxs, err := mp.fetchInputTransactions(desc.Tx)
			if err == nil {
				startingPriority = desc.StartingPriority(inputTxs)
				currentPriority = desc.CurrentPriority(inputTxs,
					newestHeight+1)
			}

			mpd := &btcjson.GetRawMempoolResult{
				Size:             int32(desc.Tx.MsgTx().SerializeSize()),
				Fee:              btcutil.Amount(desc.Fee).ToUnit(btcutil.AmountSatoshi),
				Time:             desc.Added.Unix(),
				Height:           desc.Height,
				StartingPriority: startingPriority,
				CurrentPriority:  currentPriority,
				Depends:          make([]string, 0),
			}
			for _, txIn := range desc.Tx.MsgTx().TxIn {
				hash := &txIn.PreviousOutPoint.Hash
				if s.server.txMemPool.haveTransaction(hash) {
					mpd.Depends = append(mpd.Depends,
						hash.String())
				}
			}

			result[desc.Tx.Sha().String()] = mpd
		}

		return result, nil
	}

	// The response is simply an array of the transaction hashes if the
	// verbose flag is not set.
	hashStrings := make([]string, len(descs))
	for i := range hashStrings {
		hashStrings[i] = descs[i].Tx.Sha().String()
	}

	return hashStrings, nil
}

// handleGetRawTransaction implements the getrawtransaction command.
func handleGetRawTransaction(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.GetRawTransactionCmd)

	// Convert the provided transaction hash hex to a ShaHash.
	txSha, err := btcwire.NewShaHashFromStr(c.Txid)
	if err != nil {
		rpcsLog.Errorf("Error generating sha: %v", err)
		return nil, btcjson.Error{
			Code:    btcjson.ErrBlockNotFound.Code,
			Message: "Parameter 1 must be a hexaecimal string",
		}
	}

	// Try to fetch the transaction from the memory pool and if that fails,
	// try the block database.
	var mtx *btcwire.MsgTx
	var blksha *btcwire.ShaHash
	tx, err := s.server.txMemPool.FetchTransaction(txSha)
	if err != nil {
		txList, err := s.server.db.FetchTxBySha(txSha)
		if err != nil {
			rpcsLog.Errorf("Error fetching tx: %v", err)
			return nil, btcjson.ErrNoTxInfo
		}
		if len(txList) == 0 {
			return nil, btcjson.ErrNoTxInfo
		}

		lastTx := len(txList) - 1
		mtx = txList[lastTx].Tx

		blksha = txList[lastTx].BlkSha
	} else {
		mtx = tx.MsgTx()
	}

	// When the verbose flag isn't set, simply return the network-serialized
	// transaction as a hex-encoded string.
	if c.Verbose == 0 {
		mtxHex, err := messageToHex(mtx)
		if err != nil {
			return nil, err
		}
		return mtxHex, nil
	}

	var blk *btcutil.Block
	var maxidx int64
	if blksha != nil {
		blk, err = s.server.db.FetchBlockBySha(blksha)
		if err != nil {
			rpcsLog.Errorf("Error fetching sha: %v", err)
			return nil, btcjson.ErrBlockNotFound
		}

		_, maxidx, err = s.server.db.NewestSha()
		if err != nil {
			rpcsLog.Errorf("Cannot get newest sha: %v", err)
			return nil, btcjson.ErrNoNewestBlockInfo
		}
	}

	rawTxn, err := createTxRawResult(s.server.netParams, c.Txid, mtx,
		blk, maxidx, blksha)
	if err != nil {
		rpcsLog.Errorf("Cannot create TxRawResult for txSha=%s: %v", txSha, err)
		return nil, err
	}
	return *rawTxn, nil
}

// bigToLEUint256 returns the passed big integer as an unsigned 256-bit integer
// encoded as little-endian bytes.  Numbers which are larger than the max
// unsigned 256-bit integer are truncated.
func bigToLEUint256(n *big.Int) [uint256Size]byte {
	// Pad or truncate the big-endian big int to correct number of bytes.
	nBytes := n.Bytes()
	nlen := len(nBytes)
	pad := 0
	start := 0
	if nlen <= uint256Size {
		pad = uint256Size - nlen
	} else {
		start = nlen - uint256Size
	}
	var buf [uint256Size]byte
	copy(buf[pad:], nBytes[start:])

	// Reverse the bytes to little endian and return them.
	for i := 0; i < uint256Size/2; i++ {
		buf[i], buf[uint256Size-1-i] = buf[uint256Size-1-i], buf[i]
	}
	return buf
}

// reverseUint32Array treats the passed bytes as a series of uint32s and
// reverses the byte order of each uint32.  The passed byte slice must be a
// multiple of 4 for a correct result.  The passed bytes slice is modified.
func reverseUint32Array(b []byte) {
	blen := len(b)
	for i := 0; i < blen; i += 4 {
		b[i], b[i+3] = b[i+3], b[i]
		b[i+1], b[i+2] = b[i+2], b[i+1]
	}
}

// handleGetTxOut handles gettxout commands.
func handleGetTxOut(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.GetTxOutCmd)

	// Convert the provided transaction hash hex to a ShaHash.
	txSha, err := btcwire.NewShaHashFromStr(c.Txid)
	if err != nil {
		return nil, btcjson.Error{
			Code: btcjson.ErrInvalidParameter.Code,
			Message: fmt.Sprintf("argument must be hexadecimal "+
				"string (not %q)", c.Txid),
		}
	}

	// If requested and the tx is available in the mempool try to fetch it from
	// there, otherwise attempt to fetch from the block database.
	var mtx *btcwire.MsgTx
	var bestBlockSha string
	var confirmations int64
	var dbSpentInfo []bool
	if c.IncludeMempool && s.server.txMemPool.HaveTransaction(txSha) {
		tx, err := s.server.txMemPool.FetchTransaction(txSha)
		if err != nil {
			rpcsLog.Errorf("Error fetching tx: %v", err)
			return nil, btcjson.ErrNoTxInfo
		}
		mtx = tx.MsgTx()
		confirmations = 0
		bestBlockSha = ""
	} else {
		txList, err := s.server.db.FetchTxBySha(txSha)
		if err != nil || len(txList) == 0 {
			return nil, btcjson.ErrNoTxInfo
		}

		lastTx := txList[len(txList)-1]
		mtx = lastTx.Tx
		blksha := lastTx.BlkSha
		txHeight := lastTx.Height
		dbSpentInfo = lastTx.TxSpent

		_, bestHeight, err := s.server.db.NewestSha()
		if err != nil {
			rpcsLog.Errorf("Cannot get newest sha: %v", err)
			return nil, btcjson.ErrBlockNotFound
		}

		confirmations = 1 + bestHeight - txHeight
		bestBlockSha = blksha.String()
	}

	if c.Output < 0 || c.Output > len(mtx.TxOut)-1 {
		return nil, btcjson.ErrInvalidTxVout
	}

	txOut := mtx.TxOut[c.Output]
	if txOut == nil {
		rpcsLog.Errorf("Output index: %d, for txid: %s does not exist.", c.Output, c.Txid)
		return nil, btcjson.ErrInternal
	}

	// To match the behavior of the reference client, this handler returns
	// nil (JSON null) if the transaction output is spent by another
	// transaction already in the database.  Unspent transaction outputs
	// from transactions in mempool, as well as mined transactions that are
	// spent by a mempool transaction, are not affected by this.
	if dbSpentInfo != nil && dbSpentInfo[c.Output] {
		return nil, nil
	}

	// Disassemble script into single line printable format.
	// The disassembled string will contain [error] inline if the script
	// doesn't fully parse, so ignore the error here.
	script := txOut.PkScript
	disbuf, _ := btcscript.DisasmString(script)

	// Get further info about the script.
	// Ignore the error here since an error means the script couldn't parse
	// and there is no additional information about it anyways.
	net := s.server.netParams
	scriptClass, addrs, reqSigs, _ := btcscript.ExtractPkScriptAddrs(script, net)
	addresses := make([]string, len(addrs))
	for i, addr := range addrs {
		addresses[i] = addr.EncodeAddress()
	}

	txOutReply := &btcjson.GetTxOutResult{
		BestBlock:     bestBlockSha,
		Confirmations: confirmations,
		Value:         btcutil.Amount(txOut.Value).ToUnit(btcutil.AmountBTC),
		Version:       mtx.Version,
		ScriptPubKey: btcjson.ScriptPubKeyResult{
			Asm:       disbuf,
			Hex:       hex.EncodeToString(script),
			ReqSigs:   int32(reqSigs),
			Type:      scriptClass.String(),
			Addresses: addresses,
		},
		Coinbase: btcchain.IsCoinBase(btcutil.NewTx(mtx)),
	}
	return txOutReply, nil
}

// handleGetWorkRequest is a helper for handleGetWork which deals with
// generating and returning work to the caller.
//
// This function MUST be called with the RPC workstate locked.
func handleGetWorkRequest(s *rpcServer) (interface{}, error) {
	state := s.workState

	// Generate a new block template when the current best block has
	// changed or the transactions in the memory pool have been updated
	// and it has been at least one minute since the last template was
	// generated.
	lastTxUpdate := s.server.txMemPool.LastUpdated()
	latestHash, latestHeight := s.server.blockManager.chainState.Best()
	msgBlock := state.msgBlock
	if msgBlock == nil || state.prevHash == nil ||
		!state.prevHash.IsEqual(latestHash) ||
		(state.lastTxUpdate != lastTxUpdate &&
			time.Now().After(state.lastGenerated.Add(time.Minute))) {

		// Reset the extra nonce and clear all cached template
		// variations if the best block changed.
		if state.prevHash != nil && !state.prevHash.IsEqual(latestHash) {
			state.extraNonce = 0
			state.blockInfo = make(map[btcwire.ShaHash]*workStateBlockInfo)
		}

		// Reset the previous best hash the block template was generated
		// against so any errors below cause the next invocation to try
		// again.
		state.prevHash = nil

		// Choose a payment address at random.
		payToAddr := cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))]

		template, err := NewBlockTemplate(s.server.txMemPool, payToAddr)
		if err != nil {
			errStr := fmt.Sprintf("Failed to create new block "+
				"template: %v", err)
			rpcsLog.Error(errStr)
			return nil, btcjson.Error{
				Code:    btcjson.ErrInternal.Code,
				Message: errStr,
			}
		}
		msgBlock = template.block

		// Update work state to ensure another block template isn't
		// generated until needed.
		state.msgBlock = msgBlock
		state.lastGenerated = time.Now()
		state.lastTxUpdate = lastTxUpdate
		state.prevHash = latestHash

		rpcsLog.Debugf("Generated block template (timestamp %v, extra "+
			"nonce %d, target %064x, merkle root %s, signature "+
			"script %x)", msgBlock.Header.Timestamp,
			state.extraNonce,
			btcchain.CompactToBig(msgBlock.Header.Bits),
			msgBlock.Header.MerkleRoot,
			msgBlock.Transactions[0].TxIn[0].SignatureScript)
	} else {
		// At this point, there is a saved block template and a new
		// request for work was made, but either the available
		// transactions haven't change or it hasn't been long enough to
		// trigger a new block template to be generated.  So, update the
		// existing block template and track the variations so each
		// variation can be regenerated if a caller finds an answer and
		// makes a submission against it.

		// Update the time of the block template to the current time
		// while accounting for the median time of the past several
		// blocks per the chain consensus rules.
		UpdateBlockTime(msgBlock, s.server.blockManager)

		// Increment the extra nonce and update the block template
		// with the new value by regenerating the coinbase script and
		// setting the merkle root to the new value.
		state.extraNonce++
		err := UpdateExtraNonce(msgBlock, latestHeight+1, state.extraNonce)
		if err != nil {
			errStr := fmt.Sprintf("Failed to update extra nonce: "+
				"%v", err)
			rpcsLog.Warnf(errStr)
			return nil, btcjson.Error{
				Code:    btcjson.ErrInternal.Code,
				Message: errStr,
			}
		}

		rpcsLog.Debugf("Updated block template (timestamp %v, extra "+
			"nonce %d, target %064x, merkle root %s, signature "+
			"script %x)", msgBlock.Header.Timestamp,
			state.extraNonce,
			btcchain.CompactToBig(msgBlock.Header.Bits),
			msgBlock.Header.MerkleRoot,
			msgBlock.Transactions[0].TxIn[0].SignatureScript)
	}

	// In order to efficiently store the variations of block templates that
	// have been provided to callers, save a pointer to the block as well as
	// the modified signature script keyed by the merkle root.  This
	// information, along with the data that is included in a work
	// submission, is used to rebuild the block before checking the
	// submitted solution.
	coinbaseTx := msgBlock.Transactions[0]
	state.blockInfo[msgBlock.Header.MerkleRoot] = &workStateBlockInfo{
		msgBlock:        msgBlock,
		signatureScript: coinbaseTx.TxIn[0].SignatureScript,
	}

	// Serialize the block header into a buffer large enough to hold the
	// the block header and the internal sha256 padding that is added and
	// retuned as part of the data below.
	data := make([]byte, 0, getworkDataLen)
	buf := bytes.NewBuffer(data)
	err := msgBlock.Header.Serialize(buf)
	if err != nil {
		errStr := fmt.Sprintf("Failed to serialize data: %v", err)
		rpcsLog.Warnf(errStr)
		return nil, btcjson.Error{
			Code:    btcjson.ErrInternal.Code,
			Message: errStr,
		}
	}

	// Calculate the midstate for the block header.  The midstate here is
	// the internal state of the sha256 algorithm for the first chunk of the
	// block header (sha256 operates on 64-byte chunks) which is before the
	// nonce.  This allows sophisticated callers to avoid hashing the first
	// chunk over and over while iterating the nonce range.
	data = data[:buf.Len()]
	midstate := fastsha256.MidState256(data)

	// Expand the data slice to include the full data buffer and apply the
	// internal sha256 padding which consists of a single 1 bit followed
	// by enough zeros to pad the message out to 56 bytes followed by the
	// length of the message in bits encoded as a big-endian uint64
	// (8 bytes).  Thus, the resulting length is a multiple of the sha256
	// block size (64 bytes).  This makes the data ready for sophisticated
	// caller to make use of only the second chunk along with the midstate
	// for the first chunk.
	data = data[:getworkDataLen]
	data[btcwire.MaxBlockHeaderPayload] = 0x80
	binary.BigEndian.PutUint64(data[len(data)-8:],
		btcwire.MaxBlockHeaderPayload*8)

	// Create the hash1 field which is a zero hash along with the internal
	// sha256 padding as described above.  This field is really quite
	// useless, but it is required for compatibility with the reference
	// implementation.
	var hash1 [hash1Len]byte
	hash1[btcwire.HashSize] = 0x80
	binary.BigEndian.PutUint64(hash1[len(hash1)-8:], btcwire.HashSize*8)

	// The final result reverses the each of the fields to little endian.
	// In particular, the data, hash1, and midstate fields are treated as
	// arrays of uint32s (per the internal sha256 hashing state) which are
	// in big endian, and thus each 4 bytes is byte swapped.  The target is
	// also in big endian, but it is treated as a uint256 and byte swapped
	// to little endian accordingly.
	//
	// The fact the fields are reversed in this way is rather odd and likey
	// an artifact of some legacy internal state in the reference
	// implementation, but it is required for compatibility.
	reverseUint32Array(data)
	reverseUint32Array(hash1[:])
	reverseUint32Array(midstate[:])
	target := bigToLEUint256(btcchain.CompactToBig(msgBlock.Header.Bits))
	reply := &btcjson.GetWorkResult{
		Data:     hex.EncodeToString(data),
		Hash1:    hex.EncodeToString(hash1[:]),
		Midstate: hex.EncodeToString(midstate[:]),
		Target:   hex.EncodeToString(target[:]),
	}
	return reply, nil
}

// handleGetWorkSubmission is a helper for handleGetWork which deals with
// the calling submitting work to be verified and processed.
//
// This function MUST be called with the RPC workstate locked.
func handleGetWorkSubmission(s *rpcServer, hexData string) (interface{}, error) {
	// Ensure the provided data is sane.
	if len(hexData)%2 != 0 {
		hexData = "0" + hexData
	}
	data, err := hex.DecodeString(hexData)
	if err != nil {
		return false, btcjson.Error{
			Code: btcjson.ErrDecodeHexString.Code,
			Message: fmt.Sprintf("argument must be "+
				"hexadecimal string (not %q)", hexData),
		}
	}
	if len(data) != getworkDataLen {
		return false, btcjson.Error{
			Code: btcjson.ErrInvalidParameter.Code,
			Message: fmt.Sprintf("argument must be "+
				"%d bytes (not %d)", getworkDataLen,
				len(data)),
		}
	}

	// Reverse the data as if it were an array of 32-bit unsigned integers.
	// The fact the getwork request and submission data is reversed in this
	// way is rather odd and likey an artifact of some legacy internal state
	// in the reference implementation, but it is required for
	// compatibility.
	reverseUint32Array(data)

	// Deserialize the block header from the data.
	var submittedHeader btcwire.BlockHeader
	bhBuf := bytes.NewReader(data[0:btcwire.MaxBlockHeaderPayload])
	err = submittedHeader.Deserialize(bhBuf)
	if err != nil {
		return false, btcjson.Error{
			Code: btcjson.ErrInvalidParameter.Code,
			Message: fmt.Sprintf("argument does not "+
				"contain a valid block header: %v", err),
		}
	}

	// Look up the full block for the provided data based on the
	// merkle root.  Return false to indicate the solve failed if
	// it's not available.
	state := s.workState
	blockInfo, ok := state.blockInfo[submittedHeader.MerkleRoot]
	if !ok {
		rpcsLog.Debugf("Block submitted via getwork has no matching "+
			"template for merkle root %s",
			submittedHeader.MerkleRoot)
		return false, nil
	}

	// Reconstruct the block using the submitted header stored block info.
	msgBlock := blockInfo.msgBlock
	block := btcutil.NewBlock(msgBlock)
	msgBlock.Header.Timestamp = submittedHeader.Timestamp
	msgBlock.Header.Nonce = submittedHeader.Nonce
	msgBlock.Transactions[0].TxIn[0].SignatureScript = blockInfo.signatureScript
	merkles := btcchain.BuildMerkleTreeStore(block.Transactions())
	msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1]

	// Ensure the submitted block hash is less than the target difficulty.
	err = btcchain.CheckProofOfWork(block, activeNetParams.PowLimit)
	if err != nil {
		// Anything other than a rule violation is an unexpected error,
		// so return that error as an internal error.
		if _, ok := err.(btcchain.RuleError); !ok {
			return false, btcjson.Error{
				Code: btcjson.ErrInternal.Code,
				Message: fmt.Sprintf("Unexpected error while "+
					"checking proof of work: %v", err),
			}
		}

		rpcsLog.Debugf("Block submitted via getwork does not meet "+
			"the required proof of work: %v", err)
		return false, nil
	}

	latestHash, _ := s.server.blockManager.chainState.Best()
	if !msgBlock.Header.PrevBlock.IsEqual(latestHash) {
		rpcsLog.Debugf("Block submitted via getwork with previous "+
			"block %s is stale", msgBlock.Header.PrevBlock)
		return false, nil
	}

	// Process this block using the same rules as blocks coming from other
	// nodes.  This will in turn relay it to the network like normal.
	isOrphan, err := s.server.blockManager.ProcessBlock(block, btcchain.BFNone)
	if err != nil || isOrphan {
		// Anything other than a rule violation is an unexpected error,
		// so return that error as an internal error.
		if _, ok := err.(btcchain.RuleError); !ok {
			return false, btcjson.Error{
				Code: btcjson.ErrInternal.Code,
				Message: fmt.Sprintf("Unexpected error while "+
					"processing block: %v", err),
			}
		}

		rpcsLog.Infof("Block submitted via getwork rejected: %v", err)
		return false, nil
	}

	// The block was accepted.
	blockSha, _ := block.Sha()
	rpcsLog.Infof("Block submitted via getwork accepted: %s", blockSha)
	return true, nil
}

// handleGetWork implements the getwork command.
func handleGetWork(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.GetWorkCmd)

	// Respond with an error if there are no addresses to pay the created
	// blocks to.
	if len(cfg.miningAddrs) == 0 {
		return nil, btcjson.Error{
			Code:    btcjson.ErrInternal.Code,
			Message: "No payment addresses specified via --miningaddr",
		}
	}

	// Return an error if there are no peers connected since there is no
	// way to relay a found block or receive transactions to work on.
	// However, allow this state when running in the regression test or
	// simulation test mode.
	if !(cfg.RegressionTest || cfg.SimNet) && s.server.ConnectedCount() == 0 {
		return nil, btcjson.ErrClientNotConnected
	}

	// No point in generating or accepting work before the chain is synced.
	_, currentHeight := s.server.blockManager.chainState.Best()
	if currentHeight != 0 && !s.server.blockManager.IsCurrent() {
		return nil, btcjson.ErrClientInInitialDownload
	}

	// Protect concurrent access from multiple RPC invocations for work
	// requests and submission.
	s.workState.Lock()
	defer s.workState.Unlock()

	// When the caller provides data, it is a submission of a supposedly
	// solved block that needs to be checked and submitted to the network
	// if valid.
	if c.Data != "" {
		return handleGetWorkSubmission(s, c.Data)
	}

	// No data was provided, so the caller is requesting work.
	return handleGetWorkRequest(s)
}

var helpAddenda = map[string]string{
	"sendrawtransaction": `
NOTE: btcd does not currently support the "allowhighfees" parameter.`,
}

// getHelp text retreives help text from btcjson for the command in question.
// If there is any extra btcd specific information related to the given command
// then this is appended to the string.
func getHelpText(cmdName string) (string, error) {
	help, err := btcjson.GetHelpString(cmdName)
	if err != nil {
		return "", err
	}
	if helpAddendum, ok := helpAddenda[cmdName]; ok {
		help += helpAddendum
	}

	return help, nil
}

// handleHelp implements the help command.
func handleHelp(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	help := cmd.(*btcjson.HelpCmd)

	// if no args we give a list of all known commands
	if help.Command == "" {
		commands := ""
		first := true
		// TODO(oga) this should have one liner usage for each command
		// really, but for now just a list of commands is sufficient.
		for k := range rpcHandlers {
			if !first {
				commands += "\n"
			}
			commands += k
			first = false
		}
		return commands, nil
	}

	// Check that we actually support the command asked for. We only
	// search the main list of hanlders since we do not wish to provide help
	// for commands that are unimplemented or relate to wallet
	// functionality.
	if _, ok := rpcHandlers[help.Command]; !ok {
		return "", fmt.Errorf("help: unknown command: %s", help.Command)
	}

	return getHelpText(help.Command)
}

// handlePing implements the ping command.
func handlePing(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	// Ask server to ping \o_
	nonce, err := btcwire.RandomUint64()
	if err != nil {
		return nil, fmt.Errorf("Not sending ping - can not generate "+
			"nonce: %v", err)
	}
	s.server.BroadcastMessage(btcwire.NewMsgPing(nonce))

	return nil, nil
}

// handleSendRawTransaction implements the sendrawtransaction command.
func handleSendRawTransaction(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.SendRawTransactionCmd)
	// Deserialize and send off to tx relay
	hexStr := c.HexTx
	if len(hexStr)%2 != 0 {
		hexStr = "0" + hexStr
	}
	serializedTx, err := hex.DecodeString(hexStr)
	if err != nil {
		return nil, btcjson.Error{
			Code: btcjson.ErrDecodeHexString.Code,
			Message: fmt.Sprintf("argument must be hexadecimal "+
				"string (not %q)", hexStr),
		}
	}
	msgtx := btcwire.NewMsgTx()
	err = msgtx.Deserialize(bytes.NewReader(serializedTx))
	if err != nil {
		err := btcjson.Error{
			Code:    btcjson.ErrDeserialization.Code,
			Message: "TX decode failed",
		}
		return nil, err
	}

	tx := btcutil.NewTx(msgtx)
	err = s.server.txMemPool.ProcessTransaction(tx, false, false)
	if err != nil {
		// When the error is a rule error, it means the transaction was
		// simply rejected as opposed to something actually going wrong,
		// so log it as such.  Otherwise, something really did go wrong,
		// so log it as an actual error.  In both cases, a JSON-RPC
		// error is returned to the client with the deserialization
		// error code (to match bitcoind behavior).
		if _, ok := err.(RuleError); ok {
			rpcsLog.Debugf("Rejected transaction %v: %v", tx.Sha(),
				err)
		} else {
			rpcsLog.Errorf("Failed to process transaction %v: %v",
				tx.Sha(), err)
		}
		err = btcjson.Error{
			Code:    btcjson.ErrDeserialization.Code,
			Message: fmt.Sprintf("TX rejected: %v", err),
		}
		return nil, err
	}

	// We keep track of all the sendrawtransaction request txs so that we
	// can rebroadcast them if they don't make their way into a block.
	iv := btcwire.NewInvVect(btcwire.InvTypeTx, tx.Sha())
	s.server.AddRebroadcastInventory(iv)

	return tx.Sha().String(), nil
}

// handleSetGenerate implements the setgenerate command.
func handleSetGenerate(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.SetGenerateCmd)

	// Disable generation regardless of the provided generate flag if the
	// maximum number of threads (goroutines for our purposes) is 0.
	// Otherwise enable or disable it depending on the provided flag.
	generate := c.Generate
	if c.GenProcLimit == 0 {
		generate = false
	}

	if !generate {
		s.server.cpuMiner.Stop()
	} else {
		// Respond with an error if there are no addresses to pay the
		// created blocks to.
		if len(cfg.miningAddrs) == 0 {
			return nil, btcjson.Error{
				Code: btcjson.ErrInternal.Code,
				Message: "No payment addresses specified " +
					"via --miningaddr",
			}
		}

		// It's safe to call start even if it's already started.
		s.server.cpuMiner.SetNumWorkers(int32(c.GenProcLimit))
		s.server.cpuMiner.Start()
	}
	return nil, nil
}

// handleStop implements the stop command.
func handleStop(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	s.server.Stop()
	return "btcd stopping.", nil
}

// handleSubmitBlock implements the submitblock command.
func handleSubmitBlock(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.SubmitBlockCmd)

	// Deserialize the submitted block.
	hexStr := c.HexBlock
	if len(hexStr)%2 != 0 {
		hexStr = "0" + c.HexBlock
	}
	serializedBlock, err := hex.DecodeString(hexStr)
	if err != nil {
		return nil, btcjson.Error{
			Code: btcjson.ErrDecodeHexString.Code,
			Message: fmt.Sprintf("argument must be hexadecimal "+
				"string (not %q)", hexStr),
		}
	}

	block, err := btcutil.NewBlockFromBytes(serializedBlock)
	if err != nil {
		return nil, btcjson.Error{
			Code:    btcjson.ErrDeserialization.Code,
			Message: "Block decode failed",
		}
	}

	_, err = s.server.blockManager.ProcessBlock(block, btcchain.BFNone)
	if err != nil {
		return fmt.Sprintf("rejected: %s", err.Error()), nil
	}

	blockSha, err := block.Sha()
	if err == nil {
		rpcsLog.Infof("Accepted block %s via submitblock", blockSha)
	}
	return nil, nil
}

func verifyChain(db database.Db, level, depth int32, timeSource btcchain.MedianTimeSource) error {
	_, curHeight64, err := db.NewestSha()
	if err != nil {
		rpcsLog.Errorf("Verify is unable to fetch current block "+
			"height: %v", err)
	}
	curHeight := int32(curHeight64)

	finishHeight := curHeight - depth
	if finishHeight < 0 {
		finishHeight = 0
	}
	rpcsLog.Infof("Verifying chain for %d blocks at level %d",
		curHeight-finishHeight, level)

	for height := curHeight; height > finishHeight; height-- {
		// Level 0 just looks up the block.
		sha, err := db.FetchBlockShaByHeight(int64(height))
		if err != nil {
			rpcsLog.Errorf("Verify is unable to fetch block at "+
				"height %d: %v", height, err)
			return err
		}

		block, err := db.FetchBlockBySha(sha)
		if err != nil {
			rpcsLog.Errorf("Verify is unable to fetch block at "+
				"sha %v height %d: %v", sha, height, err)
			return err
		}

		// Level 1 does basic chain sanity checks.
		if level > 0 {
			err := btcchain.CheckBlockSanity(block,
				activeNetParams.PowLimit, timeSource)
			if err != nil {
				rpcsLog.Errorf("Verify is unable to "+
					"validate block at sha %v height "+
					"%d: %v", sha, height, err)
				return err
			}
		}
	}
	rpcsLog.Infof("Chain verify completed successfully")

	return nil
}

// handleValidateAddress implements the validateaddress command.
func handleValidateAddress(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.ValidateAddressCmd)

	result := btcjson.ValidateAddressResult{}
	addr, err := btcutil.DecodeAddress(c.Address, activeNetParams.Params)
	if err != nil {
		// Return the default value (false) for IsValid.
		return result, nil
	}

	result.Address = addr.EncodeAddress()
	result.IsValid = true

	return result, nil
}

// handleVerifyChain implements the verifychain command.
func handleVerifyChain(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.VerifyChainCmd)

	err := verifyChain(s.server.db, c.CheckLevel, c.CheckDepth,
		s.server.timeSource)
	return err == nil, nil
}

// handleVerifyMessage implements the verifymessage command.
func handleVerifyMessage(s *rpcServer, cmd btcjson.Cmd, closeChan <-chan struct{}) (interface{}, error) {
	c := cmd.(*btcjson.VerifyMessageCmd)

	// Decode the provided address.
	addr, err := btcutil.DecodeAddress(c.Address, activeNetParams.Params)
	if err != nil {
		return nil, btcjson.Error{
			Code: btcjson.ErrInvalidAddressOrKey.Code,
			Message: fmt.Sprintf("%s: %v",
				btcjson.ErrInvalidAddressOrKey.Message, err),
		}
	}

	// Only P2PKH addresses are valid for signing.
	if _, ok := addr.(*btcutil.AddressPubKeyHash); !ok {
		return nil, btcjson.Error{
			Code:    btcjson.ErrType.Code,
			Message: "Address is not a pay-to-pubkey-hash address",
		}
	}

	// Decode base64 signature.
	sig, err := base64.StdEncoding.DecodeString(c.Signature)
	if err != nil {
		return nil, btcjson.Error{
			Code:    btcjson.ErrParse.Code,
			Message: fmt.Sprintf("Malformed base64 encoding: %v", err),
		}
	}

	// Validate the signature - this just shows that it was valid at all.
	// we will compare it with the key next.
	pk, wasCompressed, err := btcec.RecoverCompact(btcec.S256(), sig,
		btcwire.DoubleSha256([]byte("Bitcoin Signed Message:\n"+c.Message)))
	if err != nil {
		// Mirror Bitcoin Core behavior, which treats error in RecoverCompact as
		// invalid signature.
		return false, nil
	}

	// Reconstruct the pubkey hash.
	btcPK := (*btcec.PublicKey)(pk)
	var serializedPK []byte
	if wasCompressed {
		serializedPK = btcPK.SerializeCompressed()
	} else {
		serializedPK = btcPK.SerializeUncompressed()
	}
	address, err := btcutil.NewAddressPubKey(serializedPK,
		activeNetParams.Params)
	if err != nil {
		// Again mirror Bitcoin Core behavior, which treats error in public key
		// reconstruction as invalid signature.
		return false, nil
	}

	// Return boolean if addresses match.
	return address.EncodeAddress() == c.Address, nil
}

// parseCmd parses a marshaled known command, returning any errors as a
// btcjson.Error that can be used in replies.  The returned cmd may still
// be non-nil if b is at least a valid marshaled JSON-RPC message.
func parseCmd(b []byte) (btcjson.Cmd, *btcjson.Error) {
	cmd, err := btcjson.ParseMarshaledCmd(b)
	if err != nil {
		jsonErr, ok := err.(btcjson.Error)
		if !ok {
			jsonErr = btcjson.Error{
				Code:    btcjson.ErrParse.Code,
				Message: err.Error(),
			}
		}
		return cmd, &jsonErr
	}
	return cmd, nil
}

// standardCmdReply checks that a parsed command is a standard
// Bitcoin JSON-RPC command and runs the proper handler to reply to the
// command.
func standardCmdReply(cmd btcjson.Cmd, s *rpcServer, closeChan <-chan struct{}) (reply btcjson.Reply) {
	id := cmd.Id()
	reply.Id = &id

	handler, ok := rpcHandlers[cmd.Method()]
	if ok {
		goto handled
	}
	_, ok = rpcAskWallet[cmd.Method()]
	if ok {
		handler = handleAskWallet
		goto handled
	}
	_, ok = rpcUnimplemented[cmd.Method()]
	if ok {
		handler = handleUnimplemented
		goto handled
	}
	reply.Error = &btcjson.ErrMethodNotFound
	return reply
handled:

	result, err := handler(s, cmd, closeChan)
	if err != nil {
		jsonErr, ok := err.(btcjson.Error)
		if !ok {
			// In the case where we did not have a btcjson
			// error to begin with, make a new one to send,
			// but this really should not happen.
			jsonErr = btcjson.Error{
				Code:    btcjson.ErrInternal.Code,
				Message: err.Error(),
			}
		}
		reply.Error = &jsonErr
	} else {
		reply.Result = result
	}
	return reply
}

// getDifficultyRatio returns the proof-of-work difficulty as a multiple of the
// minimum difficulty using the passed bits field from the header of a block.
func getDifficultyRatio(bits uint32) float64 {
	// The minimum difficulty is the max possible proof-of-work limit bits
	// converted back to a number.  Note this is not the same as the the
	// proof of work limit directly because the block difficulty is encoded
	// in a block with the compact form which loses precision.
	max := btcchain.CompactToBig(activeNetParams.PowLimitBits)
	target := btcchain.CompactToBig(bits)

	difficulty := new(big.Rat).SetFrac(max, target)
	outString := difficulty.FloatString(2)
	diff, err := strconv.ParseFloat(outString, 64)
	if err != nil {
		rpcsLog.Errorf("Cannot get difficulty: %v", err)
		return 0
	}
	return diff
}

func init() {
	rpcHandlers = rpcHandlersBeforeInit
	rand.Seed(time.Now().UnixNano())
}