Skip to content

Commit

Permalink
Merge branch 'main' into carlos/rename-codehash-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
crodriguezvega authored Nov 20, 2023
2 parents fc64b79 + 482b6b2 commit 41df919
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 14 deletions.
Binary file added e2e/tests/wasm/contracts/ics10_grandpa_cw.wasm
Binary file not shown.
Binary file not shown.
File renamed without changes.
File renamed without changes.
133 changes: 127 additions & 6 deletions e2e/tests/wasm/grandpa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (
"github.com/cosmos/ibc-go/e2e/testvalues"
wasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types"
transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported"
)

const (
Expand Down Expand Up @@ -86,7 +88,7 @@ func (s *GrandpaTestSuite) TestMsgTransfer_Succeeds_GrandpaContract() {

cosmosWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount)

file, err := os.Open("../data/ics10_grandpa_cw.wasm.gz")
file, err := os.Open("contracts/ics10_grandpa_cw.wasm")
s.Require().NoError(err)

checksum := s.PushNewWasmClientProposal(ctx, cosmosChain, cosmosWallet, file)
Expand Down Expand Up @@ -234,7 +236,7 @@ func (s *GrandpaTestSuite) TestMsgMigrateContract_Success_GrandpaContract() {

cosmosWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount)

file, err := os.Open("../data/ics10_grandpa_cw.wasm.gz")
file, err := os.Open("contracts/ics10_grandpa_cw.wasm")
s.Require().NoError(err)

checksum := s.PushNewWasmClientProposal(ctx, cosmosChain, cosmosWallet, file)
Expand Down Expand Up @@ -266,7 +268,7 @@ func (s *GrandpaTestSuite) TestMsgMigrateContract_Success_GrandpaContract() {

// This contract is a dummy contract that will always succeed migration.
// Other entry points are unimplemented.
migrateFile, err := os.Open("../data/migrate_success.wasm.gz")
migrateFile, err := os.Open("contracts/migrate_success.wasm.gz")
s.Require().NoError(err)

// First Store the code
Expand Down Expand Up @@ -321,9 +323,8 @@ func (s *GrandpaTestSuite) TestMsgMigrateContract_ContractError_GrandpaContract(

cosmosWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount)

file, err := os.Open("../data/ics10_grandpa_cw.wasm.gz")
file, err := os.Open("contracts/ics10_grandpa_cw.wasm")
s.Require().NoError(err)

checksum := s.PushNewWasmClientProposal(ctx, cosmosChain, cosmosWallet, file)

s.Require().NotEmpty(checksum, "checksum was empty but should not have been")
Expand Down Expand Up @@ -353,7 +354,7 @@ func (s *GrandpaTestSuite) TestMsgMigrateContract_ContractError_GrandpaContract(

// This contract is a dummy contract that will always fail migration.
// Other entry points are unimplemented.
migrateFile, err := os.Open("../data/migrate_error.wasm.gz")
migrateFile, err := os.Open("contracts/migrate_error.wasm.gz")
s.Require().NoError(err)

// First Store the code
Expand All @@ -376,6 +377,114 @@ func (s *GrandpaTestSuite) TestMsgMigrateContract_ContractError_GrandpaContract(
s.Require().ErrorContains(err, "migration not supported")
}

// TestRecoverClient_Succeeds_GrandpaContract features:
// * setup cosmos and polkadot substrates nodes
// * funds test user wallets on both chains
// * stores a wasm client contract on the cosmos chain
// * creates a subject client using the hyperspace relayer
// * waits the expiry period and asserts the subject client status has expired
// * creates a substitute client using the hyperspace relayer
// * executes a gov proposal to recover the expired client
// * asserts the status of the subject client has been restored to active
// NOTE: The testcase features a modified grandpa client contract compiled as:
// - ics10_grandpa_cw_expiry.wasm.gz
// This contract modifies the unbonding period to 1600s with the trusting period being calculated as (unbonding period / 3).
func (s *GrandpaTestSuite) TestRecoverClient_Succeeds_GrandpaContract() {
ctx := context.Background()

// set the trusting period to a value which will still be valid upon client creation, but invalid before the first update
// the contract uses 1600s as the unbonding period with the trusting period evaluating to (unbonding period / 3)
var modifiedTrustingPeriod = (1600 * time.Second) / 3

chainA, chainB := s.GetGrandpaTestChains()

polkadotChain := chainA.(*polkadot.PolkadotChain)
cosmosChain := chainB.(*cosmos.CosmosChain)

// we explicitly skip path creation as the contract needs to be uploaded before we can create clients.
r := s.ConfigureRelayer(ctx, polkadotChain, cosmosChain, nil, func(options *interchaintest.InterchainBuildOptions) {
options.SkipPathCreation = true
})

s.InitGRPCClients(cosmosChain)

cosmosWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount)

file, err := os.Open("contracts/ics10_grandpa_cw_expiry.wasm.gz")
s.Require().NoError(err)

codeHash := s.PushNewWasmClientProposal(ctx, cosmosChain, cosmosWallet, file)
s.Require().NotEmpty(codeHash, "codehash was empty but should not have been")

eRep := s.GetRelayerExecReporter()

// Set client contract hash in cosmos chain config
err = r.SetClientContractHash(ctx, eRep, cosmosChain.Config(), codeHash)
s.Require().NoError(err)

// Ensure parachain has started (starts 1 session/epoch after relay chain)
err = testutil.WaitForBlocks(ctx, 1, polkadotChain)
s.Require().NoError(err, "polkadot chain failed to make blocks")

// Fund users on both cosmos and parachain, mints Asset 1 for Alice
fundAmount := int64(12_333_000_000_000)
_, cosmosUser := s.fundUsers(ctx, fundAmount, polkadotChain, cosmosChain)

pathName := s.GetPathName(0)
err = r.GeneratePath(ctx, eRep, cosmosChain.Config().ChainID, polkadotChain.Config().ChainID, pathName)
s.Require().NoError(err)

// create client pair with subject (bad trusting period)
subjectClientID := clienttypes.FormatClientIdentifier(ibcexported.Wasm, 0)
// TODO: The hyperspace relayer makes no use of create client opts
// https://github.com/strangelove-ventures/interchaintest/blob/main/relayer/hyperspace/hyperspace_commander.go#L83
s.SetupClients(ctx, r, ibc.CreateClientOptions{
TrustingPeriod: modifiedTrustingPeriod.String(), // NOTE: this is hardcoded within the cw contract: ics10_grapnda_cw_expiry.wasm
})

// wait for block
err = testutil.WaitForBlocks(ctx, 1, cosmosChain, polkadotChain)
s.Require().NoError(err)

// wait the bad trusting period
time.Sleep(modifiedTrustingPeriod)

// create client pair with substitue
substituteClientID := clienttypes.FormatClientIdentifier(ibcexported.Wasm, 1)
s.SetupClients(ctx, r, ibc.DefaultClientOpts())

// wait for block
err = testutil.WaitForBlocks(ctx, 1, cosmosChain, polkadotChain)
s.Require().NoError(err)

// ensure subject client is expired
status, err := s.clientStatus(ctx, cosmosChain, subjectClientID)
s.Require().NoError(err)
s.Require().Equal(ibcexported.Expired.String(), status, "unexpected subject client status")

// ensure substitute client is active
status, err = s.clientStatus(ctx, cosmosChain, substituteClientID)
s.Require().NoError(err)
s.Require().Equal(ibcexported.Active.String(), status, "unexpected substitute client status")

// create and execute a client recovery proposal
authority, err := s.QueryModuleAccountAddress(ctx, govtypes.ModuleName, cosmosChain)
s.Require().NoError(err)
msgRecoverClient := clienttypes.NewMsgRecoverClient(authority.String(), subjectClientID, substituteClientID)
s.Require().NotNil(msgRecoverClient)
s.ExecuteAndPassGovV1Proposal(ctx, msgRecoverClient, cosmosChain, cosmosUser)

// ensure subject client is active
status, err = s.clientStatus(ctx, cosmosChain, subjectClientID)
s.Require().NoError(err)
s.Require().Equal(ibcexported.Active.String(), status)

// ensure substitute client is active
status, err = s.clientStatus(ctx, cosmosChain, substituteClientID)
s.Require().NoError(err)
s.Require().Equal(ibcexported.Active.String(), status)
}

// extractChecksumFromGzippedContent takes a gzipped wasm contract and returns the checksum.
func (s *GrandpaTestSuite) extractChecksumFromGzippedContent(zippedContent []byte) string {
content, err := wasmtypes.Uncompress(zippedContent, wasmtypes.MaxWasmByteSize())
Expand Down Expand Up @@ -410,6 +519,18 @@ func (s *GrandpaTestSuite) PushNewWasmClientProposal(ctx context.Context, chain
return actualChecksum
}

func (s *GrandpaTestSuite) clientStatus(ctx context.Context, chain ibc.Chain, clientID string) (string, error) {
queryClient := s.GetChainGRCPClients(chain).ClientQueryClient
res, err := queryClient.ClientStatus(ctx, &clienttypes.QueryClientStatusRequest{
ClientId: clientID,
})
if err != nil {
return "", err
}

return res.Status, nil
}

func (s *GrandpaTestSuite) fundUsers(ctx context.Context, fundAmount int64, polkadotChain ibc.Chain, cosmosChain ibc.Chain) (ibc.Wallet, ibc.Wallet) {
users := interchaintest.GetAndFundTestUsers(s.T(), ctx, "user", fundAmount, polkadotChain, cosmosChain)
polkadotUser, cosmosUser := users[0], users[1]
Expand Down
4 changes: 2 additions & 2 deletions modules/light-clients/08-wasm/types/client_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func (cs ClientState) VerifyMembership(
Value: value,
},
}
_, err := wasmSudo[EmptyResult](ctx, cdc, payload, clientStore, &cs)
_, err := wasmSudo[EmptyResult](ctx, cdc, clientStore, &cs, payload)
return err
}

Expand Down Expand Up @@ -212,6 +212,6 @@ func (cs ClientState) VerifyNonMembership(
Path: merklePath,
},
}
_, err := wasmSudo[EmptyResult](ctx, cdc, payload, clientStore, &cs)
_, err := wasmSudo[EmptyResult](ctx, cdc, clientStore, &cs, payload)
return err
}
2 changes: 1 addition & 1 deletion modules/light-clients/08-wasm/types/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func WasmQuery[T ContractResult](ctx sdk.Context, clientStore storetypes.KVStore

// WasmSudo wraps wasmCall and is used solely for testing.
func WasmSudo[T ContractResult](ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, cs *ClientState, payload SudoMsg) (T, error) {
return wasmSudo[T](ctx, cdc, payload, clientStore, cs)
return wasmSudo[T](ctx, cdc, clientStore, cs, payload)
}

// WasmInstantiate wraps wasmInstantiate and is used solely for testing.
Expand Down
2 changes: 1 addition & 1 deletion modules/light-clients/08-wasm/types/proposal_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ func (cs ClientState) CheckSubstituteAndUpdateState(ctx sdk.Context, cdc codec.B
MigrateClientStore: &MigrateClientStoreMsg{},
}

_, err := wasmSudo[EmptyResult](ctx, cdc, payload, store, &cs)
_, err := wasmSudo[EmptyResult](ctx, cdc, store, &cs, payload)
return err
}
4 changes: 2 additions & 2 deletions modules/light-clients/08-wasm/types/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (cs ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, client
UpdateState: &UpdateStateMsg{ClientMessage: clientMessage},
}

