Skip to content

Commit

Permalink
refactor(server): audit QA (cosmos#21442)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucaslopezf committed Aug 30, 2024
1 parent 2440154 commit b33ed07
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 17 deletions.
99 changes: 98 additions & 1 deletion UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,104 @@ Additionally, thanks to the genesis simplification, as explained in [the genesis

##### GRPC-WEB

Grpc-web embedded client has been removed from the server. If you would like to use grpc-web, you can use the [envoy proxy](https://www.envoyproxy.io/docs/envoy/latest/start/start).
Grpc-web embedded client has been removed from the server. If you would like to use grpc-web, you can use the [envoy proxy](https://www.envoyproxy.io/docs/envoy/latest/start/start). Here's how to set it up:

<details>
<summary>Step by step guide</summary>

1. Install Envoy following the [official installation guide](https://www.envoyproxy.io/docs/envoy/latest/start/install).

2. Create an Envoy configuration file named `envoy.yaml` with the following content:

```yaml
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route:
cluster: grpc_service
timeout: 0s
max_stream_duration:
grpc_timeout_header_max: 0s
cors:
allow_origin_string_match:
- prefix: "*"
allow_methods: GET, PUT, DELETE, POST, OPTIONS
allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
max_age: "1728000"
expose_headers: custom-header-1,grpc-status,grpc-message
http_filters:
- name: envoy.filters.http.grpc_web
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
- name: envoy.filters.http.cors
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: grpc_service
connect_timeout: 0.25s
type: logical_dns
http2_protocol_options: {}
lb_policy: round_robin
load_assignment:
cluster_name: cluster_0
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 0.0.0.0
port_value: 9090
```

This configuration tells Envoy to listen on port 8080 and forward requests to your gRPC service on port 9090. Note that this configuration is a starting point and can be modified according to your specific needs and preferences. You may need to adjust ports, addresses, or add additional settings based on your particular setup and requirements.

3. Start your Cosmos SDK application, ensuring it's configured to serve gRPC on port 9090.

4. Start Envoy with the configuration file:

```bash
envoy -c envoy.yaml
```

5. If Envoy starts successfully, you should see output similar to this:

```bash
[2024-08-29 10:47:08.753][6281320][info][config] [source/common/listener_manager/listener_manager_impl.cc:930] all dependencies initialized. starting workers
[2024-08-29 10:47:08.754][6281320][info][main] [source/server/server.cc:978] starting main dispatch loop
```

This indicates that Envoy has started and is ready to proxy requests.

6. Update your client applications to connect to Envoy (http://localhost:8080 by default).

</details>

By following these steps, Envoy will handle the translation between gRPC-Web and gRPC, allowing your existing gRPC-Web clients to continue functioning without modifications to your Cosmos SDK application.

To test the setup, you can use a tool like [grpcurl](https://github.com/fullstorydev/grpcurl). For example:

```bash
grpcurl -plaintext localhost:8080 cosmos.base.tendermint.v1beta1.Service/GetLatestBlock
```

##### AnteHandlers

Expand Down
7 changes: 4 additions & 3 deletions server/cmt_cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,9 +363,10 @@ func QueryBlockResultsCmd() *cobra.Command {

func BootstrapStateCmd[T types.Application](appCreator types.AppCreator[T]) *cobra.Command {
cmd := &cobra.Command{
Use: "bootstrap-state",
Short: "Bootstrap CometBFT state at an arbitrary block height using a light client",
Args: cobra.NoArgs,
Use: "bootstrap-state",
Short: "Bootstrap CometBFT state at an arbitrary block height using a light client",
Args: cobra.NoArgs,
Example: fmt.Sprintf("%s bootstrap-state --height 1000000", version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
serverCtx := GetServerContextFromCmd(cmd)
logger := log.NewLogger(cmd.OutOrStdout())
Expand Down
53 changes: 53 additions & 0 deletions server/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

pruningtypes "cosmossdk.io/store/pruning/types"

sdk "github.com/cosmos/cosmos-sdk/types"
)

Expand All @@ -21,15 +23,29 @@ func TestDefaultConfig(t *testing.T) {
func TestGetAndSetMinimumGas(t *testing.T) {
cfg := DefaultConfig()

// Test case 1: Single coin
input := sdk.DecCoins{sdk.NewInt64DecCoin("foo", 5)}
cfg.SetMinGasPrices(input)
require.Equal(t, "5.000000000000000000foo", cfg.MinGasPrices)
require.EqualValues(t, cfg.GetMinGasPrices(), input)

// Test case 2: Multiple coins
input = sdk.DecCoins{sdk.NewInt64DecCoin("bar", 1), sdk.NewInt64DecCoin("foo", 5)}
cfg.SetMinGasPrices(input)
require.Equal(t, "1.000000000000000000bar,5.000000000000000000foo", cfg.MinGasPrices)
require.EqualValues(t, cfg.GetMinGasPrices(), input)

// Test case 4: Empty DecCoins
input = sdk.DecCoins{}
cfg.SetMinGasPrices(input)
require.Equal(t, "", cfg.MinGasPrices)
require.EqualValues(t, cfg.GetMinGasPrices(), input)

// Test case 5: Invalid string (should panic)
cfg.MinGasPrices = "invalid,gas,prices"
require.Panics(t, func() {
cfg.GetMinGasPrices()
}, "GetMinGasPrices should panic with invalid input")
}

func TestIndexEventsMarshalling(t *testing.T) {
Expand Down Expand Up @@ -238,3 +254,40 @@ func TestAppConfig(t *testing.T) {
require.NoError(t, v.Unmarshal(appCfg))
require.EqualValues(t, appCfg, defAppConfig)
}

func TestValidateBasic(t *testing.T) {
cfg := DefaultConfig()

// Test case 1: Valid MinGasPrices
cfg.MinGasPrices = "0.01stake"
err := cfg.ValidateBasic()
require.NoError(t, err)

// Test case 2: Default configuration (MinGasPrices is empty)
cfg.MinGasPrices = ""
err = cfg.ValidateBasic()
require.Error(t, err)
require.Contains(t, err.Error(), "set min gas price in app.toml or flag or env variable")

// Test case 3: Invalid pruning and state sync combination
cfg = DefaultConfig()
cfg.MinGasPrices = "0.01stake"
cfg.Pruning = pruningtypes.PruningOptionEverything
cfg.StateSync.SnapshotInterval = 1000
err = cfg.ValidateBasic()
require.Error(t, err)
require.Contains(t, err.Error(), "cannot enable state sync snapshots with 'everything' pruning setting")
}

func TestGetConfig(t *testing.T) {
v := viper.New()
v.Set("minimum-gas-prices", "0.01stake")
v.Set("api.enable", true)
v.Set("grpc.max-recv-msg-size", 5*1024*1024)

cfg, err := GetConfig(v)
require.NoError(t, err)
require.Equal(t, "0.01stake", cfg.MinGasPrices)
require.True(t, cfg.API.Enable)
require.Equal(t, 5*1024*1024, cfg.GRPC.MaxRecvMsgSize)
}
23 changes: 10 additions & 13 deletions server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ type StartCmdOptions[T types.Application] struct {
// AddFlags add custom flags to start cmd
AddFlags func(cmd *cobra.Command)
// StartCommandHandler can be used to customize the start command handler
StartCommandHandler func(svrCtx *Context, clientCtx client.Context, appCreator types.AppCreator[T], inProcessConsensus bool, opts StartCmdOptions[T]) error
StartCommandHandler func(svrCtx *Context, clientCtx client.Context, appCreator types.AppCreator[T], withCMT bool, opts StartCmdOptions[T]) error
}

// StartCmd runs the service passed in, either stand-alone or in-process with
Expand Down Expand Up @@ -415,31 +415,28 @@ func getAndValidateConfig(svrCtx *Context) (serverconfig.Config, error) {
// getGenDocProvider returns a function which returns the genesis doc from the genesis file.
func getGenDocProvider(cfg *cmtcfg.Config) func() (node.ChecksummedGenesisDoc, error) {
return func() (node.ChecksummedGenesisDoc, error) {
defaultGenesisDoc := node.ChecksummedGenesisDoc{
Sha256Checksum: []byte{},
}

appGenesis, err := genutiltypes.AppGenesisFromFile(cfg.GenesisFile())
if err != nil {
return node.ChecksummedGenesisDoc{
Sha256Checksum: []byte{},
}, err
return defaultGenesisDoc, err
}

gen, err := appGenesis.ToGenesisDoc()
if err != nil {
return node.ChecksummedGenesisDoc{
Sha256Checksum: []byte{},
}, err
return defaultGenesisDoc, err
}

genbz, err := gen.AppState.MarshalJSON()
if err != nil {
return node.ChecksummedGenesisDoc{
Sha256Checksum: []byte{},
}, err
return defaultGenesisDoc, err
}

bz, err := json.Marshal(genbz)
if err != nil {
return node.ChecksummedGenesisDoc{
Sha256Checksum: []byte{},
}, err
return defaultGenesisDoc, err
}
sum := sha256.Sum256(bz)

Expand Down

0 comments on commit b33ed07

Please sign in to comment.