Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: faucet api, auth key, GetHostPeerAddress #919

Closed
wants to merge 6 commits into from
Closed
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
5 changes: 3 additions & 2 deletions chain/cosmos/chain_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ type ChainNode struct {
hostRPCPort string
hostAPIPort string
hostGRPCPort string
hostP2PPort string
}

func NewChainNode(log *zap.Logger, validator bool, chain *CosmosChain, dockerClient *dockerclient.Client, networkID string, testName string, image ibc.DockerImage, index int) *ChainNode {
Expand Down Expand Up @@ -1314,11 +1315,11 @@ func (tn *ChainNode) StartContainer(ctx context.Context) error {
}

// Set the host ports once since they will not change after the container has started.
hostPorts, err := tn.containerLifecycle.GetHostPorts(ctx, rpcPort, grpcPort, apiPort)
hostPorts, err := tn.containerLifecycle.GetHostPorts(ctx, rpcPort, grpcPort, apiPort, p2pPort)
if err != nil {
return err
}
tn.hostRPCPort, tn.hostGRPCPort, tn.hostAPIPort = hostPorts[0], hostPorts[1], hostPorts[2]
tn.hostRPCPort, tn.hostGRPCPort, tn.hostAPIPort, tn.hostP2PPort = hostPorts[0], hostPorts[1], hostPorts[2], hostPorts[3]

err = tn.NewClient("tcp://" + tn.hostRPCPort)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions chain/cosmos/cosmos_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,12 @@ func (c *CosmosChain) GetHostGRPCAddress() string {
return c.getFullNode().hostGRPCPort
}

// GetHostP2PAddress returns the address of the P2P server accessible by the host.
// This will not return a valid address until the chain has been started.
func (c *CosmosChain) GetHostPeerAddress() string {
return c.getFullNode().hostP2PPort
}

// HomeDir implements ibc.Chain.
func (c *CosmosChain) HomeDir() string {
return c.getFullNode().HomeDir()
Expand Down
10 changes: 7 additions & 3 deletions chain/ethereum/unimplemented.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package ethereum
import (
"context"
"runtime"

"github.com/strangelove-ventures/interchaintest/v8/ibc"
)

func PanicFunctionName() {
pc, _, _, _ := runtime. Caller(1)
pc, _, _, _ := runtime.Caller(1)
panic(runtime.FuncForPC(pc).Name() + " not implemented")
}

Expand All @@ -27,6 +27,10 @@ func (c *EthereumChain) GetHostGRPCAddress() string {
return ""
}

func (*EthereumChain) GetHostPeerAddress() string {
PanicFunctionName()
return ""
}

// cast wallet import requires a password prompt which docker isn't properly handling. For now, we only use CreateKey().
func (c *EthereumChain) RecoverKey(ctx context.Context, keyName, mnemonic string) error {
Expand Down Expand Up @@ -64,4 +68,4 @@ func (c *EthereumChain) Timeouts(ctx context.Context, height uint64) ([]ibc.Pack
func (c *EthereumChain) BuildRelayerWallet(ctx context.Context, keyName string) (ibc.Wallet, error) {
PanicFunctionName()
return nil, nil
}
}
5 changes: 5 additions & 0 deletions chain/penumbra/penumbra_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ func (c *PenumbraChain) GetGRPCAddress() string {
return fmt.Sprintf("%s:9090", c.getFullNode().TendermintNode.HostName())
}

// Implements Chain interface
func (c *PenumbraChain) GetHostPeerAddress() string {
panic("NOT IMPLEMENTED")
}

// GetHostRPCAddress returns the address of the RPC server accessible by the host.
// This will not return a valid address until the chain has been started.
func (c *PenumbraChain) GetHostRPCAddress() string {
Expand Down
5 changes: 5 additions & 0 deletions chain/polkadot/polkadot_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,11 @@ func (c *PolkadotChain) GetGRPCAddress() string {
return fmt.Sprintf("%s:%s", c.RelayChainNodes[0].HostName(), strings.Split(wsPort, "/")[0])
}

// Implements Chain interface
func (c *PolkadotChain) GetHostPeerAddress() string {
panic("NOT IMPLEMENTED")
}

// GetHostRPCAddress returns the rpc address that can be reached by processes on the host machine.
// Note that this will not return a valid value until after Start returns.
// Implements Chain interface.
Expand Down
4 changes: 4 additions & 0 deletions ibc/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ type Chain interface {
// Note that this will not return a valid value until after Start returns.
GetHostRPCAddress() string

// GetHostPeerAddress returns the p2p address that can be reached by processes on the host machine.
// Note that this will not return a valid value until after Start returns.
GetHostPeerAddress() string

// GetHostGRPCAddress returns the grpc address that can be reached by processes on the host machine.
// Note that this will not return a valid value until after Start returns.
GetHostGRPCAddress() string
Expand Down
6 changes: 1 addition & 5 deletions internal/dockerutil/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@ func GetHostPort(cont types.ContainerJSON, portID string) string {
return ""
}

ip := m[0].HostIP
if ip == "0.0.0.0" {
ip = "127.0.0.1"
}
return net.JoinHostPort(ip, m[0].HostPort)
return net.JoinHostPort(m[0].HostIP, m[0].HostPort)
}

// Ensure that the global RNG is seeded when this package is imported.
Expand Down
2 changes: 1 addition & 1 deletion internal/dockerutil/strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestGetHostPort(t *testing.T) {
},
},
},
}, "test", "127.0.0.1:3000",
}, "test", "0.0.0.0:3000",
},

