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(tm2): add sdk/params module #2920

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
70 changes: 70 additions & 0 deletions gno.land/cmd/gnoland/testdata/params.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# test for https://github.com/gnolang/gno/pull/2920

gnoland start

# query before adding the package
gnokey query params/vm/gno.land/r/sys/setter.foo.string
stdout 'data: $'
gnokey query params/vm/gno.land/r/sys/setter.bar.bool
stdout 'data: $'
gnokey query params/vm/gno.land/r/sys/setter.baz.int64
stdout 'data: $'

gnokey maketx addpkg -pkgdir $WORK/setter -pkgpath gno.land/r/sys/setter -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1

# query after adding the package, but before setting values
gnokey query params/vm/gno.land/r/sys/setter.foo.string
stdout 'data: $'
gnokey query params/vm/gno.land/r/sys/setter.bar.bool
stdout 'data: $'
gnokey query params/vm/gno.land/r/sys/setter.baz.int64
stdout 'data: $'


# set foo (string)
gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetFoo -args foo1 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1
gnokey query params/vm/gno.land/r/sys/setter.foo.string
stdout 'data: "foo1"'

# override foo
gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetFoo -args foo2 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1
gnokey query params/vm/gno.land/r/sys/setter.foo.string
stdout 'data: "foo2"'


# set bar (bool)
gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBar -args true -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1
gnokey query params/vm/gno.land/r/sys/setter.bar.bool
stdout 'data: true'

# override bar
gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBar -args false -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1
gnokey query params/vm/gno.land/r/sys/setter.bar.bool
stdout 'data: false'


# set baz (bool)
gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBaz -args 1337 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1
gnokey query params/vm/gno.land/r/sys/setter.baz.int64
stdout 'data: "1337"'

# override baz
gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBaz -args 31337 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1
gnokey query params/vm/gno.land/r/sys/setter.baz.int64
stdout 'data: "31337"'




# XXX: create a non-sys package that should fail?

-- setter/setter.gno --
package setter

import (
"std"
)

func SetFoo(newFoo string) { std.SetConfig("foo", newFoo) }
func SetBar(newBar bool) { std.SetConfig("bar", newBar) }
func SetBaz(newBaz int64) { std.SetConfig("baz", newBaz) }
16 changes: 10 additions & 6 deletions gno.land/pkg/gnoland/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/gnolang/gno/tm2/pkg/sdk"
"github.com/gnolang/gno/tm2/pkg/sdk/auth"
"github.com/gnolang/gno/tm2/pkg/sdk/bank"
"github.com/gnolang/gno/tm2/pkg/sdk/params"
"github.com/gnolang/gno/tm2/pkg/std"
"github.com/gnolang/gno/tm2/pkg/store"
"github.com/gnolang/gno/tm2/pkg/store/dbadapter"
Expand Down Expand Up @@ -88,12 +89,13 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) {
// Construct keepers.
acctKpr := auth.NewAccountKeeper(mainKey, ProtoGnoAccount)
bankKpr := bank.NewBankKeeper(acctKpr)
vmk := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr, cfg.MaxCycles)
paramsKpr := params.NewParamsKeeper(mainKey, "vm")
vmk := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr, paramsKpr, cfg.MaxCycles)

// Set InitChainer
icc := cfg.InitChainerConfig
icc.baseApp = baseApp
icc.acctKpr, icc.bankKpr, icc.vmKpr = acctKpr, bankKpr, vmk
icc.acctKpr, icc.bankKpr, icc.vmKpr, icc.paramsKpr = acctKpr, bankKpr, vmk, paramsKpr
baseApp.SetInitChainer(icc.InitChainer)

// Set AnteHandler
Expand Down Expand Up @@ -148,6 +150,7 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) {
// Set a handler Route.
baseApp.Router().AddRoute("auth", auth.NewHandler(acctKpr))
baseApp.Router().AddRoute("bank", bank.NewHandler(bankKpr))
baseApp.Router().AddRoute("params", params.NewHandler(paramsKpr))
baseApp.Router().AddRoute("vm", vm.NewHandler(vmk))

// Load latest version.
Expand Down Expand Up @@ -225,10 +228,11 @@ type InitChainerConfig struct {

// These fields are passed directly by NewAppWithOptions, and should not be
// configurable by end-users.
baseApp *sdk.BaseApp
vmKpr vm.VMKeeperI
acctKpr auth.AccountKeeperI
bankKpr bank.BankKeeperI
baseApp *sdk.BaseApp
vmKpr vm.VMKeeperI
acctKpr auth.AccountKeeperI
bankKpr bank.BankKeeperI
paramsKpr params.ParamsKeeperI
}

// InitChainer is the function that can be used as a [sdk.InitChainer].
Expand Down
55 changes: 55 additions & 0 deletions gno.land/pkg/sdk/vm/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import (
"github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/sdk"
"github.com/gnolang/gno/tm2/pkg/sdk/params"
"github.com/gnolang/gno/tm2/pkg/std"
)

Expand Down Expand Up @@ -55,3 +56,57 @@
panic(err)
}
}

