From 7f9912106fdd6b03a2096af6d250357cbc16ada8 Mon Sep 17 00:00:00 2001
From: moul <94029+moul@users.noreply.github.com>
Date: Tue, 18 Jun 2024 12:12:14 +0200
Subject: [PATCH 01/12] feat: refactor govdao execution mechanism and examples
Signed-off-by: moul <94029+moul@users.noreply.github.com>
---
.../gno.land/r/gov/dao/prop1_filetest.gno | 85 +++++++++++++++++++
examples/gno.land/r/gov/integration/gno.mod | 3 -
.../r/gov/integration/integration.gno | 4 -
.../gno.land/r/gov/integration/z_filetest.gno | 45 ----------
.../gno.land/r/gov/proposals/prop1/gno.mod | 6 --
.../gno.land/r/gov/proposals/prop1/prop1.gno | 36 --------
.../gno.land/r/sys/validators/validators.gno | 13 +++
7 files changed, 98 insertions(+), 94 deletions(-)
create mode 100644 examples/gno.land/r/gov/dao/prop1_filetest.gno
delete mode 100644 examples/gno.land/r/gov/integration/gno.mod
delete mode 100644 examples/gno.land/r/gov/integration/integration.gno
delete mode 100644 examples/gno.land/r/gov/integration/z_filetest.gno
delete mode 100644 examples/gno.land/r/gov/proposals/prop1/gno.mod
delete mode 100644 examples/gno.land/r/gov/proposals/prop1/prop1.gno
diff --git a/examples/gno.land/r/gov/dao/prop1_filetest.gno b/examples/gno.land/r/gov/dao/prop1_filetest.gno
new file mode 100644
index 00000000000..7072618a4a7
--- /dev/null
+++ b/examples/gno.land/r/gov/dao/prop1_filetest.gno
@@ -0,0 +1,85 @@
+// Please note that this package is intended for demonstration purposes only.
+// You could execute this code (the init part) by running a `maketx run` command
+// or by uploading a similar package to a personal namespace.
+//
+// For the specific case of validators, a `r/gnoland/valopers` will be used to
+// organize the lifecycle of validators (register, etc), and this more complex
+// contract will be responsible to generate proposals.
+package main
+
+import (
+ "std"
+
+ govdao "gno.land/r/gov/dao"
+ "gno.land/r/sys/validators"
+)
+
+func init() {
+ // Create the validators change proposal.
+ changesFn := func() []validators.Change {
+ return []validators.Change{
+ // add a new validator.
+ {Address: std.Address("g12345678"), Power: 1},
+ // remove an existing validator.
+ {Address: std.Address("g000000000"), Power: 0},
+ }
+ }
+
+ // Wraps changesFn to emit a certified event only if executed from a
+ // complete governance proposal process.
+ executor := validators.NewPropExecutor(changesFn)
+
+ // Create a proposal.
+ // XXX: payment
+ comment := "manual valset changes proposal example"
+ govdao.Propose(comment, executor)
+}
+
+func main() {
+ println("--")
+ println(govdao.Render(""))
+ println("--")
+ println(govdao.Render("1"))
+ println("--")
+ govdao.VoteOnProposal(1, "YES")
+ println("--")
+ println(govdao.Render("1"))
+ println("--")
+ println(validators.Render(""))
+ println("--")
+ govdao.ExecuteProposal(1)
+ println("--")
+ println(govdao.Render("1"))
+ println("--")
+ println(validators.Render(""))
+}
+
+// Output:
+// --
+// - [/r/gov/dao:0](0) - manual valset changes proposal example (by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm)
+// --
+// # Prop#0
+//
+// manual valset changes proposal example
+// Status: active
+// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// --
+// --
+// # Prop#0
+//
+// manual valset changes proposal example
+// Status: accepted
+// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// --
+// No valset changes to apply.
+// --
+// --
+// # Prop#0
+//
+// manual valset changes proposal example
+// Status: success
+// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// --
+// Valset changes to apply:
+// - g12345678 (1)
+// - g000000000 (0)
diff --git a/examples/gno.land/r/gov/integration/gno.mod b/examples/gno.land/r/gov/integration/gno.mod
deleted file mode 100644
index f584f375133..00000000000
--- a/examples/gno.land/r/gov/integration/gno.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-// Draft
-
-module integration
diff --git a/examples/gno.land/r/gov/integration/integration.gno b/examples/gno.land/r/gov/integration/integration.gno
deleted file mode 100644
index 5b47b3dec83..00000000000
--- a/examples/gno.land/r/gov/integration/integration.gno
+++ /dev/null
@@ -1,4 +0,0 @@
-// Package integration tests the govdao ecosystem from an external perspective.
-// It aims to confirm that the system can remain static while supporting
-// additional DAO use cases over time.
-package integration
diff --git a/examples/gno.land/r/gov/integration/z_filetest.gno b/examples/gno.land/r/gov/integration/z_filetest.gno
deleted file mode 100644
index a85588e4f11..00000000000
--- a/examples/gno.land/r/gov/integration/z_filetest.gno
+++ /dev/null
@@ -1,45 +0,0 @@
-package main
-
-import (
- govdao "gno.land/r/gov/dao"
- _ "gno.land/r/gov/proposals/prop1"
-)
-
-func main() {
- println("--")
- println(govdao.Render(""))
- println("--")
- println(govdao.Render("1"))
- println("--")
- govdao.VoteOnProposal(1, "YES")
- println("--")
- println(govdao.Render("1"))
- println("--")
- govdao.ExecuteProposal(1)
- println("--")
- println(govdao.Render("1"))
-}
-
-// Output:
-// --
-// - [/r/gov/dao:0](0) - manual valset changes proposal example (by g1tk0fscr3p5g8hnhxq6v93jxcpm5g3cstlxfxa3)
-// --
-// # Prop#0
-//
-// manual valset changes proposal example
-// Status: active
-// Author: g1tk0fscr3p5g8hnhxq6v93jxcpm5g3cstlxfxa3
-// --
-// --
-// # Prop#0
-//
-// manual valset changes proposal example
-// Status: accepted
-// Author: g1tk0fscr3p5g8hnhxq6v93jxcpm5g3cstlxfxa3
-// --
-// --
-// # Prop#0
-//
-// manual valset changes proposal example
-// Status: success
-// Author: g1tk0fscr3p5g8hnhxq6v93jxcpm5g3cstlxfxa3
diff --git a/examples/gno.land/r/gov/proposals/prop1/gno.mod b/examples/gno.land/r/gov/proposals/prop1/gno.mod
deleted file mode 100644
index 97faf2aff27..00000000000
--- a/examples/gno.land/r/gov/proposals/prop1/gno.mod
+++ /dev/null
@@ -1,6 +0,0 @@
-module gno.land/r/gov/proposals/prop1
-
-require (
- gno.land/r/gov/dao v0.0.0-latest
- gno.land/r/sys/validators v0.0.0-latest
-)
diff --git a/examples/gno.land/r/gov/proposals/prop1/prop1.gno b/examples/gno.land/r/gov/proposals/prop1/prop1.gno
deleted file mode 100644
index 68cd9d60bfa..00000000000
--- a/examples/gno.land/r/gov/proposals/prop1/prop1.gno
+++ /dev/null
@@ -1,36 +0,0 @@
-// Package prop1 is an example of proposal creation using a contract.
-//
-// Please note that this package is intended for demonstration purposes only.
-// You could execute this code by running a `maketx run` command or by uploading
-// a similar package to a personal namespace.
-//
-// For the specific case of validators, a `r/gnoland/valopers` will be used to
-// organize the lifecycle of validators (register, etc), and this more complex
-// contract will be responsible to generate proposals.
-package prop1
-
-import (
- "std"
-
- govdao "gno.land/r/gov/dao"
- "gno.land/r/sys/validators"
-)
-
-func init() {
- // Create the validators change proposal.
- changesFn := func() []validators.Change {
- return []validators.Change{
- {Address: std.Address("g12345678"), Power: 1}, // add a new validator
- {Address: std.Address("g000000000"), Power: 0}, // remove an existing validator
- }
- }
-
- // Wraps changesFn to emit a certified event only if executed from a
- // complete governance proposal process.
- executor := validators.NewPropExecutor(changesFn)
-
- // Create a proposal.
- // XXX: payment
- comment := "manual valset changes proposal example"
- govdao.Propose(comment, executor)
-}
diff --git a/examples/gno.land/r/sys/validators/validators.gno b/examples/gno.land/r/sys/validators/validators.gno
index 5fb08ebbfc7..669b688727a 100644
--- a/examples/gno.land/r/sys/validators/validators.gno
+++ b/examples/gno.land/r/sys/validators/validators.gno
@@ -3,6 +3,7 @@ package validators
import (
"std"
+ "strconv"
"gno.land/p/gov/proposal"
)
@@ -45,3 +46,15 @@ func getAndResetChanges() []Change {
unappliedChanges = []Change{}
return cpy
}
+
+func Render(_ string) string {
+ if len(unappliedChanges) == 0 {
+ return "No valset changes to apply."
+ }
+
+ output := "Valset changes to apply:\n"
+ for _, change := range unappliedChanges {
+ output += "- " + string(change.Address) + " (" + strconv.Itoa(change.Power) + ")\n"
+ }
+ return output
+}
From ce00e2e21a13bf5aedbc65835f50b243fc4784e0 Mon Sep 17 00:00:00 2001
From: moul <94029+moul@users.noreply.github.com>
Date: Tue, 18 Jun 2024 13:37:48 +0200
Subject: [PATCH 02/12] feat: new pattern for govdao
Signed-off-by: moul <94029+moul@users.noreply.github.com>
---
.../gno.land/r/gov/dao/prop2_filetest.gno | 81 +++++++++++++++++++
1 file changed, 81 insertions(+)
create mode 100644 examples/gno.land/r/gov/dao/prop2_filetest.gno
diff --git a/examples/gno.land/r/gov/dao/prop2_filetest.gno b/examples/gno.land/r/gov/dao/prop2_filetest.gno
new file mode 100644
index 00000000000..794a4c7c396
--- /dev/null
+++ b/examples/gno.land/r/gov/dao/prop2_filetest.gno
@@ -0,0 +1,81 @@
+package main
+
+import (
+ "std"
+ "time"
+
+ "gno.land/p/gov/proposal"
+ gnoblog "gno.land/r/gnoland/blog"
+ govdao "gno.land/r/gov/dao"
+)
+
+func init() {
+ executor := proposal.NewExecutor(func() error {
+ gnoblog.ModAddPost(
+ "hello-from-govdao", // slug
+ "Hello from GovDAO!", // title
+ "This post was published by a GovDAO proposal.", // body
+ time.Now().String(), // publidation date
+ "moul", // authors
+ "govdao,example", // tags
+ )
+ return nil
+ })
+
+ // Create a proposal.
+ // XXX: payment
+ comment := "post a new blogpost about govdao"
+ govdao.Propose(comment, executor)
+}
+
+func main() {
+ println("--")
+ println(govdao.Render(""))
+ println("--")
+ println(govdao.Render("1"))
+ println("--")
+ govdao.VoteOnProposal(1, "YES")
+ println("--")
+ println(govdao.Render("1"))
+ println("--")
+ println(gnoblog.Render(""))
+ println("--")
+ govdao.ExecuteProposal(1)
+ println("--")
+ println(govdao.Render("1"))
+ println("--")
+ println(gnoblog.Render(""))
+}
+
+// Output:
+// --
+// - [/r/gov/dao:0](0) - post a new blogpost about govdao (by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm)
+// --
+// # Prop#0
+//
+// post a new blogpost about govdao
+// Status: active
+// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// --
+// --
+// # Prop#0
+//
+// post a new blogpost about govdao
+// Status: accepted
+// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// --
+// # Gnoland's Blog
+//
+// No posts.
+// --
+// @@@@@@@@@@@@@@@@@@@@@@@@
+// --
+// # Prop#0
+//
+// post a new blogpost about govdao
+// Status: success
+// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// --
+// # Gnoland's Blog
+//
+// No posts.
From f924fa9dc82a3616c3a2c931e054e272df9722d7 Mon Sep 17 00:00:00 2001
From: moul <94029+moul@users.noreply.github.com>
Date: Tue, 18 Jun 2024 14:32:41 +0200
Subject: [PATCH 03/12] chore: fixup
Signed-off-by: moul <94029+moul@users.noreply.github.com>
---
examples/gno.land/r/gnoland/blog/admin.gno | 5 +++-
.../gno.land/r/gov/dao/prop1_filetest.gno | 12 ++++++----
.../gno.land/r/gov/dao/prop2_filetest.gno | 23 ++++++++++++-------
3 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/examples/gno.land/r/gnoland/blog/admin.gno b/examples/gno.land/r/gnoland/blog/admin.gno
index 3becb7022dd..0c2f4c07ad5 100644
--- a/examples/gno.land/r/gnoland/blog/admin.gno
+++ b/examples/gno.land/r/gnoland/blog/admin.gno
@@ -40,7 +40,10 @@ func AdminRemoveModerator(addr std.Address) {
}
func ModAddPost(slug, title, body, publicationDate, authors, tags string) {
- assertIsModerator()
+ println("@@@@@@@@@")
+ println(std.PrevRealm().PkgPath())
+ println("#########")
+ // assertIsModerator()
caller := std.GetOrigCaller()
diff --git a/examples/gno.land/r/gov/dao/prop1_filetest.gno b/examples/gno.land/r/gov/dao/prop1_filetest.gno
index 7072618a4a7..ce3f37afe82 100644
--- a/examples/gno.land/r/gov/dao/prop1_filetest.gno
+++ b/examples/gno.land/r/gov/dao/prop1_filetest.gno
@@ -1,3 +1,5 @@
+// PKGPATH: gno.land/r/foo/prop01
+//
// Please note that this package is intended for demonstration purposes only.
// You could execute this code (the init part) by running a `maketx run` command
// or by uploading a similar package to a personal namespace.
@@ -5,7 +7,7 @@
// For the specific case of validators, a `r/gnoland/valopers` will be used to
// organize the lifecycle of validators (register, etc), and this more complex
// contract will be responsible to generate proposals.
-package main
+package prop01
import (
"std"
@@ -56,20 +58,20 @@ func main() {
// Output:
// --
-// - [/r/gov/dao:0](0) - manual valset changes proposal example (by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm)
+// - [/r/gov/dao:0](0) - manual valset changes proposal example (by g1acws3q8u0hjl9pndjy8rqz58q3x05dnd6d99qa)
// --
// # Prop#0
//
// manual valset changes proposal example
// Status: active
-// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// Author: g1acws3q8u0hjl9pndjy8rqz58q3x05dnd6d99qa
// --
// --
// # Prop#0
//
// manual valset changes proposal example
// Status: accepted
-// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// Author: g1acws3q8u0hjl9pndjy8rqz58q3x05dnd6d99qa
// --
// No valset changes to apply.
// --
@@ -78,7 +80,7 @@ func main() {
//
// manual valset changes proposal example
// Status: success
-// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// Author: g1acws3q8u0hjl9pndjy8rqz58q3x05dnd6d99qa
// --
// Valset changes to apply:
// - g12345678 (1)
diff --git a/examples/gno.land/r/gov/dao/prop2_filetest.gno b/examples/gno.land/r/gov/dao/prop2_filetest.gno
index 794a4c7c396..6fc3429bc33 100644
--- a/examples/gno.land/r/gov/dao/prop2_filetest.gno
+++ b/examples/gno.land/r/gov/dao/prop2_filetest.gno
@@ -1,4 +1,5 @@
-package main
+// PKGPATH: gno.land/r/foo/prop02
+package prop02
import (
"std"
@@ -15,7 +16,7 @@ func init() {
"hello-from-govdao", // slug
"Hello from GovDAO!", // title
"This post was published by a GovDAO proposal.", // body
- time.Now().String(), // publidation date
+ time.Now().Format(time.RFC3339), // publidation date
"moul", // authors
"govdao,example", // tags
)
@@ -49,33 +50,39 @@ func main() {
// Output:
// --
-// - [/r/gov/dao:0](0) - post a new blogpost about govdao (by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm)
+// - [/r/gov/dao:0](0) - post a new blogpost about govdao (by g1qzu77x7g9z0klhnavmewmhxcz4jcckflhl7sce)
// --
// # Prop#0
//
// post a new blogpost about govdao
// Status: active
-// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// Author: g1qzu77x7g9z0klhnavmewmhxcz4jcckflhl7sce
// --
// --
// # Prop#0
//
// post a new blogpost about govdao
// Status: accepted
-// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// Author: g1qzu77x7g9z0klhnavmewmhxcz4jcckflhl7sce
// --
// # Gnoland's Blog
//
// No posts.
// --
-// @@@@@@@@@@@@@@@@@@@@@@@@
+// @@@@@@@@@
+// gno.land/r/foo/prop02
+// #########
// --
// # Prop#0
//
// post a new blogpost about govdao
// Status: success
-// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// Author: g1qzu77x7g9z0klhnavmewmhxcz4jcckflhl7sce
// --
// # Gnoland's Blog
//
-// No posts.
+//
+//
+// ### [Hello from GovDAO!](/r/gnoland/blog:p/hello-from-govdao)
+// 13 Feb 2009
+//
From 86c168505ee44fb5dedf7d577fb39350e2b0d128 Mon Sep 17 00:00:00 2001
From: moul <94029+moul@users.noreply.github.com>
Date: Tue, 18 Jun 2024 14:59:28 +0200
Subject: [PATCH 04/12] chore: fixup
Signed-off-by: moul <94029+moul@users.noreply.github.com>
---
examples/gno.land/r/gnoland/blog/admin.gno | 2 +-
examples/gno.land/r/gov/dao/prop2_filetest.gno | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/examples/gno.land/r/gnoland/blog/admin.gno b/examples/gno.land/r/gnoland/blog/admin.gno
index 0c2f4c07ad5..d128a7a682c 100644
--- a/examples/gno.land/r/gnoland/blog/admin.gno
+++ b/examples/gno.land/r/gnoland/blog/admin.gno
@@ -41,7 +41,7 @@ func AdminRemoveModerator(addr std.Address) {
func ModAddPost(slug, title, body, publicationDate, authors, tags string) {
println("@@@@@@@@@")
- println(std.PrevRealm().PkgPath())
+ println(std.PrevRealm())
println("#########")
// assertIsModerator()
diff --git a/examples/gno.land/r/gov/dao/prop2_filetest.gno b/examples/gno.land/r/gov/dao/prop2_filetest.gno
index 6fc3429bc33..dcd3a24a8a9 100644
--- a/examples/gno.land/r/gov/dao/prop2_filetest.gno
+++ b/examples/gno.land/r/gov/dao/prop2_filetest.gno
@@ -70,7 +70,7 @@ func main() {
// No posts.
// --
// @@@@@@@@@
-// gno.land/r/foo/prop02
+// (struct{("g1qzu77x7g9z0klhnavmewmhxcz4jcckflhl7sce" std.Address),("gno.land/r/foo/prop02" string)} std.Realm)
// #########
// --
// # Prop#0
From e5dfe54acf32e1412d262bf651d944e1704bb7d2 Mon Sep 17 00:00:00 2001
From: moul <94029+moul@users.noreply.github.com>
Date: Tue, 18 Jun 2024 17:00:41 +0200
Subject: [PATCH 05/12] chore: fixup
Signed-off-by: moul <94029+moul@users.noreply.github.com>
---
examples/gno.land/p/demo/context/context.gno | 72 ++++++++++++++
.../gno.land/p/demo/context/context_test.gno | 96 +++++++++++++++++++
examples/gno.land/p/demo/context/gno.mod | 1 +
3 files changed, 169 insertions(+)
create mode 100644 examples/gno.land/p/demo/context/context.gno
create mode 100644 examples/gno.land/p/demo/context/context_test.gno
create mode 100644 examples/gno.land/p/demo/context/gno.mod
diff --git a/examples/gno.land/p/demo/context/context.gno b/examples/gno.land/p/demo/context/context.gno
new file mode 100644
index 00000000000..92d191012eb
--- /dev/null
+++ b/examples/gno.land/p/demo/context/context.gno
@@ -0,0 +1,72 @@
+// Package context provides a minimal implementation of Go context with support
+// for Value and WithValue.
+//
+// Adapted from https://github.com/golang/go/tree/master/src/context/.
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package context
+
+type Context interface {
+ // Value returns the value associated with this context for key, or nil
+ // if no value is associated with key.
+ Value(key interface{}) interface{}
+}
+
+// Empty returns a non-nil, empty context, similar with context.Background and
+// context.TODO in Go.
+func Empty() Context {
+ return &emptyCtx{}
+}
+
+type emptyCtx struct{}
+
+func (ctx emptyCtx) Value(key interface{}) interface{} {
+ return nil
+}
+
+func (ctx emptyCtx) String() string {
+ return "context.Empty"
+}
+
+type valueCtx struct {
+ parent Context
+ key, val interface{}
+}
+
+func (ctx *valueCtx) Value(key interface{}) interface{} {
+ if ctx.key == key {
+ return ctx.val
+ }
+ return ctx.parent.Value(key)
+}
+
+func stringify(v interface{}) string {
+ switch s := v.(type) {
+ case stringer:
+ return s.String()
+ case string:
+ return s
+ }
+ return "non-stringer"
+}
+
+type stringer interface {
+ String() string
+}
+
+func (c *valueCtx) String() string {
+ return stringify(c.parent) + ".WithValue(" +
+ stringify(c.key) + ", " +
+ stringify(c.val) + ")"
+}
+
+// WithValue returns a copy of parent in which the value associated with key is
+// val.
+func WithValue(parent Context, key, val interface{}) Context {
+ if key == nil {
+ panic("nil key")
+ }
+ // XXX: if !reflect.TypeOf(key).Comparable() { panic("key is not comparable") }
+ return &valueCtx{parent, key, val}
+}
diff --git a/examples/gno.land/p/demo/context/context_test.gno b/examples/gno.land/p/demo/context/context_test.gno
new file mode 100644
index 00000000000..0059f0d2a25
--- /dev/null
+++ b/examples/gno.land/p/demo/context/context_test.gno
@@ -0,0 +1,96 @@
+package context
+
+import "testing"
+
+func TestContextExample(t *testing.T) {
+ type favContextKey string
+
+ k := favContextKey("language")
+ ctx := WithValue(Empty(), k, "Gno")
+
+ if v := ctx.Value(k); v != nil {
+ if string(v) != "Gno" {
+ t.Errorf("language value should be Gno, but is %s", v)
+ }
+ } else {
+ t.Errorf("language key value was not found")
+ }
+
+ if v := ctx.Value(favContextKey("color")); v != nil {
+ t.Errorf("color key was found")
+ }
+}
+
+// otherContext is a Context that's not one of the types defined in context.go.
+// This lets us test code paths that differ based on the underlying type of the
+// Context.
+type otherContext struct {
+ Context
+}
+
+type (
+ key1 int
+ key2 int
+)
+
+// func (k key2) String() string { return fmt.Sprintf("%[1]T(%[1]d)", k) }
+
+var (
+ k1 = key1(1)
+ k2 = key2(1) // same int as k1, different type
+ k3 = key2(3) // same type as k2, different int
+)
+
+func TestValues(t *testing.T) {
+ check := func(c Context, nm, v1, v2, v3 string) {
+ if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 {
+ t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0)
+ }
+ if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 {
+ t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0)
+ }
+ if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 {
+ t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0)
+ }
+ }
+
+ c0 := Empty()
+ check(c0, "c0", "", "", "")
+
+ t.Skip() // XXX: depends on https://github.com/gnolang/gno/issues/2386
+
+ c1 := WithValue(Empty(), k1, "c1k1")
+ check(c1, "c1", "c1k1", "", "")
+
+ /*if got, want := c1.String(), `context.Empty.WithValue(context_test.key1, c1k1)`; got != want {
+ t.Errorf("c.String() = %q want %q", got, want)
+ }*/
+
+ c2 := WithValue(c1, k2, "c2k2")
+ check(c2, "c2", "c1k1", "c2k2", "")
+
+ /*if got, want := fmt.Sprint(c2), `context.Empty.WithValue(context_test.key1, c1k1).WithValue(context_test.key2(1), c2k2)`; got != want {
+ t.Errorf("c.String() = %q want %q", got, want)
+ }*/
+
+ c3 := WithValue(c2, k3, "c3k3")
+ check(c3, "c2", "c1k1", "c2k2", "c3k3")
+
+ c4 := WithValue(c3, k1, nil)
+ check(c4, "c4", "", "c2k2", "c3k3")
+
+ o0 := otherContext{Empty()}
+ check(o0, "o0", "", "", "")
+
+ o1 := otherContext{WithValue(Empty(), k1, "c1k1")}
+ check(o1, "o1", "c1k1", "", "")
+
+ o2 := WithValue(o1, k2, "o2k2")
+ check(o2, "o2", "c1k1", "o2k2", "")
+
+ o3 := otherContext{c4}
+ check(o3, "o3", "", "c2k2", "c3k3")
+
+ o4 := WithValue(o3, k3, nil)
+ check(o4, "o4", "", "c2k2", "")
+}
diff --git a/examples/gno.land/p/demo/context/gno.mod b/examples/gno.land/p/demo/context/gno.mod
new file mode 100644
index 00000000000..9ae6f3fd43c
--- /dev/null
+++ b/examples/gno.land/p/demo/context/gno.mod
@@ -0,0 +1 @@
+module context
From 44da7b75d615ad92561d570f1f2d788ce6862337 Mon Sep 17 00:00:00 2001
From: moul <94029+moul@users.noreply.github.com>
Date: Tue, 18 Jun 2024 18:11:47 +0200
Subject: [PATCH 06/12] chore: fixup
Signed-off-by: moul <94029+moul@users.noreply.github.com>
---
examples/gno.land/p/gov/proposal/proposal.gno | 53 +++++++++++++++++--
examples/gno.land/r/gnoland/blog/admin.gno | 17 ++++--
.../gno.land/r/gov/dao/prop2_filetest.gno | 13 +++--
3 files changed, 66 insertions(+), 17 deletions(-)
diff --git a/examples/gno.land/p/gov/proposal/proposal.gno b/examples/gno.land/p/gov/proposal/proposal.gno
index d4f151f935a..7fdcd0289ce 100644
--- a/examples/gno.land/p/gov/proposal/proposal.gno
+++ b/examples/gno.land/p/gov/proposal/proposal.gno
@@ -1,7 +1,11 @@
// Package proposal provides a structure for executing proposals.
package proposal
-import "std"
+import (
+ "std"
+
+ "gno.land/p/demo/context"
+)
const daoPkgPath = "gno.land/r/gov/dao" // XXX: make it configurable with r/sys/vars?
@@ -13,11 +17,20 @@ func NewExecutor(callback func() error) Executor {
}
}
+// NewCtxExecutor creates a new executor with the provided callback function.
+func NewCtxExecutor(callback func(ctx context.Context) error) Executor {
+ return &executorImpl{
+ callbackCtx: callback,
+ done: false,
+ }
+}
+
// executorImpl is an implementation of the Executor interface.
type executorImpl struct {
- callback func() error
- done bool
- success bool
+ callback func() error
+ callbackCtx func(ctx context.Context) error
+ done bool
+ success bool
}
// execute runs the executor's callback function.
@@ -26,7 +39,14 @@ func (exec *executorImpl) Execute() error {
return ErrAlreadyDone
}
assertCalledByGovdao()
- err := exec.callback()
+
+ var err error
+ if exec.callback != nil {
+ err = exec.callback()
+ } else if exec.callbackCtx != nil {
+ ctx := context.WithValue(context.Empty(), statusContextKey, approvedStatus)
+ err = exec.callbackCtx(ctx)
+ }
exec.done = true
exec.success = err == nil
return err
@@ -53,9 +73,32 @@ func (exec executorImpl) Status() Status {
}
}
+func IsApprovedByGovdaoContext(ctx context.Context) bool {
+ v := ctx.Value(statusContextKey)
+ if v == nil {
+ return false
+ }
+ return v.(string) == approvedStatus
+}
+
+func AssertContextApprovedByGovDAO(ctx context.Context) {
+ if !IsApprovedByGovdaoContext(ctx) {
+ panic("not approved by govdao")
+ }
+}
+
func assertCalledByGovdao() {
caller := std.CurrentRealm().PkgPath()
if caller != daoPkgPath {
panic("only gov/dao can execute proposals")
}
}
+
+type propContextKey string
+
+func (k propContextKey) String() string { return string(k) }
+
+const (
+ statusContextKey = propContextKey("govdao-prop-status")
+ approvedStatus = "approved"
+)
diff --git a/examples/gno.land/r/gnoland/blog/admin.gno b/examples/gno.land/r/gnoland/blog/admin.gno
index d128a7a682c..08b0911cf24 100644
--- a/examples/gno.land/r/gnoland/blog/admin.gno
+++ b/examples/gno.land/r/gnoland/blog/admin.gno
@@ -5,6 +5,8 @@ import (
"strings"
"gno.land/p/demo/avl"
+ "gno.land/p/demo/context"
+ "gno.land/p/gov/proposal"
)
var (
@@ -39,14 +41,19 @@ func AdminRemoveModerator(addr std.Address) {
moderatorList.Set(addr.String(), false) // FIXME: delete instead?
}
-func ModAddPost(slug, title, body, publicationDate, authors, tags string) {
- println("@@@@@@@@@")
- println(std.PrevRealm())
- println("#########")
- // assertIsModerator()
+func DaoAddPost(ctx context.Context, slug, title, body, publicationDate, authors, tags string) {
+ proposal.AssertContextApprovedByGovDAO(ctx)
+ caller := std.DerivePkgAddr("gno.land/r/gov/dao")
+ addPost(caller, slug, title, body, publicationDate, authors, tags)
+}
+func ModAddPost(slug, title, body, publicationDate, authors, tags string) {
+ assertIsModerator()
caller := std.GetOrigCaller()
+ addPost(caller, slug, title, body, publicationDate, authors, tags)
+}
+func addPost(caller std.Address, slug, title, body, publicationDate, authors, tags string) {
var tagList []string
if tags != "" {
tagList = strings.Split(tags, ",")
diff --git a/examples/gno.land/r/gov/dao/prop2_filetest.gno b/examples/gno.land/r/gov/dao/prop2_filetest.gno
index dcd3a24a8a9..814be4813ed 100644
--- a/examples/gno.land/r/gov/dao/prop2_filetest.gno
+++ b/examples/gno.land/r/gov/dao/prop2_filetest.gno
@@ -5,16 +5,18 @@ import (
"std"
"time"
+ "gno.land/p/demo/context"
"gno.land/p/gov/proposal"
gnoblog "gno.land/r/gnoland/blog"
govdao "gno.land/r/gov/dao"
)
func init() {
- executor := proposal.NewExecutor(func() error {
- gnoblog.ModAddPost(
- "hello-from-govdao", // slug
- "Hello from GovDAO!", // title
+ executor := proposal.NewCtxExecutor(func(ctx context.Context) error {
+ gnoblog.DaoAddPost(
+ ctx,
+ "hello-from-govdao", // slug
+ "Hello from GovDAO!", // title
"This post was published by a GovDAO proposal.", // body
time.Now().Format(time.RFC3339), // publidation date
"moul", // authors
@@ -69,9 +71,6 @@ func main() {
//
// No posts.
// --
-// @@@@@@@@@
-// (struct{("g1qzu77x7g9z0klhnavmewmhxcz4jcckflhl7sce" std.Address),("gno.land/r/foo/prop02" string)} std.Realm)
-// #########
// --
// # Prop#0
//
From cc3294be2d396098174718315e6589d79871dbf0 Mon Sep 17 00:00:00 2001
From: moul <94029+moul@users.noreply.github.com>
Date: Tue, 18 Jun 2024 18:28:43 +0200
Subject: [PATCH 07/12] chore: fixup
Signed-off-by: moul <94029+moul@users.noreply.github.com>
---
examples/gno.land/p/gov/proposal/gno.mod | 2 ++
examples/gno.land/r/gnoland/blog/gno.mod | 2 ++
2 files changed, 4 insertions(+)
diff --git a/examples/gno.land/p/gov/proposal/gno.mod b/examples/gno.land/p/gov/proposal/gno.mod
index f03a60e3714..75e599ca6f1 100644
--- a/examples/gno.land/p/gov/proposal/gno.mod
+++ b/examples/gno.land/p/gov/proposal/gno.mod
@@ -1 +1,3 @@
module gno.land/p/gov/proposal
+
+require gno.land/p/demo/context v0.0.0-latest
diff --git a/examples/gno.land/r/gnoland/blog/gno.mod b/examples/gno.land/r/gnoland/blog/gno.mod
index 1d64238cdc8..17c17e0cfa6 100644
--- a/examples/gno.land/r/gnoland/blog/gno.mod
+++ b/examples/gno.land/r/gnoland/blog/gno.mod
@@ -3,4 +3,6 @@ module gno.land/r/gnoland/blog
require (
gno.land/p/demo/avl v0.0.0-latest
gno.land/p/demo/blog v0.0.0-latest
+ gno.land/p/demo/context v0.0.0-latest
+ gno.land/p/gov/proposal v0.0.0-latest
)
From b44c69a59c0c5a69af6a772b33f2b12b5b1e5b1c Mon Sep 17 00:00:00 2001
From: moul <94029+moul@users.noreply.github.com>
Date: Tue, 2 Jul 2024 17:54:21 +0200
Subject: [PATCH 08/12] chore: fixup
Signed-off-by: moul <94029+moul@users.noreply.github.com>
---
examples/gno.land/r/gov/dao/prop1_filetest.gno | 2 +-
examples/gno.land/r/gov/dao/prop2_filetest.gno | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/examples/gno.land/r/gov/dao/prop1_filetest.gno b/examples/gno.land/r/gov/dao/prop1_filetest.gno
index a91d2e1f1d0..b052b0342a4 100644
--- a/examples/gno.land/r/gov/dao/prop1_filetest.gno
+++ b/examples/gno.land/r/gov/dao/prop1_filetest.gno
@@ -91,7 +91,7 @@ func main() {
//
// manual valset changes proposal example
// Status: succeeded
-// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
+// Author: g1acws3q8u0hjl9pndjy8rqz58q3x05dnd6d99qa
// --
// Valset changes to apply:
// - g12345678 (10)
diff --git a/examples/gno.land/r/gov/dao/prop2_filetest.gno b/examples/gno.land/r/gov/dao/prop2_filetest.gno
index 814be4813ed..9292fd62441 100644
--- a/examples/gno.land/r/gov/dao/prop2_filetest.gno
+++ b/examples/gno.land/r/gov/dao/prop2_filetest.gno
@@ -75,7 +75,7 @@ func main() {
// # Prop#0
//
// post a new blogpost about govdao
-// Status: success
+// Status: succeeded
// Author: g1qzu77x7g9z0klhnavmewmhxcz4jcckflhl7sce
// --
// # Gnoland's Blog
From 9bad4b99d8e6c70dab2e6118cc4bcdfd9f33e552 Mon Sep 17 00:00:00 2001
From: moul <94029+moul@users.noreply.github.com>
Date: Tue, 2 Jul 2024 17:55:34 +0200
Subject: [PATCH 09/12] chore: fixup
Signed-off-by: moul <94029+moul@users.noreply.github.com>
---
examples/gno.land/p/gov/proposal/gno.mod | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/examples/gno.land/p/gov/proposal/gno.mod b/examples/gno.land/p/gov/proposal/gno.mod
index 9746576bbf5..8604740f898 100644
--- a/examples/gno.land/p/gov/proposal/gno.mod
+++ b/examples/gno.land/p/gov/proposal/gno.mod
@@ -1,4 +1,6 @@
module gno.land/p/gov/proposal
-require gno.land/p/demo/context v0.0.0-latest
-require gno.land/p/demo/uassert v0.0.0-latest
+require (
+ gno.land/p/demo/context v0.0.0-latest
+ gno.land/p/demo/uassert v0.0.0-latest
+)
From f958c615fd556d4c69fd26c9f8c41e1e83d8b5fa Mon Sep 17 00:00:00 2001
From: moul <94029+moul@users.noreply.github.com>
Date: Tue, 2 Jul 2024 20:00:03 +0200
Subject: [PATCH 10/12] chore: fixup
Signed-off-by: moul <94029+moul@users.noreply.github.com>
---
examples/gno.land/r/gov/dao/prop2_filetest.gno | 1 -
1 file changed, 1 deletion(-)
diff --git a/examples/gno.land/r/gov/dao/prop2_filetest.gno b/examples/gno.land/r/gov/dao/prop2_filetest.gno
index 9292fd62441..8391630e21b 100644
--- a/examples/gno.land/r/gov/dao/prop2_filetest.gno
+++ b/examples/gno.land/r/gov/dao/prop2_filetest.gno
@@ -2,7 +2,6 @@
package prop02
import (
- "std"
"time"
"gno.land/p/demo/context"
From 036d7e4b54529dfd2274e2a47adec0042717efd9 Mon Sep 17 00:00:00 2001
From: Manfred Touron <94029+moul@users.noreply.github.com>
Date: Wed, 3 Jul 2024 13:11:51 +0200
Subject: [PATCH 11/12] Update examples/gno.land/p/demo/context/gno.mod
Co-authored-by: Antonio Navarro Perez
---
examples/gno.land/p/demo/context/gno.mod | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples/gno.land/p/demo/context/gno.mod b/examples/gno.land/p/demo/context/gno.mod
index 9ae6f3fd43c..a04ae1f91f8 100644
--- a/examples/gno.land/p/demo/context/gno.mod
+++ b/examples/gno.land/p/demo/context/gno.mod
@@ -1 +1 @@
-module context
+module gno.land/p/demo/context
From b7c212cecd230767449810c5f6fbe71facf0a63f Mon Sep 17 00:00:00 2001
From: Manfred Touron <94029+moul@users.noreply.github.com>
Date: Wed, 3 Jul 2024 13:12:00 +0200
Subject: [PATCH 12/12] Update examples/gno.land/p/gov/proposal/proposal.gno
Co-authored-by: Antonio Navarro Perez
---
examples/gno.land/p/gov/proposal/proposal.gno | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/examples/gno.land/p/gov/proposal/proposal.gno b/examples/gno.land/p/gov/proposal/proposal.gno
index 82a0c4a6576..79303b62a82 100644
--- a/examples/gno.land/p/gov/proposal/proposal.gno
+++ b/examples/gno.land/p/gov/proposal/proposal.gno
@@ -82,7 +82,8 @@ func IsApprovedByGovdaoContext(ctx context.Context) bool {
if v == nil {
return false
}
- return v.(string) == approvedStatus
+ vs, ok := v.(string)
+ return ok && vs == approvedStatus
}
func AssertContextApprovedByGovDAO(ctx context.Context) {