{types.ContainerJSON{}, "", ""},
Expand Down
14 changes: 11 additions & 3 deletions local-interchain/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,22 @@ Follow [this guide](./docs/WINDOWS.md) to setup the Windows OS environment for i
- Run: `local-ic start mytest1_ignored.json [flags]`
- Run in different directory: `ICTEST_HOME=/root/local-interchain local-ic start myother_ignored.json [flags]`

Modify the relayer information on `start` with the --relayer-* flags.

**NOTE** The ICTEST_HOME path must contain the directories `chains` and `configs` to be valid.
**NOTE** The ICTEST_HOME path must contain the directories `chains` to be valid.

*(Default: `make install` links to the cloned directory. `go install .` will use your home directory ~/local-interchain)*

*(Ending the config file with `_ignored.json` or `_ignore.json` will ignore it from git)*

### Optional Start Flags
--api-address string override the default API address (default "127.0.0.1")
--api-port uint16 override the default API port (default 8080)
--auth-key string require an auth key to use the internal API
--help
--relayer-image string override the docker relayer image (default "ghcr.io/cosmos/relayer")
--relayer-startup-flags string override the default relayer startup flags (default "--block-history=100")
--relayer-uidgid string override the default image UID:GID (default "100:1000")
--relayer-version string override the default relayer version (default "latest")

---

## REST API
Expand Down
7 changes: 6 additions & 1 deletion local-interchain/cmd/local-ic/start_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const (
FlagRelayerVersion = "relayer-version"
FlagRelayerUidGid = "relayer-uidgid"
FlagRelayerStartupFlags = "relayer-startup-flags"
FlagAuthKey = "auth-key"
)

