6 "github.com/bytom/blockchain/query"
7 "github.com/bytom/consensus/difficulty"
8 chainjson "github.com/bytom/encoding/json"
9 "github.com/bytom/protocol/bc"
10 "github.com/bytom/protocol/bc/types"
13 // return best block hash
14 func (a *API) getBestBlockHash() Response {
15 blockHash := map[string]string{"block_hash": a.chain.BestBlockHash().String()}
16 return NewSuccessResponse(blockHash)
19 // return current block count
20 func (a *API) getBlockCount() Response {
21 blockHeight := map[string]uint64{"block_count": a.chain.BestBlockHeight()}
22 return NewSuccessResponse(blockHeight)
25 // BlockTx is the tx struct for getBlock func
27 ID bc.Hash `json:"id"`
28 Version uint64 `json:"version"`
29 Size uint64 `json:"size"`
30 TimeRange uint64 `json:"time_range"`
31 Inputs []*query.AnnotatedInput `json:"inputs"`
32 Outputs []*query.AnnotatedOutput `json:"outputs"`
33 StatusFail bool `json:"status_fail"`
34 MuxID bc.Hash `json:"mux_id"`
37 // BlockReq is used to handle getBlock req
38 type BlockReq struct {
39 BlockHeight uint64 `json:"block_height"`
40 BlockHash chainjson.HexBytes `json:"block_hash"`
43 // GetBlockResp is the resp for getBlock api
44 type GetBlockResp struct {
45 Hash *bc.Hash `json:"hash"`
46 Size uint64 `json:"size"`
47 Version uint64 `json:"version"`
48 Height uint64 `json:"height"`
49 PreviousBlockHash *bc.Hash `json:"previous_block_hash"`
50 Timestamp uint64 `json:"timestamp"`
51 Nonce uint64 `json:"nonce"`
52 Bits uint64 `json:"bits"`
53 Difficulty string `json:"difficulty"`
54 TransactionsMerkleRoot *bc.Hash `json:"transaction_merkle_root"`
55 TransactionStatusHash *bc.Hash `json:"transaction_status_hash"`
56 Transactions []*BlockTx `json:"transactions"`
59 // return block by hash
60 func (a *API) getBlock(ins BlockReq) Response {
62 block := &types.Block{}
63 if len(ins.BlockHash) == 32 {
65 copy(b32[:], ins.BlockHash)
66 hash := bc.NewHash(b32)
67 block, err = a.chain.GetBlockByHash(&hash)
69 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
72 return NewErrorResponse(err)
75 blockHash := block.Hash()
76 txStatus, err := a.chain.GetTransactionStatus(&blockHash)
77 rawBlock, err := block.MarshalText()
79 return NewErrorResponse(err)
82 resp := &GetBlockResp{
84 Size: uint64(len(rawBlock)),
85 Version: block.Version,
87 PreviousBlockHash: &block.PreviousBlockHash,
88 Timestamp: block.Timestamp,
91 Difficulty: difficulty.CalcWork(block.Bits).String(),
92 TransactionsMerkleRoot: &block.TransactionsMerkleRoot,
93 TransactionStatusHash: &block.TransactionStatusHash,
94 Transactions: []*BlockTx{},
97 for i, orig := range block.Transactions {
100 Version: orig.Version,
101 Size: orig.SerializedSize,
102 TimeRange: orig.TimeRange,
103 Inputs: []*query.AnnotatedInput{},
104 Outputs: []*query.AnnotatedOutput{},
106 tx.StatusFail, err = txStatus.GetStatus(i)
108 NewSuccessResponse(resp)
111 resOutID := orig.ResultIds[0]
112 resOut, ok := orig.Entries[*resOutID].(*bc.Output)
114 tx.MuxID = *resOut.Source.Ref
116 resRetire, _ := orig.Entries[*resOutID].(*bc.Retirement)
117 tx.MuxID = *resRetire.Source.Ref
120 for i := range orig.Inputs {
121 tx.Inputs = append(tx.Inputs, a.wallet.BuildAnnotatedInput(orig, uint32(i)))
123 for i := range orig.Outputs {
124 tx.Outputs = append(tx.Outputs, a.wallet.BuildAnnotatedOutput(orig, i))
126 resp.Transactions = append(resp.Transactions, tx)
128 return NewSuccessResponse(resp)
131 // GetBlockHeaderResp is resp struct for getBlockHeader API
132 type GetBlockHeaderResp struct {
133 BlockHeader *types.BlockHeader `json:"block_header"`
134 Reward uint64 `json:"reward"`
137 func (a *API) getBlockHeader(ins BlockReq) Response {
139 block := &types.Block{}
140 if len(ins.BlockHash) == 32 {
142 copy(b32[:], ins.BlockHash)
143 hash := bc.NewHash(b32)
144 block, err = a.chain.GetBlockByHash(&hash)
146 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
149 return NewErrorResponse(err)
152 resp := &GetBlockHeaderResp{
153 BlockHeader: &block.BlockHeader,
154 Reward: block.Transactions[0].Outputs[0].Amount,
156 return NewSuccessResponse(resp)
159 // GetDifficultyResp is resp struct for getDifficulty API
160 type GetDifficultyResp struct {
161 BlockHash *bc.Hash `json:"hash"`
162 BlockHeight uint64 `json:"height"`
163 Bits uint64 `json:"bits"`
164 Difficulty string `json:"difficulty"`
167 func (a *API) getDifficulty(ins *BlockReq) Response {
169 block := &types.Block{}
171 if len(ins.BlockHash) == 32 && ins.BlockHash != nil {
173 copy(b32[:], ins.BlockHash)
174 hash := bc.NewHash(b32)
175 block, err = a.chain.GetBlockByHash(&hash)
176 } else if ins.BlockHeight > 0 {
177 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
179 hash := a.chain.BestBlockHash()
180 block, err = a.chain.GetBlockByHash(hash)
184 return NewErrorResponse(err)
187 blockHash := block.Hash()
188 resp := &GetDifficultyResp{
189 BlockHash: &blockHash,
190 BlockHeight: block.Height,
192 Difficulty: difficulty.CalcWork(block.Bits).String(),
194 return NewSuccessResponse(resp)
197 // getHashRateResp is resp struct for getHashRate API
198 type getHashRateResp struct {
199 BlockHash *bc.Hash `json:"hash"`
200 BlockHeight uint64 `json:"height"`
201 HashRate uint64 `json:"hash_rate"`
204 func (a *API) getHashRate(ins BlockReq) Response {
206 block := &types.Block{}
208 if len(ins.BlockHash) == 32 && ins.BlockHash != nil {
210 copy(b32[:], ins.BlockHash)
211 hash := bc.NewHash(b32)
212 block, err = a.chain.GetBlockByHash(&hash)
213 } else if ins.BlockHeight > 0 {
214 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
216 hash := a.chain.BestBlockHash()
217 block, err = a.chain.GetBlockByHash(hash)
221 return NewErrorResponse(err)
224 preBlock, err := a.chain.GetBlockByHash(&block.PreviousBlockHash)
226 return NewErrorResponse(err)
229 diffTime := block.Timestamp - preBlock.Timestamp
230 hashCount := difficulty.CalcWork(block.Bits)
231 hashRate := new(big.Int).Div(hashCount, big.NewInt(int64(diffTime)))
233 blockHash := block.Hash()
234 resp := &getHashRateResp{
235 BlockHash: &blockHash,
236 BlockHeight: block.Height,
237 HashRate: hashRate.Uint64(),
239 return NewSuccessResponse(resp)