Skip to content

Commit

Permalink
add interchainquery module (#432)
Browse files Browse the repository at this point in the history
* add icq module

* lint

* add interface

* .

* uncomment test

---------

Co-authored-by: themandalore <[email protected]>
  • Loading branch information
akremstudy and themandalore authored Nov 13, 2024
1 parent 032163d commit cefdcfe
Show file tree
Hide file tree
Showing 7 changed files with 287 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ test:
@go test -v ./... -short

e2e:
@cd e2e && go test -v ./... -timeout 20m
@cd e2e && go test -v -race ./... -timeout 20m

.PHONY: test e2e
###############################################################################
Expand Down
26 changes: 25 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import (
tmos "github.com/cometbft/cometbft/libs/os"
dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/gogoproto/proto"
icq "github.com/cosmos/ibc-apps/modules/async-icq/v8"
icqkeeper "github.com/cosmos/ibc-apps/modules/async-icq/v8/keeper"
icqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v8/types"
"github.com/cosmos/ibc-go/modules/capability"
capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper"
capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types"
Expand Down Expand Up @@ -174,6 +177,7 @@ var (
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
icqtypes.ModuleName: nil,
oraclemoduletypes.ModuleName: {authtypes.Minter, authtypes.Burner, authtypes.Staking},
disputemoduletypes.ModuleName: {authtypes.Minter, authtypes.Burner, authtypes.Staking},
bridgemoduletypes.ModuleName: {authtypes.Minter, authtypes.Burner},
Expand Down Expand Up @@ -227,6 +231,7 @@ type App struct {
GovKeeper govkeeper.Keeper
UpgradeKeeper *upgradekeeper.Keeper
IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly
ICQKeeper icqkeeper.Keeper
EvidenceKeeper evidencekeeper.Keeper
TransferKeeper ibctransferkeeper.Keeper
ICAHostKeeper icahostkeeper.Keeper
Expand All @@ -238,6 +243,7 @@ type App struct {
ScopedIBCKeeper capabilitykeeper.ScopedKeeper
ScopedTransferKeeper capabilitykeeper.ScopedKeeper
ScopedICAHostKeeper capabilitykeeper.ScopedKeeper
ScopedICQKeeper capabilitykeeper.ScopedKeeper

OracleKeeper oraclemodulekeeper.Keeper

Expand Down Expand Up @@ -319,6 +325,7 @@ func New(
bridgemoduletypes.StoreKey,
reportermoduletypes.StoreKey,
globalfeetypes.StoreKey,
icqtypes.StoreKey,
// this line is used by starport scaffolding # stargate/app/storeKey
)

Expand Down Expand Up @@ -357,6 +364,7 @@ func New(
scopedICAControllerKeeper := app.CapabilityKeeper.ScopeToModule(icacontrollertypes.SubModuleName)
scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName)
scopedICAHostKeeper := app.CapabilityKeeper.ScopeToModule(icahosttypes.SubModuleName)
scopedICQKeeper := app.CapabilityKeeper.ScopeToModule(icqtypes.ModuleName)
// this line is used by starport scaffolding # stargate/app/scopedKeeper

// add keepers
Expand Down Expand Up @@ -522,7 +530,18 @@ func New(
)

icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper)

// ICQ Keeper
app.ICQKeeper = icqkeeper.NewKeeper(
appCodec,
app.keys[icqtypes.StoreKey],
app.IBCKeeper.ChannelKeeper, // may be replaced with middleware
app.IBCKeeper.ChannelKeeper,
app.IBCKeeper.PortKeeper,
scopedICQKeeper,
bApp.GRPCQueryRouter(),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
icqModule := icq.NewIBCModule(app.ICQKeeper)
// Create evidence Keeper for to register the IBC light client misbehavior evidence route
evidenceKeeper := evidencekeeper.NewKeeper(
appCodec,
Expand Down Expand Up @@ -719,6 +738,7 @@ func New(
ibcRouter := ibcporttypes.NewRouter()
ibcRouter.AddRoute(icahosttypes.SubModuleName, icaHostIBCModule)
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferIBCModule)
ibcRouter.AddRoute(icqtypes.ModuleName, icqModule)
app.IBCKeeper.SetRouter(ibcRouter)

/**** Module Hooks ****/
Expand Down Expand Up @@ -789,6 +809,7 @@ func New(
ibc.NewAppModule(app.IBCKeeper),
transfer.NewAppModule(app.TransferKeeper),
ica.NewAppModule(&icaControllerKeeper, &app.ICAHostKeeper),
icqcustomModule{icq.NewAppModule(app.ICQKeeper, nil)},
// this line is used by starport scaffolding # stargate/app/appModule
)

Expand Down Expand Up @@ -842,6 +863,7 @@ func New(
govtypes.ModuleName,
stakingtypes.ModuleName,
ibctransfertypes.ModuleName,
icqtypes.ModuleName,
ibcexported.ModuleName,
icatypes.ModuleName,
capabilitytypes.ModuleName,
Expand Down Expand Up @@ -882,6 +904,7 @@ func New(
minttypes.ModuleName,
genutiltypes.ModuleName,
ibctransfertypes.ModuleName,
icqtypes.ModuleName,
ibcexported.ModuleName,
icatypes.ModuleName,
evidencetypes.ModuleName,
Expand Down Expand Up @@ -946,6 +969,7 @@ func New(

app.ScopedIBCKeeper = scopedIBCKeeper
app.ScopedTransferKeeper = scopedTransferKeeper
app.ScopedICQKeeper = scopedICQKeeper
// this line is used by starport scaffolding # stargate/app/beforeInitReturn

return app
Expand Down
14 changes: 14 additions & 0 deletions app/default_overrides.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package app
import (
"encoding/json"

icq "github.com/cosmos/ibc-apps/modules/async-icq/v8"
icqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v8/types"
"github.com/strangelove-ventures/globalfee/x/globalfee"
globalfeetypes "github.com/strangelove-ventures/globalfee/x/globalfee/types"

Expand Down Expand Up @@ -103,3 +105,15 @@ func (globalFeeModule) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {

return cdc.MustMarshalJSON(genState)
}

type icqcustomModule struct {
icq.AppModule
}

// DefaultGenesis returns custom x/globalfee module genesis state.
func (icqcustomModule) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
genState := icqtypes.DefaultGenesis()
genState.Params.AllowQueries = []string{"/layer.oracle.Query/GetCurrentAggregateReport"}

return cdc.MustMarshalJSON(genState)
}
232 changes: 232 additions & 0 deletions e2e/icq_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
package e2e_test

import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"testing"

"github.com/strangelove-ventures/interchaintest/v8"
"github.com/strangelove-ventures/interchaintest/v8/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v8/ibc"
"github.com/strangelove-ventures/interchaintest/v8/relayer"
"github.com/strangelove-ventures/interchaintest/v8/testreporter"
"github.com/strangelove-ventures/interchaintest/v8/testutil"
"github.com/stretchr/testify/require"
"github.com/tellor-io/layer/e2e"
"github.com/tellor-io/layer/utils"
"go.uber.org/zap/zaptest"

"cosmossdk.io/math"

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

func TestIbcInterchainQuery(t *testing.T) {
if testing.Short() {
t.Skip("skipping in short mode")
}

cosmos.SetSDKConfig("tellor")

rep := testreporter.NewNopReporter()
eRep := rep.RelayerExecReporter(t)

ctx := context.Background()

client, network := interchaintest.DockerSetup(t)

modifyGenesis := []cosmos.GenesisKV{
cosmos.NewGenesisKV("app_state.dispute.params.team_address", sdk.MustAccAddressFromBech32("tellor14ncp4jg0d087l54pwnp8p036s0dc580xy4gavf").Bytes()),
cosmos.NewGenesisKV("consensus.params.abci.vote_extensions_enable_height", "1"),
cosmos.NewGenesisKV("app_state.gov.params.voting_period", "15s"),
cosmos.NewGenesisKV("app_state.gov.params.max_deposit_period", "10s"),
cosmos.NewGenesisKV("app_state.gov.params.min_deposit.0.denom", "loya"),
cosmos.NewGenesisKV("app_state.gov.params.min_deposit.0.amount", "1"),
cosmos.NewGenesisKV("app_state.globalfee.params.minimum_gas_prices.0.amount", "0.0"),
}
nv := 1
nf := 0
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
{
NumValidators: &nv,
NumFullNodes: &nf,
ChainConfig: ibc.ChainConfig{
Type: "cosmos",
Name: "layer",
ChainID: "layer",
Bin: "layerd",
Denom: "loya",
Bech32Prefix: "tellor",
CoinType: "118",
GasPrices: "0.0loya",
GasAdjustment: 1.1,
TrustingPeriod: "504h",
NoHostMount: false,
Images: []ibc.DockerImage{
{
Repository: "ghcr.io/akremstudy/layer-icq", // source code ibc branch
Version: "latest",
UidGid: "1025:1025",
},
},
EncodingConfig: e2e.LayerEncoding(),
ModifyGenesis: cosmos.ModifyGenesis(modifyGenesis),
AdditionalStartArgs: []string{"--key-name", "validator", "--price-daemon-enabled=false"},
},
},
{
NumValidators: &nv,
NumFullNodes: &nf,
ChainConfig: ibc.ChainConfig{
Type: "cosmos",
Name: "layer",
ChainID: "layer-receiver",
Bin: "layerd",
Denom: "loya",
Bech32Prefix: "tellor",
CoinType: "118",
GasPrices: "0.0loya",
GasAdjustment: 1.1,
TrustingPeriod: "504h",
NoHostMount: false,
Images: []ibc.DockerImage{
{
Repository: "layer",
Version: "local",
UidGid: "1025:1025",
},
},
EncodingConfig: e2e.LayerEncoding(),
ModifyGenesis: cosmos.ModifyGenesis(modifyGenesis),
AdditionalStartArgs: []string{"--key-name", "validator", "--price-daemon-enabled=false"},
},
},
})

chains, err := cf.Chains(t.Name())
require.NoError(t, err)

layer1, layer2 := chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain)

r := interchaintest.NewBuiltinRelayerFactory(
ibc.CosmosRly,
zaptest.NewLogger(t),
relayer.StartupFlags("-b", "100"),
).Build(t, client, network)

const pathName = "layer1-layer2"
const relayerName = "relayer"

ic := interchaintest.NewInterchain().
AddChain(layer1).
AddChain(layer2).
AddRelayer(r, relayerName).
AddLink(interchaintest.InterchainLink{
Chain1: layer1,
Chain2: layer2,
Relayer: r,
Path: pathName,
CreateClientOpts: ibc.CreateClientOptions{},
CreateChannelOpts: ibc.CreateChannelOptions{
SourcePortName: "oracle",
DestPortName: "icqhost",
Order: ibc.Unordered,
Version: "icq-1",
},
})

require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{
TestName: t.Name(),
Client: client,
NetworkID: network,

SkipPathCreation: false,
}))

t.Cleanup(func() {
_ = ic.Close()
})

layer2validator := layer2.Validators[0]

valAddress, err := layer2validator.AccountKeyBech32(ctx, "validator")
require.NoError(t, err)

// create reporter
_, err = layer2.GetNode().ExecTx(ctx, "validator", "reporter", "create-reporter", math.NewUint(0).String(), math.NewUint(1_000_000).String(), "--keyring-dir", layer2.HomeDir())
require.NoError(t, err)

// tip query
_, err = layer2validator.ExecTx(ctx, "validator", "oracle", "tip", valAddress, qData, "1000000loya", "--keyring-dir", layer2.HomeDir())
require.NoError(t, err)

// submit value
_, err = layer2validator.ExecTx(ctx, "validator", "oracle", "submit-value", valAddress, qData, value, "--keyring-dir", layer2.HomeDir())
require.NoError(t, err)

// Query for the recently created channel-id.
channels, err := r.GetChannels(ctx, eRep, layer1.Config().ChainID)
require.NoError(t, err)

// Start the relayer and set the cleanup function.
err = r.StartRelayer(ctx, eRep, pathName)
require.NoError(t, err)

t.Cleanup(func() {
err := r.StopRelayer(ctx, eRep)
if err != nil {
t.Logf("an error occurred while stopping the relayer: %s", err)
}
})

err = testutil.WaitForBlocks(ctx, 5, layer1, layer2)
require.NoError(t, err)

chanID := channels[0].Counterparty.ChannelID
require.NotEmpty(t, chanID)

// get aggreate report
qidbz, err := utils.QueryIDFromDataString(qData)
require.NoError(t, err)

cmd := []string{
"layerd", "tx", "oracle", "send-query-get-current-aggregated-report", chanID, hex.EncodeToString(qidbz),
"--node", layer1.GetRPCAddress(),
"--home", layer1.HomeDir(),
"--chain-id", layer1.Config().ChainID,
"--from", "validator",
"--gas", "1000000",
"--fees", "1000000loya",
"--keyring-dir", layer1.HomeDir(),
"--keyring-backend", keyring.BackendTest,
"-y",
}

// Execute interchain query
stdout, _, err := layer1.Exec(ctx, cmd, nil)
require.NoError(t, err)
fmt.Println(string(stdout))

err = testutil.WaitForBlocks(ctx, 10, layer1, layer2)
require.NoError(t, err)
cmd = []string{
"layerd", "query", "oracle", "query-state", "--sequence", "1",
"--node", layer1.GetRPCAddress(),
"--home", layer1.HomeDir(),
"--chain-id", layer1.Config().ChainID,
"--output", "json",
}

response, _, err := layer1.Exec(ctx, cmd, nil)
fmt.Println(string(response), "response")
require.NoError(t, err)
// Validate response
var aggReport AggregateReport
err = json.Unmarshal(response, &aggReport)
require.NoError(t, err)
fmt.Println("Aggregate report: ", aggReport)
require.Equal(t, aggReport.Aggregate.AggregateReporter, valAddress)
}
Loading

0 comments on commit cefdcfe

Please sign in to comment.