Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: users namespace #2471

Merged
merged 69 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
51322b7
feat: r/system/names public functions
anarcher Oct 30, 2022
2a9fee6
test: names basic test
anarcher Nov 1, 2022
db517fd
chore: default inpause false
anarcher Nov 1, 2022
65fbc4d
feat(render): render index and namespace
anarcher Nov 2, 2022
180fb33
feat: reName and HasPerm
anarcher Nov 4, 2022
32a086f
feat: check namespace perm in vmkeeper.AddPackage
anarcher Nov 5, 2022
3b865ef
refactor: separate space methods and public function
anarcher Nov 5, 2022
5e18c06
refactor: assertIsAdmin
anarcher Nov 5, 2022
4a3c896
Update examples/gno.land/r/system/names/names.gno
anarcher Nov 10, 2022
2e9e7a5
Update examples/gno.land/r/system/names/names.gno
anarcher Nov 10, 2022
a0a83e8
refactor: move public functions to public.gno
anarcher Nov 10, 2022
32c816a
chore: comment TODO: prevent self
anarcher Nov 10, 2022
5f1c6c4
feat: caller can't remove self
anarcher Jan 16, 2023
905a458
feat: global variable `enabled` for skipping to check perms if adding
anarcher Jan 16, 2023
1595785
chore: remove todo comment
anarcher Jan 16, 2023
904bd0b
fix: avl.iterate
anarcher Jan 19, 2023
715e72f
chore: check enabled
anarcher Jun 7, 2023
d66c615
fix: avl.Tree.Iterate
anarcher Jun 8, 2023
6852b17
chore: make fmt
anarcher Jun 8, 2023
a61c9df
chore: update gno.mod
anarcher Jul 21, 2023
b8bd426
Merge remote-tracking branch 'origin/master' into feat/sys/names
gfanton Jun 19, 2024
5f3f975
wip: names
gfanton Jun 19, 2024
b20b163
wip: users
gfanton Jul 1, 2024
163a85c
feat: add keeper user check
gfanton Jul 1, 2024
dd31ab3
fix: typo
gfanton Jul 1, 2024
7418f7c
fix: increase gas test
gfanton Jul 1, 2024
3610ece
Merge branch 'master' into feat/sys/names
gfanton Jul 1, 2024
e101d63
chore: remove sys/names
gfanton Jul 1, 2024
dff9367
chore: cleanup duplicate method
gfanton Jul 1, 2024
763a39b
fix: keeper
gfanton Jul 1, 2024
5dabc77
fix: users resolve
gfanton Jul 1, 2024
1f9ba97
fix: undo change on user / add GetUserAddressByName
gfanton Jul 2, 2024
91bc22b
Update keeper.go
gfanton Jul 6, 2024
bf7fba2
wip: admin users package
gfanton Jul 6, 2024
2b88906
feat: add replace command for txtar
gfanton Jul 7, 2024
b451995
feat: Add sys/users
gfanton Jul 7, 2024
c1df7c3
chore: improve txtar comments
gfanton Jul 7, 2024
122d7d4
chore: use patchpkg instead of replace
gfanton Jul 8, 2024
0fca48f
Merge remote-tracking branch 'origin/master' into feat/check-user-perm
gfanton Jul 8, 2024
07057f3
chore: fix typo & update doc
gfanton Jul 8, 2024
a529632
feat: update user register fee to 20gnot
gfanton Jul 8, 2024
f798e3f
chore: lint
gfanton Jul 8, 2024
8873d15
chore: doc
gfanton Jul 8, 2024
2c714c9
Merge remote-tracking branch 'origin/master' into feat/check-user-perm
gfanton Jul 8, 2024
0dd8e21
feat: add preregister users/restricted
gfanton Jul 9, 2024
c03dab4
chore: typo
gfanton Jul 9, 2024
45ed16d
fix: small adjustement
gfanton Jul 9, 2024
e63ec47
chore: fix tests
gfanton Jul 9, 2024
eec6db9
fix: edit min fee
gfanton Jul 9, 2024
307810b
fix: test
gfanton Jul 9, 2024
f50dfc6
fix: users tidy
gfanton Jul 9, 2024
0799eec
chore: update typo warn
gfanton Jul 9, 2024
967aa65
fix: typo namespaces doc
gfanton Jul 9, 2024
2578356
chore: update gas deliver
gfanton Jul 9, 2024
cdd7ab2
chore: fix typo
gfanton Jul 9, 2024
cb7d3e3
chore: fix chain id
gfanton Jul 9, 2024
c754fcd
feat: use ownership for `sys/users`
gfanton Jul 9, 2024
af55828
chore: sys/users comment and name
gfanton Jul 9, 2024
adbddf1
chore: update info / remove famous name (breaking tests)
gfanton Jul 9, 2024
9cc0c97
fix: patchpkg
gfanton Jul 9, 2024
7ff351b
fix: bad user output test
gfanton Jul 9, 2024
69cab73
fix: namespace path clean
gfanton Jul 9, 2024
497038b
feat: set moul as admin for {sys/demo}/users
gfanton Jul 9, 2024
efef59e
fix: remove genesis loading from the file
gfanton Jul 9, 2024
1d43a00
Merge branch 'master' into feat/check-user-perm
gfanton Jul 9, 2024
cbe4cb9
fix: typo
gfanton Jul 9, 2024
f988b42
Update docs/concepts/namespaces.md
zivkovicmilos Jul 9, 2024
14b0c36
Update docs/concepts/namespaces.md
zivkovicmilos Jul 9, 2024
5df88c5
fix: genesis
gfanton Jul 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion docs/concepts/namespaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
gfanton marked this conversation as resolved.
Show resolved Hide resolved

