proxy.gno
4.31 Kb ยท 160 lines
1package dao
2
3import "std"
4
5// dao is the actual govDAO implementation, having all the needed business logic
6var dao DAO
7
8// AllowedDAOs contains realms that can be used to update the actual govDAO implementation,
9// and validate Proposals.
10// This is like that to be able to rollback using a previous govDAO implementation in case
11// the latest implementation has a breaking bug. After a test period, a proposal can be
12// executed to remove all previous govDAOs implementations and leave the last one.
13var AllowedDAOs []string
14
15// proposals contains all the proposals in history.
16var proposals *Proposals = NewProposals()
17
18// Remember this realm for rendering.
19var gRealm = std.CurrentRealm()
20
21// Render calls directly to Render's DAO implementation.
22// This allows to have this realm as the main entry point for everything.
23func Render(p string) string {
24 return dao.Render(gRealm.PkgPath(), p)
25}
26
27// MustCreateProposal is an utility method that does the same as CreateProposal,
28// but instead of erroing if something happens, it panics.
29func MustCreateProposal(cur realm, r ProposalRequest) ProposalID {
30 pid, err := CreateProposal(cur, r)
31 if err != nil {
32 panic(err.Error())
33 }
34
35 return pid
36}
37
38// ExecuteProposal will try to execute the proposal with the provided ProposalID.
39// If the proposal was denied, it will return false. If the proposal is correctly
40// executed, it will return true. If something happens this function will panic.
41func ExecuteProposal(cur realm, pid ProposalID) bool {
42 execute, err := dao.PreExecuteProposal(pid)
43 if err != nil {
44 panic(err.Error())
45 }
46
47 if !execute {
48 return false
49 }
50 prop, err := GetProposal(cur, pid)
51 if err != nil {
52 panic(err.Error())
53 }
54 if err := prop.executor.Execute(); err != nil {
55 panic(err.Error())
56 }
57 return true
58}
59
60// CreateProposal will try to create a new proposal, that will be validated by the actual
61// govDAO implementation. If the proposal cannot be created, an error will be returned.
62func CreateProposal(cur realm, r ProposalRequest) (ProposalID, error) {
63 author, err := dao.PreCreateProposal(r)
64 if err != nil {
65 return -1, err
66 }
67
68 p := &Proposal{
69 author: author,
70 title: r.title,
71 description: r.description,
72 executor: r.executor,
73 allowedDAOs: AllowedDAOs[:],
74 }
75
76 pid := proposals.SetProposal(p)
77 dao.PostCreateProposal(r, pid)
78
79 return pid, nil
80}
81
82func MustVoteOnProposal(cur realm, r VoteRequest) {
83 if err := VoteOnProposal(cur, r); err != nil {
84 panic(err.Error())
85 }
86}
87
88// VoteOnProposal sends a vote to the actual govDAO implementation.
89// If the voter cannot vote the specified proposal, this method will return an error
90// with the explanation of why.
91func VoteOnProposal(cur realm, r VoteRequest) error {
92 return dao.VoteOnProposal(r)
93}
94
95// MustVoteOnProposalSimple is like MustVoteOnProposal but intended to be used through gnokey with basic types.
96func MustVoteOnProposalSimple(cur realm, pid int64, option string) {
97 MustVoteOnProposal(cur, VoteRequest{
98 Option: VoteOption(option),
99 ProposalID: ProposalID(pid),
100 })
101}
102
103func MustGetProposal(cur realm, pid ProposalID) *Proposal {
104 p, err := GetProposal(cur, pid)
105 if err != nil {
106 panic(err.Error())
107 }
108
109 return p
110}
111
112// GetProposal gets created proposal by its ID
113func GetProposal(cur realm, pid ProposalID) (*Proposal, error) {
114 if err := dao.PreGetProposal(pid); err != nil {
115 return nil, err
116 }
117
118 prop := proposals.GetProposal(pid)
119
120 if err := dao.PostGetProposal(pid, prop); err != nil {
121 return nil, err
122 }
123
124 return prop, nil
125}
126
127// UpdateImpl is a method intended to be used on a proposal.
128// This method will update the current govDAO implementation
129// to a new one. AllowedDAOs are a list of realms that can
130// call this method, in case the new DAO implementation had
131// a breaking bug. Any value set as nil will be ignored.
132// If AllowedDAOs field is not set correctly, the actual DAO
133// implementation wont be able to execute new Proposals!
134func UpdateImpl(cur realm, r UpdateRequest) {
135 gRealm := std.PreviousRealm().PkgPath()
136
137 if !InAllowedDAOs(gRealm) {
138 panic("permission denied for prev realm: " + gRealm)
139 }
140
141 if r.AllowedDAOs != nil {
142 AllowedDAOs = r.AllowedDAOs
143 }
144
145 if r.DAO != nil {
146 dao = r.DAO
147 }
148}
149
150func InAllowedDAOs(pkg string) bool {
151 if len(AllowedDAOs) == 0 {
152 return true // corner case for initialization
153 }
154 for _, d := range AllowedDAOs {
155 if pkg == d {
156 return true
157 }
158 }
159 return false
160}