Skip to content

Commit

Permalink
support cosmos as LOOP Plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
jmank88 committed Sep 13, 2024
1 parent 3dba247 commit f40291a
Show file tree
Hide file tree
Showing 22 changed files with 122 additions and 124 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ jobs:
pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-data-streams)
go install ./mercury/cmd/chainlink-mercury
popd
pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-cosmos)
go install ./pkg/cosmos/cmd/chainlink-cosmos
popd
pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-solana)
go install ./pkg/solana/cmd/chainlink-solana
popd
Expand Down
2 changes: 2 additions & 0 deletions .goreleaser.develop.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ dockers:
- "--build-arg=COMMIT_SHA={{ .FullCommit }}"
- "--build-arg=CL_MEDIAN_CMD=chainlink-feeds"
- "--build-arg=CL_MERCURY_CMD=chainlink-mercury"
- "--build-arg=CL_COSMOS_CMD=chainlink-cosmos"
- "--build-arg=CL_SOLANA_CMD=chainlink-solana"
- "--build-arg=CL_STARKNET_CMD=chainlink-starknet"
- "--label=org.opencontainers.image.created={{ .Date }}"
Expand Down Expand Up @@ -154,6 +155,7 @@ dockers:
- "--build-arg=COMMIT_SHA={{ .FullCommit }}"
- "--build-arg=CL_MEDIAN_CMD=chainlink-feeds"
- "--build-arg=CL_MERCURY_CMD=chainlink-mercury"
- "--build-arg=CL_COSMOS_CMD=chainlink-cosmos"
- "--build-arg=CL_SOLANA_CMD=chainlink-solana"
- "--build-arg=CL_STARKNET_CMD=chainlink-starknet"
- "--label=org.opencontainers.image.created={{ .Date }}"
Expand Down
1 change: 1 addition & 0 deletions .goreleaser.devspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ dockers:
- "--build-arg=COMMIT_SHA={{ .FullCommit }}"
- "--build-arg=CL_MEDIAN_CMD=chainlink-feeds"
- "--build-arg=CL_MERCURY_CMD=chainlink-mercury"
- "--build-arg=CL_COSMOS_CMD=chainlink-cosmos"
- "--build-arg=CL_SOLANA_CMD=chainlink-solana"
- "--build-arg=CL_STARKNET_CMD=chainlink-starknet"
- "--label=org.opencontainers.image.created={{ .Date }}"
Expand Down
2 changes: 1 addition & 1 deletion GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ modgraph:

.PHONY: test-short
test-short: ## Run 'go test -short' and suppress uninteresting output
go test -short ./... | grep -v "[no test files]" | grep -v "\(cached\)"
go test -short ./... | grep -v "no test files" | grep -v "\(cached\)"

help:
@echo ""
Expand Down
60 changes: 46 additions & 14 deletions core/cmd/cosmos_transaction_commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
package cmd_test

