mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-10-14 00:59:33 +00:00
[DEV-317] Update JSON-RPC API call GetBlock to allow filtering by SubNetworkID (#180)
* [DEV-317] Update JSON-RPC API call GetBlock to allow filtering by SubNetworkID * [DEV-317] Changed comments, messages and refactored code
This commit is contained in:
parent
0bc7a11551
commit
3eeff11231
@ -151,7 +151,7 @@ func TestMethodUsageText(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "getBlock",
|
name: "getBlock",
|
||||||
method: "getBlock",
|
method: "getBlock",
|
||||||
expected: `getBlock "hash" (verbose=true verbosetx=false)`,
|
expected: `getBlock "hash" (verbose=true verbosetx=false "subnetwork")`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,9 +135,10 @@ func NewGetBestBlockHashCmd() *GetBestBlockHashCmd {
|
|||||||
|
|
||||||
// GetBlockCmd defines the getBlock JSON-RPC command.
|
// GetBlockCmd defines the getBlock JSON-RPC command.
|
||||||
type GetBlockCmd struct {
|
type GetBlockCmd struct {
|
||||||
Hash string
|
Hash string
|
||||||
Verbose *bool `jsonrpcdefault:"true"`
|
Verbose *bool `jsonrpcdefault:"true"`
|
||||||
VerboseTx *bool `jsonrpcdefault:"false"`
|
VerboseTx *bool `jsonrpcdefault:"false"`
|
||||||
|
Subnetwork *string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGetBlockCmd returns a new instance which can be used to issue a getBlock
|
// NewGetBlockCmd returns a new instance which can be used to issue a getBlock
|
||||||
@ -145,11 +146,12 @@ type GetBlockCmd struct {
|
|||||||
//
|
//
|
||||||
// The parameters which are pointers indicate they are optional. Passing nil
|
// The parameters which are pointers indicate they are optional. Passing nil
|
||||||
// for optional parameters will use the default value.
|
// for optional parameters will use the default value.
|
||||||
func NewGetBlockCmd(hash string, verbose, verboseTx *bool) *GetBlockCmd {
|
func NewGetBlockCmd(hash string, verbose, verboseTx *bool, subnetworkID *string) *GetBlockCmd {
|
||||||
return &GetBlockCmd{
|
return &GetBlockCmd{
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
Verbose: verbose,
|
Verbose: verbose,
|
||||||
VerboseTx: verboseTx,
|
VerboseTx: verboseTx,
|
||||||
|
Subnetwork: subnetworkID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ func TestDAGSvrCmds(t *testing.T) {
|
|||||||
return btcjson.NewCmd("getBlock", "123")
|
return btcjson.NewCmd("getBlock", "123")
|
||||||
},
|
},
|
||||||
staticCmd: func() interface{} {
|
staticCmd: func() interface{} {
|
||||||
return btcjson.NewGetBlockCmd("123", nil, nil)
|
return btcjson.NewGetBlockCmd("123", nil, nil, nil)
|
||||||
},
|
},
|
||||||
marshalled: `{"jsonrpc":"1.0","method":"getBlock","params":["123"],"id":1}`,
|
marshalled: `{"jsonrpc":"1.0","method":"getBlock","params":["123"],"id":1}`,
|
||||||
unmarshalled: &btcjson.GetBlockCmd{
|
unmarshalled: &btcjson.GetBlockCmd{
|
||||||
@ -150,7 +150,7 @@ func TestDAGSvrCmds(t *testing.T) {
|
|||||||
return btcjson.NewCmd("getBlock", "123", &verbosePtr)
|
return btcjson.NewCmd("getBlock", "123", &verbosePtr)
|
||||||
},
|
},
|
||||||
staticCmd: func() interface{} {
|
staticCmd: func() interface{} {
|
||||||
return btcjson.NewGetBlockCmd("123", btcjson.Bool(true), nil)
|
return btcjson.NewGetBlockCmd("123", btcjson.Bool(true), nil, nil)
|
||||||
},
|
},
|
||||||
marshalled: `{"jsonrpc":"1.0","method":"getBlock","params":["123",true],"id":1}`,
|
marshalled: `{"jsonrpc":"1.0","method":"getBlock","params":["123",true],"id":1}`,
|
||||||
unmarshalled: &btcjson.GetBlockCmd{
|
unmarshalled: &btcjson.GetBlockCmd{
|
||||||
@ -165,7 +165,7 @@ func TestDAGSvrCmds(t *testing.T) {
|
|||||||
return btcjson.NewCmd("getBlock", "123", true, true)
|
return btcjson.NewCmd("getBlock", "123", true, true)
|
||||||
},
|
},
|
||||||
staticCmd: func() interface{} {
|
staticCmd: func() interface{} {
|
||||||
return btcjson.NewGetBlockCmd("123", btcjson.Bool(true), btcjson.Bool(true))
|
return btcjson.NewGetBlockCmd("123", btcjson.Bool(true), btcjson.Bool(true), nil)
|
||||||
},
|
},
|
||||||
marshalled: `{"jsonrpc":"1.0","method":"getBlock","params":["123",true,true],"id":1}`,
|
marshalled: `{"jsonrpc":"1.0","method":"getBlock","params":["123",true,true],"id":1}`,
|
||||||
unmarshalled: &btcjson.GetBlockCmd{
|
unmarshalled: &btcjson.GetBlockCmd{
|
||||||
@ -174,6 +174,22 @@ func TestDAGSvrCmds(t *testing.T) {
|
|||||||
VerboseTx: btcjson.Bool(true),
|
VerboseTx: btcjson.Bool(true),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "getBlock required optional3",
|
||||||
|
newCmd: func() (interface{}, error) {
|
||||||
|
return btcjson.NewCmd("getBlock", "123", true, true, "456")
|
||||||
|
},
|
||||||
|
staticCmd: func() interface{} {
|
||||||
|
return btcjson.NewGetBlockCmd("123", btcjson.Bool(true), btcjson.Bool(true), btcjson.String("456"))
|
||||||
|
},
|
||||||
|
marshalled: `{"jsonrpc":"1.0","method":"getBlock","params":["123",true,true,"456"],"id":1}`,
|
||||||
|
unmarshalled: &btcjson.GetBlockCmd{
|
||||||
|
Hash: "123",
|
||||||
|
Verbose: btcjson.Bool(true),
|
||||||
|
VerboseTx: btcjson.Bool(true),
|
||||||
|
Subnetwork: btcjson.String("456"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "getBlockDagInfo",
|
name: "getBlockDagInfo",
|
||||||
newCmd: func() (interface{}, error) {
|
newCmd: func() (interface{}, error) {
|
||||||
|
@ -21,7 +21,7 @@ func ExampleMarshalCmd() {
|
|||||||
// convenience function for creating a pointer out of a primitive for
|
// convenience function for creating a pointer out of a primitive for
|
||||||
// optional parameters.
|
// optional parameters.
|
||||||
blockHash := "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
blockHash := "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
||||||
gbCmd := btcjson.NewGetBlockCmd(blockHash, btcjson.Bool(false), nil)
|
gbCmd := btcjson.NewGetBlockCmd(blockHash, btcjson.Bool(false), nil, nil)
|
||||||
|
|
||||||
// Marshal the command to the format suitable for sending to the RPC
|
// Marshal the command to the format suitable for sending to the RPC
|
||||||
// server. Typically the client would increment the id here which is
|
// server. Typically the client would increment the id here which is
|
||||||
@ -86,6 +86,9 @@ func ExampleUnmarshalCmd() {
|
|||||||
fmt.Println("Hash:", gbCmd.Hash)
|
fmt.Println("Hash:", gbCmd.Hash)
|
||||||
fmt.Println("Verbose:", *gbCmd.Verbose)
|
fmt.Println("Verbose:", *gbCmd.Verbose)
|
||||||
fmt.Println("VerboseTx:", *gbCmd.VerboseTx)
|
fmt.Println("VerboseTx:", *gbCmd.VerboseTx)
|
||||||
|
if gbCmd.Subnetwork != nil {
|
||||||
|
fmt.Println("Subnetwork:", *gbCmd.Subnetwork)
|
||||||
|
}
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// Hash: 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
|
// Hash: 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
|
||||||
|
@ -439,7 +439,7 @@ func (h *Harness) GenerateAndSubmitBlockWithCustomCoinbaseOutputs(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
mBlock, err := h.Node.GetBlock(parentBlockHash)
|
mBlock, err := h.Node.GetBlock(parentBlockHash, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -91,13 +91,13 @@ func (r FutureGetBlockResult) Receive() (*wire.MsgBlock, error) {
|
|||||||
// returned instance.
|
// returned instance.
|
||||||
//
|
//
|
||||||
// See GetBlock for the blocking version and more details.
|
// See GetBlock for the blocking version and more details.
|
||||||
func (c *Client) GetBlockAsync(blockHash *daghash.Hash) FutureGetBlockResult {
|
func (c *Client) GetBlockAsync(blockHash *daghash.Hash, subnetworkID *string) FutureGetBlockResult {
|
||||||
hash := ""
|
hash := ""
|
||||||
if blockHash != nil {
|
if blockHash != nil {
|
||||||
hash = blockHash.String()
|
hash = blockHash.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(false), nil)
|
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(false), btcjson.Bool(false), subnetworkID)
|
||||||
return c.sendCmd(cmd)
|
return c.sendCmd(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,8 +105,8 @@ func (c *Client) GetBlockAsync(blockHash *daghash.Hash) FutureGetBlockResult {
|
|||||||
//
|
//
|
||||||
// See GetBlockVerbose to retrieve a data structure with information about the
|
// See GetBlockVerbose to retrieve a data structure with information about the
|
||||||
// block instead.
|
// block instead.
|
||||||
func (c *Client) GetBlock(blockHash *daghash.Hash) (*wire.MsgBlock, error) {
|
func (c *Client) GetBlock(blockHash *daghash.Hash, subnetworkID *string) (*wire.MsgBlock, error) {
|
||||||
return c.GetBlockAsync(blockHash).Receive()
|
return c.GetBlockAsync(blockHash, subnetworkID).Receive()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FutureGetBlockVerboseResult is a future promise to deliver the result of a
|
// FutureGetBlockVerboseResult is a future promise to deliver the result of a
|
||||||
@ -135,13 +135,13 @@ func (r FutureGetBlockVerboseResult) Receive() (*btcjson.GetBlockVerboseResult,
|
|||||||
// the returned instance.
|
// the returned instance.
|
||||||
//
|
//
|
||||||
// See GetBlockVerbose for the blocking version and more details.
|
// See GetBlockVerbose for the blocking version and more details.
|
||||||
func (c *Client) GetBlockVerboseAsync(blockHash *daghash.Hash) FutureGetBlockVerboseResult {
|
func (c *Client) GetBlockVerboseAsync(blockHash *daghash.Hash, subnetworkID *string) FutureGetBlockVerboseResult {
|
||||||
hash := ""
|
hash := ""
|
||||||
if blockHash != nil {
|
if blockHash != nil {
|
||||||
hash = blockHash.String()
|
hash = blockHash.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), nil)
|
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), btcjson.Bool(false), subnetworkID)
|
||||||
return c.sendCmd(cmd)
|
return c.sendCmd(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,8 +150,8 @@ func (c *Client) GetBlockVerboseAsync(blockHash *daghash.Hash) FutureGetBlockVer
|
|||||||
//
|
//
|
||||||
// See GetBlockVerboseTx to retrieve transaction data structures as well.
|
// See GetBlockVerboseTx to retrieve transaction data structures as well.
|
||||||
// See GetBlock to retrieve a raw block instead.
|
// See GetBlock to retrieve a raw block instead.
|
||||||
func (c *Client) GetBlockVerbose(blockHash *daghash.Hash) (*btcjson.GetBlockVerboseResult, error) {
|
func (c *Client) GetBlockVerbose(blockHash *daghash.Hash, subnetworkID *string) (*btcjson.GetBlockVerboseResult, error) {
|
||||||
return c.GetBlockVerboseAsync(blockHash).Receive()
|
return c.GetBlockVerboseAsync(blockHash, subnetworkID).Receive()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlockVerboseTxAsync returns an instance of a type that can be used to get
|
// GetBlockVerboseTxAsync returns an instance of a type that can be used to get
|
||||||
@ -159,13 +159,13 @@ func (c *Client) GetBlockVerbose(blockHash *daghash.Hash) (*btcjson.GetBlockVerb
|
|||||||
// the returned instance.
|
// the returned instance.
|
||||||
//
|
//
|
||||||
// See GetBlockVerboseTx or the blocking version and more details.
|
// See GetBlockVerboseTx or the blocking version and more details.
|
||||||
func (c *Client) GetBlockVerboseTxAsync(blockHash *daghash.Hash) FutureGetBlockVerboseResult {
|
func (c *Client) GetBlockVerboseTxAsync(blockHash *daghash.Hash, subnetworkID *string) FutureGetBlockVerboseResult {
|
||||||
hash := ""
|
hash := ""
|
||||||
if blockHash != nil {
|
if blockHash != nil {
|
||||||
hash = blockHash.String()
|
hash = blockHash.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), btcjson.Bool(true))
|
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), btcjson.Bool(true), subnetworkID)
|
||||||
return c.sendCmd(cmd)
|
return c.sendCmd(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,8 +174,8 @@ func (c *Client) GetBlockVerboseTxAsync(blockHash *daghash.Hash) FutureGetBlockV
|
|||||||
//
|
//
|
||||||
// See GetBlockVerbose if only transaction hashes are preferred.
|
// See GetBlockVerbose if only transaction hashes are preferred.
|
||||||
// See GetBlock to retrieve a raw block instead.
|
// See GetBlock to retrieve a raw block instead.
|
||||||
func (c *Client) GetBlockVerboseTx(blockHash *daghash.Hash) (*btcjson.GetBlockVerboseResult, error) {
|
func (c *Client) GetBlockVerboseTx(blockHash *daghash.Hash, subnetworkID *string) (*btcjson.GetBlockVerboseResult, error) {
|
||||||
return c.GetBlockVerboseTxAsync(blockHash).Receive()
|
return c.GetBlockVerboseTxAsync(blockHash, subnetworkID).Receive()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FutureGetBlockCountResult is a future promise to deliver the result of a
|
// FutureGetBlockCountResult is a future promise to deliver the result of a
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
@ -47,6 +48,7 @@ import (
|
|||||||
"github.com/daglabs/btcd/util"
|
"github.com/daglabs/btcd/util"
|
||||||
"github.com/daglabs/btcd/util/fs"
|
"github.com/daglabs/btcd/util/fs"
|
||||||
"github.com/daglabs/btcd/util/network"
|
"github.com/daglabs/btcd/util/network"
|
||||||
|
"github.com/daglabs/btcd/util/subnetworkid"
|
||||||
"github.com/daglabs/btcd/version"
|
"github.com/daglabs/btcd/version"
|
||||||
"github.com/daglabs/btcd/wire"
|
"github.com/daglabs/btcd/wire"
|
||||||
)
|
)
|
||||||
@ -1107,6 +1109,42 @@ func handleGetBlock(s *Server, cmd interface{}, closeChan <-chan struct{}) (inte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle partial blocks
|
||||||
|
if c.Subnetwork != nil {
|
||||||
|
requestSubnetworkID, err := subnetworkid.NewFromStr(*c.Subnetwork)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &btcjson.RPCError{
|
||||||
|
Code: btcjson.ErrRPCInvalidRequest.Code,
|
||||||
|
Message: "invalid subnetwork string",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodeSubnetworkID := config.MainConfig().SubnetworkID
|
||||||
|
|
||||||
|
if !requestSubnetworkID.IsEqual(&wire.SubnetworkIDSupportsAll) {
|
||||||
|
if !nodeSubnetworkID.IsEqual(&wire.SubnetworkIDSupportsAll) {
|
||||||
|
if !nodeSubnetworkID.IsEqual(requestSubnetworkID) {
|
||||||
|
return nil, &btcjson.RPCError{
|
||||||
|
Code: btcjson.ErrRPCInvalidRequest.Code,
|
||||||
|
Message: "subnetwork does not match this partial node",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// nothing to do - partial node stores partial blocks
|
||||||
|
} else {
|
||||||
|
// Deserialize the block.
|
||||||
|
var msgBlock wire.MsgBlock
|
||||||
|
err = msgBlock.Deserialize(bytes.NewReader(blkBytes))
|
||||||
|
if err != nil {
|
||||||
|
context := "Failed to deserialize block"
|
||||||
|
return nil, internalRPCError(err.Error(), context)
|
||||||
|
}
|
||||||
|
msgBlock.ConvertToPartial(requestSubnetworkID)
|
||||||
|
var b bytes.Buffer
|
||||||
|
msgBlock.Serialize(bufio.NewWriter(&b))
|
||||||
|
blkBytes = b.Bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// When the verbose flag isn't set, simply return the serialized block
|
// When the verbose flag isn't set, simply return the serialized block
|
||||||
// as a hex-encoded string.
|
// as a hex-encoded string.
|
||||||
if c.Verbose != nil && !*c.Verbose {
|
if c.Verbose != nil && !*c.Verbose {
|
||||||
|
@ -169,6 +169,7 @@ var helpDescsEnUS = map[string]string{
|
|||||||
"getBlock-hash": "The hash of the block",
|
"getBlock-hash": "The hash of the block",
|
||||||
"getBlock-verbose": "Specifies the block is returned as a JSON object instead of hex-encoded string",
|
"getBlock-verbose": "Specifies the block is returned as a JSON object instead of hex-encoded string",
|
||||||
"getBlock-verboseTx": "Specifies that each transaction is returned as a JSON object and only applies if the verbose flag is true (btcd extension)",
|
"getBlock-verboseTx": "Specifies that each transaction is returned as a JSON object and only applies if the verbose flag is true (btcd extension)",
|
||||||
|
"getBlock-subnetwork": "If passed, the returned block will be a partial block of the specified subnetwork",
|
||||||
"getBlock--condition0": "verbose=false",
|
"getBlock--condition0": "verbose=false",
|
||||||
"getBlock--condition1": "verbose=true",
|
"getBlock--condition1": "verbose=true",
|
||||||
"getBlock-acceptedTx": "Specifies if the transaction got accepted",
|
"getBlock-acceptedTx": "Specifies if the transaction got accepted",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user