Search Apps Documentation Source Content File Folder Download Copy Actions Download

proxy.gno

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