4 log "github.com/sirupsen/logrus"
6 "github.com/bytom/blockchain/query"
7 "github.com/bytom/wallet"
8 "github.com/bytom/consensus/difficulty"
9 chainjson "github.com/bytom/encoding/json"
10 "github.com/bytom/protocol/bc"
11 "github.com/bytom/protocol/bc/types"
15 // return best block hash
16 func (a *API) getBestBlockHash() Response {
17 blockHash := map[string]string{"blockHash": a.chain.BestBlockHash().String()}
18 return NewSuccessResponse(blockHash)
21 // return block header by hash
22 func (a *API) getBlockHeaderByHash(strHash string) Response {
24 if err := hash.UnmarshalText([]byte(strHash)); err != nil {
25 log.WithField("error", err).Error("Error occurs when transforming string hash to hash struct")
26 return NewErrorResponse(err)
28 block, err := a.chain.GetBlockByHash(&hash)
30 log.WithField("error", err).Error("Fail to get block by hash")
31 return NewErrorResponse(err)
34 bcBlock := types.MapBlock(block)
35 return NewSuccessResponse(bcBlock.BlockHeader)
38 // BlockTx is the tx struct for getBlock func
40 ID bc.Hash `json:"id"`
41 Version uint64 `json:"version"`
42 Size uint64 `json:"size"`
43 TimeRange uint64 `json:"time_range"`
44 Inputs []*query.AnnotatedInput `json:"inputs"`
45 Outputs []*query.AnnotatedOutput `json:"outputs"`
46 StatusFail bool `json:"status_fail"`
49 // GetBlockReq is used to handle getBlock req
50 type GetBlockReq struct {
51 BlockHeight uint64 `json:"block_height"`
52 BlockHash chainjson.HexBytes `json:"block_hash"`
55 // GetBlockResp is the resp for getBlock api
56 type GetBlockResp struct {
57 Hash *bc.Hash `json:"hash"`
58 Size uint64 `json:"size"`
59 Version uint64 `json:"version"`
60 Height uint64 `json:"height"`
61 PreviousBlockHash *bc.Hash `json:"previous_block_hash"`
62 Timestamp uint64 `json:"timestamp"`
63 Nonce uint64 `json:"nonce"`
64 Bits uint64 `json:"bits"`
65 Difficulty string `json:"difficulty"`
66 TransactionsMerkleRoot *bc.Hash `json:"transaction_merkle_root"`
67 TransactionStatusHash *bc.Hash `json:"transaction_status_hash"`
68 Transactions []*BlockTx `json:"transactions"`
71 // return block by hash
72 func (a *API) getBlock(ins GetBlockReq) Response {
74 block := &types.Block{}
75 if len(ins.BlockHash) == 32 {
77 copy(b32[:], ins.BlockHash)
78 hash := bc.NewHash(b32)
79 block, err = a.chain.GetBlockByHash(&hash)
81 block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
84 return NewErrorResponse(err)
87 blockHash := block.Hash()
88 txStatus, err := a.chain.GetTransactionStatus(&blockHash)
89 rawBlock, err := block.MarshalText()
91 return NewErrorResponse(err)
94 resp := &GetBlockResp{
96 Size: uint64(len(rawBlock)),
97 Version: block.Version,
99 PreviousBlockHash: &block.PreviousBlockHash,
100 Timestamp: block.Timestamp,
103 Difficulty: difficulty.CompactToBig(block.Bits).String(),
104 TransactionsMerkleRoot: &block.TransactionsMerkleRoot,
105 TransactionStatusHash: &block.TransactionStatusHash,
106 Transactions: []*BlockTx{},
109 for i, orig := range block.Transactions {
112 Version: orig.Version,
113 Size: orig.SerializedSize,
114 TimeRange: orig.TimeRange,
115 Inputs: []*query.AnnotatedInput{},
116 Outputs: []*query.AnnotatedOutput{},
118 tx.StatusFail, err = txStatus.GetStatus(i)
120 NewSuccessResponse(resp)
123 for i := range orig.Inputs {
124 tx.Inputs = append(tx.Inputs, wallet.BuildAnnotatedInput(orig, uint32(i)))
126 for i := range orig.Outputs {
127 tx.Outputs = append(tx.Outputs, wallet.BuildAnnotatedOutput(orig, i))
129 resp.Transactions = append(resp.Transactions, tx)
131 return NewSuccessResponse(resp)
134 // return block transactions count by hash
135 func (a *API) getBlockTransactionsCountByHash(strHash string) Response {
137 if err := hash.UnmarshalText([]byte(strHash)); err != nil {
138 log.WithField("error", err).Error("Error occurs when transforming string hash to hash struct")
139 return NewErrorResponse(err)
142 legacyBlock, err := a.chain.GetBlockByHash(&hash)
144 log.WithField("error", err).Error("Fail to get block by hash")
145 return NewErrorResponse(err)
148 count := map[string]int{"count": len(legacyBlock.Transactions)}
149 return NewSuccessResponse(count)
152 // return block transactions count by height
153 func (a *API) getBlockTransactionsCountByHeight(height uint64) Response {
154 legacyBlock, err := a.chain.GetBlockByHeight(height)
156 log.WithField("error", err).Error("Fail to get block by hash")
157 return NewErrorResponse(err)
160 count := map[string]int{"count": len(legacyBlock.Transactions)}
161 return NewSuccessResponse(count)
164 // return current block count
165 func (a *API) getBlockCount() Response {
166 blockHeight := map[string]uint64{"block_count": a.chain.Height()}
167 return NewSuccessResponse(blockHeight)