From 783a044e7505e7fde074bb7a1560b69107132228 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 11 Oct 2024 01:22:35 +0200 Subject: [PATCH] feat: configure params in gno.land Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/cmd/gnoland/testdata/params.txtar | 70 ++++++++++++++++++++++ gno.land/pkg/gnoland/app.go | 16 +++-- gno.land/pkg/sdk/vm/builtins.go | 13 ++-- gnovm/stdlibs/std/params.go | 1 - tm2/pkg/sdk/params/handler.go | 11 ++-- tm2/pkg/sdk/params/keeper.go | 13 ++++ tm2/pkg/sdk/params/table.go | 7 ++- 7 files changed, 113 insertions(+), 18 deletions(-) create mode 100644 gno.land/cmd/gnoland/testdata/params.txtar diff --git a/gno.land/cmd/gnoland/testdata/params.txtar b/gno.land/cmd/gnoland/testdata/params.txtar new file mode 100644 index 00000000000..1c19bc854e1 --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/params.txtar @@ -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) } diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index 2380658c6e9..9caf2f5abd6 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -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" @@ -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 @@ -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. @@ -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]. diff --git a/gno.land/pkg/sdk/vm/builtins.go b/gno.land/pkg/sdk/vm/builtins.go index 3355d6e088e..b679e5ebf2a 100644 --- a/gno.land/pkg/sdk/vm/builtins.go +++ b/gno.land/pkg/sdk/vm/builtins.go @@ -77,28 +77,33 @@ func NewSDKParams(vmk *VMKeeper, ctx sdk.Context) *SDKParams { // - set the value. func (prm *SDKParams) SetString(key, value string) { - if !prm.vmk.prmk.Has(prm.ctx, key) { + // 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) { - if !prm.vmk.prmk.Has(prm.ctx, key) { + // if !prm.vmk.prmk.Has(prm.ctx, key) { + if !prm.vmk.prmk.HasTypeKey(key) { prm.vmk.prmk.RegisterType(params.NewParamSetPair(key, true, validateNoOp)) } prm.vmk.prmk.Set(prm.ctx, key, value) } func (prm *SDKParams) SetInt64(key string, value int64) { - if !prm.vmk.prmk.Has(prm.ctx, key) { + // 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) { - if !prm.vmk.prmk.Has(prm.ctx, key) { + // if !prm.vmk.prmk.Has(prm.ctx, key) { + if !prm.vmk.prmk.HasTypeKey(key) { prm.vmk.prmk.RegisterType(params.NewParamSetPair(key, uint64(0), validateNoOp)) } prm.vmk.prmk.Set(prm.ctx, key, value) diff --git a/gnovm/stdlibs/std/params.go b/gnovm/stdlibs/std/params.go index 008315bfd98..70ecbe6ba1d 100644 --- a/gnovm/stdlibs/std/params.go +++ b/gnovm/stdlibs/std/params.go @@ -18,7 +18,6 @@ type ParamsInterface interface { SetInt64(key string, val int64) SetUint64(key string, val uint64) // XXX: GetString(key string) (string, error)? - } func X_setConfigString(m *gno.Machine, key, val string) { diff --git a/tm2/pkg/sdk/params/handler.go b/tm2/pkg/sdk/params/handler.go index 22b6961bd47..907482db420 100644 --- a/tm2/pkg/sdk/params/handler.go +++ b/tm2/pkg/sdk/params/handler.go @@ -27,11 +27,9 @@ func (bh paramsHandler) Process(ctx sdk.Context, msg std.Msg) sdk.Result { //---------------------------------------- // Query -const QueryParams = "params" - func (bh paramsHandler) Query(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { switch secondPart(req.Path) { - case QueryParams: + case bh.params.prefix: return bh.queryParam(ctx, req) default: res = sdk.ABCIResponseQueryFromError( @@ -49,10 +47,11 @@ func (bh paramsHandler) queryParam(ctx sdk.Context, req abci.RequestQuery) (res std.ErrUnknownRequest("param key is empty")) } - // XXX: validate + // XXX: validate? - panic("not implemented") + val := bh.params.GetRaw(ctx, key) + res.Data = val return } @@ -79,5 +78,5 @@ func thirdPartWithSlashes(path string) string { if secondSlash == -1 { return "" // Return original if less than two slashes } - return path[strings.Index(path, "/")+secondSlash+1:] + return path[strings.Index(path, "/")+secondSlash+2:] } diff --git a/tm2/pkg/sdk/params/keeper.go b/tm2/pkg/sdk/params/keeper.go index e24e216bafe..0f7c14b5f47 100644 --- a/tm2/pkg/sdk/params/keeper.go +++ b/tm2/pkg/sdk/params/keeper.go @@ -11,6 +11,13 @@ import ( "github.com/gnolang/gno/tm2/pkg/store" ) +type ParamsKeeperI interface { + Get(ctx sdk.Context, key string, ptr interface{}) + Set(ctx sdk.Context, key string, value interface{}) +} + +var _ ParamsKeeperI = ParamsKeeper{} + // global paramstore Keeper. type ParamsKeeper struct { key store.StoreKey @@ -145,10 +152,16 @@ func (pk ParamsKeeper) WithKeyTable(table KeyTable) ParamsKeeper { return pk } +// XXX: added, should we remove? func (pk ParamsKeeper) RegisterType(psp ParamSetPair) { pk.table.RegisterType(psp) } +// XXX: added, should we remove? +func (pk ParamsKeeper) HasTypeKey(key string) bool { + return pk.table.HasKey(key) +} + // XXX: GetAllKeys // XXX: GetAllParams // XXX: ViewKeeper diff --git a/tm2/pkg/sdk/params/table.go b/tm2/pkg/sdk/params/table.go index 34747f0e455..dae3b0f62c6 100644 --- a/tm2/pkg/sdk/params/table.go +++ b/tm2/pkg/sdk/params/table.go @@ -43,7 +43,7 @@ func (t KeyTable) RegisterType(psp ParamSetPair) KeyTable { } if _, ok := t.m[psp.Key]; ok { - panic("duplicate parameter key") + panic("duplicate parameter key: " + psp.Key) } rty := reflect.TypeOf(psp.Value) @@ -69,4 +69,9 @@ func (t KeyTable) RegisterParamSet(ps ParamSet) KeyTable { return t } +func (t KeyTable) HasKey(key string) bool { + _, ok := t.m[key] + return ok +} + var isAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString