Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,17 @@ provider-start: build-apps
$(providerd) genesis add-genesis-account val 1000000000000uatone,1000000000000uphoton
$(providerd) keys add user
$(providerd) genesis add-genesis-account user 1000000000uatone
# Fund the IBC relayer account so it can pay fees to create the client on the provider
@chmod +x ./scripts/add-relayer-key.sh
@./scripts/add-relayer-key.sh ./build/provider $(provider_home)
$(providerd) genesis add-genesis-account relayer 1000000000uatone
$(providerd) genesis gentx val 1000000000uatone
$(providerd) genesis collect-gentxs

# Set validator gas prices
sed -i.bak 's#^minimum-gas-prices = .*#minimum-gas-prices = "0.01uatone,0.01uphoton"#g' $(provider_home)/config/app.toml
# Bind the RPC to all interfaces so the containerized ts-relayer can reach it
sed -i.bak 's#tcp://127.0.0.1:26657#tcp://0.0.0.0:26657#g' $(provider_home)/config/config.toml
# enable REST API
$(providerd) config set app api.enable true
# Decrease voting period to 5min
Expand Down Expand Up @@ -114,8 +120,10 @@ consumer-init: build-apps
$(consumerd) genesis add-genesis-account relayer 100000000uatone
# Set gas prices
sed -i.bak 's#^minimum-gas-prices = .*#minimum-gas-prices = "0.01uatone,0.01uphoton"#g' $(consumer_home)/config/app.toml
# Use different ports to avoid conflicts with provider
sed -i.bak 's#tcp://127.0.0.1:26657#tcp://127.0.0.1:26667#g' $(consumer_home)/config/config.toml
# Use different ports to avoid conflicts with provider. Bind the RPC to
# 0.0.0.0 (not just loopback) so the containerized ts-relayer can dial it
# via host.docker.internal.
sed -i.bak 's#tcp://127.0.0.1:26657#tcp://0.0.0.0:26667#g' $(consumer_home)/config/config.toml
sed -i.bak 's#tcp://0.0.0.0:26656#tcp://0.0.0.0:26666#g' $(consumer_home)/config/config.toml
sed -i.bak 's#tcp://127.0.0.1:26658#tcp://127.0.0.1:26668#g' $(consumer_home)/config/config.toml
sed -i.bak 's#tcp://localhost:26657#tcp://localhost:26667#g' $(consumer_home)/config/client.toml
Expand All @@ -128,7 +136,7 @@ consumer-init: build-apps
consumer-create:
@echo "Creating consumer chain on provider..."
@mkdir -p /tmp/vaas-test
@echo '{"chain_id": "consumer-localnet", "metadata": {"name": "consumer", "description": "test consumer chain", "metadata": "{}"}, "initialization_parameters": {"initial_height": {"revision_number": 0, "revision_height": 1}, "genesis_hash": "", "binary_hash": "", "spawn_time": "2024-01-01T00:00:00Z", "unbonding_period": 1728000000000000, "vaas_timeout_period": 2419200000000000, "historical_entries": 10000, "connection_id": ""}}' > /tmp/vaas-test/create_consumer.json
@echo '{"chain_id": "consumer-localnet", "metadata": {"name": "consumer", "description": "test consumer chain", "metadata": "{}"}, "initialization_parameters": {"initial_height": {"revision_number": 0, "revision_height": 1}, "genesis_hash": "", "binary_hash": "", "spawn_time": "2024-01-01T00:00:00Z", "unbonding_period": 1728000000000000, "vaas_timeout_period": 3600000000000, "safe_mode_threshold": 10800000000000, "historical_entries": 10000}}' > /tmp/vaas-test/create_consumer.json
$(providerd) tx provider create-consumer /tmp/vaas-test/create_consumer.json --from val --gas auto --gas-adjustment 1.5 --fees 10000uatone -y
@echo "Consumer chain created. Wait for spawn time, then run 'make consumer-genesis' to fetch the genesis."

Expand Down Expand Up @@ -189,7 +197,8 @@ TS_RELAYER ?= ghcr.io/allinbits/ibc-v2-ts-relayer:latest
ts-relayer-start:
@echo "Starting ts-relayer..."
@docker rm -f vaas-ts-relayer 2>/dev/null || true
@docker run -d --name vaas-ts-relayer --network host \
@docker run -d --name vaas-ts-relayer \
--add-host=host.docker.internal:host-gateway \
--cap-add IPC_LOCK \
$(TS_RELAYER)
@sleep 3
Expand All @@ -208,8 +217,8 @@ ts-relayer-start:
@docker exec vaas-ts-relayer /bin/with_keyring ibc-v2-ts-relayer add-path \
-s provider-localnet \
-d consumer-localnet \
--surl http://127.0.0.1:26657 \
--durl http://127.0.0.1:26667 \
--surl http://host.docker.internal:26657 \
--durl http://host.docker.internal:26667 \
--ibc-version 2
@echo "ts-relayer configured and running (log: /tmp/vaas-ts-relayer.log)"

Expand Down
7 changes: 2 additions & 5 deletions app/consumer/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package app

import (
"encoding/json"
"fmt"

cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
tmtypes "github.com/cometbft/cometbft/types"
Expand Down Expand Up @@ -90,12 +89,10 @@ func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []str
}
}

