From 1bae334dd9ff797046378e521e3ede4fffcdae14 Mon Sep 17 00:00:00 2001 From: Donald Adu-Poku Date: Thu, 5 Sep 2019 12:11:00 +0000 Subject: [PATCH] multi: remove getblocktemplate. This removes the getblocktemplate and its helpers from the codebase. Ongoing mining updates focused on the voting/block validation process with respect to generating block templates for getwork makes it the better option for decred. Also getblocktemplate rpc was buggy and has been disabled for a while. Some lint related issues have been addressed as well. --- blockmanager.go | 17 +- cmd/dcrctl/config.go | 2 +- cmd/dcrctl/dcrctl.go | 2 +- config.go | 2 +- cpuminer.go | 2 +- go.mod | 6 +- go.sum | 12 +- rpc/jsonrpc/types/chainsvrcmds.go | 92 --- rpc/jsonrpc/types/chainsvrcmds_test.go | 135 ---- rpc/jsonrpc/types/chainsvrresults.go | 55 -- rpc/jsonrpc/types/go.mod | 2 +- rpcclient/chain.go | 2 +- rpcclient/extensions.go | 2 +- rpcclient/go.mod | 6 +- rpcclient/infrastructure.go | 2 +- rpcclient/mining.go | 41 +- rpcclient/net.go | 2 +- rpcclient/notify.go | 2 +- rpcclient/rawtransactions.go | 2 +- rpcclient/wallet.go | 7 +- rpcserver.go | 946 +------------------------ rpcserverhelp.go | 61 +- rpctest/rpc_harness_test.go | 2 +- rpctest/utils.go | 2 +- rpctest/votingwallet.go | 2 +- rpcwebsocket.go | 2 +- server.go | 9 +- 27 files changed, 34 insertions(+), 1383 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index 8a5e098b..d6cc741c 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -297,8 +297,7 @@ type headerNode struct { // PeerNotifier provides an interface for server peer notifications. type PeerNotifier interface { // AnnounceNewTransactions generates and relays inventory vectors and - // notifies both websocket and getblocktemplate long poll clients of - // the passed transactions. + // notifies websocket clients of the passed transactions. AnnounceNewTransactions(txns []*dcrutil.Tx) // UpdatePeerHeights updates the heights of all peers who have @@ -1071,13 +1070,6 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // Clear the rejected transactions. b.rejectedTxns = make(map[chainhash.Hash]struct{}) - - // Allow any clients performing long polling via the - // getblocktemplate RPC to be notified when the new block causes - // their old block template to become stale. - if r := b.cfg.RpcServer(); r != nil { - r.gbtWorkState.NotifyBlockConnected(blockHash) - } } } @@ -1646,13 +1638,6 @@ out: b.cfg.TxMemPool.PruneExpiredTx() } - // Allow any clients performing long polling via the - // getblocktemplate RPC to be notified when the new block causes - // their old block template to become stale. - if r != nil { - r.gbtWorkState.NotifyBlockConnected(msg.block.Hash()) - } - msg.reply <- processBlockResponse{ isOrphan: isOrphan, err: nil, diff --git a/cmd/dcrctl/config.go b/cmd/dcrctl/config.go index 0693d57b..6604599e 100644 --- a/cmd/dcrctl/config.go +++ b/cmd/dcrctl/config.go @@ -20,7 +20,7 @@ import ( "github.com/decred/dcrd/dcrutil/v2" "github.com/decred/dcrd/internal/version" - dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types" + dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v2" wallettypes "github.com/decred/dcrwallet/rpc/jsonrpc/types" flags "github.com/jessevdk/go-flags" diff --git a/cmd/dcrctl/dcrctl.go b/cmd/dcrctl/dcrctl.go index 94640b38..6c2bd955 100644 --- a/cmd/dcrctl/dcrctl.go +++ b/cmd/dcrctl/dcrctl.go @@ -16,7 +16,7 @@ import ( "strings" "github.com/decred/dcrd/dcrjson/v3" - dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types" + dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v2" wallettypes "github.com/decred/dcrwallet/rpc/jsonrpc/types" ) diff --git a/config.go b/config.go index 3e02a063..5a279acb 100644 --- a/config.go +++ b/config.go @@ -27,7 +27,7 @@ import ( "github.com/decred/dcrd/dcrutil/v2" "github.com/decred/dcrd/internal/version" "github.com/decred/dcrd/mempool/v3" - "github.com/decred/dcrd/rpc/jsonrpc/types" + "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/sampleconfig" "github.com/decred/go-socks/socks" "github.com/decred/slog" diff --git a/cpuminer.go b/cpuminer.go index 4d69104d..c11ab518 100644 --- a/cpuminer.go +++ b/cpuminer.go @@ -610,7 +610,7 @@ func (m *CPUMiner) GenerateNBlocks(n uint32) ([]*chainhash.Hash, error) { if m.started || m.discreteMining { m.Unlock() return nil, errors.New("server is already CPU mining. Please call " + - "`setgenerate 0` before calling discrete `generate` commands.") + "`setgenerate 0` before calling discrete `generate` commands") } m.started = true diff --git a/go.mod b/go.mod index f4ff76ce..e642fba5 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/decred/dcrd/mempool/v3 v3.0.0 github.com/decred/dcrd/mining/v2 v2.0.0 github.com/decred/dcrd/peer/v2 v2.0.0 - github.com/decred/dcrd/rpc/jsonrpc/types v1.0.0 + github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.0.0 github.com/decred/dcrd/rpcclient/v5 v5.0.0 github.com/decred/dcrd/txscript/v2 v2.0.0 github.com/decred/dcrd/wire v1.2.0 @@ -36,12 +36,10 @@ require ( github.com/jessevdk/go-flags v1.4.0 github.com/jrick/bitset v1.0.0 github.com/jrick/logrotate v1.0.0 - github.com/kr/pretty v0.1.0 // indirect github.com/onsi/ginkgo v1.7.0 // indirect github.com/onsi/gomega v1.4.3 // indirect golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect - gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/yaml.v2 v2.2.2 // indirect ) @@ -66,7 +64,7 @@ replace ( github.com/decred/dcrd/mempool/v3 => ./mempool github.com/decred/dcrd/mining/v2 => ./mining github.com/decred/dcrd/peer/v2 => ./peer - github.com/decred/dcrd/rpc/jsonrpc/types => ./rpc/jsonrpc/types + github.com/decred/dcrd/rpc/jsonrpc/types/v2 => ./rpc/jsonrpc/types github.com/decred/dcrd/rpcclient/v5 => ./rpcclient github.com/decred/dcrd/txscript/v2 => ./txscript github.com/decred/dcrd/wire => ./wire diff --git a/go.sum b/go.sum index aeaaa6fc..758d7d62 100644 --- a/go.sum +++ b/go.sum @@ -9,7 +9,6 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dchest/blake256 v1.0.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY= github.com/dchest/blake256 v1.1.0 h1:4AuEhGPT/3TTKFhTfBpZ8hgZE7wJpawcYaEawwsbtqM= github.com/dchest/blake256 v1.1.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY= github.com/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4= @@ -25,8 +24,8 @@ github.com/decred/dcrd/dcrec/edwards v1.0.0/go.mod h1:HblVh1OfMt7xSxUL1ufjToaEvp github.com/decred/dcrd/dcrec/secp256k1 v1.0.1/go.mod h1:lhu4eZFSfTJWUnR3CFRcpD+Vta0KUAqnhTsTksHXgy0= github.com/decred/dcrd/dcrec/secp256k1 v1.0.2 h1:awk7sYJ4pGWmtkiGHFfctztJjHMKGLV8jctGQhAbKe0= github.com/decred/dcrd/dcrec/secp256k1 v1.0.2/go.mod h1:CHTUIVfmDDd0KFVFpNX1pFVCBUegxW387nN0IGwNKR0= -github.com/decred/dcrd/gcs v1.1.0 h1:djuYzaFUzUTJR+6ulMSRZOQ+P9rxtIyuxQeViAEfB8s= -github.com/decred/dcrd/gcs v1.1.0/go.mod h1:yBjhj217Vw5lw3aKnCdHip7fYb9zwMos8bCy5s79M9w= +github.com/decred/dcrd/rpc/jsonrpc/types v1.0.0 h1:d5ptnjuSADTQMa3i83VpeJNoMRTOJZZBqk7P+E41VXM= +github.com/decred/dcrd/rpc/jsonrpc/types v1.0.0/go.mod h1:0dwmpIP21tJxjg/UuUHWIFMbfoLv2ifCBMokNKlOxpo= github.com/decred/dcrwallet/rpc/jsonrpc/types v1.1.0 h1:ZOMpbSK/Cz8D8Yfrt7/yNfS+myBUWMNOdgAg31ND7bM= github.com/decred/dcrwallet/rpc/jsonrpc/types v1.1.0/go.mod h1:xUT7XXATLOzE0pwwmvgfRWtZdrB+PsWFilo+jkH5/Ig= github.com/decred/dcrwallet/rpc/jsonrpc/types v1.2.0 h1:k17F1rYmYRqX3iO8nQBrSacbB8A50qNU+HT3gfNo4dw= @@ -49,11 +48,6 @@ github.com/jrick/bitset v1.0.0 h1:Ws0PXV3PwXqWK2n7Vz6idCdrV/9OrBXgHEJi27ZB9Dw= github.com/jrick/bitset v1.0.0/go.mod h1:ZOYB5Uvkla7wIEY4FEssPVi3IQXa02arznRaYaAEPe4= github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= @@ -81,8 +75,6 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= diff --git a/rpc/jsonrpc/types/chainsvrcmds.go b/rpc/jsonrpc/types/chainsvrcmds.go index 5488e447..d02d4e66 100644 --- a/rpc/jsonrpc/types/chainsvrcmds.go +++ b/rpc/jsonrpc/types/chainsvrcmds.go @@ -9,9 +9,6 @@ package types import ( - "encoding/json" - "fmt" - "github.com/decred/dcrd/dcrjson/v3" ) @@ -463,94 +460,6 @@ func NewGetBlockSubsidyCmd(height int64, voters uint16) *GetBlockSubsidyCmd { } } -// TemplateRequest is a request object as defined in BIP22 -// (https://en.bitcoin.it/wiki/BIP_0022), it is optionally provided as an -// pointer argument to GetBlockTemplateCmd. -type TemplateRequest struct { - Mode string `json:"mode,omitempty"` - Capabilities []string `json:"capabilities,omitempty"` - - // Optional long polling. - LongPollID string `json:"longpollid,omitempty"` - - // Optional template tweaking. SigOpLimit and SizeLimit can be int64 - // or bool. - SigOpLimit interface{} `json:"sigoplimit,omitempty"` - SizeLimit interface{} `json:"sizelimit,omitempty"` - MaxVersion uint32 `json:"maxversion,omitempty"` - - // Basic pool extension from BIP 0023. - Target string `json:"target,omitempty"` - - // Block proposal from BIP 0023. Data is only provided when Mode is - // "proposal". - Data string `json:"data,omitempty"` - WorkID string `json:"workid,omitempty"` -} - -// convertTemplateRequestField potentially converts the provided value as -// needed. -func convertTemplateRequestField(fieldName string, iface interface{}) (interface{}, error) { - switch val := iface.(type) { - case nil: - return nil, nil - case bool: - return val, nil - case float64: - if val == float64(int64(val)) { - return int64(val), nil - } - } - - str := fmt.Sprintf("the %s field must be unspecified, a boolean, or "+ - "a 64-bit integer", fieldName) - return nil, dcrjson.Error{Code: dcrjson.ErrInvalidType, Message: str} -} - -// UnmarshalJSON provides a custom Unmarshal method for TemplateRequest. This -// is necessary because the SigOpLimit and SizeLimit fields can only be specific -// types. -func (t *TemplateRequest) UnmarshalJSON(data []byte) error { - type templateRequest TemplateRequest - - request := (*templateRequest)(t) - if err := json.Unmarshal(data, &request); err != nil { - return err - } - - // The SigOpLimit field can only be nil, bool, or int64. - val, err := convertTemplateRequestField("sigoplimit", request.SigOpLimit) - if err != nil { - return err - } - request.SigOpLimit = val - - // The SizeLimit field can only be nil, bool, or int64. - val, err = convertTemplateRequestField("sizelimit", request.SizeLimit) - if err != nil { - return err - } - request.SizeLimit = val - - return nil -} - -// GetBlockTemplateCmd defines the getblocktemplate JSON-RPC command. -type GetBlockTemplateCmd struct { - Request *TemplateRequest -} - -// NewGetBlockTemplateCmd returns a new instance which can be used to issue a -// getblocktemplate JSON-RPC command. -// -// The parameters which are pointers indicate they are optional. Passing nil -// for optional parameters will use the default value. -func NewGetBlockTemplateCmd(request *TemplateRequest) *GetBlockTemplateCmd { - return &GetBlockTemplateCmd{ - Request: request, - } -} - // GetCFilterCmd defines the getcfilter JSON-RPC command. type GetCFilterCmd struct { Hash string @@ -1226,7 +1135,6 @@ func init() { dcrjson.MustRegister(Method("getblockhash"), (*GetBlockHashCmd)(nil), flags) dcrjson.MustRegister(Method("getblockheader"), (*GetBlockHeaderCmd)(nil), flags) dcrjson.MustRegister(Method("getblocksubsidy"), (*GetBlockSubsidyCmd)(nil), flags) - dcrjson.MustRegister(Method("getblocktemplate"), (*GetBlockTemplateCmd)(nil), flags) dcrjson.MustRegister(Method("getcfilter"), (*GetCFilterCmd)(nil), flags) dcrjson.MustRegister(Method("getcfilterheader"), (*GetCFilterHeaderCmd)(nil), flags) dcrjson.MustRegister(Method("getchaintips"), (*GetChainTipsCmd)(nil), flags) diff --git a/rpc/jsonrpc/types/chainsvrcmds_test.go b/rpc/jsonrpc/types/chainsvrcmds_test.go index e63feec6..88d0b009 100644 --- a/rpc/jsonrpc/types/chainsvrcmds_test.go +++ b/rpc/jsonrpc/types/chainsvrcmds_test.go @@ -343,89 +343,6 @@ func TestChainSvrCmds(t *testing.T) { Voters: 256, }, }, - { - name: "getblocktemplate", - newCmd: func() (interface{}, error) { - return dcrjson.NewCmd(Method("getblocktemplate")) - }, - staticCmd: func() interface{} { - return NewGetBlockTemplateCmd(nil) - }, - marshalled: `{"jsonrpc":"1.0","method":"getblocktemplate","params":[],"id":1}`, - unmarshalled: &GetBlockTemplateCmd{Request: nil}, - }, - { - name: "getblocktemplate optional - template request", - newCmd: func() (interface{}, error) { - return dcrjson.NewCmd(Method("getblocktemplate"), `{"mode":"template","capabilities":["longpoll","coinbasetxn"]}`) - }, - staticCmd: func() interface{} { - template := TemplateRequest{ - Mode: "template", - Capabilities: []string{"longpoll", "coinbasetxn"}, - } - return NewGetBlockTemplateCmd(&template) - }, - marshalled: `{"jsonrpc":"1.0","method":"getblocktemplate","params":[{"mode":"template","capabilities":["longpoll","coinbasetxn"]}],"id":1}`, - unmarshalled: &GetBlockTemplateCmd{ - Request: &TemplateRequest{ - Mode: "template", - Capabilities: []string{"longpoll", "coinbasetxn"}, - }, - }, - }, - { - name: "getblocktemplate optional - template request with tweaks", - newCmd: func() (interface{}, error) { - return dcrjson.NewCmd(Method("getblocktemplate"), `{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":500,"sizelimit":100000000,"maxversion":2}`) - }, - staticCmd: func() interface{} { - template := TemplateRequest{ - Mode: "template", - Capabilities: []string{"longpoll", "coinbasetxn"}, - SigOpLimit: 500, - SizeLimit: 100000000, - MaxVersion: 2, - } - return NewGetBlockTemplateCmd(&template) - }, - marshalled: `{"jsonrpc":"1.0","method":"getblocktemplate","params":[{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":500,"sizelimit":100000000,"maxversion":2}],"id":1}`, - unmarshalled: &GetBlockTemplateCmd{ - Request: &TemplateRequest{ - Mode: "template", - Capabilities: []string{"longpoll", "coinbasetxn"}, - SigOpLimit: int64(500), - SizeLimit: int64(100000000), - MaxVersion: 2, - }, - }, - }, - { - name: "getblocktemplate optional - template request with tweaks 2", - newCmd: func() (interface{}, error) { - return dcrjson.NewCmd(Method("getblocktemplate"), `{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":true,"sizelimit":100000000,"maxversion":2}`) - }, - staticCmd: func() interface{} { - template := TemplateRequest{ - Mode: "template", - Capabilities: []string{"longpoll", "coinbasetxn"}, - SigOpLimit: true, - SizeLimit: 100000000, - MaxVersion: 2, - } - return NewGetBlockTemplateCmd(&template) - }, - marshalled: `{"jsonrpc":"1.0","method":"getblocktemplate","params":[{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":true,"sizelimit":100000000,"maxversion":2}],"id":1}`, - unmarshalled: &GetBlockTemplateCmd{ - Request: &TemplateRequest{ - Mode: "template", - Capabilities: []string{"longpoll", "coinbasetxn"}, - SigOpLimit: true, - SizeLimit: int64(100000000), - MaxVersion: 2, - }, - }, - }, { name: "getcfilter", newCmd: func() (interface{}, error) { @@ -1250,55 +1167,3 @@ func TestChainSvrCmds(t *testing.T) { } } } - -// TestChainSvrCmdErrors ensures any errors that occur in the command during -// custom marshal and unmarshal are as expected. -func TestChainSvrCmdErrors(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - result interface{} - marshalled string - err error - }{ - { - name: "template request with invalid type", - result: &TemplateRequest{}, - marshalled: `{"mode":1}`, - err: &json.UnmarshalTypeError{}, - }, - { - name: "invalid template request sigoplimit field", - result: &TemplateRequest{}, - marshalled: `{"sigoplimit":"invalid"}`, - err: dcrjson.Error{Code: dcrjson.ErrInvalidType}, - }, - { - name: "invalid template request sizelimit field", - result: &TemplateRequest{}, - marshalled: `{"sizelimit":"invalid"}`, - err: dcrjson.Error{Code: dcrjson.ErrInvalidType}, - }, - } - - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - err := json.Unmarshal([]byte(test.marshalled), &test.result) - if reflect.TypeOf(err) != reflect.TypeOf(test.err) { - t.Errorf("Test #%d (%s) wrong error type - got `%T` (%v), got `%T`", - i, test.name, err, err, test.err) - continue - } - - if terr, ok := test.err.(dcrjson.Error); ok { - gotErrorCode := err.(dcrjson.Error).Code - if gotErrorCode != terr.Code { - t.Errorf("Test #%d (%s) mismatched error code "+ - "- got %v (%v), want %v", i, test.name, - gotErrorCode, terr, terr.Code) - continue - } - } - } -} diff --git a/rpc/jsonrpc/types/chainsvrresults.go b/rpc/jsonrpc/types/chainsvrresults.go index 1cc268ee..4cbafefe 100644 --- a/rpc/jsonrpc/types/chainsvrresults.go +++ b/rpc/jsonrpc/types/chainsvrresults.go @@ -159,61 +159,6 @@ type GetBlockSubsidyResult struct { Total int64 `json:"total"` } -// GetBlockTemplateResultTx models the transactions field of the -// getblocktemplate command. -type GetBlockTemplateResultTx struct { - Data string `json:"data"` - Hash string `json:"hash"` - Depends []int64 `json:"depends"` - Fee int64 `json:"fee"` - SigOps int64 `json:"sigops"` - TxType string `json:"txtype"` -} - -// GetBlockTemplateResultAux models the coinbaseaux field of the -// getblocktemplate command. -type GetBlockTemplateResultAux struct { - Flags string `json:"flags"` -} - -// GetBlockTemplateResult models the data returned from the getblocktemplate -// command. -type GetBlockTemplateResult struct { - // Base fields from BIP 0022. CoinbaseAux is optional. One of - // CoinbaseTxn or CoinbaseValue must be specified, but not both. - // GBT has been modified from the Bitcoin semantics to include - // the header rather than various components which are all part - // of the header anyway. - Header string `json:"header"` - SigOpLimit int64 `json:"sigoplimit,omitempty"` - SizeLimit int64 `json:"sizelimit,omitempty"` - Transactions []GetBlockTemplateResultTx `json:"transactions"` - STransactions []GetBlockTemplateResultTx `json:"stransactions"` - CoinbaseAux *GetBlockTemplateResultAux `json:"coinbaseaux,omitempty"` - CoinbaseTxn *GetBlockTemplateResultTx `json:"coinbasetxn,omitempty"` - CoinbaseValue *int64 `json:"coinbasevalue,omitempty"` - WorkID string `json:"workid,omitempty"` - - // Optional long polling from BIP 0022. - LongPollID string `json:"longpollid,omitempty"` - LongPollURI string `json:"longpolluri,omitempty"` - SubmitOld *bool `json:"submitold,omitempty"` - - // Basic pool extension from BIP 0023. - Target string `json:"target,omitempty"` - Expires int64 `json:"expires,omitempty"` - - // Mutations from BIP 0023. - MaxTime int64 `json:"maxtime,omitempty"` - MinTime int64 `json:"mintime,omitempty"` - Mutable []string `json:"mutable,omitempty"` - NonceRange string `json:"noncerange,omitempty"` - - // Block proposal from BIP 0023. - Capabilities []string `json:"capabilities,omitempty"` - RejectReasion string `json:"reject-reason,omitempty"` -} - // GetChainTipsResult models the data returns from the getchaintips command. type GetChainTipsResult struct { Height int64 `json:"height"` diff --git a/rpc/jsonrpc/types/go.mod b/rpc/jsonrpc/types/go.mod index 18bf9037..68aa0c2f 100644 --- a/rpc/jsonrpc/types/go.mod +++ b/rpc/jsonrpc/types/go.mod @@ -1,4 +1,4 @@ -module github.com/decred/dcrd/rpc/jsonrpc/types +module github.com/decred/dcrd/rpc/jsonrpc/types/v2 go 1.11 diff --git a/rpcclient/chain.go b/rpcclient/chain.go index e1c6f0a2..e2b30502 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -16,7 +16,7 @@ import ( "github.com/decred/dcrd/dcrutil/v2" "github.com/decred/dcrd/gcs/v2" "github.com/decred/dcrd/gcs/v2/blockcf" - chainjson "github.com/decred/dcrd/rpc/jsonrpc/types" + chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/wire" ) diff --git a/rpcclient/extensions.go b/rpcclient/extensions.go index 54c60f57..f0dfb575 100644 --- a/rpcclient/extensions.go +++ b/rpcclient/extensions.go @@ -13,7 +13,7 @@ import ( "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/dcrjson/v3" "github.com/decred/dcrd/dcrutil/v2" - chainjson "github.com/decred/dcrd/rpc/jsonrpc/types" + chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/wire" walletjson "github.com/decred/dcrwallet/rpc/jsonrpc/types" ) diff --git a/rpcclient/go.mod b/rpcclient/go.mod index 9e792a20..b032a61c 100644 --- a/rpcclient/go.mod +++ b/rpcclient/go.mod @@ -10,6 +10,7 @@ require ( github.com/decred/dcrd/gcs/v2 v2.0.0-00010101000000-000000000000 github.com/decred/dcrd/hdkeychain/v2 v2.0.1 github.com/decred/dcrd/rpc/jsonrpc/types v1.0.0 + github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.0.0-00010101000000-000000000000 github.com/decred/dcrd/wire v1.2.0 github.com/decred/dcrwallet/rpc/jsonrpc/types v1.1.0 github.com/decred/go-socks v1.0.0 @@ -17,4 +18,7 @@ require ( github.com/gorilla/websocket v1.4.0 ) -replace github.com/decred/dcrd/gcs/v2 => ../gcs +replace ( + github.com/decred/dcrd/gcs/v2 => ../gcs + github.com/decred/dcrd/rpc/jsonrpc/types/v2 => ../rpc/jsonrpc/types +) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 28361f2a..ff932bc8 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -28,7 +28,7 @@ import ( "github.com/gorilla/websocket" "github.com/decred/dcrd/dcrjson/v3" - chainjson "github.com/decred/dcrd/rpc/jsonrpc/types" + chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/go-socks/socks" ) diff --git a/rpcclient/mining.go b/rpcclient/mining.go index 74e4e214..992ad707 100644 --- a/rpcclient/mining.go +++ b/rpcclient/mining.go @@ -12,7 +12,7 @@ import ( "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/dcrutil/v2" - chainjson "github.com/decred/dcrd/rpc/jsonrpc/types" + chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v2" ) // FutureGenerateResult is a future promise to deliver the result of a @@ -364,45 +364,6 @@ func (c *Client) GetWorkSubmit(data string) (bool, error) { return c.GetWorkSubmitAsync(data).Receive() } -// FutureGetBlockTemplate is a future promise to deliver the result of a -// GetBlockTemplateAsync RPC invocation (or an applicable error). -type FutureGetBlockTemplate chan *response - -// Receive waits for the response promised by the future and returns an error if -// any occurred while generating the block template. -func (r FutureGetBlockTemplate) Receive() (*chainjson.GetBlockTemplateResult, error) { - res, err := receiveFuture(r) - if err != nil { - return nil, err - } - - // Unmarshal result. - var gbt chainjson.GetBlockTemplateResult - err = json.Unmarshal(res, &gbt) - if err != nil { - return nil, err - } - - return &gbt, nil -} - -// GetBlockTemplateAsync returns an instance of a type that can be used to get -// the result of the RPC at some future time by invoking the Receive function on -// on the returned instance. -// -// See GetBlockTemplate for the blocking version and more details. -func (c *Client) GetBlockTemplateAsync(req *chainjson.TemplateRequest) FutureGetBlockTemplate { - cmd := chainjson.NewGetBlockTemplateCmd(req) - return c.sendCmd(cmd) -} - -// GetBlockTemplate returns a block template to work on. -// -// See SubmitBlock to submit the found solution. -func (c *Client) GetBlockTemplate(req *chainjson.TemplateRequest) (*chainjson.GetBlockTemplateResult, error) { - return c.GetBlockTemplateAsync(req).Receive() -} - // FutureSubmitBlockResult is a future promise to deliver the result of a // SubmitBlockAsync RPC invocation (or an applicable error). type FutureSubmitBlockResult chan *response diff --git a/rpcclient/net.go b/rpcclient/net.go index b24633f4..e118bc2b 100644 --- a/rpcclient/net.go +++ b/rpcclient/net.go @@ -8,7 +8,7 @@ package rpcclient import ( "encoding/json" - chainjson "github.com/decred/dcrd/rpc/jsonrpc/types" + chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v2" ) // AddNodeCommand enumerates the available commands that the AddNode function diff --git a/rpcclient/notify.go b/rpcclient/notify.go index 236a3a53..4023a106 100644 --- a/rpcclient/notify.go +++ b/rpcclient/notify.go @@ -14,7 +14,7 @@ import ( "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/dcrutil/v2" - chainjson "github.com/decred/dcrd/rpc/jsonrpc/types" + chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/wire" walletjson "github.com/decred/dcrwallet/rpc/jsonrpc/types" ) diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index d7279959..d2384bb1 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -13,7 +13,7 @@ import ( "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/dcrjson/v3" "github.com/decred/dcrd/dcrutil/v2" - chainjson "github.com/decred/dcrd/rpc/jsonrpc/types" + chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/wire" walletjson "github.com/decred/dcrwallet/rpc/jsonrpc/types" ) diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 6f3ef17f..00196290 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -13,7 +13,8 @@ import ( "github.com/decred/dcrd/dcrjson/v3" "github.com/decred/dcrd/dcrutil/v2" "github.com/decred/dcrd/hdkeychain/v2" - chainjson "github.com/decred/dcrd/rpc/jsonrpc/types" + chainjsonv1 "github.com/decred/dcrd/rpc/jsonrpc/types" + chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/wire" walletjson "github.com/decred/dcrwallet/rpc/jsonrpc/types" ) @@ -336,9 +337,9 @@ func (r FutureLockUnspentResult) Receive() error { // // See LockUnspent for the blocking version and more details. func (c *Client) LockUnspentAsync(unlock bool, ops []*wire.OutPoint) FutureLockUnspentResult { - outputs := make([]chainjson.TransactionInput, len(ops)) + outputs := make([]chainjsonv1.TransactionInput, len(ops)) for i, op := range ops { - outputs[i] = chainjson.TransactionInput{ + outputs[i] = chainjsonv1.TransactionInput{ Txid: op.Hash.String(), Vout: op.Index, Tree: op.Tree, diff --git a/rpcserver.go b/rpcserver.go index 3bfd155e..9485e334 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -47,7 +47,7 @@ import ( "github.com/decred/dcrd/dcrutil/v2" "github.com/decred/dcrd/internal/version" "github.com/decred/dcrd/mempool/v3" - "github.com/decred/dcrd/rpc/jsonrpc/types" + "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/txscript/v2" "github.com/decred/dcrd/wire" "github.com/jrick/bitset" @@ -90,17 +90,6 @@ const ( // the template pool. getworkExpirationDiff = 3 - // 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 - // sstxCommitmentString is the string to insert when a verbose // transaction output's pkscript type is a ticket commitment. sstxCommitmentString = "sstxcommitment" @@ -113,29 +102,6 @@ var ( // calculation. blake256Pad []byte - // 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 = &types.GetBlockTemplateResultAux{ - Flags: hex.EncodeToString(builderScript(txscript. - 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"} - // JSON 2.0 batched request prefix batchedRequestPrefix = []byte("[") ) @@ -155,10 +121,6 @@ var ( Code: dcrjson.ErrRPCNoWallet, Message: "This implementation does not implement wallet commands", } - - // ErrInvalidLongPoll is an internal error code to indicate that - // longpollid is not formatted properly. - ErrInvalidLongPoll = errors.New("invalid longpollid format") ) type commandHandler func(*rpcServer, interface{}, <-chan struct{}) (interface{}, error) @@ -297,7 +259,6 @@ var rpcAskWallet = map[string]struct{}{ // Commands that are currently unimplemented, but should ultimately be. var rpcUnimplemented = map[string]struct{}{ "estimatepriority": {}, - "getblocktemplate": {}, } // Commands that are available to a limited user @@ -370,18 +331,6 @@ var rpcLimited = map[string]struct{}{ "version": {}, } -// builderScript is a convenience function which is used 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 *txscript.ScriptBuilder) []byte { - script, err := builder.Script() - if err != nil { - panic(err) - } - return script -} - // rpcInternalError is a convenience function to convert an internal error to // an RPC error with the appropriate code set. It also logs the error to the // RPC server subsystem since internal errors really should not occur. The @@ -482,28 +431,6 @@ func newWorkState() *workState { return &workState{} } -// 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 *chainhash.Hash - minTimestamp time.Time - template *BlockTemplate - notifyMap map[chainhash.Hash]map[int64]chan struct{} - timeSource blockchain.MedianTimeSource -} - -// newGbtWorkState returns a new instance of a gbtWorkState with all internal -// fields initialized and ready to use. -func newGbtWorkState(timeSource blockchain.MedianTimeSource) *gbtWorkState { - return &gbtWorkState{ - notifyMap: make(map[chainhash.Hash]map[int64]chan struct{}), - timeSource: timeSource, - } -} - // handleUnimplemented is the handler for commands that should ultimately be // supported but are not yet implemented. func handleUnimplemented(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { @@ -780,10 +707,6 @@ func handleCreateRawSStx(s *rpcServer, cmd interface{}, closeChan <-chan struct{ return nil, rpcDecodeHexError(input.Txid) } - if input.Vout < 0 { - return nil, rpcInvalidError("Vout must be positive") - } - if !(input.Tree == wire.TxTreeRegular || input.Tree == wire.TxTreeStake) { rpcInvalidError("Tx tree must be regular or stake") @@ -1003,10 +926,6 @@ func handleCreateRawSSRtx(s *rpcServer, cmd interface{}, closeChan <-chan struct return nil, rpcDecodeHexError(input.Txid) } - if input.Vout < 0 { - return nil, rpcInvalidError("Vout must be positive") - } - if !(input.Tree == wire.TxTreeStake) { return nil, rpcInvalidError("Input tree is not " + "TxTreeStake type") @@ -2162,867 +2081,6 @@ func handleGetBlockSubsidy(s *rpcServer, cmd interface{}, closeChan <-chan struc return rep, nil } -// encodeTemplateID encodes the passed details into an ID that can be used to -// uniquely identify a block template. -func encodeTemplateID(prevHash *chainhash.Hash, 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) (*chainhash.Hash, int64, error) { - fields := strings.Split(templateID, "-") - if len(fields) != 2 { - return nil, 0, ErrInvalidLongPoll - } - - prevHash, err := chainhash.NewHashFromStr(fields[0]) - if err != nil { - return nil, 0, ErrInvalidLongPoll - } - lastGenerated, err := strconv.ParseInt(fields[1], 10, 64) - if err != nil { - return nil, 0, ErrInvalidLongPoll - } - - 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 *chainhash.Hash, 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(blockHash *chainhash.Hash) { - go func() { - state.Lock() - defer state.Unlock() - - state.notifyLongPollers(blockHash, 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 *chainhash.Hash, 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 long enough since the last template was generated. Otherwise, the -// timestamp for the existing block template is updated (and possibly the -// difficulty on testnet per the consensus rules). Finally, if the -// useCoinbaseValue flag is false 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 *wire.MsgBlock - var targetDifficulty string - best := s.server.chain.BestSnapshot() - latestHash := best.Hash - template := state.template - if template == nil || state.prevHash == nil || - !state.prevHash.IsEqual(&best.Hash) || - (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 dcrutil.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 := s.generator.NewBlockTemplate(payAddr) - if err != nil { - return rpcInternalError("Failed to create new block "+ - "template: "+err.Error(), "") - } - if blkTemplate == nil { - return rpcInternalError("Failed to create new block "+ - "template: not enough voters on parent and no "+ - "suitable cached template", "") - } - template = blkTemplate - msgBlock = template.Block - targetDifficulty = fmt.Sprintf("%064x", - standalone.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. - minTimestamp := minimumMedianTime(best) - - // Update work state to ensure another block template isn't - // generated until needed. - state.template = deepCopyBlockTemplate(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(&best.Hash, 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 := txscript.PayToAddrScript(payToAddr) - if err != nil { - context := "Failed to create pay-to-addr script" - return rpcInternalError(err.Error(), context) - } - template.Block.Transactions[0].TxOut[0].PkScript = pkScript - template.ValidPayAddress = true - - // Update the merkle root. - tplHeader := &template.Block.Header - tplTxns := template.Block.Transactions - tplHeader.MerkleRoot = standalone.CalcTxTreeMerkleRoot(tplTxns) - } - - // Set locals for convenience. - msgBlock = template.Block - targetDifficulty = fmt.Sprintf("%064x", - standalone.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. - err := s.generator.UpdateBlockTime(&msgBlock.Header) - if err != nil { - context := "Failed to update timestamp" - return rpcInternalError(err.Error(), context) - } - 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 types.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(bm *blockManager, useCoinbaseValue bool, submitOld *bool) (*types.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 := deepCopyBlockTemplate(state.template) - msgBlock := template.Block - header := &msgBlock.Header - adjustedTime := state.timeSource.AdjustedTime() - maxTime := adjustedTime.Add(time.Second * blockchain.MaxTimeOffsetSeconds) - if header.Timestamp.After(maxTime) { - return nil, &dcrjson.RPCError{ - Code: dcrjson.ErrRPCOutOfRange, - 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([]types.GetBlockTemplateResultTx, 0, numTx-1) - txIndex := make(map[chainhash.Hash]int64, numTx) - for i, tx := range msgBlock.Transactions { - txHash := tx.TxHashFull() - 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 multiple 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 { - context := "Failed to serialize transaction" - return nil, rpcInternalError(err.Error(), context) - } - - var txTypeStr string - txType := stake.DetermineTxType(tx) - switch txType { - case stake.TxTypeRegular: - txTypeStr = "regular" - case stake.TxTypeSStx: - txTypeStr = "error" - case stake.TxTypeSSGen: - txTypeStr = "error" - case stake.TxTypeSSRtx: - txTypeStr = "error" - } - - fee := template.Fees[i] - sigOps := template.SigOpCounts[i] - resultTx := types.GetBlockTemplateResultTx{ - Data: hex.EncodeToString(txBuf.Bytes()), - Hash: txHash.String(), - Depends: depends, - Fee: fee, - SigOps: sigOps, - TxType: txTypeStr, - } - transactions = append(transactions, resultTx) - } - - // Convert each stake transaction in the block template to a template - // result transaction. - numSTx := len(msgBlock.STransactions) - stransactions := make([]types.GetBlockTemplateResultTx, 0, numSTx) - stxIndex := make(map[chainhash.Hash]int64, numSTx) - for i, stx := range msgBlock.STransactions { - stxHash := stx.TxHashFull() - stxIndex[stxHash] = int64(i) - // 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 multiple inputs reference the same transaction. - dependsMap := make(map[int64]struct{}) - for _, txIn := range stx.TxIn { - if idx, ok := stxIndex[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, stx.SerializeSize())) - if err := stx.Serialize(txBuf); err != nil { - return nil, err - } - - var txTypeStr string - txType := stake.DetermineTxType(stx) - switch txType { - case stake.TxTypeRegular: - txTypeStr = "error" - case stake.TxTypeSStx: - txTypeStr = "ticket" - case stake.TxTypeSSGen: - txTypeStr = "vote" - case stake.TxTypeSSRtx: - txTypeStr = "revocation" - } - - fee := template.Fees[i+len(msgBlock.Transactions)] - sigOps := template.SigOpCounts[i+len(msgBlock.Transactions)] - resultTx := types.GetBlockTemplateResultTx{ - Data: hex.EncodeToString(txBuf.Bytes()), - Hash: stxHash.String(), - Depends: depends, - Fee: fee, - SigOps: sigOps, - TxType: txTypeStr, - } - stransactions = append(stransactions, resultTx) - } - - headerBytes, err := header.Bytes() - if err != nil { - context := "Could not obtain header" - return nil, rpcInternalError(err.Error(), context) - } - - // Choose the correct maximum block size as defined by the network - // parameters and the current status of any hard fork votes to change - // it when serialized. - maxBlockSize, err := bm.chain.MaxBlockSize() - if err != nil { - context := "Invalid blocksize" - return nil, rpcInternalError(err.Error(), context) - } - - // 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", standalone.CompactToBig(header.Bits)) - templateID := encodeTemplateID(state.prevHash, state.lastGenerated) - reply := types.GetBlockTemplateResult{ - Header: hex.EncodeToString(headerBytes), - SigOpLimit: blockchain.MaxSigOpsPerBlock, - SizeLimit: maxBlockSize, - Transactions: transactions, - STransactions: stransactions, - 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 { - context := "Invalid blocksize" - errStr := fmt.Sprintf("A coinbase transaction has " + - "been requested, but the server has not " + - "been configured with any payment " + - "addresses via --miningaddr") - return nil, rpcInternalError(errStr, context) - } - - // Serialize the transaction for conversion to hex. - tx := msgBlock.Transactions[0] - txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize())) - if err := tx.Serialize(txBuf); err != nil { - context := "Could not serialize" - return nil, rpcInternalError(err.Error(), context) - } - - resultTx := types.GetBlockTemplateResultTx{ - Data: hex.EncodeToString(txBuf.Bytes()), - Hash: tx.TxHash().String(), - Depends: []int64{}, - Fee: template.Fees[0], - SigOps: template.SigOpCounts[0], - } - - reply.CoinbaseTxn = &resultTx - } - - return &reply, nil -} - -// handleGetBlockTemplateLongPoll is 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 long poll ID provided by - // the caller is invalid. - prevHash, lastGenerated, err := decodeTemplateID(longPollID) - if err != nil { - result, err := state.blockTemplateResult(s.server.blockManager, - 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(s.server.blockManager, - 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 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 latest 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(s.server.blockManager, - 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 *types.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, rpcInternalError("A coinbase transaction has "+ - "been requested, but the server has not been "+ - "configured with any payment addresses via "+ - "--miningaddr", "Configuration") - } - - // 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.SimNet && s.server.ConnectedCount() == 0 { - return nil, &dcrjson.RPCError{ - Code: dcrjson.ErrRPCClientNotConnected, - Message: "Decred is not connected", - } - } - - // No point in generating or accepting work before the chain is synced. - bestHeight := s.server.chain.BestSnapshot().Height - if bestHeight != 0 && !s.server.blockManager.IsCurrent() { - return nil, &dcrjson.RPCError{ - Code: dcrjson.ErrRPCClientInInitialDownload, - Message: "Decred is downloading blocks...", - } - } - - // 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 consensus rules). - if err := state.updateBlockTemplate(s, useCoinbaseValue); err != nil { - return nil, err - } - return state.blockTemplateResult(s.server.blockManager, useCoinbaseValue, nil) -} - -// chainErrToGBTErrString converts an error returned from chain to a string -// which matches the reasons and format described in BIP0022 for rejection -// reasons. -// TODO Decred pop in the new errors from blockchain cj -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.(blockchain.RuleError) - if !ok { - return "rejected: " + err.Error() - } - - switch ruleErr.ErrorCode { - case blockchain.ErrDuplicateBlock: - return "duplicate" - case blockchain.ErrBlockTooBig: - return "bad-block-size" - case blockchain.ErrBlockVersionTooOld: - return "bad-version" - case blockchain.ErrInvalidTime: - return "bad-time" - case blockchain.ErrTimeTooOld: - return "time-too-old" - case blockchain.ErrTimeTooNew: - return "time-too-new" - case blockchain.ErrDifficultyTooLow: - return "bad-diffbits" - case blockchain.ErrUnexpectedDifficulty: - return "bad-diffbits" - case blockchain.ErrHighHash: - return "high-hash" - case blockchain.ErrBadMerkleRoot: - return "bad-txnmrklroot" - case blockchain.ErrBadCheckpoint: - return "bad-checkpoint" - case blockchain.ErrForkTooOld: - return "fork-too-old" - case blockchain.ErrCheckpointTimeTooOld: - return "checkpoint-time-too-old" - case blockchain.ErrNoTransactions: - return "bad-txns-none" - case blockchain.ErrTooManyTransactions: - return "bad-txns-toomany" - case blockchain.ErrNoTxInputs: - return "bad-txns-noinputs" - case blockchain.ErrNoTxOutputs: - return "bad-txns-nooutputs" - case blockchain.ErrTxTooBig: - return "bad-txns-size" - case blockchain.ErrBadTxOutValue: - return "bad-txns-outputvalue" - case blockchain.ErrDuplicateTxInputs: - return "bad-txns-dupinputs" - case blockchain.ErrBadTxInput: - return "bad-txns-badinput" - case blockchain.ErrMissingTxOut: - return "bad-txns-missinginput" - case blockchain.ErrUnfinalizedTx: - return "bad-txns-unfinalizedtx" - case blockchain.ErrDuplicateTx: - return "bad-txns-duplicate" - case blockchain.ErrOverwriteTx: - return "bad-txns-overwrite" - case blockchain.ErrImmatureSpend: - return "bad-txns-maturity" - case blockchain.ErrSpendTooHigh: - return "bad-txns-highspend" - case blockchain.ErrBadFees: - return "bad-txns-fees" - case blockchain.ErrTooManySigOps: - return "high-sigops" - case blockchain.ErrFirstTxNotCoinbase: - return "bad-txns-nocoinbase" - case blockchain.ErrMultipleCoinbases: - return "bad-txns-multicoinbase" - case blockchain.ErrBadCoinbaseScriptLen: - return "bad-cb-length" - case blockchain.ErrBadCoinbaseValue: - return "bad-cb-value" - case blockchain.ErrScriptMalformed: - return "bad-script-malformed" - case blockchain.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 *types.TemplateRequest) (interface{}, error) { - hexData := request.Data - if hexData == "" { - return false, rpcInvalidError("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, rpcDecodeHexError(hexData) - } - var msgBlock wire.MsgBlock - if err := msgBlock.Deserialize(bytes.NewReader(dataBytes)); err != nil { - return nil, rpcDeserializationError("Could not decode block: "+ - "%v", err) - } - block := dcrutil.NewBlock(&msgBlock) - - // Ensure the block is building from the expected previous block. - expectedPrevHash := &s.server.chain.BestSnapshot().Hash - prevHash := &block.MsgBlock().Header.PrevBlock - if *expectedPrevHash != *prevHash { - return "bad-prevblk", nil - } - - err = s.server.chain.CheckConnectBlockTemplate(block) - if err != nil { - if _, ok := err.(blockchain.RuleError); !ok { - errStr := fmt.Sprintf("Failed to process block "+ - "proposal: %v", err) - rpcsLog.Error(errStr) - return nil, rpcInternalError(err.Error(), - "Could not process block") - } - - rpcsLog.Infof("Rejected block proposal: %v", err) - return chainErrToGBTErrString(err), 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 interface{}, closeChan <-chan struct{}) (interface{}, error) { - if s.server.cpuMiner.IsMining() { - return nil, rpcMiscError("Block template production is " + - "disallowed while CPU mining is enabled. " + - "Please disable CPU mining and try again.") - } - - // Respond with an error if there are no addresses to pay the created - // blocks to. - if len(cfg.miningAddrs) == 0 { - return nil, rpcInternalError("No payment addresses specified "+ - "via --miningaddr", "Configuration") - } - - c := cmd.(*types.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, rpcInvalidError("Invalid mode: %v", mode) -} - // handleGetChainTips implements the getchaintips command. func handleGetChainTips(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { chainTips := s.chain.ChainTips() @@ -5793,7 +4851,6 @@ type rpcServer struct { wg sync.WaitGroup listeners []net.Listener workState *workState - gbtWorkState *gbtWorkState templatePool map[[merkleRootPairSize]byte]*workStateBlockInfo helpCacher *helpCacher requestProcessShutdown chan struct{} @@ -6432,7 +5489,6 @@ func newRPCServer(listenAddrs []string, generator *BlkTmplGenerator, s *server) statusLines: make(map[int]string), workState: newWorkState(), templatePool: make(map[[merkleRootPairSize]byte]*workStateBlockInfo), - gbtWorkState: newGbtWorkState(s.timeSource), helpCacher: newHelpCacher(), requestProcessShutdown: make(chan struct{}), } diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 7cff284f..9616daf8 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -12,7 +12,7 @@ import ( "sync" "github.com/decred/dcrd/dcrjson/v3" - "github.com/decred/dcrd/rpc/jsonrpc/types" + "github.com/decred/dcrd/rpc/jsonrpc/types/v2" ) // helpDescsEnUS defines the English descriptions used for the help strings. @@ -376,64 +376,6 @@ var helpDescsEnUS = map[string]string{ "getblocksubsidyresult-pow": "The Proof-of-Work subsidy", "getblocksubsidyresult-total": "The total subsidy", - // TemplateRequest help. - "templaterequest-mode": "This is 'template', 'proposal', or omitted", - "templaterequest-capabilities": "List of capabilities", - "templaterequest-longpollid": "The long poll ID of a job to monitor for expiration; required and valid only for long poll requests", - "templaterequest-sigoplimit": "Number of signature operations allowed in blocks (this parameter is ignored)", - "templaterequest-sizelimit": "Number of bytes allowed in blocks (this parameter is ignored)", - "templaterequest-maxversion": "Highest supported block version number (this parameter is ignored)", - "templaterequest-target": "The desired target for the block template (this parameter is ignored)", - "templaterequest-data": "Hex-encoded block data (only for mode=proposal)", - "templaterequest-workid": "The server provided workid if provided in block template (not applicable)", - - // GetBlockTemplateResultTx help. - "getblocktemplateresulttx-data": "Hex-encoded transaction data (byte-for-byte)", - "getblocktemplateresulttx-hash": "Hex-encoded transaction hash (little endian if treated as a 256-bit number)", - "getblocktemplateresulttx-depends": "Other transactions before this one (by 1-based index in the 'transactions' list) that must be present in the final block if this one is", - "getblocktemplateresulttx-fee": "Difference in value between transaction inputs and outputs (in Atoms)", - "getblocktemplateresulttx-sigops": "Total number of signature operations as counted for purposes of block limits", - "getblocktemplateresulttx-txtype": "Type of the transaction", - - // GetBlockTemplateResultAux help. - "getblocktemplateresultaux-flags": "Hex-encoded byte-for-byte data to include in the coinbase signature script", - - // GetBlockTemplateResult help. - "getblocktemplateresult-bits": "Hex-encoded compressed difficulty", - "getblocktemplateresult-curtime": "Current time as seen by the server (recommended for block time); must fall within mintime/maxtime rules", - "getblocktemplateresult-height": "Height of the block to be solved", - "getblocktemplateresult-previousblockhash": "Hex-encoded big-endian hash of the previous block", - "getblocktemplateresult-sigoplimit": "Number of sigops allowed in blocks", - "getblocktemplateresult-sizelimit": "Number of bytes allowed in blocks", - "getblocktemplateresult-transactions": "Array of transactions as JSON objects", - "getblocktemplateresult-version": "The block version", - "getblocktemplateresult-coinbaseaux": "Data that should be included in the coinbase signature script", - "getblocktemplateresult-coinbasetxn": "Information about the coinbase transaction", - "getblocktemplateresult-coinbasevalue": "Total amount available for the coinbase in Atoms", - "getblocktemplateresult-workid": "This value must be returned with result if provided (not provided)", - "getblocktemplateresult-longpollid": "Identifier for long poll request which allows monitoring for expiration", - "getblocktemplateresult-longpolluri": "An alternate URI to use for long poll requests if provided (not provided)", - "getblocktemplateresult-submitold": "Not applicable", - "getblocktemplateresult-target": "Hex-encoded big-endian number which valid results must be less than", - "getblocktemplateresult-expires": "Maximum number of seconds (starting from when the server sent the response) this work is valid for", - "getblocktemplateresult-maxtime": "Maximum allowed time", - "getblocktemplateresult-mintime": "Minimum allowed time", - "getblocktemplateresult-mutable": "List of mutations the server explicitly allows", - "getblocktemplateresult-noncerange": "Two concatenated hex-encoded big-endian 32-bit integers which represent the valid ranges of nonces the miner may scan", - "getblocktemplateresult-capabilities": "List of server capabilities including 'proposal' to indicate support for block proposals", - "getblocktemplateresult-reject-reason": "Reason the proposal was invalid as-is (only applies to proposal responses)", - "getblocktemplateresult-stransactions": "Stake transactions", - "getblocktemplateresult-header": "Block header", - - // GetBlockTemplateCmd help. - "getblocktemplate--synopsis": "Returns a JSON object with information necessary to construct a block to mine or accepts a proposal to validate.\n" + - "See BIP0022 and BIP0023 for the full specification.", - "getblocktemplate-request": "Request object which controls the mode and several parameters", - "getblocktemplate--condition0": "mode=template", - "getblocktemplate--condition1": "mode=proposal, rejected", - "getblocktemplate--condition2": "mode=proposal, accepted", - "getblocktemplate--result1": "An error string which represents why the proposal was rejected or nothing if accepted", - // GetCFilterCmd help. "getcfilter--synopsis": "Returns the committed filter for a block", "getcfilter--result0": "The committed filter serialized with the N value and encoded as a hex string", @@ -998,7 +940,6 @@ var rpcResultTypes = map[types.Method][]interface{}{ "getblockhash": {(*string)(nil)}, "getblockheader": {(*string)(nil), (*types.GetBlockHeaderVerboseResult)(nil)}, "getblocksubsidy": {(*types.GetBlockSubsidyResult)(nil)}, - "getblocktemplate": {(*types.GetBlockTemplateResult)(nil), (*string)(nil), nil}, "getcfilter": {(*string)(nil)}, "getcfilterheader": {(*string)(nil)}, "getchaintips": {(*[]types.GetChainTipsResult)(nil)}, diff --git a/rpctest/rpc_harness_test.go b/rpctest/rpc_harness_test.go index f227c280..a26e740c 100644 --- a/rpctest/rpc_harness_test.go +++ b/rpctest/rpc_harness_test.go @@ -17,7 +17,7 @@ import ( "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/chaincfg/v2" "github.com/decred/dcrd/dcrutil/v2" - dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types" + dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/txscript/v2" "github.com/decred/dcrd/wire" ) diff --git a/rpctest/utils.go b/rpctest/utils.go index cb344126..5d1849b6 100644 --- a/rpctest/utils.go +++ b/rpctest/utils.go @@ -9,7 +9,7 @@ import ( "reflect" "time" - dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types" + dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/rpcclient/v5" ) diff --git a/rpctest/votingwallet.go b/rpctest/votingwallet.go index 47871eea..9b6c49e3 100644 --- a/rpctest/votingwallet.go +++ b/rpctest/votingwallet.go @@ -17,7 +17,7 @@ import ( "github.com/decred/dcrd/dcrec" "github.com/decred/dcrd/dcrec/secp256k1" "github.com/decred/dcrd/dcrutil/v2" - dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types" + dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/rpcclient/v5" "github.com/decred/dcrd/txscript/v2" "github.com/decred/dcrd/wire" diff --git a/rpcwebsocket.go b/rpcwebsocket.go index a2775dd5..ae0a2bc3 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -28,7 +28,7 @@ import ( "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/dcrjson/v3" "github.com/decred/dcrd/dcrutil/v2" - "github.com/decred/dcrd/rpc/jsonrpc/types" + "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/txscript/v2" "github.com/decred/dcrd/wire" ) diff --git a/server.go b/server.go index 1006eab6..e03a4434 100644 --- a/server.go +++ b/server.go @@ -1213,9 +1213,8 @@ func (s *server) PruneRebroadcastInventory() { } // AnnounceNewTransactions generates and relays inventory vectors and notifies -// both websocket and getblocktemplate long poll clients of the passed -// transactions. This function should be called whenever new transactions -// are added to the mempool. +// websocket clients of the passed transactions. This function should be +// called whenever new transactions are added to the mempool. func (s *server) AnnounceNewTransactions(txns []*dcrutil.Tx) { // Generate and relay inventory vectors for all newly accepted // transactions into the memory pool due to the original being @@ -1228,10 +1227,6 @@ func (s *server) AnnounceNewTransactions(txns []*dcrutil.Tx) { if s.rpcServer != nil { // Notify websocket clients about mempool transactions. s.rpcServer.ntfnMgr.NotifyMempoolTx(tx, true) - - // Potentially notify any getblocktemplate long poll clients - // about stale block templates due to the new transaction. - s.rpcServer.gbtWorkState.NotifyMempoolTx(s.txMemPool.LastUpdated()) } } }