package rpc import ( "bytes" "encoding/hex" "fmt" "github.com/kaspanet/kaspad/rpc/model" "github.com/kaspanet/kaspad/util/daghash" "strconv" ) // handleGetBlockHeader implements the getBlockHeader command. func handleGetBlockHeader(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { c := cmd.(*model.GetBlockHeaderCmd) // Fetch the header from DAG. hash, err := daghash.NewHashFromStr(c.Hash) if err != nil { return nil, rpcDecodeHexError(c.Hash) } blockHeader, err := s.dag.HeaderByHash(hash) if err != nil { return nil, &model.RPCError{ Code: model.ErrRPCBlockNotFound, Message: "Block not found", } } // When the verbose flag isn't set, simply return the serialized block // header as a hex-encoded string. if c.Verbose != nil && !*c.Verbose { var headerBuf bytes.Buffer err := blockHeader.Serialize(&headerBuf) if err != nil { context := "Failed to serialize block header" return nil, internalRPCError(err.Error(), context) } return hex.EncodeToString(headerBuf.Bytes()), nil } // The verbose flag is set, so generate the JSON object and return it. // Get the hashes for the next blocks unless there are none. childHashes, err := s.dag.ChildHashesByHash(hash) if err != nil { context := "No next block" return nil, internalRPCError(err.Error(), context) } childHashStrings := daghash.Strings(childHashes) blockConfirmations, err := s.dag.BlockConfirmationsByHash(hash) if err != nil { context := "Could not get block confirmations" return nil, internalRPCError(err.Error(), context) } selectedParentHash, err := s.dag.SelectedParentHash(hash) if err != nil { context := "Could not get block selected parent" return nil, internalRPCError(err.Error(), context) } params := s.dag.Params blockHeaderReply := model.GetBlockHeaderVerboseResult{ Hash: c.Hash, Confirmations: blockConfirmations, Version: blockHeader.Version, VersionHex: fmt.Sprintf("%08x", blockHeader.Version), HashMerkleRoot: blockHeader.HashMerkleRoot.String(), AcceptedIDMerkleRoot: blockHeader.AcceptedIDMerkleRoot.String(), ChildHashes: childHashStrings, ParentHashes: daghash.Strings(blockHeader.ParentHashes), SelectedParentHash: selectedParentHash.String(), Nonce: blockHeader.Nonce, Time: blockHeader.Timestamp.UnixMilliseconds(), Bits: strconv.FormatInt(int64(blockHeader.Bits), 16), Difficulty: getDifficultyRatio(blockHeader.Bits, params), } return blockHeaderReply, nil }