// GetValidatorSet returns a slice of bonded validators.
// GetValidatorSet returns the consumer's cross-chain validators. The set may be
// empty if the consumer has not yet received a validator set from the provider.
func (app *App) GetValidatorSet(ctx sdk.Context) ([]tmtypes.GenesisValidator, error) {
cVals := app.ConsumerKeeper.GetAllCCValidator(ctx)
if len(cVals) == 0 {
return nil, fmt.Errorf("empty validator set")
}

vals := []tmtypes.GenesisValidator{}
for _, v := range cVals {
Expand Down
26 changes: 26 additions & 0 deletions app/consumer/export_empty_valset_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package app

import (
"testing"

"github.com/stretchr/testify/require"

cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"

"cosmossdk.io/log"

dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/cosmos-sdk/testutil/sims"
)

// TestGetValidatorSetToleratesEmptySet: a consumer that has not yet received a
// validator set from the provider has no cross-chain validators, and exporting
// it must succeed with an empty set rather than fail.
func TestGetValidatorSetToleratesEmptySet(t *testing.T) {
app := New(log.NewNopLogger(), dbm.NewMemDB(), nil, true, sims.EmptyAppOptions{})
ctx := app.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()})

vals, err := app.GetValidatorSet(ctx)
require.NoError(t, err, "exporting a consumer with no validators must not fail")
require.Empty(t, vals)
}
13 changes: 13 additions & 0 deletions tests/e2e/e2e_exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ func (s *baseTestSuite) dockerExec(containerID string, cmd []string) (bytes.Buff
return stdout, stderr, fmt.Errorf("failed to start exec: %w", err)
}

// StartExec reports how the exec itself went, not how the command inside it
// exited, so a command that failed comes back with err == nil and an empty
// stdout. Callers that unmarshal stdout then fail on the empty document
// rather than on the reason -- a CLI route that no longer exists, a bad
// flag, an unfunded key -- which is invisible unless the exit code and
// stderr are surfaced. Log them and leave the error nil: several callers
// deliberately run commands expected to fail and assert on stderr
// themselves.
if inspect, inspectErr := s.dkrPool.Client.InspectExec(exec.ID); inspectErr == nil && inspect.ExitCode != 0 {
s.T().Logf("command exited %d: %v\nstdout: %s\nstderr: %s",
inspect.ExitCode, cmd, stdout.String(), stderr.String())
}

return stdout, stderr, nil
}

Expand Down
42 changes: 39 additions & 3 deletions x/vaas/provider/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func NewQueryCmd() *cobra.Command {
cmd.AddCommand(CmdAllConsumerFeesPerBlockOverrides())
cmd.AddCommand(CmdConsumerFeePoolClaim())
cmd.AddCommand(CmdConsumerFeePoolClaims())
cmd.AddCommand(CmdConsumerLiveness())
cmd.AddCommand(CmdPendingDowntimeSlashes())
cmd.AddCommand(CmdWithheldFeeRecords())
return cmd
Expand Down Expand Up @@ -135,7 +136,6 @@ func CmdConsumerChains() *cobra.Command {
return cmd
}

// TODO: fix naming
func CmdConsumerValidatorKeyAssignment() *cobra.Command {
bech32PrefixConsAddr := sdk.GetConfig().GetBech32ConsensusAddrPrefix()
cmd := &cobra.Command{
Expand Down Expand Up @@ -186,7 +186,6 @@ $ %s query provider validator-consumer-key 3 %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld
return cmd
}

// TODO: fix naming
func CmdProviderValidatorKey() *cobra.Command {
bech32PrefixConsAddr := sdk.GetConfig().GetBech32ConsensusAddrPrefix()
cmd := &cobra.Command{
Expand Down Expand Up @@ -571,7 +570,11 @@ func CmdConsumerFeePoolClaims() *cobra.Command {
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
fs, err := client.FlagSetWithPageKeyDecoded(cmd.Flags())
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(fs)
if err != nil {
return err
}
Expand All @@ -591,6 +594,39 @@ func CmdConsumerFeePoolClaims() *cobra.Command {
return cmd
}

// CmdConsumerLiveness queries the liveness status of a consumer chain: the last
// VSC-ack time, the grace period, the removal ETA, and whether it is degraded.
func CmdConsumerLiveness() *cobra.Command {
cmd := &cobra.Command{
Use: "consumer-liveness [consumer-id]",
Short: "Query the liveness status of a consumer chain",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)

consumerId, err := parseConsumerIdArg(args[0])
if err != nil {
return err
}
req := &types.QueryConsumerLivenessRequest{ConsumerId: consumerId}
res, err := queryClient.QueryConsumerLiveness(cmd.Context(), req)
if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}

// CmdPendingDowntimeSlashes queries the pending downtime slashes queued for a
// consumer, awaiting the challenge window before execution.
func CmdPendingDowntimeSlashes() *cobra.Command {
Expand Down
6 changes: 4 additions & 2 deletions x/vaas/provider/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ where create_consumer.json has the following structure:
"binary_hash": "",
"spawn_time": "2024-08-29T12:26:16.529913Z",
"unbonding_period": 1728000000000000,
"ccv_timeout_period": 2419200000000000,
"vaas_timeout_period": 3600000000000,
"safe_mode_threshold": 10800000000000,
"historical_entries": 10000
}
}
Expand Down Expand Up @@ -348,7 +349,8 @@ where update_consumer.json has the following structure:
"binary_hash": "",
"spawn_time": "2024-08-29T12:26:16.529913Z",
"unbonding_period": 1728000000000000,
"ccv_timeout_period": 2419200000000000,
"vaas_timeout_period": 3600000000000,
"safe_mode_threshold": 10800000000000,
"historical_entries": 10000
},
"new_chain_id": "newConsumer-1" // is optional and can be empty (i.e., "new_chain_id": "")
Expand Down