From 57cb8e4b11a76282166442ec149625712edb945f Mon Sep 17 00:00:00 2001 From: jalavosus Date: Fri, 31 Jan 2020 12:31:47 -0500 Subject: [PATCH] Refactor FutureGetBlockVerboseResult into two types: FutureGetBlockVerboseResult, and FutureGetBlockVerboseTxResult. Due to differences in how getblock returns data based on the provided verbosity parameter, it's necessary to have two separate return types based on verbosity. This necessitates a separate unmarshalling function (represented throughout rpcclient/chain.go as Result.Receive()) to ensure that data is correctly unmarshalled and returned to the user. --- btcjson/chainsvrcmds_test.go | 31 ++++++++++++------------------- btcjson/cmdinfo_test.go | 2 +- btcjson/example_test.go | 12 +++++------- rpcclient/chain.go | 32 ++++++++++++++++++++++++++------ rpcserver.go | 4 ++-- 5 files changed, 46 insertions(+), 35 deletions(-) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 8cb4ee76..a861af1a 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -142,50 +142,43 @@ func TestChainSvrCmds(t *testing.T) { { name: "getblock", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getblock", "123") + return btcjson.NewCmd("getblock", "123", btcjson.Int(0)) }, staticCmd: func() interface{} { - return btcjson.NewGetBlockCmd("123", nil, nil) + return btcjson.NewGetBlockCmd("123", btcjson.Int(0)) }, - marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123"],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",0],"id":1}`, unmarshalled: &btcjson.GetBlockCmd{ Hash: "123", - Verbose: btcjson.Bool(true), - VerboseTx: btcjson.Bool(false), + Verbosity: btcjson.Int(0), }, }, { name: "getblock required optional1", newCmd: func() (interface{}, error) { - // Intentionally use a source param that is - // more pointers than the destination to - // exercise that path. - verbosePtr := btcjson.Bool(true) - return btcjson.NewCmd("getblock", "123", &verbosePtr) + return btcjson.NewCmd("getblock", "123", btcjson.Int(1)) }, staticCmd: func() interface{} { - return btcjson.NewGetBlockCmd("123", btcjson.Bool(true), nil) + return btcjson.NewGetBlockCmd("123", btcjson.Int(1)) }, - marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",true],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",1],"id":1}`, unmarshalled: &btcjson.GetBlockCmd{ Hash: "123", - Verbose: btcjson.Bool(true), - VerboseTx: btcjson.Bool(false), + Verbosity: btcjson.Int(1), }, }, { name: "getblock required optional2", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getblock", "123", true, true) + return btcjson.NewCmd("getblock", "123", btcjson.Int(2)) }, staticCmd: func() interface{} { - return btcjson.NewGetBlockCmd("123", btcjson.Bool(true), btcjson.Bool(true)) + return btcjson.NewGetBlockCmd("123", btcjson.Int(2)) }, - marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",true,true],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",2],"id":1}`, unmarshalled: &btcjson.GetBlockCmd{ Hash: "123", - Verbose: btcjson.Bool(true), - VerboseTx: btcjson.Bool(true), + Verbosity: btcjson.Int(2), }, }, { diff --git a/btcjson/cmdinfo_test.go b/btcjson/cmdinfo_test.go index 04404027..61a693e4 100644 --- a/btcjson/cmdinfo_test.go +++ b/btcjson/cmdinfo_test.go @@ -151,7 +151,7 @@ func TestMethodUsageText(t *testing.T) { { name: "getblock", method: "getblock", - expected: `getblock "hash" (verbose=true verbosetx=false)`, + expected: `getblock "hash" (verbosity=1)`, }, } diff --git a/btcjson/example_test.go b/btcjson/example_test.go index 527252c7..cbca495b 100644 --- a/btcjson/example_test.go +++ b/btcjson/example_test.go @@ -21,7 +21,7 @@ func ExampleMarshalCmd() { // convenience function for creating a pointer out of a primitive for // optional parameters. blockHash := "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f" - gbCmd := btcjson.NewGetBlockCmd(blockHash, btcjson.Bool(false), nil) + gbCmd := btcjson.NewGetBlockCmd(blockHash, btcjson.Int(1)) // Marshal the command to the format suitable for sending to the RPC // server. Typically the client would increment the id here which is @@ -38,7 +38,7 @@ func ExampleMarshalCmd() { fmt.Printf("%s\n", marshalledBytes) // Output: - // {"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",false],"id":1} + // {"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",1],"id":1} } // This example demonstrates how to unmarshal a JSON-RPC request and then @@ -46,7 +46,7 @@ func ExampleMarshalCmd() { func ExampleUnmarshalCmd() { // Ordinarily this would be read from the wire, but for this example, // it is hard coded here for clarity. - data := []byte(`{"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",false],"id":1}`) + data := []byte(`{"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",1],"id":1}`) // Unmarshal the raw bytes from the wire into a JSON-RPC request. var request btcjson.Request @@ -84,13 +84,11 @@ func ExampleUnmarshalCmd() { // Display the fields in the concrete command. fmt.Println("Hash:", gbCmd.Hash) - fmt.Println("Verbose:", *gbCmd.Verbose) - fmt.Println("VerboseTx:", *gbCmd.VerboseTx) + fmt.Println("Verbosity:", *gbCmd.Verbosity) // Output: // Hash: 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f - // Verbose: false - // VerboseTx: false + // Verbosity: 0 } // This example demonstrates how to marshal a JSON-RPC response. diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 996d8045..6815e1fa 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -97,7 +97,7 @@ func (c *Client) GetBlockAsync(blockHash *chainhash.Hash) FutureGetBlockResult { hash = blockHash.String() } - cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(false), nil) + cmd := btcjson.NewGetBlockCmd(hash, nil) return c.sendCmd(cmd) } @@ -140,8 +140,9 @@ func (c *Client) GetBlockVerboseAsync(blockHash *chainhash.Hash) FutureGetBlockV if blockHash != nil { hash = blockHash.String() } - - cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), nil) + // From the bitcoin-cli getblock documentation: + // "If verbosity is 1, returns an Object with information about block ." + cmd := btcjson.NewGetBlockCmd(hash, btcjson.Int(1)) return c.sendCmd(cmd) } @@ -154,18 +155,37 @@ func (c *Client) GetBlockVerbose(blockHash *chainhash.Hash) (*btcjson.GetBlockVe return c.GetBlockVerboseAsync(blockHash).Receive() } +type FutureGetBlockVerboseTxResult chan *response + +func (r FutureGetBlockVerboseTxResult) Receive() (*btcjson.GetBlockVerboseTxResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var blockResult btcjson.GetBlockVerboseTxResult + err = json.Unmarshal(res, &blockResult) + if err != nil { + return nil, err + } + + return &blockResult, nil +} + // GetBlockVerboseTxAsync 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 // the returned instance. // // See GetBlockVerboseTx or the blocking version and more details. -func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBlockVerboseResult { +func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBlockVerboseTxResult { hash := "" if blockHash != nil { hash = blockHash.String() } + // From the bitcoin-cli getblock documentation: + // "If verbosity is 2, returns an Object with information about block and information about each transaction." + cmd := btcjson.NewGetBlockCmd(hash, btcjson.Int(2)) - cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), btcjson.Bool(true)) return c.sendCmd(cmd) } @@ -174,7 +194,7 @@ func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBloc // // See GetBlockVerbose if only transaction hashes are preferred. // See GetBlock to retrieve a raw block instead. -func (c *Client) GetBlockVerboseTx(blockHash *chainhash.Hash) (*btcjson.GetBlockVerboseResult, error) { +func (c *Client) GetBlockVerboseTx(blockHash *chainhash.Hash) (*btcjson.GetBlockVerboseTxResult, error) { return c.GetBlockVerboseTxAsync(blockHash).Receive() } diff --git a/rpcserver.go b/rpcserver.go index e762cc1a..2da7e9f5 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1084,7 +1084,7 @@ func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i // When the verbose flag isn't set, simply return the serialized block // as a hex-encoded string. - if c.Verbose != nil && !*c.Verbose { + if c.Verbosity != nil && *c.Verbosity == 0 { return hex.EncodeToString(blkBytes), nil } @@ -1137,7 +1137,7 @@ func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i NextHash: nextHashString, } - if c.VerboseTx == nil || !*c.VerboseTx { + if *c.Verbosity == 1 { transactions := blk.Transactions() txNames := make([]string, len(transactions)) for i, tx := range transactions {