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!: x/clock v2 - permissionless #893

Merged
merged 39 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
cc9275e
Update Clock Proto
joelsmith-2019 Nov 22, 2023
feeb9ad
Add Keeper Logic
joelsmith-2019 Nov 22, 2023
0e6c505
Update Msg Server, Querier, & Params
joelsmith-2019 Nov 22, 2023
105aec7
Add Tx Cmds
joelsmith-2019 Nov 22, 2023
91e352a
Ensure Sender is Admin
joelsmith-2019 Nov 24, 2023
3c398ce
Add Clock CLI Queries, Update Txs
joelsmith-2019 Nov 24, 2023
4fa4f3f
Update Clock Codec
joelsmith-2019 Nov 24, 2023
8b5d8e4
Fix Get All & Manager Check
joelsmith-2019 Nov 24, 2023
249bfdb
Update Genesis, Fix Genesis Export
joelsmith-2019 Nov 24, 2023
debe734
Jail Contract on Error
joelsmith-2019 Nov 24, 2023
616b214
Pass Clock Interchain Tests (Tests are Incomplete)
joelsmith-2019 Nov 24, 2023
4fd1322
Error Check on Jail Contract
joelsmith-2019 Nov 24, 2023
45fee20
Test Msg Server
joelsmith-2019 Nov 27, 2023
5885783
Test Msg Server with Admin
joelsmith-2019 Nov 27, 2023
bd468a9
Test Querier
joelsmith-2019 Nov 27, 2023
1f2b4c5
Test Params
joelsmith-2019 Nov 27, 2023
a5d52a6
Test Genesis
joelsmith-2019 Nov 27, 2023
868bf75
Update Codec Tests
joelsmith-2019 Nov 27, 2023
22c2102
Fix Msg Tests
joelsmith-2019 Nov 27, 2023
722f3b6
Refactor Stores into Singular Store
joelsmith-2019 Nov 28, 2023
1581533
Lint
joelsmith-2019 Nov 28, 2023
d4982f3
Update Tx CLI Desc, More Lint
joelsmith-2019 Nov 28, 2023
ac083ac
Update Clock SubCmd Descs
joelsmith-2019 Nov 28, 2023
3c3aa11
Remove Contracts from Genesis
joelsmith-2019 Nov 28, 2023
2070db6
Refactor Request Validation
joelsmith-2019 Nov 28, 2023
b301d75
Use Logger in EndBlocker
joelsmith-2019 Nov 28, 2023
5d737ca
Init EndBlocker Tests
joelsmith-2019 Nov 28, 2023
d6c597f
Test Clock End Blocker
joelsmith-2019 Nov 30, 2023
4d02b19
Upload Clock Contract (No Sudo)
joelsmith-2019 Dec 5, 2023
98a4d50
Add Interchain Clock Helper
joelsmith-2019 Dec 5, 2023
3525248
Add Clock Interchain Tests
joelsmith-2019 Dec 6, 2023
51234f7
Test Unregister Clock
joelsmith-2019 Dec 7, 2023
66ed2be
Update Spec Docs
joelsmith-2019 Dec 8, 2023
1f14c90
Merge branch 'main' of https://github.com/CosmosContracts/juno into j…
joelsmith-2019 Dec 12, 2023
782ff97
remove `SetupContractWithAdmin` and instead use extraFlags
Reecepbcups Dec 12, 2023
6b6010a
wait for 2 blocks in the Clock helpers (ictest thing)
Reecepbcups Dec 12, 2023
d37317f
fix: updateParams contractGasLimit
Reecepbcups Dec 12, 2023
366a6f3
patch e2e no admin flag
Reecepbcups Dec 12, 2023
084bf19
Extract Anon Func
joelsmith-2019 Dec 13, 2023
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
1 change: 1 addition & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,7 @@ func NewAppKeepers(
appKeepers.ClockKeeper = clockkeeper.NewKeeper(
appKeepers.keys[clocktypes.StoreKey],
appCodec,
appKeepers.WasmKeeper,
appKeepers.ContractKeeper,
govModAddress,
)
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
120 changes: 120 additions & 0 deletions interchaintest/helpers/clock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package helpers

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

"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v7/ibc"
"github.com/strangelove-ventures/interchaintest/v7/testutil"
"github.com/stretchr/testify/require"
)

