context: remove verifier & trust node (#6805)
* remove verifier * more removal of trustnode flag * add todo * fix lint * remove file * remove viper and add link to issue * remve mention of trustnode
This commit is contained in:
parent
e0a81d2cca
commit
e6a56226a8
|
@ -95,11 +95,6 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont
|
|||
clientCtx = clientCtx.WithChainID(chainID)
|
||||
}
|
||||
|
||||
if flagSet.Changed(flags.FlagTrustNode) {
|
||||
trustNode, _ := flagSet.GetBool(flags.FlagTrustNode)
|
||||
clientCtx = clientCtx.WithTrustNode(trustNode)
|
||||
}
|
||||
|
||||
if clientCtx.Keyring == nil || flagSet.Changed(flags.FlagKeyringBackend) {
|
||||
keyringBackend, _ := flagSet.GetString(flags.FlagKeyringBackend)
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
tmlite "github.com/tendermint/tendermint/lite"
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
rpchttp "github.com/tendermint/tendermint/rpc/client/http"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
@ -34,7 +33,6 @@ type Context struct {
|
|||
From string
|
||||
BroadcastMode string
|
||||
FromName string
|
||||
TrustNode bool
|
||||
UseLedger bool
|
||||
Simulate bool
|
||||
GenerateOnly bool
|
||||
|
@ -43,7 +41,6 @@ type Context struct {
|
|||
TxConfig TxConfig
|
||||
AccountRetriever AccountRetriever
|
||||
NodeURI string
|
||||
Verifier tmlite.Verifier
|
||||
|
||||
// TODO: Deprecated (remove).
|
||||
Codec *codec.Codec
|
||||
|
@ -86,12 +83,6 @@ func (ctx Context) WithFrom(from string) Context {
|
|||
return ctx
|
||||
}
|
||||
|
||||
// WithTrustNode returns a copy of the context with an updated TrustNode flag.
|
||||
func (ctx Context) WithTrustNode(trustNode bool) Context {
|
||||
ctx.TrustNode = trustNode
|
||||
return ctx
|
||||
}
|
||||
|
||||
// WithOutputFormat returns a copy of the context with an updated OutputFormat field.
|
||||
func (ctx Context) WithOutputFormat(format string) Context {
|
||||
ctx.OutputFormat = format
|
||||
|
@ -129,12 +120,6 @@ func (ctx Context) WithUseLedger(useLedger bool) Context {
|
|||
return ctx
|
||||
}
|
||||
|
||||
// WithVerifier returns a copy of the context with an updated Verifier.
|
||||
func (ctx Context) WithVerifier(verifier tmlite.Verifier) Context {
|
||||
ctx.Verifier = verifier
|
||||
return ctx
|
||||
}
|
||||
|
||||
// WithChainID returns a copy of the context with an updated chain ID.
|
||||
func (ctx Context) WithChainID(chainID string) Context {
|
||||
ctx.ChainID = chainID
|
||||
|
|
|
@ -40,7 +40,6 @@ const (
|
|||
FlagNode = "node"
|
||||
FlagHeight = "height"
|
||||
FlagGasAdjustment = "gas-adjustment"
|
||||
FlagTrustNode = "trust-node"
|
||||
FlagFrom = "from"
|
||||
FlagName = "name"
|
||||
FlagAccountNumber = "account-number"
|
||||
|
@ -71,7 +70,6 @@ var LineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}}
|
|||
|
||||
// AddQueryFlagsToCmd adds common flags to a module query command.
|
||||
func AddQueryFlagsToCmd(cmd *cobra.Command) {
|
||||
cmd.Flags().Bool(FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
|
||||
cmd.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device")
|
||||
cmd.Flags().String(FlagNode, "tcp://localhost:26657", "<host>:<port> to Tendermint RPC interface for this chain")
|
||||
cmd.Flags().Int64(FlagHeight, 0, "Use a specific height to query state at (this can error if the node is pruning state)")
|
||||
|
@ -96,7 +94,6 @@ func AddTxFlagsToCmd(cmd *cobra.Command) {
|
|||
cmd.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device")
|
||||
cmd.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored ")
|
||||
cmd.Flags().StringP(FlagBroadcastMode, "b", BroadcastSync, "Transaction broadcasting mode (sync|async|block)")
|
||||
cmd.Flags().Bool(FlagTrustNode, true, "Trust connected full node (don't verify proofs for responses)")
|
||||
cmd.Flags().Bool(FlagDryRun, false, "ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it")
|
||||
cmd.Flags().Bool(FlagGenerateOnly, false, "Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase is not accessible)")
|
||||
cmd.Flags().Bool(FlagOffline, false, "Offline mode (does not allow any online functionality")
|
||||
|
|
|
@ -7,12 +7,8 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/crypto/merkle"
|
||||
tmbytes "github.com/tendermint/tendermint/libs/bytes"
|
||||
tmliteErr "github.com/tendermint/tendermint/lite/errors"
|
||||
tmliteProxy "github.com/tendermint/tendermint/lite/proxy"
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/store/rootmulti"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -86,7 +82,7 @@ func (ctx Context) queryABCI(req abci.RequestQuery) (abci.ResponseQuery, error)
|
|||
|
||||
opts := rpcclient.ABCIQueryOptions{
|
||||
Height: ctx.Height,
|
||||
Prove: req.Prove || !ctx.TrustNode,
|
||||
Prove: req.Prove,
|
||||
}
|
||||
|
||||
result, err := node.ABCIQueryWithOptions(req.Path, req.Data, opts)
|
||||
|
@ -103,18 +99,12 @@ func (ctx Context) queryABCI(req abci.RequestQuery) (abci.ResponseQuery, error)
|
|||
return result.Response, nil
|
||||
}
|
||||
|
||||
if err = ctx.verifyProof(req.Path, result.Response); err != nil {
|
||||
return abci.ResponseQuery{}, err
|
||||
}
|
||||
|
||||
return result.Response, nil
|
||||
}
|
||||
|
||||
// query performs a query to a Tendermint node with the provided store name
|
||||
// and path. It returns the result and height of the query upon success
|
||||
// or an error if the query fails. In addition, it will verify the returned
|
||||
// proof if TrustNode is disabled. If proof verification fails or the query
|
||||
// height is invalid, an error will be returned.
|
||||
// or an error if the query fails.
|
||||
func (ctx Context) query(path string, key tmbytes.HexBytes) ([]byte, int64, error) {
|
||||
resp, err := ctx.queryABCI(abci.RequestQuery{
|
||||
Path: path,
|
||||
|
@ -127,64 +117,6 @@ func (ctx Context) query(path string, key tmbytes.HexBytes) ([]byte, int64, erro
|
|||
return resp.Value, resp.Height, nil
|
||||
}
|
||||
|
||||
// Verify verifies the consensus proof at given height.
|
||||
func (ctx Context) Verify(height int64) (tmtypes.SignedHeader, error) {
|
||||
if ctx.Verifier == nil {
|
||||
return tmtypes.SignedHeader{}, fmt.Errorf("missing valid certifier to verify data from distrusted node")
|
||||
}
|
||||
|
||||
check, err := tmliteProxy.GetCertifiedCommit(height, ctx.Client, ctx.Verifier)
|
||||
|
||||
switch {
|
||||
case tmliteErr.IsErrCommitNotFound(err):
|
||||
return tmtypes.SignedHeader{}, ErrVerifyCommit(height)
|
||||
case err != nil:
|
||||
return tmtypes.SignedHeader{}, err
|
||||
}
|
||||
|
||||
return check, nil
|
||||
}
|
||||
|
||||
// verifyProof perform response proof verification.
|
||||
func (ctx Context) verifyProof(queryPath string, resp abci.ResponseQuery) error {
|
||||
if ctx.Verifier == nil {
|
||||
return fmt.Errorf("missing valid certifier to verify data from distrusted node")
|
||||
}
|
||||
|
||||
// the AppHash for height H is in header H+1
|
||||
commit, err := ctx.Verify(resp.Height + 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Instead of reconstructing, stash on Context field?
|
||||
prt := rootmulti.DefaultProofRuntime()
|
||||
|
||||
// TODO: Better convention for path?
|
||||
storeName, err := parseQueryStorePath(queryPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kp := merkle.KeyPath{}
|
||||
kp = kp.AppendKey([]byte(storeName), merkle.KeyEncodingURL)
|
||||
kp = kp.AppendKey(resp.Key, merkle.KeyEncodingURL)
|
||||
|
||||
if resp.Value == nil {
|
||||
err = prt.VerifyAbsence(resp.Proof, commit.Header.AppHash, kp.String())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to prove merkle proof")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := prt.VerifyValue(resp.Proof, commit.Header.AppHash, kp.String(), resp.Value); err != nil {
|
||||
return errors.Wrap(err, "failed to prove merkle proof")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// queryStore performs a query to a Tendermint node with the provided a store
|
||||
// name and path. It returns the result and height of the query upon success
|
||||
// or an error if the query fails.
|
||||
|
@ -213,23 +145,3 @@ func isQueryStoreWithProof(path string) bool {
|
|||
|
||||
return false
|
||||
}
|
||||
|
||||
// parseQueryStorePath expects a format like /store/<storeName>/key.
|
||||
func parseQueryStorePath(path string) (storeName string, err error) {
|
||||
if !strings.HasPrefix(path, "/") {
|
||||
return "", errors.New("expected path to start with /")
|
||||
}
|
||||
|
||||
paths := strings.SplitN(path[1:], "/", 3)
|
||||
|
||||
switch {
|
||||
case len(paths) != 3:
|
||||
return "", errors.New("expected format like /store/<storeName>/key")
|
||||
case paths[0] != "store":
|
||||
return "", errors.New("expected format like /store/<storeName>/key")
|
||||
case paths[2] != "key":
|
||||
return "", errors.New("expected format like /store/<storeName>/key")
|
||||
}
|
||||
|
||||
return paths[1], nil
|
||||
}
|
||||
|
|
|
@ -12,8 +12,6 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec/legacy"
|
||||
"github.com/cosmos/cosmos-sdk/types/rest"
|
||||
|
||||
tmliteProxy "github.com/tendermint/tendermint/lite/proxy"
|
||||
)
|
||||
|
||||
//BlockCommand returns the verified block data for a given heights
|
||||
|
@ -50,7 +48,6 @@ func BlockCommand() *cobra.Command {
|
|||
}
|
||||
|
||||
cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
|
||||
cmd.Flags().Bool(flags.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
@ -70,21 +67,6 @@ func getBlock(clientCtx client.Context, height *int64) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if !clientCtx.TrustNode {
|
||||
check, err := clientCtx.Verify(res.Block.Height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := tmliteProxy.ValidateHeader(&res.Block.Header, check); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = tmliteProxy.ValidateBlock(res.Block, check); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return legacy.Cdc.MarshalJSON(res)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -56,7 +55,6 @@ func ValidatorCommand() *cobra.Command {
|
|||
}
|
||||
|
||||
cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
|
||||
cmd.Flags().Bool(flags.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
|
||||
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
|
||||
cmd.Flags().Int(flags.FlagPage, 0, "Query a specific page of paginated results")
|
||||
cmd.Flags().Int(flags.FlagLimit, 100, "Query number of results returned per page")
|
||||
|
@ -126,17 +124,6 @@ func GetValidators(clientCtx client.Context, height *int64, page, limit int) (Re
|
|||
return ResultValidatorsOutput{}, err
|
||||
}
|
||||
|
||||
if !clientCtx.TrustNode {
|
||||
check, err := clientCtx.Verify(validatorsRes.BlockHeight)
|
||||
if err != nil {
|
||||
return ResultValidatorsOutput{}, err
|
||||
}
|
||||
|
||||
if !bytes.Equal(check.ValidatorsHash, tmtypes.NewValidatorSet(validatorsRes.Validators).Hash()) {
|
||||
return ResultValidatorsOutput{}, fmt.Errorf("received invalid validatorset")
|
||||
}
|
||||
}
|
||||
|
||||
outputValidatorsRes := ResultValidatorsOutput{
|
||||
BlockHeight: validatorsRes.BlockHeight,
|
||||
Validators: make([]ValidatorOutput, len(validatorsRes.Validators)),
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmlite "github.com/tendermint/tendermint/lite"
|
||||
tmliteproxy "github.com/tendermint/tendermint/lite/proxy"
|
||||
rpchttp "github.com/tendermint/tendermint/rpc/client/http"
|
||||
)
|
||||
|
||||
const (
|
||||
verifierDir = ".lite_verifier"
|
||||
|
||||
// DefaultVerifierCacheSize defines the default Tendermint cache size.
|
||||
DefaultVerifierCacheSize = 10
|
||||
)
|
||||
|
||||
// CreateVerifier returns a Tendermint verifier from a Context object and
|
||||
// cache size. An error is returned if the Context is missing required values
|
||||
// or if the verifier could not be created. A Context must at the very least
|
||||
// have the chain ID and home directory set. If the Context has TrustNode
|
||||
// enabled, no verifier will be created.
|
||||
func CreateVerifier(ctx Context, cacheSize int) (tmlite.Verifier, error) {
|
||||
if ctx.TrustNode {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
switch {
|
||||
case ctx.ChainID == "":
|
||||
return nil, errors.New("must provide a valid chain ID to create verifier")
|
||||
|
||||
case ctx.HomeDir == "":
|
||||
return nil, errors.New("must provide a valid home directory to create verifier")
|
||||
|
||||
case ctx.Client == nil && ctx.NodeURI == "":
|
||||
return nil, errors.New("must provide a valid RPC client or RPC URI to create verifier")
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
// create an RPC client based off of the RPC URI if no RPC client exists
|
||||
client := ctx.Client
|
||||
if client == nil {
|
||||
client, err = rpchttp.New(ctx.NodeURI, "/websocket")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return tmliteproxy.NewVerifier(
|
||||
ctx.ChainID, filepath.Join(ctx.HomeDir, ctx.ChainID, verifierDir),
|
||||
client, log.NewNopLogger(), cacheSize,
|
||||
)
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package client_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
)
|
||||
|
||||
func TestCreateVerifier(t *testing.T) {
|
||||
tmpDir, cleanup := testutil.NewTestCaseDir(t)
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
ctx client.Context
|
||||
expectErr bool
|
||||
}{
|
||||
{"no chain ID", client.Context{}, true},
|
||||
{"no home directory", client.Context{}.WithChainID("test"), true},
|
||||
{"no client or RPC URI", client.Context{HomeDir: tmpDir}.WithChainID("test"), true},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
verifier, err := client.CreateVerifier(tc.ctx, client.DefaultVerifierCacheSize)
|
||||
require.Equal(t, tc.expectErr, err != nil, err)
|
||||
|
||||
if !tc.expectErr {
|
||||
require.NotNil(t, verifier)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -57,7 +57,7 @@ This query returns the address that owns a particular name. The getter function
|
|||
+ The function should first initialize a new [`Context`](../interfaces/query-lifecycle.md#context) with the application `codec`.
|
||||
+ If applicable, the `Context` is used to retrieve any parameters (e.g. the query originator's address to be used in the query) and marshal them with the query parameter type, in preparation to be relayed to a node. There are no `Context` parameters in this case because the query does not involve any information about the user.
|
||||
+ The `queryRoute` is used to construct a `path` [`baseapp`](../core/baseapp.md) will use to route the query to the appropriate [querier](./querier.md). The expected format for a query `path` is "queryCategory/queryRoute/queryType/arg1/arg2/...", where `queryCategory` can be `p2p`, `store`, `app`, or `custom`, `queryRoute` is the name of the module, and `queryType` is the name of the query type defined within the module. [`baseapp`](../core/baseapp.md) can handle each type of `queryCategory` by routing it to a module querier or retrieving results directly from stores and functions for querying peer nodes. Module queries are `custom` type queries (some SDK modules have exceptions, such as `auth` and `gov` module queries).
|
||||
+ The `Context` `QueryWithData()` function is used to relay the query to a node and retrieve the response. It requires the `path`. It returns the result and height of the query upon success or an error if the query fails. In addition, it will verify the returned proof if `TrustNode` is disabled. If proof verification fails or the query height is invalid, an error will be returned.
|
||||
+ The `Context` `QueryWithData()` function is used to relay the query to a node and retrieve the response. It requires the `path`. It returns the result and height of the query upon success or an error if the query fails.
|
||||
+ The `codec` is used to nmarshal the response and the `Context` is used to print the output back to the user.
|
||||
- **Flags.** Add any [flags](#flags) to the command.
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
| chain-id | string | null | true | 要链接全节点的 chain id |
|
||||
| node | URL | "tcp://localhost:46657" | true | 要链接全节点的地址和端口号 |
|
||||
| laddr | URL | "tcp://localhost:1317" | true | 提供 REST 服务的地址和端口号 |
|
||||
| trust-node | bool | "false" | true | 是否信任 LCD 连接的全节点 |
|
||||
| trust-store | DIRECTORY | "\$HOME/.lcd" | false | 保存检查点和验证人集的目录 |
|
||||
|
||||
示例:
|
||||
|
@ -16,7 +15,6 @@
|
|||
gaiacli rest-server --chain-id=test \
|
||||
--laddr=tcp://localhost:1317 \
|
||||
--node tcp://localhost:26657 \
|
||||
--trust-node=false
|
||||
```
|
||||
|
||||
有关 Gaia-Lite RPC 的更多信息,请参阅 [swagger documentation](https://cosmos.network/rpc/)
|
||||
|
|
|
@ -99,7 +99,6 @@ gaiacli rest-server --node=<full_node_address:full_node_port>
|
|||
|
||||
Flags:
|
||||
|
||||
- `--trust-node`: 布尔类型。如果为 `true`,轻节点校验将被禁用。如果为 `false`, 则会校验返回结果。 对于服务提供商,应将其设置为 `true`。默认情况下,它设置为 `true`。
|
||||
- `--node`: 全节点的 IP 地址和端口。格式为 `<full_node_address:full_node_port>`。如果全节点在同一台机器上,则地址应为 `tcp:// localhost:26657`。
|
||||
- `--laddr`: 此标识允许您指定 Rest 服务器的地址和端口(默认为“1317”)。通常只使用这个标识指定端口,此时只需输入 “localhost” 作为地址,格式为`<rest_server_address:port>`。
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ To start a REST server, we need to specify the following parameters:
|
|||
| chain-id | string | null | true | chain id of the full node to connect |
|
||||
| node | URL | "tcp://localhost:46657" | true | address of the full node to connect |
|
||||
| laddr | URL | "tcp://localhost:1317" | true | address to run the rest server on |
|
||||
| trust-node | bool | "false" | true | Whether this LCD is connected to a trusted full node |
|
||||
| trust-store | DIRECTORY | "$HOME/.lcd" | false | directory for save checkpoints and validator sets |
|
||||
|
||||
For example:
|
||||
|
@ -16,7 +15,6 @@ For example:
|
|||
gaiacli rest-server --chain-id=test \
|
||||
--laddr=tcp://localhost:1317 \
|
||||
--node tcp://localhost:26657 \
|
||||
--trust-node=false
|
||||
```
|
||||
|
||||
For more information about the Gaia-Lite RPC, see the [swagger documentation](https://cosmos.network/rpc/)
|
||||
|
|
|
@ -141,7 +141,7 @@ Once a result is received from the querier, `baseapp` begins the process of retu
|
|||
|
||||
## Response
|
||||
|
||||
Since `Query()` is an ABCI function, `baseapp` returns the response as an [`abci.ResponseQuery`](https://tendermint.com/docs/spec/abci/abci.html#messages) type. The `Context` `Query()` routine receives the response and, if `--trust-node` is toggled to `false` and a proof needs to be verified, the response is verified with the `Context` `verifyProof()` function before the response is returned.
|
||||
Since `Query()` is an ABCI function, `baseapp` returns the response as an [`abci.ResponseQuery`](https://tendermint.com/docs/spec/abci/abci.html#messages) type. The `Context` `Query()` routine receives the response and.
|
||||
|
||||
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/client/context/query.go#L127-L165
|
||||
|
||||
|
|
|
@ -22,11 +22,9 @@ rootCmd.AddCommand(rest.ServeCommand(cdc, registerRoutes))
|
|||
Users will then be able to use the application CLI to start a new REST server, a local server through which they can securely interact with the application without downloading the entire state. The command entered by users would look something like this:
|
||||
|
||||
```bash
|
||||
appcli rest-server --chain-id <chainID> --trust-node
|
||||
appcli rest-server --chain-id <chainID>
|
||||
```
|
||||
|
||||
Note that if `trust-node` is set to `false`, the REST server will verify the query proof against the merkle root (contained in the block header).
|
||||
|
||||
## REST Server
|
||||
|
||||
A REST Server is used to receive and route HTTP Requests, obtain the results from the application, and return a response to the user. The REST Server defined by the SDK `rest` package contains the following:
|
||||
|
@ -68,5 +66,5 @@ rootCmd.AddCommand(rest.ServeCommand(cdc, registerRoutes))
|
|||
gaiacli rest-server --chain-id=test \
|
||||
--laddr=tcp://localhost:1317 \
|
||||
--node tcp://localhost:26657 \
|
||||
--trust-node=true --unsafe-cors
|
||||
--unsafe-cors
|
||||
```
|
||||
|
|
|
@ -8,7 +8,6 @@ REST 서버를 가동하기 위해서는 다음과 같은 파라미터 값을
|
|||
| chain-id | string | null | 필수 | 연결할 체인의 chain-id |
|
||||
| node | URL | "tcp://localhost:46657" | 필수 | 연결할 풀노드의 주소 |
|
||||
| laddr | URL | "tcp://localhost:1317" | 필수 | REST 서버를 가동할 주소 |
|
||||
| trust-node | bool | "false" | 필수 | 연결할 풀노드의 신뢰가능 여부 |
|
||||
| trust-store | DIRECTORY | "$HOME/.lcd" | 선택 | 체크포인트와 검증인 세트를 저장할 디렉터리 |
|
||||
|
||||
예를 들어::
|
||||
|
@ -16,8 +15,7 @@ REST 서버를 가동하기 위해서는 다음과 같은 파라미터 값을
|
|||
```bash
|
||||
gaiacli rest-server --chain-id=test \
|
||||
--laddr=tcp://localhost:1317 \
|
||||
--node tcp://localhost:26657 \
|
||||
--trust-node=false
|
||||
--node tcp://localhost:26657
|
||||
```
|
||||
|
||||
Gaia-Lite RPC에 대한 추가적인 정보를 원하시면 [Swagger 문서](https://cosmos.network/rpc/)를 확인하세요.
|
||||
|
|
|
@ -93,7 +93,6 @@ gaiacli advanced rest-server --node=<full_node_address:full_node_port>
|
|||
```
|
||||
|
||||
플래그:
|
||||
- `--trust-node`: 불리언 값. `true`일 경우, 라이트 클라이언트 검증 절차가 비활성화 됩니다. 만약 `false`일 경우, 절차가 활성화됩니다. 서비스 제공자의 경우 `true` 값을 이용하시면 됩니다. 기본 값은 `true`입니다.
|
||||
- `--node`: 플노드의 주소와 포트를 입력하시면 됩니다. 만약 풀노드와 REST 서버가 동일한 머신에서 운영될 경우 주소 값은 `tcp://localhost:26657`로 설정하시면 됩니다.
|
||||
- `--laddr`: REST 서버의 주소와 포트를 정하는 플래그입니다(기본 값 `1317`). 대다수의 경우에는 포트를 정하기 위해서 사용됩니다, 이 경우 주소는 "localhost"로 입력하시면 됩니다. 포맷은 <rest_server_address:port>입니다.
|
||||
|
||||
|
|
|
@ -219,8 +219,7 @@ func startInProcess(ctx *Context, cdc codec.JSONMarshaler, appCreator AppCreator
|
|||
WithHomeDir(home).
|
||||
WithChainID(genDoc.ChainID).
|
||||
WithJSONMarshaler(cdc).
|
||||
WithClient(local.New(tmNode)).
|
||||
WithTrustNode(true)
|
||||
WithClient(local.New(tmNode))
|
||||
|
||||
apiSrv = api.New(clientCtx, ctx.Logger.With("module", "api-server"))
|
||||
app.RegisterAPIRoutes(apiSrv)
|
||||
|
|
|
@ -60,8 +60,7 @@ func startInProcess(cfg Config, val *Validator) error {
|
|||
|
||||
if val.APIAddress != "" {
|
||||
val.ClientCtx = val.ClientCtx.
|
||||
WithClient(val.RPCClient).
|
||||
WithTrustNode(true)
|
||||
WithClient(val.RPCClient)
|
||||
|
||||
apiSrv := api.New(val.ClientCtx, logger.With("module", "api-server"))
|
||||
app.RegisterAPIRoutes(apiSrv)
|
||||
|
|
|
@ -184,7 +184,6 @@ $ %s query txs --%s 'message.sender=cosmos1...&message.action=withdraw_delegator
|
|||
}
|
||||
|
||||
cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
|
||||
cmd.Flags().Bool(flags.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
|
||||
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
|
||||
cmd.Flags().Int(flags.FlagPage, rest.DefaultPage, "Query a specific page of paginated results")
|
||||
cmd.Flags().Int(flags.FlagLimit, rest.DefaultLimit, "Query number of transactions results per page returned")
|
||||
|
@ -221,7 +220,6 @@ func QueryTxCmd() *cobra.Command {
|
|||
}
|
||||
|
||||
cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
|
||||
cmd.Flags().Bool(flags.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
|
||||
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
|
||||
|
||||
return cmd
|
||||
|
|
|
@ -41,22 +41,13 @@ func QueryTxsByEvents(clientCtx client.Context, events []string, page, limit int
|
|||
return nil, err
|
||||
}
|
||||
|
||||
prove := !clientCtx.TrustNode
|
||||
|
||||
resTxs, err := node.TxSearch(query, prove, page, limit, orderBy)
|
||||
// TODO: this may not always need to be proven
|
||||
// https://github.com/cosmos/cosmos-sdk/issues/6807
|
||||
resTxs, err := node.TxSearch(query, true, page, limit, orderBy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if prove {
|
||||
for _, tx := range resTxs.Txs {
|
||||
err := ValidateTxResult(clientCtx, tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resBlocks, err := getBlocksForTxResults(clientCtx, resTxs.Txs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -85,17 +76,13 @@ func QueryTx(clientCtx client.Context, hashHexStr string) (*sdk.TxResponse, erro
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resTx, err := node.Tx(hash, !clientCtx.TrustNode)
|
||||
//TODO: this may not always need to be proven
|
||||
// https://github.com/cosmos/cosmos-sdk/issues/6807
|
||||
resTx, err := node.Tx(hash, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !clientCtx.TrustNode {
|
||||
if err = ValidateTxResult(clientCtx, resTx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
resBlocks, err := getBlocksForTxResults(clientCtx, []*ctypes.ResultTx{resTx})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -123,21 +110,6 @@ func formatTxResults(cdc *codec.Codec, resTxs []*ctypes.ResultTx, resBlocks map[
|
|||
return out, nil
|
||||
}
|
||||
|
||||
// ValidateTxResult performs transaction verification.
|
||||
func ValidateTxResult(clientCtx client.Context, resTx *ctypes.ResultTx) error {
|
||||
if !clientCtx.TrustNode {
|
||||
check, err := clientCtx.Verify(resTx.Height)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = resTx.Proof.Validate(check.Header.DataHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getBlocksForTxResults(clientCtx client.Context, resTxs []*ctypes.ResultTx) (map[int64]*ctypes.ResultBlock, error) {
|
||||
node, err := clientCtx.GetNode()
|
||||
if err != nil {
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
func TestQueryDelegationRewardsAddrValidation(t *testing.T) {
|
||||
clientCtx := client.Context{}.WithJSONMarshaler(types.ModuleCdc).WithTrustNode(true)
|
||||
clientCtx := client.Context{}.WithJSONMarshaler(types.ModuleCdc)
|
||||
|
||||
type args struct {
|
||||
delAddr string
|
||||
|
|
|
@ -148,7 +148,6 @@ func TestGetPaginatedVotes(t *testing.T) {
|
|||
clientCtx := client.Context{}.
|
||||
WithJSONMarshaler(cdc).
|
||||
WithCodec(cdc).
|
||||
WithTrustNode(true).
|
||||
WithClient(cli)
|
||||
|
||||
params := types.NewQueryProposalVotesParams(0, tc.page, tc.limit)
|
||||
|
|
|
@ -399,7 +399,6 @@ type TxCreateValidatorConfig struct {
|
|||
CommissionMaxChangeRate string
|
||||
MinSelfDelegation string
|
||||
|
||||
TrustNode bool
|
||||
PubKey string
|
||||
|
||||
IP string
|
||||
|
@ -472,7 +471,6 @@ func PrepareConfigForTxCreateValidator(flagSet *flag.FlagSet, moniker, nodeID, c
|
|||
}
|
||||
|
||||
c.NodeID = nodeID
|
||||
c.TrustNode = true
|
||||
c.PubKey = sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, valPubKey)
|
||||
c.Website = website
|
||||
c.SecurityContact = securityContact
|
||||
|
|
|
@ -31,7 +31,6 @@ func TestPrepareConfigForTxCreateValidator(t *testing.T) {
|
|||
IP: ip,
|
||||
ChainID: chainID,
|
||||
NodeID: nodeID,
|
||||
TrustNode: true,
|
||||
PubKey: sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, valPubKey),
|
||||
Moniker: moniker,
|
||||
Amount: "100000000stake",
|
||||
|
@ -51,7 +50,6 @@ func TestPrepareConfigForTxCreateValidator(t *testing.T) {
|
|||
Moniker: moniker,
|
||||
ChainID: chainID,
|
||||
NodeID: nodeID,
|
||||
TrustNode: true,
|
||||
PubKey: sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, valPubKey),
|
||||
Amount: "2000stake",
|
||||
CommissionRate: "0.1",
|
||||
|
@ -70,7 +68,6 @@ func TestPrepareConfigForTxCreateValidator(t *testing.T) {
|
|||
Moniker: moniker,
|
||||
ChainID: chainID,
|
||||
NodeID: nodeID,
|
||||
TrustNode: true,
|
||||
PubKey: sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, valPubKey),
|
||||
Amount: "100000000stake",
|
||||
CommissionRate: "0.54",
|
||||
|
@ -89,7 +86,6 @@ func TestPrepareConfigForTxCreateValidator(t *testing.T) {
|
|||
Moniker: moniker,
|
||||
ChainID: chainID,
|
||||
NodeID: nodeID,
|
||||
TrustNode: true,
|
||||
PubKey: sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, valPubKey),
|
||||
Amount: "100000000stake",
|
||||
CommissionRate: "0.1",
|
||||
|
@ -108,7 +104,6 @@ func TestPrepareConfigForTxCreateValidator(t *testing.T) {
|
|||
Moniker: moniker,
|
||||
ChainID: chainID,
|
||||
NodeID: nodeID,
|
||||
TrustNode: true,
|
||||
PubKey: sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, valPubKey),
|
||||
Amount: "100000000stake",
|
||||
CommissionRate: "0.1",
|
||||
|
@ -127,7 +122,6 @@ func TestPrepareConfigForTxCreateValidator(t *testing.T) {
|
|||
Moniker: moniker,
|
||||
ChainID: chainID,
|
||||
NodeID: nodeID,
|
||||
TrustNode: true,
|
||||
PubKey: sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, valPubKey),
|
||||
Amount: "100000000stake",
|
||||
CommissionRate: "0.1",
|
||||
|
|
Loading…
Reference in New Issue