From aa24b6bf65aa0b00337ed35cd5ca2f576fe4de76 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Mon, 10 Mar 2025 17:29:28 +0100 Subject: [PATCH 1/9] changes --- .../gno.land/r/gnoland/users/v1/errors.gno | 3 +- .../gno.land/r/gnoland/users/v1/users.gno | 20 +++---- .../r/gnoland/users/v1/users_test.gno | 59 +++++++++++++++---- gnovm/stdlibs/std/native.gno | 2 +- 4 files changed, 59 insertions(+), 25 deletions(-) diff --git a/examples/gno.land/r/gnoland/users/v1/errors.gno b/examples/gno.land/r/gnoland/users/v1/errors.gno index 6acc476b8c5..0647f0f4fd3 100644 --- a/examples/gno.land/r/gnoland/users/v1/errors.gno +++ b/examples/gno.land/r/gnoland/users/v1/errors.gno @@ -7,7 +7,8 @@ import ( ) var ( + ErrNonUserCall = errors.New("r/gnoland/users: non-user call") ErrPaused = errors.New("r/gnoland/users: paused") - ErrInvalidPayment = ufmt.Errorf("r/gnoland/users: you need to send exactly %s ugnot", registerPrice) + ErrInvalidPayment = ufmt.Errorf("r/gnoland/users: you need to send exactly %d ugnot", registerPrice) ErrInvalidUsername = errors.New("r/gnoland/users: invalid username") ) diff --git a/examples/gno.land/r/gnoland/users/v1/users.gno b/examples/gno.land/r/gnoland/users/v1/users.gno index 6d09935494e..62e94e0bc68 100644 --- a/examples/gno.land/r/gnoland/users/v1/users.gno +++ b/examples/gno.land/r/gnoland/users/v1/users.gno @@ -18,33 +18,33 @@ var ( reUsername = regexp.MustCompile(reValidUsername) ) -// Register registers a new username for the caller +// Register registers a new username for the caller. // A valid username must start with a minimum of 3 letters, // end with a minimum of 3 numbers, and be less than 20 chars long. // All letters must be lowercase, and the only valid special char is `_`. // Only calls from EOAs are supported. -func Register(username string) error { - std.AssertOriginCall() +func Register(username string) { + if !std.PreviousRealm().IsUser() { + panic(ErrNonUserCall) + } if paused { - return ErrPaused + panic(ErrPaused) } if std.OriginSend().AmountOf("ugnot") != registerPrice { - return ErrInvalidPayment + panic(ErrInvalidPayment) } if matched := reUsername.MatchString(username); !matched { - return ErrInvalidUsername + panic(ErrInvalidUsername) } registrant := std.PreviousRealm().Address() if err := susers.RegisterUser(username, registrant); err != nil { - return err + panic(err) } - latestUsers.Append(username) + latestUsers.Append(username) // for display purposes std.Emit("Registeration", "address", registrant.String(), "name", username) - - return nil } diff --git a/examples/gno.land/r/gnoland/users/v1/users_test.gno b/examples/gno.land/r/gnoland/users/v1/users_test.gno index 53e2ee808c7..9fcba047e4a 100644 --- a/examples/gno.land/r/gnoland/users/v1/users_test.gno +++ b/examples/gno.land/r/gnoland/users/v1/users_test.gno @@ -23,7 +23,10 @@ func TestRegister_Valid(t *testing.T) { std.TestSetRealm(std.NewUserRealm(aliceAddr)) std.TestSetOriginCaller(aliceAddr) - uassert.NoError(t, Register(alice)) + uassert.NotPanics(t, func() { + Register(alice) + }) + res, latest := susers.ResolveName(alice) uassert.NotEqual(t, nil, res) @@ -39,24 +42,54 @@ func TestRegister_Invalid(t *testing.T) { std.TestSetOriginCaller(bobAddr) // Invalid usernames - uassert.Error(t, Register("alice"), ErrInvalidUsername.Error()) // vanity - uassert.Error(t, Register(""), ErrInvalidUsername.Error()) // empty - uassert.Error(t, Register(" "), ErrInvalidUsername.Error()) // empty - uassert.Error(t, Register("123"), ErrInvalidUsername.Error()) // only numbers - uassert.Error(t, Register("alice&#($)"), ErrInvalidUsername.Error()) // non-allowed chars - uassert.Error(t, Register("Alice123"), ErrInvalidUsername.Error()) // upper-case - uassert.Error(t, Register("toolongusernametoolongusernametoolongusername123"), - ErrInvalidUsername.Error()) // too long + uassert.PanicsWithMessage(t, ErrInvalidUsername.Error(), func() { + Register("alice") // vanity + }) + + uassert.PanicsWithMessage(t, ErrInvalidUsername.Error(), func() { + Register("") // empty + }) + + uassert.PanicsWithMessage(t, ErrInvalidUsername.Error(), func() { + Register(" ") // empty + }) + + uassert.PanicsWithMessage(t, ErrInvalidUsername.Error(), func() { + Register("123") // empty + }) + + uassert.PanicsWithMessage(t, ErrInvalidUsername.Error(), func() { + Register("123") // only numbers + }) + + uassert.PanicsWithMessage(t, ErrInvalidUsername.Error(), func() { + Register("alice&#($)") // non-allowed chars + }) + + uassert.PanicsWithMessage(t, ErrInvalidUsername.Error(), func() { + Register("Alice123") // upper-case + }) + + uassert.PanicsWithMessage(t, ErrInvalidUsername.Error(), func() { + Register("toolongusernametoolongusernametoolongusername123") // too long + }) // Name taken - urequire.NoError(t, Register(bob)) - uassert.Error(t, Register(bob), susers.ErrNameTaken.Error()) -} + urequire.NotPanics(t, func() { + Register(bob) + }) + uassert.PanicsWithMessage(t, susers.ErrNameTaken.Error(), func() { + Register(bob) // already registered + }) +} func TestRegister_InvalidPayment(t *testing.T) { std.TestSetRealm(std.NewUserRealm(bobAddr)) std.TestSetOriginCaller(bobAddr) std.TestSetOriginSend(std.NewCoins(std.NewCoin("ugnot", 12)), nil) // invalid payment amount - uassert.Error(t, Register("alice"), ErrInvalidPayment.Error()) // vanity + + uassert.PanicsWithMessage(t, ErrInvalidPayment.Error(), func() { + Register(alice) + }) } diff --git a/gnovm/stdlibs/std/native.gno b/gnovm/stdlibs/std/native.gno index 1b15bc21c29..7366494825f 100644 --- a/gnovm/stdlibs/std/native.gno +++ b/gnovm/stdlibs/std/native.gno @@ -1,7 +1,7 @@ package std // AssertOriginCall panics if the calling method is not invoked via a direct -// MsgCall. It panics for for other cases, like if the calling method +// MsgCall. It panics for other cases, like if the calling method // is invoked by another method (even from the same realm or package). // It also panic every time when the transaction is broadcasted via // MsgRun. From 30f6d0e8e46936ce7d161a9aca55b9de8957f68e Mon Sep 17 00:00:00 2001 From: leohhhn Date: Mon, 10 Mar 2025 18:19:23 +0100 Subject: [PATCH 2/9] fix comment --- examples/gno.land/r/gnoland/users/v1/admin.gno | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/r/gnoland/users/v1/admin.gno b/examples/gno.land/r/gnoland/users/v1/admin.gno index 68937dd1d3e..948d7a73a52 100644 --- a/examples/gno.land/r/gnoland/users/v1/admin.gno +++ b/examples/gno.land/r/gnoland/users/v1/admin.gno @@ -11,8 +11,8 @@ import ( var paused = false // XXX: replace with p/moul/authz -// NewSetPausedExecutor allows GovDAO to pause or unpause this realm -func NewSetPausedExecutor(newPausedValue bool) dao.Executor { +// ProposeNewPausedValue allows GovDAO to pause or unpause this realm +func ProposeNewPausedValue(newPausedValue bool) dao.Executor { cb := func() error { paused = newPausedValue return nil From 08714a18ce6c32246307cd61f0dc9428cafafdb6 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Mon, 10 Mar 2025 19:00:24 +0100 Subject: [PATCH 3/9] save --- examples/gno.land/r/gnoland/users/v1/users.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gno.land/r/gnoland/users/v1/users.gno b/examples/gno.land/r/gnoland/users/v1/users.gno index 62e94e0bc68..56280392458 100644 --- a/examples/gno.land/r/gnoland/users/v1/users.gno +++ b/examples/gno.land/r/gnoland/users/v1/users.gno @@ -45,6 +45,6 @@ func Register(username string) { panic(err) } - latestUsers.Append(username) // for display purposes + latestUsers.Append(username) std.Emit("Registeration", "address", registrant.String(), "name", username) } From 544b45bb1d73c5856995de4cfe2b33d571f9316e Mon Sep 17 00:00:00 2001 From: leohhhn Date: Mon, 10 Mar 2025 19:04:21 +0100 Subject: [PATCH 4/9] save --- examples/gno.land/r/gnoland/users/users.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gno.land/r/gnoland/users/users.gno b/examples/gno.land/r/gnoland/users/users.gno index 5eca5a272e6..c84c4e6b07f 100644 --- a/examples/gno.land/r/gnoland/users/users.gno +++ b/examples/gno.land/r/gnoland/users/users.gno @@ -11,8 +11,8 @@ import ( ) var ( - changelog = releases.NewChangelog("r/gnoland/users") cd = std.ChainDomain() + changelog = releases.NewChangelog("r/gnoland/users") ) const usersPrefix = "gno.land/r/gnoland/users/" From bcc9a0eef28fc6501073e17e2ea0a2b68ee5586e Mon Sep 17 00:00:00 2001 From: leohhhn Date: Mon, 10 Mar 2025 19:08:14 +0100 Subject: [PATCH 5/9] comment --- examples/gno.land/r/sys/users/users.gno | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/gno.land/r/sys/users/users.gno b/examples/gno.land/r/sys/users/users.gno index 4715ffa25e5..61d8ccdfe42 100644 --- a/examples/gno.land/r/sys/users/users.gno +++ b/examples/gno.land/r/sys/users/users.gno @@ -52,5 +52,8 @@ func makeUserDataSafe(data any) any { if cpy.deleted { return nil } + + // Note: when requesting data from this AVL tree, (exists bool) will be true + // Even if the data is "deleted". This is currently unavoidable return cpy } From 0001b3af78da5344973824560a48b4139fd9cf76 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 11 Mar 2025 15:01:21 +0100 Subject: [PATCH 6/9] add govdao --- examples/gno.land/r/sys/users/admin.gno | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/examples/gno.land/r/sys/users/admin.gno b/examples/gno.land/r/sys/users/admin.gno index 15183a41856..29fd6f6a411 100644 --- a/examples/gno.land/r/sys/users/admin.gno +++ b/examples/gno.land/r/sys/users/admin.gno @@ -35,6 +35,20 @@ func ProposeControllerRemoval(addr std.Address) dao.Executor { return bridge.GovDAO().NewGovDAOExecutor(cb) } +// ProposeControllerAdditionAndRemoval allows GovDAO to add a new caller and remove an old caller in the same proposal. +func ProposeControllerAdditionAndRemoval(toAdd, toRemove std.Address) dao.Executor { + cb := func() error { + err := addToWhitelist(toAdd) + if err != nil { + return err + } + + return deleteFromwhitelist(toRemove) + } + + return bridge.GovDAO().NewGovDAOExecutor(cb) +} + // Helpers func deleteFromwhitelist(addr std.Address) error { From d2e9204c2de3e88706994a9b12c36efbf54fba00 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 11 Mar 2025 16:25:30 +0100 Subject: [PATCH 7/9] fix tests --- examples/gno.land/r/demo/boards/z_0_filetest.gno | 2 +- examples/gno.land/r/demo/groups/z_2_b_filetest.gno | 2 +- examples/gno.land/r/demo/groups/z_2_d_filetest.gno | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 13ea7226432..9f28920c3ac 100644 --- a/examples/gno.land/r/demo/boards/z_0_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_0_filetest.gno @@ -14,7 +14,7 @@ var bid boards.BoardID func init() { std.TestSetRealm(std.NewUserRealm(std.Address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"))) // so that CurrentRealm.Addr() matches OrigCaller - err := users.Register("gnouser123") + users.Register("gnouser123") bid = boards.CreateBoard("test_board") boards.CreateThread(bid, "First Post (title)", "Body of the first post. (body)") diff --git a/examples/gno.land/r/demo/groups/z_2_b_filetest.gno b/examples/gno.land/r/demo/groups/z_2_b_filetest.gno index 1049382a94a..f799c69bde7 100644 --- a/examples/gno.land/r/demo/groups/z_2_b_filetest.gno +++ b/examples/gno.land/r/demo/groups/z_2_b_filetest.gno @@ -19,4 +19,4 @@ func main() { } // Error: -// user not found +// r/gnoland/users: non-user call diff --git a/examples/gno.land/r/demo/groups/z_2_d_filetest.gno b/examples/gno.land/r/demo/groups/z_2_d_filetest.gno index 500c6c9f80a..fbaacfe453c 100644 --- a/examples/gno.land/r/demo/groups/z_2_d_filetest.gno +++ b/examples/gno.land/r/demo/groups/z_2_d_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// user not found +// r/gnoland/users: non-user call From 17f1f8df346fb79a7aa14aaa568ace4701ee316b Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 11 Mar 2025 17:04:23 +0100 Subject: [PATCH 8/9] fixup --- gno.land/genesis/genesis_txs.jsonl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gno.land/genesis/genesis_txs.jsonl b/gno.land/genesis/genesis_txs.jsonl index b42d6cc52c4..29953f5bd2f 100644 --- a/gno.land/genesis/genesis_txs.jsonl +++ b/gno.land/genesis/genesis_txs.jsonl @@ -1,5 +1,5 @@ {"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"1000000ugnot","pkg_path":"gno.land/r/gnoland/users/v1","func":"Register","args":["administrator123"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":""}],"memo":""}} -{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1qpymzwx4l4cy6cerdyajp9ksvjsf20rk5y9rtt","send":"1000000ugnot","pkg_path":"gno.land/r/gnoland/users/v1","func":"Register","args":["zo_oma123"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A6yg5/iiktruezVw5vZJwLlGwyrvw8RlqOToTRMWXkE2"},"signature":""}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1qpymzwx4l4cy6cerdyajp9ksvjsf20rk5y9rtt","send":"1000000ugnot","pkg_path":"gno.land/r/gnoland/users/v1","func":"Register","args":["zoo_ma123"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A6yg5/iiktruezVw5vZJwLlGwyrvw8RlqOToTRMWXkE2"},"signature":""}],"memo":""}} {"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1manfred47kzduec920z88wfr64ylksmdcedlf5","send":"1000000ugnot","pkg_path":"gno.land/r/gnoland/users/v1","func":"Register","args":["moul001"]}],"fee":{"gas_wanted":"2000000","gas_fee":"200000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":""}],"memo":""}} {"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9","send":"1000000ugnot","pkg_path":"gno.land/r/gnoland/users/v1","func":"Register","args":["piupiu123"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"Ar68lqbU2YC63fbMcYUtJhYO3/66APM/EqF7m0nUjGyz"},"signature":""}],"memo":""}} {"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5","send":"1000000ugnot","pkg_path":"gno.land/r/gnoland/users/v1","func":"Register","args":["anarcher123"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AjpLbKdQeH+yB/1OCB148l5GlRRrXma71hdA8EES3H7f"},"signature":""}],"memo":""}} From 9e12078b54f09551f0dc9860983a5b8fbc669c47 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Tue, 11 Mar 2025 17:38:04 +0100 Subject: [PATCH 9/9] add panics --- examples/gno.land/r/sys/users/admin.gno | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/r/sys/users/admin.gno b/examples/gno.land/r/sys/users/admin.gno index 29fd6f6a411..4d8d2d6fad5 100644 --- a/examples/gno.land/r/sys/users/admin.gno +++ b/examples/gno.land/r/sys/users/admin.gno @@ -40,10 +40,15 @@ func ProposeControllerAdditionAndRemoval(toAdd, toRemove std.Address) dao.Execut cb := func() error { err := addToWhitelist(toAdd) if err != nil { - return err + panic(err) } - return deleteFromwhitelist(toRemove) + err = deleteFromwhitelist(toRemove) + if err != nil { + panic(err) + } + + return nil } return bridge.GovDAO().NewGovDAOExecutor(cb)