~edwargix/tallyard

1ebfb2cdb5f570e8e529097757a018f28c9cdca9 — David Florness 4 years ago efe483b
Remove support for result message

In preparation for a release, I'm going to remove the xyz.tallyard.result
message type for now.  Right now it serves no purpose; anyone who wants to know
an election's result need only calculate it themselves with the sums events.
5 files changed, 1 insertions(+), 153 deletions(-)

M cmd/tallyard/main.go
M election/event.go
M election/msg.go
M election/result.go
M election/voter.go
M cmd/tallyard/main.go => cmd/tallyard/main.go +0 -9
@@ 37,7 37,6 @@ var electionFilter = &mautrix.Filter{
				election.StartElectionMessage,
				election.EvalsMessage,
				election.SumMessage,
				election.ResultMessage,
			},
		},
	},


@@ 153,14 152,6 @@ func main() {
		}
	}

	// send result if needed
	if el.LocalVoter.Result == nil {
		err = el.SendResult(client, elections.EventStore)
		if err != nil {
			panic(err)
		}
	}

	el.PrintResults()

	el.Finish()

M election/event.go => election/event.go +0 -22
@@ 57,8 57,6 @@ func (store *EventStore) UnmarshalJSON(b []byte) error {
			event.Type = EvalsMessage
		case SumMessage.Type:
			event.Type = SumMessage
		case ResultMessage.Type:
			event.Type = ResultMessage
		}
		if err = event.Content.ParseRaw(event.Type); err != nil {
			return err


@@ 92,11 90,6 @@ type SumEvent struct {
	*SumMessageContent
}

type ResultEvent struct {
	*event.Event
	*ResultMessageContent
}

func (store *EventStore) GetCreateEvent(roomID id.RoomID, createID id.EventID) *CreateEvent {
	evt, err := store.getAndHandleEvent(roomID, createID, CreateElectionMessage)
	if err != nil {


@@ 172,21 165,6 @@ func (store *EventStore) GetSumEvent(roomID id.RoomID, sumID id.EventID) *SumEve
	}
}

func (store *EventStore) GetResultEvent(roomID id.RoomID, resultID id.EventID) *ResultEvent {
	evt, err := store.getAndHandleEvent(roomID, resultID, ResultMessage)
	if err != nil {
		log.Warnf("an error occurred getting result event '%s': %s", resultID, err)
		return nil
	}
	if evt == nil {
		return nil
	}
	return &ResultEvent{
		evt,
		evt.Content.Parsed.(*ResultMessageContent),
	}
}

func (store *EventStore) getAndHandleEvent(roomID id.RoomID, eventID id.EventID, eventType event.Type) (*event.Event, error) {
	// see if we've handled this event before
	store.RLock()

M election/msg.go => election/msg.go +0 -93
@@ 41,11 41,6 @@ var (
		Type:  "xyz.tallyard.sum",
		Class: event.MessageEventType,
	}
	// everyone announces their result at the end
	ResultMessage = event.Type{
		Type:  "xyz.tallyard.result",
		Class: event.MessageEventType,
	}
)

type CreateElectionContent struct {


@@ 100,7 95,6 @@ func init() {
	event.TypeMap[StartElectionMessage]  = reflect.TypeOf(StartElectionContent{})
	event.TypeMap[EvalsMessage]          = reflect.TypeOf(EvalsMessageContent{})
	event.TypeMap[SumMessage]            = reflect.TypeOf(SumMessageContent{})
	event.TypeMap[ResultMessage]         = reflect.TypeOf(ResultMessageContent{})
}

func (elections *ElectionsMap) SetupEventHooks(client *mautrix.Client, syncer mautrix.ExtensibleSyncer) {


@@ 148,7 142,6 @@ func (elections *ElectionsMap) SetupEventHooks(client *mautrix.Client, syncer ma
	eventHandlers[StartElectionMessage]  = wrapper(elections.onStartElectionMessage)
	eventHandlers[EvalsMessage]          = wrapper(elections.onEvalsMessage)
	eventHandlers[SumMessage]            = wrapper(elections.onSumMessage)
	eventHandlers[ResultMessage]         = wrapper(elections.onResultMessage)

	for eventType, handler := range eventHandlers {
		func(handler func(*event.Event) bool) {


@@ 512,89 505,3 @@ func (elections *ElectionsMap) onSumMessage(evt *event.Event) (success bool) {

	return true
}

func (elections *ElectionsMap) onResultMessage(evt *event.Event) (success bool) {
	errorf, warnf, debugf := logFuncs(fmt.Sprintf("ignoring %s's result msg (%s) since %s", evt.Sender, evt.ID, "%s"))

	content, ok := evt.Content.Parsed.(*ResultMessageContent)
	if !ok {
		warnf("we couldn't cast message content to ResultMessageContent")
		return
	}

	if incompatibleVersion(content.Version) {
		debugf("the version is incompatible")
		return
	}

	if len(content.SumIDs) == 0 {
		warnf("sums length is zero")
		return
	}

	var evalsIDs map[id.EventID]struct{}

	for _, sumID := range content.SumIDs {
		sumEvt := elections.EventStore.GetSumEvent(evt.RoomID, sumID)
		if sumEvt == nil {
			warnf("we couldn't get the sum event %s", sumID)
			return
		}
		if evalsIDs == nil {
			// run on first iteration only
			evalsIDs = make(map[id.EventID]struct{})
			for _, evalID := range sumEvt.EvalsIDs {
				evalsIDs[evalID] = struct{}{}
			}
			continue
		}
		if len(sumEvt.EvalsIDs) != len(evalsIDs) {
			warnf("sum events %s and %s don't have the same number of evals events",
				sumID, content.SumIDs[0])
		}
		for _, evalsID := range sumEvt.EvalsIDs {
			if _, exists := evalsIDs[evalsID]; !exists {
				warnf("evals ID %s exists in one evals event but not another", evalsID)
				return
			}
		}
	}

	joinEvt := elections.EventStore.GetJoinEvent(evt.RoomID, content.JoinID)
	if joinEvt == nil {
		debugf("we couldn't get the join, %s", content.JoinID)
		return
	}

	el := elections.GetElection(joinEvt.CreateID)
	if el == nil {
		// should never happen because we retrieved the join event
		errorf("election %s doesn't exist", joinEvt.CreateID)
		return
	}

	el.Lock()
	defer el.Save()
	defer el.Unlock()

	voter := el.Joins[joinEvt.ID]
	if voter == nil {
		errorf("voter %s doesn't exist", joinEvt.ID)
		return
	}

	if voter.Result != nil {
		warnf("voter %s submitted multiple results", joinEvt.ID)
		return
	}

	result, err := base64.StdEncoding.DecodeString(content.Result)
	if err != nil {
		warnf("we couldn't decode the result: %s", err)
		return
	}

	voter.Result = &result

	return true
}

M election/result.go => election/result.go +1 -27
@@ 1,7 1,6 @@
package election

import (
	"encoding/base64"
	"fmt"
	"math/big"
	"sort"


@@ 9,12 8,11 @@ import (
	"time"

	log "github.com/sirupsen/logrus"
	"maunium.net/go/mautrix"
	"maunium.net/go/mautrix/id"
	"tallyard.xyz/math"
)

func (el *Election) SendResult(client *mautrix.Client, eventStore *EventStore) error {
func (el *Election) PrintResults() {
	var sumIDs []id.EventID
	var wg sync.WaitGroup
	for _, voterJoinId := range *el.FinalJoinIDs {


@@ 40,30 38,6 @@ func (el *Election) SendResult(client *mautrix.Client, eventStore *EventStore) e
	diff := (len(el.Candidates) * len(el.Candidates)) - len(result)
	result = append(make([]byte, diff), result...)

	resp, err := client.SendMessageEvent(el.RoomID, ResultMessage, ResultMessageContent{
		Version: Version,
		JoinID:  el.LocalVoter.JoinEvt.ID,
		Result:  base64.StdEncoding.EncodeToString(result),
		SumIDs:  sumIDs,
	})
	if err != nil {
		return err
	}

	resultEvt := eventStore.GetResultEvent(el.RoomID, resp.EventID)
	if resultEvt == nil {
		return fmt.Errorf("couldn't process our own result event, %s", resp.EventID)
	}

	return nil
}

func (el *Election) PrintResults() {
	if el.LocalVoter.Result == nil {
		log.Error("PrintResults called before SendResult")
		return
	}
	result := *el.LocalVoter.Result
	candidates := el.Candidates

	log.Debugf("result: %v", result)

M election/voter.go => election/voter.go +0 -2
@@ 24,8 24,6 @@ type Voter struct {

	Eval    *big.Int    `json:"eval,omitempty"`
	EvalsID *id.EventID `json:"evals_id,omitempty"`
	Result  *[]byte     `json:"result,omitempty"`
	// no ResultID because it's the end of the graph
	Sum     *big.Int    `json:"sum,omitempty"`
	SumID   *id.EventID `json:"sum_id,omitempty"`
}