Skip to content

Commit

Permalink
feat: basic consensus determination before filter is applied
Browse files Browse the repository at this point in the history
  • Loading branch information
hacheigriega committed Aug 26, 2024
1 parent 8265dc5 commit bb3aa17
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 18 deletions.
3 changes: 2 additions & 1 deletion x/tally/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func (k Keeper) FilterAndTally(ctx sdk.Context, req types.Request) (tallyvm.VmRe
return tallyvm.VmResult{}, false, errorsmod.Wrap(err, "failed to decode consensus filter")
}

// Sort reveals.
// Sort reveals and proxy public keys.
keys := make([]string, len(req.Reveals))
i := 0
for k := range req.Reveals {
Expand All @@ -171,6 +171,7 @@ func (k Keeper) FilterAndTally(ctx sdk.Context, req types.Request) (tallyvm.VmRe
reveals := make([]types.RevealBody, len(req.Reveals))
for i, k := range keys {
reveals[i] = req.Reveals[k]
sort.Strings(reveals[i].ProxyPubKeys)
}

outliers, consensus, err := ApplyFilter(filter, reveals)
Expand Down
21 changes: 20 additions & 1 deletion x/tally/keeper/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"errors"
"fmt"

"github.com/sedaprotocol/seda-chain/x/tally/types"
)
Expand All @@ -15,12 +16,30 @@ const (
// ApplyFilter processes filter of the type specified in the first
// byte of consensus filter. It returns an outlier list, which is
// a boolean list where true at index i means that the reveal at
// index i is an outlier, consensus boolean, and error.
// index i is an outlier, consensus boolean, and error. It assumes
// that the reveals and their proxy public keys are sorted.
func ApplyFilter(input []byte, reveals []types.RevealBody) ([]int, bool, error) {
if len(input) == 0 {
return make([]int, len(reveals)), false, types.ErrInvalidFilterType
}

// Determine consensus on tuple of (exit_code, proxy_pub_keys)
var maxFreq int
freq := make(map[string]int, len(reveals))
for _, reveal := range reveals {
var success bool
if reveal.ExitCode != 0 {
success = false
}

tuple := fmt.Sprintf("%v%v", success, reveal.ProxyPubKeys)
freq[tuple]++
maxFreq = max(freq[tuple], maxFreq)
}
if maxFreq*3 < len(reveals)*2 {
return make([]int, len(reveals)), false, types.ErrNoBasicConsensus
}

var filter types.Filter
var err error
switch input[0] {
Expand Down
9 changes: 5 additions & 4 deletions x/tally/types/abci_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ type Request struct {
}

type RevealBody struct {
Salt []byte `json:"salt"`
ExitCode byte `json:"exit_code"`
GasUsed string `json:"gas_used"`
Reveal string `json:"reveal"` // base64-encoded string
Salt []byte `json:"salt"`
ExitCode byte `json:"exit_code"`
GasUsed string `json:"gas_used"`
Reveal string `json:"reveal"` // base64-encoded string
ProxyPubKeys []string `json:"proxy_public_keys"`
}

func (u *RevealBody) MarshalJSON() ([]byte, error) {
Expand Down
9 changes: 5 additions & 4 deletions x/tally/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ var (
ErrFilterInputTooShort = errors.Register("tally", 3, "filter input length too short")
ErrInvalidPathLen = errors.Register("tally", 4, "invalid JSON path length")
ErrEmptyReveals = errors.Register("tally", 5, "no reveals given")
ErrCorruptReveals = errors.Register("tally", 6, "more than 1/3 of the reveals are corrupted")
ErrNoConsensus = errors.Register("tally", 7, "1/3 or more of the reveals are not in consensus range")
ErrInvalidNumberType = errors.Register("tally", 8, "invalid number type specified")
ErrFilterUnexpected = errors.Register("tally", 9, "unexpected error occurred in filter")
ErrCorruptReveals = errors.Register("tally", 6, "> 1/3 of reveals are corrupted")
ErrNoConsensus = errors.Register("tally", 7, "> 1/3 of reveals do not agree on reveal data")
ErrNoBasicConsensus = errors.Register("tally", 8, "> 1/3 of reveals do not agree on (exit_code, proxy_pub_keys)")
ErrInvalidNumberType = errors.Register("tally", 9, "invalid number type specified")
ErrFilterUnexpected = errors.Register("tally", 10, "unexpected error occurred in filter")
)
4 changes: 1 addition & 3 deletions x/tally/types/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ package types
import (
"bytes"
"encoding/binary"

"slices"

"golang.org/x/exp/constraints"
"slices"
)

type Filter interface {
Expand Down
5 changes: 0 additions & 5 deletions x/tally/types/filters_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ func parseReveals(reveals []RevealBody, dataPath string) ([]any, dataAttributes,
freq := make(map[any]int, len(reveals))
dataList := make([]any, len(reveals))
for i, r := range reveals {
if r.ExitCode != 0 {
corruptCount++
continue
}

revealBytes, err := base64.StdEncoding.DecodeString(r.Reveal)
if err != nil {
corruptCount++
Expand Down

0 comments on commit bb3aa17

Please sign in to comment.