rpcclient: implement gettxoutsetinfo command

This commit is contained in:
Anirudha Bose 2020-09-28 14:42:18 +02:00 committed by John C. Vernaleo
parent 584c382334
commit 6519c04a6f
4 changed files with 188 additions and 0 deletions

View file

@ -9,6 +9,8 @@ import (
"encoding/hex"
"encoding/json"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
)
@ -435,6 +437,64 @@ type GetTxOutResult struct {
Coinbase bool `json:"coinbase"`
}
// GetTxOutSetInfoResult models the data from the gettxoutsetinfo command.
type GetTxOutSetInfoResult struct {
Height int64 `json:"height"`
BestBlock chainhash.Hash `json:"bestblock"`
Transactions int64 `json:"transactions"`
TxOuts int64 `json:"txouts"`
BogoSize int64 `json:"bogosize"`
HashSerialized chainhash.Hash `json:"hash_serialized_2"`
DiskSize int64 `json:"disk_size"`
TotalAmount btcutil.Amount `json:"total_amount"`
}
// UnmarshalJSON unmarshals the result of the gettxoutsetinfo JSON-RPC call
func (g *GetTxOutSetInfoResult) UnmarshalJSON(data []byte) error {
// Step 1: Create type aliases of the original struct.
type Alias GetTxOutSetInfoResult
// Step 2: Create an anonymous struct with raw replacements for the special
// fields.
aux := &struct {
BestBlock string `json:"bestblock"`
HashSerialized string `json:"hash_serialized_2"`
TotalAmount float64 `json:"total_amount"`
*Alias
}{
Alias: (*Alias)(g),
}
// Step 3: Unmarshal the data into the anonymous struct.
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
// Step 4: Convert the raw fields to the desired types
blockHash, err := chainhash.NewHashFromStr(aux.BestBlock)
if err != nil {
return err
}
g.BestBlock = *blockHash
serializedHash, err := chainhash.NewHashFromStr(aux.HashSerialized)
if err != nil {
return err
}
g.HashSerialized = *serializedHash
amount, err := btcutil.NewAmount(aux.TotalAmount)
if err != nil {
return err
}
g.TotalAmount = amount
return nil
}
// GetNetTotalsResult models the data returned from the getnettotals command.
type GetNetTotalsResult struct {
TotalBytesRecv uint64 `json:"totalbytesrecv"`

View file

@ -6,8 +6,13 @@ package btcjson_test
import (
"encoding/json"
"reflect"
"testing"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcutil"
"github.com/davecgh/go-spew/spew"
"github.com/btcsuite/btcd/btcjson"
)
@ -86,3 +91,69 @@ func TestChainSvrCustomResults(t *testing.T) {
}
}
}
// TestGetTxOutSetInfoResult ensures that custom unmarshalling of
// GetTxOutSetInfoResult works as intended.
func TestGetTxOutSetInfoResult(t *testing.T) {
t.Parallel()
tests := []struct {
name string
result string
want btcjson.GetTxOutSetInfoResult
}{
{
name: "GetTxOutSetInfoResult - not scanning",
result: `{"height":123,"bestblock":"000000000000005f94116250e2407310463c0a7cf950f1af9ebe935b1c0687ab","transactions":1,"txouts":1,"bogosize":1,"hash_serialized_2":"9a0a561203ff052182993bc5d0cb2c620880bfafdbd80331f65fd9546c3e5c3e","disk_size":1,"total_amount":0.2}`,
want: btcjson.GetTxOutSetInfoResult{
Height: 123,
BestBlock: func() chainhash.Hash {
h, err := chainhash.NewHashFromStr("000000000000005f94116250e2407310463c0a7cf950f1af9ebe935b1c0687ab")
if err != nil {
panic(err)
}
return *h
}(),
Transactions: 1,
TxOuts: 1,
BogoSize: 1,
HashSerialized: func() chainhash.Hash {
h, err := chainhash.NewHashFromStr("9a0a561203ff052182993bc5d0cb2c620880bfafdbd80331f65fd9546c3e5c3e")
if err != nil {
panic(err)
}
return *h
}(),
DiskSize: 1,
TotalAmount: func() btcutil.Amount {
a, err := btcutil.NewAmount(0.2)
if err != nil {
panic(err)
}
return a
}(),
},
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
var out btcjson.GetTxOutSetInfoResult
err := json.Unmarshal([]byte(test.result), &out)
if err != nil {
t.Errorf("Test #%d (%s) unexpected error: %v", i,
test.name, err)
continue
}
if !reflect.DeepEqual(out, test.want) {
t.Errorf("Test #%d (%s) unexpected unmarshalled data - "+
"got %v, want %v", i, test.name, spew.Sdump(out),
spew.Sdump(test.want))
continue
}
}
}

View file

@ -1026,6 +1026,44 @@ func (c *Client) GetTxOut(txHash *chainhash.Hash, index uint32, mempool bool) (*
return c.GetTxOutAsync(txHash, index, mempool).Receive()
}
// FutureGetTxOutSetInfoResult is a future promise to deliver the result of a
// GetTxOutSetInfoAsync RPC invocation (or an applicable error).
type FutureGetTxOutSetInfoResult chan *response
// Receive waits for the response promised by the future and returns the
// results of GetTxOutSetInfoAsync RPC invocation.
func (r FutureGetTxOutSetInfoResult) Receive() (*btcjson.GetTxOutSetInfoResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as an gettxoutsetinfo result object.
var txOutSetInfo *btcjson.GetTxOutSetInfoResult
err = json.Unmarshal(res, &txOutSetInfo)
if err != nil {
return nil, err
}
return txOutSetInfo, nil
}
// GetTxOutSetInfoAsync 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 GetTxOutSetInfo for the blocking version and more details.
func (c *Client) GetTxOutSetInfoAsync() FutureGetTxOutSetInfoResult {
cmd := btcjson.NewGetTxOutSetInfoCmd()
return c.sendCmd(cmd)
}
// GetTxOutSetInfo returns the statistics about the unspent transaction output
// set.
func (c *Client) GetTxOutSetInfo() (*btcjson.GetTxOutSetInfoResult, error) {
return c.GetTxOutSetInfoAsync().Receive()
}
// FutureRescanBlocksResult is a future promise to deliver the result of a
// RescanBlocksAsync RPC invocation (or an applicable error).
//

View file

@ -116,3 +116,22 @@ func ExampleClient_GetWalletInfo() {
fmt.Println(*info.HDSeedID) // eb44e4e9b864ef17e7ba947da746375b000f5d94
fmt.Println(info.Scanning.Value) // false
}
func ExampleClient_GetTxOutSetInfo() {
client, err := New(connCfg, nil)
if err != nil {
panic(err)
}
defer client.Shutdown()
r, err := client.GetTxOutSetInfo()
if err != nil {
panic(err)
}
fmt.Println(r.TotalAmount.String()) // 20947654.56996054 BTC
fmt.Println(r.BestBlock.String()) // 000000000000005f94116250e2407310463c0a7cf950f1af9ebe935b1c0687ab
fmt.Println(r.TxOuts) // 24280607
fmt.Println(r.Transactions) // 9285603
fmt.Println(r.DiskSize) // 1320871611
}