mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-04 13:16:43 +00:00
[NOD-423] Implement get selected tip RPC command (#469)
* [NOD-423] Rename BestBlock to SelectedTip * [NOD-423] Implement GetSelectedTip RPC command * [NOD-423] Add help to getSelectedTip command * [NOD-423] Fix getSelectedTip test * [NOD-423] Fix tests so they would compile. These tests will need to be rewriten at some point. * [NOD-423] Make integration test compile. Test need to be revisited * [NOD-423] Rename variables * [NOD-423] Change comment s about best block to selected tip. * [NOD-423] Update comment * [NOD-423] Change height to bluescore
This commit is contained in:
parent
7b07609fd8
commit
47214121a7
@ -72,13 +72,19 @@ func NewGenerateCmd(numBlocks uint32) *GenerateCmd {
|
||||
}
|
||||
}
|
||||
|
||||
// GetBestBlockCmd defines the getBestBlock JSON-RPC command.
|
||||
type GetBestBlockCmd struct{}
|
||||
// GetSelectedTipCmd defines the getSelectedTip JSON-RPC command.
|
||||
type GetSelectedTipCmd struct {
|
||||
Verbose *bool `jsonrpcdefault:"true"`
|
||||
VerboseTx *bool `jsonrpcdefault:"false"`
|
||||
}
|
||||
|
||||
// NewGetBestBlockCmd returns a new instance which can be used to issue a
|
||||
// getBestBlock JSON-RPC command.
|
||||
func NewGetBestBlockCmd() *GetBestBlockCmd {
|
||||
return &GetBestBlockCmd{}
|
||||
// NewGetSelectedTipCmd returns a new instance which can be used to issue a
|
||||
// getSelectedTip JSON-RPC command.
|
||||
func NewGetSelectedTipCmd(verbose, verboseTx *bool) *GetSelectedTipCmd {
|
||||
return &GetSelectedTipCmd{
|
||||
Verbose: verbose,
|
||||
VerboseTx: verboseTx,
|
||||
}
|
||||
}
|
||||
|
||||
// GetCurrentNetCmd defines the getCurrentNet JSON-RPC command.
|
||||
@ -144,7 +150,7 @@ func init() {
|
||||
MustRegisterCmd("debugLevel", (*DebugLevelCmd)(nil), flags)
|
||||
MustRegisterCmd("node", (*NodeCmd)(nil), flags)
|
||||
MustRegisterCmd("generate", (*GenerateCmd)(nil), flags)
|
||||
MustRegisterCmd("getBestBlock", (*GetBestBlockCmd)(nil), flags)
|
||||
MustRegisterCmd("getSelectedTip", (*GetSelectedTipCmd)(nil), flags)
|
||||
MustRegisterCmd("getCurrentNet", (*GetCurrentNetCmd)(nil), flags)
|
||||
MustRegisterCmd("getHeaders", (*GetHeadersCmd)(nil), flags)
|
||||
MustRegisterCmd("getTopHeaders", (*GetTopHeadersCmd)(nil), flags)
|
||||
|
@ -115,15 +115,18 @@ func TestBtcdExtCmds(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "getBestBlock",
|
||||
name: "getSelectedTip",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return btcjson.NewCmd("getBestBlock")
|
||||
return btcjson.NewCmd("getSelectedTip")
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return btcjson.NewGetBestBlockCmd()
|
||||
return btcjson.NewGetSelectedTipCmd(nil, nil)
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"getSelectedTip","params":[],"id":1}`,
|
||||
unmarshalled: &btcjson.GetSelectedTipCmd{
|
||||
Verbose: btcjson.Bool(true),
|
||||
VerboseTx: btcjson.Bool(false),
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"getBestBlock","params":[],"id":1}`,
|
||||
unmarshalled: &btcjson.GetBestBlockCmd{},
|
||||
},
|
||||
{
|
||||
name: "getCurrentNet",
|
||||
|
@ -124,13 +124,13 @@ func NewGetAllManualNodesInfoCmd(details *bool) *GetAllManualNodesInfoCmd {
|
||||
}
|
||||
}
|
||||
|
||||
// GetBestBlockHashCmd defines the getBestBlockHash JSON-RPC command.
|
||||
type GetBestBlockHashCmd struct{}
|
||||
// GetSelectedTipHashCmd defines the getSelectedTipHash JSON-RPC command.
|
||||
type GetSelectedTipHashCmd struct{}
|
||||
|
||||
// NewGetBestBlockHashCmd returns a new instance which can be used to issue a
|
||||
// getBestBlockHash JSON-RPC command.
|
||||
func NewGetBestBlockHashCmd() *GetBestBlockHashCmd {
|
||||
return &GetBestBlockHashCmd{}
|
||||
// NewGetSelectedTipHashCmd returns a new instance which can be used to issue a
|
||||
// getSelectedTipHash JSON-RPC command.
|
||||
func NewGetSelectedTipHashCmd() *GetSelectedTipHashCmd {
|
||||
return &GetSelectedTipHashCmd{}
|
||||
}
|
||||
|
||||
// GetBlockCmd defines the getBlock JSON-RPC command.
|
||||
@ -740,7 +740,7 @@ func init() {
|
||||
MustRegisterCmd("decodeRawTransaction", (*DecodeRawTransactionCmd)(nil), flags)
|
||||
MustRegisterCmd("decodeScript", (*DecodeScriptCmd)(nil), flags)
|
||||
MustRegisterCmd("getAllManualNodesInfo", (*GetAllManualNodesInfoCmd)(nil), flags)
|
||||
MustRegisterCmd("getBestBlockHash", (*GetBestBlockHashCmd)(nil), flags)
|
||||
MustRegisterCmd("getSelectedTipHash", (*GetSelectedTipHashCmd)(nil), flags)
|
||||
MustRegisterCmd("getBlock", (*GetBlockCmd)(nil), flags)
|
||||
MustRegisterCmd("getBlocks", (*GetBlocksCmd)(nil), flags)
|
||||
MustRegisterCmd("getBlockDagInfo", (*GetBlockDAGInfoCmd)(nil), flags)
|
||||
|
@ -115,15 +115,15 @@ func TestDAGSvrCmds(t *testing.T) {
|
||||
unmarshalled: &btcjson.GetAllManualNodesInfoCmd{Details: btcjson.Bool(true)},
|
||||
},
|
||||
{
|
||||
name: "getBestBlockHash",
|
||||
name: "getSelectedTipHash",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return btcjson.NewCmd("getBestBlockHash")
|
||||
return btcjson.NewCmd("getSelectedTipHash")
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return btcjson.NewGetBestBlockHashCmd()
|
||||
return btcjson.NewGetSelectedTipHashCmd()
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"getBestBlockHash","params":[],"id":1}`,
|
||||
unmarshalled: &btcjson.GetBestBlockHashCmd{},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"getSelectedTipHash","params":[],"id":1}`,
|
||||
unmarshalled: &btcjson.GetSelectedTipHashCmd{},
|
||||
},
|
||||
{
|
||||
name: "getBlock",
|
||||
|
@ -283,7 +283,7 @@ type GetSubnetworkResult struct {
|
||||
|
||||
// GetTxOutResult models the data from the gettxout command.
|
||||
type GetTxOutResult struct {
|
||||
BestBlock string `json:"bestBlock"`
|
||||
SelectedTip string `json:"selectedTip"`
|
||||
Confirmations *uint64 `json:"confirmations,omitempty"`
|
||||
IsInMempool bool `json:"isInMempool"`
|
||||
Value float64 `json:"value"`
|
||||
@ -485,12 +485,6 @@ type ValidateAddressResult struct {
|
||||
Address string `json:"address,omitempty"`
|
||||
}
|
||||
|
||||
// GetBestBlockResult models the data from the getbestblock command.
|
||||
type GetBestBlockResult struct {
|
||||
Hash string `json:"hash"`
|
||||
Height uint64 `json:"height"`
|
||||
}
|
||||
|
||||
// ChainBlock models a block that is part of the selected parent chain.
|
||||
type ChainBlock struct {
|
||||
Hash string `json:"hash"`
|
||||
|
@ -54,7 +54,7 @@ const (
|
||||
const (
|
||||
ErrRPCBlockNotFound RPCErrorCode = -5
|
||||
ErrRPCBlockCount RPCErrorCode = -5
|
||||
ErrRPCBestBlockHash RPCErrorCode = -5
|
||||
ErrRPCSelectedTipHash RPCErrorCode = -5
|
||||
ErrRPCDifficulty RPCErrorCode = -5
|
||||
ErrRPCOutOfRange RPCErrorCode = -1
|
||||
ErrRPCNoTxInfo RPCErrorCode = -5
|
||||
|
@ -435,7 +435,7 @@ func TestBIP0068AndCsv(t *testing.T) {
|
||||
|
||||
// Now mine 10 additional blocks giving the inputs generated above a
|
||||
// age of 11. Space out each block 10 minutes after the previous block.
|
||||
parentBlockHash, err := r.Node.GetBestBlockHash()
|
||||
parentBlockHash, err := r.Node.GetSelectedTipHash()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get prior block hash: %v", err)
|
||||
}
|
||||
|
@ -18,10 +18,10 @@ import (
|
||||
"github.com/daglabs/btcd/integration/rpctest"
|
||||
)
|
||||
|
||||
func testGetBestBlock(r *rpctest.Harness, t *testing.T) {
|
||||
_, prevbestHeight, err := r.Node.GetBestBlock()
|
||||
func testGetSelectedTip(r *rpctest.Harness, t *testing.T) {
|
||||
_, prevbestHeight, err := r.Node.GetSelectedTip()
|
||||
if err != nil {
|
||||
t.Fatalf("Call to `getbestblock` failed: %v", err)
|
||||
t.Fatalf("Call to `GetSelectedTip` failed: %v", err)
|
||||
}
|
||||
|
||||
// Create a new block connecting to the current tip.
|
||||
@ -30,9 +30,9 @@ func testGetBestBlock(r *rpctest.Harness, t *testing.T) {
|
||||
t.Fatalf("Unable to generate block: %v", err)
|
||||
}
|
||||
|
||||
bestHash, bestHeight, err := r.Node.GetBestBlock()
|
||||
bestHash, bestHeight, err := r.Node.GetSelectedTip()
|
||||
if err != nil {
|
||||
t.Fatalf("Call to `getbestblock` failed: %v", err)
|
||||
t.Fatalf("Call to `GetSelectedTip` failed: %v", err)
|
||||
}
|
||||
|
||||
// Hash should be the same as the newly submitted block.
|
||||
@ -95,7 +95,7 @@ func testGetBlockHash(r *rpctest.Harness, t *testing.T) {
|
||||
}
|
||||
|
||||
var rpcTestCases = []rpctest.HarnessTestCase{
|
||||
testGetBestBlock,
|
||||
testGetSelectedTip,
|
||||
testGetBlockCount,
|
||||
testGetBlockHash,
|
||||
}
|
||||
|
@ -245,14 +245,15 @@ func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error {
|
||||
|
||||
// Block until the wallet has fully synced up to the tip of the main
|
||||
// chain.
|
||||
_, height, err := h.Node.GetBestBlock()
|
||||
selectedTip, err := h.Node.GetSelectedTip()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blueScore := selectedTip.BlueScore
|
||||
ticker := time.NewTicker(time.Millisecond * 100)
|
||||
for range ticker.C {
|
||||
walletHeight := h.wallet.SyncedHeight()
|
||||
if walletHeight == height {
|
||||
if walletHeight == blueScore {
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -429,16 +430,24 @@ func (h *Harness) GenerateAndSubmitBlockWithCustomCoinbaseOutputs(
|
||||
blockVersion = BlockVersion
|
||||
}
|
||||
|
||||
parentBlockHash, parentBlockHeight, err := h.Node.GetBestBlock()
|
||||
selectedTip, err := h.Node.GetSelectedTip()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mBlock, err := h.Node.GetBlock(parentBlockHash, nil)
|
||||
|
||||
selectedTipHash, err := daghash.NewHashFromStr(selectedTip.Hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
selectedTipBlueScore := selectedTip.BlueScore
|
||||
mBlock, err := h.Node.GetBlock(selectedTipHash, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parentBlock := util.NewBlock(mBlock)
|
||||
parentBlock.SetChainHeight(parentBlockHeight)
|
||||
parentBlock.SetChainHeight(selectedTipBlueScore)
|
||||
|
||||
// Create a new block including the specified transactions
|
||||
newBlock, err := CreateBlock(parentBlock, txns, blockVersion,
|
||||
|
@ -81,19 +81,26 @@ func syncBlocks(nodes []*Harness) error {
|
||||
retry:
|
||||
for !blocksMatch {
|
||||
var parentHash *daghash.Hash
|
||||
var prevHeight uint64
|
||||
var prevBlueScore uint64
|
||||
for _, node := range nodes {
|
||||
blockHash, blockHeight, err := node.Node.GetBestBlock()
|
||||
selectedTip, err := node.Node.GetSelectedTip()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blockHash, err := daghash.NewHashFromStr(selectedTip.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blueScore := selectedTip.BlueScore
|
||||
|
||||
if parentHash != nil && (*blockHash != *parentHash ||
|
||||
blockHeight != prevHeight) {
|
||||
blueScore != prevBlueScore) {
|
||||
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
continue retry
|
||||
}
|
||||
parentHash, prevHeight = blockHash, blockHeight
|
||||
parentHash, prevBlueScore = blockHash, blueScore
|
||||
}
|
||||
|
||||
blocksMatch = true
|
||||
|
@ -15,13 +15,13 @@ import (
|
||||
"github.com/daglabs/btcd/wire"
|
||||
)
|
||||
|
||||
// FutureGetBestBlockHashResult is a future promise to deliver the result of a
|
||||
// GetBestBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBestBlockHashResult chan *response
|
||||
// FutureGetSelectedTipHashResult is a future promise to deliver the result of a
|
||||
// GetSelectedTipAsync RPC invocation (or an applicable error).
|
||||
type FutureGetSelectedTipHashResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the hash of
|
||||
// the best block in the longest block dag.
|
||||
func (r FutureGetBestBlockHashResult) Receive() (*daghash.Hash, error) {
|
||||
func (r FutureGetSelectedTipHashResult) Receive() (*daghash.Hash, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -36,20 +36,20 @@ func (r FutureGetBestBlockHashResult) Receive() (*daghash.Hash, error) {
|
||||
return daghash.NewHashFromStr(txHashStr)
|
||||
}
|
||||
|
||||
// GetBestBlockHashAsync returns an instance of a type that can be used to get
|
||||
// GetSelectedTipHashAsync 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 GetBestBlockHash for the blocking version and more details.
|
||||
func (c *Client) GetBestBlockHashAsync() FutureGetBestBlockHashResult {
|
||||
cmd := btcjson.NewGetBestBlockHashCmd()
|
||||
// See GetSelectedTipHash for the blocking version and more details.
|
||||
func (c *Client) GetSelectedTipHashAsync() FutureGetSelectedTipHashResult {
|
||||
cmd := btcjson.NewGetSelectedTipHashCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBestBlockHash returns the hash of the best block in the longest block
|
||||
// dag.
|
||||
func (c *Client) GetBestBlockHash() (*daghash.Hash, error) {
|
||||
return c.GetBestBlockHashAsync().Receive()
|
||||
// GetSelectedTipHash returns the hash of the selected tip of the
|
||||
// Block DAG.
|
||||
func (c *Client) GetSelectedTipHash() (*daghash.Hash, error) {
|
||||
return c.GetSelectedTipHashAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetBlockResult is a future promise to deliver the result of a
|
||||
|
@ -62,52 +62,87 @@ func (c *Client) DebugLevel(levelSpec string) (string, error) {
|
||||
return c.DebugLevelAsync(levelSpec).Receive()
|
||||
}
|
||||
|
||||
// FutureGetBestBlockResult is a future promise to deliver the result of a
|
||||
// GetBestBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBestBlockResult chan *response
|
||||
// FutureGetSelectedTipResult is a future promise to deliver the result of a
|
||||
// GetSelectedTipAsync RPC invocation (or an applicable error).
|
||||
type FutureGetSelectedTipResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the hash
|
||||
// and height of the block in the longest (best) chain.
|
||||
func (r FutureGetBestBlockResult) Receive() (*daghash.Hash, uint64, error) {
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// selected tip block.
|
||||
func (r FutureGetSelectedTipResult) Receive() (*wire.MsgBlock, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a getbestblock result object.
|
||||
var bestBlock btcjson.GetBestBlockResult
|
||||
err = json.Unmarshal(res, &bestBlock)
|
||||
// Unmarshal result as a string.
|
||||
var blockHex string
|
||||
err = json.Unmarshal(res, &blockHex)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert to hash from string.
|
||||
hash, err := daghash.NewHashFromStr(bestBlock.Hash)
|
||||
// Decode the serialized block hex to raw bytes.
|
||||
serializedBlock, err := hex.DecodeString(blockHex)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return hash, bestBlock.Height, nil
|
||||
// Deserialize the block and return it.
|
||||
var msgBlock wire.MsgBlock
|
||||
err = msgBlock.Deserialize(bytes.NewReader(serializedBlock))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &msgBlock, nil
|
||||
}
|
||||
|
||||
// GetBestBlockAsync returns an instance of a type that can be used to get the
|
||||
// GetSelectedTipAsync 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 GetBestBlock for the blocking version and more details.
|
||||
// See GetSelectedTip for the blocking version and more details.
|
||||
//
|
||||
// NOTE: This is a btcd extension.
|
||||
func (c *Client) GetBestBlockAsync() FutureGetBestBlockResult {
|
||||
cmd := btcjson.NewGetBestBlockCmd()
|
||||
func (c *Client) GetSelectedTipAsync() FutureGetSelectedTipResult {
|
||||
cmd := btcjson.NewGetSelectedTipCmd(btcjson.Bool(false), btcjson.Bool(false))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBestBlock returns the hash and height of the block in the longest (best)
|
||||
// chain.
|
||||
//
|
||||
// GetSelectedTip returns the block of the selected DAG tip
|
||||
// NOTE: This is a btcd extension.
|
||||
func (c *Client) GetBestBlock() (*daghash.Hash, uint64, error) {
|
||||
return c.GetBestBlockAsync().Receive()
|
||||
func (c *Client) GetSelectedTip() (*btcjson.GetBlockVerboseResult, error) {
|
||||
return c.GetSelectedTipVerboseAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetSelectedTipVerboseResult is a future promise to deliver the result of a
|
||||
// GetSelectedTipVerboseAsync RPC invocation (or an applicable error).
|
||||
type FutureGetSelectedTipVerboseResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the data
|
||||
// structure from the server with information about the requested block.
|
||||
func (r FutureGetSelectedTipVerboseResult) Receive() (*btcjson.GetBlockVerboseResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal the raw result into a BlockResult.
|
||||
var blockResult btcjson.GetBlockVerboseResult
|
||||
err = json.Unmarshal(res, &blockResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &blockResult, nil
|
||||
}
|
||||
|
||||
// GetSelectedTipVerboseAsync 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 GeSelectedTipBlockVerbose for the blocking version and more details.
|
||||
func (c *Client) GetSelectedTipVerboseAsync() FutureGetSelectedTipVerboseResult {
|
||||
cmd := btcjson.NewGetSelectedTipCmd(btcjson.Bool(true), btcjson.Bool(false))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// FutureGetCurrentNetResult is a future promise to deliver the result of a
|
||||
|
@ -1,15 +0,0 @@
|
||||
package rpc
|
||||
|
||||
import "github.com/daglabs/btcd/btcjson"
|
||||
|
||||
// handleGetBestBlock implements the getBestBlock command.
|
||||
func handleGetBestBlock(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||
// All other "get block" commands give either the height, the
|
||||
// hash, or both but require the block SHA. This gets both for
|
||||
// the best block.
|
||||
result := &btcjson.GetBestBlockResult{
|
||||
Hash: s.cfg.DAG.SelectedTipHash().String(),
|
||||
Height: s.cfg.DAG.ChainHeight(), //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
}
|
||||
return result, nil
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package rpc
|
||||
|
||||
// handleGetBestBlockHash implements the getBestBlockHash command.
|
||||
func handleGetBestBlockHash(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||
return s.cfg.DAG.SelectedTipHash().String(), nil
|
||||
}
|
@ -80,8 +80,8 @@ func handleGetBlock(s *Server, cmd interface{}, closeChan <-chan struct{}) (inte
|
||||
}
|
||||
}
|
||||
|
||||
// When the verbose flag isn't set, simply return the serialized block
|
||||
// as a hex-encoded string.
|
||||
// When the verbose flag is set to false, simply return the serialized block
|
||||
// as a hex-encoded string (verbose flag is on by default).
|
||||
if c.Verbose != nil && !*c.Verbose {
|
||||
return hex.EncodeToString(blkBytes), nil
|
||||
}
|
||||
|
46
server/rpc/handle_get_selected_tip.go
Normal file
46
server/rpc/handle_get_selected_tip.go
Normal file
@ -0,0 +1,46 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"github.com/daglabs/btcd/btcjson"
|
||||
"github.com/daglabs/btcd/database"
|
||||
"github.com/daglabs/btcd/util"
|
||||
)
|
||||
|
||||
// handleGetSelectedTip implements the getSelectedTip command.
|
||||
func handleGetSelectedTip(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||
getSelectedTipCmd := cmd.(*btcjson.GetSelectedTipCmd)
|
||||
selectedTipHash := s.cfg.DAG.SelectedTipHash()
|
||||
|
||||
var blockBytes []byte
|
||||
err := s.cfg.DB.View(func(dbTx database.Tx) error {
|
||||
var err error
|
||||
blockBytes, err = dbTx.FetchBlock(selectedTipHash)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, &btcjson.RPCError{
|
||||
Code: btcjson.ErrRPCBlockNotFound,
|
||||
Message: "Block not found",
|
||||
}
|
||||
}
|
||||
|
||||
// When the verbose flag is set to false, simply return the serialized block
|
||||
// as a hex-encoded string (verbose flag is on by default).
|
||||
if getSelectedTipCmd.Verbose != nil && !*getSelectedTipCmd.Verbose {
|
||||
return hex.EncodeToString(blockBytes), nil
|
||||
}
|
||||
|
||||
// Deserialize the block.
|
||||
blk, err := util.NewBlockFromBytes(blockBytes)
|
||||
if err != nil {
|
||||
context := "Failed to deserialize block"
|
||||
return nil, internalRPCError(err.Error(), context)
|
||||
}
|
||||
|
||||
blockVerboseResult, err := buildGetBlockVerboseResult(s, blk, getSelectedTipCmd.VerboseTx == nil || !*getSelectedTipCmd.VerboseTx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return blockVerboseResult, nil
|
||||
}
|
6
server/rpc/handle_get_selected_tip_hash.go
Normal file
6
server/rpc/handle_get_selected_tip_hash.go
Normal file
@ -0,0 +1,6 @@
|
||||
package rpc
|
||||
|
||||
// handleGetSelectedTipHash implements the getSelectedTipHash command.
|
||||
func handleGetSelectedTipHash(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||
return s.cfg.DAG.SelectedTipHash().String(), nil
|
||||
}
|
@ -22,7 +22,7 @@ func handleGetTxOut(s *Server, cmd interface{}, closeChan <-chan struct{}) (inte
|
||||
|
||||
// If requested and the tx is available in the mempool try to fetch it
|
||||
// from there, otherwise attempt to fetch from the block database.
|
||||
var bestBlockHash string
|
||||
var selectedTipHash string
|
||||
var confirmations *uint64
|
||||
var value uint64
|
||||
var scriptPubKey []byte
|
||||
@ -56,7 +56,7 @@ func handleGetTxOut(s *Server, cmd interface{}, closeChan <-chan struct{}) (inte
|
||||
return nil, internalRPCError(errStr, "")
|
||||
}
|
||||
|
||||
bestBlockHash = s.cfg.DAG.SelectedTipHash().String()
|
||||
selectedTipHash = s.cfg.DAG.SelectedTipHash().String()
|
||||
value = txOut.Value
|
||||
scriptPubKey = txOut.ScriptPubKey
|
||||
isCoinbase = mtx.IsCoinBase()
|
||||
@ -86,7 +86,7 @@ func handleGetTxOut(s *Server, cmd interface{}, closeChan <-chan struct{}) (inte
|
||||
confirmations = &txConfirmations
|
||||
}
|
||||
|
||||
bestBlockHash = s.cfg.DAG.SelectedTipHash().String()
|
||||
selectedTipHash = s.cfg.DAG.SelectedTipHash().String()
|
||||
value = entry.Amount()
|
||||
scriptPubKey = entry.ScriptPubKey()
|
||||
isCoinbase = entry.IsCoinbase()
|
||||
@ -108,7 +108,7 @@ func handleGetTxOut(s *Server, cmd interface{}, closeChan <-chan struct{}) (inte
|
||||
}
|
||||
|
||||
txOutReply := &btcjson.GetTxOutResult{
|
||||
BestBlock: bestBlockHash,
|
||||
SelectedTip: selectedTipHash,
|
||||
Confirmations: confirmations,
|
||||
IsInMempool: isInMempool,
|
||||
Value: util.Amount(value).ToBTC(),
|
||||
|
@ -66,8 +66,8 @@ var rpcHandlersBeforeInit = map[string]commandHandler{
|
||||
"decodeScript": handleDecodeScript,
|
||||
"generate": handleGenerate,
|
||||
"getAllManualNodesInfo": handleGetAllManualNodesInfo,
|
||||
"getBestBlock": handleGetBestBlock,
|
||||
"getBestBlockHash": handleGetBestBlockHash,
|
||||
"getSelectedTip": handleGetSelectedTip,
|
||||
"getSelectedTipHash": handleGetSelectedTipHash,
|
||||
"getBlock": handleGetBlock,
|
||||
"getBlocks": handleGetBlocks,
|
||||
"getBlockDagInfo": handleGetBlockDAGInfo,
|
||||
@ -140,8 +140,8 @@ var rpcLimited = map[string]struct{}{
|
||||
"createRawTransaction": {},
|
||||
"decodeRawTransaction": {},
|
||||
"decodeScript": {},
|
||||
"getBestBlock": {},
|
||||
"getBestBlockHash": {},
|
||||
"getSelectedTip": {},
|
||||
"getSelectedTipHash": {},
|
||||
"getBlock": {},
|
||||
"getBlocks": {},
|
||||
"getBlockCount": {},
|
||||
|
@ -149,17 +149,22 @@ var helpDescsEnUS = map[string]string{
|
||||
"getManualNodeInfo--condition1": "details=true",
|
||||
"getManualNodeInfo--result0": "List of added peers",
|
||||
|
||||
// GetBestBlockResult help.
|
||||
"getBestBlockResult-hash": "Hex-encoded bytes of the best block hash",
|
||||
"getBestBlockResult-height": "Height of the best block",
|
||||
// GetSelectedTipResult help.
|
||||
"getSelectedTipResult-hash": "Hex-encoded bytes of the best block hash",
|
||||
"getSelectedTipResult-height": "Height of the best block",
|
||||
|
||||
// GetBestBlockCmd help.
|
||||
"getBestBlock--synopsis": "Get block height and hash of best block in the main chain.",
|
||||
"getBestBlock--result0": "Get block height and hash of best block in the main chain.",
|
||||
// GetSelectedTipCmd help.
|
||||
"getSelectedTip--synopsis": "Returns information about the selected tip of the blockDAG.",
|
||||
"getSelectedTip-verbose": "Specifies the block is returned as a JSON object instead of hex-encoded string",
|
||||
"getSelectedTip-verboseTx": "Specifies that each transaction is returned as a JSON object and only applies if the verbose flag is true (btcd extension)",
|
||||
"getSelectedTip--condition0": "verbose=false",
|
||||
"getSelectedTip--condition1": "verbose=true",
|
||||
"getSelectedTip-acceptedTx": "Specifies if the transaction got accepted",
|
||||
"getSelectedTip--result0": "Hex-encoded bytes of the serialized block",
|
||||
|
||||
// GetBestBlockHashCmd help.
|
||||
"getBestBlockHash--synopsis": "Returns the hash of the of the best (most recent) block in the longest block chain.",
|
||||
"getBestBlockHash--result0": "The hex-encoded block hash",
|
||||
// GetSelectedTipHashCmd help.
|
||||
"getSelectedTipHash--synopsis": "Returns the hash of the of the selected tip of the blockDAG.",
|
||||
"getSelectedTipHash--result0": "The hex-encoded block hash",
|
||||
|
||||
// GetBlockCmd help.
|
||||
"getBlock--synopsis": "Returns information about a block given its hash.",
|
||||
@ -519,7 +524,7 @@ var helpDescsEnUS = map[string]string{
|
||||
"getSubnetworkResult-gasLimit": "The gas limit of the subnetwork",
|
||||
|
||||
// GetTxOutResult help.
|
||||
"getTxOutResult-bestBlock": "The block hash that contains the transaction output",
|
||||
"getTxOutResult-selectedTip": "The block hash that contains the transaction output",
|
||||
"getTxOutResult-confirmations": "The number of confirmations (Will be 'null' if txindex is not disabled)",
|
||||
"getTxOutResult-isInMempool": "Whether the transaction is in the mempool",
|
||||
"getTxOutResult-value": "The transaction amount in BTC",
|
||||
@ -675,8 +680,8 @@ var rpcResultTypes = map[string][]interface{}{
|
||||
"decodeScript": {(*btcjson.DecodeScriptResult)(nil)},
|
||||
"generate": {(*[]string)(nil)},
|
||||
"getAllManualNodesInfo": {(*[]string)(nil), (*[]btcjson.GetManualNodeInfoResult)(nil)},
|
||||
"getBestBlock": {(*btcjson.GetBestBlockResult)(nil)},
|
||||
"getBestBlockHash": {(*string)(nil)},
|
||||
"getSelectedTip": {(*btcjson.GetBlockVerboseResult)(nil)},
|
||||
"getSelectedTipHash": {(*string)(nil)},
|
||||
"getBlock": {(*string)(nil), (*btcjson.GetBlockVerboseResult)(nil)},
|
||||
"getBlocks": {(*btcjson.GetBlocksResult)(nil)},
|
||||
"getBlockCount": {(*int64)(nil)},
|
||||
|
Loading…
x
Reference in New Issue
Block a user