/
block.go
134 lines (111 loc) · 3 KB
/
block.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package rpc
import (
"context"
"fmt"
"net/http"
"strconv"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec/legacy"
"github.com/cosmos/cosmos-sdk/types/rest"
)
//BlockCommand returns the verified block data for a given heights
func BlockCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "block [height]",
Short: "Get verified data for a the block at given height",
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
var height *int64
// optional height
if len(args) > 0 {
h, err := strconv.Atoi(args[0])
if err != nil {
return err
}
if h > 0 {
tmp := int64(h)
height = &tmp
}
}
output, err := getBlock(clientCtx, height)
if err != nil {
return err
}
fmt.Println(string(output))
return nil
},
}
cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
return cmd
}
func getBlock(clientCtx client.Context, height *int64) ([]byte, error) {
// get the node
node, err := clientCtx.GetNode()
if err != nil {
return nil, err
}
// header -> BlockchainInfo
// header, tx -> Block
// results -> BlockResults
res, err := node.Block(context.Background(), height)
if err != nil {
return nil, err
}
return legacy.Cdc.MarshalJSON(res)
}
// get the current blockchain height
func GetChainHeight(clientCtx client.Context) (int64, error) {
node, err := clientCtx.GetNode()
if err != nil {
return -1, err
}
status, err := node.Status(context.Background())
if err != nil {
return -1, err
}
height := status.SyncInfo.LatestBlockHeight
return height, nil
}
// REST handler to get a block
func BlockRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
height, err := strconv.ParseInt(vars["height"], 10, 64)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest,
"couldn't parse block height. Assumed format is '/block/{height}'.")
return
}
chainHeight, err := GetChainHeight(clientCtx)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, "failed to parse chain height")
return
}
if height > chainHeight {
rest.WriteErrorResponse(w, http.StatusNotFound, "requested block height is bigger then the chain length")
return
}
output, err := getBlock(clientCtx, &height)
if rest.CheckInternalServerError(w, err) {
return
}
rest.PostProcessResponseBare(w, clientCtx, output)
}
}
// REST handler to get the latest block
func LatestBlockRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
output, err := getBlock(clientCtx, nil)
if rest.CheckInternalServerError(w, err) {
return
}
rest.PostProcessResponseBare(w, clientCtx, output)
}
}