This repository has been archived by the owner on Mar 22, 2024. It is now read-only.
forked from cosmos/cosmos-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
block.go
142 lines (127 loc) · 3.18 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
135
136
137
138
139
140
141
142
package rpc
import (
"fmt"
"net/http"
"strconv"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
)
const (
flagSelect = "select"
)
//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: printBlock,
}
cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
// TODO: change this to false when we can
cmd.Flags().Bool(client.FlagTrustNode, true, "Don't verify proofs for responses")
cmd.Flags().StringSlice(flagSelect, []string{"header", "tx"}, "Fields to return (header|txs|results)")
return cmd
}
func getBlock(ctx context.CoreContext, height *int64) ([]byte, error) {
// get the node
node, err := ctx.GetNode()
if err != nil {
return nil, err
}
// TODO: actually honor the --select flag!
// header -> BlockchainInfo
// header, tx -> Block
// results -> BlockResults
res, err := node.Block(height)
if err != nil {
return nil, err
}
// TODO move maarshalling into cmd/rest functions
// output, err := tmwire.MarshalJSON(res)
output, err := cdc.MarshalJSON(res)
if err != nil {
return nil, err
}
return output, nil
}
// get the current blockchain height
func GetChainHeight(ctx context.CoreContext) (int64, error) {
node, err := ctx.GetNode()
if err != nil {
return -1, err
}
status, err := node.Status()
if err != nil {
return -1, err
}
height := status.SyncInfo.LatestBlockHeight
return height, nil
}
// CMD
func printBlock(cmd *cobra.Command, args []string) error {
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(context.NewCoreContextFromViper(), height)
if err != nil {
return err
}
fmt.Println(string(output))
return nil
}
// REST
// REST handler to get a block
func BlockRequestHandlerFn(ctx context.CoreContext) 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 {
w.WriteHeader(400)
w.Write([]byte("ERROR: Couldn't parse block height. Assumed format is '/block/{height}'."))
return
}
chainHeight, err := GetChainHeight(ctx)
if height > chainHeight {
w.WriteHeader(404)
w.Write([]byte("ERROR: Requested block height is bigger then the chain length."))
return
}
output, err := getBlock(ctx, &height)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
}
}
// REST handler to get the latest block
func LatestBlockRequestHandlerFn(ctx context.CoreContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
height, err := GetChainHeight(ctx)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(err.Error()))
return
}
output, err := getBlock(ctx, &height)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
}
}