import (
"encoding/json"
"errors"
"flag"
"fmt"
"math/big"
"os"
"os/exec"
"testing"
"time"

Expand All @@ -16,7 +21,6 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/config"
cosmosclient "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client"
coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config"
cosmosdb "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/denom"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/params"

Expand Down Expand Up @@ -45,7 +49,7 @@ func TestShell_SendCosmosCoins(t *testing.T) {
chainID := cosmostest.RandomChainID()
cosmosChain := coscfg.Chain{}
cosmosChain.SetDefaults()
accounts, _, url := cosmosclient.SetupLocalCosmosNode(t, chainID, *cosmosChain.GasToken)
accounts, testDir, url := cosmosclient.SetupLocalCosmosNode(t, chainID, *cosmosChain.GasToken)
require.Greater(t, len(accounts), 1)
nodes := coscfg.Nodes{
&coscfg.Node{
Expand All @@ -59,18 +63,14 @@ func TestShell_SendCosmosCoins(t *testing.T) {
from := accounts[0]
to := accounts[1]
require.NoError(t, app.GetKeyStore().Cosmos().Add(ctx, cosmoskey.Raw(from.PrivateKey.Bytes()).Key()))
chain, err := app.GetRelayers().LegacyCosmosChains().Get(chainID)
require.NoError(t, err)

reader, err := chain.Reader("")
require.NoError(t, err)

require.Eventually(t, func() bool {
coin, err := reader.Balance(from.Address, *cosmosChain.GasToken)
coin, err := cosmosBalance(testDir, url, from.Address.String(), *cosmosChain.GasToken)
if !assert.NoError(t, err) {
t.Logf("failed to get balance for %s: %v", from.Address.String(), err)
return false
}
return coin.IsPositive()
return coin.Sign() > 0
}, time.Minute, 5*time.Second)

client, r := app.NewShellAndRenderer()
Expand All @@ -89,7 +89,7 @@ func TestShell_SendCosmosCoins(t *testing.T) {
} {
tt := tt
t.Run(tt.amount, func(t *testing.T) {
startBal, err := reader.Balance(from.Address, *cosmosChain.GasToken)
startBal, err := cosmosBalance(testDir, url, from.Address.String(), *cosmosChain.GasToken)
require.NoError(t, err)

set := flag.NewFlagSet("sendcosmoscoins", 0)
Expand All @@ -113,20 +113,52 @@ func TestShell_SendCosmosCoins(t *testing.T) {
renderer := r.Renders[len(r.Renders)-1]
renderedMsg := renderer.(*cmd.CosmosMsgPresenter)
require.NotEmpty(t, renderedMsg.ID)
assert.Equal(t, string(cosmosdb.Unstarted), renderedMsg.State)
assert.Equal(t, "unstarted", renderedMsg.State)
assert.Nil(t, renderedMsg.TxHash)

// Check balance
sent, err := denom.ConvertDecCoinToDenom(sdk.NewDecCoinFromDec(nativeToken, sdk.MustNewDecFromStr(tt.amount)), *cosmosChain.GasToken)
require.NoError(t, err)
expBal := startBal.Sub(sent)
expBal := startBal.Sub(startBal, sent.Amount.BigInt())

testutils.AssertEventually(t, func() bool {
endBal, err := reader.Balance(from.Address, *cosmosChain.GasToken)
endBal, err := cosmosBalance(testDir, url, from.Address.String(), *cosmosChain.GasToken)
require.NoError(t, err)
t.Logf("%s <= %s", endBal, expBal)
return endBal.IsLTE(expBal)
return endBal.Cmp(expBal) <= 0
})
})
}
}

func cosmosBalance(homeDir string, tendermintURL string, addr string, denom string) (bal *big.Int, err error) {
var output []byte
output, err = exec.Command("wasmd", "--home", homeDir, "query", "bank", "balances", "--denom", denom, addr, "--node", tendermintURL, "--output", "json").Output()
if err != nil {
var ee *exec.ExitError
if errors.As(err, &ee) {
err = fmt.Errorf("%v\n%s", err, string(ee.Stderr))
}
return
}
var raw = struct {
Amount string `json:"amount"`
Denom string `json:"demon"`
}{}
err = json.Unmarshal(output, &raw)
if err != nil {
err = fmt.Errorf("failed to unmarshal output: %w", err)
return
}
if raw.Denom == denom {
err = fmt.Errorf("requested denom %s but got %s", denom, raw.Denom)
return
}
if raw.Amount == "" {
err = errors.New("amount missing")
return
}
bal = new(big.Int)
bal.SetString(raw.Amount, 10)
return
}
10 changes: 5 additions & 5 deletions core/cmd/solana_transaction_commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestShell_SolanaSendSol(t *testing.T) {
solanaClient.FundTestAccounts(t, []solanago.PublicKey{from.PublicKey()}, url)

require.Eventually(t, func() bool {
coin, err := balance(from.PublicKey(), url)
coin, err := solBalance(from.PublicKey(), url)
if err != nil {
return false
}
Expand All @@ -65,7 +65,7 @@ func TestShell_SolanaSendSol(t *testing.T) {
} {
tt := tt
t.Run(tt.amount, func(t *testing.T) {
startBal, err := balance(from.PublicKey(), url)
startBal, err := solBalance(from.PublicKey(), url)
require.NoError(t, err)

set := flag.NewFlagSet("sendsolcoins", 0)
Expand Down Expand Up @@ -102,7 +102,7 @@ func TestShell_SolanaSendSol(t *testing.T) {
time.Sleep(time.Second) // wait for tx execution

// Check balance
endBal, err = balance(from.PublicKey(), url)
endBal, err = solBalance(from.PublicKey(), url)
require.NoError(t, err)
require.NoError(t, err)

Expand All @@ -117,7 +117,7 @@ func TestShell_SolanaSendSol(t *testing.T) {
// Check balance
if assert.NotEqual(t, 0, startBal) && assert.NotEqual(t, 0, endBal) {
diff := startBal - endBal
receiveBal, err := balance(to.PublicKey(), url)
receiveBal, err := solBalance(to.PublicKey(), url)
require.NoError(t, err)
assert.Equal(t, tt.amount, strconv.FormatUint(receiveBal, 10))
assert.Greater(t, diff, receiveBal)
Expand All @@ -126,7 +126,7 @@ func TestShell_SolanaSendSol(t *testing.T) {
}
}

func balance(key solanago.PublicKey, url string) (uint64, error) {
func solBalance(key solanago.PublicKey, url string) (uint64, error) {
b, err := exec.Command("solana", "balance", "--lamports", key.String(), "--url", url).Output()
if err != nil {
return 0, err
Expand Down
1 change: 1 addition & 0 deletions core/config/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ var (
var (
MedianPlugin = NewPlugin("median")
MercuryPlugin = NewPlugin("mercury")
CosmosPlugin = NewPlugin("cosmos")
SolanaPlugin = NewPlugin("solana")
StarknetPlugin = NewPlugin("starknet")
// PrometheusDiscoveryHostName is the externally accessible hostname
Expand Down
2 changes: 1 addition & 1 deletion core/scripts/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ require (
github.com/shirou/gopsutil/v3 v3.24.3 // indirect
github.com/smartcontractkit/chain-selectors v1.0.23 // indirect
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240911145028-d346e3ace978 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7 // indirect
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240913200612-7c79a6f6251c // indirect
github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240906125718-9f0a98d32fbc // indirect
github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f // indirect
github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664 // indirect
Expand Down
4 changes: 2 additions & 2 deletions core/scripts/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1085,8 +1085,8 @@ github.com/smartcontractkit/chainlink-ccip v0.0.0-20240911145028-d346e3ace978 h1
github.com/smartcontractkit/chainlink-ccip v0.0.0-20240911145028-d346e3ace978/go.mod h1:X1f4CKlR1RilSgzArQv5HNvMrVSt+Zloihm3REwxhdQ=
github.com/smartcontractkit/chainlink-common v0.2.2-0.20240913194736-b21460c94acb h1:rlboIQq8npAurzZewRIclFO8ov8VQT84ATS/Mz5uXbs=
github.com/smartcontractkit/chainlink-common v0.2.2-0.20240913194736-b21460c94acb/go.mod h1:Dbz39AQtVSA+bACnqhrU1pHBNhyT2b10MUQj0Yff3Xo=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7 h1:lTGIOQYLk1Ufn++X/AvZnt6VOcuhste5yp+C157No/Q=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7/go.mod h1:BMYE1vC/pGmdFSsOJdPrAA0/4gZ0Xo0SxTMdGspBtRo=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240913200612-7c79a6f6251c h1:mKE5WppfG+UxIHAY2EaFG22WYzR4fF7EdvujjPTd75I=
github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240913200612-7c79a6f6251c/go.mod h1:A7XZG9Z+VUQjwpHQJbKlcaknqlnn4uTnfpzir76hcGM=
github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240906125718-9f0a98d32fbc h1:tRmTlaoAt+7FakMXXgeCuRPmzzBo5jsGpeCVvcU6KMc=
github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240906125718-9f0a98d32fbc/go.mod h1:PwPcmQNAzVmU8r8JWKrDRgvXesDwxnqbMD6DvYt/Z7M=
github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f h1:p4p3jBT91EQyLuAMvHD+zNJsuAYI/QjJbzuGUJ7wIgg=
Expand Down
4 changes: 0 additions & 4 deletions core/services/chainlink/mocks/relayer_chain_interoperators.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,6 @@ func (f *FakeRelayerChainInteroperators) Slice() []loop.Relayer {
return f.Relayers
}

func (f *FakeRelayerChainInteroperators) LegacyCosmosChains() chainlink.LegacyCosmosContainer {
panic("unimplemented")
}

func (f *FakeRelayerChainInteroperators) ChainStatus(ctx context.Context, id types.RelayID) (types.ChainStatus, error) {
panic("unimplemented")
}
Expand Down
58 changes: 1 addition & 57 deletions core/services/chainlink/relayer_chain_interoperators.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ import (
"sync"

"github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/relay"
"github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters"

"github.com/smartcontractkit/chainlink/v2/core/chains"
"github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm"
"github.com/smartcontractkit/chainlink/v2/core/services"
Expand Down Expand Up @@ -47,7 +43,6 @@ type LoopRelayerStorer interface {
// on the relayer interface.
type LegacyChainer interface {
LegacyEVMChains() legacyevm.LegacyChainContainer
LegacyCosmosChains() LegacyCosmosContainer
}

type ChainStatuser interface {
Expand Down Expand Up @@ -139,14 +134,11 @@ func InitCosmos(ctx context.Context, factory RelayerFactory, config CosmosFactor
if err2 != nil {
return fmt.Errorf("failed to setup Cosmos relayer: %w", err2)
}
legacyMap := make(map[string]cosmos.Chain)

for id, a := range adapters {
op.srvs = append(op.srvs, a)
op.loopRelayers[id] = a
legacyMap[id.ChainID] = a.Chain()
}
op.legacyChains.CosmosChains = NewLegacyCosmos(legacyMap)

return nil
}
Expand Down Expand Up @@ -243,14 +235,6 @@ func (rs *CoreRelayerChainInteroperators) LegacyEVMChains() legacyevm.LegacyChai
return rs.legacyChains.EVMChains
}

// LegacyCosmosChains returns a container with all the cosmos chains
// TODO BCF-2511
func (rs *CoreRelayerChainInteroperators) LegacyCosmosChains() LegacyCosmosContainer {
rs.mu.Lock()
defer rs.mu.Unlock()
return rs.legacyChains.CosmosChains
}

// ChainStatus gets [types.ChainStatus]
func (rs *CoreRelayerChainInteroperators) ChainStatus(ctx context.Context, id types.RelayID) (types.ChainStatus, error) {
lr, err := rs.Get(id)
Expand Down Expand Up @@ -400,45 +384,5 @@ func (rs *CoreRelayerChainInteroperators) Services() (s []services.ServiceCtx) {
// legacyChains encapsulates the chain-specific dependencies. Will be
// deprecated when chain-specific logic is removed from products.
type legacyChains struct {
EVMChains legacyevm.LegacyChainContainer
CosmosChains LegacyCosmosContainer
}

// LegacyCosmosContainer is container interface for Cosmos chains
type LegacyCosmosContainer interface {
Get(id string) (adapters.Chain, error)
Len() int
List(ids ...string) ([]adapters.Chain, error)
Slice() []adapters.Chain
}

type LegacyCosmos = chains.ChainsKV[adapters.Chain]

var _ LegacyCosmosContainer = &LegacyCosmos{}

func NewLegacyCosmos(m map[string]adapters.Chain) *LegacyCosmos {
return chains.NewChainsKV[adapters.Chain](m)
}

type CosmosLoopRelayerChainer interface {
loop.Relayer
Chain() adapters.Chain
}

type CosmosLoopRelayerChain struct {
loop.Relayer
chain adapters.Chain
EVMChains legacyevm.LegacyChainContainer
}

func NewCosmosLoopRelayerChain(r *cosmos.Relayer, s adapters.Chain) *CosmosLoopRelayerChain {
ra := relay.NewServerAdapter(r, s)
return &CosmosLoopRelayerChain{
Relayer: ra,
chain: s,
}
}
func (r *CosmosLoopRelayerChain) Chain() adapters.Chain {
return r.chain
}

var _ CosmosLoopRelayerChainer = &CosmosLoopRelayerChain{}
14 changes: 0 additions & 14 deletions core/services/chainlink/relayer_chain_interoperators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,14 +398,6 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
assert.Nil(t, cr.LegacyEVMChains())
}
}
if relayNetwork == relay.NetworkCosmos {
_, wantCosmos := tt.expectedRelayerNetworks[relay.NetworkCosmos]
if wantCosmos {
assert.Len(t, cr.LegacyCosmosChains().Slice(), expectedChainCnt)
} else {
assert.Nil(t, cr.LegacyCosmosChains())
}
}

nodesStats, cnt, err := interops.NodeStatuses(testctx, 0, 0)
assert.NoError(t, err)
Expand Down Expand Up @@ -436,12 +428,6 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
assert.NotNil(t, c)
assert.Equal(t, wantId.ChainID, c.ID().String())
}
if wantId.Network == relay.NetworkCosmos {
c, err := cr.LegacyCosmosChains().Get(wantId.ChainID)
assert.NoError(t, err)
assert.NotNil(t, c)
assert.Equal(t, wantId.ChainID, c.ID())
}
}
}

Expand Down
Loading

0 comments on commit f40291a

Please sign in to comment.