var startCmd = &cobra.Command{
Expand Down Expand Up @@ -47,7 +48,7 @@ var startCmd = &cobra.Command{
relayerUidGid := cmd.Flag(FlagRelayerUidGid).Value.String()
relayerFlags := strings.Split(cmd.Flag(FlagRelayerStartupFlags).Value.String(), " ")

interchain.StartChain(parentDir, configPath, &interchain.AppConfig{
interchain.StartChain(parentDir, configPath, &types.AppStartConfig{
Address: apiAddr,
Port: apiPort,

Expand All @@ -59,6 +60,8 @@ var startCmd = &cobra.Command{
},
StartupFlags: relayerFlags,
},

AuthKey: cmd.Flag(FlagAuthKey).Value.String(),
})
},
}
Expand All @@ -71,4 +74,6 @@ func init() {
startCmd.Flags().String(FlagRelayerVersion, "latest", "override the default relayer version")
startCmd.Flags().String(FlagRelayerUidGid, "100:1000", "override the default image UID:GID")
startCmd.Flags().String(FlagRelayerStartupFlags, "--block-history=100", "override the default relayer startup flags")

startCmd.Flags().String(FlagAuthKey, "", "require an auth key to use the internal API")
}
63 changes: 50 additions & 13 deletions local-interchain/interchain/handlers/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import (
"strconv"
"strings"

"github.com/strangelove-ventures/localinterchain/interchain/util"
sdkmath "cosmossdk.io/math"

"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/localinterchain/interchain/util"
)

type actions struct {
Expand All @@ -23,22 +24,31 @@ type actions struct {

relayer ibc.Relayer
eRep ibc.RelayerExecReporter

authKey string
}

type ActionHandler struct {
ChainId string `json:"chain_id"`
Action string `json:"action"`
Cmd string `json:"cmd"`
AuthKey string `json:"auth_key,omitempty"`
}

func NewActions(ctx context.Context, ic *interchaintest.Interchain, cosmosChains map[string]*cosmos.CosmosChain, vals map[string]*cosmos.ChainNode, relayer ibc.Relayer, eRep ibc.RelayerExecReporter) *actions {
func NewActions(
ctx context.Context, ic *interchaintest.Interchain,
cosmosChains map[string]*cosmos.CosmosChain, vals map[string]*cosmos.ChainNode,
relayer ibc.Relayer, eRep ibc.RelayerExecReporter,
authKey string,
) *actions {
return &actions{
ctx: ctx,
ic: ic,
vals: vals,
cc: cosmosChains,
relayer: relayer,
eRep: eRep,
authKey: authKey,
}
}

Expand All @@ -50,6 +60,11 @@ func (a *actions) PostActions(w http.ResponseWriter, r *http.Request) {
return
}

if a.authKey != "" && ah.AuthKey != a.authKey {
util.WriteError(w, fmt.Errorf("invalid `auth_key`"))
return
}

action := ah.Action
if action == "kill-all" {
KillAll(a.ctx, a.ic, a.vals, a.relayer, a.eRep)
Expand Down Expand Up @@ -122,7 +137,9 @@ func (a *actions) PostActions(w http.ResponseWriter, r *http.Request) {

stdout = []byte(fmt.Sprintf(`{"added_full_node":"%s"}`, cmdMap["amount"]))
case "dump-contract-state":
dumpContractState(w, r, cmdMap, a, val)
stdout = dumpContractState(r, cmdMap, a, val)
case "faucet":
stdout = faucet(r, cmdMap, a.ctx, a, val)
}

// Relayer Actions if the above is not used.
Expand Down Expand Up @@ -208,31 +225,51 @@ func KillAll(ctx context.Context, ic *interchaintest.Interchain, vals map[string
<-ctx.Done()
}

func dumpContractState(w http.ResponseWriter, r *http.Request, cmdMap map[string]string, a *actions, val *cosmos.ChainNode) {
func dumpContractState(r *http.Request, cmdMap map[string]string, a *actions, val *cosmos.ChainNode) []byte {
contract, ok1 := cmdMap["contract"]
height, ok2 := cmdMap["height"]
if !ok1 || !ok2 {
util.WriteError(w, fmt.Errorf("contract or height not found in commands"))
return
return []byte(`{"error":"'contract' or 'height' not found in commands"}`)
}

heightInt, err := strconv.ParseInt(height, 10, 64)
if err != nil {
util.WriteError(w, err)
return
return []byte(fmt.Sprintf(`{"error":"failed to convert height to int: %s"}`, height))
}

state, err := val.DumpContractState(a.ctx, contract, heightInt)
if err != nil {
util.WriteError(w, err)
return
return []byte(fmt.Sprintf(`{"error":"%s"}`, err))
}

jsonRes, err := json.Marshal(state.Models)
if err != nil {
util.WriteError(w, err)
return
return []byte(fmt.Sprintf(`{"error":"%s"}`, err))
}

return jsonRes
}

func faucet(r *http.Request, cmdMap map[string]string, ctx context.Context, a *actions, val *cosmos.ChainNode) []byte {
amount, ok1 := cmdMap["amount"]
toAddr, ok2 := cmdMap["address"]

if !ok1 || !ok2 {
return []byte(`{"error":"'amount' or 'address' not found in commands"}`)
}

amt, ok := sdkmath.NewIntFromString(amount)
if !ok {
return []byte(fmt.Sprintf(`{"error":"failed to convert amount to int: %s"}`, amount))
}

if err := val.SendFunds(ctx, "faucet", ibc.WalletAmount{
Address: toAddr,
Amount: amt,
Denom: val.Chain.Config().Denom,
}); err != nil {
return []byte(fmt.Sprintf(`{"error":"%s"}`, err))
}

util.Write(w, jsonRes)
return []byte(fmt.Sprintf(`{"sent_funds":"%s"}`, amount))
}
11 changes: 11 additions & 0 deletions local-interchain/interchain/handlers/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ func (i *info) GetInfo(w http.ResponseWriter, r *http.Request) {
case "genesis_file_content":
v, _ := val.GenesisFileContent(i.ctx)
util.Write(w, v)
case "peer":
util.Write(w, getPeer(i.ctx, val))
default:
util.WriteError(w, fmt.Errorf("invalid get param: %s. does not exist", res[0]))
}
Expand Down Expand Up @@ -188,3 +190,12 @@ func get_logs(w http.ResponseWriter, r *http.Request, i *info) {

util.Write(w, jsonRes)
}

func getPeer(ctx context.Context, val *cosmos.ChainNode) []byte {
peer, err := val.NodeID(ctx)
if err != nil {
return []byte(fmt.Sprintf(`{"error":"%s"}`, err))
}

return []byte(peer + "@" + val.Chain.GetHostPeerAddress())
}
15 changes: 12 additions & 3 deletions local-interchain/interchain/handlers/uploader.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
type upload struct {
ctx context.Context
vals map[string]*cosmos.ChainNode

authKey string
}

type Uploader struct {
Expand All @@ -23,12 +25,14 @@ type Uploader struct {

// Upload-Type: cosmwasm only
KeyName string `json:"key_name,omitempty"`
AuthKey string `json:"auth_key,omitempty"`
}

func NewUploader(ctx context.Context, vals map[string]*cosmos.ChainNode) *upload {
func NewUploader(ctx context.Context, vals map[string]*cosmos.ChainNode, authKey string) *upload {
return &upload{
ctx: ctx,
vals: vals,
ctx: ctx,
vals: vals,
authKey: authKey,
}
}

Expand All @@ -40,6 +44,11 @@ func (u *upload) PostUpload(w http.ResponseWriter, r *http.Request) {
return
}

if u.authKey != "" && u.authKey != upload.AuthKey {
util.WriteError(w, fmt.Errorf("invalid `auth_key`"))
return
}

srcPath := upload.FilePath
if _, err := os.Stat(srcPath); os.IsNotExist(err) {
util.WriteError(w, fmt.Errorf("file %s does not exist on the source machine", srcPath))
Expand Down
1 change: 1 addition & 0 deletions local-interchain/interchain/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func DumpChainsInfoToLogs(configDir string, config *types.Config, chains []ibc.C
RPCAddress: chainObj.GetHostRPCAddress(),
RESTAddress: chainObj.GetHostAPIAddress(),
GRPCAddress: chainObj.GetHostGRPCAddress(),
P2PAddress: chainObj.GetHostPeerAddress(),
IBCPath: ibcPaths,
}

Expand Down
Loading
Loading