Skip to content

Commit

Permalink
feat(tm2): add sdk/params module (gnolang#2920)
Browse files Browse the repository at this point in the history
- [x] port x/params -> sdk/params
b930513
- [x] inject in vmkeeper + add std.SetConfig
602245d
- [x] implement in `gnoland` 783a044
	- [x] appchain
    - [x] rpc query
    - [x] txtar
- [x] implement or add comment where we should use it in the existing
codebase
	- [x] namespace's realm target
- [ ] questions
- [x] do we want a `std.GetConfig` from the contract part? -> No, it
allows unsafe, complex, and implicit patterns. If you want to get a
value from another contract, you can either import it or use a registry
pattern. This approach preserves type safety and other GNOVM
protections.
- [ ] do we want to restrict the realms able to call `SetConfig` (only
`r/sys`), or maybe set an expensive gas price?
- [x] after discussion with jae
	- [x] Rename Config -> Param for consistency
- [x] Remove `interface{}` from the setters and use specific types,
including in the tm2 implementation (string, uint64, int64, bool, bytes)
- [x] Remove the `.<type>` suffix addition, but ensure that the type is
explicitly defined by the user; and remove the table.
	- [x] Remove the types table from the tm2 implementation

Related gnolang#1418 
Related gnolang#1856

---------

Signed-off-by: moul <[email protected]>
  • Loading branch information
moul authored Oct 23, 2024
1 parent 1a57e81 commit 43dd3f3
Show file tree
Hide file tree
Showing 21 changed files with 901 additions and 31 deletions.
65 changes: 65 additions & 0 deletions gno.land/cmd/gnoland/testdata/params.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# 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"'

-- setter/setter.gno --
package setter

import (
"std"
)

func SetFoo(newFoo string) { std.SetParamString("foo.string", newFoo) }
func SetBar(newBar bool) { std.SetParamBool("bar.bool", newBar) }
func SetBaz(newBaz int64) { std.SetParamInt64("baz.int64", 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 @@ -87,12 +88,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)
paramsKpr := params.NewParamsKeeper(mainKey, "vm")
vmk := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr, paramsKpr)

// 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 @@ -147,6 +149,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 @@ -224,10 +227,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
23 changes: 23 additions & 0 deletions gno.land/pkg/sdk/vm/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,26 @@ func (bnk *SDKBanker) RemoveCoin(b32addr crypto.Bech32Address, denom string, amo
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,
}
}

func (prm *SDKParams) SetString(key, value string) { prm.vmk.prmk.SetString(prm.ctx, key, value) }
func (prm *SDKParams) SetBool(key string, value bool) { prm.vmk.prmk.SetBool(prm.ctx, key, value) }
func (prm *SDKParams) SetInt64(key string, value int64) { prm.vmk.prmk.SetInt64(prm.ctx, key, value) }
func (prm *SDKParams) SetUint64(key string, value uint64) {
prm.vmk.prmk.SetUint64(prm.ctx, key, value)
}
func (prm *SDKParams) SetBytes(key string, value []byte) { prm.vmk.prmk.SetBytes(prm.ctx, key, value) }
4 changes: 3 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,8 @@ 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)
prmk := paramsm.NewParamsKeeper(iavlCapKey, "params")
vmk := NewVMKeeper(baseCapKey, iavlCapKey, acck, bank, prmk)

mcw := ms.MultiCacheWrap()
vmk.Initialize(log.NewNoopLogger(), mcw)
Expand Down
2 changes: 1 addition & 1 deletion gno.land/pkg/sdk/vm/gas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func TestAddPkgDeliverTx(t *testing.T) {
assert.True(t, res.IsOK())

// NOTE: let's try to keep this bellow 100_000 :)
assert.Equal(t, int64(92825), gasDeliver)
assert.Equal(t, int64(93825), gasDeliver)
}

// Enough gas for a failed transaction.
Expand Down
19 changes: 17 additions & 2 deletions gno.land/pkg/sdk/vm/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,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 @@ -59,6 +60,7 @@ type VMKeeper struct {
iavlKey store.StoreKey
acck auth.AccountKeeper
bank bank.BankKeeper
prmk params.ParamsKeeper

// cached, the DeliverTx persistent state.
gnoStore gno.Store
Expand All @@ -70,13 +72,14 @@ func NewVMKeeper(
iavlKey store.StoreKey,
acck auth.AccountKeeper,
bank bank.BankKeeper,
prmk params.ParamsKeeper,
) *VMKeeper {
// TODO: create an Options struct to avoid too many constructor parameters
vmk := &VMKeeper{
baseKey: baseKey,
iavlKey: iavlKey,
acck: acck,
bank: bank,
prmk: prmk,
}
return vmk
}
Expand Down Expand Up @@ -222,9 +225,15 @@ func (vm *VMKeeper) getGnoTransactionStore(ctx sdk.Context) gno.TransactionStore
// Namespace can be either a user or crypto address.
var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([\.~_a-zA-Z0-9]+)`)

const (
sysUsersPkgParamKey = "vm/gno.land/r/sys/params.string"
sysUsersPkgDefault = "gno.land/r/sys/users"
)

// checkNamespacePermission check if the user as given has correct permssion to on the given pkg path
func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Address, pkgPath string) error {
const sysUsersPkg = "gno.land/r/sys/users"
sysUsersPkg := sysUsersPkgDefault
vm.prmk.GetString(ctx, sysUsersPkgParamKey, &sysUsersPkg)

store := vm.getGnoTransactionStore(ctx)

Expand Down Expand Up @@ -258,6 +267,7 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add
OrigPkgAddr: pkgAddr.Bech32(),
// XXX: should we remove the banker ?
Banker: NewSDKBanker(vm, ctx),
Params: NewSDKParams(vm, ctx),
EventLogger: ctx.EventLogger(),
}

Expand Down Expand Up @@ -358,6 +368,7 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) {
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 @@ -458,6 +469,7 @@ func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) {
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 @@ -556,6 +568,7 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) {
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 @@ -715,6 +728,7 @@ func (vm *VMKeeper) QueryEval(ctx sdk.Context, pkgPath string, expr string) (res
// OrigSendSpent: nil,
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx), // safe as long as ctx is a fork to be discarded.
Params: NewSDKParams(vm, ctx),
EventLogger: ctx.EventLogger(),
}
m := gno.NewMachineWithOptions(
Expand Down Expand Up @@ -781,6 +795,7 @@ func (vm *VMKeeper) QueryEvalString(ctx sdk.Context, pkgPath string, expr string
// OrigSendSpent: nil,
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx), // safe as long as ctx is a fork to be discarded.
Params: NewSDKParams(vm, ctx),
EventLogger: ctx.EventLogger(),
}
m := gno.NewMachineWithOptions(
Expand Down
56 changes: 55 additions & 1 deletion 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.SetParamString("foo.string", "foo1")
}
func Do() string {
std.SetParamInt64("bar.int64", int64(1337))
std.SetParamString("foo.string", "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.GetString(ctx, "gno.land/r/test.foo.string", &foo)
env.vmk.prmk.GetInt64(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 All @@ -320,7 +374,7 @@ import "std"
var admin std.Address
func init() {
admin = std.GetOrigCaller()
admin = std.GetOrigCaller()
}
func Echo(msg string) string {
Expand Down
Loading

0 comments on commit 43dd3f3

Please sign in to comment.