result, err := wasmSudo[UpdateStateResult](ctx, cdc, payload, clientStore, &cs)
result, err := wasmSudo[UpdateStateResult](ctx, cdc, clientStore, &cs, payload)
if err != nil {
panic(err)
}
Expand All @@ -68,7 +68,7 @@ func (cs ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.Binar
UpdateStateOnMisbehaviour: &UpdateStateOnMisbehaviourMsg{ClientMessage: clientMessage},
}

_, err := wasmSudo[EmptyResult](ctx, cdc, payload, clientStore, &cs)
_, err := wasmSudo[EmptyResult](ctx, cdc, clientStore, &cs, payload)
if err != nil {
panic(err)
}
Expand Down
2 changes: 1 addition & 1 deletion modules/light-clients/08-wasm/types/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ func (cs ClientState) VerifyUpgradeAndUpdateState(
},
}

_, err := wasmSudo[EmptyResult](ctx, cdc, payload, clientStore, &cs)
_, err := wasmSudo[EmptyResult](ctx, cdc, clientStore, &cs, payload)
return err
}
2 changes: 1 addition & 1 deletion modules/light-clients/08-wasm/types/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func wasmInstantiate(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storety
// - the response of the contract call contains non-empty events
// - the response of the contract call contains non-empty attributes
// - the data bytes of the response cannot be unmarshaled into the result type
func wasmSudo[T ContractResult](ctx sdk.Context, cdc codec.BinaryCodec, payload SudoMsg, clientStore storetypes.KVStore, cs *ClientState) (T, error) {
func wasmSudo[T ContractResult](ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, cs *ClientState, payload SudoMsg) (T, error) {
var result T

encodedData, err := json.Marshal(payload)
Expand Down

0 comments on commit 41df919

Please sign in to comment.