From b930513083e8485981878f9763bd3b49a25c3785 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 7 Oct 2024 09:43:10 +0200 Subject: [PATCH 01/69] feat(tm2/sdk/params): initial version --- tm2/pkg/sdk/auth/keeper.go | 12 +- tm2/pkg/sdk/bank/keeper.go | 4 +- tm2/pkg/sdk/params/consts.go | 6 + tm2/pkg/sdk/params/doc.go | 13 ++ tm2/pkg/sdk/params/handler.go | 83 ++++++++++++ tm2/pkg/sdk/params/keeper.go | 151 +++++++++++++++++++++ tm2/pkg/sdk/params/keeper_test.go | 209 ++++++++++++++++++++++++++++++ tm2/pkg/sdk/params/paramset.go | 25 ++++ tm2/pkg/sdk/params/table.go | 71 ++++++++++ tm2/pkg/sdk/params/test_common.go | 46 +++++++ tm2/pkg/store/README.md | 12 -- 11 files changed, 612 insertions(+), 20 deletions(-) create mode 100644 tm2/pkg/sdk/params/consts.go create mode 100644 tm2/pkg/sdk/params/doc.go create mode 100644 tm2/pkg/sdk/params/handler.go create mode 100644 tm2/pkg/sdk/params/keeper.go create mode 100644 tm2/pkg/sdk/params/keeper_test.go create mode 100644 tm2/pkg/sdk/params/paramset.go create mode 100644 tm2/pkg/sdk/params/table.go create mode 100644 tm2/pkg/sdk/params/test_common.go diff --git a/tm2/pkg/sdk/auth/keeper.go b/tm2/pkg/sdk/auth/keeper.go index e43b5389844..7669b8ace73 100644 --- a/tm2/pkg/sdk/auth/keeper.go +++ b/tm2/pkg/sdk/auth/keeper.go @@ -31,11 +31,6 @@ func NewAccountKeeper( } } -// Logger returns a module-specific logger. -func (ak AccountKeeper) Logger(ctx sdk.Context) *slog.Logger { - return ctx.Logger().With("module", fmt.Sprintf("auth")) -} - // NewAccountWithAddress implements AccountKeeper. func (ak AccountKeeper) NewAccountWithAddress(ctx sdk.Context, addr crypto.Address) std.Account { acc := ak.proto() @@ -53,7 +48,12 @@ func (ak AccountKeeper) NewAccountWithAddress(ctx sdk.Context, addr crypto.Addre return acc } -// GetAccount implements AccountKeeper. +// Logger returns a module-specific logger. +func (ak AccountKeeper) Logger(ctx sdk.Context) *slog.Logger { + return ctx.Logger().With("module", ModuleName) +} + +// GetAccount returns a specific account in the AccountKeeper. func (ak AccountKeeper) GetAccount(ctx sdk.Context, addr crypto.Address) std.Account { stor := ctx.Store(ak.key) bz := stor.Get(AddressStoreKey(addr)) diff --git a/tm2/pkg/sdk/bank/keeper.go b/tm2/pkg/sdk/bank/keeper.go index 5d3699c99ef..f98e6b3e225 100644 --- a/tm2/pkg/sdk/bank/keeper.go +++ b/tm2/pkg/sdk/bank/keeper.go @@ -25,8 +25,8 @@ type BankKeeperI interface { var _ BankKeeperI = BankKeeper{} -// BBankKeeper only allows transfers between accounts without the possibility of -// creating coins. It implements the BankKeeper interface. +// BankKeeper only allows transfers between accounts without the possibility of +// creating coins. It implements the BankKeeperI interface. type BankKeeper struct { ViewKeeper diff --git a/tm2/pkg/sdk/params/consts.go b/tm2/pkg/sdk/params/consts.go new file mode 100644 index 00000000000..eb829a08b73 --- /dev/null +++ b/tm2/pkg/sdk/params/consts.go @@ -0,0 +1,6 @@ +package params + +const ( + ModuleName = "params" + StoreKey = ModuleName +) diff --git a/tm2/pkg/sdk/params/doc.go b/tm2/pkg/sdk/params/doc.go new file mode 100644 index 00000000000..bf7449adb49 --- /dev/null +++ b/tm2/pkg/sdk/params/doc.go @@ -0,0 +1,13 @@ +// Package params provides a lightweight implementation inspired by the x/params +// module of the Cosmos SDK. +// +// It includes a keeper for managing key-value pairs with module identifiers as +// prefixes, along with a global querier for retrieving any key from any module. +// +// Changes: This version removes the concepts of subspaces and proposals, +// allowing the creation of multiple keepers identified by a provided prefix. +// Proposals may be added later when governance modules are introduced. The +// transient store and .Modified helper have also been removed but can be +// implemented later if needed. Keys are represented as strings instead of +// []byte. +package params diff --git a/tm2/pkg/sdk/params/handler.go b/tm2/pkg/sdk/params/handler.go new file mode 100644 index 00000000000..22b6961bd47 --- /dev/null +++ b/tm2/pkg/sdk/params/handler.go @@ -0,0 +1,83 @@ +package params + +import ( + "fmt" + "strings" + + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/std" +) + +type paramsHandler struct { + params ParamsKeeper +} + +func NewHandler(params ParamsKeeper) paramsHandler { + return paramsHandler{ + params: params, + } +} + +func (bh paramsHandler) Process(ctx sdk.Context, msg std.Msg) sdk.Result { + errMsg := fmt.Sprintf("unrecognized params message type: %T", msg) + return abciResult(std.ErrUnknownRequest(errMsg)) +} + +//---------------------------------------- +// Query + +const QueryParams = "params" + +func (bh paramsHandler) Query(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { + switch secondPart(req.Path) { + case QueryParams: + return bh.queryParam(ctx, req) + default: + res = sdk.ABCIResponseQueryFromError( + std.ErrUnknownRequest("unknown params query endpoint")) + return + } +} + +// queryParam returns param for a key. +func (bh paramsHandler) queryParam(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { + // parse key from path. + key := thirdPartWithSlashes(req.Path) + if key == "" { + res = sdk.ABCIResponseQueryFromError( + std.ErrUnknownRequest("param key is empty")) + } + + // XXX: validate + + panic("not implemented") + + return +} + +//---------------------------------------- +// misc + +func abciResult(err error) sdk.Result { + return sdk.ABCIResultFromError(err) +} + +// returns the second component of a path. +func secondPart(path string) string { + parts := strings.Split(path, "/") + if len(parts) < 2 { + return "" + } else { + return parts[1] + } +} + +// returns the third component of a path, including other slashes. +func thirdPartWithSlashes(path string) string { + secondSlash := strings.Index(path[strings.Index(path, "/")+1:], "/") + if secondSlash == -1 { + return "" // Return original if less than two slashes + } + return path[strings.Index(path, "/")+secondSlash+1:] +} diff --git a/tm2/pkg/sdk/params/keeper.go b/tm2/pkg/sdk/params/keeper.go new file mode 100644 index 00000000000..da1283bd5cf --- /dev/null +++ b/tm2/pkg/sdk/params/keeper.go @@ -0,0 +1,151 @@ +package params + +import ( + "fmt" + "log/slog" + "maps" + "reflect" + + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/store" +) + +// global paramstore Keeper. +type ParamsKeeper struct { + key store.StoreKey + table KeyTable + prefix string +} + +// NewParamsKeeper returns a new ParamsKeeper. +func NewParamsKeeper(key store.StoreKey, prefix string) ParamsKeeper { + return ParamsKeeper{ + key: key, + table: NewKeyTable(), + prefix: prefix, + } +} + +// Logger returns a module-specific logger. +// XXX: why do we expose this? +func (pk ParamsKeeper) Logger(ctx sdk.Context) *slog.Logger { + return ctx.Logger().With("module", ModuleName) +} + +func (pk ParamsKeeper) Has(ctx sdk.Context, key string) bool { + stor := ctx.Store(pk.key) + return stor.Has([]byte(key)) +} + +func (pk ParamsKeeper) Get(ctx sdk.Context, key string, ptr interface{}) { + pk.checkType(key, ptr) + stor := ctx.Store(pk.key) + bz := stor.Get([]byte(key)) + err := amino.UnmarshalJSON(bz, ptr) + if err != nil { + panic(err) + } +} + +func (pk ParamsKeeper) GetIfExists(ctx sdk.Context, key string, ptr interface{}) { + stor := ctx.Store(pk.key) + bz := stor.Get([]byte(key)) + if bz == nil { + return + } + pk.checkType(key, ptr) + err := amino.UnmarshalJSON(bz, ptr) + if err != nil { + panic(err) + } +} + +func (pk ParamsKeeper) GetRaw(ctx sdk.Context, key string) []byte { + stor := ctx.Store(pk.key) + return stor.Get([]byte(key)) +} + +func (pk ParamsKeeper) Set(ctx sdk.Context, key string, value interface{}) { + pk.checkType(key, value) + stor := ctx.Store(pk.key) + bz, err := amino.MarshalJSON(value) + if err != nil { + panic(err) + } + stor.Set([]byte(key), bz) +} + +func (pk ParamsKeeper) Update(ctx sdk.Context, key string, value []byte) error { + attr, ok := pk.table.m[key] + if !ok { + panic(fmt.Sprintf("parameter %s not registered", key)) + } + + ty := attr.ty + dest := reflect.New(ty).Interface() + pk.GetIfExists(ctx, key, dest) + + if err := amino.UnmarshalJSON(value, dest); err != nil { + return err + } + + destValue := reflect.Indirect(reflect.ValueOf(dest)).Interface() + if err := pk.Validate(ctx, key, destValue); err != nil { + return err + } + + pk.Set(ctx, key, dest) + return nil +} + +func (pk ParamsKeeper) Validate(ctx sdk.Context, key string, value interface{}) error { + attr, ok := pk.table.m[key] + if !ok { + return fmt.Errorf("parameter %s not registered", key) + } + + if err := attr.vfn(value); err != nil { + return fmt.Errorf("invalid parameter value: %w", err) + } + + return nil +} + +func (pk ParamsKeeper) checkType(key string, value interface{}) { + attr, ok := pk.table.m[key] + if !ok { + panic(fmt.Sprintf("parameter %s is not registered", key)) + } + + ty := attr.ty + pty := reflect.TypeOf(value) + if pty.Kind() == reflect.Ptr { + pty = pty.Elem() + } + + if pty != ty { + panic("type mismatch with registered table") + } +} + +func (pk ParamsKeeper) HasKeyTable() bool { + return len(pk.table.m) > 0 +} + +func (pk ParamsKeeper) WithKeyTable(table KeyTable) ParamsKeeper { + if table.m == nil { + panic("WithKeyTable() called with nil KeyTable") + } + if len(pk.table.m) != 0 { + panic("WithKeyTable() called on already initialized Keeper") + } + + maps.Copy(pk.table.m, table.m) + return pk +} + +// XXX: GetAllKeys +// XXX: GetAllParams +// XXX: ViewKeeper +// XXX: ModuleKeeper diff --git a/tm2/pkg/sdk/params/keeper_test.go b/tm2/pkg/sdk/params/keeper_test.go new file mode 100644 index 00000000000..6fd1e6ae65b --- /dev/null +++ b/tm2/pkg/sdk/params/keeper_test.go @@ -0,0 +1,209 @@ +package params + +import ( + "reflect" + "testing" + + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/stretchr/testify/require" +) + +// XXX: transient test + +func TestKeeper(t *testing.T) { + kvs := []struct { + key string + param int64 + }{ + {"key1", 10}, + {"key2", 55}, + {"key3", 182}, + {"key4", 17582}, + {"key5", 2768554}, + {"key6", 1157279}, + {"key7", 9058701}, + } + + table := NewKeyTable( + NewParamSetPair("key1", int64(0), validateNoOp), + NewParamSetPair("key2", int64(0), validateNoOp), + NewParamSetPair("key3", int64(0), validateNoOp), + NewParamSetPair("key4", int64(0), validateNoOp), + NewParamSetPair("key5", int64(0), validateNoOp), + NewParamSetPair("key6", int64(0), validateNoOp), + NewParamSetPair("key7", int64(0), validateNoOp), + NewParamSetPair("extra1", bool(false), validateNoOp), + NewParamSetPair("extra2", string(""), validateNoOp), + ) + + env := setupTestEnv() + ctx, store, keeper := env.ctx, env.store, env.keeper + + require.False(t, keeper.HasKeyTable()) + keeper = keeper.WithKeyTable(table) + require.True(t, keeper.HasKeyTable()) + + // Set params + for i, kv := range kvs { + require.NotPanics(t, func() { keeper.Set(ctx, kv.key, kv.param) }, "keeper.Set panics, tc #%d", i) + } + + // Test keeper.Get + for i, kv := range kvs { + var param int64 + require.NotPanics(t, func() { keeper.Get(ctx, kv.key, ¶m) }, "keeper.Get panics, tc #%d", i) + require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) + } + + // Test keeper.GetRaw + for i, kv := range kvs { + var param int64 + bz := keeper.GetRaw(ctx, kv.key) + err := amino.UnmarshalJSON(bz, ¶m) + require.Nil(t, err, "err is not nil, tc #%d", i) + require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) + } + + // Test store.Get equals keeper.Get + for i, kv := range kvs { + var param int64 + bz := store.Get([]byte(kv.key)) + require.NotNil(t, bz, "KVStore.Get returns nil, tc #%d", i) + err := amino.UnmarshalJSON(bz, ¶m) + require.NoError(t, err, "UnmarshalJSON returns error, tc #%d", i) + require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) + } + + // Test invalid keeper.Get + for i, kv := range kvs { + var param bool + require.Panics(t, func() { keeper.Get(ctx, kv.key, ¶m) }, "invalid keeper.Get not panics, tc #%d", i) + } + + // Test invalid keeper.Set + for i, kv := range kvs { + require.Panics(t, func() { keeper.Set(ctx, kv.key, true) }, "invalid keeper.Set not panics, tc #%d", i) + } +} + +// adapted from TestKeeperSubspace from Cosmos SDK, but adapted to a subspace-less Keeper. +func TestKeeper_Subspace(t *testing.T) { + env := setupTestEnv() + ctx, store, keeper := env.ctx, env.store, env.keeper + // XXX: keeper = keeper.WithKeyTable(table) + + // cdc, ctx, key, _, keeper := testComponents() + + kvs := []struct { + key string + param interface{} + zero interface{} + ptr interface{} + }{ + {"string", "test", "", new(string)}, + {"bool", true, false, new(bool)}, + {"int16", int16(1), int16(0), new(int16)}, + {"int32", int32(1), int32(0), new(int32)}, + {"int64", int64(1), int64(0), new(int64)}, + {"uint16", uint16(1), uint16(0), new(uint16)}, + {"uint32", uint32(1), uint32(0), new(uint32)}, + {"uint64", uint64(1), uint64(0), new(uint64)}, + // XXX: {"int", math.NewInt(1), math.Int{}, new(math.Int)}, + // XXX: {"uint", math.NewUint(1), math.Uint{}, new(math.Uint)}, + // XXX: {"dec", math.LegacyNewDec(1), math.LegacyDec{}, new(math.LegacyDec)}, + {"struct", s{1}, s{0}, new(s)}, + } + + table := NewKeyTable( + NewParamSetPair("string", "", validateNoOp), + NewParamSetPair("bool", false, validateNoOp), + NewParamSetPair("int16", int16(0), validateNoOp), + NewParamSetPair("int32", int32(0), validateNoOp), + NewParamSetPair("int64", int64(0), validateNoOp), + NewParamSetPair("uint16", uint16(0), validateNoOp), + NewParamSetPair("uint32", uint32(0), validateNoOp), + NewParamSetPair("uint64", uint64(0), validateNoOp), + // XXX: NewParamSetPair("int", math.Int{}, validateNoOp), + // XXX: NewParamSetPair("uint", math.Uint{}, validateNoOp), + // XXX: NewParamSetPair("dec", math.LegacyDec{}, validateNoOp), + NewParamSetPair("struct", s{}, validateNoOp), + ) + keeper = keeper.WithKeyTable(table) + + // Test keeper.Set, keeper.Modified + for i, kv := range kvs { + // require.False(t, keeper.Modified(ctx, kv.key), "keeper.Modified returns true before setting, tc #%d", i) + require.NotPanics(t, func() { keeper.Set(ctx, kv.key, kv.param) }, "keeper.Set panics, tc #%d", i) + // require.True(t, keeper.Modified(ctx, kv.key), "keeper.Modified returns false after setting, tc #%d", i) + } + + // Test keeper.Get, keeper.GetIfExists + for i, kv := range kvs { + require.NotPanics(t, func() { keeper.GetIfExists(ctx, "invalid", kv.ptr) }, "keeper.GetIfExists panics when no value exists, tc #%d", i) + require.Equal(t, kv.zero, indirect(kv.ptr), "keeper.GetIfExists unmarshalls when no value exists, tc #%d", i) + require.Panics(t, func() { keeper.Get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) + require.Equal(t, kv.zero, indirect(kv.ptr), "invalid keeper.Get unmarshalls when no value exists, tc #%d", i) + + require.NotPanics(t, func() { keeper.GetIfExists(ctx, kv.key, kv.ptr) }, "keeper.GetIfExists panics, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + require.NotPanics(t, func() { keeper.Get(ctx, kv.key, kv.ptr) }, "keeper.Get panics, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + + require.Panics(t, func() { keeper.Get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "invalid keeper.Get unmarshalls when no value existt, tc #%d", i) + + require.Panics(t, func() { keeper.Get(ctx, kv.key, nil) }, "invalid keeper.Get not panics when the pointer is nil, tc #%d", i) + require.Panics(t, func() { keeper.Get(ctx, kv.key, new(invalid)) }, "invalid keeper.Get not panics when the pointer is different type, tc #%d", i) + } + + // Test store.Get equals keeper.Get + for i, kv := range kvs { + bz := store.Get([]byte(kv.key)) + require.NotNil(t, bz, "store.Get() returns nil, tc #%d", i) + err := amino.UnmarshalJSON(bz, kv.ptr) + require.NoError(t, err, "cdc.UnmarshalJSON() returns error, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + } +} + +func TestJSONUpdate(t *testing.T) { + env := setupTestEnv() + ctx, keeper := env.ctx, env.keeper + key := "key" + + space := keeper.WithKeyTable(NewKeyTable(NewParamSetPair(key, paramJSON{}, validateNoOp))) + + var param paramJSON + + err := space.Update(ctx, key, []byte(`{"param1": "10241024"}`)) + require.NoError(t, err) + space.Get(ctx, key, ¶m) + require.Equal(t, paramJSON{10241024, ""}, param) + + err = space.Update(ctx, key, []byte(`{"param2": "helloworld"}`)) + require.NoError(t, err) + space.Get(ctx, key, ¶m) + require.Equal(t, paramJSON{10241024, "helloworld"}, param) + + err = space.Update(ctx, key, []byte(`{"param1": "20482048"}`)) + require.NoError(t, err) + space.Get(ctx, key, ¶m) + require.Equal(t, paramJSON{20482048, "helloworld"}, param) + + err = space.Update(ctx, key, []byte(`{"param1": "40964096", "param2": "goodbyeworld"}`)) + require.NoError(t, err) + space.Get(ctx, key, ¶m) + require.Equal(t, paramJSON{40964096, "goodbyeworld"}, param) +} + +type ( + invalid struct{} + s struct{ I int } + paramJSON struct { + Param1 int64 `json:"param1,omitempty" yaml:"param1,omitempty"` + Param2 string `json:"param2,omitempty" yaml:"param2,omitempty"` + } +) + +func validateNoOp(_ interface{}) error { return nil } +func indirect(ptr interface{}) interface{} { return reflect.ValueOf(ptr).Elem().Interface() } diff --git a/tm2/pkg/sdk/params/paramset.go b/tm2/pkg/sdk/params/paramset.go new file mode 100644 index 00000000000..b401c56e69e --- /dev/null +++ b/tm2/pkg/sdk/params/paramset.go @@ -0,0 +1,25 @@ +package params + +// This file mirrors the original implementation from the Cosmos SDK. + +type ValueValidatorFn func(value interface{}) error + +// ParamSetPair is used for associating param key and field of param structs. +type ParamSetPair struct { + Key string + Value interface{} + ValidatorFn ValueValidatorFn +} + +// NewParamSetPair creates a new ParamSetPair instance. +func NewParamSetPair(key string, value interface{}, vfn ValueValidatorFn) ParamSetPair { + return ParamSetPair{key, value, vfn} +} + +// ParamSetPairs Slice of KeyFieldPair. +type ParamSetPairs []ParamSetPair + +// ParamSet defines an interface for structs containing parameters for a module. +type ParamSet interface { + ParamSetPairs() ParamSetPairs +} diff --git a/tm2/pkg/sdk/params/table.go b/tm2/pkg/sdk/params/table.go new file mode 100644 index 00000000000..1ce6a3b92db --- /dev/null +++ b/tm2/pkg/sdk/params/table.go @@ -0,0 +1,71 @@ +package params + +// This file closely mirrors the original implementation from the Cosmos SDK, with only minor modifications. + +import ( + "reflect" + "regexp" +) + +type attribute struct { + ty reflect.Type + vfn ValueValidatorFn +} + +// KeyTable subspaces appropriate type for each parameter key +type KeyTable struct { + m map[string]attribute +} + +func NewKeyTable(pairs ...ParamSetPair) KeyTable { + keyTable := KeyTable{ + m: make(map[string]attribute), + } + + for _, psp := range pairs { + keyTable = keyTable.RegisterType(psp) + } + + return keyTable +} + +// RegisterType registers a single ParamSetPair (key-type pair) in a KeyTable. +func (t KeyTable) RegisterType(psp ParamSetPair) KeyTable { + if len(psp.Key) == 0 { + panic("cannot register ParamSetPair with an parameter empty key") + } + if !isAlphaNumeric(psp.Key) { + panic("cannot register ParamSetPair with a non-alphanumeric parameter key") + } + if psp.ValidatorFn == nil { + panic("cannot register ParamSetPair without a value validation function") + } + + if _, ok := t.m[psp.Key]; ok { + panic("duplicate parameter key") + } + + rty := reflect.TypeOf(psp.Value) + + // indirect rty if it is a pointer + for rty.Kind() == reflect.Ptr { + rty = rty.Elem() + } + + t.m[psp.Key] = attribute{ + vfn: psp.ValidatorFn, + ty: rty, + } + + return t +} + +// RegisterParamSet registers multiple ParamSetPairs from a ParamSet in a KeyTable. +func (t KeyTable) RegisterParamSet(ps ParamSet) KeyTable { + for _, psp := range ps.ParamSetPairs() { + t = t.RegisterType(psp) + } + return t +} + +var isAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString diff --git a/tm2/pkg/sdk/params/test_common.go b/tm2/pkg/sdk/params/test_common.go new file mode 100644 index 00000000000..8243ee867de --- /dev/null +++ b/tm2/pkg/sdk/params/test_common.go @@ -0,0 +1,46 @@ +package params + +import ( + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/db/memdb" + "github.com/gnolang/gno/tm2/pkg/log" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/store" + "github.com/gnolang/gno/tm2/pkg/store/iavl" +) + +type testEnv struct { + ctx sdk.Context + store store.Store + keeper ParamsKeeper +} + +func setupTestEnv() testEnv { + db := memdb.NewMemDB() + paramsCapKey := store.NewStoreKey("paramsCapKey") + ms := store.NewCommitMultiStore(db) + ms.MountStoreWithDB(paramsCapKey, iavl.StoreConstructor, db) + ms.LoadLatestVersion() + + prefix := "params_test" + keeper := NewParamsKeeper(paramsCapKey, prefix) + + ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{Height: 1, ChainID: "test-chain-id"}, log.NewNoopLogger()) + // XXX: context key? + ctx = ctx.WithConsensusParams(&abci.ConsensusParams{ + Block: &abci.BlockParams{ + MaxTxBytes: 1024, + MaxDataBytes: 1024 * 100, + MaxBlockBytes: 1024 * 100, + MaxGas: 10 * 1000 * 1000, + TimeIotaMS: 10, + }, + Validator: &abci.ValidatorParams{ + PubKeyTypeURLs: []string{}, // XXX + }, + }) + + stor := ctx.Store(paramsCapKey) + return testEnv{ctx: ctx, store: stor, keeper: keeper} +} diff --git a/tm2/pkg/store/README.md b/tm2/pkg/store/README.md index abf5c26bc07..24ae0c805ac 100644 --- a/tm2/pkg/store/README.md +++ b/tm2/pkg/store/README.md @@ -116,15 +116,3 @@ type traceOperation struct { ``` `traceOperation.Metadata` is filled with `Store.context` when it is not nil. `TraceContext` is a `map[string]interface{}`. - -## Transient - -`transient.Store` is a base-layer `KVStore` which is automatically discarded at the end of the block. - -```go -type Store struct { - dbadapter.Store -} -``` - -`Store.Store` is a `dbadapter.Store` with a `memdb.NewMemDB()`. All `KVStore` methods are reused. When `Store.Commit()` is called, new `dbadapter.Store` is assigned, discarding previous reference and making it garbage collected. From 602245d2efde7af76fd9846c57a91838b2024f2d Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 9 Oct 2024 06:52:31 +0200 Subject: [PATCH 02/69] feat: inject ParamsKeeper in VMKeeper Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/sdk/vm/builtins.go | 50 ++++++++++++++ gno.land/pkg/sdk/vm/common_test.go | 5 +- gno.land/pkg/sdk/vm/keeper.go | 11 ++- gno.land/pkg/sdk/vm/keeper_test.go | 54 +++++++++++++++ gnovm/stdlibs/generated.go | 104 +++++++++++++++++++++++++++++ gnovm/stdlibs/std/context.go | 1 + gnovm/stdlibs/std/params.gno | 28 ++++++++ gnovm/stdlibs/std/params.go | 62 +++++++++++++++++ misc/genstd/Makefile | 6 ++ tm2/pkg/sdk/params/doc.go | 2 + tm2/pkg/sdk/params/keeper.go | 4 ++ tm2/pkg/sdk/params/table.go | 5 +- 12 files changed, 328 insertions(+), 4 deletions(-) create mode 100644 gnovm/stdlibs/std/params.gno create mode 100644 gnovm/stdlibs/std/params.go create mode 100644 misc/genstd/Makefile diff --git a/gno.land/pkg/sdk/vm/builtins.go b/gno.land/pkg/sdk/vm/builtins.go index de58cd3e8ae..3355d6e088e 100644 --- a/gno.land/pkg/sdk/vm/builtins.go +++ b/gno.land/pkg/sdk/vm/builtins.go @@ -3,6 +3,7 @@ package vm 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" ) @@ -55,3 +56,52 @@ 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, + } +} + +// 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) { + 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) { + 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) { + 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) { + prm.vmk.prmk.RegisterType(params.NewParamSetPair(key, uint64(0), validateNoOp)) + } + prm.vmk.prmk.Set(prm.ctx, key, value) +} + +func validateNoOp(_ interface{}) error { return nil } diff --git a/gno.land/pkg/sdk/vm/common_test.go b/gno.land/pkg/sdk/vm/common_test.go index 43a8fe1fbec..e3acb278fb6 100644 --- a/gno.land/pkg/sdk/vm/common_test.go +++ b/gno.land/pkg/sdk/vm/common_test.go @@ -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" @@ -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) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 365473b3e7a..d6c6e4e63d1 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -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" @@ -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 @@ -72,14 +74,15 @@ func NewVMKeeper( 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 @@ -262,6 +265,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(), } @@ -363,6 +367,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. @@ -464,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. @@ -563,6 +569,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. @@ -724,6 +731,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( @@ -791,6 +799,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( diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index 9257da2ddaf..9f3c3e422bf 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -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() diff --git a/gnovm/stdlibs/generated.go b/gnovm/stdlibs/generated.go index 4c460e220b7..e6eca53ffe3 100644 --- a/gnovm/stdlibs/generated.go +++ b/gnovm/stdlibs/generated.go @@ -721,6 +721,110 @@ var nativeFuncs = [...]NativeFunc{ )) }, }, + { + "std", + "setConfigString", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("string")}, + }, + []gno.FieldTypeExpr{}, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 string + rp1 = reflect.ValueOf(&p1).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) + + libs_std.X_setConfigString( + m, + p0, p1) + }, + }, + { + "std", + "setConfigBool", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("bool")}, + }, + []gno.FieldTypeExpr{}, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 bool + rp1 = reflect.ValueOf(&p1).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) + + libs_std.X_setConfigBool( + m, + p0, p1) + }, + }, + { + "std", + "setConfigInt64", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("int64")}, + }, + []gno.FieldTypeExpr{}, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 int64 + rp1 = reflect.ValueOf(&p1).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) + + libs_std.X_setConfigInt64( + m, + p0, p1) + }, + }, + { + "std", + "setConfigUint64", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("uint64")}, + }, + []gno.FieldTypeExpr{}, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 uint64 + rp1 = reflect.ValueOf(&p1).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) + + libs_std.X_setConfigUint64( + m, + p0, p1) + }, + }, { "strconv", "Itoa", diff --git a/gnovm/stdlibs/std/context.go b/gnovm/stdlibs/std/context.go index ff5c91a14eb..a0dafe5dc44 100644 --- a/gnovm/stdlibs/std/context.go +++ b/gnovm/stdlibs/std/context.go @@ -18,6 +18,7 @@ type ExecContext struct { OrigSend std.Coins OrigSendSpent *std.Coins // mutable Banker BankerInterface + Params ParamsInterface EventLogger *sdk.EventLogger } diff --git a/gnovm/stdlibs/std/params.gno b/gnovm/stdlibs/std/params.gno new file mode 100644 index 00000000000..a3dc47d4bd4 --- /dev/null +++ b/gnovm/stdlibs/std/params.gno @@ -0,0 +1,28 @@ +package std + +// These are native bindings to the banker's functions. +func setConfigString(key string, val string) +func setConfigBool(key string, val bool) +func setConfigInt64(key string, val int64) +func setConfigUint64(key string, val uint64) + +// XXX: add doc +func SetConfig(key string, val interface{}) { + switch v := val.(type) { + case string: + setConfigString(key, v) + case bool: + setConfigBool(key, v) + case int64: + setConfigInt64(key, v) + case uint64: + setConfigUint64(key, v) + default: + panic("unsupported type") + } +} + +// XXX: add doc +//func GetConfig(key string) string { +// return getConfig(key) +//} diff --git a/gnovm/stdlibs/std/params.go b/gnovm/stdlibs/std/params.go new file mode 100644 index 00000000000..008315bfd98 --- /dev/null +++ b/gnovm/stdlibs/std/params.go @@ -0,0 +1,62 @@ +package std + +import ( + "fmt" + "unicode" + + gno "github.com/gnolang/gno/gnovm/pkg/gnolang" +) + +// ParamsInterface is the interface through which Gno is capable of accessing +// the blockchain's params. +// +// The name is what it is to avoid a collision with Gno's Params, when +// transpiling. +type ParamsInterface interface { + SetString(key, val string) + SetBool(key string, val bool) + 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) { + pk := pkey(m, key, "string") + GetContext(m).Params.SetString(pk, val) +} + +func X_setConfigBool(m *gno.Machine, key string, val bool) { + pk := pkey(m, key, "bool") + GetContext(m).Params.SetBool(pk, val) +} + +func X_setConfigInt64(m *gno.Machine, key string, val int64) { + pk := pkey(m, key, "int64") + GetContext(m).Params.SetInt64(pk, val) +} + +func X_setConfigUint64(m *gno.Machine, key string, val uint64) { + pk := pkey(m, key, "uint64") + GetContext(m).Params.SetUint64(pk, val) +} + +func pkey(m *gno.Machine, key string, kind string) string { + // validate key. + if len(key) == 0 { + panic("empty param key") + } + first := rune(key[0]) + if !unicode.IsLetter(first) && first != '_' { + panic("invalid param key: " + key) + } + for _, char := range key[1:] { + if !unicode.IsLetter(char) && !unicode.IsDigit(char) && char != '_' { + panic("invalid param key: " + key) + } + } + + // decorate key with realm and type. + _, rlmPath := currentRealm(m) + return fmt.Sprintf("%s.%s.%s", rlmPath, key, kind) +} diff --git a/misc/genstd/Makefile b/misc/genstd/Makefile new file mode 100644 index 00000000000..2022a6cc2b4 --- /dev/null +++ b/misc/genstd/Makefile @@ -0,0 +1,6 @@ +run: + cd ../../gnovm/stdlibs && go run ../../misc/genstd + cd ../../gnovm/tests/stdlibs && go run ../../../misc/genstd + +test: + go test -v . diff --git a/tm2/pkg/sdk/params/doc.go b/tm2/pkg/sdk/params/doc.go index bf7449adb49..a433b5eb115 100644 --- a/tm2/pkg/sdk/params/doc.go +++ b/tm2/pkg/sdk/params/doc.go @@ -10,4 +10,6 @@ // transient store and .Modified helper have also been removed but can be // implemented later if needed. Keys are represented as strings instead of // []byte. +// +// XXX: removes isAlphaNum validation for keys. package params diff --git a/tm2/pkg/sdk/params/keeper.go b/tm2/pkg/sdk/params/keeper.go index da1283bd5cf..e24e216bafe 100644 --- a/tm2/pkg/sdk/params/keeper.go +++ b/tm2/pkg/sdk/params/keeper.go @@ -145,6 +145,10 @@ func (pk ParamsKeeper) WithKeyTable(table KeyTable) ParamsKeeper { return pk } +func (pk ParamsKeeper) RegisterType(psp ParamSetPair) { + pk.table.RegisterType(psp) +} + // XXX: GetAllKeys // XXX: GetAllParams // XXX: ViewKeeper diff --git a/tm2/pkg/sdk/params/table.go b/tm2/pkg/sdk/params/table.go index 1ce6a3b92db..34747f0e455 100644 --- a/tm2/pkg/sdk/params/table.go +++ b/tm2/pkg/sdk/params/table.go @@ -34,9 +34,10 @@ func (t KeyTable) RegisterType(psp ParamSetPair) KeyTable { if len(psp.Key) == 0 { panic("cannot register ParamSetPair with an parameter empty key") } - if !isAlphaNumeric(psp.Key) { + // XXX: sanitize more? + /*if !isAlphaNumeric(psp.Key) { panic("cannot register ParamSetPair with a non-alphanumeric parameter key") - } + }*/ if psp.ValidatorFn == nil { panic("cannot register ParamSetPair without a value validation function") } 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 03/69] 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 From 89e046ce8534fba873d22b5398ad7eb3dc9b128f Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 09:14:10 -0500 Subject: [PATCH 04/69] chore: remove unused param Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/cmd/gnoland/start.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go index 21f0cb4b1a6..d871cb65aa1 100644 --- a/gno.land/cmd/gnoland/start.go +++ b/gno.land/cmd/gnoland/start.go @@ -51,7 +51,6 @@ type startCfg struct { genesisFile string chainID string dataDir string - genesisMaxVMCycles int64 config string lazyInit bool @@ -137,13 +136,6 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { "replacement for '%%REMOTE%%' in genesis", ) - fs.Int64Var( - &c.genesisMaxVMCycles, - "genesis-max-vm-cycles", - 100_000_000, - "set maximum allowed vm cycles per operation. Zero means no limit.", - ) - fs.StringVar( &c.config, flagConfigFlag, From 5d1e36a59db9730a41cc2abbb934a77a2d26e501 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 09:20:35 -0500 Subject: [PATCH 05/69] chore: disable --flag-config-path Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/cmd/gnoland/root.go | 10 +--------- gno.land/cmd/gnoland/start.go | 8 -------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/gno.land/cmd/gnoland/root.go b/gno.land/cmd/gnoland/root.go index 8df716b1fed..b40a1160b0b 100644 --- a/gno.land/cmd/gnoland/root.go +++ b/gno.land/cmd/gnoland/root.go @@ -5,12 +5,8 @@ import ( "os" "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/peterbourgon/ff/v3" - "github.com/peterbourgon/ff/v3/fftoml" ) -const flagConfigFlag = "flag-config-path" - func main() { cmd := newRootCmd(commands.NewDefaultIO()) @@ -21,11 +17,7 @@ func newRootCmd(io commands.IO) *commands.Command { cmd := commands.NewCommand( commands.Metadata{ ShortUsage: " [flags] [...]", - ShortHelp: "starts the gnoland blockchain node", - Options: []ff.Option{ - ff.WithConfigFileFlag(flagConfigFlag), - ff.WithConfigFileParser(fftoml.Parser), - }, + ShortHelp: "manages the gnoland blockchain node", }, commands.NewEmptyConfig(), commands.HelpExec, diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go index 21f0cb4b1a6..689c102722b 100644 --- a/gno.land/cmd/gnoland/start.go +++ b/gno.land/cmd/gnoland/start.go @@ -52,7 +52,6 @@ type startCfg struct { chainID string dataDir string genesisMaxVMCycles int64 - config string lazyInit bool logLevel string @@ -144,13 +143,6 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { "set maximum allowed vm cycles per operation. Zero means no limit.", ) - fs.StringVar( - &c.config, - flagConfigFlag, - "", - "the flag config file (optional)", - ) - fs.StringVar( &c.logLevel, "log-level", From a39d1721739cddd4f4a470f55d92a7989188ff0f Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:08:25 -0500 Subject: [PATCH 06/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/sdk/vm/gas_test.go | 2 +- gno.land/pkg/sdk/vm/keeper.go | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/gno.land/pkg/sdk/vm/gas_test.go b/gno.land/pkg/sdk/vm/gas_test.go index 4171b1cdbc3..53809a7f223 100644 --- a/gno.land/pkg/sdk/vm/gas_test.go +++ b/gno.land/pkg/sdk/vm/gas_test.go @@ -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. diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index d6c6e4e63d1..3118862a945 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -229,9 +229,12 @@ 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" + // 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" + var sysUsersPkg = "gno.land/r/sys/users" + vm.prmk.GetIfExists(ctx, sysUsersPkgParamKey, &sysUsersPkg) store := vm.getGnoTransactionStore(ctx) From 0342b61fa79bf6116ad85205ee174720181774e8 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:18:07 -0500 Subject: [PATCH 07/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/sdk/vm/keeper.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 3118862a945..616e755ed31 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -230,10 +230,11 @@ func (vm *VMKeeper) getGnoTransactionStore(ctx sdk.Context) gno.TransactionStore var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([\.~_a-zA-Z0-9]+)`) const sysUsersPkgParamKey = "vm/gno.land/r/sys/params.string" +const defaultSysUsersPkg = "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 { - var sysUsersPkg = "gno.land/r/sys/users" + sysUsersPkg := defaultSysUsersPkg vm.prmk.GetIfExists(ctx, sysUsersPkgParamKey, &sysUsersPkg) store := vm.getGnoTransactionStore(ctx) From dd8ca08b58067880c9000469ecf59a7f80bc587b Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 12:25:24 -0500 Subject: [PATCH 08/69] chore: remove vmkeeper.maxcycles Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoland/app.go | 3 +- gno.land/pkg/gnoland/node_inmemory.go | 1 - gno.land/pkg/gnoland/vals.go | 61 --------------- gno.land/pkg/sdk/vm/keeper.go | 103 ++++++++++++-------------- 4 files changed, 47 insertions(+), 121 deletions(-) delete mode 100644 gno.land/pkg/gnoland/vals.go diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index 2380658c6e9..ca746dbe386 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -34,7 +34,6 @@ type AppOptions struct { DB dbm.DB // required Logger *slog.Logger // required EventSwitch events.EventSwitch // required - MaxCycles int64 // hard limit for cycles in GnoVM InitChainerConfig // options related to InitChainer } @@ -88,7 +87,7 @@ 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) + vmk := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr) // Set InitChainer icc := cfg.InitChainerConfig diff --git a/gno.land/pkg/gnoland/node_inmemory.go b/gno.land/pkg/gnoland/node_inmemory.go index d168c955607..5352f810a94 100644 --- a/gno.land/pkg/gnoland/node_inmemory.go +++ b/gno.land/pkg/gnoland/node_inmemory.go @@ -106,7 +106,6 @@ func NewInMemoryNode(logger *slog.Logger, cfg *InMemoryNodeConfig) (*node.Node, // Initialize the application with the provided options gnoApp, err := NewAppWithOptions(&AppOptions{ Logger: logger, - MaxCycles: cfg.GenesisMaxVMCycles, DB: cfg.DB, EventSwitch: evsw, InitChainerConfig: cfg.InitChainerConfig, diff --git a/gno.land/pkg/gnoland/vals.go b/gno.land/pkg/gnoland/vals.go deleted file mode 100644 index 1843dff3984..00000000000 --- a/gno.land/pkg/gnoland/vals.go +++ /dev/null @@ -1,61 +0,0 @@ -package gnoland - -import ( - "regexp" - - gnovm "github.com/gnolang/gno/gnovm/stdlibs/std" - "github.com/gnolang/gno/tm2/pkg/bft/types" - "github.com/gnolang/gno/tm2/pkg/events" -) - -const ( - valRealm = "gno.land/r/sys/validators" - valChangesFn = "GetChanges" - - validatorAddedEvent = "ValidatorAdded" - validatorRemovedEvent = "ValidatorRemoved" -) - -// XXX: replace with amino-based clean approach -var valRegexp = regexp.MustCompile(`{\("([^"]*)"\s[^)]+\),\("((?:[^"]|\\")*)"\s[^)]+\),\((\d+)\s[^)]+\)}`) - -// validatorUpdate is a type being used for "notifying" -// that a validator change happened on-chain. The events from `r/sys/validators` -// do not pass data related to validator add / remove instances (who, what, how) -type validatorUpdate struct{} - -// validatorEventFilter filters the given event to determine if it -// is tied to a validator update -func validatorEventFilter(event events.Event) []validatorUpdate { - // Make sure the event is a new TX event - txResult, ok := event.(types.EventTx) - if !ok { - return nil - } - - // Make sure an add / remove event happened - for _, ev := range txResult.Result.Response.Events { - // Make sure the event is a GnoVM event - gnoEv, ok := ev.(gnovm.GnoEvent) - if !ok { - continue - } - - // Make sure the event is from `r/sys/validators` - if gnoEv.PkgPath != valRealm { - continue - } - - // Make sure the event is either an add / remove - switch gnoEv.Type { - case validatorAddedEvent, validatorRemovedEvent: - // We don't pass data around with the events, but a single - // notification is enough to "trigger" a VM scrape - return []validatorUpdate{{}} - default: - continue - } - } - - return nil -} diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 365473b3e7a..f069cce3723 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -62,8 +62,6 @@ type VMKeeper struct { // cached, the DeliverTx persistent state. gnoStore gno.Store - - maxCycles int64 // max allowed cylces on VM executions } // NewVMKeeper returns a new VMKeeper. @@ -72,15 +70,13 @@ func NewVMKeeper( iavlKey store.StoreKey, acck auth.AccountKeeper, bank bank.BankKeeper, - maxCycles int64, ) *VMKeeper { // TODO: create an Options struct to avoid too many constructor parameters vmk := &VMKeeper{ - baseKey: baseKey, - iavlKey: iavlKey, - acck: acck, - bank: bank, - maxCycles: maxCycles, + baseKey: baseKey, + iavlKey: iavlKey, + acck: acck, + bank: bank, } return vmk } @@ -267,13 +263,12 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: os.Stdout, // XXX - Store: store, - Context: msgCtx, - Alloc: store.GetAllocator(), - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: os.Stdout, // XXX + Store: store, + Context: msgCtx, + Alloc: store.GetAllocator(), + GasMeter: ctx.GasMeter(), }) defer m.Release() @@ -368,13 +363,12 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { // Parse and run the files, construct *PV. m2 := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: os.Stdout, // XXX - Store: gnostore, - Alloc: gnostore.GetAllocator(), - Context: msgCtx, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: os.Stdout, // XXX + Store: gnostore, + Alloc: gnostore.GetAllocator(), + Context: msgCtx, + GasMeter: ctx.GasMeter(), }) defer m2.Release() defer func() { @@ -469,13 +463,12 @@ func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { // Construct machine and evaluate. m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: os.Stdout, // XXX - Store: gnostore, - Context: msgCtx, - Alloc: gnostore.GetAllocator(), - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: os.Stdout, // XXX + Store: gnostore, + Context: msgCtx, + Alloc: gnostore.GetAllocator(), + GasMeter: ctx.GasMeter(), }) defer m.Release() m.SetActivePackage(mpv) @@ -569,13 +562,12 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { buf := new(bytes.Buffer) m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: buf, - Store: gnostore, - Alloc: gnostore.GetAllocator(), - Context: msgCtx, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: buf, + Store: gnostore, + Alloc: gnostore.GetAllocator(), + Context: msgCtx, + GasMeter: ctx.GasMeter(), }) // XXX MsgRun does not have pkgPath. How do we find it on chain? defer m.Release() @@ -596,13 +588,12 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { m2 := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: buf, - Store: gnostore, - Alloc: gnostore.GetAllocator(), - Context: msgCtx, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: buf, + Store: gnostore, + Alloc: gnostore.GetAllocator(), + Context: msgCtx, + GasMeter: ctx.GasMeter(), }) defer m2.Release() m2.SetActivePackage(pv) @@ -728,13 +719,12 @@ func (vm *VMKeeper) QueryEval(ctx sdk.Context, pkgPath string, expr string) (res } m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: pkgPath, - Output: os.Stdout, // XXX - Store: gnostore, - Context: msgCtx, - Alloc: alloc, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: pkgPath, + Output: os.Stdout, // XXX + Store: gnostore, + Context: msgCtx, + Alloc: alloc, + GasMeter: ctx.GasMeter(), }) defer m.Release() defer func() { @@ -795,13 +785,12 @@ func (vm *VMKeeper) QueryEvalString(ctx sdk.Context, pkgPath string, expr string } m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: pkgPath, - Output: os.Stdout, // XXX - Store: gnostore, - Context: msgCtx, - Alloc: alloc, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: pkgPath, + Output: os.Stdout, // XXX + Store: gnostore, + Context: msgCtx, + Alloc: alloc, + GasMeter: ctx.GasMeter(), }) defer m.Release() defer func() { From e573b6a59764f26d46ca512c4208cef88b797f39 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 12:31:56 -0500 Subject: [PATCH 09/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoland/validators.go | 61 ++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 gno.land/pkg/gnoland/validators.go diff --git a/gno.land/pkg/gnoland/validators.go b/gno.land/pkg/gnoland/validators.go new file mode 100644 index 00000000000..1843dff3984 --- /dev/null +++ b/gno.land/pkg/gnoland/validators.go @@ -0,0 +1,61 @@ +package gnoland + +import ( + "regexp" + + gnovm "github.com/gnolang/gno/gnovm/stdlibs/std" + "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/events" +) + +const ( + valRealm = "gno.land/r/sys/validators" + valChangesFn = "GetChanges" + + validatorAddedEvent = "ValidatorAdded" + validatorRemovedEvent = "ValidatorRemoved" +) + +// XXX: replace with amino-based clean approach +var valRegexp = regexp.MustCompile(`{\("([^"]*)"\s[^)]+\),\("((?:[^"]|\\")*)"\s[^)]+\),\((\d+)\s[^)]+\)}`) + +// validatorUpdate is a type being used for "notifying" +// that a validator change happened on-chain. The events from `r/sys/validators` +// do not pass data related to validator add / remove instances (who, what, how) +type validatorUpdate struct{} + +// validatorEventFilter filters the given event to determine if it +// is tied to a validator update +func validatorEventFilter(event events.Event) []validatorUpdate { + // Make sure the event is a new TX event + txResult, ok := event.(types.EventTx) + if !ok { + return nil + } + + // Make sure an add / remove event happened + for _, ev := range txResult.Result.Response.Events { + // Make sure the event is a GnoVM event + gnoEv, ok := ev.(gnovm.GnoEvent) + if !ok { + continue + } + + // Make sure the event is from `r/sys/validators` + if gnoEv.PkgPath != valRealm { + continue + } + + // Make sure the event is either an add / remove + switch gnoEv.Type { + case validatorAddedEvent, validatorRemovedEvent: + // We don't pass data around with the events, but a single + // notification is enough to "trigger" a VM scrape + return []validatorUpdate{{}} + default: + continue + } + } + + return nil +} From 993d2130dce9a58fd6ad8734ceb83e83fc36eb7f Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 12:43:03 -0500 Subject: [PATCH 10/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/sdk/vm/common_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gno.land/pkg/sdk/vm/common_test.go b/gno.land/pkg/sdk/vm/common_test.go index 43a8fe1fbec..66975fba923 100644 --- a/gno.land/pkg/sdk/vm/common_test.go +++ b/gno.land/pkg/sdk/vm/common_test.go @@ -47,7 +47,7 @@ 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) + vmk := NewVMKeeper(baseCapKey, iavlCapKey, acck, bank) mcw := ms.MultiCacheWrap() vmk.Initialize(log.NewNoopLogger(), mcw) From 95384ae6a9267e6d0f40a9fcfa58a63808f75d48 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 20:27:18 -0500 Subject: [PATCH 11/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- tm2/pkg/sdk/params/consts.go | 6 - tm2/pkg/sdk/params/keeper.go | 189 ++++++++++++------------- tm2/pkg/sdk/params/keeper_test.go | 226 +++++++++++------------------- tm2/pkg/sdk/params/paramset.go | 25 ---- tm2/pkg/sdk/params/table.go | 77 ---------- 5 files changed, 170 insertions(+), 353 deletions(-) delete mode 100644 tm2/pkg/sdk/params/consts.go delete mode 100644 tm2/pkg/sdk/params/paramset.go delete mode 100644 tm2/pkg/sdk/params/table.go diff --git a/tm2/pkg/sdk/params/consts.go b/tm2/pkg/sdk/params/consts.go deleted file mode 100644 index eb829a08b73..00000000000 --- a/tm2/pkg/sdk/params/consts.go +++ /dev/null @@ -1,6 +0,0 @@ -package params - -const ( - ModuleName = "params" - StoreKey = ModuleName -) diff --git a/tm2/pkg/sdk/params/keeper.go b/tm2/pkg/sdk/params/keeper.go index 0f7c14b5f47..ffeb1775acb 100644 --- a/tm2/pkg/sdk/params/keeper.go +++ b/tm2/pkg/sdk/params/keeper.go @@ -1,19 +1,36 @@ package params import ( - "fmt" "log/slog" - "maps" - "reflect" + "strings" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/gnolang/gno/tm2/pkg/store" ) +const ( + ModuleName = "params" + StoreKey = ModuleName +) + type ParamsKeeperI interface { - Get(ctx sdk.Context, key string, ptr interface{}) - Set(ctx sdk.Context, key string, value interface{}) + GetString(ctx sdk.Context, key string, ptr *string) + GetInt64(ctx sdk.Context, key string, ptr *int64) + GetUint64(ctx sdk.Context, key string, ptr *uint64) + GetBool(ctx sdk.Context, key string, ptr *bool) + GetBytes(ctx sdk.Context, key string, ptr *[]byte) + + SetString(ctx sdk.Context, key string, value string) + SetInt64(ctx sdk.Context, key string, value int64) + SetUint64(ctx sdk.Context, key string, value uint64) + SetBool(ctx sdk.Context, key string, value bool) + SetBytes(ctx sdk.Context, key string, value []byte) + + Has(ctx sdk.Context, key string) bool + GetRaw(ctx sdk.Context, key string) []byte + + // XXX: ListKeys? } var _ ParamsKeeperI = ParamsKeeper{} @@ -21,7 +38,6 @@ var _ ParamsKeeperI = ParamsKeeper{} // global paramstore Keeper. type ParamsKeeper struct { key store.StoreKey - table KeyTable prefix string } @@ -29,7 +45,6 @@ type ParamsKeeper struct { func NewParamsKeeper(key store.StoreKey, prefix string) ParamsKeeper { return ParamsKeeper{ key: key, - table: NewKeyTable(), prefix: prefix, } } @@ -45,124 +60,98 @@ func (pk ParamsKeeper) Has(ctx sdk.Context, key string) bool { return stor.Has([]byte(key)) } -func (pk ParamsKeeper) Get(ctx sdk.Context, key string, ptr interface{}) { - pk.checkType(key, ptr) - stor := ctx.Store(pk.key) - bz := stor.Get([]byte(key)) - err := amino.UnmarshalJSON(bz, ptr) - if err != nil { - panic(err) - } -} - -func (pk ParamsKeeper) GetIfExists(ctx sdk.Context, key string, ptr interface{}) { - stor := ctx.Store(pk.key) - bz := stor.Get([]byte(key)) - if bz == nil { - return - } - pk.checkType(key, ptr) - err := amino.UnmarshalJSON(bz, ptr) - if err != nil { - panic(err) - } -} - func (pk ParamsKeeper) GetRaw(ctx sdk.Context, key string) []byte { stor := ctx.Store(pk.key) return stor.Get([]byte(key)) } -func (pk ParamsKeeper) Set(ctx sdk.Context, key string, value interface{}) { - pk.checkType(key, value) - stor := ctx.Store(pk.key) - bz, err := amino.MarshalJSON(value) - if err != nil { - panic(err) - } - stor.Set([]byte(key), bz) +func (pk ParamsKeeper) GetString(ctx sdk.Context, key string, ptr *string) { + checkSuffix(key, ".string") + pk.getIfExists(ctx, key, ptr) } -func (pk ParamsKeeper) Update(ctx sdk.Context, key string, value []byte) error { - attr, ok := pk.table.m[key] - if !ok { - panic(fmt.Sprintf("parameter %s not registered", key)) - } - - ty := attr.ty - dest := reflect.New(ty).Interface() - pk.GetIfExists(ctx, key, dest) - - if err := amino.UnmarshalJSON(value, dest); err != nil { - return err - } - - destValue := reflect.Indirect(reflect.ValueOf(dest)).Interface() - if err := pk.Validate(ctx, key, destValue); err != nil { - return err - } +func (pk ParamsKeeper) GetBool(ctx sdk.Context, key string, ptr *bool) { + checkSuffix(key, ".bool") + pk.getIfExists(ctx, key, ptr) +} - pk.Set(ctx, key, dest) - return nil +func (pk ParamsKeeper) GetInt64(ctx sdk.Context, key string, ptr *int64) { + checkSuffix(key, ".int64") + pk.getIfExists(ctx, key, ptr) } -func (pk ParamsKeeper) Validate(ctx sdk.Context, key string, value interface{}) error { - attr, ok := pk.table.m[key] - if !ok { - return fmt.Errorf("parameter %s not registered", key) - } +func (pk ParamsKeeper) GetUint64(ctx sdk.Context, key string, ptr *uint64) { + checkSuffix(key, ".uint64") + pk.getIfExists(ctx, key, ptr) +} - if err := attr.vfn(value); err != nil { - return fmt.Errorf("invalid parameter value: %w", err) - } +func (pk ParamsKeeper) GetBytes(ctx sdk.Context, key string, ptr *[]byte) { + checkSuffix(key, ".bytes") + pk.getIfExists(ctx, key, ptr) +} - return nil +func (pk ParamsKeeper) SetString(ctx sdk.Context, key, value string) { + checkSuffix(key, ".string") + pk.set(ctx, key, value) } -func (pk ParamsKeeper) checkType(key string, value interface{}) { - attr, ok := pk.table.m[key] - if !ok { - panic(fmt.Sprintf("parameter %s is not registered", key)) - } +func (pk ParamsKeeper) SetBool(ctx sdk.Context, key string, value bool) { + checkSuffix(key, ".bool") + pk.set(ctx, key, value) +} - ty := attr.ty - pty := reflect.TypeOf(value) - if pty.Kind() == reflect.Ptr { - pty = pty.Elem() - } +func (pk ParamsKeeper) SetInt64(ctx sdk.Context, key string, value int64) { + checkSuffix(key, ".int64") + pk.set(ctx, key, value) +} - if pty != ty { - panic("type mismatch with registered table") - } +func (pk ParamsKeeper) SetUint64(ctx sdk.Context, key string, value uint64) { + checkSuffix(key, ".uint64") + pk.set(ctx, key, value) } -func (pk ParamsKeeper) HasKeyTable() bool { - return len(pk.table.m) > 0 +func (pk ParamsKeeper) SetBytes(ctx sdk.Context, key string, value []byte) { + checkSuffix(key, ".bytes") + pk.set(ctx, key, value) } -func (pk ParamsKeeper) WithKeyTable(table KeyTable) ParamsKeeper { - if table.m == nil { - panic("WithKeyTable() called with nil KeyTable") +func (pk ParamsKeeper) getIfExists(ctx sdk.Context, key string, ptr interface{}) { + stor := ctx.Store(pk.key) + bz := stor.Get([]byte(key)) + if bz == nil { + return } - if len(pk.table.m) != 0 { - panic("WithKeyTable() called on already initialized Keeper") + err := amino.UnmarshalJSON(bz, ptr) + if err != nil { + panic(err) } - - maps.Copy(pk.table.m, table.m) - return pk } -// XXX: added, should we remove? -func (pk ParamsKeeper) RegisterType(psp ParamSetPair) { - pk.table.RegisterType(psp) +func (pk ParamsKeeper) get(ctx sdk.Context, key string, ptr interface{}) { + stor := ctx.Store(pk.key) + bz := stor.Get([]byte(key)) + err := amino.UnmarshalJSON(bz, ptr) + if err != nil { + panic(err) + } } -// XXX: added, should we remove? -func (pk ParamsKeeper) HasTypeKey(key string) bool { - return pk.table.HasKey(key) +func (pk ParamsKeeper) set(ctx sdk.Context, key string, value interface{}) { + stor := ctx.Store(pk.key) + bz, err := amino.MarshalJSON(value) + if err != nil { + panic(err) + } + stor.Set([]byte(key), bz) } -// XXX: GetAllKeys -// XXX: GetAllParams -// XXX: ViewKeeper -// XXX: ModuleKeeper +func checkSuffix(key, expectedSuffix string) { + var ( + noSuffix = !strings.HasSuffix(key, expectedSuffix) + noName = len(key) == len(expectedSuffix) + // XXX: additional sanity checks? + ) + if noSuffix || noName { + panic(`key should be like "` + expectedSuffix + `"`) + } +} diff --git a/tm2/pkg/sdk/params/keeper_test.go b/tm2/pkg/sdk/params/keeper_test.go index 6fd1e6ae65b..a0435f03bb3 100644 --- a/tm2/pkg/sdk/params/keeper_test.go +++ b/tm2/pkg/sdk/params/keeper_test.go @@ -8,91 +8,87 @@ import ( "github.com/stretchr/testify/require" ) -// XXX: transient test - func TestKeeper(t *testing.T) { - kvs := []struct { - key string - param int64 - }{ - {"key1", 10}, - {"key2", 55}, - {"key3", 182}, - {"key4", 17582}, - {"key5", 2768554}, - {"key6", 1157279}, - {"key7", 9058701}, - } - - table := NewKeyTable( - NewParamSetPair("key1", int64(0), validateNoOp), - NewParamSetPair("key2", int64(0), validateNoOp), - NewParamSetPair("key3", int64(0), validateNoOp), - NewParamSetPair("key4", int64(0), validateNoOp), - NewParamSetPair("key5", int64(0), validateNoOp), - NewParamSetPair("key6", int64(0), validateNoOp), - NewParamSetPair("key7", int64(0), validateNoOp), - NewParamSetPair("extra1", bool(false), validateNoOp), - NewParamSetPair("extra2", string(""), validateNoOp), - ) - env := setupTestEnv() ctx, store, keeper := env.ctx, env.store, env.keeper + _ = store // XXX: add store tests? + + require.False(t, keeper.Has(ctx, "param1.string")) + require.False(t, keeper.Has(ctx, "param2.bool")) + require.False(t, keeper.Has(ctx, "param3.uint64")) + require.False(t, keeper.Has(ctx, "param4.int64")) + require.False(t, keeper.Has(ctx, "param5.bytes")) + + // initial set + require.NotPanics(t, func() { keeper.SetString(ctx, "param1.string", "foo") }) + require.NotPanics(t, func() { keeper.SetBool(ctx, "param2.bool", true) }) + require.NotPanics(t, func() { keeper.SetUint64(ctx, "param3.uint64", 42) }) + require.NotPanics(t, func() { keeper.SetInt64(ctx, "param4.int64", -1337) }) + require.NotPanics(t, func() { keeper.SetBytes(ctx, "param5.bytes", []byte("hello world!")) }) + + require.True(t, keeper.Has(ctx, "param1.string")) + require.True(t, keeper.Has(ctx, "param2.bool")) + require.True(t, keeper.Has(ctx, "param3.uint64")) + require.True(t, keeper.Has(ctx, "param4.int64")) + require.True(t, keeper.Has(ctx, "param5.bytes")) + + var ( + param1 string + param2 bool + param3 uint64 + param4 int64 + param5 []byte + ) - require.False(t, keeper.HasKeyTable()) - keeper = keeper.WithKeyTable(table) - require.True(t, keeper.HasKeyTable()) - - // Set params - for i, kv := range kvs { - require.NotPanics(t, func() { keeper.Set(ctx, kv.key, kv.param) }, "keeper.Set panics, tc #%d", i) - } - - // Test keeper.Get - for i, kv := range kvs { - var param int64 - require.NotPanics(t, func() { keeper.Get(ctx, kv.key, ¶m) }, "keeper.Get panics, tc #%d", i) - require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) - } - - // Test keeper.GetRaw - for i, kv := range kvs { - var param int64 - bz := keeper.GetRaw(ctx, kv.key) - err := amino.UnmarshalJSON(bz, ¶m) - require.Nil(t, err, "err is not nil, tc #%d", i) - require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) - } - - // Test store.Get equals keeper.Get - for i, kv := range kvs { - var param int64 - bz := store.Get([]byte(kv.key)) - require.NotNil(t, bz, "KVStore.Get returns nil, tc #%d", i) - err := amino.UnmarshalJSON(bz, ¶m) - require.NoError(t, err, "UnmarshalJSON returns error, tc #%d", i) - require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) - } - - // Test invalid keeper.Get - for i, kv := range kvs { - var param bool - require.Panics(t, func() { keeper.Get(ctx, kv.key, ¶m) }, "invalid keeper.Get not panics, tc #%d", i) - } - - // Test invalid keeper.Set - for i, kv := range kvs { - require.Panics(t, func() { keeper.Set(ctx, kv.key, true) }, "invalid keeper.Set not panics, tc #%d", i) - } + require.NotPanics(t, func() { keeper.GetString(ctx, "param1.string", ¶m1) }) + require.NotPanics(t, func() { keeper.GetBool(ctx, "param2.bool", ¶m2) }) + require.NotPanics(t, func() { keeper.GetUint64(ctx, "param3.uint64", ¶m3) }) + require.NotPanics(t, func() { keeper.GetInt64(ctx, "param4.int64", ¶m4) }) + require.NotPanics(t, func() { keeper.GetBytes(ctx, "param5.bytes", ¶m5) }) + + require.Equal(t, param1, "foo") + require.Equal(t, param2, true) + require.Equal(t, param3, uint64(42)) + require.Equal(t, param4, int64(-1337)) + require.Equal(t, param5, []byte("hello world!")) + + // reset + require.NotPanics(t, func() { keeper.SetString(ctx, "param1.string", "bar") }) + require.NotPanics(t, func() { keeper.SetBool(ctx, "param2.bool", false) }) + require.NotPanics(t, func() { keeper.SetUint64(ctx, "param3.uint64", 12345) }) + require.NotPanics(t, func() { keeper.SetInt64(ctx, "param4.int64", 1000) }) + require.NotPanics(t, func() { keeper.SetBytes(ctx, "param5.bytes", []byte("bye")) }) + + require.True(t, keeper.Has(ctx, "param1.string")) + require.True(t, keeper.Has(ctx, "param2.bool")) + require.True(t, keeper.Has(ctx, "param3.uint64")) + require.True(t, keeper.Has(ctx, "param4.int64")) + require.True(t, keeper.Has(ctx, "param5.bytes")) + + require.NotPanics(t, func() { keeper.GetString(ctx, "param1.string", ¶m1) }) + require.NotPanics(t, func() { keeper.GetBool(ctx, "param2.bool", ¶m2) }) + require.NotPanics(t, func() { keeper.GetUint64(ctx, "param3.uint64", ¶m3) }) + require.NotPanics(t, func() { keeper.GetInt64(ctx, "param4.int64", ¶m4) }) + require.NotPanics(t, func() { keeper.GetBytes(ctx, "param5.bytes", ¶m5) }) + + require.Equal(t, param1, "bar") + require.Equal(t, param2, false) + require.Equal(t, param3, uint64(12345)) + require.Equal(t, param4, int64(1000)) + require.Equal(t, param5, []byte("bye")) + + // invalid sets + require.PanicsWithValue(t, `key should be like ".string"`, func() { keeper.SetString(ctx, "invalid.int64", "hello") }) + require.PanicsWithValue(t, `key should be like ".int64"`, func() { keeper.SetInt64(ctx, "invalid.string", int64(42)) }) + require.PanicsWithValue(t, `key should be like ".uint64"`, func() { keeper.SetUint64(ctx, "invalid.int64", uint64(42)) }) + require.PanicsWithValue(t, `key should be like ".bool"`, func() { keeper.SetBool(ctx, "invalid.int64", true) }) + require.PanicsWithValue(t, `key should be like ".bytes"`, func() { keeper.SetBytes(ctx, "invalid.int64", []byte("hello")) }) } // adapted from TestKeeperSubspace from Cosmos SDK, but adapted to a subspace-less Keeper. -func TestKeeper_Subspace(t *testing.T) { +func TestKeeper_internal(t *testing.T) { env := setupTestEnv() ctx, store, keeper := env.ctx, env.store, env.keeper - // XXX: keeper = keeper.WithKeyTable(table) - - // cdc, ctx, key, _, keeper := testComponents() kvs := []struct { key string @@ -108,55 +104,30 @@ func TestKeeper_Subspace(t *testing.T) { {"uint16", uint16(1), uint16(0), new(uint16)}, {"uint32", uint32(1), uint32(0), new(uint32)}, {"uint64", uint64(1), uint64(0), new(uint64)}, - // XXX: {"int", math.NewInt(1), math.Int{}, new(math.Int)}, - // XXX: {"uint", math.NewUint(1), math.Uint{}, new(math.Uint)}, - // XXX: {"dec", math.LegacyNewDec(1), math.LegacyDec{}, new(math.LegacyDec)}, {"struct", s{1}, s{0}, new(s)}, } - table := NewKeyTable( - NewParamSetPair("string", "", validateNoOp), - NewParamSetPair("bool", false, validateNoOp), - NewParamSetPair("int16", int16(0), validateNoOp), - NewParamSetPair("int32", int32(0), validateNoOp), - NewParamSetPair("int64", int64(0), validateNoOp), - NewParamSetPair("uint16", uint16(0), validateNoOp), - NewParamSetPair("uint32", uint32(0), validateNoOp), - NewParamSetPair("uint64", uint64(0), validateNoOp), - // XXX: NewParamSetPair("int", math.Int{}, validateNoOp), - // XXX: NewParamSetPair("uint", math.Uint{}, validateNoOp), - // XXX: NewParamSetPair("dec", math.LegacyDec{}, validateNoOp), - NewParamSetPair("struct", s{}, validateNoOp), - ) - keeper = keeper.WithKeyTable(table) - - // Test keeper.Set, keeper.Modified for i, kv := range kvs { - // require.False(t, keeper.Modified(ctx, kv.key), "keeper.Modified returns true before setting, tc #%d", i) - require.NotPanics(t, func() { keeper.Set(ctx, kv.key, kv.param) }, "keeper.Set panics, tc #%d", i) - // require.True(t, keeper.Modified(ctx, kv.key), "keeper.Modified returns false after setting, tc #%d", i) + require.NotPanics(t, func() { keeper.set(ctx, kv.key, kv.param) }, "keeper.Set panics, tc #%d", i) } - // Test keeper.Get, keeper.GetIfExists for i, kv := range kvs { - require.NotPanics(t, func() { keeper.GetIfExists(ctx, "invalid", kv.ptr) }, "keeper.GetIfExists panics when no value exists, tc #%d", i) + require.NotPanics(t, func() { keeper.getIfExists(ctx, "invalid", kv.ptr) }, "keeper.GetIfExists panics when no value exists, tc #%d", i) require.Equal(t, kv.zero, indirect(kv.ptr), "keeper.GetIfExists unmarshalls when no value exists, tc #%d", i) - require.Panics(t, func() { keeper.Get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) + require.Panics(t, func() { keeper.get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) require.Equal(t, kv.zero, indirect(kv.ptr), "invalid keeper.Get unmarshalls when no value exists, tc #%d", i) - require.NotPanics(t, func() { keeper.GetIfExists(ctx, kv.key, kv.ptr) }, "keeper.GetIfExists panics, tc #%d", i) + require.NotPanics(t, func() { keeper.getIfExists(ctx, kv.key, kv.ptr) }, "keeper.GetIfExists panics, tc #%d", i) require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) - require.NotPanics(t, func() { keeper.Get(ctx, kv.key, kv.ptr) }, "keeper.Get panics, tc #%d", i) + require.NotPanics(t, func() { keeper.get(ctx, kv.key, kv.ptr) }, "keeper.Get panics, tc #%d", i) require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) - require.Panics(t, func() { keeper.Get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) + require.Panics(t, func() { keeper.get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) require.Equal(t, kv.param, indirect(kv.ptr), "invalid keeper.Get unmarshalls when no value existt, tc #%d", i) - require.Panics(t, func() { keeper.Get(ctx, kv.key, nil) }, "invalid keeper.Get not panics when the pointer is nil, tc #%d", i) - require.Panics(t, func() { keeper.Get(ctx, kv.key, new(invalid)) }, "invalid keeper.Get not panics when the pointer is different type, tc #%d", i) + require.Panics(t, func() { keeper.get(ctx, kv.key, nil) }, "invalid keeper.Get not panics when the pointer is nil, tc #%d", i) } - // Test store.Get equals keeper.Get for i, kv := range kvs { bz := store.Get([]byte(kv.key)) require.NotNil(t, bz, "store.Get() returns nil, tc #%d", i) @@ -166,44 +137,9 @@ func TestKeeper_Subspace(t *testing.T) { } } -func TestJSONUpdate(t *testing.T) { - env := setupTestEnv() - ctx, keeper := env.ctx, env.keeper - key := "key" - - space := keeper.WithKeyTable(NewKeyTable(NewParamSetPair(key, paramJSON{}, validateNoOp))) - - var param paramJSON - - err := space.Update(ctx, key, []byte(`{"param1": "10241024"}`)) - require.NoError(t, err) - space.Get(ctx, key, ¶m) - require.Equal(t, paramJSON{10241024, ""}, param) - - err = space.Update(ctx, key, []byte(`{"param2": "helloworld"}`)) - require.NoError(t, err) - space.Get(ctx, key, ¶m) - require.Equal(t, paramJSON{10241024, "helloworld"}, param) - - err = space.Update(ctx, key, []byte(`{"param1": "20482048"}`)) - require.NoError(t, err) - space.Get(ctx, key, ¶m) - require.Equal(t, paramJSON{20482048, "helloworld"}, param) - - err = space.Update(ctx, key, []byte(`{"param1": "40964096", "param2": "goodbyeworld"}`)) - require.NoError(t, err) - space.Get(ctx, key, ¶m) - require.Equal(t, paramJSON{40964096, "goodbyeworld"}, param) -} - type ( - invalid struct{} - s struct{ I int } - paramJSON struct { - Param1 int64 `json:"param1,omitempty" yaml:"param1,omitempty"` - Param2 string `json:"param2,omitempty" yaml:"param2,omitempty"` - } + invalid struct{} + s struct{ I int } ) -func validateNoOp(_ interface{}) error { return nil } func indirect(ptr interface{}) interface{} { return reflect.ValueOf(ptr).Elem().Interface() } diff --git a/tm2/pkg/sdk/params/paramset.go b/tm2/pkg/sdk/params/paramset.go deleted file mode 100644 index b401c56e69e..00000000000 --- a/tm2/pkg/sdk/params/paramset.go +++ /dev/null @@ -1,25 +0,0 @@ -package params - -// This file mirrors the original implementation from the Cosmos SDK. - -type ValueValidatorFn func(value interface{}) error - -// ParamSetPair is used for associating param key and field of param structs. -type ParamSetPair struct { - Key string - Value interface{} - ValidatorFn ValueValidatorFn -} - -// NewParamSetPair creates a new ParamSetPair instance. -func NewParamSetPair(key string, value interface{}, vfn ValueValidatorFn) ParamSetPair { - return ParamSetPair{key, value, vfn} -} - -// ParamSetPairs Slice of KeyFieldPair. -type ParamSetPairs []ParamSetPair - -// ParamSet defines an interface for structs containing parameters for a module. -type ParamSet interface { - ParamSetPairs() ParamSetPairs -} diff --git a/tm2/pkg/sdk/params/table.go b/tm2/pkg/sdk/params/table.go deleted file mode 100644 index dae3b0f62c6..00000000000 --- a/tm2/pkg/sdk/params/table.go +++ /dev/null @@ -1,77 +0,0 @@ -package params - -// This file closely mirrors the original implementation from the Cosmos SDK, with only minor modifications. - -import ( - "reflect" - "regexp" -) - -type attribute struct { - ty reflect.Type - vfn ValueValidatorFn -} - -// KeyTable subspaces appropriate type for each parameter key -type KeyTable struct { - m map[string]attribute -} - -func NewKeyTable(pairs ...ParamSetPair) KeyTable { - keyTable := KeyTable{ - m: make(map[string]attribute), - } - - for _, psp := range pairs { - keyTable = keyTable.RegisterType(psp) - } - - return keyTable -} - -// RegisterType registers a single ParamSetPair (key-type pair) in a KeyTable. -func (t KeyTable) RegisterType(psp ParamSetPair) KeyTable { - if len(psp.Key) == 0 { - panic("cannot register ParamSetPair with an parameter empty key") - } - // XXX: sanitize more? - /*if !isAlphaNumeric(psp.Key) { - panic("cannot register ParamSetPair with a non-alphanumeric parameter key") - }*/ - if psp.ValidatorFn == nil { - panic("cannot register ParamSetPair without a value validation function") - } - - if _, ok := t.m[psp.Key]; ok { - panic("duplicate parameter key: " + psp.Key) - } - - rty := reflect.TypeOf(psp.Value) - - // indirect rty if it is a pointer - for rty.Kind() == reflect.Ptr { - rty = rty.Elem() - } - - t.m[psp.Key] = attribute{ - vfn: psp.ValidatorFn, - ty: rty, - } - - return t -} - -// RegisterParamSet registers multiple ParamSetPairs from a ParamSet in a KeyTable. -func (t KeyTable) RegisterParamSet(ps ParamSet) KeyTable { - for _, psp := range ps.ParamSetPairs() { - t = t.RegisterType(psp) - } - return t -} - -func (t KeyTable) HasKey(key string) bool { - _, ok := t.m[key] - return ok -} - -var isAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString From a4608ebdc107977f47e7983bbf847c0a8794e3ef Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 21:09:44 -0500 Subject: [PATCH 12/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/sdk/vm/builtins.go | 42 ++++-------------------------- gno.land/pkg/sdk/vm/keeper.go | 10 ++++--- gno.land/pkg/sdk/vm/keeper_test.go | 4 +-- 3 files changed, 13 insertions(+), 43 deletions(-) diff --git a/gno.land/pkg/sdk/vm/builtins.go b/gno.land/pkg/sdk/vm/builtins.go index cbd4eb14539..161e459873d 100644 --- a/gno.land/pkg/sdk/vm/builtins.go +++ b/gno.land/pkg/sdk/vm/builtins.go @@ -3,7 +3,6 @@ package vm 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" ) @@ -72,41 +71,10 @@ func NewSDKParams(vmk *VMKeeper, ctx sdk.Context) *SDKParams { } } -// 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) { - // 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.HasTypeKey(key) { - prm.vmk.prmk.RegisterType(params.NewParamSetPair(key, int64(0), validateNoOp)) - } - prm.vmk.prmk.Set(prm.ctx, key, value) -} - +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) { - // 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) + prm.vmk.prmk.SetUint64(prm.ctx, key, value) } - -func validateNoOp(_ interface{}) error { return nil } +func (prm *SDKParams) SetBytes(key string, value []byte) { prm.vmk.prmk.SetBytes(prm.ctx, key, value) } diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 573d9163ac3..ef1705c7ae9 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -225,13 +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" -const defaultSysUsersPkg = "gno.land/r/sys/users" +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 { - sysUsersPkg := defaultSysUsersPkg - vm.prmk.GetIfExists(ctx, sysUsersPkgParamKey, &sysUsersPkg) + sysUsersPkg := sysUsersPkgDefault + vm.prmk.GetString(ctx, sysUsersPkgParamKey, &sysUsersPkg) store := vm.getGnoTransactionStore(ctx) diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index 37fbb0af4f7..a6faa410009 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -346,8 +346,8 @@ func Do() string { 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) + 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) } From 9f18bad9a58dfda6bf58f86389dfcbb982a8f975 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 21:29:11 -0500 Subject: [PATCH 13/69] chore: rename config -> param Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/cmd/gnoland/testdata/params.txtar | 11 ++---- gno.land/pkg/sdk/vm/keeper_test.go | 8 ++--- gnovm/stdlibs/generated.go | 42 +++++++++++++++++----- gnovm/stdlibs/std/params.gno | 22 ++++++------ gnovm/stdlibs/std/params.go | 15 +++++--- 5 files changed, 63 insertions(+), 35 deletions(-) diff --git a/gno.land/cmd/gnoland/testdata/params.txtar b/gno.land/cmd/gnoland/testdata/params.txtar index 1c19bc854e1..817c616b76d 100644 --- a/gno.land/cmd/gnoland/testdata/params.txtar +++ b/gno.land/cmd/gnoland/testdata/params.txtar @@ -53,11 +53,6 @@ gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBaz -args 31337 -gas- 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 @@ -65,6 +60,6 @@ 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) } +func SetFoo(newFoo string) { std.SetParam("foo", newFoo) } +func SetBar(newBar bool) { std.SetParam("bar", newBar) } +func SetBaz(newBaz int64) { std.SetParam("baz", newBaz) } diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index a6faa410009..9ec74abbf7f 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -319,12 +319,12 @@ package test import "std" func init() { - std.SetConfig("foo", "foo1") + std.SetParam("foo", "foo1") } func Do() string { - std.SetConfig("bar", int64(1337)) - std.SetConfig("foo", "foo2") // override init + std.SetParam("bar", int64(1337)) + std.SetParam("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 }`}, @@ -374,7 +374,7 @@ import "std" var admin std.Address func init() { - admin = std.GetOrigCaller() + admin = std.GetOrigCaller() } func Echo(msg string) string { diff --git a/gnovm/stdlibs/generated.go b/gnovm/stdlibs/generated.go index eaafa58309e..b0788fc6d1b 100644 --- a/gnovm/stdlibs/generated.go +++ b/gnovm/stdlibs/generated.go @@ -722,7 +722,7 @@ var nativeFuncs = [...]NativeFunc{ }, { "std", - "setConfigString", + "setParamString", []gno.FieldTypeExpr{ {Name: gno.N("p0"), Type: gno.X("string")}, {Name: gno.N("p1"), Type: gno.X("string")}, @@ -741,14 +741,14 @@ var nativeFuncs = [...]NativeFunc{ gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) - libs_std.X_setConfigString( + libs_std.X_setParamString( m, p0, p1) }, }, { "std", - "setConfigBool", + "setParamBool", []gno.FieldTypeExpr{ {Name: gno.N("p0"), Type: gno.X("string")}, {Name: gno.N("p1"), Type: gno.X("bool")}, @@ -767,14 +767,14 @@ var nativeFuncs = [...]NativeFunc{ gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) - libs_std.X_setConfigBool( + libs_std.X_setParamBool( m, p0, p1) }, }, { "std", - "setConfigInt64", + "setParamInt64", []gno.FieldTypeExpr{ {Name: gno.N("p0"), Type: gno.X("string")}, {Name: gno.N("p1"), Type: gno.X("int64")}, @@ -793,14 +793,14 @@ var nativeFuncs = [...]NativeFunc{ gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) - libs_std.X_setConfigInt64( + libs_std.X_setParamInt64( m, p0, p1) }, }, { "std", - "setConfigUint64", + "setParamUint64", []gno.FieldTypeExpr{ {Name: gno.N("p0"), Type: gno.X("string")}, {Name: gno.N("p1"), Type: gno.X("uint64")}, @@ -819,7 +819,33 @@ var nativeFuncs = [...]NativeFunc{ gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) - libs_std.X_setConfigUint64( + libs_std.X_setParamUint64( + m, + p0, p1) + }, + }, + { + "std", + "setParamBytes", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("[]byte")}, + }, + []gno.FieldTypeExpr{}, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 []byte + rp1 = reflect.ValueOf(&p1).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) + + libs_std.X_setParamBytes( m, p0, p1) }, diff --git a/gnovm/stdlibs/std/params.gno b/gnovm/stdlibs/std/params.gno index a3dc47d4bd4..febc774c70e 100644 --- a/gnovm/stdlibs/std/params.gno +++ b/gnovm/stdlibs/std/params.gno @@ -1,28 +1,30 @@ package std // These are native bindings to the banker's functions. -func setConfigString(key string, val string) -func setConfigBool(key string, val bool) -func setConfigInt64(key string, val int64) -func setConfigUint64(key string, val uint64) +func setParamString(key string, val string) +func setParamBool(key string, val bool) +func setParamInt64(key string, val int64) +func setParamUint64(key string, val uint64) +func setParamBytes(key string, val []byte) // XXX: add doc -func SetConfig(key string, val interface{}) { +func SetParam(key string, val interface{}) { switch v := val.(type) { case string: - setConfigString(key, v) + setParamString(key, v) case bool: - setConfigBool(key, v) + setParamBool(key, v) case int64: - setConfigInt64(key, v) + setParamInt64(key, v) case uint64: - setConfigUint64(key, v) + setParamUint64(key, v) + case []byte: + setParamBytes(key, v) default: panic("unsupported type") } } -// XXX: add doc //func GetConfig(key string) string { // return getConfig(key) //} diff --git a/gnovm/stdlibs/std/params.go b/gnovm/stdlibs/std/params.go index 70ecbe6ba1d..36fcaf824af 100644 --- a/gnovm/stdlibs/std/params.go +++ b/gnovm/stdlibs/std/params.go @@ -17,29 +17,34 @@ type ParamsInterface interface { SetBool(key string, val bool) SetInt64(key string, val int64) SetUint64(key string, val uint64) - // XXX: GetString(key string) (string, error)? + SetBytes(key string, val []byte) } -func X_setConfigString(m *gno.Machine, key, val string) { +func X_setParamString(m *gno.Machine, key, val string) { pk := pkey(m, key, "string") GetContext(m).Params.SetString(pk, val) } -func X_setConfigBool(m *gno.Machine, key string, val bool) { +func X_setParamBool(m *gno.Machine, key string, val bool) { pk := pkey(m, key, "bool") GetContext(m).Params.SetBool(pk, val) } -func X_setConfigInt64(m *gno.Machine, key string, val int64) { +func X_setParamInt64(m *gno.Machine, key string, val int64) { pk := pkey(m, key, "int64") GetContext(m).Params.SetInt64(pk, val) } -func X_setConfigUint64(m *gno.Machine, key string, val uint64) { +func X_setParamUint64(m *gno.Machine, key string, val uint64) { pk := pkey(m, key, "uint64") GetContext(m).Params.SetUint64(pk, val) } +func X_setParamBytes(m *gno.Machine, key string, val []byte) { + pk := pkey(m, key, "bytes") + GetContext(m).Params.SetBytes(pk, val) +} + func pkey(m *gno.Machine, key string, kind string) string { // validate key. if len(key) == 0 { From 5ba066e8fc043c83ce6f6053dd504c198a285ec7 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Mon, 21 Oct 2024 21:39:51 -0500 Subject: [PATCH 14/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- tm2/pkg/sdk/params/keeper_test.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tm2/pkg/sdk/params/keeper_test.go b/tm2/pkg/sdk/params/keeper_test.go index a0435f03bb3..45a97ae44ad 100644 --- a/tm2/pkg/sdk/params/keeper_test.go +++ b/tm2/pkg/sdk/params/keeper_test.go @@ -137,9 +137,6 @@ func TestKeeper_internal(t *testing.T) { } } -type ( - invalid struct{} - s struct{ I int } -) +type s struct{ I int } func indirect(ptr interface{}) interface{} { return reflect.ValueOf(ptr).Elem().Interface() } From 52600590a3f3a4775f39849658f42a384e9e71aa Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 09:14:57 -0500 Subject: [PATCH 15/69] chore: ignore generated files from codecov Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .github/codecov.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/codecov.yml b/.github/codecov.yml index ea1c701d946..68bb808ea4f 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -39,3 +39,8 @@ flag_management: - type: patch target: auto # Let's decrease this later. threshold: 10 + +ignore: + - gnovm/stdlibs/generated.go + - gnovm/tests/stdlibs/generated.go + - **/*.pb.go From 309806f6b47a4efb2c0a55e529b7d7ef5e3235ab Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 09:17:09 -0500 Subject: [PATCH 16/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .github/codecov.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/codecov.yml b/.github/codecov.yml index 68bb808ea4f..d1ecba7ade3 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -41,6 +41,6 @@ flag_management: threshold: 10 ignore: - - gnovm/stdlibs/generated.go - - gnovm/tests/stdlibs/generated.go - - **/*.pb.go + - "gnovm/stdlibs/generated.go" + - "gnovm/tests/stdlibs/generated.go" + - "**/*.pb.go" From 604466c0d4b228272e54892dbc00f5ee6ebab8f7 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 10:49:49 -0500 Subject: [PATCH 17/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gnovm/stdlibs/std/params.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gnovm/stdlibs/std/params.go b/gnovm/stdlibs/std/params.go index 36fcaf824af..f4cd8f7e245 100644 --- a/gnovm/stdlibs/std/params.go +++ b/gnovm/stdlibs/std/params.go @@ -48,15 +48,15 @@ func X_setParamBytes(m *gno.Machine, key string, val []byte) { func pkey(m *gno.Machine, key string, kind string) string { // validate key. if len(key) == 0 { - panic("empty param key") + m.Panic(typedString("empty param key")) } first := rune(key[0]) if !unicode.IsLetter(first) && first != '_' { - panic("invalid param key: " + key) + m.Panic(typedString("invalid param key: " + key)) } for _, char := range key[1:] { if !unicode.IsLetter(char) && !unicode.IsDigit(char) && char != '_' { - panic("invalid param key: " + key) + m.Panic(typedString("invalid param key: " + key)) } } From 8c5b00ab5f64e2827de143f3e98ad19d2159494e Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 13:00:02 -0500 Subject: [PATCH 18/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- tm2/pkg/sdk/params/handler_test.go | 58 ++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 tm2/pkg/sdk/params/handler_test.go diff --git a/tm2/pkg/sdk/params/handler_test.go b/tm2/pkg/sdk/params/handler_test.go new file mode 100644 index 00000000000..1fff5d007d3 --- /dev/null +++ b/tm2/pkg/sdk/params/handler_test.go @@ -0,0 +1,58 @@ +package params + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" + + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/sdk" + tu "github.com/gnolang/gno/tm2/pkg/sdk/testutils" +) + +func TestInvalidMsg(t *testing.T) { + t.Parallel() + + h := NewHandler(ParamsKeeper{}) + res := h.Process(sdk.NewContext(sdk.RunTxModeDeliver, nil, &bft.Header{ChainID: "test-chain"}, nil), tu.NewTestMsg()) + require.False(t, res.IsOK()) + require.True(t, strings.Contains(res.Log, "unrecognized params message type")) +} + +func TestQuery(t *testing.T) { + t.Parallel() + + env := setupTestEnv() + h := NewHandler(env.keeper) + + req := abci.RequestQuery{ + Path: "params/params_test/foo/bar.string", + } + + res := h.Query(env.ctx, req) + require.Nil(t, res.Error) + require.NotNil(t, res) + require.Nil(t, res.Data) + + env.keeper.SetString(env.ctx, "foo/bar.string", "baz") + + res = h.Query(env.ctx, req) + require.Nil(t, res.Error) + require.NotNil(t, res) + require.Equal(t, string(res.Data), `"baz"`) +} + +func TestQuerierRouteNotFound(t *testing.T) { + t.Parallel() + + env := setupTestEnv() + h := NewHandler(env.keeper) + req := abci.RequestQuery{ + Path: "params/notfound", + Data: []byte{}, + } + res := h.Query(env.ctx, req) + require.Error(t, res.Error) +} From 4a1c0bbbd34ccbe61d94ea19aebc594c7fa576e5 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 13:08:10 -0500 Subject: [PATCH 19/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/cmd/gnoland/testdata/params.txtar | 6 +++--- gnovm/stdlibs/std/params.go | 10 ++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/gno.land/cmd/gnoland/testdata/params.txtar b/gno.land/cmd/gnoland/testdata/params.txtar index 817c616b76d..7f728e14003 100644 --- a/gno.land/cmd/gnoland/testdata/params.txtar +++ b/gno.land/cmd/gnoland/testdata/params.txtar @@ -60,6 +60,6 @@ import ( "std" ) -func SetFoo(newFoo string) { std.SetParam("foo", newFoo) } -func SetBar(newBar bool) { std.SetParam("bar", newBar) } -func SetBaz(newBaz int64) { std.SetParam("baz", newBaz) } +func SetFoo(newFoo string) { std.SetParam("foo.string", newFoo) } +func SetBar(newBar bool) { std.SetParam("bar.bool", newBar) } +func SetBaz(newBaz int64) { std.SetParam("baz.int64", newBaz) } diff --git a/gnovm/stdlibs/std/params.go b/gnovm/stdlibs/std/params.go index f4cd8f7e245..e21bd9912dd 100644 --- a/gnovm/stdlibs/std/params.go +++ b/gnovm/stdlibs/std/params.go @@ -2,6 +2,7 @@ package std import ( "fmt" + "strings" "unicode" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" @@ -47,6 +48,11 @@ func X_setParamBytes(m *gno.Machine, key string, val []byte) { func pkey(m *gno.Machine, key string, kind string) string { // validate key. + untypedKey := strings.TrimSuffix(key, "."+kind) + if key == untypedKey { + m.Panic(typedString("invalid param key: " + key)) + } + if len(key) == 0 { m.Panic(typedString("empty param key")) } @@ -54,7 +60,7 @@ func pkey(m *gno.Machine, key string, kind string) string { if !unicode.IsLetter(first) && first != '_' { m.Panic(typedString("invalid param key: " + key)) } - for _, char := range key[1:] { + for _, char := range untypedKey[1:] { if !unicode.IsLetter(char) && !unicode.IsDigit(char) && char != '_' { m.Panic(typedString("invalid param key: " + key)) } @@ -62,5 +68,5 @@ func pkey(m *gno.Machine, key string, kind string) string { // decorate key with realm and type. _, rlmPath := currentRealm(m) - return fmt.Sprintf("%s.%s.%s", rlmPath, key, kind) + return fmt.Sprintf("%s.%s", rlmPath, key) } From 86b4fbdd961ab2417db5655b7818f00ddd5dff0e Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 13:12:06 -0500 Subject: [PATCH 20/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- tm2/pkg/sdk/params/handler.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tm2/pkg/sdk/params/handler.go b/tm2/pkg/sdk/params/handler.go index 907482db420..b662fc06c58 100644 --- a/tm2/pkg/sdk/params/handler.go +++ b/tm2/pkg/sdk/params/handler.go @@ -64,7 +64,7 @@ func abciResult(err error) sdk.Result { // returns the second component of a path. func secondPart(path string) string { - parts := strings.Split(path, "/") + parts := strings.SplitN(path, "/", 3) if len(parts) < 2 { return "" } else { @@ -74,9 +74,6 @@ func secondPart(path string) string { // returns the third component of a path, including other slashes. func thirdPartWithSlashes(path string) string { - secondSlash := strings.Index(path[strings.Index(path, "/")+1:], "/") - if secondSlash == -1 { - return "" // Return original if less than two slashes - } - return path[strings.Index(path, "/")+secondSlash+2:] + split := strings.SplitN(path, "/", 3) + return split[2] } From 61839a8926436207361ad3aeca02f7c9e1338c4a Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 18:15:46 -0500 Subject: [PATCH 21/69] feat: add r/sys/params + params genesis support Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/genesis/params.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 gno.land/genesis/params.txt diff --git a/gno.land/genesis/params.txt b/gno.land/genesis/params.txt new file mode 100644 index 00000000000..0b762adfc26 --- /dev/null +++ b/gno.land/genesis/params.txt @@ -0,0 +1,5 @@ +# VM +#vm_chain_domain=gno.land +#vm_enable_namespaces=... +#vm_lock_token=... +#vm_gas_xxx=... From bf942222baf461f6f7b414e4356e4f534af785b3 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 18:52:27 -0500 Subject: [PATCH 22/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/sys/params/gno.mod | 1 + examples/gno.land/r/sys/params/params.gno | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 examples/gno.land/r/sys/params/gno.mod create mode 100644 examples/gno.land/r/sys/params/params.gno diff --git a/examples/gno.land/r/sys/params/gno.mod b/examples/gno.land/r/sys/params/gno.mod new file mode 100644 index 00000000000..2c24e81b2e6 --- /dev/null +++ b/examples/gno.land/r/sys/params/gno.mod @@ -0,0 +1 @@ +module gno.land/r/sys/params \ No newline at end of file diff --git a/examples/gno.land/r/sys/params/params.gno b/examples/gno.land/r/sys/params/params.gno new file mode 100644 index 00000000000..e00beb70b4c --- /dev/null +++ b/examples/gno.land/r/sys/params/params.gno @@ -0,0 +1,12 @@ +package params + +import "std" + +func Set(key string, value interface{}) { + assertGovDao() + std.SetParam(key, value) +} + +func assertGovDao() { + panic("not implemented") +} From 902eb9c49b3f541d82189b175dfc7052a29d0f0d Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:03:08 -0500 Subject: [PATCH 23/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/sdk/vm/keeper_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index 9ec74abbf7f..a125e2fb2f0 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -319,12 +319,12 @@ package test import "std" func init() { - std.SetParam("foo", "foo1") + std.SetParam("foo.string", "foo1") } func Do() string { - std.SetParam("bar", int64(1337)) - std.SetParam("foo", "foo2") // override init + std.SetParam("bar.int64", int64(1337)) + std.SetParam("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 }`}, From cb57a8fdbf7ef8ca60b4ee6dcb2ddf946af087b6 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:36:20 -0500 Subject: [PATCH 24/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/sys/params/params.gno | 25 +++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/examples/gno.land/r/sys/params/params.gno b/examples/gno.land/r/sys/params/params.gno index e00beb70b4c..c5f9361ffb4 100644 --- a/examples/gno.land/r/sys/params/params.gno +++ b/examples/gno.land/r/sys/params/params.gno @@ -1,12 +1,25 @@ package params -import "std" +import ( + "std" -func Set(key string, value interface{}) { - assertGovDao() - std.SetParam(key, value) + "gno.land/p/gov/proposal" +) + +func NewPropExecutor(key string, value interface{}) proposal.Executor { + callback := func() error { + assertGovDAOCaller() + std.SetParam(key, value) + return nil + } + + return proposal.NewExecutor(callback) } -func assertGovDao() { - panic("not implemented") +const daoPkgPath = "gno.land/r/gov/dao" + +func assertGovDAOCaller() { + if std.PrevRealm().PkgPath() != daoPkgPath { + panic(errNotGovDAO) + } } From 74025b56aeb2e7511049c2cd46262bc49eaa9db1 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:39:46 -0500 Subject: [PATCH 25/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/sys/params/params.gno | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/examples/gno.land/r/sys/params/params.gno b/examples/gno.land/r/sys/params/params.gno index c5f9361ffb4..a944cc6db52 100644 --- a/examples/gno.land/r/sys/params/params.gno +++ b/examples/gno.land/r/sys/params/params.gno @@ -6,20 +6,15 @@ import ( "gno.land/p/gov/proposal" ) +const daoPkgPath = "gno.land/r/gov/dao" + func NewPropExecutor(key string, value interface{}) proposal.Executor { callback := func() error { - assertGovDAOCaller() + if std.PrevRealm().PkgPath() != daoPkgPath { + panic("should be executed from govdao") + } std.SetParam(key, value) return nil } - return proposal.NewExecutor(callback) } - -const daoPkgPath = "gno.land/r/gov/dao" - -func assertGovDAOCaller() { - if std.PrevRealm().PkgPath() != daoPkgPath { - panic(errNotGovDAO) - } -} From 8f5242832a6845486f019ae61428ad370143a5cf Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:44:35 -0500 Subject: [PATCH 26/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/genesis/params.txt | 19 ++++++++++++++++--- gno.land/pkg/sdk/vm/keeper.go | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/gno.land/genesis/params.txt b/gno.land/genesis/params.txt index 0b762adfc26..de21822b146 100644 --- a/gno.land/genesis/params.txt +++ b/gno.land/genesis/params.txt @@ -1,5 +1,18 @@ -# VM -#vm_chain_domain=gno.land -#vm_enable_namespaces=... +# gno.land +gnoland_sys_users_rlm.string=gno.land/r/sys/users + +# gnovm +vm_enable_namespaces.bool=true +#vm_chain_domain.string=gno.land #vm_lock_token=... #vm_gas_xxx=... + +# tm2 +# ... + +# misc +foo.string=bar +foo.int64=-1337 +foo.uint64=42 +foo.bool=true + diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index ef1705c7ae9..4a4e66617d9 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -226,7 +226,7 @@ func (vm *VMKeeper) getGnoTransactionStore(ctx sdk.Context) gno.TransactionStore var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([\.~_a-zA-Z0-9]+)`) const ( - sysUsersPkgParamKey = "vm/gno.land/r/sys/params.string" + sysUsersPkgParamKey = "vm/gno.land/r/sys/params.gnoland_sys_users_rlm.string" sysUsersPkgDefault = "gno.land/r/sys/users" ) From d38c6b8017ac64268a7c2e4e168f91f1b6e57363 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 21:25:37 -0500 Subject: [PATCH 27/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/sdk/vm/keeper_test.go | 6 +++--- gnovm/stdlibs/std/params.gno | 29 +++++++---------------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index a125e2fb2f0..c6d8e3f5fa0 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -319,12 +319,12 @@ package test import "std" func init() { - std.SetParam("foo.string", "foo1") + std.SetParamString("foo.string", "foo1") } func Do() string { - std.SetParam("bar.int64", int64(1337)) - std.SetParam("foo.string", "foo2") // override init + 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 }`}, diff --git a/gnovm/stdlibs/std/params.gno b/gnovm/stdlibs/std/params.gno index febc774c70e..7af4d8a24b3 100644 --- a/gnovm/stdlibs/std/params.gno +++ b/gnovm/stdlibs/std/params.gno @@ -1,30 +1,15 @@ package std -// These are native bindings to the banker's functions. func setParamString(key string, val string) func setParamBool(key string, val bool) func setParamInt64(key string, val int64) func setParamUint64(key string, val uint64) func setParamBytes(key string, val []byte) -// XXX: add doc -func SetParam(key string, val interface{}) { - switch v := val.(type) { - case string: - setParamString(key, v) - case bool: - setParamBool(key, v) - case int64: - setParamInt64(key, v) - case uint64: - setParamUint64(key, v) - case []byte: - setParamBytes(key, v) - default: - panic("unsupported type") - } -} - -//func GetConfig(key string) string { -// return getConfig(key) -//} +var ( + SetParamString = setParamString + SetParamBool = setParamBool + SetParamInt64 = setParamInt64 + SetParamUint64 = setParamUint64 + SetParamBytes = setParamBytes +) From dc37fe0d5f4ef29099211d3f5e2ae9108d431dff Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 21:29:23 -0500 Subject: [PATCH 28/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/cmd/gnoland/testdata/params.txtar | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gno.land/cmd/gnoland/testdata/params.txtar b/gno.land/cmd/gnoland/testdata/params.txtar index 7f728e14003..30363aa6369 100644 --- a/gno.land/cmd/gnoland/testdata/params.txtar +++ b/gno.land/cmd/gnoland/testdata/params.txtar @@ -60,6 +60,6 @@ import ( "std" ) -func SetFoo(newFoo string) { std.SetParam("foo.string", newFoo) } -func SetBar(newBar bool) { std.SetParam("bar.bool", newBar) } -func SetBaz(newBaz int64) { std.SetParam("baz.int64", newBaz) } +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) } From a166760be0eca38e49f62340fc707d4f977be346 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 22:33:54 -0500 Subject: [PATCH 29/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/genesis/params.txt | 1 - gno.land/pkg/gnoland/genesis.go | 30 +++++++++++++++++ gno.land/pkg/gnoland/param.go | 42 ++++++++++++++++++++++++ gno.land/pkg/gnoland/types.go | 1 + gno.land/pkg/integration/testing_node.go | 12 +++++++ 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 gno.land/pkg/gnoland/param.go diff --git a/gno.land/genesis/params.txt b/gno.land/genesis/params.txt index de21822b146..c687f4891d0 100644 --- a/gno.land/genesis/params.txt +++ b/gno.land/genesis/params.txt @@ -15,4 +15,3 @@ foo.string=bar foo.int64=-1337 foo.uint64=42 foo.bool=true - diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go index f5f0aa56758..61c4615f4f0 100644 --- a/gno.land/pkg/gnoland/genesis.go +++ b/gno.land/pkg/gnoland/genesis.go @@ -58,6 +58,36 @@ func LoadGenesisBalancesFile(path string) ([]Balance, error) { return balances, nil } +// LoadGenesisParamsFile loads genesis params from the provided file path. +func LoadGenesisParamsFile(path string) ([]Param, error) { + // each param is in the form: key.kind=value + content := osm.MustReadFile(path) + lines := strings.Split(string(content), "\n") + + params := make([]Param, 0, len(lines)) + for _, line := range lines { + line = strings.TrimSpace(line) + + // remove comments. + line = strings.Split(line, "#")[0] + line = strings.TrimSpace(line) + + // skip empty lines. + if line == "" { + continue + } + + var p Param + if err := p.Parse(line); err != nil { + return nil, errors.New("invalid genesis_param line: " + line) + } + + params = append(params, p) + } + + return params, nil +} + // LoadGenesisTxsFile loads genesis transactions from the provided file path. // XXX: Improve the way we generate and load this file func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]std.Tx, error) { diff --git a/gno.land/pkg/gnoland/param.go b/gno.land/pkg/gnoland/param.go new file mode 100644 index 00000000000..6524eecf670 --- /dev/null +++ b/gno.land/pkg/gnoland/param.go @@ -0,0 +1,42 @@ +package gnoland + +import ( + "fmt" + "strings" +) + +type Param struct { + key string + value string // pre-parsing representation +} + +func (p Param) Verify() error { + // XXX: validate + return nil +} + +func (p *Param) Parse(entry string) error { + parts := strings.Split(strings.TrimSpace(entry), "=") // .= + if len(parts) != 2 { + return fmt.Errorf("malformed entry: %q", entry) + } + + p.key = parts[0] + p.value = parts[1] + + return p.Verify() +} + +func (p Param) String() string { + return fmt.Sprintf("%s=%s", p.key, p.value) +} + +/* +func (p *Param) UnmarshalAmino(rep string) error { + return p.Parse(rep) +} + +func (p Param) MarshalAmino() (string, error) { + return p.String(), nil +} +*/ diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go index 016f3279dbd..ff6476c1438 100644 --- a/gno.land/pkg/gnoland/types.go +++ b/gno.land/pkg/gnoland/types.go @@ -22,4 +22,5 @@ func ProtoGnoAccount() std.Account { type GnoGenesisState struct { Balances []Balance `json:"balances"` Txs []std.Tx `json:"txs"` + Params []Param `json:"params"` } diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go index 5e9e2272049..3c3c7227a99 100644 --- a/gno.land/pkg/integration/testing_node.go +++ b/gno.land/pkg/integration/testing_node.go @@ -59,6 +59,7 @@ func TestingNodeConfig(t TestingTS, gnoroot string, additionalTxs ...std.Tx) (*g creator := crypto.MustAddressFromString(DefaultAccount_Address) // test1 + params := LoadDefaultGenesisParamFile(t, gnoroot) balances := LoadDefaultGenesisBalanceFile(t, gnoroot) txs := []std.Tx{} txs = append(txs, LoadDefaultPackages(t, creator, gnoroot)...) @@ -67,6 +68,7 @@ func TestingNodeConfig(t TestingTS, gnoroot string, additionalTxs ...std.Tx) (*g cfg.Genesis.AppState = gnoland.GnoGenesisState{ Balances: balances, Txs: txs, + Params: params, } return cfg, creator @@ -147,6 +149,16 @@ func LoadDefaultGenesisBalanceFile(t TestingTS, gnoroot string) []gnoland.Balanc return genesisBalances } +// LoadDefaultGenesisParamFile loads the default genesis balance file for testing. +func LoadDefaultGenesisParamFile(t TestingTS, gnoroot string) []gnoland.Param { + paramFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_params.txt") + + genesisParams, err := gnoland.LoadGenesisParamsFile(paramFile) + require.NoError(t, err) + + return genesisParams +} + // LoadDefaultGenesisTXsFile loads the default genesis transactions file for testing. func LoadDefaultGenesisTXsFile(t TestingTS, chainid string, gnoroot string) []std.Tx { txsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.jsonl") From e7840ff5fb7ed008b07fbabb6188f93ac33e1522 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 22 Oct 2024 22:57:23 -0500 Subject: [PATCH 30/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/cmd/gnoland/testdata/genesis_params.txtar | 12 ++++++++++++ gno.land/genesis/params.txt | 14 ++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 gno.land/cmd/gnoland/testdata/genesis_params.txtar diff --git a/gno.land/cmd/gnoland/testdata/genesis_params.txtar b/gno.land/cmd/gnoland/testdata/genesis_params.txtar new file mode 100644 index 00000000000..b70c1e4dc14 --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/genesis_params.txtar @@ -0,0 +1,12 @@ +# test for https://github.com/gnolang/gno/pull/3003 + +gnoland start + +gnokey query params/vm/gno.land/r/sys/params.foo.string +stdout 'data: bar$' +gnokey query params/vm/gno.land/r/sys/params.foo.int64 +stdout 'data: -1337' +gnokey query params/vm/gno.land/r/sys/params.foo.uint64 +stdout 'data: 42' +gnokey query params/vm/gno.land/r/sys/params.foo.bool +stdout 'data: true' diff --git a/gno.land/genesis/params.txt b/gno.land/genesis/params.txt index c687f4891d0..77a2fa48387 100644 --- a/gno.land/genesis/params.txt +++ b/gno.land/genesis/params.txt @@ -1,17 +1,23 @@ -# gno.land +## gno.land gnoland_sys_users_rlm.string=gno.land/r/sys/users -# gnovm +## gnovm vm_enable_namespaces.bool=true #vm_chain_domain.string=gno.land #vm_lock_token=... #vm_gas_xxx=... -# tm2 +## tm2 # ... -# misc +## misc +# ... + +## testing +# do not remove these lines are we are currently having a txtar integration test +# relying on them. foo.string=bar foo.int64=-1337 foo.uint64=42 foo.bool=true +#foo.bytes=todo From f3827711296af225be56cbfdbabd6e26b900b68b Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 23 Oct 2024 12:13:06 -0500 Subject: [PATCH 31/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoland/app.go | 8 +++- gno.land/pkg/gnoland/app_test.go | 18 ++++++++ gno.land/pkg/gnoland/param.go | 75 +++++++++++++++++++++++++++++--- tm2/pkg/sdk/params/handler.go | 1 + 4 files changed, 94 insertions(+), 8 deletions(-) diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index e784f2148aa..cdab1d2c63a 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -290,7 +290,7 @@ func (cfg InitChainerConfig) loadAppState(ctx sdk.Context, appState any) ([]abci return nil, fmt.Errorf("invalid AppState of type %T", appState) } - // Parse and set genesis state balances + // Apply genesis balances. for _, bal := range state.Balances { acc := cfg.acctKpr.NewAccountWithAddress(ctx, bal.Address) cfg.acctKpr.SetAccount(ctx, acc) @@ -300,6 +300,12 @@ func (cfg InitChainerConfig) loadAppState(ctx sdk.Context, appState any) ([]abci } } + // Apply genesis params. + for _, param := range state.Params { + param.Register(ctx, cfg.paramsKpr) + } + + // Replay genesis txs. txResponses := make([]abci.ResponseDeliverTx, 0, len(state.Txs)) // Run genesis txs for _, tx := range state.Txs { diff --git a/gno.land/pkg/gnoland/app_test.go b/gno.land/pkg/gnoland/app_test.go index 193ff0b0b14..75782fb9ccd 100644 --- a/gno.land/pkg/gnoland/app_test.go +++ b/gno.land/pkg/gnoland/app_test.go @@ -63,6 +63,13 @@ func TestNewAppWithOptions(t *testing.T) { Signatures: []std.Signature{{}}, // one empty signature }, }, + Params: []Param{ + {key: "foo.string", string_val: "hello"}, + {key: "bar.int64", int64_val: -42}, + {key: "foo.uint64", uint64_val: 1337}, + {key: "bar.bool", bool_val: true}, + {key: "foo.bytes", bytes_val: []byte{0x48, 0x69, 0x21}}, + }, }, }) require.True(t, resp.IsOK(), "InitChain response: %v", resp) @@ -84,6 +91,17 @@ func TestNewAppWithOptions(t *testing.T) { Tx: tx, }) require.True(t, dtxResp.IsOK(), "DeliverTx response: %v", dtxResp) + + for _, path := range []string{ + "params/vm/foo.string", + "params/foo.string", + "vm/foo.string", + } { + qres := bapp.Query(abci.RequestQuery{ + Path: path, + }) + println("path=", path, "ok=", qres.IsOK(), "res=", string(qres.Data), "error=", qres.Error.Error()) + } } func TestNewAppWithOptions_ErrNoDB(t *testing.T) { diff --git a/gno.land/pkg/gnoland/param.go b/gno.land/pkg/gnoland/param.go index 6524eecf670..1a172b51bce 100644 --- a/gno.land/pkg/gnoland/param.go +++ b/gno.land/pkg/gnoland/param.go @@ -1,13 +1,22 @@ package gnoland import ( + "errors" "fmt" "strings" + + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/sdk/params" ) type Param struct { - key string - value string // pre-parsing representation + key string + + string_val string + int64_val int64 + uint64_val uint64 + bool_val bool + bytes_val []byte } func (p Param) Verify() error { @@ -16,22 +25,56 @@ func (p Param) Verify() error { } func (p *Param) Parse(entry string) error { - parts := strings.Split(strings.TrimSpace(entry), "=") // .= + parts := strings.SplitN(strings.TrimSpace(entry), "=", 2) // .= if len(parts) != 2 { return fmt.Errorf("malformed entry: %q", entry) } p.key = parts[0] - p.value = parts[1] + kind := p.Kind() + raw := parts[1] + switch kind { + case "string": + p.string_val = raw + case "bool": + panic("not implemented") + case "int64": + panic("not implemented") + case "uint64": + panic("not implemented") + case "bytes": + panic("not implemented") + default: + return errors.New("unsupported param kind: " + kind) + } return p.Verify() } +func (p Param) Kind() string { + return p.key[strings.LastIndex(p.key, ".")+1:] +} + func (p Param) String() string { - return fmt.Sprintf("%s=%s", p.key, p.value) + kind := p.Kind() + switch kind { + case "string": + return fmt.Sprintf("%s=%s", p.key, p.string_val) + case "int64": + return fmt.Sprintf("%s=%d", p.key, p.int64_val) + case "uint64": + return fmt.Sprintf("%s=%d", p.key, p.uint64_val) + case "bool": + if p.bool_val { + return fmt.Sprintf("%s=true", p.key) + } + return fmt.Sprintf("%s=false", p.key) + case "bytes": + return fmt.Sprintf("%s=%x", p.key, p.bytes_val) + } + panic("invalid param kind:" + kind) } -/* func (p *Param) UnmarshalAmino(rep string) error { return p.Parse(rep) } @@ -39,4 +82,22 @@ func (p *Param) UnmarshalAmino(rep string) error { func (p Param) MarshalAmino() (string, error) { return p.String(), nil } -*/ + +func (p Param) Register(ctx sdk.Context, prk params.ParamsKeeperI) { + kind := p.Kind() + switch kind { + case "string": + println("@@@@", p.key, p.string_val) + prk.SetString(ctx, p.key, p.string_val) + case "int64": + prk.SetInt64(ctx, p.key, p.int64_val) + case "uint64": + prk.SetUint64(ctx, p.key, p.uint64_val) + case "bool": + prk.SetBool(ctx, p.key, p.bool_val) + case "bytes": + prk.SetBytes(ctx, p.key, p.bytes_val) + default: + panic("invalid param kind: " + kind) + } +} diff --git a/tm2/pkg/sdk/params/handler.go b/tm2/pkg/sdk/params/handler.go index b662fc06c58..8241eae3210 100644 --- a/tm2/pkg/sdk/params/handler.go +++ b/tm2/pkg/sdk/params/handler.go @@ -28,6 +28,7 @@ func (bh paramsHandler) Process(ctx sdk.Context, msg std.Msg) sdk.Result { // Query func (bh paramsHandler) Query(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { + println("AAAAAAAAAAAAAAAAAAAA", req.Path) switch secondPart(req.Path) { case bh.params.prefix: return bh.queryParam(ctx, req) From d92a95924a0dd57327d90bb00d4cd1553be19cbb Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 23 Oct 2024 12:18:03 -0500 Subject: [PATCH 32/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/sys/params/gno.mod | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/gno.land/r/sys/params/gno.mod b/examples/gno.land/r/sys/params/gno.mod index 2c24e81b2e6..f23f3871054 100644 --- a/examples/gno.land/r/sys/params/gno.mod +++ b/examples/gno.land/r/sys/params/gno.mod @@ -1 +1,3 @@ -module gno.land/r/sys/params \ No newline at end of file +module gno.land/r/sys/params + +require gno.land/p/gov/proposal v0.0.0-latest From 2c4c9792abc96fbdb1b52b897d247203aa4b6a11 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:26:24 -0500 Subject: [PATCH 33/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoland/app_test.go | 24 +++++++++++++++++------- gno.land/pkg/gnoland/param.go | 1 - tm2/pkg/sdk/params/handler.go | 1 - 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/gno.land/pkg/gnoland/app_test.go b/gno.land/pkg/gnoland/app_test.go index 75782fb9ccd..0c27ad5ce46 100644 --- a/gno.land/pkg/gnoland/app_test.go +++ b/gno.land/pkg/gnoland/app_test.go @@ -92,15 +92,25 @@ func TestNewAppWithOptions(t *testing.T) { }) require.True(t, dtxResp.IsOK(), "DeliverTx response: %v", dtxResp) - for _, path := range []string{ - "params/vm/foo.string", - "params/foo.string", - "vm/foo.string", - } { + cres := bapp.Commit() + require.NotNil(t, cres) + + tcs := []struct { + path string + expectedVal string + }{ + {"params/vm/foo.string", `"hello"`}, + {"params/vm/bar.int64", `"-42"`}, + {"params/vm/foo.uint64", `"1337"`}, + {"params/vm/bar.bool", `true`}, + {"params/vm/foo.bytes", `"SGkh"`}, // XXX: make this test more readable + } + for _, tc := range tcs { qres := bapp.Query(abci.RequestQuery{ - Path: path, + Path: tc.path, }) - println("path=", path, "ok=", qres.IsOK(), "res=", string(qres.Data), "error=", qres.Error.Error()) + require.True(t, qres.IsOK()) + require.Equal(t, qres.Data, []byte(tc.expectedVal)) } } diff --git a/gno.land/pkg/gnoland/param.go b/gno.land/pkg/gnoland/param.go index 1a172b51bce..44d0e990b61 100644 --- a/gno.land/pkg/gnoland/param.go +++ b/gno.land/pkg/gnoland/param.go @@ -87,7 +87,6 @@ func (p Param) Register(ctx sdk.Context, prk params.ParamsKeeperI) { kind := p.Kind() switch kind { case "string": - println("@@@@", p.key, p.string_val) prk.SetString(ctx, p.key, p.string_val) case "int64": prk.SetInt64(ctx, p.key, p.int64_val) diff --git a/tm2/pkg/sdk/params/handler.go b/tm2/pkg/sdk/params/handler.go index 8241eae3210..b662fc06c58 100644 --- a/tm2/pkg/sdk/params/handler.go +++ b/tm2/pkg/sdk/params/handler.go @@ -28,7 +28,6 @@ func (bh paramsHandler) Process(ctx sdk.Context, msg std.Msg) sdk.Result { // Query func (bh paramsHandler) Query(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { - println("AAAAAAAAAAAAAAAAAAAA", req.Path) switch secondPart(req.Path) { case bh.params.prefix: return bh.queryParam(ctx, req) From abf17048edf2a884bf2a9b3f1f47b6fa8850143a Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:45:11 -0500 Subject: [PATCH 34/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/sys/params/params.gno | 24 +++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/r/sys/params/params.gno b/examples/gno.land/r/sys/params/params.gno index a944cc6db52..a820c98a611 100644 --- a/examples/gno.land/r/sys/params/params.gno +++ b/examples/gno.land/r/sys/params/params.gno @@ -8,12 +8,32 @@ import ( const daoPkgPath = "gno.land/r/gov/dao" -func NewPropExecutor(key string, value interface{}) proposal.Executor { +func NewStringPropExecutor(key string, value string) proposal.Executor { + return newPropExecutor(func() { std.SetParamString(key, value) }) +} + +func NewInt64PropExecutor(key string, value int64) proposal.Executor { + return newPropExecutor(func() { std.SetParamInt64(key, value) }) +} + +func NewUint64PropExecutor(key string, value uint64) proposal.Executor { + return newPropExecutor(func() { std.SetParamUint64(key, value) }) +} + +func NewBoolPropExecutor(key string, value bool) proposal.Executor { + return newPropExecutor(func() { std.SetParamBool(key, value) }) +} + +func NewBytesPropExecutor(key string, value []byte) proposal.Executor { + return newPropExecutor(func() { std.SetParamBytes(key, value) }) +} + +func newPropExecutor(fn func()) proposal.Executor { callback := func() error { if std.PrevRealm().PkgPath() != daoPkgPath { panic("should be executed from govdao") } - std.SetParam(key, value) + fn() return nil } return proposal.NewExecutor(callback) From 83eae8d6ae9eb5c464dd5e2f5eac49fcc4b4d052 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:52:21 -0500 Subject: [PATCH 35/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoland/param.go | 38 +++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/gno.land/pkg/gnoland/param.go b/gno.land/pkg/gnoland/param.go index 44d0e990b61..8113eb14d08 100644 --- a/gno.land/pkg/gnoland/param.go +++ b/gno.land/pkg/gnoland/param.go @@ -24,6 +24,14 @@ func (p Param) Verify() error { return nil } +const ( + ParamKindString = "string" + ParamKindInt64 = "int64" + ParamKindUint64 = "uint64" + ParamKindBool = "bool" + ParamKindBytes = "bytes" +) + func (p *Param) Parse(entry string) error { parts := strings.SplitN(strings.TrimSpace(entry), "=", 2) // .= if len(parts) != 2 { @@ -34,15 +42,15 @@ func (p *Param) Parse(entry string) error { kind := p.Kind() raw := parts[1] switch kind { - case "string": + case ParamKindString: p.string_val = raw - case "bool": + case ParamKindBool: panic("not implemented") - case "int64": + case ParamKindInt64: panic("not implemented") - case "uint64": + case ParamKindUint64: panic("not implemented") - case "bytes": + case ParamKindBytes: panic("not implemented") default: return errors.New("unsupported param kind: " + kind) @@ -58,18 +66,18 @@ func (p Param) Kind() string { func (p Param) String() string { kind := p.Kind() switch kind { - case "string": + case ParamKindString: return fmt.Sprintf("%s=%s", p.key, p.string_val) - case "int64": + case ParamKindInt64: return fmt.Sprintf("%s=%d", p.key, p.int64_val) - case "uint64": + case ParamKindUint64: return fmt.Sprintf("%s=%d", p.key, p.uint64_val) - case "bool": + case ParamKindBool: if p.bool_val { return fmt.Sprintf("%s=true", p.key) } return fmt.Sprintf("%s=false", p.key) - case "bytes": + case ParamKindBytes: return fmt.Sprintf("%s=%x", p.key, p.bytes_val) } panic("invalid param kind:" + kind) @@ -86,15 +94,15 @@ func (p Param) MarshalAmino() (string, error) { func (p Param) Register(ctx sdk.Context, prk params.ParamsKeeperI) { kind := p.Kind() switch kind { - case "string": + case ParamKindString: prk.SetString(ctx, p.key, p.string_val) - case "int64": + case ParamKindInt64: prk.SetInt64(ctx, p.key, p.int64_val) - case "uint64": + case ParamKindUint64: prk.SetUint64(ctx, p.key, p.uint64_val) - case "bool": + case ParamKindBool: prk.SetBool(ctx, p.key, p.bool_val) - case "bytes": + case ParamKindBytes: prk.SetBytes(ctx, p.key, p.bytes_val) default: panic("invalid param kind: " + kind) From 672fb9757392a7c4312feccd06278b61ad91adef Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 23 Oct 2024 15:15:04 -0500 Subject: [PATCH 36/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoland/app_test.go | 10 ++--- gno.land/pkg/gnoland/param.go | 60 +++++++++++++++++++----------- gno.land/pkg/gnoland/param_test.go | 38 +++++++++++++++++++ 3 files changed, 82 insertions(+), 26 deletions(-) create mode 100644 gno.land/pkg/gnoland/param_test.go diff --git a/gno.land/pkg/gnoland/app_test.go b/gno.land/pkg/gnoland/app_test.go index 0c27ad5ce46..a6542fc2b21 100644 --- a/gno.land/pkg/gnoland/app_test.go +++ b/gno.land/pkg/gnoland/app_test.go @@ -64,11 +64,11 @@ func TestNewAppWithOptions(t *testing.T) { }, }, Params: []Param{ - {key: "foo.string", string_val: "hello"}, - {key: "bar.int64", int64_val: -42}, - {key: "foo.uint64", uint64_val: 1337}, - {key: "bar.bool", bool_val: true}, - {key: "foo.bytes", bytes_val: []byte{0x48, 0x69, 0x21}}, + {key: "foo.string", stringVal: "hello"}, + {key: "bar.int64", int64Val: -42}, + {key: "foo.uint64", uint64Val: 1337}, + {key: "bar.bool", boolVal: true}, + {key: "foo.bytes", bytesVal: []byte{0x48, 0x69, 0x21}}, }, }, }) diff --git a/gno.land/pkg/gnoland/param.go b/gno.land/pkg/gnoland/param.go index 8113eb14d08..171501dcb15 100644 --- a/gno.land/pkg/gnoland/param.go +++ b/gno.land/pkg/gnoland/param.go @@ -1,8 +1,10 @@ package gnoland import ( + "encoding/hex" "errors" "fmt" + "strconv" "strings" "github.com/gnolang/gno/tm2/pkg/sdk" @@ -12,11 +14,11 @@ import ( type Param struct { key string - string_val string - int64_val int64 - uint64_val uint64 - bool_val bool - bytes_val []byte + stringVal string + int64Val int64 + uint64Val uint64 + boolVal bool + bytesVal []byte } func (p Param) Verify() error { @@ -43,15 +45,31 @@ func (p *Param) Parse(entry string) error { raw := parts[1] switch kind { case ParamKindString: - p.string_val = raw - case ParamKindBool: - panic("not implemented") + p.stringVal = raw case ParamKindInt64: - panic("not implemented") + v, err := strconv.ParseInt(raw, 10, 64) + if err != nil { + return err + } + p.int64Val = v + case ParamKindBool: + v, err := strconv.ParseBool(raw) + if err != nil { + return err + } + p.boolVal = v case ParamKindUint64: - panic("not implemented") + v, err := strconv.ParseUint(raw, 10, 64) + if err != nil { + return err + } + p.uint64Val = v case ParamKindBytes: - panic("not implemented") + v, err := hex.DecodeString(raw) + if err != nil { + return err + } + p.bytesVal = v default: return errors.New("unsupported param kind: " + kind) } @@ -67,18 +85,18 @@ func (p Param) String() string { kind := p.Kind() switch kind { case ParamKindString: - return fmt.Sprintf("%s=%s", p.key, p.string_val) + return fmt.Sprintf("%s=%s", p.key, p.stringVal) case ParamKindInt64: - return fmt.Sprintf("%s=%d", p.key, p.int64_val) + return fmt.Sprintf("%s=%d", p.key, p.int64Val) case ParamKindUint64: - return fmt.Sprintf("%s=%d", p.key, p.uint64_val) + return fmt.Sprintf("%s=%d", p.key, p.uint64Val) case ParamKindBool: - if p.bool_val { + if p.boolVal { return fmt.Sprintf("%s=true", p.key) } return fmt.Sprintf("%s=false", p.key) case ParamKindBytes: - return fmt.Sprintf("%s=%x", p.key, p.bytes_val) + return fmt.Sprintf("%s=%x", p.key, p.bytesVal) } panic("invalid param kind:" + kind) } @@ -95,15 +113,15 @@ func (p Param) Register(ctx sdk.Context, prk params.ParamsKeeperI) { kind := p.Kind() switch kind { case ParamKindString: - prk.SetString(ctx, p.key, p.string_val) + prk.SetString(ctx, p.key, p.stringVal) case ParamKindInt64: - prk.SetInt64(ctx, p.key, p.int64_val) + prk.SetInt64(ctx, p.key, p.int64Val) case ParamKindUint64: - prk.SetUint64(ctx, p.key, p.uint64_val) + prk.SetUint64(ctx, p.key, p.uint64Val) case ParamKindBool: - prk.SetBool(ctx, p.key, p.bool_val) + prk.SetBool(ctx, p.key, p.boolVal) case ParamKindBytes: - prk.SetBytes(ctx, p.key, p.bytes_val) + prk.SetBytes(ctx, p.key, p.bytesVal) default: panic("invalid param kind: " + kind) } diff --git a/gno.land/pkg/gnoland/param_test.go b/gno.land/pkg/gnoland/param_test.go new file mode 100644 index 00000000000..226fd841b8e --- /dev/null +++ b/gno.land/pkg/gnoland/param_test.go @@ -0,0 +1,38 @@ +package gnoland + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestParam_Parse(t *testing.T) { + tests := []struct { + name string + entry string + expected Param + expectErr bool + }{ + {"valid string", "foo.string=hello", Param{key: "foo.string", stringVal: "hello"}, false}, + {"valid int64", "foo.int64=-1337", Param{key: "foo.int64", int64Val: -1337}, false}, + {"valid uint64", "foo.uint64=42", Param{key: "foo.uint64", uint64Val: 42}, false}, + {"valid bool", "foo.bool=true", Param{key: "foo.bool", boolVal: true}, false}, + {"valid bytes", "foo.bytes=AAAA", Param{key: "foo.bytes", bytesVal: []byte{0xaa, 0xaa}}, false}, + {"invalid key", "invalidkey=foo", Param{}, true}, + {"invalid int64", "invalid.int64=foobar", Param{}, true}, + {"invalid uint64", "invalid.uint64=-42", Param{}, true}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + param := Param{} + err := param.Parse(tc.entry) + if tc.expectErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.expected, param) + } + }) + } +} From 95c975d5f6b533cff9a27615ca738b590ed9095c Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:53:35 -0500 Subject: [PATCH 37/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../gno.land/r/gov/dao/prop2_filetest.gno | 3 - .../gno.land/r/gov/dao/prop3_filetest.gno | 88 +++++++++++++++++++ examples/gno.land/r/sys/params/params.gno | 15 ++-- gno.land/pkg/gnoland/param_test.go | 1 + gnovm/tests/file.go | 17 ++++ 5 files changed, 115 insertions(+), 9 deletions(-) create mode 100644 examples/gno.land/r/gov/dao/prop3_filetest.gno diff --git a/examples/gno.land/r/gov/dao/prop2_filetest.gno b/examples/gno.land/r/gov/dao/prop2_filetest.gno index 047709cc45f..e5738840d83 100644 --- a/examples/gno.land/r/gov/dao/prop2_filetest.gno +++ b/examples/gno.land/r/gov/dao/prop2_filetest.gno @@ -18,11 +18,8 @@ func init() { } mExec := govdao.NewPropExecutor(membersFn) - comment := "adding someone to vote" - id := govdao.Propose(comment, mExec) - govdao.ExecuteProposal(id) executor := proposal.NewCtxExecutor(func(ctx context.Context) error { diff --git a/examples/gno.land/r/gov/dao/prop3_filetest.gno b/examples/gno.land/r/gov/dao/prop3_filetest.gno new file mode 100644 index 00000000000..e6305db9c31 --- /dev/null +++ b/examples/gno.land/r/gov/dao/prop3_filetest.gno @@ -0,0 +1,88 @@ +package main + +import ( + "std" + + "gno.land/r/gnoland/blog" + govdao "gno.land/r/gov/dao" + "gno.land/r/sys/params" +) + +func init() { + { // prop0 + membersFn := func() []std.Address { + return []std.Address{ + std.Address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), + } + } + mExec := govdao.NewPropExecutor(membersFn) + comment := "adding someone to vote" + id := govdao.Propose(comment, mExec) + govdao.ExecuteProposal(id) + } + + { // prop1 + mExec := params.NewStringPropExecutor("prop1.string", "value1") + comment := "setting prop1.string param" + id := govdao.Propose(comment, mExec) + } +} + +func main() { + println("--") + println(govdao.Render("")) + println("--") + println(govdao.Render("1")) + println("--") + govdao.VoteOnProposal(1, "YES") + println("--") + println(govdao.Render("1")) + println("--") + govdao.ExecuteProposal(1) + println("--") + println(govdao.Render("1")) +} + +// Events: + +// Output: +// -- +// - [0](/r/gov/dao:0) - adding someone to vote (**succeeded**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// - [1](/r/gov/dao:1) - setting prop1.string param (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// +// -- +// # Prop #1 +// +// setting prop1.string param +// +// Status: active +// +// Voting status: YES: 0, NO: 0, percent: 0, members: 1 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// +// -- +// -- +// # Prop #1 +// +// setting prop1.string param +// +// Status: accepted +// +// Voting status: YES: 1, NO: 0, percent: 100, members: 1 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// +// -- +// -- +// # Prop #1 +// +// setting prop1.string param +// +// Status: succeeded +// +// Voting status: YES: 1, NO: 0, percent: 100, members: 1 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm diff --git a/examples/gno.land/r/sys/params/params.gno b/examples/gno.land/r/sys/params/params.gno index a820c98a611..676f23f0193 100644 --- a/examples/gno.land/r/sys/params/params.gno +++ b/examples/gno.land/r/sys/params/params.gno @@ -9,30 +9,33 @@ import ( const daoPkgPath = "gno.land/r/gov/dao" func NewStringPropExecutor(key string, value string) proposal.Executor { - return newPropExecutor(func() { std.SetParamString(key, value) }) + return newPropExecutor(key, func() { std.SetParamString(key, value) }) } func NewInt64PropExecutor(key string, value int64) proposal.Executor { - return newPropExecutor(func() { std.SetParamInt64(key, value) }) + return newPropExecutor(key, func() { std.SetParamInt64(key, value) }) } func NewUint64PropExecutor(key string, value uint64) proposal.Executor { - return newPropExecutor(func() { std.SetParamUint64(key, value) }) + return newPropExecutor(key, func() { std.SetParamUint64(key, value) }) } func NewBoolPropExecutor(key string, value bool) proposal.Executor { - return newPropExecutor(func() { std.SetParamBool(key, value) }) + return newPropExecutor(key, func() { std.SetParamBool(key, value) }) } func NewBytesPropExecutor(key string, value []byte) proposal.Executor { - return newPropExecutor(func() { std.SetParamBytes(key, value) }) + return newPropExecutor(key, func() { std.SetParamBytes(key, value) }) } -func newPropExecutor(fn func()) proposal.Executor { +func newPropExecutor(key string, fn func()) proposal.Executor { callback := func() error { if std.PrevRealm().PkgPath() != daoPkgPath { panic("should be executed from govdao") } + std.Emit("set", + "k", key, + ) fn() return nil } diff --git a/gno.land/pkg/gnoland/param_test.go b/gno.land/pkg/gnoland/param_test.go index 226fd841b8e..6cd4097552f 100644 --- a/gno.land/pkg/gnoland/param_test.go +++ b/gno.land/pkg/gnoland/param_test.go @@ -19,6 +19,7 @@ func TestParam_Parse(t *testing.T) { {"valid bool", "foo.bool=true", Param{key: "foo.bool", boolVal: true}, false}, {"valid bytes", "foo.bytes=AAAA", Param{key: "foo.bytes", bytesVal: []byte{0xaa, 0xaa}}, false}, {"invalid key", "invalidkey=foo", Param{}, true}, + {"invalid kind", "invalid.kind=foo", Param{}, true}, {"invalid int64", "invalid.int64=foobar", Param{}, true}, {"invalid uint64", "invalid.uint64=-42", Param{}, true}, } diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index f45beffe648..62cc2129d64 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -56,6 +56,7 @@ func TestContext(pkgPath string, send std.Coins) *teststd.TestExecContext { pkgCoins := std.MustParseCoins(ugnot.ValueString(200000000)).Add(send) // >= send. banker := newTestBanker(pkgAddr.Bech32(), pkgCoins) + params := newTestParams() ctx := stdlibs.ExecContext{ ChainID: "dev", Height: 123, @@ -66,6 +67,7 @@ func TestContext(pkgPath string, send std.Coins) *teststd.TestExecContext { OrigSend: send, OrigSendSpent: new(std.Coins), Banker: banker, + Params: params, EventLogger: sdk.NewEventLogger(), } return &teststd.TestExecContext{ @@ -574,6 +576,21 @@ func trimTrailingSpaces(result string) string { return strings.Join(lines, "\n") } +// ---------------------------------------- +// testParams +type testParams struct{} + +func newTestParams() *testParams { + return &testParams{} +} + +// XXX: not noop? +func (tp *testParams) SetBool(key string, val bool) { /* noop */ } +func (tp *testParams) SetBytes(key string, val []byte) { /* noop */ } +func (tp *testParams) SetInt64(key string, val int64) { /* noop */ } +func (tp *testParams) SetUint64(key string, val uint64) { /* noop */ } +func (tp *testParams) SetString(key string, val string) { /* noop */ } + // ---------------------------------------- // testBanker From 9bc2f6ef4febf0ca61cdc1a9bc77ee1ffbebe642 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:00:55 -0500 Subject: [PATCH 38/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/gov/dao/prop3_filetest.gno | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/gno.land/r/gov/dao/prop3_filetest.gno b/examples/gno.land/r/gov/dao/prop3_filetest.gno index e6305db9c31..d797e337d26 100644 --- a/examples/gno.land/r/gov/dao/prop3_filetest.gno +++ b/examples/gno.land/r/gov/dao/prop3_filetest.gno @@ -26,6 +26,12 @@ func init() { comment := "setting prop1.string param" id := govdao.Propose(comment, mExec) } + + { // prop2 + mExec := params.NewInt64PropExecutor("prop2.int64", 12345) + comment := "setting prop2.int64 param" + id := govdao.Propose(comment, mExec) + } } func main() { @@ -44,11 +50,13 @@ func main() { } // Events: +// [{"type":"set","attrs":[{"key":"k","value":"prop1.string"}],"pkg_path":"gno.land/r/sys/params","func":""}] // Output: // -- // - [0](/r/gov/dao:0) - adding someone to vote (**succeeded**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) // - [1](/r/gov/dao:1) - setting prop1.string param (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// - [2](/r/gov/dao:2) - setting prop2.int64 param (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) // // -- // # Prop #1 From af5b3137e8da3da7205646ffad02b8952fce1062 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:23:29 -0500 Subject: [PATCH 39/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../cmd/gnoland/testdata/genesis_params.txtar | 8 ++++--- gno.land/genesis/genesis_params.txt | 23 +++++++++++++++++++ gno.land/genesis/params.txt | 23 ------------------- .../pkg/integration/testing_integration.go | 1 + 4 files changed, 29 insertions(+), 26 deletions(-) create mode 100644 gno.land/genesis/genesis_params.txt delete mode 100644 gno.land/genesis/params.txt diff --git a/gno.land/cmd/gnoland/testdata/genesis_params.txtar b/gno.land/cmd/gnoland/testdata/genesis_params.txtar index b70c1e4dc14..07b9349319f 100644 --- a/gno.land/cmd/gnoland/testdata/genesis_params.txtar +++ b/gno.land/cmd/gnoland/testdata/genesis_params.txtar @@ -3,10 +3,12 @@ gnoland start gnokey query params/vm/gno.land/r/sys/params.foo.string -stdout 'data: bar$' +stdout 'data: "bar"$' gnokey query params/vm/gno.land/r/sys/params.foo.int64 -stdout 'data: -1337' +stdout 'data: "-1337"' gnokey query params/vm/gno.land/r/sys/params.foo.uint64 -stdout 'data: 42' +stdout 'data: "42"' gnokey query params/vm/gno.land/r/sys/params.foo.bool stdout 'data: true' +# XXX: bytes + diff --git a/gno.land/genesis/genesis_params.txt b/gno.land/genesis/genesis_params.txt new file mode 100644 index 00000000000..ebc4a646912 --- /dev/null +++ b/gno.land/genesis/genesis_params.txt @@ -0,0 +1,23 @@ +## gno.land +gno.land/r/sys/params.gnoland_sys_users_rlm.string=gno.land/r/sys/users + +## gnovm +gno.land/r/sys/params.vm_enable_namespaces.bool=true +#gno.land/r/sys/params.vm_chain_domain.string=gno.land +#gno.land/r/sys/params.vm_lock_token=... +#gno.land/r/sys/params.vm_gas_xxx=... + +## tm2 +# ... + +## misc +# ... + +## testing +# do not remove these lines are we are currently having a txtar integration test +# relying on them. +gno.land/r/sys/params.foo.string=bar +gno.land/r/sys/params.foo.int64=-1337 +gno.land/r/sys/params.foo.uint64=42 +gno.land/r/sys/params.foo.bool=true +#gno.land/r/sys/params.foo.bytes=todo diff --git a/gno.land/genesis/params.txt b/gno.land/genesis/params.txt deleted file mode 100644 index 77a2fa48387..00000000000 --- a/gno.land/genesis/params.txt +++ /dev/null @@ -1,23 +0,0 @@ -## gno.land -gnoland_sys_users_rlm.string=gno.land/r/sys/users - -## gnovm -vm_enable_namespaces.bool=true -#vm_chain_domain.string=gno.land -#vm_lock_token=... -#vm_gas_xxx=... - -## tm2 -# ... - -## misc -# ... - -## testing -# do not remove these lines are we are currently having a txtar integration test -# relying on them. -foo.string=bar -foo.int64=-1337 -foo.uint64=42 -foo.bool=true -#foo.bytes=todo diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index d3f55cfadf7..0ba0c6c6bdf 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -134,6 +134,7 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { // This genesis will be use when node is started. genesis := &gnoland.GnoGenesisState{ Balances: LoadDefaultGenesisBalanceFile(t, gnoRootDir), + Params: LoadDefaultGenesisParamFile(t, gnoRootDir), Txs: []std.Tx{}, } From 9b230684318f66c60a1ab75cef1616f25707aba6 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 24 Oct 2024 07:30:09 -0500 Subject: [PATCH 40/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/genesis/genesis_params.txt | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/gno.land/genesis/genesis_params.txt b/gno.land/genesis/genesis_params.txt index ebc4a646912..27ebb7b8ced 100644 --- a/gno.land/genesis/genesis_params.txt +++ b/gno.land/genesis/genesis_params.txt @@ -1,11 +1,17 @@ ## gno.land -gno.land/r/sys/params.gnoland_sys_users_rlm.string=gno.land/r/sys/users +[[gno.land/r/sys/params.sys]] + token_lock=true + users_pkgpath.string=gno.land/r/sys/users + validators_pkgpath.string=gno.land/r/sys/validators + rewards_pkgpath.string=gno.land/r/sys/rewards ## gnovm -gno.land/r/sys/params.vm_enable_namespaces.bool=true -#gno.land/r/sys/params.vm_chain_domain.string=gno.land -#gno.land/r/sys/params.vm_lock_token=... -#gno.land/r/sys/params.vm_gas_xxx=... +[[gno.land/r/sys/params.vm]] + namespaces.bool=true + max_gas.int64=10_000_000_000 + chain_tz.string=UTC + default_storage_allowance.string=UTC + #chain_domain.string=gno.land ## tm2 # ... @@ -16,8 +22,9 @@ gno.land/r/sys/params.vm_enable_namespaces.bool=true ## testing # do not remove these lines are we are currently having a txtar integration test # relying on them. -gno.land/r/sys/params.foo.string=bar -gno.land/r/sys/params.foo.int64=-1337 -gno.land/r/sys/params.foo.uint64=42 -gno.land/r/sys/params.foo.bool=true -#gno.land/r/sys/params.foo.bytes=todo +[[gno.land/r/sys/params.test]] + foo.string=bar + foo.int64=-1337 + foo.uint64=42 + foo.bool=true + #foo.bytes=todo From f6fc9ae6ed9f84c62ee783fb5a25cc04b28daecf Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 24 Oct 2024 12:17:24 -0500 Subject: [PATCH 41/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../cmd/gnoland/testdata/genesis_params.txtar | 8 +-- gno.land/genesis/genesis_params.txt | 30 --------- gno.land/pkg/gnoland/app_test.go | 10 +-- gno.land/pkg/gnoland/genesis.go | 43 +++++++------ gno.land/pkg/gnoland/param.go | 64 ++++++++----------- gno.land/pkg/gnoland/param_test.go | 10 +-- gno.land/pkg/integration/testing_node.go | 2 +- tm2/pkg/sdk/params/keeper.go | 2 +- 8 files changed, 69 insertions(+), 100 deletions(-) delete mode 100644 gno.land/genesis/genesis_params.txt diff --git a/gno.land/cmd/gnoland/testdata/genesis_params.txtar b/gno.land/cmd/gnoland/testdata/genesis_params.txtar index 07b9349319f..43ecd8ccacb 100644 --- a/gno.land/cmd/gnoland/testdata/genesis_params.txtar +++ b/gno.land/cmd/gnoland/testdata/genesis_params.txtar @@ -2,13 +2,13 @@ gnoland start -gnokey query params/vm/gno.land/r/sys/params.foo.string +gnokey query params/vm/gno.land/r/sys/params.test.foo.string stdout 'data: "bar"$' -gnokey query params/vm/gno.land/r/sys/params.foo.int64 +gnokey query params/vm/gno.land/r/sys/params.test.foo.int64 stdout 'data: "-1337"' -gnokey query params/vm/gno.land/r/sys/params.foo.uint64 +gnokey query params/vm/gno.land/r/sys/params.test.foo.uint64 stdout 'data: "42"' -gnokey query params/vm/gno.land/r/sys/params.foo.bool +gnokey query params/vm/gno.land/r/sys/params.test.foo.bool stdout 'data: true' # XXX: bytes diff --git a/gno.land/genesis/genesis_params.txt b/gno.land/genesis/genesis_params.txt deleted file mode 100644 index 27ebb7b8ced..00000000000 --- a/gno.land/genesis/genesis_params.txt +++ /dev/null @@ -1,30 +0,0 @@ -## gno.land -[[gno.land/r/sys/params.sys]] - token_lock=true - users_pkgpath.string=gno.land/r/sys/users - validators_pkgpath.string=gno.land/r/sys/validators - rewards_pkgpath.string=gno.land/r/sys/rewards - -## gnovm -[[gno.land/r/sys/params.vm]] - namespaces.bool=true - max_gas.int64=10_000_000_000 - chain_tz.string=UTC - default_storage_allowance.string=UTC - #chain_domain.string=gno.land - -## tm2 -# ... - -## misc -# ... - -## testing -# do not remove these lines are we are currently having a txtar integration test -# relying on them. -[[gno.land/r/sys/params.test]] - foo.string=bar - foo.int64=-1337 - foo.uint64=42 - foo.bool=true - #foo.bytes=todo diff --git a/gno.land/pkg/gnoland/app_test.go b/gno.land/pkg/gnoland/app_test.go index a6542fc2b21..c48d2b67d0c 100644 --- a/gno.land/pkg/gnoland/app_test.go +++ b/gno.land/pkg/gnoland/app_test.go @@ -64,11 +64,11 @@ func TestNewAppWithOptions(t *testing.T) { }, }, Params: []Param{ - {key: "foo.string", stringVal: "hello"}, - {key: "bar.int64", int64Val: -42}, - {key: "foo.uint64", uint64Val: 1337}, - {key: "bar.bool", boolVal: true}, - {key: "foo.bytes", bytesVal: []byte{0x48, 0x69, 0x21}}, + {key: "foo", kind: "string", value: "hello"}, + {key: "foo", kind: "int64", value: int64(-42)}, + {key: "foo", kind: "uint64", value: uint64(1337)}, + {key: "foo", kind: "bool", value: true}, + {key: "foo", kind: "bytes", value: []byte{0x48, 0x69, 0x21}}, }, }, }) diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go index 61c4615f4f0..3763c391b13 100644 --- a/gno.land/pkg/gnoland/genesis.go +++ b/gno.land/pkg/gnoland/genesis.go @@ -13,6 +13,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/crypto" osm "github.com/gnolang/gno/tm2/pkg/os" "github.com/gnolang/gno/tm2/pkg/std" + "github.com/pelletier/go-toml" ) // LoadGenesisBalancesFile loads genesis balances from the provided file path. @@ -62,27 +63,33 @@ func LoadGenesisBalancesFile(path string) ([]Balance, error) { func LoadGenesisParamsFile(path string) ([]Param, error) { // each param is in the form: key.kind=value content := osm.MustReadFile(path) - lines := strings.Split(string(content), "\n") - - params := make([]Param, 0, len(lines)) - for _, line := range lines { - line = strings.TrimSpace(line) - - // remove comments. - line = strings.Split(line, "#")[0] - line = strings.TrimSpace(line) - // skip empty lines. - if line == "" { - continue - } + m := map[string] /*category*/ map[string] /*key*/ map[string] /*kind*/ interface{} /*value*/ {} + err := toml.Unmarshal(content, &m) + if err != nil { + return nil, err + } - var p Param - if err := p.Parse(line); err != nil { - return nil, errors.New("invalid genesis_param line: " + line) + params := make([]Param, 0) + for category, keys := range m { + for key, kinds := range keys { + for kind, val := range kinds { + param := Param{ + key: category + "." + key, + kind: kind, + } + switch kind { + case "uint64": // toml + param.value = uint64(val.(int64)) + default: + param.value = val + } + if err := param.Verify(); err != nil { + return nil, err + } + params = append(params, param) + } } - - params = append(params, p) } return params, nil diff --git a/gno.land/pkg/gnoland/param.go b/gno.land/pkg/gnoland/param.go index 171501dcb15..8ca97ad028f 100644 --- a/gno.land/pkg/gnoland/param.go +++ b/gno.land/pkg/gnoland/param.go @@ -12,13 +12,9 @@ import ( ) type Param struct { - key string - - stringVal string - int64Val int64 - uint64Val uint64 - boolVal bool - bytesVal []byte + key string + kind string + value interface{} } func (p Param) Verify() error { @@ -40,65 +36,61 @@ func (p *Param) Parse(entry string) error { return fmt.Errorf("malformed entry: %q", entry) } - p.key = parts[0] - kind := p.Kind() + keyWithKind := parts[0] + p.kind = keyWithKind[strings.LastIndex(keyWithKind, ".")+1:] + p.key = strings.TrimSuffix(keyWithKind, "."+p.kind) raw := parts[1] - switch kind { + switch p.kind { case ParamKindString: - p.stringVal = raw + p.value = raw case ParamKindInt64: v, err := strconv.ParseInt(raw, 10, 64) if err != nil { return err } - p.int64Val = v + p.value = v case ParamKindBool: v, err := strconv.ParseBool(raw) if err != nil { return err } - p.boolVal = v + p.value = v case ParamKindUint64: v, err := strconv.ParseUint(raw, 10, 64) if err != nil { return err } - p.uint64Val = v + p.value = v case ParamKindBytes: v, err := hex.DecodeString(raw) if err != nil { return err } - p.bytesVal = v + p.value = v default: - return errors.New("unsupported param kind: " + kind) + return errors.New("unsupported param kind: " + p.kind) } return p.Verify() } -func (p Param) Kind() string { - return p.key[strings.LastIndex(p.key, ".")+1:] -} - func (p Param) String() string { - kind := p.Kind() - switch kind { + switch p.kind { case ParamKindString: - return fmt.Sprintf("%s=%s", p.key, p.stringVal) + return fmt.Sprintf("%s=%s", p.key, p.value) case ParamKindInt64: - return fmt.Sprintf("%s=%d", p.key, p.int64Val) + return fmt.Sprintf("%s=%d", p.key, p.value) case ParamKindUint64: - return fmt.Sprintf("%s=%d", p.key, p.uint64Val) + return fmt.Sprintf("%s=%d", p.key, p.value) case ParamKindBool: - if p.boolVal { + if p.value.(bool) { return fmt.Sprintf("%s=true", p.key) } return fmt.Sprintf("%s=false", p.key) case ParamKindBytes: - return fmt.Sprintf("%s=%x", p.key, p.bytesVal) + return fmt.Sprintf("%s=%x", p.key, p.value) } - panic("invalid param kind:" + kind) + panic("invalid param kind:" + p.kind) } func (p *Param) UnmarshalAmino(rep string) error { @@ -110,19 +102,19 @@ func (p Param) MarshalAmino() (string, error) { } func (p Param) Register(ctx sdk.Context, prk params.ParamsKeeperI) { - kind := p.Kind() - switch kind { + key := p.key + "." + p.kind + switch p.kind { case ParamKindString: - prk.SetString(ctx, p.key, p.stringVal) + prk.SetString(ctx, key, p.value.(string)) case ParamKindInt64: - prk.SetInt64(ctx, p.key, p.int64Val) + prk.SetInt64(ctx, key, p.value.(int64)) case ParamKindUint64: - prk.SetUint64(ctx, p.key, p.uint64Val) + prk.SetUint64(ctx, key, p.value.(uint64)) case ParamKindBool: - prk.SetBool(ctx, p.key, p.boolVal) + prk.SetBool(ctx, key, p.value.(bool)) case ParamKindBytes: - prk.SetBytes(ctx, p.key, p.bytesVal) + prk.SetBytes(ctx, key, p.value.([]byte)) default: - panic("invalid param kind: " + kind) + panic("invalid param kind: " + p.kind) } } diff --git a/gno.land/pkg/gnoland/param_test.go b/gno.land/pkg/gnoland/param_test.go index 6cd4097552f..3c072ff5c8d 100644 --- a/gno.land/pkg/gnoland/param_test.go +++ b/gno.land/pkg/gnoland/param_test.go @@ -13,11 +13,11 @@ func TestParam_Parse(t *testing.T) { expected Param expectErr bool }{ - {"valid string", "foo.string=hello", Param{key: "foo.string", stringVal: "hello"}, false}, - {"valid int64", "foo.int64=-1337", Param{key: "foo.int64", int64Val: -1337}, false}, - {"valid uint64", "foo.uint64=42", Param{key: "foo.uint64", uint64Val: 42}, false}, - {"valid bool", "foo.bool=true", Param{key: "foo.bool", boolVal: true}, false}, - {"valid bytes", "foo.bytes=AAAA", Param{key: "foo.bytes", bytesVal: []byte{0xaa, 0xaa}}, false}, + {"valid string", "foo.string=hello", Param{key: "foo", kind: "string", value: "hello"}, false}, + {"valid int64", "foo.int64=-1337", Param{key: "foo", kind: "int64", value: int64(-1337)}, false}, + {"valid uint64", "foo.uint64=42", Param{key: "foo", kind: "uint64", value: uint64(42)}, false}, + {"valid bool", "foo.bool=true", Param{key: "foo", kind: "bool", value: true}, false}, + {"valid bytes", "foo.bytes=AAAA", Param{key: "foo", kind: "bytes", value: []byte{0xaa, 0xaa}}, false}, {"invalid key", "invalidkey=foo", Param{}, true}, {"invalid kind", "invalid.kind=foo", Param{}, true}, {"invalid int64", "invalid.int64=foobar", Param{}, true}, diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go index 3c3c7227a99..3f5807d8fae 100644 --- a/gno.land/pkg/integration/testing_node.go +++ b/gno.land/pkg/integration/testing_node.go @@ -151,7 +151,7 @@ func LoadDefaultGenesisBalanceFile(t TestingTS, gnoroot string) []gnoland.Balanc // LoadDefaultGenesisParamFile loads the default genesis balance file for testing. func LoadDefaultGenesisParamFile(t TestingTS, gnoroot string) []gnoland.Param { - paramFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_params.txt") + paramFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_params.toml") genesisParams, err := gnoland.LoadGenesisParamsFile(paramFile) require.NoError(t, err) diff --git a/tm2/pkg/sdk/params/keeper.go b/tm2/pkg/sdk/params/keeper.go index ffeb1775acb..523e8d54f69 100644 --- a/tm2/pkg/sdk/params/keeper.go +++ b/tm2/pkg/sdk/params/keeper.go @@ -152,6 +152,6 @@ func checkSuffix(key, expectedSuffix string) { // XXX: additional sanity checks? ) if noSuffix || noName { - panic(`key should be like "` + expectedSuffix + `"`) + panic(`key should be like "` + expectedSuffix + `" (` + key + `)`) } } From 18944a24e4c82fbddd378e213a968092d4c4ef91 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:08:57 -0500 Subject: [PATCH 42/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/genesis/genesis_params.toml | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 gno.land/genesis/genesis_params.toml diff --git a/gno.land/genesis/genesis_params.toml b/gno.land/genesis/genesis_params.toml new file mode 100644 index 00000000000..4021d1166a9 --- /dev/null +++ b/gno.land/genesis/genesis_params.toml @@ -0,0 +1,29 @@ +## gno.land +["gno.land/r/sys/params.sys"] + token_lock.bool = true + users_pkgpath.string = "gno.land/r/sys/users" + validators_pkgpath.string = "gno.land/r/sys/validators" + rewards_pkgpath.string = "gno.land/r/sys/rewards" + +## gnovm +["gno.land/r/sys/params.vm"] + namespaces.bool = true + max_gas.int64 = 10_000_000_000 + chain_tz.string = "UTC" + default_storage_allowance.string = "UTC" + chain_domain.string = "gno.land" + +## tm2 +["gno.land/r/sys/params.tm2"] + +## misc +["gno.land/r/sys/params.mix"] + +## testing +# do not remove these lines. they are needed for a txtar integration test. +["gno.land/r/sys/params.test"] + foo.string = "bar" + foo.int64 = -1337 + foo.uint64 = 42 + foo.bool = true + #foo.bytes = todo From 9b8958af3341690d0ebbfbe9c6554487dfb2b184 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:12:18 -0500 Subject: [PATCH 43/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/gov/dao/prop3_filetest.gno | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/gno.land/r/gov/dao/prop3_filetest.gno b/examples/gno.land/r/gov/dao/prop3_filetest.gno index d797e337d26..bb00321dbe9 100644 --- a/examples/gno.land/r/gov/dao/prop3_filetest.gno +++ b/examples/gno.land/r/gov/dao/prop3_filetest.gno @@ -3,7 +3,6 @@ package main import ( "std" - "gno.land/r/gnoland/blog" govdao "gno.land/r/gov/dao" "gno.land/r/sys/params" ) From 888dfa96c073eb4ed2c9aeaaf2ccf2aa240951d0 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:24:06 -0500 Subject: [PATCH 44/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- tm2/pkg/sdk/params/keeper_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tm2/pkg/sdk/params/keeper_test.go b/tm2/pkg/sdk/params/keeper_test.go index 45a97ae44ad..832d16229ee 100644 --- a/tm2/pkg/sdk/params/keeper_test.go +++ b/tm2/pkg/sdk/params/keeper_test.go @@ -78,11 +78,11 @@ func TestKeeper(t *testing.T) { require.Equal(t, param5, []byte("bye")) // invalid sets - require.PanicsWithValue(t, `key should be like ".string"`, func() { keeper.SetString(ctx, "invalid.int64", "hello") }) - require.PanicsWithValue(t, `key should be like ".int64"`, func() { keeper.SetInt64(ctx, "invalid.string", int64(42)) }) - require.PanicsWithValue(t, `key should be like ".uint64"`, func() { keeper.SetUint64(ctx, "invalid.int64", uint64(42)) }) - require.PanicsWithValue(t, `key should be like ".bool"`, func() { keeper.SetBool(ctx, "invalid.int64", true) }) - require.PanicsWithValue(t, `key should be like ".bytes"`, func() { keeper.SetBytes(ctx, "invalid.int64", []byte("hello")) }) + require.PanicsWithValue(t, `key should be like ".string" (invalid.int64)`, func() { keeper.SetString(ctx, "invalid.int64", "hello") }) + require.PanicsWithValue(t, `key should be like ".int64" (invalid.string)`, func() { keeper.SetInt64(ctx, "invalid.string", int64(42)) }) + require.PanicsWithValue(t, `key should be like ".uint64" (invalid.int64)`, func() { keeper.SetUint64(ctx, "invalid.int64", uint64(42)) }) + require.PanicsWithValue(t, `key should be like ".bool" (invalid.int64)`, func() { keeper.SetBool(ctx, "invalid.int64", true) }) + require.PanicsWithValue(t, `key should be like ".bytes" (invalid.int64)`, func() { keeper.SetBytes(ctx, "invalid.int64", []byte("hello")) }) } // adapted from TestKeeperSubspace from Cosmos SDK, but adapted to a subspace-less Keeper. From fcafaed21e2cc340837b2072efabee65289008fd Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 24 Oct 2024 16:17:58 -0500 Subject: [PATCH 45/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoland/param.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/gno.land/pkg/gnoland/param.go b/gno.land/pkg/gnoland/param.go index 8ca97ad028f..eb3c5a1b00e 100644 --- a/gno.land/pkg/gnoland/param.go +++ b/gno.land/pkg/gnoland/param.go @@ -37,58 +37,59 @@ func (p *Param) Parse(entry string) error { } keyWithKind := parts[0] + rawValue := parts[1] p.kind = keyWithKind[strings.LastIndex(keyWithKind, ".")+1:] p.key = strings.TrimSuffix(keyWithKind, "."+p.kind) - raw := parts[1] switch p.kind { case ParamKindString: - p.value = raw + p.value = rawValue case ParamKindInt64: - v, err := strconv.ParseInt(raw, 10, 64) + v, err := strconv.ParseInt(rawValue, 10, 64) if err != nil { return err } p.value = v case ParamKindBool: - v, err := strconv.ParseBool(raw) + v, err := strconv.ParseBool(rawValue) if err != nil { return err } p.value = v case ParamKindUint64: - v, err := strconv.ParseUint(raw, 10, 64) + v, err := strconv.ParseUint(rawValue, 10, 64) if err != nil { return err } p.value = v case ParamKindBytes: - v, err := hex.DecodeString(raw) + v, err := hex.DecodeString(rawValue) if err != nil { return err } p.value = v default: - return errors.New("unsupported param kind: " + p.kind) + return errors.New("unsupported param kind: " + p.kind + " (" + entry + ")") } return p.Verify() } func (p Param) String() string { + typedKey := p.key + "." + p.kind switch p.kind { case ParamKindString: - return fmt.Sprintf("%s=%s", p.key, p.value) + return fmt.Sprintf("%s=%s", typedKey, p.value) case ParamKindInt64: - return fmt.Sprintf("%s=%d", p.key, p.value) + return fmt.Sprintf("%s=%d", typedKey, p.value) case ParamKindUint64: - return fmt.Sprintf("%s=%d", p.key, p.value) + return fmt.Sprintf("%s=%d", typedKey, p.value) case ParamKindBool: if p.value.(bool) { - return fmt.Sprintf("%s=true", p.key) + return fmt.Sprintf("%s=true", typedKey) } - return fmt.Sprintf("%s=false", p.key) + return fmt.Sprintf("%s=false", typedKey) case ParamKindBytes: - return fmt.Sprintf("%s=%x", p.key, p.value) + return fmt.Sprintf("%s=%x", typedKey, p.value) } panic("invalid param kind:" + p.kind) } From 21a3983252401cd203d31bdcd5af7120ad964ad5 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:36:25 -0500 Subject: [PATCH 46/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gnovm/tests/files/std12_stdlibs.gno | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 gnovm/tests/files/std12_stdlibs.gno diff --git a/gnovm/tests/files/std12_stdlibs.gno b/gnovm/tests/files/std12_stdlibs.gno new file mode 100644 index 00000000000..ca2ec7ed1d4 --- /dev/null +++ b/gnovm/tests/files/std12_stdlibs.gno @@ -0,0 +1,15 @@ +package main + +import "std" + +func main() { + std.SetParamString("foo.string", "hello") + std.SetParamInt64("bar.int64", 12345) + std.SetParamInt64("baz.uint64", -12345) + std.SetParamInt64("oof.bool", true) + std.SetParamInt64("rab.bytes", []byte("world")) + println("done") +} + +// Output: +// done From 6ab560e182109e74d06eddfc2d916326ff3c4aea Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 24 Oct 2024 18:09:36 -0500 Subject: [PATCH 47/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoland/app_test.go | 6 ++-- tm2/pkg/sdk/params/handler_test.go | 45 ++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/gno.land/pkg/gnoland/app_test.go b/gno.land/pkg/gnoland/app_test.go index c48d2b67d0c..25bf5fd5be5 100644 --- a/gno.land/pkg/gnoland/app_test.go +++ b/gno.land/pkg/gnoland/app_test.go @@ -100,9 +100,9 @@ func TestNewAppWithOptions(t *testing.T) { expectedVal string }{ {"params/vm/foo.string", `"hello"`}, - {"params/vm/bar.int64", `"-42"`}, + {"params/vm/foo.int64", `"-42"`}, {"params/vm/foo.uint64", `"1337"`}, - {"params/vm/bar.bool", `true`}, + {"params/vm/foo.bool", `true`}, {"params/vm/foo.bytes", `"SGkh"`}, // XXX: make this test more readable } for _, tc := range tcs { @@ -110,7 +110,7 @@ func TestNewAppWithOptions(t *testing.T) { Path: tc.path, }) require.True(t, qres.IsOK()) - require.Equal(t, qres.Data, []byte(tc.expectedVal)) + assert.Equal(t, qres.Data, []byte(tc.expectedVal)) } } diff --git a/tm2/pkg/sdk/params/handler_test.go b/tm2/pkg/sdk/params/handler_test.go index 1fff5d007d3..071eb12b52b 100644 --- a/tm2/pkg/sdk/params/handler_test.go +++ b/tm2/pkg/sdk/params/handler_test.go @@ -4,12 +4,12 @@ import ( "strings" "testing" - "github.com/stretchr/testify/require" - abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/sdk" tu "github.com/gnolang/gno/tm2/pkg/sdk/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestInvalidMsg(t *testing.T) { @@ -27,21 +27,42 @@ func TestQuery(t *testing.T) { env := setupTestEnv() h := NewHandler(env.keeper) - req := abci.RequestQuery{ - Path: "params/params_test/foo/bar.string", + tcs := []struct { + path string + expected string + }{ + {path: "params/params_test/foo/bar.string", expected: `"baz"`}, + {path: "params/params_test/foo/bar.int64", expected: `"-12345"`}, + {path: "params/params_test/foo/bar.uint64", expected: `"4242"`}, + {path: "params/params_test/foo/bar.bool", expected: "true"}, + {path: "params/params_test/foo/bar.bytes", expected: `"YmF6"`}, } - res := h.Query(env.ctx, req) - require.Nil(t, res.Error) - require.NotNil(t, res) - require.Nil(t, res.Data) + for _, tc := range tcs { + req := abci.RequestQuery{ + Path: tc.path, + } + res := h.Query(env.ctx, req) + require.Nil(t, res.Error) + require.NotNil(t, res) + require.Nil(t, res.Data) + } env.keeper.SetString(env.ctx, "foo/bar.string", "baz") + env.keeper.SetInt64(env.ctx, "foo/bar.int64", -12345) + env.keeper.SetUint64(env.ctx, "foo/bar.uint64", 4242) + env.keeper.SetBool(env.ctx, "foo/bar.bool", true) + env.keeper.SetBytes(env.ctx, "foo/bar.bytes", []byte("baz")) - res = h.Query(env.ctx, req) - require.Nil(t, res.Error) - require.NotNil(t, res) - require.Equal(t, string(res.Data), `"baz"`) + for _, tc := range tcs { + req := abci.RequestQuery{ + Path: tc.path, + } + res := h.Query(env.ctx, req) + require.Nil(t, res.Error) + require.NotNil(t, res) + assert.Equal(t, string(res.Data), tc.expected) + } } func TestQuerierRouteNotFound(t *testing.T) { From 1dc779bf5101969401dfce439a2809876681607f Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 25 Oct 2024 00:04:46 -0500 Subject: [PATCH 48/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/genesis/genesis_params.toml | 12 ++++++------ gno.land/pkg/sdk/vm/keeper.go | 18 +++++++++++------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/gno.land/genesis/genesis_params.toml b/gno.land/genesis/genesis_params.toml index 4021d1166a9..46c7ccb399d 100644 --- a/gno.land/genesis/genesis_params.toml +++ b/gno.land/genesis/genesis_params.toml @@ -1,17 +1,17 @@ ## gno.land ["gno.land/r/sys/params.sys"] - token_lock.bool = true users_pkgpath.string = "gno.land/r/sys/users" validators_pkgpath.string = "gno.land/r/sys/validators" rewards_pkgpath.string = "gno.land/r/sys/rewards" + enable_namespaces.bool = true + # token_lock.bool = true # TODO ## gnovm ["gno.land/r/sys/params.vm"] - namespaces.bool = true - max_gas.int64 = 10_000_000_000 - chain_tz.string = "UTC" - default_storage_allowance.string = "UTC" - chain_domain.string = "gno.land" + # max_gas.int64 = 100_000_000 # TODO + # chain_tz.string = "UTC" # TODO + # default_storage_allowance.string = "" # TODO + # chain_domain.string = "gno.land" # TODO ## tm2 ["gno.land/r/sys/params.tm2"] diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 4a4e66617d9..934af0264e7 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -225,15 +225,19 @@ 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.gnoland_sys_users_rlm.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 { - sysUsersPkg := sysUsersPkgDefault - vm.prmk.GetString(ctx, sysUsersPkgParamKey, &sysUsersPkg) + var isEnabled bool + vm.prmk.GetBool(ctx, "vm/gno.land/r/sys/params.enable_namespaces.bool", &isEnabled) + if !isEnabled { + return nil + } + + var sysUsersPkg string + vm.prmk.GetString(ctx, "vm/gno.land/r/sys/params.sys.users_pkgpath.string", &sysUsersPkg) + if sysUsersPkg == "" { // namespace support disabled + return nil + } store := vm.getGnoTransactionStore(ctx) From 5ddb4cbd3f81f0393860fba533995429ba2e8831 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 25 Oct 2024 00:14:38 -0500 Subject: [PATCH 49/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gnovm/tests/files/std12_stdlibs.gno | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gnovm/tests/files/std12_stdlibs.gno b/gnovm/tests/files/std12_stdlibs.gno index ca2ec7ed1d4..a06fd841f91 100644 --- a/gnovm/tests/files/std12_stdlibs.gno +++ b/gnovm/tests/files/std12_stdlibs.gno @@ -4,10 +4,10 @@ import "std" func main() { std.SetParamString("foo.string", "hello") - std.SetParamInt64("bar.int64", 12345) - std.SetParamInt64("baz.uint64", -12345) - std.SetParamInt64("oof.bool", true) - std.SetParamInt64("rab.bytes", []byte("world")) + std.SetParamInt64("bar.int64", -12345) + std.SetParamUint64("baz.uint64", 12345) + std.SetParamBool("oof.bool", true) + std.SetParamBytes("rab.bytes", []byte("world")) println("done") } From 4ebb76c61cb0a4b6877bafb8f7e4a477036c19e8 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 25 Oct 2024 07:40:20 -0500 Subject: [PATCH 50/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/integration/testing_integration.go | 1 + gno.land/pkg/integration/testing_node.go | 5 +++-- gno.land/pkg/sdk/vm/gas_test.go | 2 +- gno.land/pkg/sdk/vm/keeper.go | 7 +++++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index 0ba0c6c6bdf..c61b211228a 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -197,6 +197,7 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { cfg := TestingMinimalNodeConfig(t, gnoRootDir) genesis := ts.Value(envKeyGenesis).(*gnoland.GnoGenesisState) genesis.Txs = append(pkgsTxs, genesis.Txs...) + fmt.Printf("\n9999999999: %v\n", genesis.Params) // setup genesis state cfg.Genesis.AppState = *genesis diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go index 3f5807d8fae..128b8de1751 100644 --- a/gno.land/pkg/integration/testing_node.go +++ b/gno.land/pkg/integration/testing_node.go @@ -120,10 +120,11 @@ func DefaultTestingGenesisConfig(t TestingTS, gnoroot string, self crypto.PubKey Balances: []gnoland.Balance{ { Address: crypto.MustAddressFromString(DefaultAccount_Address), - Amount: std.MustParseCoins(ugnot.ValueString(10000000000000)), + Amount: std.MustParseCoins(ugnot.ValueString(10_000_000_000_000)), }, }, - Txs: []std.Tx{}, + Txs: []std.Tx{}, + Params: []gnoland.Param{}, }, } } diff --git a/gno.land/pkg/sdk/vm/gas_test.go b/gno.land/pkg/sdk/vm/gas_test.go index 53809a7f223..4171b1cdbc3 100644 --- a/gno.land/pkg/sdk/vm/gas_test.go +++ b/gno.land/pkg/sdk/vm/gas_test.go @@ -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(93825), gasDeliver) + assert.Equal(t, int64(92825), gasDeliver) } // Enough gas for a failed transaction. diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 934af0264e7..c0650f3797f 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -228,13 +228,16 @@ var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([\.~_a-zA-Z0-9]+)`) // 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 { var isEnabled bool - vm.prmk.GetBool(ctx, "vm/gno.land/r/sys/params.enable_namespaces.bool", &isEnabled) - if !isEnabled { + + vm.prmk.GetBool(ctx, "vm/gno.land/r/sys/params.sys.enable_namespaces.bool", &isEnabled) + println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", isEnabled) + if !isEnabled && false { return nil } var sysUsersPkg string vm.prmk.GetString(ctx, "vm/gno.land/r/sys/params.sys.users_pkgpath.string", &sysUsersPkg) + println("BBBBBBBBB", sysUsersPkg) if sysUsersPkg == "" { // namespace support disabled return nil } From 065842b527920a9dffa502aac696b8527183f8df Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:03:36 -0500 Subject: [PATCH 51/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/integration/testing_integration.go | 1 - gno.land/pkg/sdk/vm/keeper.go | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index c61b211228a..0ba0c6c6bdf 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -197,7 +197,6 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { cfg := TestingMinimalNodeConfig(t, gnoRootDir) genesis := ts.Value(envKeyGenesis).(*gnoland.GnoGenesisState) genesis.Txs = append(pkgsTxs, genesis.Txs...) - fmt.Printf("\n9999999999: %v\n", genesis.Params) // setup genesis state cfg.Genesis.AppState = *genesis diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index c0650f3797f..37dad631303 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -229,15 +229,13 @@ var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([\.~_a-zA-Z0-9]+)`) func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Address, pkgPath string) error { var isEnabled bool - vm.prmk.GetBool(ctx, "vm/gno.land/r/sys/params.sys.enable_namespaces.bool", &isEnabled) - println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", isEnabled) + vm.prmk.GetBool(ctx, "gno.land/r/sys/params.sys.enable_namespaces.bool", &isEnabled) if !isEnabled && false { return nil } var sysUsersPkg string - vm.prmk.GetString(ctx, "vm/gno.land/r/sys/params.sys.users_pkgpath.string", &sysUsersPkg) - println("BBBBBBBBB", sysUsersPkg) + vm.prmk.GetString(ctx, "gno.land/r/sys/params.sys.users_pkgpath.string", &sysUsersPkg) if sysUsersPkg == "" { // namespace support disabled return nil } From fc3d1493ce9cade78bb973b52ab9be2302daf2a4 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 25 Oct 2024 22:34:45 -0400 Subject: [PATCH 52/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/sdk/vm/gas_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gno.land/pkg/sdk/vm/gas_test.go b/gno.land/pkg/sdk/vm/gas_test.go index 4171b1cdbc3..53809a7f223 100644 --- a/gno.land/pkg/sdk/vm/gas_test.go +++ b/gno.land/pkg/sdk/vm/gas_test.go @@ -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. From 3ad7ffa0a9217845f808b85772089588ccd6ac55 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 25 Oct 2024 22:39:55 -0400 Subject: [PATCH 53/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/genesis/genesis_params.toml | 16 ++++++++-------- gno.land/pkg/sdk/vm/keeper.go | 9 +-------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/gno.land/genesis/genesis_params.toml b/gno.land/genesis/genesis_params.toml index 46c7ccb399d..d8604cb9a5f 100644 --- a/gno.land/genesis/genesis_params.toml +++ b/gno.land/genesis/genesis_params.toml @@ -1,17 +1,17 @@ ## gno.land ["gno.land/r/sys/params.sys"] - users_pkgpath.string = "gno.land/r/sys/users" + users_pkgpath.string = "gno.land/r/sys/users" # if empty, no namespace support. validators_pkgpath.string = "gno.land/r/sys/validators" - rewards_pkgpath.string = "gno.land/r/sys/rewards" - enable_namespaces.bool = true - # token_lock.bool = true # TODO + # TODO: rewards_pkgpath.string = "gno.land/r/sys/rewards" + # TODO: token_lock.bool = true ## gnovm ["gno.land/r/sys/params.vm"] - # max_gas.int64 = 100_000_000 # TODO - # chain_tz.string = "UTC" # TODO - # default_storage_allowance.string = "" # TODO - # chain_domain.string = "gno.land" # TODO + max_alloc_tx.uint64 = 500_000_000 + # TODO: chain_domain.string = "gno.land" + # TODO: max_gas.int64 = 100_000_000 + # TODO: chain_tz.string = "UTC" + # TODO: default_storage_allowance.string = "" ## tm2 ["gno.land/r/sys/params.tm2"] diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 37dad631303..b3d10361ed7 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -227,16 +227,9 @@ var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([\.~_a-zA-Z0-9]+)`) // 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 { - var isEnabled bool - - vm.prmk.GetBool(ctx, "gno.land/r/sys/params.sys.enable_namespaces.bool", &isEnabled) - if !isEnabled && false { - return nil - } - var sysUsersPkg string vm.prmk.GetString(ctx, "gno.land/r/sys/params.sys.users_pkgpath.string", &sysUsersPkg) - if sysUsersPkg == "" { // namespace support disabled + if sysUsersPkg == "" { return nil } From 2eea8674b61002d5a32eb5db51c101be44374c5c Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 25 Oct 2024 22:49:28 -0400 Subject: [PATCH 54/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/genesis/genesis_params.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gno.land/genesis/genesis_params.toml b/gno.land/genesis/genesis_params.toml index d8604cb9a5f..2f210a87df1 100644 --- a/gno.land/genesis/genesis_params.toml +++ b/gno.land/genesis/genesis_params.toml @@ -1,13 +1,13 @@ + ## gno.land ["gno.land/r/sys/params.sys"] users_pkgpath.string = "gno.land/r/sys/users" # if empty, no namespace support. - validators_pkgpath.string = "gno.land/r/sys/validators" + # TODO: validators_pkgpath.string = "gno.land/r/sys/validators" # TODO: rewards_pkgpath.string = "gno.land/r/sys/rewards" # TODO: token_lock.bool = true ## gnovm ["gno.land/r/sys/params.vm"] - max_alloc_tx.uint64 = 500_000_000 # TODO: chain_domain.string = "gno.land" # TODO: max_gas.int64 = 100_000_000 # TODO: chain_tz.string = "UTC" From ae0bd03118abfffda1b2f43ca350dae6ffd9d1a2 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 25 Oct 2024 22:52:31 -0400 Subject: [PATCH 55/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/genesis/genesis_params.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gno.land/genesis/genesis_params.toml b/gno.land/genesis/genesis_params.toml index 2f210a87df1..5f4d9c5015c 100644 --- a/gno.land/genesis/genesis_params.toml +++ b/gno.land/genesis/genesis_params.toml @@ -17,7 +17,7 @@ ["gno.land/r/sys/params.tm2"] ## misc -["gno.land/r/sys/params.mix"] +["gno.land/r/sys/params.misc"] ## testing # do not remove these lines. they are needed for a txtar integration test. From cef75f659e4cd40d2fb5254cbd264b208dd05b46 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 26 Oct 2024 14:23:42 +0200 Subject: [PATCH 56/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/sdk/vm/gas_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gno.land/pkg/sdk/vm/gas_test.go b/gno.land/pkg/sdk/vm/gas_test.go index 53809a7f223..4171b1cdbc3 100644 --- a/gno.land/pkg/sdk/vm/gas_test.go +++ b/gno.land/pkg/sdk/vm/gas_test.go @@ -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(93825), gasDeliver) + assert.Equal(t, int64(92825), gasDeliver) } // Enough gas for a failed transaction. From 12f01407618b7327903ffc2a39fe254822ddd81f Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 31 Oct 2024 11:47:02 +0100 Subject: [PATCH 57/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../gno.land/r/gov/dao/prop3_filetest.gno | 95 --------------- .../gno.land/r/gov/dao/v2/prop4_filetest.gno | 112 ++++++++++++++++++ examples/gno.land/r/sys/params/params.gno | 26 ++-- 3 files changed, 122 insertions(+), 111 deletions(-) delete mode 100644 examples/gno.land/r/gov/dao/prop3_filetest.gno create mode 100644 examples/gno.land/r/gov/dao/v2/prop4_filetest.gno diff --git a/examples/gno.land/r/gov/dao/prop3_filetest.gno b/examples/gno.land/r/gov/dao/prop3_filetest.gno deleted file mode 100644 index bb00321dbe9..00000000000 --- a/examples/gno.land/r/gov/dao/prop3_filetest.gno +++ /dev/null @@ -1,95 +0,0 @@ -package main - -import ( - "std" - - govdao "gno.land/r/gov/dao" - "gno.land/r/sys/params" -) - -func init() { - { // prop0 - membersFn := func() []std.Address { - return []std.Address{ - std.Address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - } - } - mExec := govdao.NewPropExecutor(membersFn) - comment := "adding someone to vote" - id := govdao.Propose(comment, mExec) - govdao.ExecuteProposal(id) - } - - { // prop1 - mExec := params.NewStringPropExecutor("prop1.string", "value1") - comment := "setting prop1.string param" - id := govdao.Propose(comment, mExec) - } - - { // prop2 - mExec := params.NewInt64PropExecutor("prop2.int64", 12345) - comment := "setting prop2.int64 param" - id := govdao.Propose(comment, mExec) - } -} - -func main() { - println("--") - println(govdao.Render("")) - println("--") - println(govdao.Render("1")) - println("--") - govdao.VoteOnProposal(1, "YES") - println("--") - println(govdao.Render("1")) - println("--") - govdao.ExecuteProposal(1) - println("--") - println(govdao.Render("1")) -} - -// Events: -// [{"type":"set","attrs":[{"key":"k","value":"prop1.string"}],"pkg_path":"gno.land/r/sys/params","func":""}] - -// Output: -// -- -// - [0](/r/gov/dao:0) - adding someone to vote (**succeeded**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) -// - [1](/r/gov/dao:1) - setting prop1.string param (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) -// - [2](/r/gov/dao:2) - setting prop2.int64 param (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) -// -// -- -// # Prop #1 -// -// setting prop1.string param -// -// Status: active -// -// Voting status: YES: 0, NO: 0, percent: 0, members: 1 -// -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// -// -// -- -// -- -// # Prop #1 -// -// setting prop1.string param -// -// Status: accepted -// -// Voting status: YES: 1, NO: 0, percent: 100, members: 1 -// -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// -// -// -- -// -- -// # Prop #1 -// -// setting prop1.string param -// -// Status: succeeded -// -// Voting status: YES: 1, NO: 0, percent: 100, members: 1 -// -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm diff --git a/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno b/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno new file mode 100644 index 00000000000..6769871a0ce --- /dev/null +++ b/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno @@ -0,0 +1,112 @@ +package main + +import ( + "gno.land/p/demo/dao" + "gno.land/r/gov/dao/bridge" + govdaov2 "gno.land/r/gov/dao/v2" + "gno.land/r/sys/params" +) + +func init() { + /*{ // prop0 + membersFn := func() []std.Address { + return []std.Address{ + std.Address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), + } + } + mExec := bridge.GovDAO().NewMemberPropExecutor(membersFn) + comment := "adding someone to vote" + id := bridge.GovDAO().Propose(comment, mExec) + bridge.GovDAO().ExecuteProposal(id) + }*/ + + { // prop0 + mExec := params.NewStringPropExecutor("prop1.string", "value1") + comment := "setting prop1.string param" + prop := dao.ProposalRequest{ + Description: comment, + Executor: mExec, + } + id := bridge.GovDAO().Propose(prop) + println("new prop", id) + } + + { // prop1 + mExec := params.NewInt64PropExecutor("prop2.int64", 12345) + comment := "setting prop2.int64 param" + prop := dao.ProposalRequest{ + Description: comment, + Executor: mExec, + } + id := bridge.GovDAO().Propose(prop) + println("new prop", id) + } +} + +func main() { + println("--") + println(govdaov2.Render("")) + println("--") + println(govdaov2.Render("1")) + println("--") + bridge.GovDAO().VoteOnProposal(1, "YES") + println("--") + println(govdaov2.Render("1")) + println("--") + bridge.GovDAO().ExecuteProposal(1) + println("--") + println(govdaov2.Render("1")) +} + +// Events: +// [{"type":"ProposalAdded","attrs":[{"key":"proposal-id","value":"0"},{"key":"proposal-author","value":"g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"}],"pkg_path":"gno.land/r/gov/dao/v2","func":"EmitProposalAdded"},{"type":"ProposalAdded","attrs":[{"key":"proposal-id","value":"1"},{"key":"proposal-author","value":"g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"}],"pkg_path":"gno.land/r/gov/dao/v2","func":"EmitProposalAdded"},{"type":"VoteAdded","attrs":[{"key":"proposal-id","value":"1"},{"key":"author","value":"g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"},{"key":"option","value":"YES"}],"pkg_path":"gno.land/r/gov/dao/v2","func":"EmitVoteAdded"},{"type":"ProposalAccepted","attrs":[{"key":"proposal-id","value":"1"}],"pkg_path":"gno.land/r/gov/dao/v2","func":"EmitProposalAccepted"},{"type":"set","attrs":[{"key":"k","value":"prop2.int64"}],"pkg_path":"gno.land/r/sys/params","func":""},{"type":"ProposalExecuted","attrs":[{"key":"proposal-id","value":"1"},{"key":"exec-status","value":"accepted"}],"pkg_path":"gno.land/r/gov/dao/v2","func":"ExecuteProposal"}] + +// Output: +// new prop 0 +// new prop 1 +// -- +// - [Proposal #0](/r/gov/dao/v2:0) - (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// - [Proposal #1](/r/gov/dao/v2:1) - (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// +// -- +// # Prop #1 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// setting prop2.int64 param +// +// Status: active +// +// Voting stats: YAY 0 (0%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 10 (100%) +// +// Threshold met: false +// +// +// -- +// -- +// # Prop #1 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// setting prop2.int64 param +// +// Status: accepted +// +// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) +// +// Threshold met: true +// +// +// -- +// -- +// # Prop #1 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// setting prop2.int64 param +// +// Status: execution successful +// +// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) +// +// Threshold met: true diff --git a/examples/gno.land/r/sys/params/params.gno b/examples/gno.land/r/sys/params/params.gno index 676f23f0193..91236ce4827 100644 --- a/examples/gno.land/r/sys/params/params.gno +++ b/examples/gno.land/r/sys/params/params.gno @@ -3,41 +3,35 @@ package params import ( "std" - "gno.land/p/gov/proposal" + "gno.land/p/demo/dao" + "gno.land/r/gov/dao/bridge" ) -const daoPkgPath = "gno.land/r/gov/dao" - -func NewStringPropExecutor(key string, value string) proposal.Executor { +func NewStringPropExecutor(key string, value string) dao.Executor { return newPropExecutor(key, func() { std.SetParamString(key, value) }) } -func NewInt64PropExecutor(key string, value int64) proposal.Executor { +func NewInt64PropExecutor(key string, value int64) dao.Executor { return newPropExecutor(key, func() { std.SetParamInt64(key, value) }) } -func NewUint64PropExecutor(key string, value uint64) proposal.Executor { +func NewUint64PropExecutor(key string, value uint64) dao.Executor { return newPropExecutor(key, func() { std.SetParamUint64(key, value) }) } -func NewBoolPropExecutor(key string, value bool) proposal.Executor { +func NewBoolPropExecutor(key string, value bool) dao.Executor { return newPropExecutor(key, func() { std.SetParamBool(key, value) }) } -func NewBytesPropExecutor(key string, value []byte) proposal.Executor { +func NewBytesPropExecutor(key string, value []byte) dao.Executor { return newPropExecutor(key, func() { std.SetParamBytes(key, value) }) } -func newPropExecutor(key string, fn func()) proposal.Executor { +func newPropExecutor(key string, fn func()) dao.Executor { callback := func() error { - if std.PrevRealm().PkgPath() != daoPkgPath { - panic("should be executed from govdao") - } - std.Emit("set", - "k", key, - ) fn() + std.Emit("set", "k", key) return nil } - return proposal.NewExecutor(callback) + return bridge.GovDAO().NewGovDAOExecutor(callback) } From ac774bdd8dea239b5c921c2241bb1724f1bc8f5e Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 31 Oct 2024 11:50:33 +0100 Subject: [PATCH 58/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/sys/params/gno.mod | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/gno.land/r/sys/params/gno.mod b/examples/gno.land/r/sys/params/gno.mod index f23f3871054..4b4c2bf790f 100644 --- a/examples/gno.land/r/sys/params/gno.mod +++ b/examples/gno.land/r/sys/params/gno.mod @@ -1,3 +1,6 @@ module gno.land/r/sys/params -require gno.land/p/gov/proposal v0.0.0-latest +require ( + gno.land/p/demo/dao v0.0.0-latest + gno.land/r/gov/dao/bridge v0.0.0-latest +) From f70a2e00a0b768f67857860d76ba502f059c6a4f Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:00:12 +0100 Subject: [PATCH 59/69] chore(gno): intended json on filetests's Events: directives Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../gno.land/r/demo/event/z1_filetest.gno | 25 ++++++++++++++++++- .../testdata/gno_test/filetest_events.txtar | 20 ++++++++++++++- gnovm/tests/file.go | 2 +- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/r/demo/event/z1_filetest.gno b/examples/gno.land/r/demo/event/z1_filetest.gno index 1fcfa1a0e4f..b138aa4351c 100644 --- a/examples/gno.land/r/demo/event/z1_filetest.gno +++ b/examples/gno.land/r/demo/event/z1_filetest.gno @@ -8,4 +8,27 @@ func main() { } // Events: -// [{"type":"TAG","attrs":[{"key":"key","value":"foo"}],"pkg_path":"gno.land/r/demo/event","func":"Emit"},{"type":"TAG","attrs":[{"key":"key","value":"bar"}],"pkg_path":"gno.land/r/demo/event","func":"Emit"}] +// [ +// { +// "type": "TAG", +// "attrs": [ +// { +// "key": "key", +// "value": "foo" +// } +// ], +// "pkg_path": "gno.land/r/demo/event", +// "func": "Emit" +// }, +// { +// "type": "TAG", +// "attrs": [ +// { +// "key": "key", +// "value": "bar" +// } +// ], +// "pkg_path": "gno.land/r/demo/event", +// "func": "Emit" +// } +// ] diff --git a/gnovm/cmd/gno/testdata/gno_test/filetest_events.txtar b/gnovm/cmd/gno/testdata/gno_test/filetest_events.txtar index 5e0520a2e85..0236872e78a 100644 --- a/gnovm/cmd/gno/testdata/gno_test/filetest_events.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/filetest_events.txtar @@ -30,4 +30,22 @@ func main() { // test // Events: -// [{"type":"EventA","attrs":[],"pkg_path":"","func":"main"},{"type":"EventB","attrs":[{"key":"keyA","value":"valA"}],"pkg_path":"","func":"main"}] +// [ +// { +// "type": "EventA", +// "attrs": [], +// "pkg_path": "", +// "func": "main" +// }, +// { +// "type": "EventB", +// "attrs": [ +// { +// "key": "keyA", +// "value": "valA" +// } +// ], +// "pkg_path": "", +// "func": "main" +// } +// ] diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index 9df982d4fd8..98e54114af9 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -374,7 +374,7 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { } // check result events := m.Context.(*teststd.TestExecContext).EventLogger.Events() - evtjson, err := json.Marshal(events) + evtjson, err := json.MarshalIndent(events, "", " ") if err != nil { panic(err) } From f9c6d0c0c93126852e4abc8edfcb98a77b2142df Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:01:45 +0100 Subject: [PATCH 60/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../gno.land/r/gov/dao/v2/prop4_filetest.gno | 89 ++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno b/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno index 6769871a0ce..9bbb2ee376d 100644 --- a/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno +++ b/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno @@ -59,7 +59,94 @@ func main() { } // Events: -// [{"type":"ProposalAdded","attrs":[{"key":"proposal-id","value":"0"},{"key":"proposal-author","value":"g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"}],"pkg_path":"gno.land/r/gov/dao/v2","func":"EmitProposalAdded"},{"type":"ProposalAdded","attrs":[{"key":"proposal-id","value":"1"},{"key":"proposal-author","value":"g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"}],"pkg_path":"gno.land/r/gov/dao/v2","func":"EmitProposalAdded"},{"type":"VoteAdded","attrs":[{"key":"proposal-id","value":"1"},{"key":"author","value":"g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"},{"key":"option","value":"YES"}],"pkg_path":"gno.land/r/gov/dao/v2","func":"EmitVoteAdded"},{"type":"ProposalAccepted","attrs":[{"key":"proposal-id","value":"1"}],"pkg_path":"gno.land/r/gov/dao/v2","func":"EmitProposalAccepted"},{"type":"set","attrs":[{"key":"k","value":"prop2.int64"}],"pkg_path":"gno.land/r/sys/params","func":""},{"type":"ProposalExecuted","attrs":[{"key":"proposal-id","value":"1"},{"key":"exec-status","value":"accepted"}],"pkg_path":"gno.land/r/gov/dao/v2","func":"ExecuteProposal"}] +// [ +// { +// "type": "ProposalAdded", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// }, +// { +// "key": "proposal-author", +// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitProposalAdded" +// }, +// { +// "type": "ProposalAdded", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "1" +// }, +// { +// "key": "proposal-author", +// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitProposalAdded" +// }, +// { +// "type": "VoteAdded", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "1" +// }, +// { +// "key": "author", +// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" +// }, +// { +// "key": "option", +// "value": "YES" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitVoteAdded" +// }, +// { +// "type": "ProposalAccepted", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "1" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitProposalAccepted" +// }, +// { +// "type": "set", +// "attrs": [ +// { +// "key": "k", +// "value": "prop2.int64" +// } +// ], +// "pkg_path": "gno.land/r/sys/params", +// "func": "" +// }, +// { +// "type": "ProposalExecuted", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "1" +// }, +// { +// "key": "exec-status", +// "value": "accepted" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "ExecuteProposal" +// } +// ] // Output: // new prop 0 From d31d255628903e66d45237437fd6df5063b20172 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:03:16 +0100 Subject: [PATCH 61/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../gno.land/r/gov/dao/v2/prop1_filetest.gno | 82 ++++++++++++++ .../gno.land/r/gov/dao/v2/prop2_filetest.gno | 64 +++++++++++ .../gno.land/r/gov/dao/v2/prop3_filetest.gno | 64 +++++++++++ .../gno.land/r/gov/dao/v2/prop4_filetest.gno | 100 +++++++++--------- 4 files changed, 260 insertions(+), 50 deletions(-) diff --git a/examples/gno.land/r/gov/dao/v2/prop1_filetest.gno b/examples/gno.land/r/gov/dao/v2/prop1_filetest.gno index 69e55ef1ab6..17324c7395d 100644 --- a/examples/gno.land/r/gov/dao/v2/prop1_filetest.gno +++ b/examples/gno.land/r/gov/dao/v2/prop1_filetest.gno @@ -126,3 +126,85 @@ func main() { // - #123: g12345678 (10) // - #123: g000000000 (10) // - #123: g000000000 (0) + +// Events: +// [ +// { +// "type": "ProposalAdded", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// }, +// { +// "key": "proposal-author", +// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitProposalAdded" +// }, +// { +// "type": "VoteAdded", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// }, +// { +// "key": "author", +// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" +// }, +// { +// "key": "option", +// "value": "YES" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitVoteAdded" +// }, +// { +// "type": "ProposalAccepted", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitProposalAccepted" +// }, +// { +// "type": "ValidatorAdded", +// "attrs": [], +// "pkg_path": "gno.land/r/sys/validators/v2", +// "func": "addValidator" +// }, +// { +// "type": "ValidatorAdded", +// "attrs": [], +// "pkg_path": "gno.land/r/sys/validators/v2", +// "func": "addValidator" +// }, +// { +// "type": "ValidatorRemoved", +// "attrs": [], +// "pkg_path": "gno.land/r/sys/validators/v2", +// "func": "removeValidator" +// }, +// { +// "type": "ProposalExecuted", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// }, +// { +// "key": "exec-status", +// "value": "accepted" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "ExecuteProposal" +// } +// ] diff --git a/examples/gno.land/r/gov/dao/v2/prop2_filetest.gno b/examples/gno.land/r/gov/dao/v2/prop2_filetest.gno index 32ddc11b67c..aebf5f2362d 100644 --- a/examples/gno.land/r/gov/dao/v2/prop2_filetest.gno +++ b/examples/gno.land/r/gov/dao/v2/prop2_filetest.gno @@ -108,3 +108,67 @@ func main() { // ### [Hello from GovDAO!](/r/gnoland/blog:p/hello-from-govdao) // 13 Feb 2009 // + +// Events: +// [ +// { +// "type": "ProposalAdded", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// }, +// { +// "key": "proposal-author", +// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitProposalAdded" +// }, +// { +// "type": "VoteAdded", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// }, +// { +// "key": "author", +// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" +// }, +// { +// "key": "option", +// "value": "YES" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitVoteAdded" +// }, +// { +// "type": "ProposalAccepted", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitProposalAccepted" +// }, +// { +// "type": "ProposalExecuted", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// }, +// { +// "key": "exec-status", +// "value": "accepted" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "ExecuteProposal" +// } +// ] diff --git a/examples/gno.land/r/gov/dao/v2/prop3_filetest.gno b/examples/gno.land/r/gov/dao/v2/prop3_filetest.gno index 5aa9947c74b..d7348253f92 100644 --- a/examples/gno.land/r/gov/dao/v2/prop3_filetest.gno +++ b/examples/gno.land/r/gov/dao/v2/prop3_filetest.gno @@ -118,3 +118,67 @@ func main() { // // -- // 4 + +// Events: +// [ +// { +// "type": "ProposalAdded", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// }, +// { +// "key": "proposal-author", +// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitProposalAdded" +// }, +// { +// "type": "VoteAdded", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// }, +// { +// "key": "author", +// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" +// }, +// { +// "key": "option", +// "value": "YES" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitVoteAdded" +// }, +// { +// "type": "ProposalAccepted", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "EmitProposalAccepted" +// }, +// { +// "type": "ProposalExecuted", +// "attrs": [ +// { +// "key": "proposal-id", +// "value": "0" +// }, +// { +// "key": "exec-status", +// "value": "accepted" +// } +// ], +// "pkg_path": "gno.land/r/gov/dao/v2", +// "func": "ExecuteProposal" +// } +// ] diff --git a/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno b/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno index 9bbb2ee376d..542d180aa15 100644 --- a/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno +++ b/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno @@ -58,6 +58,56 @@ func main() { println(govdaov2.Render("1")) } +// Output: +// new prop 0 +// new prop 1 +// -- +// - [Proposal #0](/r/gov/dao/v2:0) - (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// - [Proposal #1](/r/gov/dao/v2:1) - (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// +// -- +// # Prop #1 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// setting prop2.int64 param +// +// Status: active +// +// Voting stats: YAY 0 (0%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 10 (100%) +// +// Threshold met: false +// +// +// -- +// -- +// # Prop #1 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// setting prop2.int64 param +// +// Status: accepted +// +// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) +// +// Threshold met: true +// +// +// -- +// -- +// # Prop #1 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// setting prop2.int64 param +// +// Status: execution successful +// +// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) +// +// Threshold met: true + // Events: // [ // { @@ -147,53 +197,3 @@ func main() { // "func": "ExecuteProposal" // } // ] - -// Output: -// new prop 0 -// new prop 1 -// -- -// - [Proposal #0](/r/gov/dao/v2:0) - (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) -// - [Proposal #1](/r/gov/dao/v2:1) - (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) -// -// -- -// # Prop #1 -// -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// -// setting prop2.int64 param -// -// Status: active -// -// Voting stats: YAY 0 (0%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 10 (100%) -// -// Threshold met: false -// -// -// -- -// -- -// # Prop #1 -// -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// -// setting prop2.int64 param -// -// Status: accepted -// -// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) -// -// Threshold met: true -// -// -// -- -// -- -// # Prop #1 -// -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// -// setting prop2.int64 param -// -// Status: execution successful -// -// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) -// -// Threshold met: true From 9ce3bd41daf2b754c569931d912373f20fcf52b0 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 8 Nov 2024 21:06:16 +0100 Subject: [PATCH 62/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/gov/dao/v2/dao.gno | 16 ++-- .../gno.land/r/gov/dao/v2/prop3_filetest.gno | 3 +- .../gno.land/r/gov/dao/v2/prop4_filetest.gno | 92 +++++-------------- 3 files changed, 34 insertions(+), 77 deletions(-) diff --git a/examples/gno.land/r/gov/dao/v2/dao.gno b/examples/gno.land/r/gov/dao/v2/dao.gno index c37eda80bff..d99a161bcdf 100644 --- a/examples/gno.land/r/gov/dao/v2/dao.gno +++ b/examples/gno.land/r/gov/dao/v2/dao.gno @@ -16,15 +16,13 @@ var ( ) func init() { - var ( - // Example initial member set (just test addresses) - set = []membstore.Member{ - { - Address: std.Address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - VotingPower: 10, - }, - } - ) + // Example initial member set (just test addresses) + set := []membstore.Member{ + { + Address: std.Address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), + VotingPower: 10, + }, + } // Set the member store members = membstore.NewMembStore(membstore.WithInitialMembers(set)) diff --git a/examples/gno.land/r/gov/dao/v2/prop3_filetest.gno b/examples/gno.land/r/gov/dao/v2/prop3_filetest.gno index 2f1ee6fa368..546213431e4 100644 --- a/examples/gno.land/r/gov/dao/v2/prop3_filetest.gno +++ b/examples/gno.land/r/gov/dao/v2/prop3_filetest.gno @@ -5,6 +5,7 @@ import ( "gno.land/p/demo/dao" "gno.land/p/demo/membstore" + "gno.land/r/gov/dao/bridge" govdao "gno.land/r/gov/dao/v2" ) @@ -34,7 +35,7 @@ func init() { Executor: govdao.NewMemberPropExecutor(memberFn), } - govdao.Propose(prop) + bridge.GovDAO().Propose(prop) } func main() { diff --git a/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno b/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno index 542d180aa15..c90e76727da 100644 --- a/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno +++ b/examples/gno.land/r/gov/dao/v2/prop4_filetest.gno @@ -8,103 +8,76 @@ import ( ) func init() { - /*{ // prop0 - membersFn := func() []std.Address { - return []std.Address{ - std.Address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - } - } - mExec := bridge.GovDAO().NewMemberPropExecutor(membersFn) - comment := "adding someone to vote" - id := bridge.GovDAO().Propose(comment, mExec) - bridge.GovDAO().ExecuteProposal(id) - }*/ - - { // prop0 - mExec := params.NewStringPropExecutor("prop1.string", "value1") - comment := "setting prop1.string param" - prop := dao.ProposalRequest{ - Description: comment, - Executor: mExec, - } - id := bridge.GovDAO().Propose(prop) - println("new prop", id) - } - - { // prop1 - mExec := params.NewInt64PropExecutor("prop2.int64", 12345) - comment := "setting prop2.int64 param" - prop := dao.ProposalRequest{ - Description: comment, - Executor: mExec, - } - id := bridge.GovDAO().Propose(prop) - println("new prop", id) + mExec := params.NewStringPropExecutor("prop1.string", "value1") + comment := "setting prop1.string param" + prop := dao.ProposalRequest{ + Description: comment, + Executor: mExec, } + id := bridge.GovDAO().Propose(prop) + println("new prop", id) } func main() { println("--") println(govdaov2.Render("")) println("--") - println(govdaov2.Render("1")) + println(govdaov2.Render("0")) println("--") - bridge.GovDAO().VoteOnProposal(1, "YES") + bridge.GovDAO().VoteOnProposal(0, "YES") println("--") - println(govdaov2.Render("1")) + println(govdaov2.Render("0")) println("--") - bridge.GovDAO().ExecuteProposal(1) + bridge.GovDAO().ExecuteProposal(0) println("--") - println(govdaov2.Render("1")) + println(govdaov2.Render("0")) } // Output: // new prop 0 -// new prop 1 // -- // - [Proposal #0](/r/gov/dao/v2:0) - (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) -// - [Proposal #1](/r/gov/dao/v2:1) - (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) // // -- -// # Prop #1 +// # Prop #0 // // Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm // -// setting prop2.int64 param +// setting prop1.string param // // Status: active // -// Voting stats: YAY 0 (0%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 10 (100%) +// Voting stats: YES 0 (0%), NO 0 (0%), ABSTAIN 0 (0%), MISSING VOTE 10 (100%) // // Threshold met: false // // // -- // -- -// # Prop #1 +// # Prop #0 // // Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm // -// setting prop2.int64 param +// setting prop1.string param // // Status: accepted // -// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) +// Voting stats: YES 10 (100%), NO 0 (0%), ABSTAIN 0 (0%), MISSING VOTE 0 (0%) // // Threshold met: true // // // -- // -- -// # Prop #1 +// # Prop #0 // // Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm // -// setting prop2.int64 param +// setting prop1.string param // // Status: execution successful // -// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) +// Voting stats: YES 10 (100%), NO 0 (0%), ABSTAIN 0 (0%), MISSING VOTE 0 (0%) // // Threshold met: true @@ -126,26 +99,11 @@ func main() { // "func": "EmitProposalAdded" // }, // { -// "type": "ProposalAdded", -// "attrs": [ -// { -// "key": "proposal-id", -// "value": "1" -// }, -// { -// "key": "proposal-author", -// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" -// } -// ], -// "pkg_path": "gno.land/r/gov/dao/v2", -// "func": "EmitProposalAdded" -// }, -// { // "type": "VoteAdded", // "attrs": [ // { // "key": "proposal-id", -// "value": "1" +// "value": "0" // }, // { // "key": "author", @@ -164,7 +122,7 @@ func main() { // "attrs": [ // { // "key": "proposal-id", -// "value": "1" +// "value": "0" // } // ], // "pkg_path": "gno.land/r/gov/dao/v2", @@ -175,7 +133,7 @@ func main() { // "attrs": [ // { // "key": "k", -// "value": "prop2.int64" +// "value": "prop1.string" // } // ], // "pkg_path": "gno.land/r/sys/params", @@ -186,7 +144,7 @@ func main() { // "attrs": [ // { // "key": "proposal-id", -// "value": "1" +// "value": "0" // }, // { // "key": "exec-status", From 187d1e50e9566679065a13c0fca734120037b164 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:14:55 +0100 Subject: [PATCH 63/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoland/genesis.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go index 0e411af01dc..ea692bcaf0d 100644 --- a/gno.land/pkg/gnoland/genesis.go +++ b/gno.land/pkg/gnoland/genesis.go @@ -19,7 +19,10 @@ import ( // LoadGenesisBalancesFile loads genesis balances from the provided file path. func LoadGenesisBalancesFile(path string) ([]Balance, error) { // each balance is in the form: g1xxxxxxxxxxxxxxxx=100000ugnot - content := osm.MustReadFile(path) + content, err := osm.ReadFile(path) + if err != nil { + return nil, err + } lines := strings.Split(string(content), "\n") balances := make([]Balance, 0, len(lines)) @@ -62,10 +65,13 @@ func LoadGenesisBalancesFile(path string) ([]Balance, error) { // LoadGenesisParamsFile loads genesis params from the provided file path. func LoadGenesisParamsFile(path string) ([]Param, error) { // each param is in the form: key.kind=value - content := osm.MustReadFile(path) + content, err := osm.ReadFile(path) + if err != nil { + return nil, err + } m := map[string] /*category*/ map[string] /*key*/ map[string] /*kind*/ interface{} /*value*/ {} - err := toml.Unmarshal(content, &m) + err = toml.Unmarshal(content, &m) if err != nil { return nil, err } @@ -100,7 +106,10 @@ func LoadGenesisParamsFile(path string) ([]Param, error) { func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]TxWithMetadata, error) { txs := make([]TxWithMetadata, 0) - txsBz := osm.MustReadFile(path) + txsBz, err := osm.ReadFile(path) + if err != nil { + return nil, err + } txsLines := strings.Split(string(txsBz), "\n") for _, txLine := range txsLines { if txLine == "" { From 0a3ea0e77eea02943474ae828964795bda72cad5 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:25:18 +0100 Subject: [PATCH 64/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/sdk/vm/keeper.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index b9f0b0b0fd5..5fa2075b8f7 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -228,10 +228,12 @@ 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 sysUsersPkgParamPath = "gno.land/r/sys/params.sys.users_pkgpath.string" + // 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 { var sysUsersPkg string - vm.prmk.GetString(ctx, "gno.land/r/sys/params.sys.users_pkgpath.string", &sysUsersPkg) + vm.prmk.GetString(ctx, sysUsersPkgParamPath, &sysUsersPkg) if sysUsersPkg == "" { return nil } From 23f8ce2acf5b17dafce306ff78ec69b66d6de160 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:46:12 +0100 Subject: [PATCH 65/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gnovm/tests/file.go | 1 - 1 file changed, 1 deletion(-) diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index 960a829569b..98dbab6ac0e 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -642,7 +642,6 @@ func newTestParams() *testParams { return &testParams{} } -// XXX: not noop? func (tp *testParams) SetBool(key string, val bool) { /* noop */ } func (tp *testParams) SetBytes(key string, val []byte) { /* noop */ } func (tp *testParams) SetInt64(key string, val int64) { /* noop */ } From 81a3f5651b2e29429cdf5cb0455d4f83f0e99221 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:47:15 +0100 Subject: [PATCH 66/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoland/param_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gno.land/pkg/gnoland/param_test.go b/gno.land/pkg/gnoland/param_test.go index 3c072ff5c8d..5d17aab40da 100644 --- a/gno.land/pkg/gnoland/param_test.go +++ b/gno.land/pkg/gnoland/param_test.go @@ -7,6 +7,7 @@ import ( ) func TestParam_Parse(t *testing.T) { + t.Parallel() tests := []struct { name string entry string @@ -26,6 +27,7 @@ func TestParam_Parse(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { + t.Parallel() param := Param{} err := param.Parse(tc.entry) if tc.expectErr { From 6c473666a637bef004dddff6b078352ad7c72c68 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:49:36 +0100 Subject: [PATCH 67/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoland/app.go | 2 +- gno.land/pkg/gnoland/param.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index f7095834f8c..e0c93f6194f 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -306,7 +306,7 @@ func (cfg InitChainerConfig) loadAppState(ctx sdk.Context, appState any) ([]abci // Apply genesis params. for _, param := range state.Params { - param.Register(ctx, cfg.paramsKpr) + param.register(ctx, cfg.paramsKpr) } // Replay genesis txs. diff --git a/gno.land/pkg/gnoland/param.go b/gno.land/pkg/gnoland/param.go index eb3c5a1b00e..4c1e1190751 100644 --- a/gno.land/pkg/gnoland/param.go +++ b/gno.land/pkg/gnoland/param.go @@ -102,7 +102,7 @@ func (p Param) MarshalAmino() (string, error) { return p.String(), nil } -func (p Param) Register(ctx sdk.Context, prk params.ParamsKeeperI) { +func (p Param) register(ctx sdk.Context, prk params.ParamsKeeperI) { key := p.key + "." + p.kind switch p.kind { case ParamKindString: From fbf4fdb582e1e6efa3721149469a515dc7a36642 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:53:42 +0100 Subject: [PATCH 68/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/sys/params/params_test.gno | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 examples/gno.land/r/sys/params/params_test.gno diff --git a/examples/gno.land/r/sys/params/params_test.gno b/examples/gno.land/r/sys/params/params_test.gno new file mode 100644 index 00000000000..eaa1ad039d3 --- /dev/null +++ b/examples/gno.land/r/sys/params/params_test.gno @@ -0,0 +1,15 @@ +package params + +import "testing" + +// Testing this package is limited because it only contains an `std.Set` method +// without a corresponding `std.Get` method. For comprehensive testing, refer to +// the tests located in the r/gov/dao/ directory, specifically in one of the +// propX_filetest.gno files. + +func TestNewStringPropExecutor(t *testing.T) { + executor := NewStringPropExecutor("foo", "bar") + if executor == nil { + t.Errorf("executor shouldn't be nil") + } +} From 6d99f19b723bcdfac457a825638eb956d22cb0e3 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:57:40 +0100 Subject: [PATCH 69/69] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/sys/params/params.gno | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/examples/gno.land/r/sys/params/params.gno b/examples/gno.land/r/sys/params/params.gno index 91236ce4827..fa04c90de3f 100644 --- a/examples/gno.land/r/sys/params/params.gno +++ b/examples/gno.land/r/sys/params/params.gno @@ -1,3 +1,20 @@ +// Package params provides functions for creating parameter executors that +// interface with the Params Keeper. +// +// This package enables setting various parameter types (such as strings, +// integers, booleans, and byte slices) through the GovDAO proposal mechanism. +// Each function returns an executor that, when called, sets the specified +// parameter in the Params Keeper. +// +// The executors are designed to be used within governance proposals to modify +// parameters dynamically. The integration with the GovDAO allows for parameter +// changes to be proposed and executed in a controlled manner, ensuring that +// modifications are subject to governance processes. +// +// Example usage: +// +// executor := params.NewStringPropExecutor("exampleKey", "exampleValue") +// // This executor can be used in a governance proposal to set the parameter. package params import (