channels_host.gno
4.06 Kb · 91 lines
1package memba_weighted_host
2
3import (
4 "chain"
5 "gno.land/p/samcrew/memba_weighted_policy"
6)
7
8type ChannelsState struct {
9 Owner, PendingOwner address
10 Paused bool
11 MemberCount int
12 MembershipRevision uint64
13 OwnerMember, DAOMember, SuccessorMember, SubjectMember bool
14 OwnerRoles, DAORoles, SuccessorRoles, SubjectRoles string
15 ChannelCount int
16 ChannelExists bool
17 ChannelDescription, ChannelType, ChannelReadRoles, ChannelWriteRoles string
18}
19type channelsProposal struct { action ChannelsAction; before ChannelsState }
20
21func channelsCommitment(a ChannelsAction, s ChannelsState) string {
22 return a.Bytes()+"|before|"+channelsStateJSON(s)
23}
24func (h *Host) validateChannels(a ChannelsAction, s ChannelsState) {
25 if h.channelsPolicy==nil { panic("channels actions are not configured") }
26 a.Bytes()
27 p:=h.channelsPolicy
28 if !s.Owner.IsValid() || (s.PendingOwner!="" && !s.PendingOwner.IsValid()) || s.MemberCount<1 || !s.OwnerMember || s.ChannelCount<0 || s.ChannelCount>20 {
29 panic("invalid channels authority pre-state")
30 }
31 if a.Subject()=="" && (s.SubjectMember || s.SubjectRoles!="") { panic("unexpected channels subject pre-state") }
32 if a.Name()=="" && (s.ChannelExists || s.ChannelDescription!="" || s.ChannelType!="" || s.ChannelReadRoles!="" || s.ChannelWriteRoles!="") { panic("unexpected channels creation pre-state") }
33 if a.Kind()==ChannelsAcceptOwner {
34 if s.Owner==p.DAO() || s.PendingOwner!=p.DAO() || s.DAOMember {
35 panic("DAO is not pending channels owner or already has membership")
36 }
37 return
38 }
39 if s.Owner!=p.DAO() || !s.DAOMember || s.DAORoles!=s.OwnerRoles { panic("DAO is not channels owner") }
40 if a.Kind()==ChannelsAbortReturn {
41 if a.Recipient()!=p.Successor() || s.PendingOwner!=p.Successor() { panic("channels return does not match policy") }
42 return
43 }
44 if s.PendingOwner!="" { panic("channels authority transfer is pending") }
45 switch a.Kind() {
46 case ChannelsReturnOwner:
47 if a.Recipient()!=p.Successor() || s.SuccessorMember { panic("channels successor mismatch or preexisting membership") }
48 case ChannelsAddMember, ChannelsRemoveMember, ChannelsSetRoles:
49 if a.Subject()==p.DAO() || a.Subject()==chain.PackageAddress(ChannelsPath) || (a.Subject()==p.Successor() && a.Kind()!=ChannelsRemoveMember) {
50 panic("channels member action targets protected authority")
51 }
52 if a.Kind()==ChannelsAddMember && s.SubjectMember { panic("channels member already exists") }
53 if a.Kind()!=ChannelsAddMember && !s.SubjectMember { panic("channels member does not exist") }
54 if a.Kind()==ChannelsSetRoles && s.SubjectRoles==a.Roles() { panic("channels roles are unchanged") }
55 case ChannelsCreateText:
56 if s.ChannelCount>=20 || s.ChannelExists { panic("channels text creation unavailable") }
57 case ChannelsUnpause:
58 if !s.Paused { panic("channels unpause is a no-op") }
59 default: panic("unsupported channels action")
60 }
61}
62func (h *Host) ProposeChannels(a ChannelsAction, s ChannelsState, rlm realm) uint64 {
63 who:=assertCaller(h,rlm)
64 h.validateChannels(a,s)
65 p:=&roleProposal{proposer:who,channels:&channelsProposal{action:a,before:s}}
66 p.ballot=h.policy.NewProposal(a.Category(),channelsCommitment(a,s))
67 h.addProposal(p)
68 return uint64(len(h.proposals))
69}
70func (h *Host) invalidateChannelsPeers(cause string, id uint64) {
71 members:=[]memba_weighted_policy.Member{}
72 for _,seat:=range h.seats { members=append(members,seat.Member) }
73 h.policy.Reconfigure(members)
74 h.recordInvalidation(cause, id, ChannelsPath)
75}
76func (h *Host) ConsumeChannels(id uint64, s ChannelsState, rlm realm) ChannelsAction {
77 assertCaller(h,rlm)
78 p:=h.proposal(id)
79 if p.channels==nil { panic("proposal is not a channels action") }
80 h.validateChannels(p.channels.action,s)
81 p.ballot.Consume(channelsCommitment(p.channels.action,s))
82 h.invalidateChannelsPeers(InvalidatedByExecution, id)
83 return p.channels.action
84}
85func (h *Host) PrepareChannelsEmergencyPause(s ChannelsState, rlm realm) {
86 assertCaller(h,rlm)
87 if h.channelsPolicy==nil || s.Owner!=h.channelsPolicy.DAO() || s.Paused || !s.OwnerMember || !s.DAOMember || s.DAORoles!=s.OwnerRoles {
88 panic("channels emergency pause unavailable")
89 }
90 h.invalidateChannelsPeers(InvalidatedByPause, 0)
91}