-
Notifications
You must be signed in to change notification settings - Fork 370
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: r/gov/dao
v2
#2581
base: master
Are you sure you want to change the base?
feat: r/gov/dao
v2
#2581
Conversation
The high-level feedback is:
|
import "strings" | ||
|
||
// CombinedError is a combined execution error | ||
type CombinedError struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p/combinederr
? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved:
"gno.land/p/demo/context" | ||
"gno.land/p/gov/proposal" | ||
"gno.land/p/demo/dao" | ||
govdao "gno.land/r/gov/dao/v2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should not depend on a specific govdao version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved in:
"gno.land/p/demo/ufmt" | ||
pVals "gno.land/p/sys/validators" | ||
govdao "gno.land/r/gov/dao" | ||
"gno.land/r/sys/validators" | ||
govdao "gno.land/r/gov/dao/v2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should find a solution to avoid depending on a specific GovDAO version.
You can either use another mechanism or create a r/valopers/v2/govdaov2
helper package. This will allow us to build the necessary bridge if we switch to GovDAO v3.
Let me know if you can't find an elegant solution, and I can help you brainstorm one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried to apply the proxy pattern you've mentioned, and I think it fits in nice. Realms that require an expanded GovDAO API will just define their own "bridge", or have some kind of update mechanism.
Let me know what you think:
// Craft the proposal comment | ||
comment := ufmt.Sprintf( | ||
// Craft the proposal description | ||
description := ufmt.Sprintf( | ||
"Proposal to add valoper %s (Address: %s; PubKey: %s) to the valset", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Proposal to add valoper %s (Address: %s; PubKey: %s) to the valset", | |
"Add valoper %s (Address: %s; PubKey: %s) to the valset", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed:
|
||
// maxRequestVotes is the maximum number of | ||
// paginated votes that can be requested | ||
maxRequestVotes = 50 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dropped:
gno.land/p/nt/poa v0.0.0-latest | ||
gno.land/p/sys/validators v0.0.0-latest | ||
gno.land/r/gov/dao/v2 v0.0.0-latest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r/sys/validators shouldn't depend on r/gov/dao/v2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved in:
} | ||
|
||
// Proposal is the single proposal abstraction | ||
type Proposal interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self: Wouldn't it be better and more secure to use a struct here? What if we define a custom struct that implements the interface for an attack?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fine to leave the implementation details of the proposal up to the package / realm creator:
// Proposal is the single proposal abstraction
type Proposal interface {
// Author returns the author of the proposal
Author() std.Address
// Description returns the description of the proposal
Description() string
// Status returns the status of the proposal
Status() ProposalStatus
// Executor returns the proposal executor
Executor() Executor
// Stats returns the voting stats of the proposal
Stats() Stats
// IsExpired returns a flag indicating if the proposal expired
IsExpired() bool
// Render renders the proposal in a readable format
Render() string
}
The Package
abstraction is completely read-only anyways. An example of this is the simpledao.proposal
, which is an implementation of a Proposal
that has tally information
@@ -0,0 +1,70 @@ | |||
package dao |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment to explain that the vote will be removed from this p/demo/dao package. A DAO shouldn't have to comply with or define how the voting mechanism works internally; it should be viewed as an entity that makes decisions. Therefore, we should focus on the proposal rather than the votes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to merge this PR soon, so I'm in favor of just adding the comment. However, please note that this is the biggest weakness of this implementation, and it's the only issue I see that will require us to create a v2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked, it turns out the extent of "votes" being present in the dao package is just in the context of a single type Stats
. We don't enforce a voting strategy in the p/demo/dao
package, at all.
simpledao
, which is a DAO implementation, exposes its own vote method, that is not standard.
I've added a comment to make it clear:
func WithInitialMembers(members []Member) Option { | ||
return func(store *MembStore) { | ||
for _, m := range members { | ||
store.members.Set(m.Address.String(), m) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check for ErrAlreadyMember
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added check, good catch:
status dao.ProposalStatus // status of the proposal | ||
|
||
tally *tally // voting tally | ||
getTotalVotingPowerFn func() uint64 // callback for the total voting power |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't get the reason for having this callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Voting power information is not contained in the proposal, but in the membstore that's associated with the DAO. We need this callback to construct the proposal stats:
func (p *proposal) Stats() dao.Stats {
// Get the total voting power of the body
totalPower := p.getTotalVotingPowerFn()
return dao.Stats{
YayVotes: p.tally.yays,
NayVotes: p.tally.nays,
AbstainVotes: p.tally.abstains,
TotalVotingPower: totalPower,
}
}
We set it when initializing the proposal:
// Create the wrapped proposal
prop := &proposal{
author: caller,
description: request.Description,
executor: request.Executor,
status: dao.Active,
tally: newTally(),
getTotalVotingPowerFn: s.membStore.TotalPower,
}
Co-authored-by: Manfred Touron <[email protected]>
…/gno into dev/zivkovicmilos/govdao
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly doc nitpicking comments, one clarification needed about missing vs abstain votes, and a suggestion on members() method.
|
||
import "strings" | ||
|
||
// CombinedError is a combined execution error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// CombinedError is a combined execution error | |
// CombinedError is a combined execution error. |
Nitpick: in comments, sentences end with a period. It can be enforced by a linter. I only reported this line, but there are many other occurences of missing period.
// ACTIVE -> ACCEPTED -> EXECUTION(SUCCEEDED/FAILED) | ||
// ACTIVE -> NOT ACCEPTED |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: these comment lines should be part of a comment block for type ProposalStatus string
declaration, with a short explanation sentence.
We should use a linter for missing comments for exports.
|
||
return m | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// AddMember adds member to the member store `m`. | |
// It fails if `m` is not a GovDAO or if member is already in store. |
|
||
return nil | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// UpdateMember updates the MembStore in case of change of member address or voting power. | |
// It fails if the MembStore is not a a GovDAO. |
|
||
type VoteOption string | ||
|
||
const ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be an option DidNotVote
at iota
, as it indicates a missing vote, different from voluntary abstention? What impact on decision rules, quorum, etc?
I see that later in the code you keep track of missing votes (it is always useful), but it is not clear to me if, when and why missing vote == abstain, in the context of a generic govDAO where provided specific governance rules could be different.
|
||
return nil | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// IsMember returns true if the member associated with address is in m store. |
|
||
return exists | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Member returns the member entry in m corresponding to address, or an error if not present. |
|
||
return member.(Member), nil | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had difficuties to understand Members()
API. May be it would help it you keep the same idiom as Go slices: if m was a Go array, members(start, end uint64) would return m[start:end].
func (m *MembStore) Size() int { | ||
return m.members.Size() | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Size() returns the number of members of the member store. |
Description
This PR introduces an upgrade to the
r/gov/dao
system:p/demo/simpledao
implementationContributors' checklist...
BREAKING CHANGE: xxx
message was included in the description