Implement 'getblockstats' JSON-RPC command
This commit is contained in:
parent
8b1be46463
commit
cfcf4fb762
4 changed files with 172 additions and 0 deletions
|
@ -191,6 +191,50 @@ func NewGetBlockHeaderCmd(hash string, verbose *bool) *GetBlockHeaderCmd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HashOrHeight defines a type that can be used as hash_or_height value in JSON-RPC commands.
|
||||||
|
type HashOrHeight struct {
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface
|
||||||
|
func (h HashOrHeight) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(h.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the json.Unmarshaler interface
|
||||||
|
func (h *HashOrHeight) UnmarshalJSON(data []byte) error {
|
||||||
|
var unmarshalled interface{}
|
||||||
|
if err := json.Unmarshal(data, &unmarshalled); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v := unmarshalled.(type) {
|
||||||
|
case float64:
|
||||||
|
h.Value = int(v)
|
||||||
|
case string:
|
||||||
|
h.Value = v
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid hash_or_height value: %v", unmarshalled)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlockStatsCmd defines the getblockstats JSON-RPC command.
|
||||||
|
type GetBlockStatsCmd struct {
|
||||||
|
HashOrHeight HashOrHeight
|
||||||
|
Stats *[]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGetBlockStatsCmd returns a new instance which can be used to issue a
|
||||||
|
// getblockstats JSON-RPC command. Either height or hash must be specified.
|
||||||
|
func NewGetBlockStatsCmd(hashOrHeight HashOrHeight, stats *[]string) *GetBlockStatsCmd {
|
||||||
|
return &GetBlockStatsCmd{
|
||||||
|
HashOrHeight: hashOrHeight,
|
||||||
|
Stats: stats,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TemplateRequest is a request object as defined in BIP22
|
// TemplateRequest is a request object as defined in BIP22
|
||||||
// (https://en.bitcoin.it/wiki/BIP_0022), it is optionally provided as an
|
// (https://en.bitcoin.it/wiki/BIP_0022), it is optionally provided as an
|
||||||
// pointer argument to GetBlockTemplateCmd.
|
// pointer argument to GetBlockTemplateCmd.
|
||||||
|
@ -798,6 +842,7 @@ func init() {
|
||||||
MustRegisterCmd("getblockcount", (*GetBlockCountCmd)(nil), flags)
|
MustRegisterCmd("getblockcount", (*GetBlockCountCmd)(nil), flags)
|
||||||
MustRegisterCmd("getblockhash", (*GetBlockHashCmd)(nil), flags)
|
MustRegisterCmd("getblockhash", (*GetBlockHashCmd)(nil), flags)
|
||||||
MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags)
|
MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags)
|
||||||
|
MustRegisterCmd("getblockstats", (*GetBlockStatsCmd)(nil), flags)
|
||||||
MustRegisterCmd("getblocktemplate", (*GetBlockTemplateCmd)(nil), flags)
|
MustRegisterCmd("getblocktemplate", (*GetBlockTemplateCmd)(nil), flags)
|
||||||
MustRegisterCmd("getcfilter", (*GetCFilterCmd)(nil), flags)
|
MustRegisterCmd("getcfilter", (*GetCFilterCmd)(nil), flags)
|
||||||
MustRegisterCmd("getcfilterheader", (*GetCFilterHeaderCmd)(nil), flags)
|
MustRegisterCmd("getcfilterheader", (*GetCFilterHeaderCmd)(nil), flags)
|
||||||
|
|
|
@ -228,6 +228,60 @@ func TestChainSvrCmds(t *testing.T) {
|
||||||
Verbose: btcjson.Bool(true),
|
Verbose: btcjson.Bool(true),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "getblockstats height",
|
||||||
|
newCmd: func() (interface{}, error) {
|
||||||
|
return btcjson.NewCmd("getblockstats", btcjson.HashOrHeight{Value: 123})
|
||||||
|
},
|
||||||
|
staticCmd: func() interface{} {
|
||||||
|
return btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: 123}, nil)
|
||||||
|
},
|
||||||
|
marshalled: `{"jsonrpc":"1.0","method":"getblockstats","params":[123],"id":1}`,
|
||||||
|
unmarshalled: &btcjson.GetBlockStatsCmd{
|
||||||
|
HashOrHeight: btcjson.HashOrHeight{Value: 123},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "getblockstats hash",
|
||||||
|
newCmd: func() (interface{}, error) {
|
||||||
|
return btcjson.NewCmd("getblockstats", btcjson.HashOrHeight{Value: "deadbeef"})
|
||||||
|
},
|
||||||
|
staticCmd: func() interface{} {
|
||||||
|
return btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: "deadbeef"}, nil)
|
||||||
|
},
|
||||||
|
marshalled: `{"jsonrpc":"1.0","method":"getblockstats","params":["deadbeef"],"id":1}`,
|
||||||
|
unmarshalled: &btcjson.GetBlockStatsCmd{
|
||||||
|
HashOrHeight: btcjson.HashOrHeight{Value: "deadbeef"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "getblockstats height optional stats",
|
||||||
|
newCmd: func() (interface{}, error) {
|
||||||
|
return btcjson.NewCmd("getblockstats", btcjson.HashOrHeight{Value: 123}, []string{"avgfee", "maxfee"})
|
||||||
|
},
|
||||||
|
staticCmd: func() interface{} {
|
||||||
|
return btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: 123}, &[]string{"avgfee", "maxfee"})
|
||||||
|
},
|
||||||
|
marshalled: `{"jsonrpc":"1.0","method":"getblockstats","params":[123,["avgfee","maxfee"]],"id":1}`,
|
||||||
|
unmarshalled: &btcjson.GetBlockStatsCmd{
|
||||||
|
HashOrHeight: btcjson.HashOrHeight{Value: 123},
|
||||||
|
Stats: &[]string{"avgfee", "maxfee"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "getblockstats hash optional stats",
|
||||||
|
newCmd: func() (interface{}, error) {
|
||||||
|
return btcjson.NewCmd("getblockstats", btcjson.HashOrHeight{Value: "deadbeef"}, []string{"avgfee", "maxfee"})
|
||||||
|
},
|
||||||
|
staticCmd: func() interface{} {
|
||||||
|
return btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: "deadbeef"}, &[]string{"avgfee", "maxfee"})
|
||||||
|
},
|
||||||
|
marshalled: `{"jsonrpc":"1.0","method":"getblockstats","params":["deadbeef",["avgfee","maxfee"]],"id":1}`,
|
||||||
|
unmarshalled: &btcjson.GetBlockStatsCmd{
|
||||||
|
HashOrHeight: btcjson.HashOrHeight{Value: "deadbeef"},
|
||||||
|
Stats: &[]string{"avgfee", "maxfee"},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "getblocktemplate",
|
name: "getblocktemplate",
|
||||||
newCmd: func() (interface{}, error) {
|
newCmd: func() (interface{}, error) {
|
||||||
|
|
|
@ -24,6 +24,38 @@ type GetBlockHeaderVerboseResult struct {
|
||||||
NextHash string `json:"nextblockhash,omitempty"`
|
NextHash string `json:"nextblockhash,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetBlockStatsResult models the data from the getblockstats command.
|
||||||
|
type GetBlockStatsResult struct {
|
||||||
|
AverageFee int64 `json:"avgfee"`
|
||||||
|
AverageFeeRate int64 `json:"avgfeerate"`
|
||||||
|
AverageTxSize int64 `json:"avgtxsize"`
|
||||||
|
FeeratePercentiles []int64 `json:"feerate_percentiles"`
|
||||||
|
Hash string `json:"blockhash"`
|
||||||
|
Height int64 `json:"height"`
|
||||||
|
Ins int64 `json:"ins"`
|
||||||
|
MaxFee int64 `json:"maxfee"`
|
||||||
|
MaxFeeRate int64 `json:"maxfeerate"`
|
||||||
|
MaxTxSize int64 `json:"maxtxsize"`
|
||||||
|
MedianFee int64 `json:"medianfee"`
|
||||||
|
MedianTime int64 `json:"mediantime"`
|
||||||
|
MedianTxSize int64 `json:"mediantxsize"`
|
||||||
|
MinFee int64 `json:"minfee"`
|
||||||
|
MinFeeRate int64 `json:"minfeerate"`
|
||||||
|
MinTxSize int64 `json:"mintxsize"`
|
||||||
|
Outs int64 `json:"outs"`
|
||||||
|
SegWitTotalSize int64 `json:"swtotal_size"`
|
||||||
|
SegWitTotalWeight int64 `json:"swtotal_weight"`
|
||||||
|
SegWitTxs int64 `json:"swtxs"`
|
||||||
|
Subsidy int64 `json:"subsidy"`
|
||||||
|
Time int64 `json:"time"`
|
||||||
|
TotalOut int64 `json:"total_out"`
|
||||||
|
TotalSize int64 `json:"total_size"`
|
||||||
|
TotalWeight int64 `json:"total_weight"`
|
||||||
|
Txs int64 `json:"txs"`
|
||||||
|
UTXOIncrease int64 `json:"utxo_increase"`
|
||||||
|
UTXOSizeIncrease int64 `json:"utxo_size_inc"`
|
||||||
|
}
|
||||||
|
|
||||||
// GetBlockVerboseResult models the data from the getblock command when the
|
// GetBlockVerboseResult models the data from the getblock command when the
|
||||||
// verbose flag is set to 1. When the verbose flag is set to 0, getblock returns a
|
// verbose flag is set to 1. When the verbose flag is set to 0, getblock returns a
|
||||||
// hex-encoded string. When the verbose flag is set to 1, getblock returns an object
|
// hex-encoded string. When the verbose flag is set to 1, getblock returns an object
|
||||||
|
|
|
@ -1037,3 +1037,44 @@ func (c *Client) GetCFilterHeader(blockHash *chainhash.Hash,
|
||||||
filterType wire.FilterType) (*wire.MsgCFHeaders, error) {
|
filterType wire.FilterType) (*wire.MsgCFHeaders, error) {
|
||||||
return c.GetCFilterHeaderAsync(blockHash, filterType).Receive()
|
return c.GetCFilterHeaderAsync(blockHash, filterType).Receive()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FutureGetBlockStatsResult is a future promise to deliver the result of a
|
||||||
|
// GetBlockStatsAsync RPC invocation (or an applicable error).
|
||||||
|
type FutureGetBlockStatsResult chan *response
|
||||||
|
|
||||||
|
// Receive waits for the response promised by the future and returns statistics
|
||||||
|
// of a block at a certain height.
|
||||||
|
func (r FutureGetBlockStatsResult) Receive() (*btcjson.GetBlockStatsResult, error) {
|
||||||
|
res, err := receiveFuture(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var blockStats btcjson.GetBlockStatsResult
|
||||||
|
err = json.Unmarshal(res, &blockStats)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &blockStats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlockStatsAsync 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 GetBlockStats or the blocking version and more details.
|
||||||
|
func (c *Client) GetBlockStatsAsync(hashOrHeight interface{}, stats *[]string) FutureGetBlockStatsResult {
|
||||||
|
if hash, ok := hashOrHeight.(*chainhash.Hash); ok {
|
||||||
|
hashOrHeight = hash.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: hashOrHeight}, stats)
|
||||||
|
return c.sendCmd(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlockStats returns block statistics. First argument specifies height or hash of the target block.
|
||||||
|
// Second argument allows to select certain stats to return.
|
||||||
|
func (c *Client) GetBlockStats(hashOrHeight interface{}, stats *[]string) (*btcjson.GetBlockStatsResult, error) {
|
||||||
|
return c.GetBlockStatsAsync(hashOrHeight, stats).Receive()
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue