OSDN Git Service

edit the req name
[bytom/bytom.git] / api / block_retrieve.go
1 package api
2
3 import (
4         "github.com/bytom/blockchain/query"
5         "github.com/bytom/consensus/difficulty"
6         chainjson "github.com/bytom/encoding/json"
7         "github.com/bytom/protocol/bc"
8         "github.com/bytom/protocol/bc/types"
9 )
10
11 // return best block hash
12 func (a *API) getBestBlockHash() Response {
13         blockHash := map[string]string{"block_hash": a.chain.BestBlockHash().String()}
14         return NewSuccessResponse(blockHash)
15 }
16
17 // return current block count
18 func (a *API) getBlockCount() Response {
19         blockHeight := map[string]uint64{"block_count": a.chain.BestBlockHeight()}
20         return NewSuccessResponse(blockHeight)
21 }
22
23 // BlockTx is the tx struct for getBlock func
24 type BlockTx struct {
25         ID         bc.Hash                  `json:"id"`
26         Version    uint64                   `json:"version"`
27         Size       uint64                   `json:"size"`
28         TimeRange  uint64                   `json:"time_range"`
29         Inputs     []*query.AnnotatedInput  `json:"inputs"`
30         Outputs    []*query.AnnotatedOutput `json:"outputs"`
31         StatusFail bool                     `json:"status_fail"`
32 }
33
34 // BlockReq is used to handle getBlock req
35 type BlockReq struct {
36         BlockHeight uint64             `json:"block_height"`
37         BlockHash   chainjson.HexBytes `json:"block_hash"`
38 }
39
40 // GetBlockResp is the resp for getBlock api
41 type GetBlockResp struct {
42         Hash                   *bc.Hash   `json:"hash"`
43         Size                   uint64     `json:"size"`
44         Version                uint64     `json:"version"`
45         Height                 uint64     `json:"height"`
46         PreviousBlockHash      *bc.Hash   `json:"previous_block_hash"`
47         Timestamp              uint64     `json:"timestamp"`
48         Nonce                  uint64     `json:"nonce"`
49         Bits                   uint64     `json:"bits"`
50         Difficulty             string     `json:"difficulty"`
51         TransactionsMerkleRoot *bc.Hash   `json:"transaction_merkle_root"`
52         TransactionStatusHash  *bc.Hash   `json:"transaction_status_hash"`
53         Transactions           []*BlockTx `json:"transactions"`
54 }
55
56 // return block by hash
57 func (a *API) getBlock(ins BlockReq) Response {
58         var err error
59         block := &types.Block{}
60         if len(ins.BlockHash) == 32 {
61                 b32 := [32]byte{}
62                 copy(b32[:], ins.BlockHash)
63                 hash := bc.NewHash(b32)
64                 block, err = a.chain.GetBlockByHash(&hash)
65         } else {
66                 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
67         }
68         if err != nil {
69                 return NewErrorResponse(err)
70         }
71
72         blockHash := block.Hash()
73         txStatus, err := a.chain.GetTransactionStatus(&blockHash)
74         rawBlock, err := block.MarshalText()
75         if err != nil {
76                 return NewErrorResponse(err)
77         }
78
79         resp := &GetBlockResp{
80                 Hash:                   &blockHash,
81                 Size:                   uint64(len(rawBlock)),
82                 Version:                block.Version,
83                 Height:                 block.Height,
84                 PreviousBlockHash:      &block.PreviousBlockHash,
85                 Timestamp:              block.Timestamp,
86                 Nonce:                  block.Nonce,
87                 Bits:                   block.Bits,
88                 Difficulty:             difficulty.CompactToBig(block.Bits).String(),
89                 TransactionsMerkleRoot: &block.TransactionsMerkleRoot,
90                 TransactionStatusHash:  &block.TransactionStatusHash,
91                 Transactions:           []*BlockTx{},
92         }
93
94         for i, orig := range block.Transactions {
95                 tx := &BlockTx{
96                         ID:        orig.ID,
97                         Version:   orig.Version,
98                         Size:      orig.SerializedSize,
99                         TimeRange: orig.TimeRange,
100                         Inputs:    []*query.AnnotatedInput{},
101                         Outputs:   []*query.AnnotatedOutput{},
102                 }
103                 tx.StatusFail, err = txStatus.GetStatus(i)
104                 if err != nil {
105                         NewSuccessResponse(resp)
106                 }
107
108                 for i := range orig.Inputs {
109                         tx.Inputs = append(tx.Inputs, a.wallet.BuildAnnotatedInput(orig, uint32(i)))
110                 }
111                 for i := range orig.Outputs {
112                         tx.Outputs = append(tx.Outputs, a.wallet.BuildAnnotatedOutput(orig, i))
113                 }
114                 resp.Transactions = append(resp.Transactions, tx)
115         }
116         return NewSuccessResponse(resp)
117 }
118
119 // GetBlockHeaderResp is resp struct for getBlockHeader API
120 type GetBlockHeaderResp struct {
121         BlockHeader *types.BlockHeader `json:"block_header"`
122         Reward      uint64             `json:"reward"`
123 }
124
125 func (a *API) getBlockHeader(ins BlockReq) Response {
126         var err error
127         block := &types.Block{}
128         if len(ins.BlockHash) == 32 {
129                 b32 := [32]byte{}
130                 copy(b32[:], ins.BlockHash)
131                 hash := bc.NewHash(b32)
132                 block, err = a.chain.GetBlockByHash(&hash)
133         } else {
134                 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
135         }
136         if err != nil {
137                 return NewErrorResponse(err)
138         }
139
140         resp := &GetBlockHeaderResp{
141                 BlockHeader: &block.BlockHeader,
142                 Reward:      block.Transactions[0].Outputs[0].Amount,
143         }
144         return NewSuccessResponse(resp)
145 }