Skip to content

Commit

Permalink
Merge branch 'cosmos:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
p-offtermatt authored Jul 31, 2023
2 parents 721d488 + 1301e1d commit 5f6e6f6
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 40 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/interchaintest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,28 @@ jobs:
- name: interchaintest
run: make interchaintest-fee-middleware

fee-grant:
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.20
uses: actions/setup-go@v1
with:
go-version: 1.20
id: go

- name: checkout relayer
uses: actions/checkout@v2

- uses: actions/cache@v1
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: interchaintest
run: make interchaintest-fee-grant

scenarios:
runs-on: ubuntu-latest
steps:
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ interchaintest-misbehaviour:
interchaintest-fee-middleware:
cd interchaintest && go test -race -v -run TestRelayerFeeMiddleware .

interchaintest-fee-grant:
cd interchaintest && go test -race -v -run TestRelayerFeeGrant .

interchaintest-scenario: ## Scenario tests are suitable for simple networks of 1 validator and no full nodes. They test specific functionality.
cd interchaintest && go test -timeout 30m -race -v -run TestScenario ./...

Expand Down
35 changes: 24 additions & 11 deletions cmd/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -1070,9 +1070,10 @@ $ %s query unrelayed-acks demo-path channel-0`,

func queryClientsExpiration(a *appState) *cobra.Command {
cmd := &cobra.Command{
Use: "clients-expiration path",
Short: "query for light clients expiration date",
Args: withUsage(cobra.ExactArgs(1)),
Use: "clients-expiration path",
Aliases: []string{"ce"},
Short: "query for light clients expiration date",
Args: withUsage(cobra.ExactArgs(1)),
Example: strings.TrimSpace(fmt.Sprintf(`
$ %s query clients-expiration demo-path`,
appName,
Expand All @@ -1095,17 +1096,29 @@ $ %s query clients-expiration demo-path`,
return err
}

