[rpc blockchain] Add support for mediantime, chainwork to RPC getblock.
This commit is contained in:
parent
b147fe2a5b
commit
daa3137dc4
4 changed files with 72 additions and 25 deletions
|
@ -8,6 +8,7 @@ package blockchain
|
|||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -1373,6 +1374,54 @@ func (b *BlockChain) BlockHashByHeight(blockHeight int32) (*chainhash.Hash, erro
|
|||
return &node.hash, nil
|
||||
}
|
||||
|
||||
// BlockAttributes desribes a Block in relation to others on the main chain.
|
||||
type BlockAttributes struct {
|
||||
Height int32
|
||||
Confirmations int32
|
||||
MedianTime time.Time
|
||||
ChainWork *big.Int
|
||||
PrevHash *chainhash.Hash
|
||||
NextHash *chainhash.Hash
|
||||
}
|
||||
|
||||
// BlockAttributesByHash returns BlockAttributes for the block with the given hash
|
||||
// relative to other blocks in the main chain. A BestState snapshot describing
|
||||
// the main chain is also returned for convenience.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (b *BlockChain) BlockAttributesByHash(hash *chainhash.Hash, prevHash *chainhash.Hash) (
|
||||
attrs *BlockAttributes, best *BestState, err error) {
|
||||
best = b.BestSnapshot()
|
||||
node := b.index.LookupNode(hash)
|
||||
if node == nil || !b.bestChain.Contains(node) {
|
||||
str := fmt.Sprintf("block %s is not in the main chain", hash)
|
||||
return nil, best, errNotInMainChain(str)
|
||||
}
|
||||
|
||||
attrs = &BlockAttributes{
|
||||
Height: node.height,
|
||||
Confirmations: 1 + best.Height - node.height,
|
||||
MedianTime: node.CalcPastMedianTime(),
|
||||
ChainWork: node.workSum,
|
||||
}
|
||||
|
||||
// Populate prev block hash if there is one.
|
||||
if node.height > 0 {
|
||||
attrs.PrevHash = prevHash
|
||||
}
|
||||
|
||||
// Populate next block hash if there is one.
|
||||
if node.height < best.Height {
|
||||
nextHash, err := b.BlockHashByHeight(node.height + 1)
|
||||
if err != nil {
|
||||
return nil, best, err
|
||||
}
|
||||
attrs.NextHash = nextHash
|
||||
}
|
||||
|
||||
return attrs, best, nil
|
||||
}
|
||||
|
||||
// HeightRange returns a range of block hashes for the given start and end
|
||||
// heights. It is inclusive of the start height and exclusive of the end
|
||||
// height. The end height will be limited to the current main chain height.
|
||||
|
|
|
@ -77,9 +77,11 @@ type GetBlockVerboseResultBase struct {
|
|||
VersionHex string `json:"versionHex"`
|
||||
MerkleRoot string `json:"merkleroot"`
|
||||
Time int64 `json:"time"`
|
||||
MedianTime int64 `json:"mediantime"`
|
||||
Nonce uint32 `json:"nonce"`
|
||||
Bits string `json:"bits"`
|
||||
Difficulty float64 `json:"difficulty"`
|
||||
ChainWork string `json:"chainwork"`
|
||||
PreviousHash string `json:"previousblockhash,omitempty"`
|
||||
NextHash string `json:"nextblockhash,omitempty"`
|
||||
|
||||
|
|
44
rpcserver.go
44
rpcserver.go
|
@ -1209,31 +1209,23 @@ func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i
|
|||
return nil, internalRPCError(err.Error(), context)
|
||||
}
|
||||
|
||||
// Get the block height from chain.
|
||||
blockHeight, err := s.cfg.Chain.BlockHeightByHash(hash)
|
||||
if err != nil {
|
||||
context := "Failed to obtain block height"
|
||||
return nil, internalRPCError(err.Error(), context)
|
||||
}
|
||||
blk.SetHeight(blockHeight)
|
||||
best := s.cfg.Chain.BestSnapshot()
|
||||
|
||||
// Get next block hash unless there are none.
|
||||
var nextHashString string
|
||||
if blockHeight < best.Height {
|
||||
nextHash, err := s.cfg.Chain.BlockHashByHeight(blockHeight + 1)
|
||||
if err != nil {
|
||||
context := "No next block"
|
||||
return nil, internalRPCError(err.Error(), context)
|
||||
}
|
||||
nextHashString = nextHash.String()
|
||||
}
|
||||
|
||||
params := s.cfg.ChainParams
|
||||
blockHeader := &blk.MsgBlock().Header
|
||||
|
||||
// Get further details (height, confirmations, nexthash, mediantime, etc.) from chain.
|
||||
attrs, best, err := s.cfg.Chain.BlockAttributesByHash(hash, &blockHeader.PrevBlock)
|
||||
if err != nil {
|
||||
context := "Failed to obtain block details"
|
||||
return nil, internalRPCError(err.Error(), context)
|
||||
}
|
||||
|
||||
var prevHashString string
|
||||
if blockHeight > 0 {
|
||||
prevHashString = blockHeader.PrevBlock.String()
|
||||
if attrs.PrevHash != nil {
|
||||
prevHashString = attrs.PrevHash.String()
|
||||
}
|
||||
var nextHashString string
|
||||
if attrs.NextHash != nil {
|
||||
nextHashString = attrs.NextHash.String()
|
||||
}
|
||||
|
||||
base := btcjson.GetBlockVerboseResultBase{
|
||||
|
@ -1244,13 +1236,15 @@ func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i
|
|||
PreviousHash: prevHashString,
|
||||
Nonce: blockHeader.Nonce,
|
||||
Time: blockHeader.Timestamp.Unix(),
|
||||
Confirmations: int64(1 + best.Height - blockHeight),
|
||||
Height: int64(blockHeight),
|
||||
MedianTime: attrs.MedianTime.Unix(),
|
||||
Confirmations: int64(attrs.Confirmations),
|
||||
Height: int64(attrs.Height),
|
||||
Size: int32(len(blkBytes)),
|
||||
StrippedSize: int32(blk.MsgBlock().SerializeSizeStripped()),
|
||||
Weight: int32(blockchain.GetBlockWeight(blk)),
|
||||
Bits: strconv.FormatInt(int64(blockHeader.Bits), 16),
|
||||
Difficulty: getDifficultyRatio(blockHeader.Bits, params),
|
||||
ChainWork: attrs.ChainWork.Text(16),
|
||||
NextHash: nextHashString,
|
||||
ClaimTrie: blockHeader.ClaimTrie.String(),
|
||||
}
|
||||
|
@ -1275,7 +1269,7 @@ func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i
|
|||
for i, tx := range txns {
|
||||
rawTxn, err := createTxRawResult(params, tx.MsgTx(),
|
||||
tx.Hash().String(), blockHeader, hash.String(),
|
||||
blockHeight, best.Height)
|
||||
attrs.Height, best.Height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -260,9 +260,11 @@ var helpDescsEnUS = map[string]string{
|
|||
"getblockverboseresult-tx": "The transaction hashes (only when verbosity=1)",
|
||||
"getblockverboseresult-nTx": "The number of transactions (aka, count of TX)",
|
||||
"getblockverboseresult-time": "The block time in seconds since 1 Jan 1970 GMT",
|
||||
"getblockverboseresult-mediantime": "The median block time in seconds since 1 Jan 1970 GMT",
|
||||
"getblockverboseresult-nonce": "The block nonce",
|
||||
"getblockverboseresult-bits": "The bits which represent the block difficulty",
|
||||
"getblockverboseresult-difficulty": "The proof-of-work difficulty as a multiple of the minimum difficulty",
|
||||
"getblockverboseresult-chainwork": "Expected number of hashes required to produce the chain up to this block (in hex)",
|
||||
"getblockverboseresult-previousblockhash": "The hash of the previous block",
|
||||
"getblockverboseresult-nextblockhash": "The hash of the next block (only if there is one)",
|
||||
"getblockverboseresult-strippedsize": "The size of the block without witness data",
|
||||
|
|
Loading…
Reference in a new issue