// ----------------------------------------
// SDKParams

type SDKParams struct {
vmk *VMKeeper
ctx sdk.Context
}

func NewSDKParams(vmk *VMKeeper, ctx sdk.Context) *SDKParams {
return &SDKParams{
vmk: vmk,
ctx: ctx,
}
}

// SetXXX helpers:
// - dynamically register a new key with the corresponding type in the paramset table (only once).
// - set the value.

func (prm *SDKParams) SetString(key, value string) {
// if !prm.vmk.prmk.Has(prm.ctx, key) {
// XXX: bad workaround, maybe we should have a dedicated "dynamic keeper" allowing to create keys on the go?
if !prm.vmk.prmk.HasTypeKey(key) {
prm.vmk.prmk.RegisterType(params.NewParamSetPair(key, "", validateNoOp))
}
prm.vmk.prmk.Set(prm.ctx, key, value)
}

func (prm *SDKParams) SetBool(key string, value bool) {

Check warning on line 88 in gno.land/pkg/sdk/vm/builtins.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/builtins.go#L88

Added line #L88 was not covered by tests
// if !prm.vmk.prmk.Has(prm.ctx, key) {
if !prm.vmk.prmk.HasTypeKey(key) {
prm.vmk.prmk.RegisterType(params.NewParamSetPair(key, true, validateNoOp))

Check warning on line 91 in gno.land/pkg/sdk/vm/builtins.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/builtins.go#L90-L91

Added lines #L90 - L91 were not covered by tests
}
prm.vmk.prmk.Set(prm.ctx, key, value)

Check warning on line 93 in gno.land/pkg/sdk/vm/builtins.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/builtins.go#L93

Added line #L93 was not covered by tests
}

func (prm *SDKParams) SetInt64(key string, value int64) {
// if !prm.vmk.prmk.Has(prm.ctx, key) {
if !prm.vmk.prmk.HasTypeKey(key) {
prm.vmk.prmk.RegisterType(params.NewParamSetPair(key, int64(0), validateNoOp))
}
prm.vmk.prmk.Set(prm.ctx, key, value)
}

func (prm *SDKParams) SetUint64(key string, value uint64) {

Check warning on line 104 in gno.land/pkg/sdk/vm/builtins.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/builtins.go#L104

Added line #L104 was not covered by tests
// if !prm.vmk.prmk.Has(prm.ctx, key) {
if !prm.vmk.prmk.HasTypeKey(key) {
prm.vmk.prmk.RegisterType(params.NewParamSetPair(key, uint64(0), validateNoOp))

Check warning on line 107 in gno.land/pkg/sdk/vm/builtins.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/builtins.go#L106-L107

Added lines #L106 - L107 were not covered by tests
}
prm.vmk.prmk.Set(prm.ctx, key, value)

Check warning on line 109 in gno.land/pkg/sdk/vm/builtins.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/builtins.go#L109

Added line #L109 was not covered by tests
}

func validateNoOp(_ interface{}) error { return nil }

Check warning on line 112 in gno.land/pkg/sdk/vm/builtins.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/builtins.go#L112

Added line #L112 was not covered by tests
5 changes: 4 additions & 1 deletion gno.land/pkg/sdk/vm/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/gnolang/gno/tm2/pkg/sdk"
authm "github.com/gnolang/gno/tm2/pkg/sdk/auth"
bankm "github.com/gnolang/gno/tm2/pkg/sdk/bank"
paramsm "github.com/gnolang/gno/tm2/pkg/sdk/params"
"github.com/gnolang/gno/tm2/pkg/std"
"github.com/gnolang/gno/tm2/pkg/store"
"github.com/gnolang/gno/tm2/pkg/store/dbadapter"
Expand Down Expand Up @@ -47,7 +48,9 @@ func _setupTestEnv(cacheStdlibs bool) testEnv {
ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{ChainID: "test-chain-id"}, log.NewNoopLogger())
acck := authm.NewAccountKeeper(iavlCapKey, std.ProtoBaseAccount)
bank := bankm.NewBankKeeper(acck)
vmk := NewVMKeeper(baseCapKey, iavlCapKey, acck, bank, 100_000_000)
prmk := paramsm.NewParamsKeeper(iavlCapKey, "params")
maxCycles := int64(100_000_000) // XXX: use x/params for 100_000_000
vmk := NewVMKeeper(baseCapKey, iavlCapKey, acck, bank, prmk, maxCycles)

mcw := ms.MultiCacheWrap()
vmk.Initialize(log.NewNoopLogger(), mcw)
Expand Down
11 changes: 10 additions & 1 deletion gno.land/pkg/sdk/vm/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"github.com/gnolang/gno/tm2/pkg/sdk"
"github.com/gnolang/gno/tm2/pkg/sdk/auth"
"github.com/gnolang/gno/tm2/pkg/sdk/bank"
"github.com/gnolang/gno/tm2/pkg/sdk/params"
"github.com/gnolang/gno/tm2/pkg/std"
"github.com/gnolang/gno/tm2/pkg/store"
"github.com/gnolang/gno/tm2/pkg/store/dbadapter"
Expand Down Expand Up @@ -59,6 +60,7 @@
iavlKey store.StoreKey
acck auth.AccountKeeper
bank bank.BankKeeper
prmk params.ParamsKeeper

