mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-06 06:06:49 +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)
|
||||
|
||||
visited := newSet()
|
||||
for i := uint32(0); queue.Len() > 0 && i < maxEntries; i++ {
|
||||
for queue.Len() > 0 && uint32(len(nodes)) < maxEntries {
|
||||
var current *blockNode
|
||||
current = queue.pop()
|
||||
if !visited.contains(current) {
|
||||
@ -1474,6 +1474,32 @@ func (dag *BlockDAG) locateHeaders(locator BlockLocator, hashStop *daghash.Hash,
|
||||
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.
|
||||
func (dag *BlockDAG) RLock() {
|
||||
dag.dagLock.RLock()
|
||||
|
@ -90,6 +90,19 @@ func NewGetCurrentNetCmd() *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.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
@ -134,5 +147,6 @@ func init() {
|
||||
MustRegisterCmd("getBestBlock", (*GetBestBlockCmd)(nil), flags)
|
||||
MustRegisterCmd("getCurrentNet", (*GetCurrentNetCmd)(nil), flags)
|
||||
MustRegisterCmd("getHeaders", (*GetHeadersCmd)(nil), flags)
|
||||
MustRegisterCmd("getTopHeaders", (*GetTopHeadersCmd)(nil), flags)
|
||||
MustRegisterCmd("version", (*VersionCmd)(nil), flags)
|
||||
}
|
||||
|
@ -176,6 +176,34 @@ func TestBtcdExtCmds(t *testing.T) {
|
||||
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",
|
||||
newCmd: func() (interface{}, error) {
|
||||
|
@ -275,6 +275,24 @@ func (r FutureGetHeadersResult) Receive() ([]wire.BlockHeader, error) {
|
||||
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
|
||||
// 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,
|
||||
"getHashesPerSec": handleGetHashesPerSec,
|
||||
"getHeaders": handleGetHeaders,
|
||||
"getTopHeaders": handleGetTopHeaders,
|
||||
"getInfo": handleGetInfo,
|
||||
"getManualNodeInfo": handleGetManualNodeInfo,
|
||||
"getMempoolInfo": handleGetMempoolInfo,
|
||||
@ -2289,6 +2290,39 @@ func handleGetHashesPerSec(s *Server, cmd interface{}, closeChan <-chan struct{}
|
||||
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.
|
||||
//
|
||||
// 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-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.
|
||||
"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",
|
||||
@ -707,6 +712,7 @@ var rpcResultTypes = map[string][]interface{}{
|
||||
"getDifficulty": {(*float64)(nil)},
|
||||
"getGenerate": {(*bool)(nil)},
|
||||
"getHashesPerSec": {(*float64)(nil)},
|
||||
"getTopHeaders": {(*[]string)(nil)},
|
||||
"getHeaders": {(*[]string)(nil)},
|
||||
"getInfo": {(*btcjson.InfoDAGResult)(nil)},
|
||||
"getManualNodeInfo": {(*string)(nil), (*btcjson.GetManualNodeInfoResult)(nil)},
|
||||
|
Loading…
x
Reference in New Issue
Block a user