-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add rest framework * add rest endpoints for ibc connection * add rest endpoints for ibc client * add rest endpoints for ibc channel * modify ibc rest api * add rest endpoints for ibc transfer * fix query route * fix receive packet * fix query client state api * use sub module name instead of icsxx * use const for prove judgement * modify ibc rest api * add api docs to swagger * add ibc config * fix proof path in swagger * return query result proof * update swagger docs * parse prove * clean up * fix ibc rest api and swagger docs * fix host validate * fix typo * add submitMisbehaviour error response in swagger * fix rest queryRoot and swagger doc * add response comments for each REST functions * fix rest function comments
- Loading branch information
1 parent
7c987fe
commit 321463f
Showing
26 changed files
with
2,985 additions
and
34 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
package rest | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"strconv" | ||
|
||
"github.com/gorilla/mux" | ||
abci "github.com/tendermint/tendermint/abci/types" | ||
tmtypes "github.com/tendermint/tendermint/types" | ||
|
||
"github.com/cosmos/cosmos-sdk/client/context" | ||
"github.com/cosmos/cosmos-sdk/types/rest" | ||
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/client/utils" | ||
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" | ||
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint" | ||
commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" | ||
) | ||
|
||
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, queryRoute string) { | ||
r.HandleFunc(fmt.Sprintf("/ibc/clients/{%s}/consensus-state", RestClientID), queryConsensusStateHandlerFn(cliCtx, queryRoute)).Methods("GET") | ||
r.HandleFunc(fmt.Sprintf("/ibc/clients/{%s}/client-state", RestClientID), queryClientStateHandlerFn(cliCtx, queryRoute)).Methods("GET") | ||
r.HandleFunc(fmt.Sprintf("/ibc/clients/{%s}/roots/{%s}", RestClientID, RestRootHeight), queryRootHandlerFn(cliCtx, queryRoute)).Methods("GET") | ||
r.HandleFunc("/ibc/header", queryHeaderHandlerFn(cliCtx)).Methods("GET") | ||
r.HandleFunc("/ibc/node-state", queryNodeConsensusStateHandlerFn(cliCtx)).Methods("GET") | ||
r.HandleFunc("/ibc/path", queryPathHandlerFn(cliCtx)).Methods("GET") | ||
} | ||
|
||
// queryConsensusStateHandlerFn implements a consensus state querying route | ||
// | ||
// @Summary Query cliet consensus-state | ||
// @Tags IBC | ||
// @Produce json | ||
// @Param client-id path string true "Client ID" | ||
// @Param prove query boolean false "Proof of result" | ||
// @Success 200 {object} QueryConsensusState "OK" | ||
// @Failure 400 {object} rest.ErrorResponse "Invalid client id" | ||
// @Failure 500 {object} rest.ErrorResponse "Internal Server Error" | ||
// @Router /ibc/clients/{client-id}/consensus-state [get] | ||
func queryConsensusStateHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
vars := mux.Vars(r) | ||
clientID := vars[RestClientID] | ||
|
||
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) | ||
if !ok { | ||
return | ||
} | ||
|
||
req := abci.RequestQuery{ | ||
Path: "store/ibc/key", | ||
Data: types.KeyConsensusState(clientID), | ||
Prove: rest.ParseQueryProve(r), | ||
} | ||
|
||
res, err := cliCtx.QueryABCI(req) | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
var cs tendermint.ConsensusState | ||
if err := cliCtx.Codec.UnmarshalBinaryLengthPrefixed(res.Value, &cs); err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
} | ||
|
||
cliCtx = cliCtx.WithHeight(res.Height) | ||
rest.PostProcessResponse(w, cliCtx, types.NewConsensusStateResponse(clientID, cs, res.Proof, res.Height)) | ||
} | ||
} | ||
|
||
// queryHeaderHandlerFn implements a header querying route | ||
// | ||
// @Summary Query header | ||
// @Tags IBC | ||
// @Produce json | ||
// @Success 200 {object} QueryHeader "OK" | ||
// @Failure 500 {object} rest.ErrorResponse "Internal Server Error" | ||
// @Router /ibc/header [get] | ||
func queryHeaderHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
header, err := utils.GetTendermintHeader(cliCtx) | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
rest.PostProcessResponse(w, cliCtx, header) | ||
} | ||
} | ||
|
||
// queryClientStateHandlerFn implements a client state querying route | ||
// | ||
// @Summary Query client state | ||
// @Tags IBC | ||
// @Produce json | ||
// @Param client-id path string true "Client ID" | ||
// @Param prove query boolean false "Proof of result" | ||
// @Success 200 {object} QueryClientState "OK" | ||
// @Failure 400 {object} rest.ErrorResponse "Invalid client id" | ||
// @Failure 500 {object} rest.ErrorResponse "Internal Server Error" | ||
// @Router /ibc/clients/{client-id}/client-state [get] | ||
func queryClientStateHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
vars := mux.Vars(r) | ||
clientID := vars[RestClientID] | ||
|
||
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) | ||
if !ok { | ||
return | ||
} | ||
|
||
req := abci.RequestQuery{ | ||
Path: "store/ibc/key", | ||
Data: types.KeyClientState(clientID), | ||
Prove: rest.ParseQueryProve(r), | ||
} | ||
|
||
res, err := cliCtx.QueryABCI(req) | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
var state types.State | ||
if err := cliCtx.Codec.UnmarshalBinaryLengthPrefixed(res.Value, &state); err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
} | ||
|
||
cliCtx = cliCtx.WithHeight(res.Height) | ||
rest.PostProcessResponse(w, cliCtx, types.NewClientStateResponse(clientID, state, res.Proof, res.Height)) | ||
} | ||
} | ||
|
||
// queryRootHandlerFn implements a root querying route | ||
// | ||
// @Summary Query client root | ||
// @Tags IBC | ||
// @Produce json | ||
// @Param client-id path string true "Client ID" | ||
// @Param height path number true "Root height" | ||
// @Success 200 {object} QueryRoot "OK" | ||
// @Failure 400 {object} rest.ErrorResponse "Invalid client id or height" | ||
// @Failure 500 {object} rest.ErrorResponse "Internal Server Error" | ||
// @Router /ibc/clients/{client-id}/roots/{height} [get] | ||
func queryRootHandlerFn(cliCtx context.CLIContext, queryRoute string) http.HandlerFunc { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
vars := mux.Vars(r) | ||
clientID := vars[RestClientID] | ||
height, err := strconv.ParseUint(vars[RestRootHeight], 10, 64) | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) | ||
return | ||
} | ||
|
||
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) | ||
if !ok { | ||
return | ||
} | ||
|
||
req := abci.RequestQuery{ | ||
Path: "store/ibc/key", | ||
Data: types.KeyRoot(clientID, height), | ||
Prove: rest.ParseQueryProve(r), | ||
} | ||
|
||
res, err := cliCtx.QueryABCI(req) | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
var root commitment.Root | ||
if err := cliCtx.Codec.UnmarshalJSON(res.Value, &root); err != nil { | ||
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) | ||
return | ||
} | ||
|
||
cliCtx = cliCtx.WithHeight(res.Height) | ||
rest.PostProcessResponse(w, cliCtx, types.NewRootResponse(clientID, height, root, res.Proof, res.Height)) | ||
} | ||
} | ||
|
||
// queryNodeConsensusStateHandlerFn implements a node consensus state querying route | ||
// | ||
// @Summary Query node consensus-state | ||
// @Tags IBC | ||
// @Produce json | ||
// @Success 200 {object} QueryNodeConsensusState "OK" | ||
// @Failure 500 {object} rest.ErrorResponse "Internal Server Error" | ||
// @Router /ibc/node-state [get] | ||
func queryNodeConsensusStateHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
node, err := cliCtx.GetNode() | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
info, err := node.ABCIInfo() | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
height := info.Response.LastBlockHeight | ||
prevHeight := height - 1 | ||
|
||
commit, err := node.Commit(&height) | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
validators, err := node.Validators(&prevHeight) | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
state := tendermint.ConsensusState{ | ||
ChainID: commit.ChainID, | ||
Height: uint64(commit.Height), | ||
Root: commitment.NewRoot(commit.AppHash), | ||
NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), | ||
} | ||
|
||
res := cliCtx.Codec.MustMarshalJSON(state) | ||
cliCtx = cliCtx.WithHeight(height) | ||
rest.PostProcessResponse(w, cliCtx, res) | ||
} | ||
} | ||
|
||
// queryPathHandlerFn implements a node consensus path querying route | ||
// | ||
// @Summary Query IBC path | ||
// @Tags IBC | ||
// @Produce json | ||
// @Success 200 {object} QueryPath "OK" | ||
// @Failure 500 {object} rest.ErrorResponse "Internal Server Error" | ||
// @Router /ibc/path [get] | ||
func queryPathHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
path := commitment.NewPrefix([]byte("ibc")) | ||
res := cliCtx.Codec.MustMarshalJSON(path) | ||
rest.PostProcessResponse(w, cliCtx, res) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package rest | ||
|
||
import ( | ||
"github.com/gorilla/mux" | ||
|
||
"github.com/cosmos/cosmos-sdk/client/context" | ||
"github.com/cosmos/cosmos-sdk/types/rest" | ||
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" | ||
) | ||
|
||
const ( | ||
RestClientID = "client-id" | ||
RestRootHeight = "height" | ||
) | ||
|
||
// RegisterRoutes - Central function to define routes that get registered by the main application | ||
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, queryRoute string) { | ||
registerQueryRoutes(cliCtx, r, queryRoute) | ||
registerTxRoutes(cliCtx, r) | ||
} | ||
|
||
// CreateClientReq defines the properties of a create client request's body. | ||
type CreateClientReq struct { | ||
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` | ||
ClientID string `json:"client_id" yaml:"client_id"` | ||
ConsensusState exported.ConsensusState `json:"consensus_state" yaml:"consensus_state"` | ||
} | ||
|
||
// UpdateClientReq defines the properties of a update client request's body. | ||
type UpdateClientReq struct { | ||
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` | ||
Header exported.Header `json:"header" yaml:"header"` | ||
} | ||
|
||
// SubmitMisbehaviourReq defines the properties of a submit misbehaviour request's body. | ||
type SubmitMisbehaviourReq struct { | ||
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` | ||
Evidence exported.Evidence `json:"evidence" yaml:"evidence"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package rest | ||
|
||
import ( | ||
auth "github.com/cosmos/cosmos-sdk/x/auth" | ||
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" | ||
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint" | ||
commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" | ||
) | ||
|
||
type ( | ||
QueryConsensusState struct { | ||
Height int64 `json:"height"` | ||
Result types.ConsensusStateResponse `json:"result"` | ||
} | ||
|
||
QueryHeader struct { | ||
Height int64 `json:"height"` | ||
Result tendermint.Header `json:"result"` | ||
} | ||
|
||
QueryClientState struct { | ||
Height int64 `json:"height"` | ||
Result types.StateResponse `json:"result"` | ||
} | ||
|
||
QueryRoot struct { | ||
Height int64 `json:"height"` | ||
Result types.RootResponse `json:"result"` | ||
} | ||
|
||
QueryNodeConsensusState struct { | ||
Height int64 `json:"height"` | ||
Result tendermint.ConsensusState `json:"result"` | ||
} | ||
|
||
QueryPath struct { | ||
Height int64 `json:"height"` | ||
Result commitment.Prefix `json:"result"` | ||
} | ||
|
||
PostCreateClient struct { | ||
Msgs []types.MsgCreateClient `json:"msg" yaml:"msg"` | ||
Fee auth.StdFee `json:"fee" yaml:"fee"` | ||
Signatures []auth.StdSignature `json:"signatures" yaml:"signatures"` | ||
Memo string `json:"memo" yaml:"memo"` | ||
} | ||
|
||
PostUpdateClient struct { | ||
Msgs []types.MsgUpdateClient `json:"msg" yaml:"msg"` | ||
Fee auth.StdFee `json:"fee" yaml:"fee"` | ||
Signatures []auth.StdSignature `json:"signatures" yaml:"signatures"` | ||
Memo string `json:"memo" yaml:"memo"` | ||
} | ||
|
||
PostSubmitMisbehaviour struct { | ||
Msgs []types.MsgSubmitMisbehaviour `json:"msg" yaml:"msg"` | ||
Fee auth.StdFee `json:"fee" yaml:"fee"` | ||
Signatures []auth.StdSignature `json:"signatures" yaml:"signatures"` | ||
Memo string `json:"memo" yaml:"memo"` | ||
} | ||
) |
Oops, something went wrong.