# Package Path

Expand All @@ -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.
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved

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.
gfanton marked this conversation as resolved.
Show resolved Hide resolved
You can do this by using the user's own address as a namespace. This is formatted as `{p,r}/{std.Address}/**`.
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 2 additions & 2 deletions examples/gno.land/r/demo/boards/z_0_b_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// PKGPATH: gno.land/r/demo/boards_test
package boards_test

// SEND: 199000000ugnot
// SEND: 19900000ugnot

import (
"gno.land/r/demo/boards"
Expand All @@ -20,4 +20,4 @@ func main() {
}

// Error:
// payment must not be less than 200000000
// payment must not be less than 20000000
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_0_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// PKGPATH: gno.land/r/demo/boards_test
package boards_test

// SEND: 200000000ugnot
// SEND: 20000000ugnot

import (
"gno.land/r/demo/boards"
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_10_b_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// PKGPATH: gno.land/r/demo/boards_test
package boards_test

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"strconv"
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_11_a_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// PKGPATH: gno.land/r/demo/boards_test
package boards_test

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"strconv"
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_11_b_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// PKGPATH: gno.land/r/demo/boards_test
package boards_test

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"strconv"
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_11_c_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// PKGPATH: gno.land/r/demo/boards_test
package boards_test

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"strconv"
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_11_d_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// PKGPATH: gno.land/r/demo/boards_test
package boards_test

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"strconv"
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_11_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// PKGPATH: gno.land/r/demo/boards_test
package boards_test

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"strconv"
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_5_b_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package main

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"std"
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_5_c_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package main

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"std"
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_5_d_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package main

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"std"
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_7_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// PKGPATH: gno.land/r/demo/boards_test
package boards_test

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"gno.land/r/demo/boards"
Expand Down
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/boards/z_8_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// PKGPATH: gno.land/r/demo/boards_test
package boards_test

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"strconv"
Expand Down
71 changes: 71 additions & 0 deletions examples/gno.land/r/demo/users/preregister.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package users

import (
"std"

"gno.land/p/demo/users"
)

// pre-restricted names
var preRestrictedNames = []string{
"bitcoin", "cosmos", "newtendermint", "administrator", "ethereum",
}
gfanton marked this conversation as resolved.
Show resolved Hide resolved

// pre-registered users
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)
}
}
58 changes: 50 additions & 8 deletions examples/gno.land/r/demo/users/users.gno
gfanton marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -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 = 200 * 1000000 // 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.
)

//----------------------------------------
Expand All @@ -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) {
Expand All @@ -55,6 +59,7 @@ func Register(inviter std.Address, name string, profile string) {
}
invites.Remove(invitekey)
}

// assert not already registered.
_, ok := name2User.Get(name)
if ok {
Expand All @@ -64,10 +69,25 @@ func Register(inviter std.Address, name string, profile string) {
if ok {
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.
if !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 {
Expand Down Expand Up @@ -240,10 +260,32 @@ func Resolve(input users.AddressOrName) std.Address {
if !isName {
return std.Address(input) // TODO check validity
}

user := GetUserByName(name)
return user.Address
}

// Add restricted name to the list
func AdminAddRestrictedName(name string) {
// assert admin
gfanton marked this conversation as resolved.
Show resolved Hide resolved

// assert CallTx call.
std.AssertOriginCall()
// get caller
caller := std.GetOrigCaller()
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
if caller != admin {
panic("unauthorized")
}

if user := GetUserByName(name); user != nil {
panic("already registered name")
}

// register restricted name

restricted.Set(name, true)
}

//----------------------------------------
// Constants

Expand Down
4 changes: 2 additions & 2 deletions examples/gno.land/r/demo/users/z_0_b_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package main

// SEND: 199000000ugnot
// SEND: 19900000ugnot

import (
"gno.land/r/demo/users"
Expand All @@ -12,4 +12,4 @@ func main() {
}

// Error:
// payment must not be less than 200000000
// payment must not be less than 20000000
25 changes: 25 additions & 0 deletions examples/gno.land/r/demo/users/z_11_filetest.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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)
users.AdminAddRestrictedName("superrestricted")

// test restricted name
std.TestSetOrigCaller(caller)
users.Register("", "superrestricted", "my profile")
println("done")
}

// Error:
// restricted name
28 changes: 28 additions & 0 deletions examples/gno.land/r/demo/users/z_11b_filetest.gno
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion examples/gno.land/r/demo/users/z_1_filetest.gno
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package main

// SEND: 2000000000ugnot
// SEND: 200000000ugnot

import (
"gno.land/r/demo/users"
Expand Down
Loading
Loading