// Register the clock contract
func RegisterClockContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contract string) {
cmd := []string{
"junod", "tx", "clock", "register", contract,
"--node", chain.GetRPCAddress(),
"--home", chain.HomeDir(),
"--chain-id", chain.Config().ChainID,
"--fees", "500ujuno",
"--from", user.KeyName(),
"--keyring-dir", chain.HomeDir(),
"--keyring-backend", keyring.BackendTest,
"-y",
}
stdout, _, err := chain.Exec(ctx, cmd, nil)
require.NoError(t, err)

debugOutput(t, string(stdout))

err = testutil.WaitForBlocks(ctx, 2, chain)
require.NoError(t, err)
}

// Unregister the clock contract
func UnregisterClockContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contract string) {
cmd := []string{
"junod", "tx", "clock", "unregister", contract,
"--node", chain.GetRPCAddress(),
"--home", chain.HomeDir(),
"--chain-id", chain.Config().ChainID,
"--fees", "500ujuno",
"--from", user.KeyName(),
"--keyring-dir", chain.HomeDir(),
"--keyring-backend", keyring.BackendTest,
"-y",
}
stdout, _, err := chain.Exec(ctx, cmd, nil)
require.NoError(t, err)

debugOutput(t, string(stdout))

err = testutil.WaitForBlocks(ctx, 2, chain)
require.NoError(t, err)
}

// Unjail the clock contract
func UnjailClockContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contract string) {
cmd := []string{
"junod", "tx", "clock", "unjail", contract,
"--node", chain.GetRPCAddress(),
"--home", chain.HomeDir(),
"--chain-id", chain.Config().ChainID,
"--fees", "500ujuno",
"--from", user.KeyName(),
"--keyring-dir", chain.HomeDir(),
"--keyring-backend", keyring.BackendTest,
"-y",
}
stdout, _, err := chain.Exec(ctx, cmd, nil)
require.NoError(t, err)

debugOutput(t, string(stdout))

err = testutil.WaitForBlocks(ctx, 2, chain)
require.NoError(t, err)
}

type ClockContract struct {
joelsmith-2019 marked this conversation as resolved.
Show resolved Hide resolved
ClockContract struct {
ContractAddress string `json:"contract_address"`
IsJailed bool `json:"is_jailed"`
} `json:"clock_contract"`
}

// Get the clock contract
func GetClockContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, contract string) ClockContract {
var res ClockContract

cmd := getClockQueryCommand(chain, contract)
stdout, _, err := chain.Exec(ctx, cmd, nil)
require.NoError(t, err)

fmt.Println(string(stdout))

if err := json.Unmarshal(stdout, &res); err != nil {
t.Fatal(err)
}

return res
}

// Validate a contract is not registered with the clock module
func ValidateNoClockContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, contract string) {
cmd := getClockQueryCommand(chain, contract)
_, _, err := chain.Exec(ctx, cmd, nil)
require.Error(t, err)
}

// Get the clock query command
func getClockQueryCommand(chain *cosmos.CosmosChain, contract string) []string {
return []string{"junod", "query", "clock", "contract", contract,
"--node", chain.GetRPCAddress(),
"--chain-id", chain.Config().ChainID,
"--output", "json",
}
}
48 changes: 46 additions & 2 deletions interchaintest/helpers/cosmwasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,61 @@ func SmartQueryString(t *testing.T, ctx context.Context, chain *cosmos.CosmosCha
return err
}

func SetupContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, keyname string, fileLoc string, message string) (codeId, contract string) {
func StoreContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, keyname string, fileLoc string) (codeId string) {
codeId, err := chain.StoreContract(ctx, keyname, fileLoc)
if err != nil {
t.Fatal(err)
}
return codeId
}

func SetupContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, keyname string, fileLoc string, message string, extraFlags ...string) (codeId, contract string) {
codeId = StoreContract(t, ctx, chain, keyname, fileLoc)

needsNoAdminFlag := true
// if extraFlags contains "--admin", switch to false
for _, flag := range extraFlags {
if flag == "--admin" {
needsNoAdminFlag = false
}
}

contractAddr, err := chain.InstantiateContract(ctx, keyname, codeId, message, needsNoAdminFlag, extraFlags...)
if err != nil {
t.Fatal(err)
}

contractAddr, err := chain.InstantiateContract(ctx, keyname, codeId, message, true)
return codeId, contractAddr
}

func MigrateContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, keyname string, contractAddr string, fileLoc string, message string) (codeId, contract string) {
codeId, err := chain.StoreContract(ctx, keyname, fileLoc)
if err != nil {
t.Fatal(err)
}

// Execute migrate tx
cmd := []string{
"junod", "tx", "wasm", "migrate", contractAddr, codeId, message,
"--node", chain.GetRPCAddress(),
"--home", chain.HomeDir(),
"--chain-id", chain.Config().ChainID,
"--from", keyname,
"--gas", "500000",
"--keyring-dir", chain.HomeDir(),
"--keyring-backend", keyring.BackendTest,
"-y",
}

stdout, _, err := chain.Exec(ctx, cmd, nil)
require.NoError(t, err)

debugOutput(t, string(stdout))

if err := testutil.WaitForBlocks(ctx, 2, chain); err != nil {
t.Fatal(err)
}

return codeId, contractAddr
}

Expand Down
96 changes: 87 additions & 9 deletions interchaintest/module_clock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/strangelove-ventures/interchaintest/v7"
"github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v7/ibc"
"github.com/strangelove-ventures/interchaintest/v7/testutil"
"github.com/stretchr/testify/require"

helpers "github.com/CosmosContracts/juno/tests/interchaintest/helpers"
Expand All @@ -33,40 +32,119 @@ func TestJunoClock(t *testing.T) {
users := interchaintest.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), juno, juno)
user := users[0]

// Upload & init contract payment to another address
//
// -- REGULAR GAS CONTRACT --
// Ensure logic works as expected for a contract that uses less than the gas limit
// and has a valid sudo message entry point.
//

// Setup contract
_, contractAddr := helpers.SetupContract(t, ctx, juno, user.KeyName(), "contracts/clock_example.wasm", `{}`)

// Ensure config is 0
res := helpers.GetClockContractValue(t, ctx, juno, contractAddr)
fmt.Printf("- res: %v\n", res.Data.Val)
require.Equal(t, uint32(0), res.Data.Val)

// Submit the proposal to add it to the allowed contracts list
SubmitParamChangeProp(t, ctx, juno, user, []string{contractAddr})
// Register the contract
helpers.RegisterClockContract(t, ctx, juno, user, contractAddr)

// Wait 1 block
_ = testutil.WaitForBlocks(ctx, 1, juno)
// Validate contract is not jailed
contract := helpers.GetClockContract(t, ctx, juno, contractAddr)
require.False(t, contract.ClockContract.IsJailed)

// Validate the contract is now auto incrementing from the end blocker
res = helpers.GetClockContractValue(t, ctx, juno, contractAddr)
fmt.Printf("- res: %v\n", res.Data.Val)
require.GreaterOrEqual(t, res.Data.Val, uint32(1))

// Unregister the contract & ensure it is removed from the store
helpers.UnregisterClockContract(t, ctx, juno, user, contractAddr)
helpers.ValidateNoClockContract(t, ctx, juno, contractAddr)

//
// -- HIGH GAS CONTRACT --
// Ensure contracts that exceed the gas limit are jailed.
//

// Setup contract
_, contractAddr = helpers.SetupContract(t, ctx, juno, user.KeyName(), "contracts/clock_example_high_gas.wasm", `{}`, "--admin", user.FormattedAddress())

// Ensure config is 0
res = helpers.GetClockContractValue(t, ctx, juno, contractAddr)
fmt.Printf("- res: %v\n", res.Data.Val)
require.Equal(t, uint32(0), res.Data.Val)

// Register the contract
helpers.RegisterClockContract(t, ctx, juno, user, contractAddr)

// Validate contract is jailed
contract = helpers.GetClockContract(t, ctx, juno, contractAddr)
require.True(t, contract.ClockContract.IsJailed)

//
// -- MIGRATE CONTRACT --
// Ensure migrations can patch contracts that error or exceed gas limit
// so they can be unjailed.
//

