Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}