srcExpiration, err := relayer.QueryClientExpiration(cmd.Context(), c[src], c[dst])
if err != nil {
return err
srcExpiration, srcClientInfo, errSrc := relayer.QueryClientExpiration(cmd.Context(), c[src], c[dst])
if errSrc != nil && !strings.Contains(errSrc.Error(), "light client not found") {
return errSrc
}
dstExpiration, err := relayer.QueryClientExpiration(cmd.Context(), c[dst], c[src])
if err != nil {
return err
dstExpiration, dstClientInfo, errDst := relayer.QueryClientExpiration(cmd.Context(), c[dst], c[src])
if errDst != nil && !strings.Contains(errDst.Error(), "light client not found") {
return errDst
}

// if only the src light client is found, just print info for source light client
if errSrc == nil && errDst != nil {
fmt.Fprintln(cmd.OutOrStdout(), relayer.SPrintClientExpiration(c[src], srcExpiration, srcClientInfo))
return nil
}

// if only the dst light client is found, just print info for destination light client
if errDst == nil && errSrc != nil {
fmt.Fprintln(cmd.OutOrStdout(), relayer.SPrintClientExpiration(c[dst], dstExpiration, dstClientInfo))
return nil
}

fmt.Fprintf(cmd.OutOrStdout(), relayer.SPrintClientExpiration(c[src], srcExpiration))
fmt.Fprintf(cmd.OutOrStdout(), relayer.SPrintClientExpiration(c[dst], dstExpiration))
fmt.Fprintln(cmd.OutOrStdout(), relayer.SPrintClientExpiration(c[src], srcExpiration, srcClientInfo))
fmt.Fprintln(cmd.OutOrStdout(), relayer.SPrintClientExpiration(c[dst], dstExpiration, dstClientInfo))

return nil
},
Expand Down
8 changes: 4 additions & 4 deletions interchaintest/feegrant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ func genMnemonic(t *testing.T) string {
return mn
}

// TestScenarioFeegrantBasic Feegrant on a single chain
// Run this test with e.g. go test -timeout 300s -run ^TestScenarioFeegrantBasic$ github.com/cosmos/relayer/v2/ibctest.
// TestRelayerFeeGrant Feegrant on a single chain
// Run this test with e.g. go test -timeout 300s -run ^TestRelayerFeeGrant$ github.com/cosmos/relayer/v2/ibctest.
//
// Helpful to debug:
// docker ps -a --format {{.Names}} then e.g. docker logs gaia-1-val-0-TestScenarioFeegrantBasic 2>&1 -f
func TestScenarioFeegrantBasic(t *testing.T) {
// docker ps -a --format {{.Names}} then e.g. docker logs gaia-1-val-0-TestRelayerFeeGrant 2>&1 -f
func TestRelayerFeeGrant(t *testing.T) {
ctx := context.Background()
logger := zaptest.NewLogger(t)

Expand Down
33 changes: 21 additions & 12 deletions relayer/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,39 +272,48 @@ func QueryBalance(ctx context.Context, chain *Chain, address string, showDenoms
return out, nil
}

func QueryClientExpiration(ctx context.Context, src, dst *Chain) (time.Time, error) {
func QueryClientExpiration(ctx context.Context, src, dst *Chain) (time.Time, ClientStateInfo, error) {
latestHeight, err := src.ChainProvider.QueryLatestHeight(ctx)
if err != nil {
return time.Time{}, err
return time.Time{}, ClientStateInfo{}, err
}

clientStateRes, err := src.ChainProvider.QueryClientStateResponse(ctx, latestHeight, src.ClientID())
if err != nil {
return time.Time{}, err
return time.Time{}, ClientStateInfo{}, err
}

clientInfo, err := ClientInfoFromClientState(clientStateRes.ClientState)
if err != nil {
return time.Time{}, err
return time.Time{}, ClientStateInfo{}, err
}

clientTime, err := dst.ChainProvider.BlockTime(ctx, int64(clientInfo.LatestHeight.GetRevisionHeight()))
if err != nil {
return time.Time{}, err
return time.Time{}, ClientStateInfo{}, err
}

return clientTime.Add(clientInfo.TrustingPeriod), nil
return clientTime.Add(clientInfo.TrustingPeriod), clientInfo, nil
}

func SPrintClientExpiration(chain *Chain, expiration time.Time) string {
func SPrintClientExpiration(chain *Chain, expiration time.Time, clientInfo ClientStateInfo) string {
now := time.Now()
remainingTime := expiration.Sub(now)
expirationFormatted := expiration.Format(time.RFC822)

if remainingTime < 0 {
return fmt.Sprintf("client %s (%s) is already expired (%s)\n",
chain.ClientID(), chain.ChainID(), expirationFormatted)
var status string
if remainingTime <= 0 {
status = "EXPIRED"
} else {
status = "GOOD"
}
return fmt.Sprintf("client %s (%s) expires in %s (%s)\n",
chain.ClientID(), chain.ChainID(), remainingTime.Round(time.Second), expirationFormatted)

return fmt.Sprintf(`
client: %s (%s)
HEALTH: %s
TIME: %s (%s)
LAST UPDATE HEIGHT: %d
TRUSTING PERIOD: %s
`,
chain.ClientID(), chain.ChainID(), status, expirationFormatted, remainingTime.Round(time.Second), clientInfo.LatestHeight.GetRevisionHeight(), clientInfo.TrustingPeriod.String())
}
83 changes: 70 additions & 13 deletions relayer/query_test.go
Original file line number Diff line number Diff line change
@@ -1,76 +1,124 @@
package relayer

import (
"github.com/cosmos/relayer/v2/relayer/chains/cosmos"
"testing"
"time"

"github.com/cosmos/relayer/v2/relayer/chains/cosmos"

clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported"
"github.com/stretchr/testify/require"
)

func TestSPrintClientExpiration_PrintChainId(t *testing.T) {
previousTime := time.Now().Add(10 * time.Hour)
mockHeight := clienttypes.NewHeight(1, 100)
trustingPeriod := time.Duration(1 * time.Hour)

chain := mockChain("expected-chain-id", "test-client-id")
expiration := SPrintClientExpiration(chain, previousTime)
clientStateInfo := mockClientStateInfo("test-chain-id", trustingPeriod, mockHeight)
expiration := SPrintClientExpiration(chain, previousTime, *clientStateInfo)

require.Contains(t, expiration, "expected-chain-id")
}

func TestSPrintClientExpiration_PrintClientId(t *testing.T) {
previousTime := time.Now().Add(10 * time.Hour)
mockHeight := clienttypes.NewHeight(1, 100)
trustingPeriod := time.Duration(1 * time.Hour)

chain := mockChain("test-chain-id", "expected-client-id")
expiration := SPrintClientExpiration(chain, previousTime)
clientStateInfo := mockClientStateInfo("test-chain-id", trustingPeriod, mockHeight)
expiration := SPrintClientExpiration(chain, previousTime, *clientStateInfo)

require.Contains(t, expiration, "expected-client-id")
}

func TestSPrintClientExpiration_PrintIsAlreadyExpired_WhenTimeIsInPast(t *testing.T) {
func TestSPrintClientExpiration_PrintExpired_WhenTimeIsInPast(t *testing.T) {
previousTime := time.Now().Add(-10 * time.Hour)
mockHeight := clienttypes.NewHeight(1, 100)
trustingPeriod := time.Duration(1 * time.Hour)

chain := mockChain("test-chain-id", "test-client-id")
expiration := SPrintClientExpiration(chain, previousTime)
clientStateInfo := mockClientStateInfo("test-chain-id", trustingPeriod, mockHeight)
expiration := SPrintClientExpiration(chain, previousTime, *clientStateInfo)

require.Contains(t, expiration, "is already expired")
require.Contains(t, expiration, "EXPIRED")
}

func TestSPrintClientExpiration_PrintRFC822FormattedTime_WhenTimeIsInPast(t *testing.T) {
pastTime := time.Now().Add(-10 * time.Hour)
mockHeight := clienttypes.NewHeight(1, 100)
trustingPeriod := time.Duration(1 * time.Hour)

chain := mockChain("test-chain-id", "test-client-id")
expiration := SPrintClientExpiration(chain, pastTime)
chain := mockChain("expected-chain-id", "test-client-id")
clientStateInfo := mockClientStateInfo("test-chain-id", trustingPeriod, mockHeight)
expiration := SPrintClientExpiration(chain, pastTime, *clientStateInfo)

require.Contains(t, expiration, pastTime.Format(time.RFC822))
}

func TestSPrintClientExpiration_PrintExpiresIn_WhenTimeIsInFuture(t *testing.T) {
func TestSPrintClientExpiration_PrintGood_WhenTimeIsInFuture(t *testing.T) {
previousTime := time.Now().Add(10 * time.Hour)
mockHeight := clienttypes.NewHeight(1, 100)
trustingPeriod := time.Duration(1 * time.Hour)

chain := mockChain("test-chain-id", "test-client-id")
expiration := SPrintClientExpiration(chain, previousTime)
clientStateInfo := mockClientStateInfo("test-chain-id", trustingPeriod, mockHeight)
expiration := SPrintClientExpiration(chain, previousTime, *clientStateInfo)

require.Contains(t, expiration, "expires in")
require.Contains(t, expiration, "GOOD")
}

func TestSPrintClientExpiration_PrintRFC822FormattedTime_WhenTimeIsInFuture(t *testing.T) {
futureTime := time.Now().Add(10 * time.Hour)
mockHeight := clienttypes.NewHeight(1, 100)
trustingPeriod := time.Duration(1 * time.Hour)

chain := mockChain("test-chain-id", "test-client-id")
expiration := SPrintClientExpiration(chain, futureTime)
clientStateInfo := mockClientStateInfo("test-chain-id", trustingPeriod, mockHeight)
expiration := SPrintClientExpiration(chain, futureTime, *clientStateInfo)

require.Contains(t, expiration, futureTime.Format(time.RFC822))
}

func TestSPrintClientExpiration_PrintRemainingTime_WhenTimeIsInFuture(t *testing.T) {
futureTime := time.Now().Add(10 * time.Hour)
mockHeight := clienttypes.NewHeight(1, 100)
trustingPeriod := time.Duration(1 * time.Hour)

chain := mockChain("test-chain-id", "test-client-id")
expiration := SPrintClientExpiration(chain, futureTime)
clientStateInfo := mockClientStateInfo("test-chain-id", trustingPeriod, mockHeight)
expiration := SPrintClientExpiration(chain, futureTime, *clientStateInfo)

require.Contains(t, expiration, "10h0m0s")
}

func TestSPrintClientExpiration_TrustingPeriod(t *testing.T) {
previousTime := time.Now().Add(10 * time.Hour)
mockHeight := clienttypes.NewHeight(1, 100)
trustingPeriod := time.Duration(1 * time.Hour)

chain := mockChain("expected-chain-id", "test-client-id")
clientStateInfo := mockClientStateInfo("test-chain-id", trustingPeriod, mockHeight)
expiration := SPrintClientExpiration(chain, previousTime, *clientStateInfo)

require.Contains(t, expiration, "1h0m0s")
}

func TestSPrintClientExpiration_LastUpdateHeight(t *testing.T) {
previousTime := time.Now().Add(10 * time.Hour)
mockHeight := clienttypes.NewHeight(1, 100)
trustingPeriod := time.Duration(1 * time.Hour)

chain := mockChain("expected-chain-id", "test-client-id")
clientStateInfo := mockClientStateInfo("test-chain-id", trustingPeriod, mockHeight)
expiration := SPrintClientExpiration(chain, previousTime, *clientStateInfo)

require.Contains(t, expiration, "100")
}

func mockChain(chainId string, clientId string) *Chain {
return &Chain{
Chainid: chainId,
Expand All @@ -85,3 +133,12 @@ func mockChain(chainId string, clientId string) *Chain {
},
}
}

func mockClientStateInfo(chainID string, trustingPeriod time.Duration, latestHeight ibcexported.Height) *ClientStateInfo {
mockHeight := clienttypes.NewHeight(1, 100)
return &ClientStateInfo{
ChainID: chainID,
TrustingPeriod: time.Duration(1 * time.Hour),
LatestHeight: mockHeight,
}
}

0 comments on commit 5f6e6f6

Please sign in to comment.