// Migrate the high gas contract to a contract with lower gas usage
helpers.MigrateContract(t, ctx, juno, user.KeyName(), contractAddr, "contracts/clock_example_migrate.wasm", `{}`)

// Unjail the contract
helpers.UnjailClockContract(t, ctx, juno, user, contractAddr)
joelsmith-2019 marked this conversation as resolved.
Show resolved Hide resolved

// Validate contract is not jailed
contract = helpers.GetClockContract(t, ctx, juno, contractAddr)
require.False(t, contract.ClockContract.IsJailed)

// Validate the contract is now auto incrementing from the end blocker
res = helpers.GetClockContractValue(t, ctx, juno, contractAddr)
fmt.Printf("- res: %v\n", res.Data.Val)
require.GreaterOrEqual(t, res.Data.Val, uint32(1))

//
// -- NO SUDO CONTRACT --
// Ensure contracts that do not have a sudo message entry point are jailed.
//

// Setup contract
_, contractAddr = helpers.SetupContract(t, ctx, juno, user.KeyName(), "contracts/clock_example_no_sudo.wasm", `{}`)

// Ensure config is 0
res = helpers.GetClockContractValue(t, ctx, juno, contractAddr)
fmt.Printf("- res: %v\n", res.Data.Val)
require.Equal(t, uint32(0), res.Data.Val)

// Register the contract
helpers.RegisterClockContract(t, ctx, juno, user, contractAddr)

// Validate contract is jailed
contract = helpers.GetClockContract(t, ctx, juno, contractAddr)
require.True(t, contract.ClockContract.IsJailed)

// Validate contract is not auto incrementing
res = helpers.GetClockContractValue(t, ctx, juno, contractAddr)
fmt.Printf("- res: %v\n", res.Data.Val)
require.Equal(t, uint32(0), res.Data.Val)

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

func SubmitParamChangeProp(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contracts []string) string {
func SubmitParamChangeProp(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, gasLimit uint64) string {
govAcc := "juno10d07y265gmmuvt4z0w9aw880jnsr700jvss730"
updateParams := []cosmosproto.Message{
&clocktypes.MsgUpdateParams{
Authority: govAcc,
Params: clocktypes.NewParams(contracts, 1_000_000_000),
Params: clocktypes.Params{
ContractGasLimit: gasLimit,
},
},
}

proposal, err := chain.BuildProposal(updateParams, "Params Add Contract", "params", "ipfs://CID", fmt.Sprintf(`500000000%s`, chain.Config().Denom))
proposal, err := chain.BuildProposal(updateParams, "Params Update Gas Limit", "params", "ipfs://CID", fmt.Sprintf(`500000000%s`, chain.Config().Denom))
require.NoError(t, err, "error building proposal")

txProp, err := chain.SubmitProposal(ctx, user.KeyName(), proposal)
Expand Down
13 changes: 13 additions & 0 deletions proto/juno/clock/v1/clock.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
syntax = "proto3";
package juno.clock.v1;

option go_package = "github.com/CosmosContracts/juno/x/clock/types";

// This object is used to store the contract address and the
// jail status of the contract.
message ClockContract {
// The address of the contract.
string contract_address = 1;
// The jail status of the contract.
bool is_jailed = 2;
}
10 changes: 3 additions & 7 deletions proto/juno/clock/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package juno.clock.v1;

import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "juno/clock/v1/clock.proto";

option go_package = "github.com/CosmosContracts/juno/x/clock/types";

Expand All @@ -17,13 +18,8 @@ message GenesisState {

// Params defines the set of module parameters.
message Params {
// contract_addresses stores the list of executable contracts to be ticked on every block.
repeated string contract_addresses = 1 [
(gogoproto.jsontag) = "contract_addresses,omitempty",
(gogoproto.moretags) = "yaml:\"contract_addresses\""
];

uint64 contract_gas_limit = 2 [
// contract_gas_limit defines the maximum amount of gas that can be used by a contract.
uint64 contract_gas_limit = 1 [
(gogoproto.jsontag) = "contract_gas_limit,omitempty",
(gogoproto.moretags) = "yaml:\"contract_gas_limit\""
];
Expand Down
Loading
Loading