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"
11 "github.com/bytom/wallet"
14 // return best block hash
15 func (a *API) getBestBlockHash() Response {
16 blockHash := map[string]string{"blockHash": a.chain.BestBlockHash().String()}
17 return NewSuccessResponse(blockHash)
20 // return block header by hash
21 func (a *API) getBlockHeaderByHash(strHash string) Response {
23 if err := hash.UnmarshalText([]byte(strHash)); err != nil {
24 log.WithField("error", err).Error("Error occurs when transforming string hash to hash struct")
25 return NewErrorResponse(err)
27 block, err := a.chain.GetBlockByHash(&hash)
29 log.WithField("error", err).Error("Fail to get block by hash")
30 return NewErrorResponse(err)
33 bcBlock := types.MapBlock(block)
34 return NewSuccessResponse(bcBlock.BlockHeader)
37 // BlockTx is the tx struct for getBlock func
39 ID bc.Hash `json:"id"`
40 Version uint64 `json:"version"`
41 Size uint64 `json:"size"`
42 TimeRange uint64 `json:"time_range"`
43 Inputs []*query.AnnotatedInput `json:"inputs"`
44 Outputs []*query.AnnotatedOutput `json:"outputs"`
45 StatusFail bool `json:"status_fail"`
48 // GetBlockReq is used to handle getBlock req
49 type GetBlockReq struct {
50 BlockHeight uint64 `json:"block_height"`
51 BlockHash chainjson.HexBytes `json:"block_hash"`
54 // GetBlockResp is the resp for getBlock api
55 type GetBlockResp struct {
56 Hash *bc.Hash `json:"hash"`
57 Size uint64 `json:"size"`
58 Version uint64 `json:"version"`
59 Height uint64 `json:"height"`
60 PreviousBlockHash *bc.Hash `json:"previous_block_hash"`
61 Timestamp uint64 `json:"timestamp"`
62 Nonce uint64 `json:"nonce"`
63 Bits uint64 `json:"bits"`
64 Difficulty string `json:"difficulty"`
65 TransactionsMerkleRoot *bc.Hash `json:"transaction_merkle_root"`
66 TransactionStatusHash *bc.Hash `json:"transaction_status_hash"`
67 Transactions []*BlockTx `json:"transactions"`
70 // return block by hash
71 func (a *API) getBlock(ins GetBlockReq) Response {
73 block := &types.Block{}
74 if len(ins.BlockHash) == 32 {
76 copy(b32[:], ins.BlockHash)
77 hash := bc.NewHash(b32)
78 block, err = a.chain.GetBlockByHash(&hash)
80 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
83 return NewErrorResponse(err)
86 blockHash := block.Hash()
87 txStatus, err := a.chain.GetTransactionStatus(&blockHash)
88 rawBlock, err := block.MarshalText()
90 return NewErrorResponse(err)
93 resp := &GetBlockResp{
95 Size: uint64(len(rawBlock)),
96 Version: block.Version,
98 PreviousBlockHash: &block.PreviousBlockHash,
99 Timestamp: block.Timestamp,
102 Difficulty: difficulty.CompactToBig(block.Bits).String(),
103 TransactionsMerkleRoot: &block.TransactionsMerkleRoot,
104 TransactionStatusHash: &block.TransactionStatusHash,
105 Transactions: []*BlockTx{},
108 for i, orig := range block.Transactions {
111 Version: orig.Version,
112 Size: orig.SerializedSize,
113 TimeRange: orig.TimeRange,
114 Inputs: []*query.AnnotatedInput{},
115 Outputs: []*query.AnnotatedOutput{},
117 tx.StatusFail, err = txStatus.GetStatus(i)
119 NewSuccessResponse(resp)
122 for i := range orig.Inputs {
123 tx.Inputs = append(tx.Inputs, wallet.BuildAnnotatedInput(orig, uint32(i)))
125 for i := range orig.Outputs {
126 tx.Outputs = append(tx.Outputs, wallet.BuildAnnotatedOutput(orig, i))
128 resp.Transactions = append(resp.Transactions, tx)
130 return NewSuccessResponse(resp)
133 // return block transactions count by hash
134 func (a *API) getBlockTransactionsCountByHash(strHash string) Response {
136 if err := hash.UnmarshalText([]byte(strHash)); err != nil {
137 log.WithField("error", err).Error("Error occurs when transforming string hash to hash struct")
138 return NewErrorResponse(err)
141 legacyBlock, err := a.chain.GetBlockByHash(&hash)
143 log.WithField("error", err).Error("Fail to get block by hash")
144 return NewErrorResponse(err)
147 count := map[string]int{"count": len(legacyBlock.Transactions)}
148 return NewSuccessResponse(count)
151 // return block transactions count by height
152 func (a *API) getBlockTransactionsCountByHeight(height uint64) Response {
153 legacyBlock, err := a.chain.GetBlockByHeight(height)
155 log.WithField("error", err).Error("Fail to get block by hash")
156 return NewErrorResponse(err)
159 count := map[string]int{"count": len(legacyBlock.Transactions)}
160 return NewSuccessResponse(count)
163 // return current block count
164 func (a *API) getBlockCount() Response {
165 blockHeight := map[string]uint64{"block_count": a.chain.Height()}
166 return NewSuccessResponse(blockHeight)