Skip to content

Commit

Permalink
client/test_helpers: fix SetupLocalCosmosNode (#321)
Browse files Browse the repository at this point in the history
* client/test_helpers: terrad -> wasmd

* client/test_helpers: specify --home instead of --keyring-dir so that ~/.wasmd isn't created

* client/test_helpers: only listen locally

* remove terrad.nix, add wasmd.nix to install wasmd

* nix.conf: disable sandbox

* .github/workflows: set extra_nix_config

* fix derivation path, set ATOM coin type

* client/test_helpers: rpc.laddr parameter requires tcp as protocol

* client/test_helpers: fix hardcoded token

* cosmos/testdata: recompile my_first_contract.wasm

* client/test_helpers: fix out of gas error, set gas adjustment on deploy

* cosmos/client: fix wasm attribute filters when reading events

* client/client_test: fix wasm attribute check, remove count attribute check

.. because it doesn't exist in the updated contract reset function

https://github.com/CosmWasm/cw-template/blob/main/src/contract.rs#L69

* client/test_helpers: add required Label field when instantiating contract

* cosmos/client: register auth types with interface registry

* cosmos/client: don't hardcode chain id in DeployTestContract

* .github/workflows: cache nix
  • Loading branch information
cfal authored Mar 29, 2023
1 parent 4e21318 commit a675729
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 66 deletions.
18 changes: 16 additions & 2 deletions .github/workflows/contracts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ jobs:
uses: cachix/install-nix-action@5c11eae19dba042788936d4f1c9685fdd814ac49 # v19
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: "sandbox = false"

- name: Cache Nix
uses: cachix/cachix-action@v12
with:
name: chainlink-cosmos
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'

# TODO: We probably want cachix enabled heres
# https://github.com/smartcontractkit/chainlink-terra/issues/15
# https://github.com/smartcontractkit/chainlink-cosmos/issues/15

- name: Run unit tests
run: nix develop -c cargo unit-test --locked
Expand All @@ -47,6 +54,13 @@ jobs:
uses: cachix/install-nix-action@5c11eae19dba042788936d4f1c9685fdd814ac49 # v19
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: "sandbox = false"

- name: Cache Nix
uses: cachix/cachix-action@v12
with:
name: chainlink-cosmos
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'

- name: Avoid using non-nix rust binaries
run: rm -rf ~/.cargo/bin
Expand All @@ -59,6 +73,6 @@ jobs:

- name: Run cargo clippy
run: nix develop -c cargo clippy -- -D warnings

# TODO: Add schema checks
# https://github.com/smartcontractkit/chainlink-terra/issues/17
9 changes: 8 additions & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ on:
QA_KUBECONFIG:
required: true
description: The kubernetes configuation to use

jobs:
e2e_build_contracts:
name: E2E Build Contracts
Expand Down Expand Up @@ -82,6 +82,13 @@ jobs:
uses: cachix/install-nix-action@5c11eae19dba042788936d4f1c9685fdd814ac49 # v19
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: "sandbox = false"

- name: Cache Nix
uses: cachix/cachix-action@v12
with:
name: chainlink-cosmos
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/e2e_custom_cl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ jobs:
uses: cachix/install-nix-action@5c11eae19dba042788936d4f1c9685fdd814ac49 # v19
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: "sandbox = false"
- name: Cache Nix
uses: cachix/cachix-action@v12
with:
name: chainlink-cosmos
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
Expand Down Expand Up @@ -118,4 +124,4 @@ jobs:
uses: actions/upload-artifact@v2.2.4
with:
name: test-logs
path: /home/runner/work/chainlink-terra/chainlink-terra/tests/e2e/logs
path: /home/runner/work/chainlink-terra/chainlink-terra/tests/e2e/logs
18 changes: 18 additions & 0 deletions .github/workflows/gauntlet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ jobs:
uses: cachix/install-nix-action@5c11eae19dba042788936d4f1c9685fdd814ac49 # v19
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: "sandbox = false"
- name: Cache Nix
uses: cachix/cachix-action@v12
with:
name: chainlink-cosmos
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix develop -c yarn install --frozen-lockfile
- run: nix develop -c yarn build

Expand All @@ -29,6 +35,12 @@ jobs:
uses: cachix/install-nix-action@5c11eae19dba042788936d4f1c9685fdd814ac49 # v19
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: "sandbox = false"
- name: Cache Nix
uses: cachix/cachix-action@v12
with:
name: chainlink-cosmos
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix develop -c yarn install --frozen-lockfile
- run: nix develop -c yarn lint:format

Expand All @@ -43,5 +55,11 @@ jobs:
uses: cachix/install-nix-action@5c11eae19dba042788936d4f1c9685fdd814ac49 # v19
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: "sandbox = false"
- name: Cache Nix
uses: cachix/cachix-action@v12
with:
name: chainlink-cosmos
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix develop -c yarn install --frozen-lockfile
- run: nix develop -c yarn test:ci
9 changes: 8 additions & 1 deletion .github/workflows/relay.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ jobs:
uses: cachix/install-nix-action@5c11eae19dba042788936d4f1c9685fdd814ac49 # v19
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: "sandbox = false"

- name: Cache Nix
uses: cachix/cachix-action@v12
with:
name: chainlink-cosmos
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'

- name: Compile relay
run: nix develop -c go build -v ./pkg/cosmos/...
Expand All @@ -38,4 +45,4 @@ jobs:
run: nix develop -c go test -v ./pkg/cosmos/...

- name: Run tests with the race detector enabled
run: nix develop -c go test -v ./pkg/cosmos/... -race -count=10
run: nix develop -c go test -v ./pkg/cosmos/... -race -count=10
1 change: 1 addition & 0 deletions nix.conf
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
experimental-features = nix-command flakes
sandbox = false
2 changes: 1 addition & 1 deletion packages-ts/gauntlet-terra/src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const BIP44_ATOM_PATH = "44'/330'/0'/0/0"
export const BIP44_ATOM_PATH = "44'/118'/0'/0/0"
4 changes: 4 additions & 0 deletions pkg/cosmos/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ var (
func init() {
// Extracted from app.MakeEncodingConfig() to ensure that we only call them once, since they race and can panic.
std.RegisterLegacyAminoCodec(encodingConfig.Amino)
// This registers base sdk, tx and crypto types, see
// https://github.com/cosmos/cosmos-sdk/blob/47f46643affd7ec7978329c42bac47275ac7e1cc/std/codec.go#L20
std.RegisterInterfaces(encodingConfig.InterfaceRegistry)
// needed for Client.Account() to deserialize authtypes.AccountI
authtypes.RegisterInterfaces(encodingConfig.InterfaceRegistry)

// NOTE: bech32 is configured globally, blocked on https://github.com/cosmos/cosmos-sdk/issues/13140
config := sdk.GetConfig()
Expand Down
29 changes: 17 additions & 12 deletions pkg/cosmos/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestBatchSim(t *testing.T) {
return func() { assert.Len(t, logs.TakeAll(), l) }
}

contract := DeployTestContract(t, tendermintURL, accounts[0], accounts[0], tc, testdir, "../testdata/my_first_contract.wasm")
contract := DeployTestContract(t, tendermintURL, "42", accounts[0], accounts[0], tc, testdir, "../testdata/my_first_contract.wasm")
var succeed sdk.Msg = &wasmtypes.MsgExecuteContract{Sender: accounts[0].Address.String(), Contract: contract.String(), Msg: []byte(`{"reset":{"count":5}}`)}
var fail sdk.Msg = &wasmtypes.MsgExecuteContract{Sender: accounts[0].Address.String(), Contract: contract.String(), Msg: []byte(`{"blah":{"count":5}}`)}

Expand Down Expand Up @@ -132,7 +132,7 @@ func TestCosmosClient(t *testing.T) {
gpe := NewFixedGasPriceEstimator(map[string]sdk.DecCoin{
"ucosm": sdk.NewDecCoinFromDec("ucosm", sdk.MustNewDecFromStr("0.01")),
})
contract := DeployTestContract(t, tendermintURL, accounts[0], accounts[0], tc, testdir, "../testdata/my_first_contract.wasm")
contract := DeployTestContract(t, tendermintURL, "42", accounts[0], accounts[0], tc, testdir, "../testdata/my_first_contract.wasm")

t.Run("send tx between accounts", func(t *testing.T) {
// Assert balance before
Expand Down Expand Up @@ -239,34 +239,39 @@ func TestCosmosClient(t *testing.T) {

// Check events querying works
// TxEvents sorts in a descending manner, so latest txes are first
ev, err := tc.TxsEvents([]string{fmt.Sprintf("wasm-reset.contract_address='%s'", contract.String())}, nil)
ev, err := tc.TxsEvents([]string{"wasm.action='reset'", fmt.Sprintf("wasm._contract_address='%s'", contract.String())}, nil)
require.NoError(t, err)
require.Equal(t, 2, len(ev.TxResponses))
foundCount := false
foundContract := false
for _, event := range ev.TxResponses[0].Logs[0].Events {
if event.Type != "wasm-reset" {
if event.Type != "wasm" {
continue
}
isResetAction := false
for _, attr := range event.Attributes {
if attr.Key == "count" {
assert.Equal(t, "4", attr.Value)
foundCount = true
if attr.Key != "action" {
continue
}
if attr.Key == "contract_address" {
isResetAction = attr.Value == "reset"
break
}
if !isResetAction {
continue
}
for _, attr := range event.Attributes {
if attr.Key == "_contract_address" {
assert.Equal(t, contract.String(), attr.Value)
foundContract = true
}
}
}
assert.True(t, foundCount)
assert.True(t, foundContract)

// Ensure the height filtering works
ev, err = tc.TxsEvents([]string{fmt.Sprintf("tx.height>=%d", resp1.TxResponse.Height+1), fmt.Sprintf("wasm-reset.contract_address='%s'", contract.String())}, nil)
ev, err = tc.TxsEvents([]string{fmt.Sprintf("tx.height>=%d", resp1.TxResponse.Height+1), "wasm.action='reset'", fmt.Sprintf("wasm._contract_address='%s'", contract.String())}, nil)
require.NoError(t, err)
require.Equal(t, 1, len(ev.TxResponses))
ev, err = tc.TxsEvents([]string{fmt.Sprintf("tx.height=%d", resp1.TxResponse.Height), fmt.Sprintf("wasm-reset.contract_address='%s'", contract)}, nil)
ev, err = tc.TxsEvents([]string{fmt.Sprintf("tx.height=%d", resp1.TxResponse.Height), "wasm.action='reset'", fmt.Sprintf("wasm._contract_address='%s'", contract)}, nil)
require.NoError(t, err)
require.Equal(t, 1, len(ev.TxResponses))
for _, ev := range ev.TxResponses[0].Logs[0].Events {
Expand Down
54 changes: 35 additions & 19 deletions pkg/cosmos/client/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"os"
"os/exec"
"path"
"strings"
"testing"
"time"

Expand All @@ -32,16 +33,15 @@ type Account struct {
// 0.001
var minGasPrice = sdk.NewDecCoinFromDec("ucosm", sdk.NewDecWithPrec(1, 3))

// SetupLocalCosmosNode sets up a local terra node via terrad, and returns pre-funded accounts, the test directory, and the url.
// SetupLocalCosmosNode sets up a local terra node via wasmd, and returns pre-funded accounts, the test directory, and the url.
func SetupLocalCosmosNode(t *testing.T, chainID string) ([]Account, string, string) {
t.Skip("depends on wasmd")
testdir, err := os.MkdirTemp("", "integration-test")
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, os.RemoveAll(testdir))
})
t.Log(testdir)
out, err := exec.Command("terrad", "init", "integration-test", "-o", "--chain-id", chainID, "--home", testdir).Output()
out, err := exec.Command("wasmd", "init", "integration-test", "-o", "--chain-id", chainID, "--home", testdir).Output()
require.NoError(t, err, string(out))

p := path.Join(testdir, "config", "app.toml")
Expand All @@ -54,11 +54,23 @@ func SetupLocalCosmosNode(t *testing.T, chainID string) ([]Account, string, stri
require.NoError(t, os.WriteFile(p, []byte(config.String()), 0600))
// TODO: could also speed up the block mining config

p = path.Join(testdir, "config", "genesis.json")
f, err = os.ReadFile(p)
require.NoError(t, err)

genesisData := string(f)
// fix hardcoded token, see
// https://github.com/CosmWasm/wasmd/blob/develop/docker/setup_wasmd.sh
// https://github.com/CosmWasm/wasmd/blob/develop/contrib/local/setup_wasmd.sh
genesisData = strings.ReplaceAll(genesisData, "\"ustake\"", "\"ucosm\"")
genesisData = strings.ReplaceAll(genesisData, "\"stake\"", "\"ucosm\"")
require.NoError(t, os.WriteFile(p, []byte(genesisData), 0600))

// Create 2 test accounts
var accounts []Account
for i := 0; i < 2; i++ {
account := fmt.Sprintf("test%d", i)
key, err2 := exec.Command("terrad", "keys", "add", account, "--output", "json", "--keyring-backend", "test", "--keyring-dir", testdir).CombinedOutput()
key, err2 := exec.Command("wasmd", "keys", "add", account, "--output", "json", "--keyring-backend", "test", "--home", testdir).CombinedOutput()
require.NoError(t, err2, string(key))
var k struct {
Address string `json:"address"`
Expand All @@ -71,7 +83,7 @@ func SetupLocalCosmosNode(t *testing.T, chainID string) ([]Account, string, stri
require.NoError(t, err4)
require.Equal(t, expAcctAddr, address)
// Give it 100 luna
out2, err2 := exec.Command("terrad", "add-genesis-account", k.Address, "100000000ucosm", "--home", testdir).Output() //nolint:gosec
out2, err2 := exec.Command("wasmd", "add-genesis-account", k.Address, "100000000ucosm", "--home", testdir).Output() //nolint:gosec
require.NoError(t, err2, string(out2))
accounts = append(accounts, Account{
Name: account,
Expand All @@ -80,28 +92,30 @@ func SetupLocalCosmosNode(t *testing.T, chainID string) ([]Account, string, stri
})
}
// Stake 10 luna in first acct
out, err = exec.Command("terrad", "gentx", accounts[0].Name, "10000000ucosm", fmt.Sprintf("--chain-id=%s", chainID), "--keyring-backend", "test", "--keyring-dir", testdir, "--home", testdir).CombinedOutput() //nolint:gosec
out, err = exec.Command("wasmd", "gentx", accounts[0].Name, "10000000ucosm", "--chain-id", chainID, "--keyring-backend", "test", "--home", testdir).CombinedOutput() //nolint:gosec
require.NoError(t, err, string(out))
out, err = exec.Command("terrad", "collect-gentxs", "--home", testdir).CombinedOutput()
out, err = exec.Command("wasmd", "collect-gentxs", "--home", testdir).CombinedOutput()
require.NoError(t, err, string(out))

port := mustRandomPort()
tendermintURL := fmt.Sprintf("http://127.0.0.1:%d", port)
tendermintHost := fmt.Sprintf("127.0.0.1:%d", port)
tendermintURL := "http://" + tendermintHost
t.Log(tendermintURL)
cmd := exec.Command("terrad", "start", "--home", testdir,
"--rpc.laddr", fmt.Sprintf("tcp://127.0.0.1:%d", port),
"--rpc.pprof_laddr", "0.0.0.0:0",
"--grpc.address", "0.0.0.0:0",
"--grpc-web.address", "0.0.0.0:0",
"--p2p.laddr", "0.0.0.0:0")

cmd := exec.Command("wasmd", "start", "--home", testdir,
"--rpc.laddr", "tcp://"+tendermintHost,
"--rpc.pprof_laddr", "127.0.0.1:0",
"--grpc.address", "127.0.0.1:0",
"--grpc-web.address", "127.0.0.1:0",
"--p2p.laddr", "127.0.0.1:0")
var stdErr bytes.Buffer
cmd.Stderr = &stdErr
require.NoError(t, cmd.Start())
t.Cleanup(func() {
assert.NoError(t, cmd.Process.Kill())
if err2 := cmd.Wait(); assert.Error(t, err2) {
if !assert.Contains(t, err2.Error(), "signal: killed", cmd.ProcessState.String()) {
t.Log("terrad stderr:", stdErr.String())
t.Log("wasmd stderr:", stdErr.String())
}
}
})
Expand Down Expand Up @@ -135,18 +149,20 @@ func SetupLocalCosmosNode(t *testing.T, chainID string) ([]Account, string, stri
}

// DeployTestContract deploys a test contract.
func DeployTestContract(t *testing.T, tendermintURL string, deployAccount, ownerAccount Account, tc *Client, testdir, wasmTestContractPath string) sdk.AccAddress {
func DeployTestContract(t *testing.T, tendermintURL, chainID string, deployAccount, ownerAccount Account, tc *Client, testdir, wasmTestContractPath string) sdk.AccAddress {
//nolint:gosec
out, err := exec.Command("terrad", "tx", "wasm", "store", wasmTestContractPath, "--node", tendermintURL,
"--from", deployAccount.Name, "--gas", "auto", "--fees", "100000ucosm", "--chain-id", "42", "--broadcast-mode", "block", "--home", testdir, "--keyring-backend", "test", "--keyring-dir", testdir, "--yes").CombinedOutput()
out, err := exec.Command("wasmd", "tx", "wasm", "store", wasmTestContractPath, "--node", tendermintURL,
"--from", deployAccount.Name, "--gas", "auto", "--fees", "100000ucosm", "--gas-adjustment", "1.3", "--chain-id", chainID, "--broadcast-mode", "block", "--home", testdir, "--keyring-backend", "test", "--keyring-dir", testdir, "--yes", "--output", "json").CombinedOutput()
require.NoError(t, err, string(out))
an, sn, err2 := tc.Account(ownerAccount.Address)
require.NoError(t, err2)
r, err3 := tc.SignAndBroadcast([]sdk.Msg{
&wasmtypes.MsgInstantiateContract{
Sender: ownerAccount.Address.String(),
Admin: "",
// TODO: this only works for the first code deployment, read code_id from the store invocation above and use the value here.
CodeID: 1,
Label: "testcontract",
Msg: []byte(`{"count":0}`),
Funds: sdk.Coins{},
},
Expand All @@ -170,7 +186,7 @@ func GetContractAddr(t *testing.T, tc *Client, deploymentHash string) sdk.AccAdd
for _, etype := range deploymentTx.TxResponse.Events {
if etype.Type == "wasm" {
for _, attr := range etype.Attributes {
if string(attr.Key) == "contract_address" {
if string(attr.Key) == "_contract_address" {
contractAddr = string(attr.Value)
}
}
Expand Down
Binary file modified pkg/cosmos/testdata/my_first_contract.wasm
Binary file not shown.
9 changes: 8 additions & 1 deletion pkg/cosmos/testutil/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ func CreateMnemonic() (string, error) {
return bip39.NewMnemonic(entropy)
}

// TODO: these should be configurable
var (
// ATOM coin type
// ref: https://github.com/satoshilabs/slips/blob/master/slip-0044.md
coinType uint32 = 118
)

// CreateHDPath returns BIP 44 object from account and index parameters.
func CreateHDPath(account uint32, index uint32) string {
return hd.CreateHDPath(330, account, index).String()
return hd.CreateHDPath(coinType, account, index).String()
}

func CreateKeyFromMnemonic(mnemonic string) (cryptotypes.PrivKey, sdk.AccAddress, error) {
Expand Down
Loading

0 comments on commit a675729

Please sign in to comment.