mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-07 14:46:44 +00:00
[NOD-88] Add getTopHeaders rpc command (#242)
* [NOD-88] Add getTopHeaders rpc command * [NOD-88] Fix gofmt error * [NOD-88] Remove unnecessary variable * [NOD-88] Remove GetTopHeaders from rpcSyncMgr
This commit is contained in:
parent
7c30bc4301
commit
aa22480d5e
@ -1421,7 +1421,7 @@ func (dag *BlockDAG) locateBlockNodes(locator BlockLocator, hashStop *daghash.Ha
|
|||||||
queue.pushSet(node.children)
|
queue.pushSet(node.children)
|
||||||
|
|
||||||
visited := newSet()
|
visited := newSet()
|
||||||
for i := uint32(0); queue.Len() > 0 && i < maxEntries; i++ {
|
for queue.Len() > 0 && uint32(len(nodes)) < maxEntries {
|
||||||
var current *blockNode
|
var current *blockNode
|
||||||
current = queue.pop()
|
current = queue.pop()
|
||||||
if !visited.contains(current) {
|
if !visited.contains(current) {
|
||||||
@ -1474,6 +1474,32 @@ func (dag *BlockDAG) locateHeaders(locator BlockLocator, hashStop *daghash.Hash,
|
|||||||
return headers
|
return headers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTopHeaders returns the top wire.MaxBlockHeadersPerMsg block headers ordered by height.
|
||||||
|
func (dag *BlockDAG) GetTopHeaders(startHash *daghash.Hash) ([]*wire.BlockHeader, error) {
|
||||||
|
startNode := &dag.virtual.blockNode
|
||||||
|
if startHash != nil {
|
||||||
|
startNode = dag.index.LookupNode(startHash)
|
||||||
|
if startNode == nil {
|
||||||
|
return nil, fmt.Errorf("Couldn't find the start hash %s in the dag", startHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
headers := make([]*wire.BlockHeader, 0, startNode.blueScore)
|
||||||
|
queue := NewDownHeap()
|
||||||
|
queue.pushSet(startNode.parents)
|
||||||
|
|
||||||
|
visited := newSet()
|
||||||
|
for i := uint32(0); queue.Len() > 0 && len(headers) < wire.MaxBlockHeadersPerMsg; i++ {
|
||||||
|
var current *blockNode
|
||||||
|
current = queue.pop()
|
||||||
|
if !visited.contains(current) {
|
||||||
|
visited.add(current)
|
||||||
|
headers = append(headers, current.Header())
|
||||||
|
queue.pushSet(current.parents)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headers, nil
|
||||||
|
}
|
||||||
|
|
||||||
// RLock locks the DAG's UTXO set for reading.
|
// RLock locks the DAG's UTXO set for reading.
|
||||||
func (dag *BlockDAG) RLock() {
|
func (dag *BlockDAG) RLock() {
|
||||||
dag.dagLock.RLock()
|
dag.dagLock.RLock()
|
||||||
|
@ -90,6 +90,19 @@ func NewGetCurrentNetCmd() *GetCurrentNetCmd {
|
|||||||
return &GetCurrentNetCmd{}
|
return &GetCurrentNetCmd{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTopHeadersCmd defined the getTopHeaders JSON-RPC command.
|
||||||
|
type GetTopHeadersCmd struct {
|
||||||
|
StartHash *string `json:"startHash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGetTopHeadersCmd returns a new instance which can be used to issue a
|
||||||
|
// getTopHeaders JSON-RPC command.
|
||||||
|
func NewGetTopHeadersCmd(startHash *string) *GetTopHeadersCmd {
|
||||||
|
return &GetTopHeadersCmd{
|
||||||
|
StartHash: startHash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetHeadersCmd defines the getHeaders JSON-RPC command.
|
// GetHeadersCmd defines the getHeaders JSON-RPC command.
|
||||||
//
|
//
|
||||||
// NOTE: This is a btcsuite extension ported from
|
// NOTE: This is a btcsuite extension ported from
|
||||||
@ -134,5 +147,6 @@ func init() {
|
|||||||
MustRegisterCmd("getBestBlock", (*GetBestBlockCmd)(nil), flags)
|
MustRegisterCmd("getBestBlock", (*GetBestBlockCmd)(nil), flags)
|
||||||
MustRegisterCmd("getCurrentNet", (*GetCurrentNetCmd)(nil), flags)
|
MustRegisterCmd("getCurrentNet", (*GetCurrentNetCmd)(nil), flags)
|
||||||
MustRegisterCmd("getHeaders", (*GetHeadersCmd)(nil), flags)
|
MustRegisterCmd("getHeaders", (*GetHeadersCmd)(nil), flags)
|
||||||
|
MustRegisterCmd("getTopHeaders", (*GetTopHeadersCmd)(nil), flags)
|
||||||
MustRegisterCmd("version", (*VersionCmd)(nil), flags)
|
MustRegisterCmd("version", (*VersionCmd)(nil), flags)
|
||||||
}
|
}
|
||||||
|
@ -176,6 +176,34 @@ func TestBtcdExtCmds(t *testing.T) {
|
|||||||
HashStop: "000000000000000000ba33b33e1fad70b69e234fc24414dd47113bff38f523f7",
|
HashStop: "000000000000000000ba33b33e1fad70b69e234fc24414dd47113bff38f523f7",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "getTopHeaders",
|
||||||
|
newCmd: func() (interface{}, error) {
|
||||||
|
return btcjson.NewCmd("getTopHeaders")
|
||||||
|
},
|
||||||
|
staticCmd: func() interface{} {
|
||||||
|
return btcjson.NewGetTopHeadersCmd(
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
marshalled: `{"jsonrpc":"1.0","method":"getTopHeaders","params":[],"id":1}`,
|
||||||
|
unmarshalled: &btcjson.GetTopHeadersCmd{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "getTopHeaders - with start hash",
|
||||||
|
newCmd: func() (interface{}, error) {
|
||||||
|
return btcjson.NewCmd("getTopHeaders", "000000000000000000ba33b33e1fad70b69e234fc24414dd47113bff38f523f7")
|
||||||
|
},
|
||||||
|
staticCmd: func() interface{} {
|
||||||
|
return btcjson.NewGetTopHeadersCmd(
|
||||||
|
btcjson.String("000000000000000000ba33b33e1fad70b69e234fc24414dd47113bff38f523f7"),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
marshalled: `{"jsonrpc":"1.0","method":"getTopHeaders","params":["000000000000000000ba33b33e1fad70b69e234fc24414dd47113bff38f523f7"],"id":1}`,
|
||||||
|
unmarshalled: &btcjson.GetTopHeadersCmd{
|
||||||
|
StartHash: btcjson.String("000000000000000000ba33b33e1fad70b69e234fc24414dd47113bff38f523f7"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "version",
|
name: "version",
|
||||||
newCmd: func() (interface{}, error) {
|
newCmd: func() (interface{}, error) {
|
||||||
|
@ -275,6 +275,24 @@ func (r FutureGetHeadersResult) Receive() ([]wire.BlockHeader, error) {
|
|||||||
return headers, nil
|
return headers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTopHeadersAsync 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 GetTopHeaders for the blocking version and more details.
|
||||||
|
func (c *Client) GetTopHeadersAsync(startHash *daghash.Hash) FutureGetHeadersResult {
|
||||||
|
var hash *string
|
||||||
|
if startHash != nil {
|
||||||
|
hash = btcjson.String(startHash.String())
|
||||||
|
}
|
||||||
|
cmd := btcjson.NewGetTopHeadersCmd(hash)
|
||||||
|
return c.sendCmd(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTopHeaders sends a getTopHeaders rpc command to the server.
|
||||||
|
func (c *Client) GetTopHeaders(startHash *daghash.Hash) ([]wire.BlockHeader, error) {
|
||||||
|
return c.GetTopHeadersAsync(startHash).Receive()
|
||||||
|
}
|
||||||
|
|
||||||
// GetHeadersAsync returns an instance of a type that can be used to get the result
|
// GetHeadersAsync 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.
|
// of the RPC at some future time by invoking the Receive function on the returned instance.
|
||||||
//
|
//
|
||||||
|
@ -161,6 +161,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{
|
|||||||
"getGenerate": handleGetGenerate,
|
"getGenerate": handleGetGenerate,
|
||||||
"getHashesPerSec": handleGetHashesPerSec,
|
"getHashesPerSec": handleGetHashesPerSec,
|
||||||
"getHeaders": handleGetHeaders,
|
"getHeaders": handleGetHeaders,
|
||||||
|
"getTopHeaders": handleGetTopHeaders,
|
||||||
"getInfo": handleGetInfo,
|
"getInfo": handleGetInfo,
|
||||||
"getManualNodeInfo": handleGetManualNodeInfo,
|
"getManualNodeInfo": handleGetManualNodeInfo,
|
||||||
"getMempoolInfo": handleGetMempoolInfo,
|
"getMempoolInfo": handleGetMempoolInfo,
|
||||||
@ -2289,6 +2290,39 @@ func handleGetHashesPerSec(s *Server, cmd interface{}, closeChan <-chan struct{}
|
|||||||
return int64(s.cfg.CPUMiner.HashesPerSecond()), nil
|
return int64(s.cfg.CPUMiner.HashesPerSecond()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleGetTopHeaders implements the getTopHeaders command.
|
||||||
|
func handleGetTopHeaders(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||||
|
c := cmd.(*btcjson.GetTopHeadersCmd)
|
||||||
|
|
||||||
|
var startHash *daghash.Hash
|
||||||
|
if c.StartHash != nil {
|
||||||
|
startHash = &daghash.Hash{}
|
||||||
|
err := daghash.Decode(startHash, *c.StartHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, rpcDecodeHexError(*c.StartHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
headers, err := s.cfg.DAG.GetTopHeaders(startHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, internalRPCError(err.Error(),
|
||||||
|
"Failed to get top headers")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the serialized block headers as hex-encoded strings.
|
||||||
|
hexBlockHeaders := make([]string, len(headers))
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for i, h := range headers {
|
||||||
|
err := h.Serialize(&buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, internalRPCError(err.Error(),
|
||||||
|
"Failed to serialize block header")
|
||||||
|
}
|
||||||
|
hexBlockHeaders[i] = hex.EncodeToString(buf.Bytes())
|
||||||
|
buf.Reset()
|
||||||
|
}
|
||||||
|
return hexBlockHeaders, nil
|
||||||
|
}
|
||||||
|
|
||||||
// handleGetHeaders implements the getHeaders command.
|
// handleGetHeaders implements the getHeaders command.
|
||||||
//
|
//
|
||||||
// NOTE: This is a btcsuite extension originally ported from
|
// NOTE: This is a btcsuite extension originally ported from
|
||||||
|
@ -402,6 +402,11 @@ var helpDescsEnUS = map[string]string{
|
|||||||
"infoWalletResult-relayFee": "The minimum relay fee for non-free transactions in BTC/KB",
|
"infoWalletResult-relayFee": "The minimum relay fee for non-free transactions in BTC/KB",
|
||||||
"infoWalletResult-errors": "Any current errors",
|
"infoWalletResult-errors": "Any current errors",
|
||||||
|
|
||||||
|
// GetTopHeadersCmd help.
|
||||||
|
"getTopHeaders--synopsis": "Returns the top block headers starting with the provided start hash (not inclusive)",
|
||||||
|
"getTopHeaders-startHash": "Block hash to stop including block headers for; if not found, all headers to the latest known block are returned.",
|
||||||
|
"getTopHeaders--result0": "Serialized block headers of all located blocks, limited to some arbitrary maximum number of hashes (currently 2000, which matches the wire protocol headers message, but this is not guaranteed)",
|
||||||
|
|
||||||
// GetHeadersCmd help.
|
// GetHeadersCmd help.
|
||||||
"getHeaders--synopsis": "Returns block headers starting with the first known block hash from the request",
|
"getHeaders--synopsis": "Returns block headers starting with the first known block hash from the request",
|
||||||
"getHeaders-blockLocators": "JSON array of hex-encoded hashes of blocks. Headers are returned starting from the first known hash in this list",
|
"getHeaders-blockLocators": "JSON array of hex-encoded hashes of blocks. Headers are returned starting from the first known hash in this list",
|
||||||
@ -707,6 +712,7 @@ var rpcResultTypes = map[string][]interface{}{
|
|||||||
"getDifficulty": {(*float64)(nil)},
|
"getDifficulty": {(*float64)(nil)},
|
||||||
"getGenerate": {(*bool)(nil)},
|
"getGenerate": {(*bool)(nil)},
|
||||||
"getHashesPerSec": {(*float64)(nil)},
|
"getHashesPerSec": {(*float64)(nil)},
|
||||||
|
"getTopHeaders": {(*[]string)(nil)},
|
||||||
"getHeaders": {(*[]string)(nil)},
|
"getHeaders": {(*[]string)(nil)},
|
||||||
"getInfo": {(*btcjson.InfoDAGResult)(nil)},
|
"getInfo": {(*btcjson.InfoDAGResult)(nil)},
|
||||||
"getManualNodeInfo": {(*string)(nil), (*btcjson.GetManualNodeInfoResult)(nil)},
|
"getManualNodeInfo": {(*string)(nil), (*btcjson.GetManualNodeInfoResult)(nil)},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user