Skip to content

Commit

Permalink
feat: add ExposeAdditionalPorts config option (#1098)
Browse files Browse the repository at this point in the history
for cosmos chains, ExposeAdditionalPorts takes a list of port ids that
will be exposed on all validators and full nodes for the chains on
random host ports.

extends the ethermint test by exposing the EVM & verifying the port
actually gets exposed.
  • Loading branch information
pirtleshell authored Apr 24, 2024
1 parent 9c6cfa3 commit 3428d39
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 5 deletions.
16 changes: 16 additions & 0 deletions chain/cosmos/chain_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,9 @@ func (tn *ChainNode) CreateNodeContainer(ctx context.Context) error {
for k, v := range sentryPorts {
usingPorts[k] = v
}
for _, port := range chainCfg.ExposeAdditionalPorts {
usingPorts[nat.Port(port)] = []nat.PortBinding{}
}

// to prevent port binding conflicts, host port overrides are only exposed on the first validator node.
if tn.Validator && tn.Index == 0 && chainCfg.HostPortOverride != nil {
Expand Down Expand Up @@ -1377,3 +1380,16 @@ func (tn *ChainNode) SendICABankTransfer(ctx context.Context, connectionID, from
_, err := tn.SendICATx(ctx, fromAddr, connectionID, ir, msgs, icaTxMemo, "proto3")
return err
}

// GetHostAddress returns the host-accessible url for a port in the container.
// This is useful for finding the url & random host port for ports exposed via ChainConfig.ExposeAdditionalPorts
func (tn *ChainNode) GetHostAddress(ctx context.Context, portID string) (string, error) {
ports, err := tn.containerLifecycle.GetHostPorts(ctx, portID)
if err != nil {
return "", err
}
if len(ports) == 0 || ports[0] == "" {
return "", fmt.Errorf("no port with id '%s' found", portID)
}
return "http://" + ports[0], nil
}
4 changes: 4 additions & 0 deletions chainspec.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ func (s *ChainSpec) Config(log *zap.Logger) (*ibc.ChainConfig, error) {
}
}

if len(s.ExposeAdditionalPorts) > 0 {
s.ChainConfig.ExposeAdditionalPorts = append(s.ChainConfig.ExposeAdditionalPorts, s.ExposeAdditionalPorts...)
}

// s.Name and chainConfig.Name are interchangeable
if s.Name == "" && s.ChainConfig.Name != "" {
s.Name = s.ChainConfig.Name
Expand Down
40 changes: 35 additions & 5 deletions examples/cosmos/ethermint_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package cosmos_test

import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"testing"
"time"

Expand All @@ -11,6 +15,7 @@ import (
"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/testutil"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
)
Expand All @@ -27,9 +32,6 @@ func TestEthermintChain(t *testing.T) {
t.Skip("skipping in short mode")
}

numVals := 1
numFullNodes := 0

cosmos.SetSDKConfig(wallet)

genesis := []cosmos.GenesisKV{
Expand Down Expand Up @@ -83,6 +85,11 @@ func TestEthermintChain(t *testing.T) {
}),
}

jsonRpcOverrides := make(testutil.Toml)
jsonRpcOverrides["address"] = "0.0.0.0:8545"
appTomlOverrides := make(testutil.Toml)
appTomlOverrides["json-rpc"] = jsonRpcOverrides

decimals := int64(decimals)
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
{
Expand All @@ -100,9 +107,10 @@ func TestEthermintChain(t *testing.T) {
TrustingPeriod: "168h0m0s",
ModifyGenesis: cosmos.ModifyGenesis(genesis),
CoinDecimals: &decimals,
// open the port for the EVM on all nodes
ExposeAdditionalPorts: []string{"8545/tcp"},
ConfigFileOverrides: map[string]any{"config/app.toml": appTomlOverrides},
},
NumValidators: &numVals,
NumFullNodes: &numFullNodes,
},
})

Expand Down Expand Up @@ -133,6 +141,28 @@ func TestEthermintChain(t *testing.T) {
balance, err := chain.GetNode().Chain.GetBalance(ctx, user.FormattedAddress(), denom)
require.NoError(t, err)
require.Equal(t, "10000000000", balance.String())

// verify access to port exposed via ExposeAdditionalPorts
evmJsonRpcUrl, err := chain.FullNodes[0].GetHostAddress(ctx, "8545/tcp")
require.NoError(t, err)

data := []byte(`{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["0x1", null]}`)
resp, err := http.Post(evmJsonRpcUrl, "application/json", bytes.NewBuffer(data))
require.NoError(t, err)
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
require.NoError(t, err)

response := struct {
Result struct {
Number string `json:"number"`
} `json:"result"`
}{}
err = json.Unmarshal(body, &response)
require.NoError(t, err)

require.Equal(t, "0x1", response.Result.Number)
}

type evmEpoch struct {
Expand Down
11 changes: 11 additions & 0 deletions ibc/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ type ChainConfig struct {
// HostPortOverride exposes ports to the host.
// To avoid port binding conflicts, ports are only exposed on the 0th validator.
HostPortOverride map[int]int `yaml:"host-port-override"`
// ExposeAdditionalPorts exposes each port id to the host on a random port. ex: "8080/tcp"
// Access the address with ChainNode.GetHostAddress
ExposeAdditionalPorts []string
// Additional start command arguments
AdditionalStartArgs []string
// Environment variables for chain nodes
Expand All @@ -84,6 +87,10 @@ func (c ChainConfig) Clone() ChainConfig {
copy(sidecars, c.SidecarConfigs)
x.SidecarConfigs = sidecars

additionalPorts := make([]string, len(c.ExposeAdditionalPorts))
copy(additionalPorts, c.ExposeAdditionalPorts)
x.ExposeAdditionalPorts = additionalPorts

if c.CoinDecimals != nil {
coinDecimals := *c.CoinDecimals
x.CoinDecimals = &coinDecimals
Expand Down Expand Up @@ -206,6 +213,10 @@ func (c ChainConfig) MergeChainSpecConfig(other ChainConfig) ChainConfig {
c.Env = append(c.Env, other.Env...)
}

if len(other.ExposeAdditionalPorts) > 0 {
c.ExposeAdditionalPorts = append(c.ExposeAdditionalPorts, other.ExposeAdditionalPorts...)
}

return c
}

Expand Down

0 comments on commit 3428d39

Please sign in to comment.