From 51322b790dda07cb561049019f9d71e2f83db0b1 Mon Sep 17 00:00:00 2001 From: anarcher Date: Mon, 31 Oct 2022 01:11:45 +0900 Subject: [PATCH 01/64] feat: r/system/names public functions --- examples/gno.land/r/system/names/names.gno | 59 ++++++++++++++----- .../gno.land/r/system/names/names_test.gno | 1 + examples/gno.land/r/system/names/utils.gno | 36 +++++++++++ 3 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 examples/gno.land/r/system/names/names_test.gno create mode 100644 examples/gno.land/r/system/names/utils.gno diff --git a/examples/gno.land/r/system/names/names.gno b/examples/gno.land/r/system/names/names.gno index e1f479fc379..7d40efd6e3f 100644 --- a/examples/gno.land/r/system/names/names.gno +++ b/examples/gno.land/r/system/names/names.gno @@ -23,34 +23,65 @@ func Register(namespace string) { // - already exists / reserved. // - min/max length, format. // - fees (dynamic, based on length). - panic("not implemented") + if existsNamespace(namespace) { + panic("namespace already exists") + } + + caller := std.GetOrigCaller() + namespaces.Set(namespace, Space{ + Admins: []std.Address{caller}, + }) } func AddAdmin(namespace string, newAdmin std.Address) { - // TODO: assertIsAdmin() - panic("not implemented") + assertIsAdmin(namespace) + + space := getSpace(namespace) + if !containsAddress(space.Admins, newAdmin) { + space.Admins = append(space.Admins, newAdmin) + } } func RemoveAdmin(namespace string, newAdmin std.Address) { - // TODO: assertIsAdmin() // TODO: check if self. - panic("not implemented") + assertIsAdmin(namespace) + + // remove admin + space := getSpace(namespace) + for i, admin := range space.Admins { + if admin == newAdmin { + space.Admins = append(space.Admins[:i], space.Admins[i+1:]...) + break + } + } } -func AddEditor(namespace string, newAdmin std.Address) { - // TODO: assertIsAdmin() - panic("not implemented") +func AddEditor(namespace string, newEditor std.Address) { + assertIsAdmin(namespace) + space := getSpace(namespace) + + if !containsAddress(space.Editors, newEditor) { + space.Editors = append(space.Editors, newEditor) + } } -func RemoveEditor(namespace string, newAdmin std.Address) { - // TODO: assertIsAdmin() - // TODO: check if self. - panic("not implemented") +func RemoveEditor(namespace string, newEditor std.Address) { + assertIsAdmin(namespace) + + // remove editor + space := getSpace(namespace) + for i, editor := range space.Editors { + if editor == newEditor { + space.Editors = append(space.Editors[:i], space.Editors[i+1:]...) + break + } + } } func SetInPause(namespace string, state bool) { - // TODO: assertIsAdmin() - panic("not implemented") + assertIsAdmin(namespace) + space := getSpace(namespace) + space.InPause = state } func Render(path string) string { diff --git a/examples/gno.land/r/system/names/names_test.gno b/examples/gno.land/r/system/names/names_test.gno new file mode 100644 index 00000000000..33577bef6a7 --- /dev/null +++ b/examples/gno.land/r/system/names/names_test.gno @@ -0,0 +1 @@ +package names diff --git a/examples/gno.land/r/system/names/utils.gno b/examples/gno.land/r/system/names/utils.gno new file mode 100644 index 00000000000..d8fcfef02f2 --- /dev/null +++ b/examples/gno.land/r/system/names/utils.gno @@ -0,0 +1,36 @@ +package names + +import ( + "std" +) + +func getSpace(namespace string) Space { + s, ok := namespaces.Get(namespace) + if !ok { + panic("namespace does not exist") + } + return s.(Space) +} + +func existsNamespace(name string) bool { + _, ok := namespaces.Get(name) + return ok +} + +func assertIsAdmin(namespace string) { + caller := std.GetOrigCaller() + space := getSpace(namespace) + + if !containsAddress(space.Admins, caller) { + panic("Only admins can call this function") + } +} + +func containsAddress(addrs []std.Address, addr std.Address) bool { + for _, a := range addrs { + if a == addr { + return true + } + } + return false +} From 2a9fee62de7b9e3d2d67c3d30fdf35b6d98dd174 Mon Sep 17 00:00:00 2001 From: anarcher Date: Tue, 1 Nov 2022 23:05:14 +0900 Subject: [PATCH 02/64] test: names basic test --- examples/gno.land/r/system/names/names.gno | 8 ++- .../gno.land/r/system/names/names_test.gno | 49 +++++++++++++++++++ examples/gno.land/r/system/names/utils.gno | 4 +- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/examples/gno.land/r/system/names/names.gno b/examples/gno.land/r/system/names/names.gno index 7d40efd6e3f..058728e0665 100644 --- a/examples/gno.land/r/system/names/names.gno +++ b/examples/gno.land/r/system/names/names.gno @@ -28,8 +28,9 @@ func Register(namespace string) { } caller := std.GetOrigCaller() - namespaces.Set(namespace, Space{ - Admins: []std.Address{caller}, + namespaces.Set(namespace, &Space{ + Admins: []std.Address{caller}, + InPause: true, }) } @@ -48,6 +49,9 @@ func RemoveAdmin(namespace string, newAdmin std.Address) { // remove admin space := getSpace(namespace) + if len(space.Admins) == 1 { + panic("namespace at least needs one admin") + } for i, admin := range space.Admins { if admin == newAdmin { space.Admins = append(space.Admins[:i], space.Admins[i+1:]...) diff --git a/examples/gno.land/r/system/names/names_test.gno b/examples/gno.land/r/system/names/names_test.gno index 33577bef6a7..5294c47d715 100644 --- a/examples/gno.land/r/system/names/names_test.gno +++ b/examples/gno.land/r/system/names/names_test.gno @@ -1 +1,50 @@ package names + +import ( + "std" + "testing" +) + +func TestRegisterNamespace(t *testing.T) { + std.TestSetOrigCaller(std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq")) + creator := std.GetOrigCaller() + + n := "test2" + Register(n) + s := getSpace(n) + assertTrue(t, containsAddress(s.Admins, creator)) +} + +func TestAddAdmins(t *testing.T) { + std.TestSetOrigCaller(std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq")) + creator := std.GetOrigCaller() + + test1 := std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + test2 := std.Address("g1r6casl322p5adkmmjjkjea404e7f6w29y6gzwg") + + ns := "test3" + + Register(ns) + s := getSpace(ns) + + AddAdmin(ns, test1) + AddAdmin(ns, test2) + assertTrue(t, containsAddress(s.Admins, test1)) + assertTrue(t, containsAddress(s.Admins, test2)) + + RemoveAdmin(ns, test1) + assertTrue(t, !containsAddress(s.Admins, test1)) + assertTrue(t, containsAddress(s.Admins, test2)) + + AddEditor(ns, test1) + assertTrue(t, containsAddress(s.Editors, test1)) + + RemoveEditor(ns, test1) + assertTrue(t, !containsAddress(s.Editors, test1)) +} + +func assertTrue(t *testing.T, b bool) { + if !b { + t.Fail() + } +} diff --git a/examples/gno.land/r/system/names/utils.gno b/examples/gno.land/r/system/names/utils.gno index d8fcfef02f2..e95cd013680 100644 --- a/examples/gno.land/r/system/names/utils.gno +++ b/examples/gno.land/r/system/names/utils.gno @@ -4,12 +4,12 @@ import ( "std" ) -func getSpace(namespace string) Space { +func getSpace(namespace string) *Space { s, ok := namespaces.Get(namespace) if !ok { panic("namespace does not exist") } - return s.(Space) + return s.(*Space) } func existsNamespace(name string) bool { From db517fd79ceb30e8f47dbadfd852918225b63878 Mon Sep 17 00:00:00 2001 From: anarcher Date: Wed, 2 Nov 2022 00:07:15 +0900 Subject: [PATCH 03/64] chore: default inpause false --- examples/gno.land/r/system/names/names.gno | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/gno.land/r/system/names/names.gno b/examples/gno.land/r/system/names/names.gno index 058728e0665..4b5d32a696b 100644 --- a/examples/gno.land/r/system/names/names.gno +++ b/examples/gno.land/r/system/names/names.gno @@ -29,8 +29,7 @@ func Register(namespace string) { caller := std.GetOrigCaller() namespaces.Set(namespace, &Space{ - Admins: []std.Address{caller}, - InPause: true, + Admins: []std.Address{caller}, }) } From 65fbc4dc0bca2223423dad5652fb090a1160116e Mon Sep 17 00:00:00 2001 From: anarcher Date: Thu, 3 Nov 2022 00:52:22 +0900 Subject: [PATCH 04/64] feat(render): render index and namespace --- examples/gno.land/r/system/names/names.gno | 53 +++++++++++++++++++++- examples/gno.land/r/system/names/utils.gno | 7 +++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/r/system/names/names.gno b/examples/gno.land/r/system/names/names.gno index 4b5d32a696b..82982830c35 100644 --- a/examples/gno.land/r/system/names/names.gno +++ b/examples/gno.land/r/system/names/names.gno @@ -5,6 +5,7 @@ import ( "std" "gno.land/p/demo/avl" + "gno.land/p/demo/ufmt" ) // "AddPkg" will check if r/system/names exists. If yes, it will @@ -88,7 +89,55 @@ func SetInPause(namespace string, state bool) { } func Render(path string) string { - // TODO: by namespace. // TODO: by address. - return "not implemented" + + if path == "" { + return renderIndex() + } else if path[:2] == "n/" { + return renderNamespace(path[2:]) + } + return "" +} + +func renderNamespace(namespace string) string { + space := getSpace(namespace) + output := ufmt.Sprintf(` +# %s + +## Admins + +%s + +## Editors + +%s + +## InPause + +%s + +`, namespace, renderAddresses(space.Admins), renderAddresses(space.Editors), formatBool(space.InPause)) + return output + +} + +func renderIndex() string { + output := "## Namespaces \n" + namespaces.Iterate("", "", func(n *avl.Tree) bool { + namespace := n.Key() + space := n.Value().(*Space) + output += ufmt.Sprintf("* [%s](/r/system/names:n/%s) - admins: %d editors: %d inPause: %s \n", + namespace, namespace, len(space.Admins), len(space.Editors), formatBool(space.InPause)) + return false + }) + + return output +} + +func renderAddresses(addresses []std.Address) string { + output := "" + for _, address := range addresses { + output += ufmt.Sprintf("* %s \n", string(address)) + } + return output } diff --git a/examples/gno.land/r/system/names/utils.gno b/examples/gno.land/r/system/names/utils.gno index e95cd013680..3f19d9d94db 100644 --- a/examples/gno.land/r/system/names/utils.gno +++ b/examples/gno.land/r/system/names/utils.gno @@ -34,3 +34,10 @@ func containsAddress(addrs []std.Address, addr std.Address) bool { } return false } + +func formatBool(b bool) string { + if b { + return "true" + } + return "false" +} From 180fb33a5d4734297a736cef38e6de590800fe82 Mon Sep 17 00:00:00 2001 From: anarcher Date: Sat, 5 Nov 2022 01:11:47 +0900 Subject: [PATCH 05/64] feat: reName and HasPerm --- examples/gno.land/r/system/names/names.gno | 44 +++++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/r/system/names/names.gno b/examples/gno.land/r/system/names/names.gno index 82982830c35..9b43e753d6e 100644 --- a/examples/gno.land/r/system/names/names.gno +++ b/examples/gno.land/r/system/names/names.gno @@ -2,6 +2,8 @@ package names import ( + "errors" + "regexp" "std" "gno.land/p/demo/avl" @@ -13,6 +15,9 @@ import ( // determine if an address can publish a package or not. var namespaces avl.Tree // name(string) -> Space +// TODO: more accurate. +var reNamespace = regexp.MustCompile(`^[a-z][a-z0-9_]{2,30}$`) + type Space struct { Admins []std.Address Editors []std.Address @@ -28,6 +33,10 @@ func Register(namespace string) { panic("namespace already exists") } + if err := validateNamespace(namespace); err != nil { + panic(err) + } + caller := std.GetOrigCaller() namespaces.Set(namespace, &Space{ Admins: []std.Address{caller}, @@ -52,12 +61,14 @@ func RemoveAdmin(namespace string, newAdmin std.Address) { if len(space.Admins) == 1 { panic("namespace at least needs one admin") } + var admins []std.Address for i, admin := range space.Admins { if admin == newAdmin { - space.Admins = append(space.Admins[:i], space.Admins[i+1:]...) + admins = append(space.Admins[:i], space.Admins[i+1:]...) break } } + space.Admins = admins } func AddEditor(namespace string, newEditor std.Address) { @@ -74,12 +85,14 @@ func RemoveEditor(namespace string, newEditor std.Address) { // remove editor space := getSpace(namespace) + var editors []std.Address for i, editor := range space.Editors { if editor == newEditor { - space.Editors = append(space.Editors[:i], space.Editors[i+1:]...) + editors = append(space.Editors[:i], space.Editors[i+1:]...) break } } + space.Editors = editors } func SetInPause(namespace string, state bool) { @@ -88,6 +101,26 @@ func SetInPause(namespace string, state bool) { space.InPause = state } +// HasPerm returns true if the caller has permission of the namespace. +func HasPerm(namespace string) bool { + caller := std.GetOrigCaller() + space := getSpace(namespace) + + if space.InPause { + return false + } + + if containsAddress(space.Admins, caller) { + return true + } + + if containsAddress(space.Editors, caller) { + return true + } + + return false +} + func Render(path string) string { // TODO: by address. @@ -141,3 +174,10 @@ func renderAddresses(addresses []std.Address) string { } return output } + +func validateNamespace(namespace string) error { + if !reNamespace.MatchString(namespace) { + return errors.New("invalid namespace") + } + return nil +} From 32a086fe22d2a0ab77013d9042f953539e7241a1 Mon Sep 17 00:00:00 2001 From: anarcher Date: Sat, 5 Nov 2022 15:53:11 +0900 Subject: [PATCH 06/64] feat: check namespace perm in vmkeeper.AddPackage --- tm2/pkg/sdk/vm/keeper.go | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/tm2/pkg/sdk/vm/keeper.go b/tm2/pkg/sdk/vm/keeper.go index 28531f0a773..a251effd8ca 100644 --- a/tm2/pkg/sdk/vm/keeper.go +++ b/tm2/pkg/sdk/vm/keeper.go @@ -9,6 +9,7 @@ import ( gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/stdlibs" + "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/gnolang/gno/tm2/pkg/sdk/auth" @@ -128,6 +129,35 @@ func (vm *VMKeeper) getGnoStore(ctx sdk.Context) gno.Store { } } +func (vm *VMKeeper) checkNamespacePerm(ctx sdk.Context, creator crypto.Address, pkgPath string) error { + store := vm.getGnoStore(ctx) + + // if r/system/names does not exists -> skip validation. + if pv := store.GetPackage("gno.land/r/system/names", false); pv == nil { + return nil + } + + pathSp := strings.SplitN(pkgPath, "/", 4) // gno.land/r/... + namespace := pathSp[2] + + res, err := vm.Call(ctx, MsgCall{ + Caller: creator, + Send: std.Coins{}, + PkgPath: "gno.land/r/system/names", + Func: "HasPerm", + Args: []string{namespace}, + }) + if err != nil { + return err + } + //TODO: needs fixed representation of bool + if res != "(true bool)" { + return fmt.Errorf("namespace %q not allowed", namespace) + } + + return nil +} + // AddPackage adds a package with given fileset. func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) error { creator := msg.Creator @@ -153,12 +183,9 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) error { // Pay deposit from creator. pkgAddr := gno.DerivePkgAddr(pkgPath) - // TODO: ACLs. - // - if r/system/names does not exists -> skip validation. - // - loads r/system/names data state. - // - lookup r/system/names.namespaces for `{r,p}/NAMES`. - // - check if caller is in Admins or Editors. - // - check if namespace is not in pause. + if err := vm.checkNamespacePerm(ctx, creator, pkgPath); err != nil { + return err + } err := vm.bank.SendCoins(ctx, creator, pkgAddr, deposit) if err != nil { From 3b865ef1a5ac6cb955ffe6f67dc4bbd8927d03a2 Mon Sep 17 00:00:00 2001 From: anarcher Date: Sat, 5 Nov 2022 16:36:45 +0900 Subject: [PATCH 07/64] refactor: separate space methods and public function --- examples/gno.land/r/system/names/names.gno | 104 +++++++++++---------- examples/gno.land/r/system/names/utils.gno | 16 ++++ 2 files changed, 72 insertions(+), 48 deletions(-) diff --git a/examples/gno.land/r/system/names/names.gno b/examples/gno.land/r/system/names/names.gno index 9b43e753d6e..8c25b5fbb52 100644 --- a/examples/gno.land/r/system/names/names.gno +++ b/examples/gno.land/r/system/names/names.gno @@ -24,6 +24,49 @@ type Space struct { InPause bool } +func (s *Space) addAdmin(newAdmin std.Address) { + if !containsAddress(s.Admins, newAdmin) { + s.Admins = append(s.Admins, newAdmin) + } +} + +func (s *Space) removeAdmin(admin std.Address) error { + if len(s.Admins) == 1 { + return errors.New("namespace at least needs one admin") + } + admins := removeAddress(s.Admins, admin) + s.Admins = admins + return nil +} + +func (s *Space) addEditor(newEditor std.Address) { + if !containsAddress(s.Editors, newEditor) { + s.Editors = append(s.Editors, newEditor) + } +} + +func (s *Space) removeEditor(editor std.Address) error { + editors := removeAddress(s.Editors, editor) + s.Editors = editors + return nil +} + +func (s *Space) hasPerm(caller std.Address) bool { + if s.InPause { + return false + } + + if containsAddress(s.Admins, caller) { + return true + } + + if containsAddress(s.Editors, caller) { + return true + } + + return false +} + func Register(namespace string) { // TODO: input sanitization: // - already exists / reserved. @@ -45,54 +88,28 @@ func Register(namespace string) { func AddAdmin(namespace string, newAdmin std.Address) { assertIsAdmin(namespace) - space := getSpace(namespace) - if !containsAddress(space.Admins, newAdmin) { - space.Admins = append(space.Admins, newAdmin) - } + space.addAdmin(newAdmin) } -func RemoveAdmin(namespace string, newAdmin std.Address) { - // TODO: check if self. +func RemoveAdmin(namespace string, admin std.Address) { assertIsAdmin(namespace) - - // remove admin space := getSpace(namespace) - if len(space.Admins) == 1 { - panic("namespace at least needs one admin") - } - var admins []std.Address - for i, admin := range space.Admins { - if admin == newAdmin { - admins = append(space.Admins[:i], space.Admins[i+1:]...) - break - } - } - space.Admins = admins + err := space.removeAdmin(admin) + checkErr(err) } func AddEditor(namespace string, newEditor std.Address) { assertIsAdmin(namespace) space := getSpace(namespace) - - if !containsAddress(space.Editors, newEditor) { - space.Editors = append(space.Editors, newEditor) - } + space.addEditor(newEditor) } -func RemoveEditor(namespace string, newEditor std.Address) { +func RemoveEditor(namespace string, editor std.Address) { assertIsAdmin(namespace) - - // remove editor space := getSpace(namespace) - var editors []std.Address - for i, editor := range space.Editors { - if editor == newEditor { - editors = append(space.Editors[:i], space.Editors[i+1:]...) - break - } - } - space.Editors = editors + err := space.removeEditor(editor) + checkErr(err) } func SetInPause(namespace string, state bool) { @@ -102,23 +119,14 @@ func SetInPause(namespace string, state bool) { } // HasPerm returns true if the caller has permission of the namespace. +// If the namespace does not exist, it will return panic. +// If the namespace exists but the caller is not an admin or editor, +// it will return false. +// The vm keeper will use this function to check to add package func HasPerm(namespace string) bool { caller := std.GetOrigCaller() space := getSpace(namespace) - - if space.InPause { - return false - } - - if containsAddress(space.Admins, caller) { - return true - } - - if containsAddress(space.Editors, caller) { - return true - } - - return false + return space.hasPerm(caller) } func Render(path string) string { diff --git a/examples/gno.land/r/system/names/utils.gno b/examples/gno.land/r/system/names/utils.gno index 3f19d9d94db..b44341fe33f 100644 --- a/examples/gno.land/r/system/names/utils.gno +++ b/examples/gno.land/r/system/names/utils.gno @@ -26,6 +26,16 @@ func assertIsAdmin(namespace string) { } } +func removeAddress(addrs []std.Address, addr std.Address) []std.Address { + var newAddrs []std.Address + for _, a := range addrs { + if a != addr { + newAddrs = append(newAddrs, a) + } + } + return newAddrs +} + func containsAddress(addrs []std.Address, addr std.Address) bool { for _, a := range addrs { if a == addr { @@ -35,6 +45,12 @@ func containsAddress(addrs []std.Address, addr std.Address) bool { return false } +func checkErr(err error) { + if err != nil { + panic(err) + } +} + func formatBool(b bool) string { if b { return "true" From 5e18c066efac4da8a1b7ccabf7998cf3122caae0 Mon Sep 17 00:00:00 2001 From: anarcher Date: Sat, 5 Nov 2022 22:16:18 +0900 Subject: [PATCH 08/64] refactor: assertIsAdmin --- examples/gno.land/r/system/names/names.gno | 17 ++++++++++++----- examples/gno.land/r/system/names/utils.gno | 6 ++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/examples/gno.land/r/system/names/names.gno b/examples/gno.land/r/system/names/names.gno index 8c25b5fbb52..d3604788216 100644 --- a/examples/gno.land/r/system/names/names.gno +++ b/examples/gno.land/r/system/names/names.gno @@ -24,6 +24,13 @@ type Space struct { InPause bool } +func (s *Space) isAdmin(addr std.Address) bool { + if containsAddress(s.Admins, addr) { + return true + } + return false +} + func (s *Space) addAdmin(newAdmin std.Address) { if !containsAddress(s.Admins, newAdmin) { s.Admins = append(s.Admins, newAdmin) @@ -87,34 +94,34 @@ func Register(namespace string) { } func AddAdmin(namespace string, newAdmin std.Address) { - assertIsAdmin(namespace) space := getSpace(namespace) + assertIsAdmin(space) space.addAdmin(newAdmin) } func RemoveAdmin(namespace string, admin std.Address) { - assertIsAdmin(namespace) space := getSpace(namespace) + assertIsAdmin(space) err := space.removeAdmin(admin) checkErr(err) } func AddEditor(namespace string, newEditor std.Address) { - assertIsAdmin(namespace) space := getSpace(namespace) + assertIsAdmin(space) space.addEditor(newEditor) } func RemoveEditor(namespace string, editor std.Address) { - assertIsAdmin(namespace) space := getSpace(namespace) + assertIsAdmin(space) err := space.removeEditor(editor) checkErr(err) } func SetInPause(namespace string, state bool) { - assertIsAdmin(namespace) space := getSpace(namespace) + assertIsAdmin(space) space.InPause = state } diff --git a/examples/gno.land/r/system/names/utils.gno b/examples/gno.land/r/system/names/utils.gno index b44341fe33f..8215ddc5b5a 100644 --- a/examples/gno.land/r/system/names/utils.gno +++ b/examples/gno.land/r/system/names/utils.gno @@ -17,11 +17,9 @@ func existsNamespace(name string) bool { return ok } -func assertIsAdmin(namespace string) { +func assertIsAdmin(space *Space) { caller := std.GetOrigCaller() - space := getSpace(namespace) - - if !containsAddress(space.Admins, caller) { + if !space.isAdmin(caller) { panic("Only admins can call this function") } } From 4a3c896bae50a81be6df7dce05695635467dfcb2 Mon Sep 17 00:00:00 2001 From: "myoung-su,shin" Date: Thu, 10 Nov 2022 15:47:40 +0900 Subject: [PATCH 09/64] Update examples/gno.land/r/system/names/names.gno Thanks! :-) Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com> --- examples/gno.land/r/system/names/names.gno | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/gno.land/r/system/names/names.gno b/examples/gno.land/r/system/names/names.gno index d3604788216..0d39827b0b6 100644 --- a/examples/gno.land/r/system/names/names.gno +++ b/examples/gno.land/r/system/names/names.gno @@ -25,10 +25,7 @@ type Space struct { } func (s *Space) isAdmin(addr std.Address) bool { - if containsAddress(s.Admins, addr) { - return true - } - return false + return containsAddress(s.Admins, addr) } func (s *Space) addAdmin(newAdmin std.Address) { From 2e9e7a54298a2f8492510243418cf04d6b98ab8e Mon Sep 17 00:00:00 2001 From: "myoung-su,shin" Date: Thu, 10 Nov 2022 15:49:07 +0900 Subject: [PATCH 10/64] Update examples/gno.land/r/system/names/names.gno Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com> --- examples/gno.land/r/system/names/names.gno | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/r/system/names/names.gno b/examples/gno.land/r/system/names/names.gno index 0d39827b0b6..65b2cc9c766 100644 --- a/examples/gno.land/r/system/names/names.gno +++ b/examples/gno.land/r/system/names/names.gno @@ -80,9 +80,8 @@ func Register(namespace string) { panic("namespace already exists") } - if err := validateNamespace(namespace); err != nil { - panic(err) - } + err := validateNamespace(namespace) + checkErr(err) caller := std.GetOrigCaller() namespaces.Set(namespace, &Space{ From a0a83e8ea4fbc86b589cee0fa6ce43239b8c7134 Mon Sep 17 00:00:00 2001 From: anarcher Date: Fri, 11 Nov 2022 01:57:39 +0900 Subject: [PATCH 11/64] refactor: move public functions to public.gno --- examples/gno.land/r/system/names/names.gno | 116 ----------------- examples/gno.land/r/system/names/public.gno | 123 ++++++++++++++++++ .../names/{names_test.gno => public_test.gno} | 0 3 files changed, 123 insertions(+), 116 deletions(-) create mode 100644 examples/gno.land/r/system/names/public.gno rename examples/gno.land/r/system/names/{names_test.gno => public_test.gno} (100%) diff --git a/examples/gno.land/r/system/names/names.gno b/examples/gno.land/r/system/names/names.gno index 65b2cc9c766..b84a76b7f68 100644 --- a/examples/gno.land/r/system/names/names.gno +++ b/examples/gno.land/r/system/names/names.gno @@ -7,7 +7,6 @@ import ( "std" "gno.land/p/demo/avl" - "gno.land/p/demo/ufmt" ) // "AddPkg" will check if r/system/names exists. If yes, it will @@ -71,121 +70,6 @@ func (s *Space) hasPerm(caller std.Address) bool { return false } -func Register(namespace string) { - // TODO: input sanitization: - // - already exists / reserved. - // - min/max length, format. - // - fees (dynamic, based on length). - if existsNamespace(namespace) { - panic("namespace already exists") - } - - err := validateNamespace(namespace) - checkErr(err) - - caller := std.GetOrigCaller() - namespaces.Set(namespace, &Space{ - Admins: []std.Address{caller}, - }) -} - -func AddAdmin(namespace string, newAdmin std.Address) { - space := getSpace(namespace) - assertIsAdmin(space) - space.addAdmin(newAdmin) -} - -func RemoveAdmin(namespace string, admin std.Address) { - space := getSpace(namespace) - assertIsAdmin(space) - err := space.removeAdmin(admin) - checkErr(err) -} - -func AddEditor(namespace string, newEditor std.Address) { - space := getSpace(namespace) - assertIsAdmin(space) - space.addEditor(newEditor) -} - -func RemoveEditor(namespace string, editor std.Address) { - space := getSpace(namespace) - assertIsAdmin(space) - err := space.removeEditor(editor) - checkErr(err) -} - -func SetInPause(namespace string, state bool) { - space := getSpace(namespace) - assertIsAdmin(space) - space.InPause = state -} - -// HasPerm returns true if the caller has permission of the namespace. -// If the namespace does not exist, it will return panic. -// If the namespace exists but the caller is not an admin or editor, -// it will return false. -// The vm keeper will use this function to check to add package -func HasPerm(namespace string) bool { - caller := std.GetOrigCaller() - space := getSpace(namespace) - return space.hasPerm(caller) -} - -func Render(path string) string { - // TODO: by address. - - if path == "" { - return renderIndex() - } else if path[:2] == "n/" { - return renderNamespace(path[2:]) - } - return "" -} - -func renderNamespace(namespace string) string { - space := getSpace(namespace) - output := ufmt.Sprintf(` -# %s - -## Admins - -%s - -## Editors - -%s - -## InPause - -%s - -`, namespace, renderAddresses(space.Admins), renderAddresses(space.Editors), formatBool(space.InPause)) - return output - -} - -func renderIndex() string { - output := "## Namespaces \n" - namespaces.Iterate("", "", func(n *avl.Tree) bool { - namespace := n.Key() - space := n.Value().(*Space) - output += ufmt.Sprintf("* [%s](/r/system/names:n/%s) - admins: %d editors: %d inPause: %s \n", - namespace, namespace, len(space.Admins), len(space.Editors), formatBool(space.InPause)) - return false - }) - - return output -} - -func renderAddresses(addresses []std.Address) string { - output := "" - for _, address := range addresses { - output += ufmt.Sprintf("* %s \n", string(address)) - } - return output -} - func validateNamespace(namespace string) error { if !reNamespace.MatchString(namespace) { return errors.New("invalid namespace") diff --git a/examples/gno.land/r/system/names/public.gno b/examples/gno.land/r/system/names/public.gno new file mode 100644 index 00000000000..a2bce902427 --- /dev/null +++ b/examples/gno.land/r/system/names/public.gno @@ -0,0 +1,123 @@ +package names + +import ( + "std" + + "gno.land/p/demo/avl" + "gno.land/p/demo/ufmt" +) + +func Register(namespace string) { + // TODO: input sanitization: + // - already exists / reserved. + // - min/max length, format. + // - fees (dynamic, based on length). + if existsNamespace(namespace) { + panic("namespace already exists") + } + + err := validateNamespace(namespace) + checkErr(err) + + caller := std.GetOrigCaller() + namespaces.Set(namespace, &Space{ + Admins: []std.Address{caller}, + }) +} + +func AddAdmin(namespace string, newAdmin std.Address) { + space := getSpace(namespace) + assertIsAdmin(space) + space.addAdmin(newAdmin) +} + +func RemoveAdmin(namespace string, admin std.Address) { + space := getSpace(namespace) + assertIsAdmin(space) + err := space.removeAdmin(admin) + checkErr(err) +} + +func AddEditor(namespace string, newEditor std.Address) { + space := getSpace(namespace) + assertIsAdmin(space) + space.addEditor(newEditor) +} + +func RemoveEditor(namespace string, editor std.Address) { + space := getSpace(namespace) + assertIsAdmin(space) + err := space.removeEditor(editor) + checkErr(err) +} + +func SetInPause(namespace string, state bool) { + space := getSpace(namespace) + assertIsAdmin(space) + space.InPause = state +} + +// HasPerm returns true if the caller has permission of the namespace. +// If the namespace does not exist, it will return panic. +// If the namespace exists but the caller is not an admin or editor, +// it will return false. +// The vm keeper will use this function to check to add package +func HasPerm(namespace string) bool { + caller := std.GetOrigCaller() + space := getSpace(namespace) + return space.hasPerm(caller) +} + +func Render(path string) string { + // TODO: by address. + + if path == "" { + return renderIndex() + } else if path[:2] == "n/" { + return renderNamespace(path[2:]) + } + return "" +} + +func renderNamespace(namespace string) string { + space := getSpace(namespace) + output := ufmt.Sprintf(` +# %s + +## Admins + +%s + +## Editors + +%s + +## InPause + +%s + +`, namespace, renderAddresses(space.Admins), renderAddresses(space.Editors), formatBool(space.InPause)) + return output + +} + +func renderIndex() string { + output := "## Namespaces \n" + namespaces.Iterate("", "", func(n *avl.Tree) bool { + namespace := n.Key() + space := n.Value().(*Space) + output += ufmt.Sprintf("* [%s](/r/system/names:n/%s) - admins: %d editors: %d inPause: %s \n", + namespace, namespace, len(space.Admins), len(space.Editors), formatBool(space.InPause)) + return false + }) + + return output +} + +func renderAddresses(addresses []std.Address) string { + output := "" + for _, address := range addresses { + output += ufmt.Sprintf("* %s \n", string(address)) + } + return output +} diff --git a/examples/gno.land/r/system/names/names_test.gno b/examples/gno.land/r/system/names/public_test.gno similarity index 100% rename from examples/gno.land/r/system/names/names_test.gno rename to examples/gno.land/r/system/names/public_test.gno From 32c816a8cddd7ed212fb4569780ae591205b1011 Mon Sep 17 00:00:00 2001 From: anarcher Date: Fri, 11 Nov 2022 02:00:20 +0900 Subject: [PATCH 12/64] chore: comment TODO: prevent self --- examples/gno.land/r/system/names/public.gno | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/gno.land/r/system/names/public.gno b/examples/gno.land/r/system/names/public.gno index a2bce902427..4c94d4f6abe 100644 --- a/examples/gno.land/r/system/names/public.gno +++ b/examples/gno.land/r/system/names/public.gno @@ -34,6 +34,7 @@ func AddAdmin(namespace string, newAdmin std.Address) { func RemoveAdmin(namespace string, admin std.Address) { space := getSpace(namespace) assertIsAdmin(space) + // TODO: prevent self err := space.removeAdmin(admin) checkErr(err) } From 5f1c6c4e8aa8330e395828eeed35dd9e2d705cad Mon Sep 17 00:00:00 2001 From: anarcher Date: Mon, 16 Jan 2023 23:11:02 +0900 Subject: [PATCH 13/64] feat: caller can't remove self --- examples/gno.land/r/system/names/names.gno | 6 ++++ .../gno.land/r/system/names/public_test.gno | 29 +++++++++++++++++-- examples/gno.land/r/system/names/utils.gno | 7 +++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/r/system/names/names.gno b/examples/gno.land/r/system/names/names.gno index b84a76b7f68..265c5e43779 100644 --- a/examples/gno.land/r/system/names/names.gno +++ b/examples/gno.land/r/system/names/names.gno @@ -37,6 +37,9 @@ func (s *Space) removeAdmin(admin std.Address) error { if len(s.Admins) == 1 { return errors.New("namespace at least needs one admin") } + if isCallerAddress(admin) { + return errors.New("cannot remove self") + } admins := removeAddress(s.Admins, admin) s.Admins = admins return nil @@ -49,6 +52,9 @@ func (s *Space) addEditor(newEditor std.Address) { } func (s *Space) removeEditor(editor std.Address) error { + if isCallerAddress(editor) { + return errors.New("cannot remove self") + } editors := removeAddress(s.Editors, editor) s.Editors = editors return nil diff --git a/examples/gno.land/r/system/names/public_test.gno b/examples/gno.land/r/system/names/public_test.gno index 5294c47d715..0d8de50519a 100644 --- a/examples/gno.land/r/system/names/public_test.gno +++ b/examples/gno.land/r/system/names/public_test.gno @@ -15,7 +15,7 @@ func TestRegisterNamespace(t *testing.T) { assertTrue(t, containsAddress(s.Admins, creator)) } -func TestAddAdmins(t *testing.T) { +func TestAdminFuncs(t *testing.T) { std.TestSetOrigCaller(std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq")) creator := std.GetOrigCaller() @@ -33,7 +33,7 @@ func TestAddAdmins(t *testing.T) { assertTrue(t, containsAddress(s.Admins, test2)) RemoveAdmin(ns, test1) - assertTrue(t, !containsAddress(s.Admins, test1)) + assertFalse(t, containsAddress(s.Admins, test1)) assertTrue(t, containsAddress(s.Admins, test2)) AddEditor(ns, test1) @@ -43,8 +43,33 @@ func TestAddAdmins(t *testing.T) { assertTrue(t, !containsAddress(s.Editors, test1)) } +func TestSpaceMethods(t *testing.T) { + std.TestSetOrigCaller(std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq")) + creator := std.GetOrigCaller() + + test1 := std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + test2 := std.Address("g1r6casl322p5adkmmjjkjea404e7f6w29y6gzwg") + + ns := "test4" + Register(ns) + s := getSpace(ns) + + assertTrue(t, s.isAdmin(creator)) + assertTrue(t, s.removeAdmin(creator) != nil) + + s.addAdmin(test1) + assertTrue(t, s.removeAdmin(test1) == nil) + +} + func assertTrue(t *testing.T, b bool) { if !b { t.Fail() } } + +func assertFalse(t *testing.T, b bool) { + if b { + t.Fail() + } +} diff --git a/examples/gno.land/r/system/names/utils.gno b/examples/gno.land/r/system/names/utils.gno index 8215ddc5b5a..5774c1adde5 100644 --- a/examples/gno.land/r/system/names/utils.gno +++ b/examples/gno.land/r/system/names/utils.gno @@ -43,6 +43,13 @@ func containsAddress(addrs []std.Address, addr std.Address) bool { return false } +func isCallerAddress(addr std.Address) bool { + if addr == std.GetOrigCaller() { + return true + } + return false +} + func checkErr(err error) { if err != nil { panic(err) From 905a45859e040179c2aa30031070763314e46ce5 Mon Sep 17 00:00:00 2001 From: anarcher Date: Mon, 16 Jan 2023 23:34:55 +0900 Subject: [PATCH 14/64] feat: global variable `enabled` for skipping to check perms if adding pkg --- examples/gno.land/r/system/names/enable.gno | 5 +++++ examples/gno.land/r/system/names/public.gno | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 examples/gno.land/r/system/names/enable.gno diff --git a/examples/gno.land/r/system/names/enable.gno b/examples/gno.land/r/system/names/enable.gno new file mode 100644 index 00000000000..b8cba4f892c --- /dev/null +++ b/examples/gno.land/r/system/names/enable.gno @@ -0,0 +1,5 @@ +package names + +// if enabled is true, `HasPerm` will check the permissions of names. +// todo: this is a temporary solution, we should use a more robust +var enabled bool = false diff --git a/examples/gno.land/r/system/names/public.gno b/examples/gno.land/r/system/names/public.gno index 4c94d4f6abe..5cddb736fb4 100644 --- a/examples/gno.land/r/system/names/public.gno +++ b/examples/gno.land/r/system/names/public.gno @@ -64,6 +64,10 @@ func SetInPause(namespace string, state bool) { // it will return false. // The vm keeper will use this function to check to add package func HasPerm(namespace string) bool { + // if enabled is false, it always returns true for dev and testing. + if enabled == false { + return true + } caller := std.GetOrigCaller() space := getSpace(namespace) return space.hasPerm(caller) From 159578584696ce79fbab5f8d81295e7c56919077 Mon Sep 17 00:00:00 2001 From: anarcher Date: Mon, 16 Jan 2023 23:37:38 +0900 Subject: [PATCH 15/64] chore: remove todo comment --- examples/gno.land/r/system/names/public.gno | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/gno.land/r/system/names/public.gno b/examples/gno.land/r/system/names/public.gno index 5cddb736fb4..e41305473ce 100644 --- a/examples/gno.land/r/system/names/public.gno +++ b/examples/gno.land/r/system/names/public.gno @@ -34,7 +34,6 @@ func AddAdmin(namespace string, newAdmin std.Address) { func RemoveAdmin(namespace string, admin std.Address) { space := getSpace(namespace) assertIsAdmin(space) - // TODO: prevent self err := space.removeAdmin(admin) checkErr(err) } From 904bd0be8e6dd4da08316321cceeb7f93e838540 Mon Sep 17 00:00:00 2001 From: anarcher Date: Thu, 19 Jan 2023 23:35:07 +0900 Subject: [PATCH 16/64] fix: avl.iterate --- examples/gno.land/r/system/names/public.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gno.land/r/system/names/public.gno b/examples/gno.land/r/system/names/public.gno index e41305473ce..d3530aff89a 100644 --- a/examples/gno.land/r/system/names/public.gno +++ b/examples/gno.land/r/system/names/public.gno @@ -107,7 +107,7 @@ func renderNamespace(namespace string) string { func renderIndex() string { output := "## Namespaces \n" - namespaces.Iterate("", "", func(n *avl.Tree) bool { + namespaces.Iterate("", "", func(n *avl.Node) bool { namespace := n.Key() space := n.Value().(*Space) output += ufmt.Sprintf("* [%s](/r/system/names:n/%s) - admins: %d editors: %d inPause: %s \n", From 715e72fef794a1f0bd3e038a3a397859980081e4 Mon Sep 17 00:00:00 2001 From: anarcher Date: Thu, 8 Jun 2023 01:36:30 +0900 Subject: [PATCH 17/64] chore: check enabled --- examples/gno.land/r/system/names/public.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gno.land/r/system/names/public.gno b/examples/gno.land/r/system/names/public.gno index d3530aff89a..55a21adad7b 100644 --- a/examples/gno.land/r/system/names/public.gno +++ b/examples/gno.land/r/system/names/public.gno @@ -64,7 +64,7 @@ func SetInPause(namespace string, state bool) { // The vm keeper will use this function to check to add package func HasPerm(namespace string) bool { // if enabled is false, it always returns true for dev and testing. - if enabled == false { + if !enabled { return true } caller := std.GetOrigCaller() From d66c61591f4f40e6ebd7211cc8d6021f4248ff4b Mon Sep 17 00:00:00 2001 From: anarcher Date: Fri, 9 Jun 2023 02:27:33 +0900 Subject: [PATCH 18/64] fix: avl.Tree.Iterate --- examples/gno.land/r/system/names/public.gno | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/gno.land/r/system/names/public.gno b/examples/gno.land/r/system/names/public.gno index 55a21adad7b..ccf5c00e0dd 100644 --- a/examples/gno.land/r/system/names/public.gno +++ b/examples/gno.land/r/system/names/public.gno @@ -3,7 +3,6 @@ package names import ( "std" - "gno.land/p/demo/avl" "gno.land/p/demo/ufmt" ) @@ -107,9 +106,8 @@ func renderNamespace(namespace string) string { func renderIndex() string { output := "## Namespaces \n" - namespaces.Iterate("", "", func(n *avl.Node) bool { - namespace := n.Key() - space := n.Value().(*Space) + namespaces.Iterate("", "", func(namespace string, value interface{}) bool { + space := value.(*Space) output += ufmt.Sprintf("* [%s](/r/system/names:n/%s) - admins: %d editors: %d inPause: %s \n", namespace, namespace, len(space.Admins), len(space.Editors), formatBool(space.InPause)) return false From 6852b1788456ba4400f921abdd818789aa43cf7a Mon Sep 17 00:00:00 2001 From: anarcher Date: Fri, 9 Jun 2023 02:47:17 +0900 Subject: [PATCH 19/64] chore: make fmt --- examples/gno.land/r/system/names/public.gno | 1 - examples/gno.land/r/system/names/public_test.gno | 1 - tm2/pkg/sdk/vm/keeper.go | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/gno.land/r/system/names/public.gno b/examples/gno.land/r/system/names/public.gno index ccf5c00e0dd..8c82f903fce 100644 --- a/examples/gno.land/r/system/names/public.gno +++ b/examples/gno.land/r/system/names/public.gno @@ -101,7 +101,6 @@ func renderNamespace(namespace string) string { `, namespace, renderAddresses(space.Admins), renderAddresses(space.Editors), formatBool(space.InPause)) return output - } func renderIndex() string { diff --git a/examples/gno.land/r/system/names/public_test.gno b/examples/gno.land/r/system/names/public_test.gno index 0d8de50519a..dc840024d2d 100644 --- a/examples/gno.land/r/system/names/public_test.gno +++ b/examples/gno.land/r/system/names/public_test.gno @@ -59,7 +59,6 @@ func TestSpaceMethods(t *testing.T) { s.addAdmin(test1) assertTrue(t, s.removeAdmin(test1) == nil) - } func assertTrue(t *testing.T, b bool) { diff --git a/tm2/pkg/sdk/vm/keeper.go b/tm2/pkg/sdk/vm/keeper.go index a251effd8ca..f26dafe6134 100644 --- a/tm2/pkg/sdk/vm/keeper.go +++ b/tm2/pkg/sdk/vm/keeper.go @@ -150,7 +150,7 @@ func (vm *VMKeeper) checkNamespacePerm(ctx sdk.Context, creator crypto.Address, if err != nil { return err } - //TODO: needs fixed representation of bool + // TODO: needs fixed representation of bool if res != "(true bool)" { return fmt.Errorf("namespace %q not allowed", namespace) } From a61c9df2c182beacc7b4d289ca1927fca20b5319 Mon Sep 17 00:00:00 2001 From: anarcher Date: Sat, 22 Jul 2023 07:48:17 +0900 Subject: [PATCH 20/64] chore: update gno.mod --- examples/gno.land/r/system/names/gno.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/gno.land/r/system/names/gno.mod b/examples/gno.land/r/system/names/gno.mod index 31c456f90e0..3a19b02113a 100644 --- a/examples/gno.land/r/system/names/gno.mod +++ b/examples/gno.land/r/system/names/gno.mod @@ -2,4 +2,5 @@ module gno.land/r/system/names require ( "gno.land/p/demo/avl" v0.0.0-latest + "gno.land/p/demo/ufmt" v0.0.0-latest ) From 5f3f975cc8695b5b725e0b0ae9c7ca087ac4979b Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Wed, 19 Jun 2024 20:20:53 +0200 Subject: [PATCH 21/64] wip: names Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- gno.land/pkg/sdk/vm/keeper.go | 65 +++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 106d0d92180..4e362491c31 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -9,6 +9,7 @@ import ( "os" "strings" + "github.com/gnolang/gno/gnovm/pkg/gnolang" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/stdlibs" "github.com/gnolang/gno/tm2/pkg/crypto" @@ -82,6 +83,7 @@ func (vm *VMKeeper) Initialize(ms store.MultiStore) { baseSDKStore := ms.GetStore(vm.baseKey) iavlSDKStore := ms.GetStore(vm.iavlKey) vm.gnoStore = gno.NewStore(alloc, baseSDKStore, iavlSDKStore) + vm.initBuiltinPackagesAndTypes(vm.gnoStore) if vm.gnoStore.NumMemPackages() > 0 { // for now, all mem packages must be re-run after reboot. @@ -137,31 +139,64 @@ func (vm *VMKeeper) getGnoStore(ctx sdk.Context) gno.Store { } func (vm *VMKeeper) checkNamespacePerm(ctx sdk.Context, creator crypto.Address, pkgPath string) error { + const syspkg = "gno.land/r/sys/names" + store := vm.getGnoStore(ctx) - // if r/system/names does not exists -> skip validation. - if pv := store.GetPackage("gno.land/r/system/names", false); pv == nil { + // if r/sys/names does not exists -> skip validation. + if store.GetPackage("gno.land/r/sys/names", false) == nil { return nil } + pkgAddr := gno.DerivePkgAddr(pkgPath) pathSp := strings.SplitN(pkgPath, "/", 4) // gno.land/r/... namespace := pathSp[2] - res, err := vm.Call(ctx, MsgCall{ - Caller: creator, - Send: std.Coins{}, - PkgPath: "gno.land/r/system/names", - Func: "HasPerm", - Args: []string{namespace}, - }) - if err != nil { - return err - } - // TODO: needs fixed representation of bool - if res != "(true bool)" { - return fmt.Errorf("namespace %q not allowed", namespace) + // Parse and run the files, construct *PV. + msgCtx := stdlibs.ExecContext{ + ChainID: ctx.ChainID(), + Height: ctx.BlockHeight(), + Timestamp: ctx.BlockTime().Unix(), + OrigCaller: creator.Bech32(), + OrigSendSpent: new(std.Coins), + OrigPkgAddr: pkgAddr.Bech32(), + Banker: NewSDKBanker(vm, ctx), + EventLogger: ctx.EventLogger(), } + m := gno.NewMachineWithOptions( + gno.MachineOptions{ + PkgPath: pkgPath, + Output: os.Stdout, // XXX + Store: store, + Context: msgCtx, + Alloc: store.GetAllocator(), + MaxCycles: vm.maxCycles, + GasMeter: ctx.GasMeter(), + }) + // - res, err := vm.Call(ctx, MsgCall{ + // - Caller: creator, + // - Send: std.Coins{}, + // - PkgPath: "gno.land/r/system/names", + // - Func: "HasPerm", + // - Args: []string{namespace}, + // - }) + + x := gno.Call( + gno.Sel(gnolang.Nx("names"), "HasPerm"), // Call testing.RunTest + gno.Str(namespace), // First param, the name of the test + ) + + ret := m.Eval(x) + panic(ret) + // // if err != nil { + // // return err + // // } + // // TODO: needs fixed representation of bool + // if res != "(true bool)" { + // return fmt.Errorf("namespace %q not allowed", namespace) + // } + return nil } From b20b163af0af1964486296578e1cf31904e2bb20 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:19:29 +0200 Subject: [PATCH 22/64] wip: users Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- .../gnoland/testdata/addpkg_namespace.txtar | 33 +++++++++++ gno.land/pkg/sdk/vm/keeper.go | 57 ++++++++++++------- 2 files changed, 68 insertions(+), 22 deletions(-) create mode 100644 gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar diff --git a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar new file mode 100644 index 00000000000..959237cc910 --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar @@ -0,0 +1,33 @@ +loadpkg gno.land/r/demo/users + +adduser gui + +gnoland start + +! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guil/counter -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1 +stderr 'unauthorized user' + +gnokey maketx call -pkgpath gno.land/r/demo/users -func Invite -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_gui test1 + +gnokey maketx call -pkgpath gno.land/r/demo/users -func Register -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_test1 -args 'guiland' -args 'im gui' gui + +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/counter -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui + +-- counter.gno -- +package counter + +import "strconv" + +var count = 0 + +func Inc() { + count += 1 +} + +func Render(path string) string { + return "# Counter: " + strconv.Itoa(count) +} + + +-- gno.mod -- +module gno.land/r/guiland/counter diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 4e362491c31..a7d9b0a1050 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "os" + "path/filepath" "strings" "github.com/gnolang/gno/gnovm/pkg/gnolang" @@ -25,6 +26,11 @@ import ( "go.opentelemetry.io/otel/metric" ) +var ( + ErrInvalidUrl = errors.New("invalid url") + ErrUnauthorizedUser = errors.New("unauthorized user") +) + const ( maxAllocTx = 500 * 1000 * 1000 maxAllocQuery = 1500 * 1000 * 1000 // higher limit for queries @@ -139,20 +145,27 @@ func (vm *VMKeeper) getGnoStore(ctx sdk.Context) gno.Store { } func (vm *VMKeeper) checkNamespacePerm(ctx sdk.Context, creator crypto.Address, pkgPath string) error { - const syspkg = "gno.land/r/sys/names" + const sysUsersPkg = "gno.land/r/demo/users" store := vm.getGnoStore(ctx) // if r/sys/names does not exists -> skip validation. - if store.GetPackage("gno.land/r/sys/names", false) == nil { + usersPkg := store.GetPackage(sysUsersPkg, false) + if usersPkg == nil { return nil } - pkgAddr := gno.DerivePkgAddr(pkgPath) - pathSp := strings.SplitN(pkgPath, "/", 4) // gno.land/r/... - namespace := pathSp[2] + pkgPath = filepath.Clean(pkgPath) // cleanup pkgpath + pathSp := strings.SplitN(pkgPath, "/", 4) // gno.land/r// + if len(pathSp) < 3 { + return fmt.Errorf("%w: %s", ErrInvalidUrl, pkgPath) + } + + // XXX: cleanup username + username := pathSp[2] // Parse and run the files, construct *PV. + pkgAddr := gno.DerivePkgAddr(pkgPath) msgCtx := stdlibs.ExecContext{ ChainID: ctx.ChainID(), Height: ctx.BlockHeight(), @@ -174,28 +187,22 @@ func (vm *VMKeeper) checkNamespacePerm(ctx sdk.Context, creator crypto.Address, MaxCycles: vm.maxCycles, GasMeter: ctx.GasMeter(), }) - // - res, err := vm.Call(ctx, MsgCall{ - // - Caller: creator, - // - Send: std.Coins{}, - // - PkgPath: "gno.land/r/system/names", - // - Func: "HasPerm", - // - Args: []string{namespace}, - // - }) + defer m.Release() + m.RunDeclaration(gno.ImportD("users", sysUsersPkg)) x := gno.Call( - gno.Sel(gnolang.Nx("names"), "HasPerm"), // Call testing.RunTest - gno.Str(namespace), // First param, the name of the test + gno.Sel(gnolang.Nx("users"), "GetUserByAddressOrName"), // Call testing.RunTest + gno.Str("@"+username), // First param, the name of the test ) ret := m.Eval(x) - panic(ret) - // // if err != nil { - // // return err - // // } - // // TODO: needs fixed representation of bool - // if res != "(true bool)" { - // return fmt.Errorf("namespace %q not allowed", namespace) - // } + if len(ret) == 0 { + panic("invalid response length call") + } + + if user := ret[0]; user.V == nil { + return fmt.Errorf("%w: %s", ErrUnauthorizedUser, pkgPath) + } return nil } @@ -235,6 +242,12 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { // Pay deposit from creator. pkgAddr := gno.DerivePkgAddr(pkgPath) + // TODO: ACLs. + // - if r/system/names does not exists -> skip validation. + // - loads r/system/names data state. + // - lookup r/system/names.namespaces for `{r,p}/NAMES`. + // - check if caller is in Admins or Editors. + // - check if namespace is not in pause. if err := vm.checkNamespacePerm(ctx, creator, pkgPath); err != nil { return err } From 163a85cadf41800a4ff9e626c78678f367c8a9d9 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:19:29 +0200 Subject: [PATCH 23/64] feat: add keeper user check Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- .../gnoland/testdata/addpkg_namespace.txtar | 36 ++++++----- gno.land/pkg/sdk/vm/keeper.go | 59 ++++++++++++++----- 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar index 959237cc910..9b68c1b6514 100644 --- a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar +++ b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar @@ -4,30 +4,34 @@ adduser gui gnoland start -! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guil/counter -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1 +## test address namespace + +! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stderr 'unauthorized user' -gnokey maketx call -pkgpath gno.land/r/demo/users -func Invite -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_gui test1 +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_gui/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui +stdout 'OK!' -gnokey maketx call -pkgpath gno.land/r/demo/users -func Register -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_test1 -args 'guiland' -args 'im gui' gui +## test unregister namespace -gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/counter -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui +! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1 +stderr 'unauthorized user' --- counter.gno -- -package counter +## test register namespace -import "strconv" +## XXX: THE FOLLOWING LINES REQUIRE BEING ABLE TO SET examples/gno.land/r/demo/users/users.admin= +# gnokey maketx call -pkgpath gno.land/r/demo/users -func Invite -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_gui test1 +# stdout 'OK!' -var count = 0 +# gnokey maketx call -pkgpath gno.land/r/demo/users -func Register -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_test1 -args 'guiland' -args 'im gui' gui +# stdout 'OK!' -func Inc() { - count += 1 -} +# gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui +# stdout 'OK!' + +-- one.gno -- +package one func Render(path string) string { - return "# Counter: " + strconv.Itoa(count) + return "# Hello One" } - - --- gno.mod -- -module gno.land/r/guiland/counter diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index a7d9b0a1050..902c58c86f3 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -8,9 +8,9 @@ import ( "fmt" "os" "path/filepath" + "regexp" "strings" - "github.com/gnolang/gno/gnovm/pkg/gnolang" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/stdlibs" "github.com/gnolang/gno/tm2/pkg/crypto" @@ -27,7 +27,7 @@ import ( ) var ( - ErrInvalidUrl = errors.New("invalid url") + ErrInvalidRealm = errors.New("invalid realm") ErrUnauthorizedUser = errors.New("unauthorized user") ) @@ -144,25 +144,42 @@ func (vm *VMKeeper) getGnoStore(ctx sdk.Context) gno.Store { } } -func (vm *VMKeeper) checkNamespacePerm(ctx sdk.Context, creator crypto.Address, pkgPath string) error { +// Namespace can be either a user or crypto address. +// XXX: Uppercase should be valid but transform into lowercase ? +var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([a-zA-Z]+[_a-zA-Z0-9]+)`) + +// checkNamespacePermission check if +func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Address, pkgPath string) error { const sysUsersPkg = "gno.land/r/demo/users" store := vm.getGnoStore(ctx) - // if r/sys/names does not exists -> skip validation. + // if `sysUsersPkg` does not exists -> skip validation. usersPkg := store.GetPackage(sysUsersPkg, false) if usersPkg == nil { return nil } - pkgPath = filepath.Clean(pkgPath) // cleanup pkgpath - pathSp := strings.SplitN(pkgPath, "/", 4) // gno.land/r// - if len(pathSp) < 3 { - return fmt.Errorf("%w: %s", ErrInvalidUrl, pkgPath) + // XXX: is this necessary ? + pkgPath = filepath.Clean(pkgPath) // cleanup pkgpath + + match := reNamespace.FindStringSubmatch(pkgPath) + if len(match) != 2 { + return fmt.Errorf("%w: %q", ErrInvalidRealm, pkgPath) } + username := match[1] + + // Lowercase username + username = strings.ToLower(username) + + // Allow user with their own address as namespace + if addr, err := crypto.AddressFromBech32(username); err == nil { + if addr.Compare(creator) == 0 { + return nil + } - // XXX: cleanup username - username := pathSp[2] + return fmt.Errorf("%w: %q", ErrUnauthorizedUser, username) + } // Parse and run the files, construct *PV. pkgAddr := gno.DerivePkgAddr(pkgPath) @@ -173,13 +190,14 @@ func (vm *VMKeeper) checkNamespacePerm(ctx sdk.Context, creator crypto.Address, OrigCaller: creator.Bech32(), OrigSendSpent: new(std.Coins), OrigPkgAddr: pkgAddr.Bech32(), - Banker: NewSDKBanker(vm, ctx), - EventLogger: ctx.EventLogger(), + // XXX: should we remove the banker ? + Banker: NewSDKBanker(vm, ctx), + EventLogger: ctx.EventLogger(), } m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: pkgPath, + PkgPath: "", Output: os.Stdout, // XXX Store: store, Context: msgCtx, @@ -189,10 +207,14 @@ func (vm *VMKeeper) checkNamespacePerm(ctx sdk.Context, creator crypto.Address, }) defer m.Release() + // call $sysUsersPkg.GetUserByName("") + // We only need to check by name here, as address have already been check + mpv := gno.NewPackageNode("main", "main", nil).NewPackage() + m.SetActivePackage(mpv) m.RunDeclaration(gno.ImportD("users", sysUsersPkg)) x := gno.Call( - gno.Sel(gnolang.Nx("users"), "GetUserByAddressOrName"), // Call testing.RunTest - gno.Str("@"+username), // First param, the name of the test + gno.Sel(gno.Nx("users"), "GetUserByName"), + gno.Str(username), ) ret := m.Eval(x) @@ -200,8 +222,9 @@ func (vm *VMKeeper) checkNamespacePerm(ctx sdk.Context, creator crypto.Address, panic("invalid response length call") } + // If value is nil, no user has been registered for this namespace if user := ret[0]; user.V == nil { - return fmt.Errorf("%w: %s", ErrUnauthorizedUser, pkgPath) + return fmt.Errorf("%w: %q", ErrUnauthorizedUser, username) } return nil @@ -252,6 +275,10 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { return err } + if err := vm.checkNamespacePermission(ctx, creator, pkgPath); err != nil { + return err + } + err = vm.bank.SendCoins(ctx, creator, pkgAddr, deposit) if err != nil { return err From dd31ab363190b515ec02310570e24372d9b4e606 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:22:35 +0200 Subject: [PATCH 24/64] fix: typo Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- gno.land/pkg/sdk/vm/keeper.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 902c58c86f3..9d3874642ac 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -148,7 +148,7 @@ func (vm *VMKeeper) getGnoStore(ctx sdk.Context) gno.Store { // XXX: Uppercase should be valid but transform into lowercase ? var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([a-zA-Z]+[_a-zA-Z0-9]+)`) -// checkNamespacePermission check if +// 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/demo/users" @@ -219,7 +219,7 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add ret := m.Eval(x) if len(ret) == 0 { - panic("invalid response length call") + panic("call: invalid response length") } // If value is nil, no user has been registered for this namespace From 7418f7ca29eeb159d09a5aa1738e42c74e9a47fa Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:23:16 +0200 Subject: [PATCH 25/64] fix: increase gas test Signed-off-by: gfanton <8671905+gfanton@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 9f4ae1a6678..2fb86ffd1c3 100644 --- a/gno.land/pkg/sdk/vm/gas_test.go +++ b/gno.land/pkg/sdk/vm/gas_test.go @@ -67,7 +67,7 @@ func TestAddPkgDeliverTx(t *testing.T) { gasDeliver := gctx.GasMeter().GasConsumed() assert.True(t, res.IsOK()) - assert.Equal(t, int64(87809), gasDeliver) + assert.Equal(t, int64(88809), gasDeliver) } // Enough gas for a failed transaction. From e101d6308d8b72254587d23c7df54e960cce1144 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:50:31 +0200 Subject: [PATCH 26/64] chore: remove sys/names Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/sys/names/enable.gno | 5 - examples/gno.land/r/sys/names/genesis.gno | 30 ----- examples/gno.land/r/sys/names/gno.mod | 3 - examples/gno.land/r/sys/names/names.gno | 84 ------------ examples/gno.land/r/sys/names/public.gno | 124 ------------------ examples/gno.land/r/sys/names/public_test.gno | 74 ----------- examples/gno.land/r/sys/names/utils.gno | 64 --------- 7 files changed, 384 deletions(-) delete mode 100644 examples/gno.land/r/sys/names/enable.gno delete mode 100644 examples/gno.land/r/sys/names/genesis.gno delete mode 100644 examples/gno.land/r/sys/names/gno.mod delete mode 100644 examples/gno.land/r/sys/names/names.gno delete mode 100644 examples/gno.land/r/sys/names/public.gno delete mode 100644 examples/gno.land/r/sys/names/public_test.gno delete mode 100644 examples/gno.land/r/sys/names/utils.gno diff --git a/examples/gno.land/r/sys/names/enable.gno b/examples/gno.land/r/sys/names/enable.gno deleted file mode 100644 index b8cba4f892c..00000000000 --- a/examples/gno.land/r/sys/names/enable.gno +++ /dev/null @@ -1,5 +0,0 @@ -package names - -// if enabled is true, `HasPerm` will check the permissions of names. -// todo: this is a temporary solution, we should use a more robust -var enabled bool = false diff --git a/examples/gno.land/r/sys/names/genesis.gno b/examples/gno.land/r/sys/names/genesis.gno deleted file mode 100644 index 7e4ae51645f..00000000000 --- a/examples/gno.land/r/sys/names/genesis.gno +++ /dev/null @@ -1,30 +0,0 @@ -package names - -import "std" - -func init() { - // Please, do not edit this file to reserve your username, use a transaction instead. - var ( - jaekwon = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") - manfred = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") - test1 = std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") - reservedAdmin = std.Address("g100000000000000000000000000000000000000") // FIXME: create a multisig. - reservedNames = []string{ - // FIXME: complete this list. - "gno", "gnolang", "tendermint", "cosmos", "hub", "admin", - "ethereum", "bitcoin", - // FIXME: reserve brands? then, require KYC to unlock? - } - ) - namespaces.Set("demo", &Space{Admins: []std.Address{jaekwon, manfred}}) - namespaces.Set("gnoland", &Space{Admins: []std.Address{jaekwon, manfred}}) - namespaces.Set("sys", &Space{Admins: []std.Address{jaekwon, manfred}}) - namespaces.Set("gov", &Space{Admins: []std.Address{jaekwon, manfred}}) - namespaces.Set("jaekwon", &Space{Admins: []std.Address{jaekwon}}) - namespaces.Set("manfred", &Space{Admins: []std.Address{manfred}}) - namespaces.Set("test1", &Space{Admins: []std.Address{test1}}) - - for _, keyword := range reservedNames { - namespaces.Set(keyword, &Space{Admins: []std.Address{reservedAdmin}}) - } -} diff --git a/examples/gno.land/r/sys/names/gno.mod b/examples/gno.land/r/sys/names/gno.mod deleted file mode 100644 index 97236a84892..00000000000 --- a/examples/gno.land/r/sys/names/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/sys/names - -require gno.land/p/demo/avl v0.0.0-latest diff --git a/examples/gno.land/r/sys/names/names.gno b/examples/gno.land/r/sys/names/names.gno deleted file mode 100644 index 8aba0fc7a15..00000000000 --- a/examples/gno.land/r/sys/names/names.gno +++ /dev/null @@ -1,84 +0,0 @@ -// The realm r/sys/names is used to manage namespaces on gno.land. -package names - -import ( - "errors" - "regexp" - "std" - - "gno.land/p/demo/avl" -) - -// "AddPkg" will check if r/sys/names exists. If yes, it will -// inspect the realm's state and use the following variable to -// determine if an address can publish a package or not. -var namespaces avl.Tree // name(string) -> Space - -// TODO: more accurate. -var reNamespace = regexp.MustCompile(`^[a-z][a-z0-9_]{2,30}$`) - -type Space struct { - Admins []std.Address - Editors []std.Address - InPause bool -} - -func (s *Space) isAdmin(addr std.Address) bool { - return containsAddress(s.Admins, addr) -} - -func (s *Space) addAdmin(newAdmin std.Address) { - if !containsAddress(s.Admins, newAdmin) { - s.Admins = append(s.Admins, newAdmin) - } -} - -func (s *Space) removeAdmin(admin std.Address) error { - if len(s.Admins) == 1 { - return errors.New("namespace at least needs one admin") - } - if isCallerAddress(admin) { - return errors.New("cannot remove self") - } - admins := removeAddress(s.Admins, admin) - s.Admins = admins - return nil -} - -func (s *Space) addEditor(newEditor std.Address) { - if !containsAddress(s.Editors, newEditor) { - s.Editors = append(s.Editors, newEditor) - } -} - -func (s *Space) removeEditor(editor std.Address) error { - if isCallerAddress(editor) { - return errors.New("cannot remove self") - } - editors := removeAddress(s.Editors, editor) - s.Editors = editors - return nil -} - -func (s *Space) hasPerm(caller std.Address) bool { - if s.InPause { - return false - } - - if containsAddress(s.Admins, caller) { - return true - } - - if containsAddress(s.Editors, caller) { - return true - } - - return false -} - -func validateNamespace(namespace string) error { - if !reNamespace.MatchString(namespace) { - return errors.New("invalid namespace") - } - return nil -} diff --git a/examples/gno.land/r/sys/names/public.gno b/examples/gno.land/r/sys/names/public.gno deleted file mode 100644 index 8c82f903fce..00000000000 --- a/examples/gno.land/r/sys/names/public.gno +++ /dev/null @@ -1,124 +0,0 @@ -package names - -import ( - "std" - - "gno.land/p/demo/ufmt" -) - -func Register(namespace string) { - // TODO: input sanitization: - // - already exists / reserved. - // - min/max length, format. - // - fees (dynamic, based on length). - if existsNamespace(namespace) { - panic("namespace already exists") - } - - err := validateNamespace(namespace) - checkErr(err) - - caller := std.GetOrigCaller() - namespaces.Set(namespace, &Space{ - Admins: []std.Address{caller}, - }) -} - -func AddAdmin(namespace string, newAdmin std.Address) { - space := getSpace(namespace) - assertIsAdmin(space) - space.addAdmin(newAdmin) -} - -func RemoveAdmin(namespace string, admin std.Address) { - space := getSpace(namespace) - assertIsAdmin(space) - err := space.removeAdmin(admin) - checkErr(err) -} - -func AddEditor(namespace string, newEditor std.Address) { - space := getSpace(namespace) - assertIsAdmin(space) - space.addEditor(newEditor) -} - -func RemoveEditor(namespace string, editor std.Address) { - space := getSpace(namespace) - assertIsAdmin(space) - err := space.removeEditor(editor) - checkErr(err) -} - -func SetInPause(namespace string, state bool) { - space := getSpace(namespace) - assertIsAdmin(space) - space.InPause = state -} - -// HasPerm returns true if the caller has permission of the namespace. -// If the namespace does not exist, it will return panic. -// If the namespace exists but the caller is not an admin or editor, -// it will return false. -// The vm keeper will use this function to check to add package -func HasPerm(namespace string) bool { - // if enabled is false, it always returns true for dev and testing. - if !enabled { - return true - } - caller := std.GetOrigCaller() - space := getSpace(namespace) - return space.hasPerm(caller) -} - -func Render(path string) string { - // TODO: by address. - - if path == "" { - return renderIndex() - } else if path[:2] == "n/" { - return renderNamespace(path[2:]) - } - return "" -} - -func renderNamespace(namespace string) string { - space := getSpace(namespace) - output := ufmt.Sprintf(` -# %s - -## Admins - -%s - -## Editors - -%s - -## InPause - -%s - -`, namespace, renderAddresses(space.Admins), renderAddresses(space.Editors), formatBool(space.InPause)) - return output -} - -func renderIndex() string { - output := "## Namespaces \n" - namespaces.Iterate("", "", func(namespace string, value interface{}) bool { - space := value.(*Space) - output += ufmt.Sprintf("* [%s](/r/system/names:n/%s) - admins: %d editors: %d inPause: %s \n", - namespace, namespace, len(space.Admins), len(space.Editors), formatBool(space.InPause)) - return false - }) - - return output -} - -func renderAddresses(addresses []std.Address) string { - output := "" - for _, address := range addresses { - output += ufmt.Sprintf("* %s \n", string(address)) - } - return output -} diff --git a/examples/gno.land/r/sys/names/public_test.gno b/examples/gno.land/r/sys/names/public_test.gno deleted file mode 100644 index dc840024d2d..00000000000 --- a/examples/gno.land/r/sys/names/public_test.gno +++ /dev/null @@ -1,74 +0,0 @@ -package names - -import ( - "std" - "testing" -) - -func TestRegisterNamespace(t *testing.T) { - std.TestSetOrigCaller(std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq")) - creator := std.GetOrigCaller() - - n := "test2" - Register(n) - s := getSpace(n) - assertTrue(t, containsAddress(s.Admins, creator)) -} - -func TestAdminFuncs(t *testing.T) { - std.TestSetOrigCaller(std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq")) - creator := std.GetOrigCaller() - - test1 := std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") - test2 := std.Address("g1r6casl322p5adkmmjjkjea404e7f6w29y6gzwg") - - ns := "test3" - - Register(ns) - s := getSpace(ns) - - AddAdmin(ns, test1) - AddAdmin(ns, test2) - assertTrue(t, containsAddress(s.Admins, test1)) - assertTrue(t, containsAddress(s.Admins, test2)) - - RemoveAdmin(ns, test1) - assertFalse(t, containsAddress(s.Admins, test1)) - assertTrue(t, containsAddress(s.Admins, test2)) - - AddEditor(ns, test1) - assertTrue(t, containsAddress(s.Editors, test1)) - - RemoveEditor(ns, test1) - assertTrue(t, !containsAddress(s.Editors, test1)) -} - -func TestSpaceMethods(t *testing.T) { - std.TestSetOrigCaller(std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq")) - creator := std.GetOrigCaller() - - test1 := std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") - test2 := std.Address("g1r6casl322p5adkmmjjkjea404e7f6w29y6gzwg") - - ns := "test4" - Register(ns) - s := getSpace(ns) - - assertTrue(t, s.isAdmin(creator)) - assertTrue(t, s.removeAdmin(creator) != nil) - - s.addAdmin(test1) - assertTrue(t, s.removeAdmin(test1) == nil) -} - -func assertTrue(t *testing.T, b bool) { - if !b { - t.Fail() - } -} - -func assertFalse(t *testing.T, b bool) { - if b { - t.Fail() - } -} diff --git a/examples/gno.land/r/sys/names/utils.gno b/examples/gno.land/r/sys/names/utils.gno deleted file mode 100644 index 5774c1adde5..00000000000 --- a/examples/gno.land/r/sys/names/utils.gno +++ /dev/null @@ -1,64 +0,0 @@ -package names - -import ( - "std" -) - -func getSpace(namespace string) *Space { - s, ok := namespaces.Get(namespace) - if !ok { - panic("namespace does not exist") - } - return s.(*Space) -} - -func existsNamespace(name string) bool { - _, ok := namespaces.Get(name) - return ok -} - -func assertIsAdmin(space *Space) { - caller := std.GetOrigCaller() - if !space.isAdmin(caller) { - panic("Only admins can call this function") - } -} - -func removeAddress(addrs []std.Address, addr std.Address) []std.Address { - var newAddrs []std.Address - for _, a := range addrs { - if a != addr { - newAddrs = append(newAddrs, a) - } - } - return newAddrs -} - -func containsAddress(addrs []std.Address, addr std.Address) bool { - for _, a := range addrs { - if a == addr { - return true - } - } - return false -} - -func isCallerAddress(addr std.Address) bool { - if addr == std.GetOrigCaller() { - return true - } - return false -} - -func checkErr(err error) { - if err != nil { - panic(err) - } -} - -func formatBool(b bool) string { - if b { - return "true" - } - return "false" -} From dff936709833c5b5c24cbf70053abf11e7f528fc Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:52:16 +0200 Subject: [PATCH 27/64] chore: cleanup duplicate method Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- gno.land/pkg/sdk/vm/keeper.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 774f25b4bd3..57a0aca2316 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -271,10 +271,6 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { // - lookup r/system/names.namespaces for `{r,p}/NAMES`. // - check if caller is in Admins or Editors. // - check if namespace is not in pause. - if err := vm.checkNamespacePerm(ctx, creator, pkgPath); err != nil { - return err - } - if err := vm.checkNamespacePermission(ctx, creator, pkgPath); err != nil { return err } From 763a39b4510e62b25cab46cbbc403ed9762092c6 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:26:56 +0200 Subject: [PATCH 28/64] fix: keeper Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- .../gnoland/testdata/addpkg_namespace.txtar | 16 ++++++-- gno.land/pkg/sdk/vm/errors.go | 20 ++++++---- gno.land/pkg/sdk/vm/keeper.go | 40 ++++++++++--------- gno.land/pkg/sdk/vm/package.go | 1 + 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar index 9b68c1b6514..c1321b529e9 100644 --- a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar +++ b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar @@ -4,7 +4,7 @@ adduser gui gnoland start -## test address namespace +## test address (g1...) namespace ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stderr 'unauthorized user' @@ -12,23 +12,31 @@ stderr 'unauthorized user' gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_gui/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stdout 'OK!' -## test unregister namespace +## test unregistered namespace ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1 stderr 'unauthorized user' -## test register namespace +## test registered namespace -## XXX: THE FOLLOWING LINES REQUIRE BEING ABLE TO SET examples/gno.land/r/demo/users/users.admin= +# # XXX: THE FOLLOWING LINES REQUIRE BEING ABLE TO SET examples/gno.land/r/demo/users/users.admin= +# # test test1 invite gui # gnokey maketx call -pkgpath gno.land/r/demo/users -func Invite -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_gui test1 # stdout 'OK!' +# # test gui register namespace # gnokey maketx call -pkgpath gno.land/r/demo/users -func Register -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_test1 -args 'guiland' -args 'im gui' gui # stdout 'OK!' +# # test gui pushing on guiland/one # gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui # stdout 'OK!' +# # test test1 pushing on guiland/two +# ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/two -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1 +# stderr 'unauthorized user' + + -- one.gno -- package one diff --git a/gno.land/pkg/sdk/vm/errors.go b/gno.land/pkg/sdk/vm/errors.go index 0020e989eb6..a0e71e08d14 100644 --- a/gno.land/pkg/sdk/vm/errors.go +++ b/gno.land/pkg/sdk/vm/errors.go @@ -15,18 +15,20 @@ func (abciError) AssertABCIError() {} // declare all script errors. // NOTE: these are meant to be used in conjunction with pkgs/errors. type ( - InvalidPkgPathError struct{ abciError } - InvalidStmtError struct{ abciError } - InvalidExprError struct{ abciError } - TypeCheckError struct { + InvalidPkgPathError struct{ abciError } + InvalidStmtError struct{ abciError } + InvalidExprError struct{ abciError } + UnauthorizedUserError struct{ abciError } + TypeCheckError struct { abciError Errors []string `json:"errors"` } ) -func (e InvalidPkgPathError) Error() string { return "invalid package path" } -func (e InvalidStmtError) Error() string { return "invalid statement" } -func (e InvalidExprError) Error() string { return "invalid expression" } +func (e InvalidPkgPathError) Error() string { return "invalid package path" } +func (e InvalidStmtError) Error() string { return "invalid statement" } +func (e InvalidExprError) Error() string { return "invalid expression" } +func (e UnauthorizedUserError) Error() string { return "unauthorized user" } func (e TypeCheckError) Error() string { var bld strings.Builder bld.WriteString("invalid gno package; type check errors:\n") @@ -34,6 +36,10 @@ func (e TypeCheckError) Error() string { return bld.String() } +func ErrUnauthorizedUser(msg string) error { + return errors.Wrap(UnauthorizedUserError{}, msg) +} + func ErrInvalidPkgPath(msg string) error { return errors.Wrap(InvalidPkgPathError{}, msg) } diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 57a0aca2316..2f72c4949e9 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -7,7 +7,7 @@ import ( "context" "fmt" "os" - "path/filepath" + "path" "regexp" "strings" @@ -26,11 +26,6 @@ import ( "go.opentelemetry.io/otel/metric" ) -var ( - ErrInvalidRealm = errors.New("invalid realm") - ErrUnauthorizedUser = errors.New("unauthorized user") -) - const ( maxAllocTx = 500 * 1000 * 1000 maxAllocQuery = 1500 * 1000 * 1000 // higher limit for queries @@ -162,11 +157,11 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add } // XXX: is this necessary ? - pkgPath = filepath.Clean(pkgPath) // cleanup pkgpath + pkgPath = path.Clean(pkgPath) // cleanup pkgpath match := reNamespace.FindStringSubmatch(pkgPath) if len(match) != 2 { - return fmt.Errorf("%w: %q", ErrInvalidRealm, pkgPath) + return ErrInvalidPkgPath(pkgPath) } username := match[1] @@ -176,10 +171,10 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add // Allow user with their own address as namespace if addr, err := crypto.AddressFromBech32(username); err == nil { if addr.Compare(creator) == 0 { - return nil + return nil // ok } - return fmt.Errorf("%w: %q", ErrUnauthorizedUser, username) + return ErrUnauthorizedUser(username) } // Parse and run the files, construct *PV. @@ -208,14 +203,14 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add }) defer m.Release() - // call $sysUsersPkg.GetUserByName("") + // call $sysUsersPkg.Resolve("") // We only need to check by name here, as address have already been check mpv := gno.NewPackageNode("main", "main", nil).NewPackage() m.SetActivePackage(mpv) m.RunDeclaration(gno.ImportD("users", sysUsersPkg)) x := gno.Call( - gno.Sel(gno.Nx("users"), "GetUserByName"), - gno.Str(username), + gno.Sel(gno.Nx("users"), "Resolve"), + gno.Str("@"+username), ) ret := m.Eval(x) @@ -223,12 +218,22 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add panic("call: invalid response length") } + useraddress := ret[0] // If value is nil, no user has been registered for this namespace - if user := ret[0]; user.V == nil { - return fmt.Errorf("%w: %q", ErrUnauthorizedUser, username) + if useraddress.T.Kind() != gno.StringKind { + panic("call: invalid response kind") } - return nil + // Check for ownership + if rawAddr := useraddress.GetString(); rawAddr != "" { + if owner, err := crypto.AddressFromBech32(rawAddr); err == nil { + if owner.Compare(creator) == 0 { + return nil // ok + } + } + } + + return ErrUnauthorizedUser(username) } // AddPackage adds a package with given fileset. @@ -268,9 +273,6 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { // TODO: ACLs. // - if r/system/names does not exists -> skip validation. // - loads r/system/names data state. - // - lookup r/system/names.namespaces for `{r,p}/NAMES`. - // - check if caller is in Admins or Editors. - // - check if namespace is not in pause. if err := vm.checkNamespacePermission(ctx, creator, pkgPath); err != nil { return err } diff --git a/gno.land/pkg/sdk/vm/package.go b/gno.land/pkg/sdk/vm/package.go index b2e7fbecfc4..e62a7b53928 100644 --- a/gno.land/pkg/sdk/vm/package.go +++ b/gno.land/pkg/sdk/vm/package.go @@ -21,4 +21,5 @@ var Package = amino.RegisterPackage(amino.NewPackage( InvalidStmtError{}, "InvalidStmtError", InvalidExprError{}, "InvalidExprError", TypeCheckError{}, "TypeCheckError", + UnauthorizedUserError{}, "UnauthorizedUserError", )) From 5dabc779f9cd9379a573299f31add65d67652b66 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:27:09 +0200 Subject: [PATCH 29/64] fix: users resolve Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/demo/users/users.gno | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/gno.land/r/demo/users/users.gno b/examples/gno.land/r/demo/users/users.gno index 5b4b8ec2c14..c66871718d6 100644 --- a/examples/gno.land/r/demo/users/users.gno +++ b/examples/gno.land/r/demo/users/users.gno @@ -236,12 +236,11 @@ func GetUserByAddressOrName(input users.AddressOrName) *users.User { } func Resolve(input users.AddressOrName) std.Address { - name, isName := input.GetName() - if !isName { - return std.Address(input) // TODO check validity + if user := GetUserByAddressOrName(input); user != nil { + return user.Address } - user := GetUserByName(name) - return user.Address + + return std.Address("") } //---------------------------------------- From 1f9ba975191e3fb364c71d13a56bdaeb8e09330b Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 2 Jul 2024 16:26:05 +0200 Subject: [PATCH 30/64] fix: undo change on user / add GetUserAddressByName Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/demo/users/users.gno | 17 ++++++++++++++--- gno.land/pkg/sdk/vm/keeper.go | 4 ++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/examples/gno.land/r/demo/users/users.gno b/examples/gno.land/r/demo/users/users.gno index c66871718d6..65cf80011f6 100644 --- a/examples/gno.land/r/demo/users/users.gno +++ b/examples/gno.land/r/demo/users/users.gno @@ -218,6 +218,15 @@ func GetUserByName(name string) *users.User { return userI.(*users.User) } +// Get user address by name +func GetUserAddressByName(name string) std.Address { + if user := GetUserByName(input); user != nil { + return user.Address + } + + return std.Address("") +} + func GetUserByAddress(addr std.Address) *users.User { userI, ok := addr2User.Get(addr.String()) if !ok { @@ -236,11 +245,13 @@ func GetUserByAddressOrName(input users.AddressOrName) *users.User { } func Resolve(input users.AddressOrName) std.Address { - if user := GetUserByAddressOrName(input); user != nil { - return user.Address + name, isName := input.GetName() + if !isName { + return std.Address(input) // TODO check validity } - return std.Address("") + user := GetUserByName(name) + return user.Address } //---------------------------------------- diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 2f72c4949e9..f50c1035a80 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -209,8 +209,8 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add m.SetActivePackage(mpv) m.RunDeclaration(gno.ImportD("users", sysUsersPkg)) x := gno.Call( - gno.Sel(gno.Nx("users"), "Resolve"), - gno.Str("@"+username), + gno.Sel(gno.Nx("users"), "GetUserAddressByName"), + gno.Str(username), ) ret := m.Eval(x) From 91bc22b252567f813b98cc62d10231f67c8e845c Mon Sep 17 00:00:00 2001 From: Guilhem Fanton <8671905+gfanton@users.noreply.github.com> Date: Sat, 6 Jul 2024 15:40:07 +0200 Subject: [PATCH 31/64] Update keeper.go Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com> --- gno.land/pkg/sdk/vm/keeper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index f50c1035a80..5accd15c6fe 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -150,7 +150,7 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add store := vm.getGnoStore(ctx) - // if `sysUsersPkg` does not exists -> skip validation. + // if `sysUsersPkg` does not exist -> skip validation. usersPkg := store.GetPackage(sysUsersPkg, false) if usersPkg == nil { return nil From bf7fba2dd70c03832541be1969971c7cd66fac7e Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Sat, 6 Jul 2024 21:32:48 +0200 Subject: [PATCH 32/64] wip: admin users package Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/demo/users/users.gno | 9 ------ examples/gno.land/r/sys/users/gno.mod | 1 + examples/gno.land/r/sys/users/users.gno | 39 ++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 examples/gno.land/r/sys/users/gno.mod create mode 100644 examples/gno.land/r/sys/users/users.gno diff --git a/examples/gno.land/r/demo/users/users.gno b/examples/gno.land/r/demo/users/users.gno index 65cf80011f6..90886d134fb 100644 --- a/examples/gno.land/r/demo/users/users.gno +++ b/examples/gno.land/r/demo/users/users.gno @@ -218,15 +218,6 @@ func GetUserByName(name string) *users.User { return userI.(*users.User) } -// Get user address by name -func GetUserAddressByName(name string) std.Address { - if user := GetUserByName(input); user != nil { - return user.Address - } - - return std.Address("") -} - func GetUserByAddress(addr std.Address) *users.User { userI, ok := addr2User.Get(addr.String()) if !ok { diff --git a/examples/gno.land/r/sys/users/gno.mod b/examples/gno.land/r/sys/users/gno.mod new file mode 100644 index 00000000000..542999a54ed --- /dev/null +++ b/examples/gno.land/r/sys/users/gno.mod @@ -0,0 +1 @@ +module gno.land/r/sys/users \ No newline at end of file diff --git a/examples/gno.land/r/sys/users/users.gno b/examples/gno.land/r/sys/users/users.gno new file mode 100644 index 00000000000..5eaf282b6a8 --- /dev/null +++ b/examples/gno.land/r/sys/users/users.gno @@ -0,0 +1,39 @@ +package users + +import ( + "std" + + "gno.land/r/demo/users" +) + +// For now this package is disable by default +var enable = false + +var admin = "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq" // @moul + +// Admin call to Activate or Desactivate this package. +func AdminActivate(t bool) { + assertAdmin() + + enable = t +} + +// This method ensure that the given address have ownership on the given name. +func IsAuthorizedAddressForName(address std.Address, name string) bool { + if !enable { + return true + } + + if user := users.GetUserByName(name); user != nil { + return user.Address == address + } + + return false +} + +func assertIsAdmin() { + caller := std.GetOrigCaller() + if admin != caller { + panic("access restricted.") + } +} From 2b889061e9379a0ae100a49ebe02efb80bbe7fd2 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Sun, 7 Jul 2024 17:30:34 +0200 Subject: [PATCH 33/64] feat: add replace command for txtar Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- .../pkg/integration/testdata/replace.txtar | 20 +++++++ .../pkg/integration/testing_integration.go | 55 +++++++++++++++++-- 2 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 gno.land/pkg/integration/testdata/replace.txtar diff --git a/gno.land/pkg/integration/testdata/replace.txtar b/gno.land/pkg/integration/testdata/replace.txtar new file mode 100644 index 00000000000..cd81c568bbd --- /dev/null +++ b/gno.land/pkg/integration/testdata/replace.txtar @@ -0,0 +1,20 @@ +loadpkg gno.land/r/dev/admin $WORK + +adduser dev + +replace "g1abcde" $USER_ADDR_dev + +gnoland start + +gnokey maketx call -pkgpath gno.land/r/dev/admin -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +! stdout g1abcde +stdout $USER_ADDR_dev + +-- admin.gno -- +package admin + +var admin = "g1abcde" + +func Render(path string) string { + return "# Hello "+admin +} diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index 654dda0b45e..ebc71289bfa 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -15,6 +15,7 @@ import ( "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/gno.land/pkg/keyscli" "github.com/gnolang/gno/gno.land/pkg/log" + "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/tm2/pkg/bft/node" @@ -259,7 +260,7 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { err = cmd.ParseAndRun(context.Background(), args) tsValidateError(ts, "gnokey", neg, err) }, - // adduser commands must be executed before starting the node; it errors out otherwise. + // adduser command must be executed before starting the node; it errors out otherwise. "adduser": func(ts *testscript.TestScript, neg bool, args []string) { if nodeIsRunning(nodes, getNodeSID(ts)) { tsValidateError(ts, "adduser", neg, errors.New("adduser must be used before starting node")) @@ -339,7 +340,23 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { fmt.Fprintf(ts.Stdout(), "Added %s(%s) to genesis", args[0], balance.Address) }, - // `loadpkg` load a specific package from the 'examples' or working directory + // `replace` will replace all occurences of the first argument with the second + // argument of any loaded files + "replace": func(ts *testscript.TestScript, neg bool, args []string) { + args, err := unquote(args) + if err != nil { + tsValidateError(ts, "replace", neg, err) + } + + if len(args) != 2 { + ts.Fatalf("`replace`: should have exactly 2 arguments") + } + + pkgs := ts.Value(envKeyPkgsLoader).(*pkgsLoader) + replace, with := args[0], args[1] + pkgs.SetReplace(replace, with) + }, + // `loadpkg` load a specific package from the 'examples' or working directory. "loadpkg": func(ts *testscript.TestScript, neg bool, args []string) { // special dirs workDir := ts.Getenv("WORK") @@ -575,12 +592,17 @@ func createAccountFrom(env envSetter, kb keys.Keybase, accountName, mnemonic str type pkgsLoader struct { pkgs []gnomod.Pkg visited map[string]struct{} + + // list of occurences to replaces with the given value + // XXX: find a better way + replaces map[string]string } func newPkgsLoader() *pkgsLoader { return &pkgsLoader{ - pkgs: make([]gnomod.Pkg, 0), - visited: make(map[string]struct{}), + pkgs: make([]gnomod.Pkg, 0), + visited: make(map[string]struct{}), + replaces: make(map[string]string), } } @@ -588,6 +610,10 @@ func (pl *pkgsLoader) List() gnomod.PkgList { return pl.pkgs } +func (pl *pkgsLoader) SetReplace(replace, with string) { + pl.replaces[replace] = with +} + func (pl *pkgsLoader) LoadPackages(creator bft.Address, fee std.Fee, deposit std.Coins) ([]std.Tx, error) { pkgslist, err := pl.List().Sort() // sorts packages by their dependencies. if err != nil { @@ -600,6 +626,27 @@ func (pl *pkgsLoader) LoadPackages(creator bft.Address, fee std.Fee, deposit std if err != nil { return nil, fmt.Errorf("unable to load pkg %q: %w", pkg.Name, err) } + + // If any replace value is specified, apply them + if len(pl.replaces) > 0 { + for _, msg := range tx.Msgs { + addpkg, ok := msg.(vm.MsgAddPackage) + if !ok { + continue + } + + if addpkg.Package == nil { + continue + } + + for _, file := range addpkg.Package.Files { + for replace, with := range pl.replaces { + file.Body = strings.ReplaceAll(file.Body, replace, with) + } + } + } + } + txs[i] = tx } From b451995cad310fe7eab470c8e6471b0ca78b94bc Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Sun, 7 Jul 2024 17:30:44 +0200 Subject: [PATCH 34/64] feat: Add sys/users Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/sys/users/users.gno | 25 ++++++-- .../gnoland/testdata/addpkg_namespace.txtar | 64 ++++++++++++++----- gno.land/pkg/sdk/vm/keeper.go | 38 ++++------- 3 files changed, 80 insertions(+), 47 deletions(-) diff --git a/examples/gno.land/r/sys/users/users.gno b/examples/gno.land/r/sys/users/users.gno index 5eaf282b6a8..6322fc9d5ee 100644 --- a/examples/gno.land/r/sys/users/users.gno +++ b/examples/gno.land/r/sys/users/users.gno @@ -9,21 +9,34 @@ import ( // For now this package is disable by default var enable = false -var admin = "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq" // @moul +var admin = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // Admin call to Activate or Desactivate this package. -func AdminActivate(t bool) { - assertAdmin() +func AdminEnable() { + assertIsAdmin() - enable = t + enable = true } +func AdminDisable() { + assertIsAdmin() + + enable = false +} + +func IsEnable() bool { return enable } + // This method ensure that the given address have ownership on the given name. func IsAuthorizedAddressForName(address std.Address, name string) bool { if !enable { return true } + // Allow user with their own address as name + if address.String() == name { + return true + } + if user := users.GetUserByName(name); user != nil { return user.Address == address } @@ -33,7 +46,7 @@ func IsAuthorizedAddressForName(address std.Address, name string) bool { func assertIsAdmin() { caller := std.GetOrigCaller() - if admin != caller { - panic("access restricted.") + if admin != caller.String() { + panic("access restricted") } } diff --git a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar index c1321b529e9..a5a8c577cc6 100644 --- a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar +++ b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar @@ -1,40 +1,74 @@ loadpkg gno.land/r/demo/users +loadpkg gno.land/r/sys/users +adduser admin adduser gui +replace "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" $USER_ADDR_admin # use our custom admin + gnoland start -## test address (g1...) namespace +## When Disable + +# `sys/users` should be disable by default, addpkg should works by default + +# check is sys/users is disable +gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test gui +stdout 'OK!' +stdout 'false' + +# gui sould be able to addpkg on test1 addr +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/mysuperpkg -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui +stdout 'OK!' + +# gui sould be able to addpkg on random name +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/randomname/mysuperpkg -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui +stdout 'OK!' + +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/myfirstpkg -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui +stdout 'OK!' +## When Enable + +# enable users +gnokey maketx call -pkgpath gno.land/r/sys/users -func AdminEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test admin +stdout 'OK!' + +# check that sys/users as been enable +gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test admin +stdout 'OK!' +stdout 'true' + +# try to add a pkg with unregistered user ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stderr 'unauthorized user' +# try to add a pkg with unregistered user, on their own address as namespace gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_gui/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stdout 'OK!' ## test unregistered namespace -! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1 +! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test admin stderr 'unauthorized user' ## test registered namespace -# # XXX: THE FOLLOWING LINES REQUIRE BEING ABLE TO SET examples/gno.land/r/demo/users/users.admin= -# # test test1 invite gui -# gnokey maketx call -pkgpath gno.land/r/demo/users -func Invite -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_gui test1 -# stdout 'OK!' +# test admin invite gui +gnokey maketx call -pkgpath gno.land/r/demo/users -func Invite -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_gui admin +stdout 'OK!' -# # test gui register namespace -# gnokey maketx call -pkgpath gno.land/r/demo/users -func Register -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_test1 -args 'guiland' -args 'im gui' gui -# stdout 'OK!' +# test gui register namespace +gnokey maketx call -pkgpath gno.land/r/demo/users -func Register -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_admin -args 'guiland' -args 'im gui' gui +stdout 'OK!' -# # test gui pushing on guiland/one -# gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui -# stdout 'OK!' +# test gui pushing on guiland/one +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui +stdout 'OK!' -# # test test1 pushing on guiland/two -# ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/two -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1 -# stderr 'unauthorized user' +# test admin pushing on guiland/two +! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/two -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test admin +stderr 'unauthorized user' -- one.gno -- diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 5accd15c6fe..d7302f60f94 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -146,16 +146,10 @@ var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([a-zA-Z]+[_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 { - const sysUsersPkg = "gno.land/r/demo/users" + const sysUsersPkg = "gno.land/r/sys/users" store := vm.getGnoStore(ctx) - // if `sysUsersPkg` does not exist -> skip validation. - usersPkg := store.GetPackage(sysUsersPkg, false) - if usersPkg == nil { - return nil - } - // XXX: is this necessary ? pkgPath = path.Clean(pkgPath) // cleanup pkgpath @@ -168,13 +162,10 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add // Lowercase username username = strings.ToLower(username) - // Allow user with their own address as namespace - if addr, err := crypto.AddressFromBech32(username); err == nil { - if addr.Compare(creator) == 0 { - return nil // ok - } - - return ErrUnauthorizedUser(username) + // if `sysUsersPkg` does not exist -> skip validation. + usersPkg := store.GetPackage(sysUsersPkg, false) + if usersPkg == nil { + return nil } // Parse and run the files, construct *PV. @@ -203,13 +194,14 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add }) defer m.Release() - // call $sysUsersPkg.Resolve("") + // call $sysUsersPkg.IsAuthorizedAddressForName("") // We only need to check by name here, as address have already been check mpv := gno.NewPackageNode("main", "main", nil).NewPackage() m.SetActivePackage(mpv) m.RunDeclaration(gno.ImportD("users", sysUsersPkg)) x := gno.Call( - gno.Sel(gno.Nx("users"), "GetUserAddressByName"), + gno.Sel(gno.Nx("users"), "IsAuthorizedAddressForName"), + gno.Str(creator.String()), gno.Str(username), ) @@ -219,21 +211,15 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add } useraddress := ret[0] - // If value is nil, no user has been registered for this namespace - if useraddress.T.Kind() != gno.StringKind { + if useraddress.T.Kind() != gno.BoolKind { panic("call: invalid response kind") } - // Check for ownership - if rawAddr := useraddress.GetString(); rawAddr != "" { - if owner, err := crypto.AddressFromBech32(rawAddr); err == nil { - if owner.Compare(creator) == 0 { - return nil // ok - } - } + if isAuthorized := useraddress.GetBool(); !isAuthorized { + return ErrUnauthorizedUser(username) } - return ErrUnauthorizedUser(username) + return nil } // AddPackage adds a package with given fileset. From c1df7c36809f36253687aeec1001557ce1d94f28 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Sun, 7 Jul 2024 17:49:14 +0200 Subject: [PATCH 35/64] chore: improve txtar comments Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- .../gnoland/testdata/addpkg_namespace.txtar | 25 +++++++++++++------ .../pkg/integration/testing_integration.go | 3 ++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar index a5a8c577cc6..676d6b828d9 100644 --- a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar +++ b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar @@ -8,69 +8,78 @@ replace "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" $USER_ADDR_admin # use our cu gnoland start -## When Disable +## When `sys/users` is Disable -# `sys/users` should be disable by default, addpkg should works by default +# should be disable by default, addpkg should works by default # check is sys/users is disable +# gui call -> sys/users.IsEnable gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test gui stdout 'OK!' stdout 'false' # gui sould be able to addpkg on test1 addr +# gui addpkg -> gno.land/r//mysuperpkg gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/mysuperpkg -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stdout 'OK!' # gui sould be able to addpkg on random name +# gui addpkg -> gno.land/r/randomname/mysuperpkg gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/randomname/mysuperpkg -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stdout 'OK!' -gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/myfirstpkg -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui -stdout 'OK!' - -## When Enable +## When `sys/users` is Enable # enable users +# admin call -> sys/users.AdminEnable gnokey maketx call -pkgpath gno.land/r/sys/users -func AdminEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test admin stdout 'OK!' # check that sys/users as been enable -gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test admin +# gui call -> sys/users.IsEnable +gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test gui stdout 'OK!' stdout 'true' # try to add a pkg with unregistered user +# gui addpkg -> gno.land/r//one ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stderr 'unauthorized user' # try to add a pkg with unregistered user, on their own address as namespace +# gui addpkg -> gno.land/r//one gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_gui/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stdout 'OK!' ## test unregistered namespace +# call addpkg with admin user on gui namespace +# admin addpkg -> gno.land/r/guiland/one ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test admin stderr 'unauthorized user' ## test registered namespace # test admin invite gui +# admin call -> demo/users.Invite gnokey maketx call -pkgpath gno.land/r/demo/users -func Invite -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_gui admin stdout 'OK!' # test gui register namespace +# gui call -> demo/users.Register gnokey maketx call -pkgpath gno.land/r/demo/users -func Register -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_admin -args 'guiland' -args 'im gui' gui stdout 'OK!' # test gui pushing on guiland/one +# gui addpkg -> gno.land/r/guiland/one gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stdout 'OK!' # test admin pushing on guiland/two +# admin addpkg -> gno.land/r/guiland/one ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/two -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test admin stderr 'unauthorized user' - -- one.gno -- package one diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index ebc71289bfa..7c9d9b3563e 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -341,7 +341,8 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { fmt.Fprintf(ts.Stdout(), "Added %s(%s) to genesis", args[0], balance.Address) }, // `replace` will replace all occurences of the first argument with the second - // argument of any loaded files + // argument of any loaded files. + // This is mostly use to replace hardcoded address inside txtar file. "replace": func(ts *testscript.TestScript, neg bool, args []string) { args, err := unquote(args) if err != nil { From 122d7d4e56f3c67f679885866e8222f863140f32 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 8 Jul 2024 09:40:35 +0200 Subject: [PATCH 36/64] chore: use patchpkg instead of replace Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar | 10 +++++----- gno.land/pkg/integration/doc.go | 6 ++++++ .../testdata/{replace.txtar => patchpkg.txtar} | 0 gno.land/pkg/integration/testing_integration.go | 6 +++--- 4 files changed, 14 insertions(+), 8 deletions(-) rename gno.land/pkg/integration/testdata/{replace.txtar => patchpkg.txtar} (100%) diff --git a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar index 676d6b828d9..fcaee878d53 100644 --- a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar +++ b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar @@ -4,13 +4,13 @@ loadpkg gno.land/r/sys/users adduser admin adduser gui -replace "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" $USER_ADDR_admin # use our custom admin +patchpkg "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" $USER_ADDR_admin # use our custom admin gnoland start ## When `sys/users` is Disable -# should be disable by default, addpkg should works by default +# should be disable by default, addpkg should works by default # check is sys/users is disable # gui call -> sys/users.IsEnable @@ -30,12 +30,12 @@ stdout 'OK!' ## When `sys/users` is Enable -# enable users +# enable `sys/users` # admin call -> sys/users.AdminEnable gnokey maketx call -pkgpath gno.land/r/sys/users -func AdminEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test admin stdout 'OK!' -# check that sys/users as been enable +# check that `sys/users` as been enable # gui call -> sys/users.IsEnable gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test gui stdout 'OK!' @@ -76,7 +76,7 @@ gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000 stdout 'OK!' # test admin pushing on guiland/two -# admin addpkg -> gno.land/r/guiland/one +# admin addpkg -> gno.land/r/guiland/two ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/two -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test admin stderr 'unauthorized user' diff --git a/gno.land/pkg/integration/doc.go b/gno.land/pkg/integration/doc.go index bea0fe78349..9c779de0061 100644 --- a/gno.land/pkg/integration/doc.go +++ b/gno.land/pkg/integration/doc.go @@ -45,6 +45,12 @@ // - It's important to note that the load order is significant when using multiple `loadpkg` // command; packages should be loaded in the order they are dependent upon. // +// 6. `patchpkg`: +// - Patches any loaded files by package by replacing all occurrences of the first argument with the second. +// - This is mostly used to replace hardcoded addresses inside txtar files. +// - NOTE: this command may only be temporary, as it's not best approach to +// solve the above problem +// // Logging: // // Gnoland logs aren't forwarded to stdout to avoid overwhelming the tests with too much diff --git a/gno.land/pkg/integration/testdata/replace.txtar b/gno.land/pkg/integration/testdata/patchpkg.txtar similarity index 100% rename from gno.land/pkg/integration/testdata/replace.txtar rename to gno.land/pkg/integration/testdata/patchpkg.txtar diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index 7c9d9b3563e..731812febaa 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -340,10 +340,10 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { fmt.Fprintf(ts.Stdout(), "Added %s(%s) to genesis", args[0], balance.Address) }, - // `replace` will replace all occurences of the first argument with the second - // argument of any loaded files. + // `patchpkg` Patch any loaded files by packages by replacing all occurences of the + // first argument with the second. // This is mostly use to replace hardcoded address inside txtar file. - "replace": func(ts *testscript.TestScript, neg bool, args []string) { + "patchpkg": func(ts *testscript.TestScript, neg bool, args []string) { args, err := unquote(args) if err != nil { tsValidateError(ts, "replace", neg, err) From 07057f33e81ab5ffbcc5cec45f266800f2c0f349 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:53:12 +0200 Subject: [PATCH 37/64] chore: fix typo & update doc Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- docs/concepts/namespaces.md | 15 ++++++++++++++- gno.land/pkg/sdk/vm/keeper.go | 8 +++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/concepts/namespaces.md b/docs/concepts/namespaces.md index 74129697c88..5224c9a64da 100644 --- a/docs/concepts/namespaces.md +++ b/docs/concepts/namespaces.md @@ -6,7 +6,7 @@ id: namespaces Namespaces provide users with the exclusive capability to publish contracts under their designated namespaces, similar to GitHub's user and organization model. -This feature is currently a work in progress (WIP). To learn more about namespaces, please checkout https://github.com/gnolang/gno/issues/1107. +__NOTE__: This feature isn't enabled by default on the chain and is currently only enabled on gno.land. # Package Path @@ -33,3 +33,16 @@ Examples: - `gno.land/p/demo/avl`: This signifies a package named `avl` within the `demo` namespace. - `gno.land/r/gnoland/home`: This signifies a realm named `home` within the `gnoland` namespace. + +## Registration Process + +The registration process is contract-based. The `AddPkg` command references `sys/users` for filtering, which in turn is based on `r/demo/users`. + +When `sys/users` is enabled, you need to register a name using `r/demo/users`. This process requires an `Invite`, after which you can call the `r/demo/users.Register` function to register the name for the caller's address. + +After successful registration, you can add a package under the registered namespace. + +## Anonymous Namespace + +Gno.land offers the ability to add a package without having a registered namespace. +You can do this by using the user's own address as a namespace. This is formatted as `{p,r}/{std.Address}/**`. diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 07012fdcc03..8d8f0ca2a1a 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -251,7 +251,6 @@ func (vm *VMKeeper) getGnoStore(ctx sdk.Context) gno.Store { } // Namespace can be either a user or crypto address. -// XXX: Uppercase should be valid but transform into lowercase ? var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([a-zA-Z]+[_a-zA-Z0-9]+)`) // checkNamespacePermission check if the user as given has correct permssion to on the given pkg path @@ -264,6 +263,13 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add pkgPath = path.Clean(pkgPath) // cleanup pkgpath match := reNamespace.FindStringSubmatch(pkgPath) + switch len(match) { + case 0: + return ErrInvalidPkgPath(pkgPath) // no match + case 2: // ok + default: + panic("invalid pattern while matching pkgpath") + } if len(match) != 2 { return ErrInvalidPkgPath(pkgPath) } From a52963284f4bf8c57feb2e1735d41a8e7d46e1f9 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 8 Jul 2024 15:17:00 +0200 Subject: [PATCH 38/64] feat: update user register fee to 20gnot Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/demo/users/users.gno | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/gno.land/r/demo/users/users.gno b/examples/gno.land/r/demo/users/users.gno index 90886d134fb..05ce5e1c8c7 100644 --- a/examples/gno.land/r/demo/users/users.gno +++ b/examples/gno.land/r/demo/users/users.gno @@ -15,12 +15,12 @@ import ( var ( admin std.Address = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" - name2User avl.Tree // Name -> *users.User - addr2User avl.Tree // std.Address -> *users.User - invites avl.Tree // string(inviter+":"+invited) -> true - counter int // user id counter - minFee int64 = 200 * 1000000 // minimum gnot must be paid to register. - maxFeeMult int64 = 10 // maximum multiples of minFee accepted. + name2User avl.Tree // Name -> *users.User + addr2User avl.Tree // std.Address -> *users.User + invites avl.Tree // string(inviter+":"+invited) -> true + counter int // user id counter + minFee int64 = 20 * 1_000_000 // minimum gnot must be paid to register. + maxFeeMult int64 = 10 // maximum multiples of minFee accepted. ) //---------------------------------------- From f798e3f97bc3e91c48cdd2dbec46da082b7e6ac5 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 8 Jul 2024 15:22:52 +0200 Subject: [PATCH 39/64] chore: lint Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- .../pkg/integration/testing_integration.go | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index 731812febaa..0462b0c7639 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -340,22 +340,22 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { fmt.Fprintf(ts.Stdout(), "Added %s(%s) to genesis", args[0], balance.Address) }, - // `patchpkg` Patch any loaded files by packages by replacing all occurences of the + // `patchpkg` Patch any loaded files by packages by replacing all occurrences of the // first argument with the second. // This is mostly use to replace hardcoded address inside txtar file. "patchpkg": func(ts *testscript.TestScript, neg bool, args []string) { args, err := unquote(args) if err != nil { - tsValidateError(ts, "replace", neg, err) + tsValidateError(ts, "patchpkg", neg, err) } if len(args) != 2 { - ts.Fatalf("`replace`: should have exactly 2 arguments") + ts.Fatalf("`patchpkg`: should have exactly 2 arguments") } pkgs := ts.Value(envKeyPkgsLoader).(*pkgsLoader) replace, with := args[0], args[1] - pkgs.SetReplace(replace, with) + pkgs.SetPatch(replace, with) }, // `loadpkg` load a specific package from the 'examples' or working directory. "loadpkg": func(ts *testscript.TestScript, neg bool, args []string) { @@ -594,16 +594,16 @@ type pkgsLoader struct { pkgs []gnomod.Pkg visited map[string]struct{} - // list of occurences to replaces with the given value + // list of occurrences to patchs with the given value // XXX: find a better way - replaces map[string]string + patchs map[string]string } func newPkgsLoader() *pkgsLoader { return &pkgsLoader{ - pkgs: make([]gnomod.Pkg, 0), - visited: make(map[string]struct{}), - replaces: make(map[string]string), + pkgs: make([]gnomod.Pkg, 0), + visited: make(map[string]struct{}), + patchs: make(map[string]string), } } @@ -611,8 +611,8 @@ func (pl *pkgsLoader) List() gnomod.PkgList { return pl.pkgs } -func (pl *pkgsLoader) SetReplace(replace, with string) { - pl.replaces[replace] = with +func (pl *pkgsLoader) SetPatch(replace, with string) { + pl.patchs[replace] = with } func (pl *pkgsLoader) LoadPackages(creator bft.Address, fee std.Fee, deposit std.Coins) ([]std.Tx, error) { @@ -629,7 +629,7 @@ func (pl *pkgsLoader) LoadPackages(creator bft.Address, fee std.Fee, deposit std } // If any replace value is specified, apply them - if len(pl.replaces) > 0 { + if len(pl.patchs) > 0 { for _, msg := range tx.Msgs { addpkg, ok := msg.(vm.MsgAddPackage) if !ok { @@ -641,7 +641,7 @@ func (pl *pkgsLoader) LoadPackages(creator bft.Address, fee std.Fee, deposit std } for _, file := range addpkg.Package.Files { - for replace, with := range pl.replaces { + for replace, with := range pl.patchs { file.Body = strings.ReplaceAll(file.Body, replace, with) } } From 8873d15699f75d8819d65425fd4a8449d45e15a2 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Mon, 8 Jul 2024 15:25:28 +0200 Subject: [PATCH 40/64] chore: doc Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- gno.land/pkg/integration/doc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gno.land/pkg/integration/doc.go b/gno.land/pkg/integration/doc.go index 9c779de0061..2b6d24c23b8 100644 --- a/gno.land/pkg/integration/doc.go +++ b/gno.land/pkg/integration/doc.go @@ -47,7 +47,7 @@ // // 6. `patchpkg`: // - Patches any loaded files by package by replacing all occurrences of the first argument with the second. -// - This is mostly used to replace hardcoded addresses inside txtar files. +// - This is mostly used to replace hardcoded addresses from loaded packages. // - NOTE: this command may only be temporary, as it's not best approach to // solve the above problem // From 0dd8e21a3f03b7ce4171bafd6ae935c0bd82c4bb Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 09:32:40 +0200 Subject: [PATCH 41/64] feat: add preregister users/restricted Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- .../gno.land/r/demo/users/preregister.gno | 70 +++++++++++++++++++ examples/gno.land/r/demo/users/users.gno | 55 ++++++++++++--- .../gno.land/r/demo/users/z_11_filetest.gno | 23 ++++++ .../gno.land/r/demo/users/z_11b_filetest.gno | 28 ++++++++ 4 files changed, 168 insertions(+), 8 deletions(-) create mode 100644 examples/gno.land/r/demo/users/preregister.gno create mode 100644 examples/gno.land/r/demo/users/z_11_filetest.gno create mode 100644 examples/gno.land/r/demo/users/z_11b_filetest.gno diff --git a/examples/gno.land/r/demo/users/preregister.gno b/examples/gno.land/r/demo/users/preregister.gno new file mode 100644 index 00000000000..02ae52dbf5f --- /dev/null +++ b/examples/gno.land/r/demo/users/preregister.gno @@ -0,0 +1,70 @@ +package users + +import ( + "std" + + "gno.land/p/demo/users" +) + +// pre-restricted name +var preRestrictedNames = []string{ + "bitcoin", "cosmos", "newtendermint", "administrator", "ethereum", "allinbits", +} + +var preRegisteredUsers = []struct { + Name string + Address std.Address +}{ + // system name + {"archives", "g1xlnyjrnf03ju82v0f98ruhpgnquk28knmjfe5k"}, // -> @r_archives + {"demo", "g13ek2zz9qurzynzvssyc4sthwppnruhnp0gdz8n"}, // -> @r_demo + {"gno", "g19602kd9tfxrfd60sgreadt9zvdyyuudcyxsz8a"}, // -> @r_gno + {"gnoland", "g1g3lsfxhvaqgdv4ccemwpnms4fv6t3aq3p5z6u7"}, // -> @r_gnoland + {"gnolang", "g1yjlnm3z2630gg5mryjd79907e0zx658wxs9hnd"}, // -> @r_gnolang + {"gov", "g1g73v2anukg4ej7axwqpthsatzrxjsh0wk797da"}, // -> @r_gov + {"nt", "g15ge0ae9077eh40erwrn2eq0xw6wupwqthpv34l"}, // -> @r_nt + {"sys", "g1r929wt2qplfawe4lvqv9zuwfdcz4vxdun7qh8l"}, // -> @r_sys + {"x", "g164sdpew3c2t3rvxj3kmfv7c7ujlvcw2punzzuz"}, // -> @r_x + + // famous name + {"test1", "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"}, // -> @test1 + {"jaekwon", "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj"}, // -> @jae + {"manfred", "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq"}, // -> @moul +} + +func init() { + // add pre-registered users + for _, res := range preRegisteredUsers { + // assert not already registered. + _, ok := name2User.Get(res.Name) + if ok { + panic("name already registered") + } + + _, ok = addr2User.Get(res.Address.String()) + if ok { + panic("address already registered") + } + + counter++ + user := &users.User{ + Address: res.Address, + Name: res.Name, + Profile: "", + Number: counter, + Invites: int(0), + Inviter: admin, + } + name2User.Set(res.Name, user) + addr2User.Set(res.Address.String(), user) + } + + // add pre-restricted names + for _, name := range preRestrictedNames { + if _, ok := name2User.Get(name); ok { + panic("name already registered") + } + + restricted.Set(name, true) + } +} diff --git a/examples/gno.land/r/demo/users/users.gno b/examples/gno.land/r/demo/users/users.gno index 05ce5e1c8c7..191eb81a84f 100644 --- a/examples/gno.land/r/demo/users/users.gno +++ b/examples/gno.land/r/demo/users/users.gno @@ -14,13 +14,15 @@ import ( // State var ( - admin std.Address = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" - name2User avl.Tree // Name -> *users.User - addr2User avl.Tree // std.Address -> *users.User - invites avl.Tree // string(inviter+":"+invited) -> true - counter int // user id counter - minFee int64 = 20 * 1_000_000 // minimum gnot must be paid to register. - maxFeeMult int64 = 10 // maximum multiples of minFee accepted. + admin std.Address = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // @jae + + restricted avl.Tree // Name -> true - restricted name + name2User avl.Tree // Name -> *users.User + addr2User avl.Tree // std.Address -> *users.User + invites avl.Tree // string(inviter+":"+invited) -> true + counter int // user id counter + minFee int64 = 20 * 1_000_000 // minimum gnot must be paid to register. + maxFeeMult int64 = 10 // maximum multiples of minFee accepted. ) //---------------------------------------- @@ -34,8 +36,10 @@ func Register(inviter std.Address, name string, profile string) { if caller != std.GetOrigCaller() { panic("should not happen") // because std.AssertOrigCall(). } + sentCoins := std.GetOrigSend() minCoin := std.NewCoin("ugnot", minFee) + if inviter == "" { // banker := std.GetBanker(std.BankerTypeOrigSend) if len(sentCoins) == 1 && sentCoins[0].IsGTE(minCoin) { @@ -55,6 +59,17 @@ func Register(inviter std.Address, name string, profile string) { } invites.Remove(invitekey) } + + // check for restricted name + if _, isRestricted := restricted.Get(name); isRestricted { + // only name invite by the admin can register restricted name + if inviter != admin { + panic("restricted name") + } + + restricted.Remove(name) + } + // assert not already registered. _, ok := name2User.Get(name) if ok { @@ -64,8 +79,11 @@ func Register(inviter std.Address, name string, profile string) { if ok { panic("address already registered") } + // assert name is valid. - if !reName.MatchString(name) { + // admin can bypass name restriction + isAdmin := caller == admin + if !isAdmin && !reName.MatchString(name) { panic("invalid name: " + name + " (must be at least 6 characters, lowercase alphanumeric with underscore)") } // remainder of fees go toward invites. @@ -245,6 +263,27 @@ func Resolve(input users.AddressOrName) std.Address { return user.Address } +// Add restricted name to the list of +func AdminAddRestrictedName(name string) { + // assert admin + + // assert CallTx call. + std.AssertOriginCall() + // get caller + caller := std.GetOrigCaller() + if caller != admin { + panic("unauthorized") + } + + if user := GetUserByName(name); user != nil { + panic("already registered name") + } + + // register restricted name + + restricted.Set(name, true) +} + //---------------------------------------- // Constants diff --git a/examples/gno.land/r/demo/users/z_11_filetest.gno b/examples/gno.land/r/demo/users/z_11_filetest.gno new file mode 100644 index 00000000000..7ef903bbd06 --- /dev/null +++ b/examples/gno.land/r/demo/users/z_11_filetest.gno @@ -0,0 +1,23 @@ +package main + +// SEND: 200000000ugnot + +import ( + "std" + + "gno.land/r/demo/users" +) + +const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") + +func main() { + std.TestSetOrigCaller(admin) + users.AdminAddRestrictedName("superrestricted") + + // test restricted name + users.Register("", "superrestricted", "my profile") + println("done") +} + +// Error: +// restricted name diff --git a/examples/gno.land/r/demo/users/z_11b_filetest.gno b/examples/gno.land/r/demo/users/z_11b_filetest.gno new file mode 100644 index 00000000000..9e04479d8a6 --- /dev/null +++ b/examples/gno.land/r/demo/users/z_11b_filetest.gno @@ -0,0 +1,28 @@ +package main + +// SEND: 200000000ugnot + +import ( + "std" + + "gno.land/r/demo/users" +) + +const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") + +func main() { + caller := std.GetOrigCaller() // main + std.TestSetOrigCaller(admin) + // add restricted name + users.AdminAddRestrictedName("superrestricted") + // grant invite to caller + users.Invite(caller.String()) + // set back caller + std.TestSetOrigCaller(caller) + // register restricted name with admin invite + users.Register(admin, "superrestricted", "my profile") + println("done") +} + +// Output: +// done From c03dab47f798f5dd07efb3823067cd210345c0dc Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 09:44:42 +0200 Subject: [PATCH 42/64] chore: typo Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/demo/users/preregister.gno | 2 +- examples/gno.land/r/demo/users/users.gno | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/r/demo/users/preregister.gno b/examples/gno.land/r/demo/users/preregister.gno index 02ae52dbf5f..ad6e64f661f 100644 --- a/examples/gno.land/r/demo/users/preregister.gno +++ b/examples/gno.land/r/demo/users/preregister.gno @@ -8,7 +8,7 @@ import ( // pre-restricted name var preRestrictedNames = []string{ - "bitcoin", "cosmos", "newtendermint", "administrator", "ethereum", "allinbits", + "bitcoin", "cosmos", "newtendermint", "administrator", "ethereum", } var preRegisteredUsers = []struct { diff --git a/examples/gno.land/r/demo/users/users.gno b/examples/gno.land/r/demo/users/users.gno index 191eb81a84f..f97c022ec1a 100644 --- a/examples/gno.land/r/demo/users/users.gno +++ b/examples/gno.land/r/demo/users/users.gno @@ -60,6 +60,8 @@ func Register(inviter std.Address, name string, profile string) { invites.Remove(invitekey) } + isAdmin := caller == admin + // check for restricted name if _, isRestricted := restricted.Get(name); isRestricted { // only name invite by the admin can register restricted name @@ -82,7 +84,6 @@ func Register(inviter std.Address, name string, profile string) { // assert name is valid. // admin can bypass name restriction - isAdmin := caller == admin if !isAdmin && !reName.MatchString(name) { panic("invalid name: " + name + " (must be at least 6 characters, lowercase alphanumeric with underscore)") } From 45ed16d2aff96afa39724d299a2bd72de718dd6f Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 09:52:41 +0200 Subject: [PATCH 43/64] fix: small adjustement Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- .../gno.land/r/demo/users/preregister.gno | 3 +- examples/gno.land/r/demo/users/users.gno | 31 ++++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/examples/gno.land/r/demo/users/preregister.gno b/examples/gno.land/r/demo/users/preregister.gno index ad6e64f661f..b5cb71b4c8c 100644 --- a/examples/gno.land/r/demo/users/preregister.gno +++ b/examples/gno.land/r/demo/users/preregister.gno @@ -6,11 +6,12 @@ import ( "gno.land/p/demo/users" ) -// pre-restricted name +// pre-restricted names var preRestrictedNames = []string{ "bitcoin", "cosmos", "newtendermint", "administrator", "ethereum", } +// pre-registered users var preRegisteredUsers = []struct { Name string Address std.Address diff --git a/examples/gno.land/r/demo/users/users.gno b/examples/gno.land/r/demo/users/users.gno index f97c022ec1a..b08b32aff94 100644 --- a/examples/gno.land/r/demo/users/users.gno +++ b/examples/gno.land/r/demo/users/users.gno @@ -60,18 +60,6 @@ func Register(inviter std.Address, name string, profile string) { invites.Remove(invitekey) } - isAdmin := caller == admin - - // check for restricted name - if _, isRestricted := restricted.Get(name); isRestricted { - // only name invite by the admin can register restricted name - if inviter != admin { - panic("restricted name") - } - - restricted.Remove(name) - } - // assert not already registered. _, ok := name2User.Get(name) if ok { @@ -82,11 +70,24 @@ func Register(inviter std.Address, name string, profile string) { panic("address already registered") } + isInviterAdmin := inviter != admin + + // check for restricted name + if _, isRestricted := restricted.Get(name); isRestricted { + // only address invite by the admin can register restricted name + if !isInviterAdmin { + panic("restricted name") + } + + restricted.Remove(name) + } + // assert name is valid. - // admin can bypass name restriction - if !isAdmin && !reName.MatchString(name) { + // admin inviter can bypass name restriction + if !isInviterAdmin && !reName.MatchString(name) { panic("invalid name: " + name + " (must be at least 6 characters, lowercase alphanumeric with underscore)") } + // remainder of fees go toward invites. invites := int(0) if len(sentCoins) == 1 { @@ -264,7 +265,7 @@ func Resolve(input users.AddressOrName) std.Address { return user.Address } -// Add restricted name to the list of +// Add restricted name to the list func AdminAddRestrictedName(name string) { // assert admin From e63ec479a3349acb857905619019402d455a42f2 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 09:59:29 +0200 Subject: [PATCH 44/64] chore: fix tests Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/demo/users/users.gno | 2 +- .../gno.land/r/demo/users/z_0_b_filetest.gno | 4 ++-- examples/gno.land/r/demo/users/z_11_filetest.gno | 2 ++ examples/gno.land/r/demo/users/z_1_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_2_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_3_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_4_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_5_filetest.gno | 16 ++++++++++++++-- examples/gno.land/r/demo/users/z_7_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_7b_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_8_filetest.gno | 2 +- 11 files changed, 26 insertions(+), 12 deletions(-) diff --git a/examples/gno.land/r/demo/users/users.gno b/examples/gno.land/r/demo/users/users.gno index b08b32aff94..8f3dce8d6b5 100644 --- a/examples/gno.land/r/demo/users/users.gno +++ b/examples/gno.land/r/demo/users/users.gno @@ -70,7 +70,7 @@ func Register(inviter std.Address, name string, profile string) { panic("address already registered") } - isInviterAdmin := inviter != admin + isInviterAdmin := inviter == admin // check for restricted name if _, isRestricted := restricted.Get(name); isRestricted { diff --git a/examples/gno.land/r/demo/users/z_0_b_filetest.gno b/examples/gno.land/r/demo/users/z_0_b_filetest.gno index 9095057076c..c33edc32985 100644 --- a/examples/gno.land/r/demo/users/z_0_b_filetest.gno +++ b/examples/gno.land/r/demo/users/z_0_b_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 199000000ugnot +// SEND: 19900000ugnot import ( "gno.land/r/demo/users" @@ -12,4 +12,4 @@ func main() { } // Error: -// payment must not be less than 200000000 +// payment must not be less than 20000000 diff --git a/examples/gno.land/r/demo/users/z_11_filetest.gno b/examples/gno.land/r/demo/users/z_11_filetest.gno index 7ef903bbd06..067d019bcb7 100644 --- a/examples/gno.land/r/demo/users/z_11_filetest.gno +++ b/examples/gno.land/r/demo/users/z_11_filetest.gno @@ -11,10 +11,12 @@ import ( const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") func main() { + caller := std.GetOrigCaller() // main std.TestSetOrigCaller(admin) users.AdminAddRestrictedName("superrestricted") // test restricted name + std.TestSetOrigCaller(caller) users.Register("", "superrestricted", "my profile") println("done") } diff --git a/examples/gno.land/r/demo/users/z_1_filetest.gno b/examples/gno.land/r/demo/users/z_1_filetest.gno index a1c7e682022..504a0c7c3f9 100644 --- a/examples/gno.land/r/demo/users/z_1_filetest.gno +++ b/examples/gno.land/r/demo/users/z_1_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "gno.land/r/demo/users" diff --git a/examples/gno.land/r/demo/users/z_2_filetest.gno b/examples/gno.land/r/demo/users/z_2_filetest.gno index a99e8fd12ee..4e1bc49832c 100644 --- a/examples/gno.land/r/demo/users/z_2_filetest.gno +++ b/examples/gno.land/r/demo/users/z_2_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "std" diff --git a/examples/gno.land/r/demo/users/z_3_filetest.gno b/examples/gno.land/r/demo/users/z_3_filetest.gno index 1cd3886152a..7a75aa057b3 100644 --- a/examples/gno.land/r/demo/users/z_3_filetest.gno +++ b/examples/gno.land/r/demo/users/z_3_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "std" diff --git a/examples/gno.land/r/demo/users/z_4_filetest.gno b/examples/gno.land/r/demo/users/z_4_filetest.gno index 51bd255e3e7..07d6d8b32d2 100644 --- a/examples/gno.land/r/demo/users/z_4_filetest.gno +++ b/examples/gno.land/r/demo/users/z_4_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "std" diff --git a/examples/gno.land/r/demo/users/z_5_filetest.gno b/examples/gno.land/r/demo/users/z_5_filetest.gno index 5a96eec5322..413acf3f461 100644 --- a/examples/gno.land/r/demo/users/z_5_filetest.gno +++ b/examples/gno.land/r/demo/users/z_5_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "std" @@ -36,8 +36,20 @@ func main() { } // Output: -// * [gnouser](/r/demo/users:gnouser) +// * [archives](/r/demo/users:archives) +// * [demo](/r/demo/users:demo) +// * [gno](/r/demo/users:gno) +// * [gnoland](/r/demo/users:gnoland) +// * [gnolang](/r/demo/users:gnolang) +// * [gnouser](/r/demo/users:gnouser) +// * [gov](/r/demo/users:gov) +// * [jaekwon](/r/demo/users:jaekwon) +// * [manfred](/r/demo/users:manfred) +// * [nt](/r/demo/users:nt) // * [satoshi](/r/demo/users:satoshi) +// * [sys](/r/demo/users:sys) +// * [test1](/r/demo/users:test1) +// * [x](/r/demo/users:x) // // ======================================== // ## user gnouser diff --git a/examples/gno.land/r/demo/users/z_7_filetest.gno b/examples/gno.land/r/demo/users/z_7_filetest.gno index 60efc3b91ea..98b1694c3eb 100644 --- a/examples/gno.land/r/demo/users/z_7_filetest.gno +++ b/examples/gno.land/r/demo/users/z_7_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "std" diff --git a/examples/gno.land/r/demo/users/z_7b_filetest.gno b/examples/gno.land/r/demo/users/z_7b_filetest.gno index 81f1076b3d1..27a8420d531 100644 --- a/examples/gno.land/r/demo/users/z_7b_filetest.gno +++ b/examples/gno.land/r/demo/users/z_7b_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "std" diff --git a/examples/gno.land/r/demo/users/z_8_filetest.gno b/examples/gno.land/r/demo/users/z_8_filetest.gno index 56c13862257..3c35cf21e71 100644 --- a/examples/gno.land/r/demo/users/z_8_filetest.gno +++ b/examples/gno.land/r/demo/users/z_8_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "std" From eec6db9dfe72c48d1ba7d97b086b12672c12a3fd Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 11:27:59 +0200 Subject: [PATCH 45/64] fix: edit min fee Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/demo/boards/z_0_b_filetest.gno | 4 ++-- examples/gno.land/r/demo/boards/z_0_filetest.gno | 2 +- examples/gno.land/r/demo/boards/z_10_b_filetest.gno | 2 +- examples/gno.land/r/demo/boards/z_11_a_filetest.gno | 2 +- examples/gno.land/r/demo/boards/z_11_b_filetest.gno | 2 +- examples/gno.land/r/demo/boards/z_11_c_filetest.gno | 2 +- examples/gno.land/r/demo/boards/z_11_d_filetest.gno | 2 +- examples/gno.land/r/demo/boards/z_11_filetest.gno | 2 +- examples/gno.land/r/demo/boards/z_5_b_filetest.gno | 2 +- examples/gno.land/r/demo/boards/z_5_c_filetest.gno | 2 +- examples/gno.land/r/demo/boards/z_5_d_filetest.gno | 2 +- examples/gno.land/r/demo/boards/z_7_filetest.gno | 2 +- examples/gno.land/r/demo/boards/z_8_filetest.gno | 2 +- gno.land/genesis/genesis_txs.jsonl | 10 +++++----- 14 files changed, 19 insertions(+), 19 deletions(-) diff --git a/examples/gno.land/r/demo/boards/z_0_b_filetest.gno b/examples/gno.land/r/demo/boards/z_0_b_filetest.gno index 5405a2508ec..9bcbe9ffafa 100644 --- a/examples/gno.land/r/demo/boards/z_0_b_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_0_b_filetest.gno @@ -1,7 +1,7 @@ // PKGPATH: gno.land/r/demo/boards_test package boards_test -// SEND: 199000000ugnot +// SEND: 19900000ugnot import ( "gno.land/r/demo/boards" @@ -20,4 +20,4 @@ func main() { } // Error: -// payment must not be less than 200000000 +// payment must not be less than 20000000 diff --git a/examples/gno.land/r/demo/boards/z_0_filetest.gno b/examples/gno.land/r/demo/boards/z_0_filetest.gno index 1debeecba04..e20964d50b7 100644 --- a/examples/gno.land/r/demo/boards/z_0_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_0_filetest.gno @@ -1,7 +1,7 @@ // PKGPATH: gno.land/r/demo/boards_test package boards_test -// SEND: 200000000ugnot +// SEND: 20000000ugnot import ( "gno.land/r/demo/boards" diff --git a/examples/gno.land/r/demo/boards/z_10_b_filetest.gno b/examples/gno.land/r/demo/boards/z_10_b_filetest.gno index 58ecbecabdf..cf8a332174f 100644 --- a/examples/gno.land/r/demo/boards/z_10_b_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_10_b_filetest.gno @@ -1,7 +1,7 @@ // PKGPATH: gno.land/r/demo/boards_test package boards_test -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "strconv" diff --git a/examples/gno.land/r/demo/boards/z_11_a_filetest.gno b/examples/gno.land/r/demo/boards/z_11_a_filetest.gno index 50bcfac355c..d7dc7b90782 100644 --- a/examples/gno.land/r/demo/boards/z_11_a_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_11_a_filetest.gno @@ -1,7 +1,7 @@ // PKGPATH: gno.land/r/demo/boards_test package boards_test -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "strconv" diff --git a/examples/gno.land/r/demo/boards/z_11_b_filetest.gno b/examples/gno.land/r/demo/boards/z_11_b_filetest.gno index 9a067f5aac5..3aa28095502 100644 --- a/examples/gno.land/r/demo/boards/z_11_b_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_11_b_filetest.gno @@ -1,7 +1,7 @@ // PKGPATH: gno.land/r/demo/boards_test package boards_test -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "strconv" diff --git a/examples/gno.land/r/demo/boards/z_11_c_filetest.gno b/examples/gno.land/r/demo/boards/z_11_c_filetest.gno index 524b626ff6d..df764303562 100644 --- a/examples/gno.land/r/demo/boards/z_11_c_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_11_c_filetest.gno @@ -1,7 +1,7 @@ // PKGPATH: gno.land/r/demo/boards_test package boards_test -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "strconv" diff --git a/examples/gno.land/r/demo/boards/z_11_d_filetest.gno b/examples/gno.land/r/demo/boards/z_11_d_filetest.gno index 33e6ca1eea9..c114e769ab1 100644 --- a/examples/gno.land/r/demo/boards/z_11_d_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_11_d_filetest.gno @@ -1,7 +1,7 @@ // PKGPATH: gno.land/r/demo/boards_test package boards_test -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "strconv" diff --git a/examples/gno.land/r/demo/boards/z_11_filetest.gno b/examples/gno.land/r/demo/boards/z_11_filetest.gno index 9e85b8ace8c..4cbdeeca4c3 100644 --- a/examples/gno.land/r/demo/boards/z_11_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_11_filetest.gno @@ -1,7 +1,7 @@ // PKGPATH: gno.land/r/demo/boards_test package boards_test -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "strconv" diff --git a/examples/gno.land/r/demo/boards/z_5_b_filetest.gno b/examples/gno.land/r/demo/boards/z_5_b_filetest.gno index 105c7f19ef7..e79da5c3677 100644 --- a/examples/gno.land/r/demo/boards/z_5_b_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_5_b_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "std" diff --git a/examples/gno.land/r/demo/boards/z_5_c_filetest.gno b/examples/gno.land/r/demo/boards/z_5_c_filetest.gno index bb9d7a57010..176b1d89015 100644 --- a/examples/gno.land/r/demo/boards/z_5_c_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_5_c_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "std" diff --git a/examples/gno.land/r/demo/boards/z_5_d_filetest.gno b/examples/gno.land/r/demo/boards/z_5_d_filetest.gno index e54ac578dc1..54cfe49eec6 100644 --- a/examples/gno.land/r/demo/boards/z_5_d_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_5_d_filetest.gno @@ -1,6 +1,6 @@ package main -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "std" diff --git a/examples/gno.land/r/demo/boards/z_7_filetest.gno b/examples/gno.land/r/demo/boards/z_7_filetest.gno index 7a6b4d89eec..f1d41aa1723 100644 --- a/examples/gno.land/r/demo/boards/z_7_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_7_filetest.gno @@ -1,7 +1,7 @@ // PKGPATH: gno.land/r/demo/boards_test package boards_test -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "gno.land/r/demo/boards" diff --git a/examples/gno.land/r/demo/boards/z_8_filetest.gno b/examples/gno.land/r/demo/boards/z_8_filetest.gno index e7f94a78746..18ad64083f4 100644 --- a/examples/gno.land/r/demo/boards/z_8_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_8_filetest.gno @@ -1,7 +1,7 @@ // PKGPATH: gno.land/r/demo/boards_test package boards_test -// SEND: 2000000000ugnot +// SEND: 200000000ugnot import ( "strconv" diff --git a/gno.land/genesis/genesis_txs.jsonl b/gno.land/genesis/genesis_txs.jsonl index 278055711b0..026dd1040b3 100644 --- a/gno.land/genesis/genesis_txs.jsonl +++ b/gno.land/genesis/genesis_txs.jsonl @@ -1,12 +1,12 @@ {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s:1\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8:1\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q:1\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj:1\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0:1\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz:1\ng187982000zsc493znqt828s90cmp6hcp2erhu6m:1\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl:1\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037:1\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5:1\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr:1\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz:1\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w:1\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz:1\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3:1\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0:1\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n:1\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac:1\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap:1\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv:1\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv:1\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq:1\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6:1\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q:1\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7:1\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k:1\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll:1\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd:1\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64:1\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw:1\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a:1\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc:1\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6:1\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6:1\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9:1\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea:1\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3:1\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp:1\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5:1\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf:1\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g:1\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r:1\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su:1\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69:1\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6:1\ng1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq:10\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa:10\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t:5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"S8iMMzlOMK8dmox78R9Z8+pSsS8YaTCXrIcaHDpiOgkOy7gqoQJ0oftM0zf8zAz4xpezK8Lzg8Q0fCdXJxV76w=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1thlf3yct7n7ex70k0p62user0kn6mj6d3s0cg3\ng1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"njczE6xYdp01+CaUU/8/v0YC/NuZD06+qLind+ZZEEMNaRe/4Ln+4z7dG6HYlaWUMsyI1KCoB6NIehoE0PZ44Q=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz\ng187982000zsc493znqt828s90cmp6hcp2erhu6m\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6\ng1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t\n"]}],"fee":{"gas_wanted":"4000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"7AmlhZhsVkxCUl0bbpvpPMnIKihwtG7A5IFR6Tg4xStWLgaUr05XmWRKlO2xjstTtwbVKQT5mFL4h5wyX4SQzw=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"2000000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","administrator","g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"AqCqe0cS55Ym7/BvPDoCDyPP5q8284gecVQ2PMOlq/4lJpO9Q18SOWKI15dMEBY1pT0AYyhCeTirlsM1I3Y4Cg=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1qpymzwx4l4cy6cerdyajp9ksvjsf20rk5y9rtt","send":"2000000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","zo_oma","Love is the encryption key\u003c3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A6yg5/iiktruezVw5vZJwLlGwyrvw8RlqOToTRMWXkE2"},"signature":"GGp+bVL2eEvKecPqgcULSABYOSnSMnJzfIsR8ZIRER1GGX/fOiCReX4WKMrGLVROJVfbLQkDRwvhS4TLHlSoSQ=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"2000000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","manfred","https://github.com/moul"]}],"fee":{"gas_wanted":"2000000","gas_fee":"2000000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":"9CWeNbKx+hEL+RdHplAVAFntcrAVx5mK9tMqoywuHVoreH844n3yOxddQrGfBk6T2tMBmNWakERRqWZfS+bYAQ=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9","send":"2000000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","piupiu","@piux2"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"Ar68lqbU2YC63fbMcYUtJhYO3/66APM/EqF7m0nUjGyz"},"signature":"pTUpP0d/XlfVe3TH1hlaoLhKadzIKG1gtQ/Ueuat72p+659RWRea58Z0mk6GgPE/EeTbhMEY45zufevBdGJVoQ=="}],"memo":""} +{"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","administrator","g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"AqCqe0cS55Ym7/BvPDoCDyPP5q8284gecVQ2PMOlq/4lJpO9Q18SOWKI15dMEBY1pT0AYyhCeTirlsM1I3Y4Cg=="}],"memo":""} +{"msg":[{"@type":"/vm.m_call","caller":"g1qpymzwx4l4cy6cerdyajp9ksvjsf20rk5y9rtt","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","zo_oma","Love is the encryption key\u003c3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A6yg5/iiktruezVw5vZJwLlGwyrvw8RlqOToTRMWXkE2"},"signature":"GGp+bVL2eEvKecPqgcULSABYOSnSMnJzfIsR8ZIRER1GGX/fOiCReX4WKMrGLVROJVfbLQkDRwvhS4TLHlSoSQ=="}],"memo":""} +{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","manfred","https://github.com/moul"]}],"fee":{"gas_wanted":"2000000","gas_fee":"200000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":"9CWeNbKx+hEL+RdHplAVAFntcrAVx5mK9tMqoywuHVoreH844n3yOxddQrGfBk6T2tMBmNWakERRqWZfS+bYAQ=="}],"memo":""} +{"msg":[{"@type":"/vm.m_call","caller":"g1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","piupiu","@piux2"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"Ar68lqbU2YC63fbMcYUtJhYO3/66APM/EqF7m0nUjGyz"},"signature":"pTUpP0d/XlfVe3TH1hlaoLhKadzIKG1gtQ/Ueuat72p+659RWRea58Z0mk6GgPE/EeTbhMEY45zufevBdGJVoQ=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5","send":"","pkg_path":"gno.land/r/demo/users","func":"Register","args":["g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","anarcher","https://twitter.com/anarcher"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AjpLbKdQeH+yB/1OCB148l5GlRRrXma71hdA8EES3H7f"},"signature":"pf5xm8oWIQIOEwSGw4icPmynLXb1P1HxKfjeh8UStU1mlIBPKa7yppeIMPpAflC0o2zjFR7Axe7CimAebm3BHg=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g15gdm49ktawvkrl88jadqpucng37yxutucuwaef","send":"2000000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","ideamour","\u003c3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AhClx4AsDuX3DNCPxhDwWnrfd4MIZmxJE4vt47ClVvT2"},"signature":"IQe64af878k6HjLDqIJeg27GXAVF6xS+96cDe2jMlxNV6+8sOcuUctp0GiWVnYfN4tpthC6d4WhBo+VlpHqkbg=="}],"memo":""} +{"msg":[{"@type":"/vm.m_call","caller":"g15gdm49ktawvkrl88jadqpucng37yxutucuwaef","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","ideamour","\u003c3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AhClx4AsDuX3DNCPxhDwWnrfd4MIZmxJE4vt47ClVvT2"},"signature":"IQe64af878k6HjLDqIJeg27GXAVF6xS+96cDe2jMlxNV6+8sOcuUctp0GiWVnYfN4tpthC6d4WhBo+VlpHqkbg=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateBoard","args":["testboard"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"vzlSxEFh5jOkaSdv3rsV91v/OJKEF2qSuoCpri1u5tRWq62T7xr3KHRCF5qFnn4aQX/yE8g8f/Y//WPOCUGhJw=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","Hello World","This is a demo of Gno smart contract programming. This document was\nconstructed by Gno onto a smart contract hosted on the data Realm \nname [\"gno.land/r/demo/boards\"](https://gno.land/r/demo/boards/)\n([github](https://github.com/gnolang/gno/tree/master/examples/gno.land/r/demo/boards)).\n\n## Starting the `gnoland` node node/validator.\n\nNOTE: Where you see `--remote %%REMOTE%%` here, that flag can be replaced\nwith `--remote localhost:26657` for local testnets.\n\n### build gnoland.\n\n```bash\ngit clone git@github.com:gnolang/gno.git\ncd ./gno\nmake \n```\n\n### add test account.\n\n```bash\n./build/gnokey add test1 --recover\n```\n\nUse this mnemonic:\n\u003e source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast\n\n### start gnoland validator node.\n\n```bash\n./build/gnoland\n```\n\n(This can be reset with `make reset`).\n\n### start gnoland web server (optional).\n\n```bash\ngo run ./gnoland/website\n```\n\n## Signing and broadcasting transactions.\n\n### publish the \"gno.land/p/demo/avl\" package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/p/demo/avl\" --pkgdir \"examples/gno.land/p/demo/avl\" --deposit 100ugnot --gas-fee 1ugnot --gas-wanted 2000000 \u003e addpkg.avl.unsigned.txt\n./build/gnokey query \"auth/accounts/g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5\"\n./build/gnokey sign test1 --txpath addpkg.avl.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 0 \u003e addpkg.avl.signed.txt\n./build/gnokey broadcast addpkg.avl.signed.txt --remote %%REMOTE%%\n```\n\n### publish the \"gno.land/r/demo/boards\" realm package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/r/demo/boards\" --pkgdir \"examples/gno.land/r/demo/boards\" --deposit 100ugnot --gas-fee 1ugnot --gas-wanted 300000000 \u003e addpkg.boards.unsigned.txt\n./build/gnokey sign test1 --txpath addpkg.boards.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 1 \u003e addpkg.boards.signed.txt\n./build/gnokey broadcast addpkg.boards.signed.txt --remote %%REMOTE%%\n```\n\n### create a board with a smart contract call.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreateBoard --args \"testboard\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createboard.unsigned.txt\n./build/gnokey sign test1 --txpath createboard.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 2 \u003e createboard.signed.txt\n./build/gnokey broadcast createboard.signed.txt --remote %%REMOTE%%\n```\nNext, query for the permanent board ID by querying (you need this to create a new post):\n\n```bash\n./build/gnokey query \"vm/qeval\" --data \"gno.land/r/demo/boards.GetBoardIDFromName(\\\"testboard\\\")\"\n```\n\n### create a post of a board with a smart contract call.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreatePost --args 1 --args \"Hello World\" --args#file \"./examples/gno.land/r/demo/boards/README.md\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createpost.unsigned.txt\n./build/gnokey sign test1 --txpath createpost.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 3 \u003e createpost.signed.txt\n./build/gnokey broadcast createpost.signed.txt --remote %%REMOTE%%\n```\n\n### create a comment to a post.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreateReply --args 1 --args 1 --args \"A comment\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createcomment.unsigned.txt\n./build/gnokey sign test1 --txpath createcomment.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 4 \u003e createcomment.signed.txt\n./build/gnokey broadcast createcomment.signed.txt --remote %%REMOTE%%\n```\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:testboard/1\"\n```\n\n### render page with optional path expression.\n\nThe contents of `https://gno.land/r/demo/boards:` and `https://gno.land/r/demo/boards:testboard` are rendered by calling\nthe `Render(path string)` function like so:\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:testboard\"\n```\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"V43B1waFxhzheW9TfmCpjLdrC4dC1yjUGES5y3J6QsNar6hRpNz4G1thzWmWK7xXhg8u1PCIpxLxGczKQYhuPw=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","NFT example","NFT's are all the rage these days, for various reasons.\n\nI read over EIP-721 which appears to be the de-facto NFT standard on Ethereum. Then, made a sample implementation of EIP-721 (let's here called GRC-721). The implementation isn't complete, but it demonstrates the main functionality.\n\n - [EIP-721](https://eips.ethereum.org/EIPS/eip-721)\n - [gno.land/r/demo/nft/nft.gno](https://gno.land/r/demo/nft/nft.gno)\n - [zrealm_nft3.gno test](https://github.com/gnolang/gno/blob/master/examples/gno.land/r/demo/nft/z_3_filetest.gno)\n\nIn short, this demonstrates how to implement Ethereum contract interfaces in gno.land; by using only standard Go language features.\n\nPlease leave a comment ([guide](https://gno.land/r/demo/boards:testboard/1)).\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"ZXfrTiHxPFQL8uSm+Tv7WXIHPMca9okhm94RAlC6YgNbB1VHQYYpoP4w+cnL3YskVzGrOZxensXa9CAZ+cNNeg=="}],"memo":""} From 307810b1d0363dd804eb51d667a4afdff2d3518c Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:49:30 +0200 Subject: [PATCH 46/64] fix: test Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/demo/groups/z_0_b_filetest.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gno.land/r/demo/groups/z_0_b_filetest.gno b/examples/gno.land/r/demo/groups/z_0_b_filetest.gno index 49e4167ae1a..6d328825dd6 100644 --- a/examples/gno.land/r/demo/groups/z_0_b_filetest.gno +++ b/examples/gno.land/r/demo/groups/z_0_b_filetest.gno @@ -16,4 +16,4 @@ func main() { } // Error: -// payment must not be less than 200000000 +// payment must not be less than 20000000 From f50dfc6c28703e5035826999789f056f601f0d51 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:50:23 +0200 Subject: [PATCH 47/64] fix: users tidy Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/sys/users/gno.mod | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/gno.land/r/sys/users/gno.mod b/examples/gno.land/r/sys/users/gno.mod index 542999a54ed..da5d1ba8fcd 100644 --- a/examples/gno.land/r/sys/users/gno.mod +++ b/examples/gno.land/r/sys/users/gno.mod @@ -1 +1,3 @@ -module gno.land/r/sys/users \ No newline at end of file +module gno.land/r/sys/users + +require gno.land/r/demo/users v0.0.0-latest From 0799eec3e24e73cbaa07373739fcd5593b1e3a3a Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 13:04:37 +0200 Subject: [PATCH 48/64] chore: update typo warn Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- docs/concepts/namespaces.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/namespaces.md b/docs/concepts/namespaces.md index 5224c9a64da..139fc5588d9 100644 --- a/docs/concepts/namespaces.md +++ b/docs/concepts/namespaces.md @@ -6,7 +6,7 @@ id: namespaces Namespaces provide users with the exclusive capability to publish contracts under their designated namespaces, similar to GitHub's user and organization model. -__NOTE__: This feature isn't enabled by default on the chain and is currently only enabled on gno.land. +:::warn This feature isn't enabled by default on the chain and is currently only on test4.gno.land. # Package Path From 967aa650614c961282ba94c1bb7fe5a4ea81a7ea Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 13:21:46 +0200 Subject: [PATCH 49/64] fix: typo namespaces doc Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> Acked-by: gfanton <8671905+gfanton@users.noreply.github.com> --- docs/concepts/namespaces.md | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/docs/concepts/namespaces.md b/docs/concepts/namespaces.md index 139fc5588d9..9652a153ab4 100644 --- a/docs/concepts/namespaces.md +++ b/docs/concepts/namespaces.md @@ -4,13 +4,15 @@ id: namespaces # Namespaces -Namespaces provide users with the exclusive capability to publish contracts under their designated namespaces, similar to GitHub's user and organization model. +Namespaces provide users with the exclusive capability to publish contracts under their designated namespaces, +similar to GitHub's user and organization model. :::warn This feature isn't enabled by default on the chain and is currently only on test4.gno.land. # Package Path -A package path is a unique identifier for each package/realm. It specifies the location of the package source code which helps differentiate it from others. You can use a package path to: +A package path is a unique identifier for each package/realm. It specifies the location of the package source +code which helps differentiate it from others. You can use a package path to: - Call a specific function from a package/realm. (e.g using `gnokey maketx call`) - Import it in other packages/realms. @@ -21,7 +23,9 @@ Here's a breakdown of the structure of a package path: - Type: Defines the type of package. - `p/`: [Package](packages.md) - `r/`: [Realm](realms.md) -- Namespace: A namespace can be included after the type (e.g., user or organization name). Namespaces are a way to group related packages or realms, but currently ownership cannot be claimed. (see [Issue #1107](https://github.com/gnolang/gno/issues/1107) for more info) +- Namespace: A namespace can be included after the type (e.g., user or organization name). Namespaces are a + way to group related packages or realms, but currently ownership cannot be claimed. (see + [Issue#1107](https://github.com/gnolang/gno/issues/1107) for more info) - Remaining Path: The remaining part of the path. - Can only contain alphanumeric characters (letters and numbers) and underscores. - No special characters allowed (except underscore). @@ -36,9 +40,22 @@ Examples: ## Registration Process -The registration process is contract-based. The `AddPkg` command references `sys/users` for filtering, which in turn is based on `r/demo/users`. - -When `sys/users` is enabled, you need to register a name using `r/demo/users`. This process requires an `Invite`, after which you can call the `r/demo/users.Register` function to register the name for the caller's address. +The registration process is contract-based. The `AddPkg` command references +`sys/users` for filtering, which in turn is based on `r/demo/users`. + +When `sys/users` is enabled, you need to register a name using `r/demo/users`. You can call the +`r/demo/users.Register` function to register the name for the caller's address. + +```bash +$ gnokey maketx call -pkgpath gno.land/r/demo/users \ + -func Register \ + -gas-fee 1000000ugnot -gas-wanted 2000000 \ + -broadcast -chainid=dev \ + -send=20000000ugnot \ + -args '' # first argument + -args 'patrick' + -args 'My Profile Quote' test1 +``` After successful registration, you can add a package under the registered namespace. From 2578356d0609fd0b5bdb746d28ad7e2eff6bde01 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 13:50:01 +0200 Subject: [PATCH 50/64] chore: update gas deliver Signed-off-by: gfanton <8671905+gfanton@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 af4b869c73f..66655994bd4 100644 --- a/gno.land/pkg/sdk/vm/gas_test.go +++ b/gno.land/pkg/sdk/vm/gas_test.go @@ -69,7 +69,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(91825), gasDeliver) + assert.Equal(t, int64(92825), gasDeliver) } // Enough gas for a failed transaction. From cdd7ab294664c637546db83598ce884b0a6e3a9f Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:18:09 +0200 Subject: [PATCH 51/64] chore: fix typo Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- docs/concepts/namespaces.md | 26 ++++++++++++--- examples/gno.land/r/demo/users/users.gno | 3 +- examples/gno.land/r/sys/users/users.gno | 10 +++--- .../gnoland/testdata/addpkg_namespace.txtar | 32 +++++++++---------- 4 files changed, 44 insertions(+), 27 deletions(-) diff --git a/docs/concepts/namespaces.md b/docs/concepts/namespaces.md index 9652a153ab4..84161fd9ca0 100644 --- a/docs/concepts/namespaces.md +++ b/docs/concepts/namespaces.md @@ -46,20 +46,38 @@ The registration process is contract-based. The `AddPkg` command references When `sys/users` is enabled, you need to register a name using `r/demo/users`. You can call the `r/demo/users.Register` function to register the name for the caller's address. +> ex: `test1` user registering as `patrick` ```bash $ gnokey maketx call -pkgpath gno.land/r/demo/users \ -func Register \ -gas-fee 1000000ugnot -gas-wanted 2000000 \ - -broadcast -chainid=dev \ + -broadcast \ + -chainid=dev \ -send=20000000ugnot \ - -args '' # first argument - -args 'patrick' + -args '' \ + -args 'patrick' \ -args 'My Profile Quote' test1 ``` +:::note Do not forget to update chain id + + After successful registration, you can add a package under the registered namespace. ## Anonymous Namespace Gno.land offers the ability to add a package without having a registered namespace. -You can do this by using the user's own address as a namespace. This is formatted as `{p,r}/{std.Address}/**`. +You can do this by using your own address as a namespace. This is formatted as `{p,r}/{std.Address}/**`. + +> ex: with `test1` user adding a package `microblog` using his own address as namespace +```bash +$ gnokey maketx addpkg \ + --pkgpath "gno.land/r/g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5/microblog" \ + --pkgdir "examples/gno.land/p/demo/microblog" \ + --deposit 100000000ugnot \ + --gas-fee 1000000ugnot \ + --gas-wanted 2000000 \ + --broadcast \ + --chainid dev \ + test1 +``` diff --git a/examples/gno.land/r/demo/users/users.gno b/examples/gno.land/r/demo/users/users.gno index 8f3dce8d6b5..df3c856bb30 100644 --- a/examples/gno.land/r/demo/users/users.gno +++ b/examples/gno.land/r/demo/users/users.gno @@ -267,12 +267,11 @@ func Resolve(input users.AddressOrName) std.Address { // Add restricted name to the list func AdminAddRestrictedName(name string) { - // assert admin - // assert CallTx call. std.AssertOriginCall() // get caller caller := std.GetOrigCaller() + // assert admin if caller != admin { panic("unauthorized") } diff --git a/examples/gno.land/r/sys/users/users.gno b/examples/gno.land/r/sys/users/users.gno index 6322fc9d5ee..d687381cd43 100644 --- a/examples/gno.land/r/sys/users/users.gno +++ b/examples/gno.land/r/sys/users/users.gno @@ -7,7 +7,7 @@ import ( ) // For now this package is disable by default -var enable = false +var enabled = false var admin = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" @@ -15,20 +15,20 @@ var admin = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" func AdminEnable() { assertIsAdmin() - enable = true + enabled = true } func AdminDisable() { assertIsAdmin() - enable = false + enabled = false } -func IsEnable() bool { return enable } +func IsEnable() bool { return enabled } // This method ensure that the given address have ownership on the given name. func IsAuthorizedAddressForName(address std.Address, name string) bool { - if !enable { + if !enabled { return true } diff --git a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar index fcaee878d53..62a6379a84f 100644 --- a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar +++ b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar @@ -8,59 +8,59 @@ patchpkg "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" $USER_ADDR_admin # use our c gnoland start -## When `sys/users` is Disable +## When `sys/users` is disabled -# should be disable by default, addpkg should works by default +# Should be disabled by default, addpkg should work by default -# check is sys/users is disable +# Check if sys/users is disabled # gui call -> sys/users.IsEnable gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test gui stdout 'OK!' stdout 'false' -# gui sould be able to addpkg on test1 addr +# Gui should be able to addpkg on test1 addr # gui addpkg -> gno.land/r//mysuperpkg gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/mysuperpkg -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stdout 'OK!' -# gui sould be able to addpkg on random name +# Gui should be able to addpkg on random name # gui addpkg -> gno.land/r/randomname/mysuperpkg gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/randomname/mysuperpkg -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stdout 'OK!' -## When `sys/users` is Enable +## When `sys/users` is enabled -# enable `sys/users` +# Enable `sys/users` # admin call -> sys/users.AdminEnable gnokey maketx call -pkgpath gno.land/r/sys/users -func AdminEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test admin stdout 'OK!' -# check that `sys/users` as been enable +# Check that `sys/users` has been enabled # gui call -> sys/users.IsEnable gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test gui stdout 'OK!' stdout 'true' -# try to add a pkg with unregistered user +# Try to add a pkg an with unregistered user # gui addpkg -> gno.land/r//one ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_test1/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stderr 'unauthorized user' -# try to add a pkg with unregistered user, on their own address as namespace +# Try to add a pkg with an unregistered user, on their own address as namespace # gui addpkg -> gno.land/r//one gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/$USER_ADDR_gui/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stdout 'OK!' -## test unregistered namespace +## Test unregistered namespace -# call addpkg with admin user on gui namespace +# Call addpkg with admin user on gui namespace # admin addpkg -> gno.land/r/guiland/one ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test admin stderr 'unauthorized user' -## test registered namespace +## Test registered namespace -# test admin invite gui +# Test admin invites gui # admin call -> demo/users.Invite gnokey maketx call -pkgpath gno.land/r/demo/users -func Invite -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_gui admin stdout 'OK!' @@ -70,12 +70,12 @@ stdout 'OK!' gnokey maketx call -pkgpath gno.land/r/demo/users -func Register -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -args $USER_ADDR_admin -args 'guiland' -args 'im gui' gui stdout 'OK!' -# test gui pushing on guiland/one +# Test gui publishing on guiland/one # gui addpkg -> gno.land/r/guiland/one gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/one -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test gui stdout 'OK!' -# test admin pushing on guiland/two +# Test admin publishing on guiland/two # admin addpkg -> gno.land/r/guiland/two ! gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/guiland/two -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test admin stderr 'unauthorized user' From cb7d3e3ca8021f85c62832f45d2186a96a74f8f0 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:21:36 +0200 Subject: [PATCH 52/64] chore: fix chain id Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- docs/concepts/namespaces.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/concepts/namespaces.md b/docs/concepts/namespaces.md index 84161fd9ca0..3356a2c803a 100644 --- a/docs/concepts/namespaces.md +++ b/docs/concepts/namespaces.md @@ -52,7 +52,7 @@ $ gnokey maketx call -pkgpath gno.land/r/demo/users \ -func Register \ -gas-fee 1000000ugnot -gas-wanted 2000000 \ -broadcast \ - -chainid=dev \ + -chainid=test4 \ -send=20000000ugnot \ -args '' \ -args 'patrick' \ @@ -78,6 +78,6 @@ $ gnokey maketx addpkg \ --gas-fee 1000000ugnot \ --gas-wanted 2000000 \ --broadcast \ - --chainid dev \ + --chainid test4 \ test1 ``` From c754fcdee0f819a6a78f8df0b761e94ee634bebe Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:57:37 +0200 Subject: [PATCH 53/64] feat: use ownership for `sys/users` Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/sys/users/gno.mod | 5 +- examples/gno.land/r/sys/users/users.gno | 52 --------------- examples/gno.land/r/sys/users/verify.gno | 80 ++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 53 deletions(-) delete mode 100644 examples/gno.land/r/sys/users/users.gno create mode 100644 examples/gno.land/r/sys/users/verify.gno diff --git a/examples/gno.land/r/sys/users/gno.mod b/examples/gno.land/r/sys/users/gno.mod index da5d1ba8fcd..774a364a272 100644 --- a/examples/gno.land/r/sys/users/gno.mod +++ b/examples/gno.land/r/sys/users/gno.mod @@ -1,3 +1,6 @@ module gno.land/r/sys/users -require gno.land/r/demo/users v0.0.0-latest +require ( + gno.land/p/demo/ownable v0.0.0-latest + gno.land/r/demo/users v0.0.0-latest +) diff --git a/examples/gno.land/r/sys/users/users.gno b/examples/gno.land/r/sys/users/users.gno deleted file mode 100644 index d687381cd43..00000000000 --- a/examples/gno.land/r/sys/users/users.gno +++ /dev/null @@ -1,52 +0,0 @@ -package users - -import ( - "std" - - "gno.land/r/demo/users" -) - -// For now this package is disable by default -var enabled = false - -var admin = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" - -// Admin call to Activate or Desactivate this package. -func AdminEnable() { - assertIsAdmin() - - enabled = true -} - -func AdminDisable() { - assertIsAdmin() - - enabled = false -} - -func IsEnable() bool { return enabled } - -// This method ensure that the given address have ownership on the given name. -func IsAuthorizedAddressForName(address std.Address, name string) bool { - if !enabled { - return true - } - - // Allow user with their own address as name - if address.String() == name { - return true - } - - if user := users.GetUserByName(name); user != nil { - return user.Address == address - } - - return false -} - -func assertIsAdmin() { - caller := std.GetOrigCaller() - if admin != caller.String() { - panic("access restricted") - } -} diff --git a/examples/gno.land/r/sys/users/verify.gno b/examples/gno.land/r/sys/users/verify.gno new file mode 100644 index 00000000000..6365a8ebe0a --- /dev/null +++ b/examples/gno.land/r/sys/users/verify.gno @@ -0,0 +1,80 @@ +package users + +import ( + "std" + + "gno.land/p/demo/ownable" + "gno.land/r/demo/users" +) + +const admin = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // @jae + +type VerifyNameFunc func(enabled bool, address std.Address, name string) bool + +var ( + owner = ownable.NewWithAddress(admin) // Pkg owner + checkFunc = DefaultCheckName // Checking namesapce callback + enabled = false // For now this package is disable by default +) + +func IsEnable() bool { return enabled } + +// This method ensure that the given address have ownership on the given name. +func IsAuthorizedAddressForName(address std.Address, name string) bool { + return checkFunc(enabled, address, name) +} + +func DefaultCheckName(enable bool, address std.Address, name string) bool { + if !enable { + return true + } + + // Allow user with their own address as name + if address.String() == name { + return true + } + + if user := users.GetUserByName(name); user != nil { + return user.Address == address + } + + return false +} + +// Admin calls + +// Enable this package. +func AdminEnable() { + if err := owner.CallerIsOwner(); err != nil { + panic(err) + } + + enabled = true +} + +// Disable this package. +func AdminDisable() { + if err := owner.CallerIsOwner(); err != nil { + panic(err) + } + + enabled = false +} + +// AdminUpdateVerifyCall updates the method that verifies the namespace. +func AdminUpdateVerifyCall(check VerifyNameFunc) { + if err := owner.CallerIsOwner(); err != nil { + panic(err) + } + + checkFunc = check +} + +// AdminTransferOwnership transfers the ownership to a new owner. +func AdminTransferOwnership(newOwner std.Address) error { + if err := owner.CallerIsOwner(); err != nil { + panic(err) + } + + return owner.TransferOwnership(newOwner) +} From af558281cb62094c4e4130b99d9415b664ba97aa Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:33:17 +0200 Subject: [PATCH 54/64] chore: sys/users comment and name Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/sys/users/verify.gno | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/gno.land/r/sys/users/verify.gno b/examples/gno.land/r/sys/users/verify.gno index 6365a8ebe0a..e6f61620711 100644 --- a/examples/gno.land/r/sys/users/verify.gno +++ b/examples/gno.land/r/sys/users/verify.gno @@ -12,19 +12,22 @@ const admin = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // @jae type VerifyNameFunc func(enabled bool, address std.Address, name string) bool var ( - owner = ownable.NewWithAddress(admin) // Pkg owner - checkFunc = DefaultCheckName // Checking namesapce callback - enabled = false // For now this package is disable by default + owner = ownable.NewWithAddress(admin) // Package owner + checkFunc = VerifyNameByUser // Checking namespace callback + enabled = false // For now this package is disabled by default ) func IsEnable() bool { return enabled } -// This method ensure that the given address have ownership on the given name. +// This method ensures that the given address has ownership of the given name. func IsAuthorizedAddressForName(address std.Address, name string) bool { return checkFunc(enabled, address, name) } -func DefaultCheckName(enable bool, address std.Address, name string) bool { +// VerifyNameByUser checks from the `users` package that the user has correctly +// registered the given name. +// This function considers as valid an `address` that matches the `name`. +func VerifyNameByUser(enable bool, address std.Address, name string) bool { if !enable { return true } From adbddf122aecdc4c7cb8085936e1735ef469b5e7 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:00:28 +0200 Subject: [PATCH 55/64] chore: update info / remove famous name (breaking tests) Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/demo/users/preregister.gno | 7 +------ examples/gno.land/r/demo/users/users.gno | 6 +++--- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/examples/gno.land/r/demo/users/preregister.gno b/examples/gno.land/r/demo/users/preregister.gno index b5cb71b4c8c..a6377c54938 100644 --- a/examples/gno.land/r/demo/users/preregister.gno +++ b/examples/gno.land/r/demo/users/preregister.gno @@ -8,7 +8,7 @@ import ( // pre-restricted names var preRestrictedNames = []string{ - "bitcoin", "cosmos", "newtendermint", "administrator", "ethereum", + "bitcoin", "cosmos", "newtendermint", "ethereum", } // pre-registered users @@ -26,11 +26,6 @@ var preRegisteredUsers = []struct { {"nt", "g15ge0ae9077eh40erwrn2eq0xw6wupwqthpv34l"}, // -> @r_nt {"sys", "g1r929wt2qplfawe4lvqv9zuwfdcz4vxdun7qh8l"}, // -> @r_sys {"x", "g164sdpew3c2t3rvxj3kmfv7c7ujlvcw2punzzuz"}, // -> @r_x - - // famous name - {"test1", "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"}, // -> @test1 - {"jaekwon", "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj"}, // -> @jae - {"manfred", "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq"}, // -> @moul } func init() { diff --git a/examples/gno.land/r/demo/users/users.gno b/examples/gno.land/r/demo/users/users.gno index df3c856bb30..74965b3e592 100644 --- a/examples/gno.land/r/demo/users/users.gno +++ b/examples/gno.land/r/demo/users/users.gno @@ -63,11 +63,11 @@ func Register(inviter std.Address, name string, profile string) { // assert not already registered. _, ok := name2User.Get(name) if ok { - panic("name already registered") + panic("name already registered: " + name) } _, ok = addr2User.Get(caller.String()) if ok { - panic("address already registered") + panic("address already registered: " + caller.String()) } isInviterAdmin := inviter == admin @@ -76,7 +76,7 @@ func Register(inviter std.Address, name string, profile string) { if _, isRestricted := restricted.Get(name); isRestricted { // only address invite by the admin can register restricted name if !isInviterAdmin { - panic("restricted name") + panic("restricted name: " + name) } restricted.Remove(name) From 9cc0c9722613a0fcaffe6a076865f8029083fa41 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:01:33 +0200 Subject: [PATCH 56/64] fix: patchpkg Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- gno.land/pkg/integration/testdata/patchpkg.txtar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gno.land/pkg/integration/testdata/patchpkg.txtar b/gno.land/pkg/integration/testdata/patchpkg.txtar index cd81c568bbd..c5962709625 100644 --- a/gno.land/pkg/integration/testdata/patchpkg.txtar +++ b/gno.land/pkg/integration/testdata/patchpkg.txtar @@ -2,7 +2,7 @@ loadpkg gno.land/r/dev/admin $WORK adduser dev -replace "g1abcde" $USER_ADDR_dev +patchpkg "g1abcde" $USER_ADDR_dev gnoland start From 7ff351bd3bf8a590a6d42160563334dcc8f02cd4 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:28:09 +0200 Subject: [PATCH 57/64] fix: bad user output test Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/demo/users/z_11_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_5_filetest.gno | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/gno.land/r/demo/users/z_11_filetest.gno b/examples/gno.land/r/demo/users/z_11_filetest.gno index 067d019bcb7..a7516729717 100644 --- a/examples/gno.land/r/demo/users/z_11_filetest.gno +++ b/examples/gno.land/r/demo/users/z_11_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// restricted name +// restricted name: superrestricted diff --git a/examples/gno.land/r/demo/users/z_5_filetest.gno b/examples/gno.land/r/demo/users/z_5_filetest.gno index 413acf3f461..045390af970 100644 --- a/examples/gno.land/r/demo/users/z_5_filetest.gno +++ b/examples/gno.land/r/demo/users/z_5_filetest.gno @@ -43,12 +43,9 @@ func main() { // * [gnolang](/r/demo/users:gnolang) // * [gnouser](/r/demo/users:gnouser) // * [gov](/r/demo/users:gov) -// * [jaekwon](/r/demo/users:jaekwon) -// * [manfred](/r/demo/users:manfred) // * [nt](/r/demo/users:nt) // * [satoshi](/r/demo/users:satoshi) // * [sys](/r/demo/users:sys) -// * [test1](/r/demo/users:test1) // * [x](/r/demo/users:x) // // ======================================== From 69cab73b2a07ea4f6068335afebc69d83b9d2ebd Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:21:57 +0200 Subject: [PATCH 58/64] fix: namespace path clean Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- gno.land/pkg/sdk/vm/keeper.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 8d8f0ca2a1a..9899afa2eac 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -8,7 +8,6 @@ import ( "fmt" "log/slog" "os" - "path" "path/filepath" "regexp" "strings" @@ -251,7 +250,7 @@ func (vm *VMKeeper) getGnoStore(ctx sdk.Context) gno.Store { } // Namespace can be either a user or crypto address. -var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([a-zA-Z]+[_a-zA-Z0-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 { @@ -259,9 +258,6 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add store := vm.getGnoStore(ctx) - // XXX: is this necessary ? - pkgPath = path.Clean(pkgPath) // cleanup pkgpath - match := reNamespace.FindStringSubmatch(pkgPath) switch len(match) { case 0: @@ -275,9 +271,6 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add } username := match[1] - // Lowercase username - username = strings.ToLower(username) - // if `sysUsersPkg` does not exist -> skip validation. usersPkg := store.GetPackage(sysUsersPkg, false) if usersPkg == nil { From 497038be3cb5c88d0155b68cb6eb2a47bc7ac71c Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:27:33 +0200 Subject: [PATCH 59/64] feat: set moul as admin for {sys/demo}/users Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/demo/groups/z_1_a_filetest.gno | 2 +- examples/gno.land/r/demo/groups/z_2_a_filetest.gno | 2 +- examples/gno.land/r/demo/users/users.gno | 2 +- examples/gno.land/r/demo/users/z_10_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_11_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_11b_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_2_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_3_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_4_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_5_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_6_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_7_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_7b_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_8_filetest.gno | 2 +- examples/gno.land/r/demo/users/z_9_filetest.gno | 2 +- examples/gno.land/r/sys/users/verify.gno | 2 +- gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/examples/gno.land/r/demo/groups/z_1_a_filetest.gno b/examples/gno.land/r/demo/groups/z_1_a_filetest.gno index 95d13c6f241..aeff9ab7774 100644 --- a/examples/gno.land/r/demo/groups/z_1_a_filetest.gno +++ b/examples/gno.land/r/demo/groups/z_1_a_filetest.gno @@ -13,7 +13,7 @@ import ( var gid groups.GroupID -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/groups/z_2_a_filetest.gno b/examples/gno.land/r/demo/groups/z_2_a_filetest.gno index d9bee0e2edc..d1cc53d612f 100644 --- a/examples/gno.land/r/demo/groups/z_2_a_filetest.gno +++ b/examples/gno.land/r/demo/groups/z_2_a_filetest.gno @@ -13,7 +13,7 @@ import ( var gid groups.GroupID -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/users/users.gno b/examples/gno.land/r/demo/users/users.gno index 74965b3e592..9b8e93b579b 100644 --- a/examples/gno.land/r/demo/users/users.gno +++ b/examples/gno.land/r/demo/users/users.gno @@ -14,7 +14,7 @@ import ( // State var ( - admin std.Address = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // @jae + admin std.Address = "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq" // @moul restricted avl.Tree // Name -> true - restricted name name2User avl.Tree // Name -> *users.User diff --git a/examples/gno.land/r/demo/users/z_10_filetest.gno b/examples/gno.land/r/demo/users/z_10_filetest.gno index 878fa296fdd..078058c0703 100644 --- a/examples/gno.land/r/demo/users/z_10_filetest.gno +++ b/examples/gno.land/r/demo/users/z_10_filetest.gno @@ -8,7 +8,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func init() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/users/z_11_filetest.gno b/examples/gno.land/r/demo/users/z_11_filetest.gno index a7516729717..603d63f371d 100644 --- a/examples/gno.land/r/demo/users/z_11_filetest.gno +++ b/examples/gno.land/r/demo/users/z_11_filetest.gno @@ -8,7 +8,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/users/z_11b_filetest.gno b/examples/gno.land/r/demo/users/z_11b_filetest.gno index 9e04479d8a6..5e661e8f8c1 100644 --- a/examples/gno.land/r/demo/users/z_11b_filetest.gno +++ b/examples/gno.land/r/demo/users/z_11b_filetest.gno @@ -8,7 +8,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/users/z_2_filetest.gno b/examples/gno.land/r/demo/users/z_2_filetest.gno index 4e1bc49832c..84b62a7e483 100644 --- a/examples/gno.land/r/demo/users/z_2_filetest.gno +++ b/examples/gno.land/r/demo/users/z_2_filetest.gno @@ -9,7 +9,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/users/z_3_filetest.gno b/examples/gno.land/r/demo/users/z_3_filetest.gno index 7a75aa057b3..ce34c6bba66 100644 --- a/examples/gno.land/r/demo/users/z_3_filetest.gno +++ b/examples/gno.land/r/demo/users/z_3_filetest.gno @@ -9,7 +9,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/users/z_4_filetest.gno b/examples/gno.land/r/demo/users/z_4_filetest.gno index 07d6d8b32d2..1a46d915c96 100644 --- a/examples/gno.land/r/demo/users/z_4_filetest.gno +++ b/examples/gno.land/r/demo/users/z_4_filetest.gno @@ -9,7 +9,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/users/z_5_filetest.gno b/examples/gno.land/r/demo/users/z_5_filetest.gno index 045390af970..4ab68ec0e0b 100644 --- a/examples/gno.land/r/demo/users/z_5_filetest.gno +++ b/examples/gno.land/r/demo/users/z_5_filetest.gno @@ -9,7 +9,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/users/z_6_filetest.gno b/examples/gno.land/r/demo/users/z_6_filetest.gno index 008ba03a936..85305fff1ad 100644 --- a/examples/gno.land/r/demo/users/z_6_filetest.gno +++ b/examples/gno.land/r/demo/users/z_6_filetest.gno @@ -6,7 +6,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() diff --git a/examples/gno.land/r/demo/users/z_7_filetest.gno b/examples/gno.land/r/demo/users/z_7_filetest.gno index 98b1694c3eb..3332ab49af4 100644 --- a/examples/gno.land/r/demo/users/z_7_filetest.gno +++ b/examples/gno.land/r/demo/users/z_7_filetest.gno @@ -9,7 +9,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/users/z_7b_filetest.gno b/examples/gno.land/r/demo/users/z_7b_filetest.gno index 27a8420d531..60a397abe79 100644 --- a/examples/gno.land/r/demo/users/z_7b_filetest.gno +++ b/examples/gno.land/r/demo/users/z_7b_filetest.gno @@ -9,7 +9,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/users/z_8_filetest.gno b/examples/gno.land/r/demo/users/z_8_filetest.gno index 3c35cf21e71..1eaa017b7d2 100644 --- a/examples/gno.land/r/demo/users/z_8_filetest.gno +++ b/examples/gno.land/r/demo/users/z_8_filetest.gno @@ -9,7 +9,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/demo/users/z_9_filetest.gno b/examples/gno.land/r/demo/users/z_9_filetest.gno index e77a68d7ff9..2bd9bf555dc 100644 --- a/examples/gno.land/r/demo/users/z_9_filetest.gno +++ b/examples/gno.land/r/demo/users/z_9_filetest.gno @@ -7,7 +7,7 @@ import ( "gno.land/r/demo/users" ) -const admin = std.Address("g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj") +const admin = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") func main() { caller := std.GetOrigCaller() // main diff --git a/examples/gno.land/r/sys/users/verify.gno b/examples/gno.land/r/sys/users/verify.gno index e6f61620711..8df7d360d32 100644 --- a/examples/gno.land/r/sys/users/verify.gno +++ b/examples/gno.land/r/sys/users/verify.gno @@ -7,7 +7,7 @@ import ( "gno.land/r/demo/users" ) -const admin = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // @jae +const admin = "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq" // @moul type VerifyNameFunc func(enabled bool, address std.Address, name string) bool diff --git a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar index 62a6379a84f..d9f89133306 100644 --- a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar +++ b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar @@ -4,7 +4,7 @@ loadpkg gno.land/r/sys/users adduser admin adduser gui -patchpkg "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" $USER_ADDR_admin # use our custom admin +patchpkg "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq" $USER_ADDR_admin # use our custom admin gnoland start From efef59ed7911183fb0ab037511e013de9e125d79 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 19:11:31 +0200 Subject: [PATCH 60/64] fix: remove genesis loading from the file Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- gno.land/pkg/integration/testing_node.go | 1 - 1 file changed, 1 deletion(-) diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go index 06020d9c94b..05a24ebc3e5 100644 --- a/gno.land/pkg/integration/testing_node.go +++ b/gno.land/pkg/integration/testing_node.go @@ -50,7 +50,6 @@ func TestingNodeConfig(t TestingTS, gnoroot string) (*gnoland.InMemoryNodeConfig balances := LoadDefaultGenesisBalanceFile(t, gnoroot) txs := []std.Tx{} txs = append(txs, LoadDefaultPackages(t, creator, gnoroot)...) - txs = append(txs, LoadDefaultGenesisTXsFile(t, cfg.Genesis.ChainID, gnoroot)...) cfg.Genesis.AppState = gnoland.GnoGenesisState{ Balances: balances, From cbe4cb9e9922243dfc03c406aa1b2285eccc33ac Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 19:14:14 +0200 Subject: [PATCH 61/64] fix: typo Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- examples/gno.land/r/sys/users/verify.gno | 2 +- gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/r/sys/users/verify.gno b/examples/gno.land/r/sys/users/verify.gno index 8df7d360d32..852626622e4 100644 --- a/examples/gno.land/r/sys/users/verify.gno +++ b/examples/gno.land/r/sys/users/verify.gno @@ -17,7 +17,7 @@ var ( enabled = false // For now this package is disabled by default ) -func IsEnable() bool { return enabled } +func IsEnabled() bool { return enabled } // This method ensures that the given address has ownership of the given name. func IsAuthorizedAddressForName(address std.Address, name string) bool { diff --git a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar index d9f89133306..5a88fd6d603 100644 --- a/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar +++ b/gno.land/cmd/gnoland/testdata/addpkg_namespace.txtar @@ -14,7 +14,7 @@ gnoland start # Check if sys/users is disabled # gui call -> sys/users.IsEnable -gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test gui +gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnabled -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test gui stdout 'OK!' stdout 'false' @@ -37,7 +37,7 @@ stdout 'OK!' # Check that `sys/users` has been enabled # gui call -> sys/users.IsEnable -gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnable -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test gui +gnokey maketx call -pkgpath gno.land/r/sys/users -func IsEnabled -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test gui stdout 'OK!' stdout 'true' From f988b424987f87c0228fa5b0b1f18f864b4309b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20=C5=BDivkovi=C4=87?= Date: Tue, 9 Jul 2024 19:28:12 +0200 Subject: [PATCH 62/64] Update docs/concepts/namespaces.md --- docs/concepts/namespaces.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/concepts/namespaces.md b/docs/concepts/namespaces.md index 3356a2c803a..4e4bc68210c 100644 --- a/docs/concepts/namespaces.md +++ b/docs/concepts/namespaces.md @@ -7,7 +7,11 @@ id: namespaces Namespaces provide users with the exclusive capability to publish contracts under their designated namespaces, similar to GitHub's user and organization model. -:::warn This feature isn't enabled by default on the chain and is currently only on test4.gno.land. +:::warn Not enabled + +This feature isn't enabled by default on the portal loop chain and is currently available only on test4.gno.land. + +::: # Package Path From 14b0c367822508e83608605c4c025229380462ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20=C5=BDivkovi=C4=87?= Date: Tue, 9 Jul 2024 19:28:20 +0200 Subject: [PATCH 63/64] Update docs/concepts/namespaces.md --- docs/concepts/namespaces.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/concepts/namespaces.md b/docs/concepts/namespaces.md index 4e4bc68210c..3c8d1f797a1 100644 --- a/docs/concepts/namespaces.md +++ b/docs/concepts/namespaces.md @@ -63,7 +63,11 @@ $ gnokey maketx call -pkgpath gno.land/r/demo/users \ -args 'My Profile Quote' test1 ``` -:::note Do not forget to update chain id +:::note Chain-ID + +Do not forget to update chain id, adequate to the network you're interacting with + +::: After successful registration, you can add a package under the registered namespace. From 5df88c56f322e04cc9206e072335e136f7ac6cb9 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 9 Jul 2024 19:47:04 +0200 Subject: [PATCH 64/64] fix: genesis Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- gno.land/genesis/genesis_txs.jsonl | 8 ++++---- gno.land/pkg/gnoweb/gnoweb_test.go | 8 ++++++-- gno.land/pkg/integration/testing_node.go | 3 ++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/gno.land/genesis/genesis_txs.jsonl b/gno.land/genesis/genesis_txs.jsonl index 026dd1040b3..daf9fbdc5d4 100644 --- a/gno.land/genesis/genesis_txs.jsonl +++ b/gno.land/genesis/genesis_txs.jsonl @@ -1,11 +1,11 @@ -{"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s:1\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8:1\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q:1\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj:1\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0:1\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz:1\ng187982000zsc493znqt828s90cmp6hcp2erhu6m:1\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl:1\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037:1\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5:1\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr:1\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz:1\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w:1\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz:1\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3:1\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0:1\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n:1\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac:1\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap:1\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv:1\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv:1\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq:1\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6:1\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q:1\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7:1\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k:1\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll:1\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd:1\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64:1\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw:1\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a:1\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc:1\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6:1\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6:1\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9:1\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea:1\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3:1\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp:1\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5:1\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf:1\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g:1\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r:1\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su:1\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69:1\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6:1\ng1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq:10\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa:10\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t:5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"S8iMMzlOMK8dmox78R9Z8+pSsS8YaTCXrIcaHDpiOgkOy7gqoQJ0oftM0zf8zAz4xpezK8Lzg8Q0fCdXJxV76w=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1thlf3yct7n7ex70k0p62user0kn6mj6d3s0cg3\ng1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"njczE6xYdp01+CaUU/8/v0YC/NuZD06+qLind+ZZEEMNaRe/4Ln+4z7dG6HYlaWUMsyI1KCoB6NIehoE0PZ44Q=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz\ng187982000zsc493znqt828s90cmp6hcp2erhu6m\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6\ng1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t\n"]}],"fee":{"gas_wanted":"4000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"7AmlhZhsVkxCUl0bbpvpPMnIKihwtG7A5IFR6Tg4xStWLgaUr05XmWRKlO2xjstTtwbVKQT5mFL4h5wyX4SQzw=="}],"memo":""} +{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj:10\ng1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s:1\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8:1\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q:1\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj:1\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0:1\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz:1\ng187982000zsc493znqt828s90cmp6hcp2erhu6m:1\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl:1\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037:1\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5:1\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr:1\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz:1\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w:1\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz:1\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3:1\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0:1\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n:1\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac:1\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap:1\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv:1\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv:1\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq:1\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6:1\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q:1\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7:1\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k:1\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll:1\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd:1\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64:1\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw:1\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a:1\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc:1\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6:1\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6:1\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9:1\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea:1\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3:1\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp:1\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5:1\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf:1\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g:1\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r:1\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su:1\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69:1\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6:1\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa:10\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t:5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"S8iMMzlOMK8dmox78R9Z8+pSsS8YaTCXrIcaHDpiOgkOy7gqoQJ0oftM0zf8zAz4xpezK8Lzg8Q0fCdXJxV76w=="}],"memo":""} +{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1thlf3yct7n7ex70k0p62user0kn6mj6d3s0cg3\ng1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"njczE6xYdp01+CaUU/8/v0YC/NuZD06+qLind+ZZEEMNaRe/4Ln+4z7dG6HYlaWUMsyI1KCoB6NIehoE0PZ44Q=="}],"memo":""} +{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz\ng187982000zsc493znqt828s90cmp6hcp2erhu6m\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6\ng1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t\n"]}],"fee":{"gas_wanted":"4000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"7AmlhZhsVkxCUl0bbpvpPMnIKihwtG7A5IFR6Tg4xStWLgaUr05XmWRKlO2xjstTtwbVKQT5mFL4h5wyX4SQzw=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","administrator","g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"AqCqe0cS55Ym7/BvPDoCDyPP5q8284gecVQ2PMOlq/4lJpO9Q18SOWKI15dMEBY1pT0AYyhCeTirlsM1I3Y4Cg=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1qpymzwx4l4cy6cerdyajp9ksvjsf20rk5y9rtt","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","zo_oma","Love is the encryption key\u003c3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A6yg5/iiktruezVw5vZJwLlGwyrvw8RlqOToTRMWXkE2"},"signature":"GGp+bVL2eEvKecPqgcULSABYOSnSMnJzfIsR8ZIRER1GGX/fOiCReX4WKMrGLVROJVfbLQkDRwvhS4TLHlSoSQ=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","manfred","https://github.com/moul"]}],"fee":{"gas_wanted":"2000000","gas_fee":"200000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":"9CWeNbKx+hEL+RdHplAVAFntcrAVx5mK9tMqoywuHVoreH844n3yOxddQrGfBk6T2tMBmNWakERRqWZfS+bYAQ=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","piupiu","@piux2"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"Ar68lqbU2YC63fbMcYUtJhYO3/66APM/EqF7m0nUjGyz"},"signature":"pTUpP0d/XlfVe3TH1hlaoLhKadzIKG1gtQ/Ueuat72p+659RWRea58Z0mk6GgPE/EeTbhMEY45zufevBdGJVoQ=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5","send":"","pkg_path":"gno.land/r/demo/users","func":"Register","args":["g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","anarcher","https://twitter.com/anarcher"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AjpLbKdQeH+yB/1OCB148l5GlRRrXma71hdA8EES3H7f"},"signature":"pf5xm8oWIQIOEwSGw4icPmynLXb1P1HxKfjeh8UStU1mlIBPKa7yppeIMPpAflC0o2zjFR7Axe7CimAebm3BHg=="}],"memo":""} +{"msg":[{"@type":"/vm.m_call","caller":"g1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5","send":"","pkg_path":"gno.land/r/demo/users","func":"Register","args":["g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","anarcher","https://twitter.com/anarcher"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AjpLbKdQeH+yB/1OCB148l5GlRRrXma71hdA8EES3H7f"},"signature":"pf5xm8oWIQIOEwSGw4icPmynLXb1P1HxKfjeh8UStU1mlIBPKa7yppeIMPpAflC0o2zjFR7Axe7CimAebm3BHg=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g15gdm49ktawvkrl88jadqpucng37yxutucuwaef","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","ideamour","\u003c3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AhClx4AsDuX3DNCPxhDwWnrfd4MIZmxJE4vt47ClVvT2"},"signature":"IQe64af878k6HjLDqIJeg27GXAVF6xS+96cDe2jMlxNV6+8sOcuUctp0GiWVnYfN4tpthC6d4WhBo+VlpHqkbg=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateBoard","args":["testboard"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"vzlSxEFh5jOkaSdv3rsV91v/OJKEF2qSuoCpri1u5tRWq62T7xr3KHRCF5qFnn4aQX/yE8g8f/Y//WPOCUGhJw=="}],"memo":""} {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","Hello World","This is a demo of Gno smart contract programming. This document was\nconstructed by Gno onto a smart contract hosted on the data Realm \nname [\"gno.land/r/demo/boards\"](https://gno.land/r/demo/boards/)\n([github](https://github.com/gnolang/gno/tree/master/examples/gno.land/r/demo/boards)).\n\n## Starting the `gnoland` node node/validator.\n\nNOTE: Where you see `--remote %%REMOTE%%` here, that flag can be replaced\nwith `--remote localhost:26657` for local testnets.\n\n### build gnoland.\n\n```bash\ngit clone git@github.com:gnolang/gno.git\ncd ./gno\nmake \n```\n\n### add test account.\n\n```bash\n./build/gnokey add test1 --recover\n```\n\nUse this mnemonic:\n\u003e source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast\n\n### start gnoland validator node.\n\n```bash\n./build/gnoland\n```\n\n(This can be reset with `make reset`).\n\n### start gnoland web server (optional).\n\n```bash\ngo run ./gnoland/website\n```\n\n## Signing and broadcasting transactions.\n\n### publish the \"gno.land/p/demo/avl\" package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/p/demo/avl\" --pkgdir \"examples/gno.land/p/demo/avl\" --deposit 100ugnot --gas-fee 1ugnot --gas-wanted 2000000 \u003e addpkg.avl.unsigned.txt\n./build/gnokey query \"auth/accounts/g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5\"\n./build/gnokey sign test1 --txpath addpkg.avl.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 0 \u003e addpkg.avl.signed.txt\n./build/gnokey broadcast addpkg.avl.signed.txt --remote %%REMOTE%%\n```\n\n### publish the \"gno.land/r/demo/boards\" realm package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/r/demo/boards\" --pkgdir \"examples/gno.land/r/demo/boards\" --deposit 100ugnot --gas-fee 1ugnot --gas-wanted 300000000 \u003e addpkg.boards.unsigned.txt\n./build/gnokey sign test1 --txpath addpkg.boards.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 1 \u003e addpkg.boards.signed.txt\n./build/gnokey broadcast addpkg.boards.signed.txt --remote %%REMOTE%%\n```\n\n### create a board with a smart contract call.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreateBoard --args \"testboard\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createboard.unsigned.txt\n./build/gnokey sign test1 --txpath createboard.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 2 \u003e createboard.signed.txt\n./build/gnokey broadcast createboard.signed.txt --remote %%REMOTE%%\n```\nNext, query for the permanent board ID by querying (you need this to create a new post):\n\n```bash\n./build/gnokey query \"vm/qeval\" --data \"gno.land/r/demo/boards.GetBoardIDFromName(\\\"testboard\\\")\"\n```\n\n### create a post of a board with a smart contract call.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreatePost --args 1 --args \"Hello World\" --args#file \"./examples/gno.land/r/demo/boards/README.md\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createpost.unsigned.txt\n./build/gnokey sign test1 --txpath createpost.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 3 \u003e createpost.signed.txt\n./build/gnokey broadcast createpost.signed.txt --remote %%REMOTE%%\n```\n\n### create a comment to a post.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreateReply --args 1 --args 1 --args \"A comment\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createcomment.unsigned.txt\n./build/gnokey sign test1 --txpath createcomment.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 4 \u003e createcomment.signed.txt\n./build/gnokey broadcast createcomment.signed.txt --remote %%REMOTE%%\n```\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:testboard/1\"\n```\n\n### render page with optional path expression.\n\nThe contents of `https://gno.land/r/demo/boards:` and `https://gno.land/r/demo/boards:testboard` are rendered by calling\nthe `Render(path string)` function like so:\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:testboard\"\n```\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"V43B1waFxhzheW9TfmCpjLdrC4dC1yjUGES5y3J6QsNar6hRpNz4G1thzWmWK7xXhg8u1PCIpxLxGczKQYhuPw=="}],"memo":""} diff --git a/gno.land/pkg/gnoweb/gnoweb_test.go b/gno.land/pkg/gnoweb/gnoweb_test.go index d6b93b37d69..b266dc80a6a 100644 --- a/gno.land/pkg/gnoweb/gnoweb_test.go +++ b/gno.land/pkg/gnoweb/gnoweb_test.go @@ -49,7 +49,9 @@ func TestRoutes(t *testing.T) { {"/p/demo/flow/LICENSE", ok, "BSD 3-Clause"}, } - config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) + rootdir := gnoenv.RootDir() + genesis := integration.LoadDefaultGenesisTXsFile(t, "tendermint_test", rootdir) + config, _ := integration.TestingNodeConfig(t, rootdir, genesis...) node, remoteAddr := integration.TestingInMemoryNode(t, log.NewTestingLogger(t), config) defer node.Stop() @@ -96,7 +98,9 @@ func TestAnalytics(t *testing.T) { "/404-not-found", } - config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) + rootdir := gnoenv.RootDir() + genesis := integration.LoadDefaultGenesisTXsFile(t, "tendermint_test", rootdir) + config, _ := integration.TestingNodeConfig(t, rootdir, genesis...) node, remoteAddr := integration.TestingInMemoryNode(t, log.NewTestingLogger(t), config) defer node.Stop() diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go index 05a24ebc3e5..993386f6b04 100644 --- a/gno.land/pkg/integration/testing_node.go +++ b/gno.land/pkg/integration/testing_node.go @@ -42,7 +42,7 @@ func TestingInMemoryNode(t TestingTS, logger *slog.Logger, config *gnoland.InMem // TestingNodeConfig constructs an in-memory node configuration // with default packages and genesis transactions already loaded. // It will return the default creator address of the loaded packages. -func TestingNodeConfig(t TestingTS, gnoroot string) (*gnoland.InMemoryNodeConfig, bft.Address) { +func TestingNodeConfig(t TestingTS, gnoroot string, additionalTxs ...std.Tx) (*gnoland.InMemoryNodeConfig, bft.Address) { cfg := TestingMinimalNodeConfig(t, gnoroot) creator := crypto.MustAddressFromString(DefaultAccount_Address) // test1 @@ -50,6 +50,7 @@ func TestingNodeConfig(t TestingTS, gnoroot string) (*gnoland.InMemoryNodeConfig balances := LoadDefaultGenesisBalanceFile(t, gnoroot) txs := []std.Tx{} txs = append(txs, LoadDefaultPackages(t, creator, gnoroot)...) + txs = append(txs, additionalTxs...) cfg.Genesis.AppState = gnoland.GnoGenesisState{ Balances: balances,