// cached, the DeliverTx persistent state.
gnoStore gno.Store
Expand All @@ -72,14 +74,15 @@
iavlKey store.StoreKey,
acck auth.AccountKeeper,
bank bank.BankKeeper,
prmk params.ParamsKeeper,
maxCycles int64,
) *VMKeeper {
// TODO: create an Options struct to avoid too many constructor parameters
vmk := &VMKeeper{
baseKey: baseKey,
iavlKey: iavlKey,
acck: acck,
bank: bank,
prmk: prmk,
maxCycles: maxCycles,
}
return vmk
Expand Down Expand Up @@ -262,6 +265,7 @@
OrigPkgAddr: pkgAddr.Bech32(),
// XXX: should we remove the banker ?
Banker: NewSDKBanker(vm, ctx),
Params: NewSDKParams(vm, ctx),

Check warning on line 268 in gno.land/pkg/sdk/vm/keeper.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/keeper.go#L268

Added line #L268 was not covered by tests
EventLogger: ctx.EventLogger(),
}

Expand Down Expand Up @@ -363,6 +367,7 @@
OrigSendSpent: new(std.Coins),
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx),
Params: NewSDKParams(vm, ctx),
EventLogger: ctx.EventLogger(),
}
// Parse and run the files, construct *PV.
Expand Down Expand Up @@ -464,6 +469,7 @@
OrigSendSpent: new(std.Coins),
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx),
Params: NewSDKParams(vm, ctx),
EventLogger: ctx.EventLogger(),
}
// Construct machine and evaluate.
Expand Down Expand Up @@ -563,6 +569,7 @@
OrigSendSpent: new(std.Coins),
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx),
Params: NewSDKParams(vm, ctx),
EventLogger: ctx.EventLogger(),
}
// Parse and run the files, construct *PV.
Expand Down Expand Up @@ -724,6 +731,7 @@
// OrigSendSpent: nil,
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx), // safe as long as ctx is a fork to be discarded.
Params: NewSDKParams(vm, ctx),

Check warning on line 734 in gno.land/pkg/sdk/vm/keeper.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/keeper.go#L734

Added line #L734 was not covered by tests
EventLogger: ctx.EventLogger(),
}
m := gno.NewMachineWithOptions(
Expand Down Expand Up @@ -791,6 +799,7 @@
// OrigSendSpent: nil,
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx), // safe as long as ctx is a fork to be discarded.
Params: NewSDKParams(vm, ctx),

Check warning on line 802 in gno.land/pkg/sdk/vm/keeper.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/keeper.go#L802

Added line #L802 was not covered by tests
EventLogger: ctx.EventLogger(),
}
m := gno.NewMachineWithOptions(
Expand Down
54 changes: 54 additions & 0 deletions gno.land/pkg/sdk/vm/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,60 @@ func Echo(msg string) string {
assert.Error(t, err)
}

// Using x/params from a realm.
func TestVMKeeperParams(t *testing.T) {
env := setupTestEnv()
ctx := env.vmk.MakeGnoTransactionStore(env.ctx)

// Give "addr1" some gnots.
addr := crypto.AddressFromPreimage([]byte("addr1"))
acc := env.acck.NewAccountWithAddress(ctx, addr)
env.acck.SetAccount(ctx, acc)
env.bank.SetCoins(ctx, addr, std.MustParseCoins(coinsString))
// env.prmk.
assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString)))

// Create test package.
files := []*std.MemFile{
{"init.gno", `
package test

import "std"

func init() {
std.SetConfig("foo", "foo1")
}

func Do() string {
std.SetConfig("bar", int64(1337))
std.SetConfig("foo", "foo2") // override init

return "XXX" // return std.GetConfig("gno.land/r/test.foo"), if we want to expose std.GetConfig, maybe as a std.TestGetConfig
}`},
}
pkgPath := "gno.land/r/test"
msg1 := NewMsgAddPackage(addr, pkgPath, files)
err := env.vmk.AddPackage(ctx, msg1)
assert.NoError(t, err)

// Run Echo function.
coins := std.MustParseCoins(ugnot.ValueString(9_000_000))
msg2 := NewMsgCall(addr, coins, pkgPath, "Do", []string{})

res, err := env.vmk.Call(ctx, msg2)
assert.NoError(t, err)
_ = res
expected := fmt.Sprintf("(\"%s\" string)\n\n", "XXX") // XXX: return something more useful
assert.Equal(t, expected, res)

var foo string
var bar int64
env.vmk.prmk.Get(ctx, "gno.land/r/test.foo.string", &foo)
env.vmk.prmk.Get(ctx, "gno.land/r/test.bar.int64", &bar)
assert.Equal(t, "foo2", foo)
assert.Equal(t, int64(1337), bar)
}

// Assign admin as OrigCaller on deploying the package.
func TestVMKeeperOrigCallerInit(t *testing.T) {
env := setupTestEnv()
Expand Down
Loading
Loading