Skip to content

Commit

Permalink
MERC-6003 Move aggregator to v4 pkg
Browse files Browse the repository at this point in the history
  • Loading branch information
martin-cll committed Jul 24, 2024
1 parent e7042e6 commit 79c5140
Show file tree
Hide file tree
Showing 5 changed files with 335 additions and 82 deletions.
36 changes: 0 additions & 36 deletions mercury/aggregate_functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,39 +166,3 @@ func GetConsensusNativeFee(paos []PAONativeFee, f int) (*big.Int, error) {

return validNativeFees[len(validNativeFees)/2], nil
}

type PAOMarketStatus interface {
GetMarketStatus() (uint32, bool)
}

// GetConsensusMarketStatus gets the most common status, provided that it is at least F+1.
func GetConsensusMarketStatus(paos []PAOMarketStatus, f int) (uint32, error) {
marketStatusCounts := make(map[uint32]int)
for _, pao := range paos {
marketStatus, valid := pao.GetMarketStatus()
if valid {
marketStatusCounts[marketStatus] += 1
}
}

var mostCommonMarketStatus uint32
var mostCommonCount int
for marketStatus, count := range marketStatusCounts {
if count > mostCommonCount {
mostCommonMarketStatus = marketStatus
mostCommonCount = count
} else if count == mostCommonCount {
// For stability, always prefer the smaller enum value in case of ties.
// In practice this will prefer CLOSED over OPEN.
if marketStatus < mostCommonMarketStatus {
mostCommonMarketStatus = marketStatus
}
}
}

if mostCommonCount < f+1 {
return 0, fmt.Errorf("market status has fewer than f+1 observations (status %d got %d/%d)", mostCommonMarketStatus, mostCommonCount, len(paos))
}

return mostCommonMarketStatus, nil
}
44 changes: 0 additions & 44 deletions mercury/aggregate_functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,44 +407,6 @@ func Test_AggregateFunctions(t *testing.T) {
assert.EqualError(t, err, "fewer than f+1 observations have a valid nativeFee (got: 1/4)")
})
})

t.Run("GetConsensusMarketStatus", func(t *testing.T) {
t.Run("gets consensus on market status when valid", func(t *testing.T) {
marketStatus, err := GetConsensusMarketStatus(convertMarketStatus(validPaos), f)
require.NoError(t, err)
assert.Equal(t, uint32(1), marketStatus)
})
t.Run("treats zero values as valid", func(t *testing.T) {
paos := NewValidParsedAttributedObservations()
for i := range paos {
paos[i].MarketStatus = 0
}
marketStatus, err := GetConsensusMarketStatus(convertMarketStatus(paos), f)
require.NoError(t, err)
assert.Equal(t, uint32(0), marketStatus)
})
t.Run("is stable during ties", func(t *testing.T) {
paos := NewValidParsedAttributedObservations()
for i := range paos {
paos[i].MarketStatus = uint32(i % 2)
}
marketStatus, err := GetConsensusMarketStatus(convertMarketStatus(paos), f)
require.NoError(t, err)
assert.Equal(t, uint32(0), marketStatus)
})
t.Run("fails when the mode is less than f+1", func(t *testing.T) {
paos := NewValidParsedAttributedObservations()
for i := range paos {
paos[i].MarketStatus = uint32(i)
}
_, err := GetConsensusMarketStatus(convertMarketStatus(paos), f)
assert.EqualError(t, err, "market status has fewer than f+1 observations (status 0 got 1/4)")
})
t.Run("fails when all observations are invalid", func(t *testing.T) {
_, err := GetConsensusMarketStatus(convertMarketStatus(invalidPaos), f)
assert.EqualError(t, err, "market status has fewer than f+1 observations (status 0 got 0/4)")
})
})
}

// convert funcs are necessary because go is not smart enough to cast
Expand Down Expand Up @@ -485,9 +447,3 @@ func convertNativeFee(pao []testParsedAttributedObservation) (ret []PAONativeFee
}
return ret
}
func convertMarketStatus(pao []testParsedAttributedObservation) (ret []PAOMarketStatus) {
for _, v := range pao {
ret = append(ret, v)
}
return ret
}
39 changes: 39 additions & 0 deletions mercury/v4/aggregate_functions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package v4

import "fmt"

type PAOMarketStatus interface {
GetMarketStatus() (uint32, bool)
}

// GetConsensusMarketStatus gets the most common status, provided that it is at least F+1.
func GetConsensusMarketStatus(paos []PAOMarketStatus, f int) (uint32, error) {
marketStatusCounts := make(map[uint32]int)
for _, pao := range paos {
marketStatus, valid := pao.GetMarketStatus()
if valid {
marketStatusCounts[marketStatus] += 1
}
}

var mostCommonMarketStatus uint32
var mostCommonCount int
for marketStatus, count := range marketStatusCounts {
if count > mostCommonCount {
mostCommonMarketStatus = marketStatus
mostCommonCount = count
} else if count == mostCommonCount {
// For stability, always prefer the smaller enum value in case of ties.
// In practice this will prefer CLOSED over OPEN.
if marketStatus < mostCommonMarketStatus {
mostCommonMarketStatus = marketStatus
}
}
}

if mostCommonCount < f+1 {
return 0, fmt.Errorf("market status has fewer than f+1 observations (status %d got %d/%d)", mostCommonMarketStatus, mostCommonCount, len(paos))
}

return mostCommonMarketStatus, nil
}
Loading

0 comments on commit 79c5140

Please sign in to comment.