github.com/lino-network/lino@v0.6.11/client/blockchain/query.go (about) 1 package blockchain 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "strconv" 7 "strings" 8 "time" 9 10 "github.com/cosmos/cosmos-sdk/client" 11 "github.com/cosmos/cosmos-sdk/client/context" 12 "github.com/cosmos/cosmos-sdk/client/rpc" 13 "github.com/cosmos/cosmos-sdk/codec" 14 sdk "github.com/cosmos/cosmos-sdk/types" 15 txutils "github.com/cosmos/cosmos-sdk/x/auth/client/utils" 16 "github.com/spf13/cobra" 17 tmliteProxy "github.com/tendermint/tendermint/lite/proxy" 18 ctypes "github.com/tendermint/tendermint/rpc/core/types" 19 20 // "github.com/lino-network/lino/utils" 21 22 linotypes "github.com/lino-network/lino/types" 23 ) 24 25 func GetQueryCmd(cdc *codec.Codec) *cobra.Command { 26 cmd := &cobra.Command{ 27 Use: "blockchain", 28 Short: "Blockchain-related Queries", 29 DisableFlagParsing: true, 30 SuggestionsMinimumDistance: 2, 31 RunE: client.ValidateCmd, 32 } 33 cmd.AddCommand( 34 // txutils.QueryTxCmd(cdc), 35 rpc.ValidatorCommand(cdc), 36 rpc.BlockCommand(), 37 ) 38 cmd.AddCommand(client.GetCommands( 39 getCmdTx(cdc), 40 getCmdHeight(cdc), 41 getCmdMessage(cdc), 42 )...) 43 return cmd 44 } 45 46 // GetCmdHeight - 47 func getCmdHeight(cdc *codec.Codec) *cobra.Command { 48 return &cobra.Command{ 49 Use: "height", 50 Short: "height current block height", 51 Args: cobra.ExactArgs(0), 52 RunE: func(cmd *cobra.Command, args []string) error { 53 cliCtx := context.NewCLIContext().WithCodec(cdc) 54 height, err := rpc.GetChainHeight(cliCtx) 55 if err != nil { 56 return err 57 } 58 fmt.Println(height) 59 return nil 60 }, 61 } 62 } 63 64 type MsgPrintLayout struct { 65 Hash string `json:"hash"` 66 Msgs []sdk.Msg `json:"msgs"` 67 } 68 69 // GetCmdBlock - 70 func getCmdMessage(cdc *codec.Codec) *cobra.Command { 71 return &cobra.Command{ 72 Use: "msg", 73 Short: "msg <block-height>, print messages and results of the block height", 74 Args: cobra.MaximumNArgs(1), 75 RunE: func(cmd *cobra.Command, args []string) error { 76 cliCtx := context.NewCLIContext().WithCodec(cdc) 77 var height *int64 78 // optional height 79 if len(args) > 0 { 80 h, err := strconv.Atoi(args[0]) 81 if err != nil { 82 return err 83 } 84 if h > 0 { 85 tmp := int64(h) 86 height = &tmp 87 } 88 } 89 90 // get the node 91 node, err := cliCtx.GetNode() 92 if err != nil { 93 return err 94 } 95 96 // header -> BlockchainInfo 97 // header, tx -> Block 98 // results -> BlockResults 99 res, err := node.Block(height) 100 if err != nil { 101 return err 102 } 103 104 if !cliCtx.TrustNode { 105 check, err := cliCtx.Verify(res.Block.Height) 106 if err != nil { 107 return err 108 } 109 110 err = tmliteProxy.ValidateBlockMeta(res.BlockMeta, check) 111 if err != nil { 112 return err 113 } 114 115 err = tmliteProxy.ValidateBlock(res.Block, check) 116 if err != nil { 117 return err 118 } 119 } 120 121 decoder := linotypes.TxDecoder(cdc) 122 var result []MsgPrintLayout 123 for _, txbytes := range res.Block.Data.Txs { 124 hexstr := hex.EncodeToString(txbytes.Hash()) 125 hexstr = strings.ToUpper(hexstr) 126 tx, err := decoder(txbytes) 127 if err != nil { 128 return err 129 } 130 result = append(result, MsgPrintLayout{ 131 Hash: hexstr, 132 Msgs: tx.GetMsgs(), 133 }) 134 } 135 out, err := cdc.MarshalJSONIndent(result, "", " ") 136 if err != nil { 137 return err 138 } 139 fmt.Println(string(out)) 140 141 return nil 142 }, 143 } 144 } 145 146 // GetCmdTx - 147 func getCmdTx(cdc *codec.Codec) *cobra.Command { 148 return &cobra.Command{ 149 Use: "tx", 150 Short: "tx <hash>", 151 Args: cobra.ExactArgs(1), 152 RunE: func(cmd *cobra.Command, args []string) error { 153 cliCtx := context.NewCLIContext().WithCodec(cdc) 154 hashHexStr := args[0] 155 hash, err := hex.DecodeString(hashHexStr) 156 if err != nil { 157 return err 158 } 159 160 node, err := cliCtx.GetNode() 161 if err != nil { 162 return err 163 } 164 165 resTx, err := node.Tx(hash, !cliCtx.TrustNode) 166 if err != nil { 167 return err 168 } 169 170 if !cliCtx.TrustNode { 171 if err = txutils.ValidateTxResult(cliCtx, resTx); err != nil { 172 return err 173 } 174 } 175 176 _ = printTx(cdc, resTx.Tx) 177 178 resBlocks, err := getBlocksForTxResults(cliCtx, []*ctypes.ResultTx{resTx}) 179 if err != nil { 180 return err 181 } 182 183 out, err := formatTxResult(cliCtx.Codec, resTx, resBlocks[resTx.Height]) 184 if err != nil { 185 return err 186 } 187 188 fmt.Println(out) 189 return nil 190 }, 191 } 192 } 193 194 func getBlocksForTxResults(cliCtx context.CLIContext, resTxs []*ctypes.ResultTx) (map[int64]*ctypes.ResultBlock, error) { 195 node, err := cliCtx.GetNode() 196 if err != nil { 197 return nil, err 198 } 199 200 resBlocks := make(map[int64]*ctypes.ResultBlock) 201 202 for _, resTx := range resTxs { 203 if _, ok := resBlocks[resTx.Height]; !ok { 204 resBlock, err := node.Block(&resTx.Height) 205 if err != nil { 206 return nil, err 207 } 208 209 resBlocks[resTx.Height] = resBlock 210 } 211 } 212 213 return resBlocks, nil 214 } 215 216 func formatTxResult(cdc *codec.Codec, resTx *ctypes.ResultTx, resBlock *ctypes.ResultBlock) (sdk.TxResponse, error) { 217 tx, err := parseTx(linotypes.TxDecoder(cdc), resTx.Tx) 218 if err != nil { 219 return sdk.TxResponse{}, err 220 } 221 222 return sdk.NewResponseResultTx(resTx, tx, resBlock.Block.Time.Format(time.RFC3339)), nil 223 } 224 225 func parseTx(decoder sdk.TxDecoder, txBytes []byte) (sdk.Tx, error) { 226 tx, err := decoder(txBytes) 227 if err != nil { 228 return nil, err 229 } 230 231 return tx, nil 232 } 233 234 func printTx(cdc *codec.Codec, txBytes []byte) error { 235 decoder := linotypes.TxDecoder(cdc) 236 msg, err := decoder(txBytes) 237 if err != nil { 238 return err 239 } 240 out, err2 := cdc.MarshalJSONIndent(msg, "", " ") 241 if err2 != nil { 242 return err 243 } 244 fmt.Println(string(out)) 245 return nil 246 }