4 log "github.com/sirupsen/logrus"
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 block header by hash
20 func (a *API) getBlockHeaderByHash(strHash string) Response {
22 if err := hash.UnmarshalText([]byte(strHash)); err != nil {
23 log.WithField("error", err).Error("Error occurs when transforming string hash to hash struct")
24 return NewErrorResponse(err)
26 block, err := a.chain.GetBlockByHash(&hash)
28 log.WithField("error", err).Error("Fail to get block by hash")
29 return NewErrorResponse(err)
32 bcBlock := types.MapBlock(block)
33 return NewSuccessResponse(bcBlock.BlockHeader)
36 // BlockTx is the tx struct for getBlock func
38 ID bc.Hash `json:"id"`
39 Version uint64 `json:"version"`
40 Size uint64 `json:"size"`
41 TimeRange uint64 `json:"time_range"`
42 Inputs []*query.AnnotatedInput `json:"inputs"`
43 Outputs []*query.AnnotatedOutput `json:"outputs"`
44 StatusFail bool `json:"status_fail"`
47 // GetBlockReq is used to handle getBlock req
48 type GetBlockReq struct {
49 BlockHeight uint64 `json:"block_height"`
50 BlockHash chainjson.HexBytes `json:"block_hash"`
53 // GetBlockResp is the resp for getBlock api
54 type GetBlockResp struct {
55 Hash *bc.Hash `json:"hash"`
56 Size uint64 `json:"size"`
57 Version uint64 `json:"version"`
58 Height uint64 `json:"height"`
59 PreviousBlockHash *bc.Hash `json:"previous_block_hash"`
60 Timestamp uint64 `json:"timestamp"`
61 Nonce uint64 `json:"nonce"`
62 Bits uint64 `json:"bits"`
63 Difficulty string `json:"difficulty"`
64 TransactionsMerkleRoot *bc.Hash `json:"transaction_merkle_root"`
65 TransactionStatusHash *bc.Hash `json:"transaction_status_hash"`
66 Transactions []*BlockTx `json:"transactions"`
69 // return block by hash
70 func (a *API) getBlock(ins GetBlockReq) Response {
72 block := &types.Block{}
73 if len(ins.BlockHash) == 32 {
75 copy(b32[:], ins.BlockHash)
76 hash := bc.NewHash(b32)
77 block, err = a.chain.GetBlockByHash(&hash)
79 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
82 return NewErrorResponse(err)
85 blockHash := block.Hash()
86 txStatus, err := a.chain.GetTransactionStatus(&blockHash)
87 rawBlock, err := block.MarshalText()
89 return NewErrorResponse(err)
92 resp := &GetBlockResp{
94 Size: uint64(len(rawBlock)),
95 Version: block.Version,
97 PreviousBlockHash: &block.PreviousBlockHash,
98 Timestamp: block.Timestamp,
101 Difficulty: difficulty.CompactToBig(block.Bits).String(),
102 TransactionsMerkleRoot: &block.TransactionsMerkleRoot,
103 TransactionStatusHash: &block.TransactionStatusHash,
104 Transactions: []*BlockTx{},
107 for i, orig := range block.Transactions {
110 Version: orig.Version,
111 Size: orig.SerializedSize,
112 TimeRange: orig.TimeRange,
113 Inputs: []*query.AnnotatedInput{},
114 Outputs: []*query.AnnotatedOutput{},
116 tx.StatusFail, err = txStatus.GetStatus(i)
118 NewSuccessResponse(resp)
121 for i := range orig.Inputs {
122 tx.Inputs = append(tx.Inputs, a.wallet.BuildAnnotatedInput(orig, uint32(i)))
124 for i := range orig.Outputs {
125 tx.Outputs = append(tx.Outputs, a.wallet.BuildAnnotatedOutput(orig, i))
127 resp.Transactions = append(resp.Transactions, tx)
129 return NewSuccessResponse(resp)
132 // return block transactions count by hash
133 func (a *API) getBlockTransactionsCountByHash(strHash string) Response {
135 if err := hash.UnmarshalText([]byte(strHash)); err != nil {
136 log.WithField("error", err).Error("Error occurs when transforming string hash to hash struct")
137 return NewErrorResponse(err)
140 legacyBlock, err := a.chain.GetBlockByHash(&hash)
142 log.WithField("error", err).Error("Fail to get block by hash")
143 return NewErrorResponse(err)
146 count := map[string]int{"count": len(legacyBlock.Transactions)}
147 return NewSuccessResponse(count)
150 // return block transactions count by height
151 func (a *API) getBlockTransactionsCountByHeight(height uint64) Response {
152 legacyBlock, err := a.chain.GetBlockByHeight(height)
154 log.WithField("error", err).Error("Fail to get block by hash")
155 return NewErrorResponse(err)
158 count := map[string]int{"count": len(legacyBlock.Transactions)}
159 return NewSuccessResponse(count)
162 // return current block count
163 func (a *API) getBlockCount() Response {
164 blockHeight := map[string]uint64{"block_count": a.chain.BestBlockHeight()}
165 return NewSuccessResponse(blockHeight)