Skip to content

Commit

Permalink
Diego/proto 2855 add outlier detection (#703)
Browse files Browse the repository at this point in the history
<!-- < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < ☺
v           ✰  Thanks for creating a PR! You're awesome! ✰
v Please note that maintainers will only review those PRs with a
completed PR template.
☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >  -->

## Purpose of Changes and their Description

* Add new params `InferenceOutlierDetectionThreshold`,
`InferenceOutlierDetectionAlpha` to control outlier-resistant
inferences.
* Add stores of MAD ema per topic and last median.
* Use new state stores at `closeWorkerNonce` to compute MAD and
last_median.
* Addition of query `network-inferences-at-block-outlier-resistant` that
computes such network inferences on the fly, using the new state
additions.

Migration created for `v0_8_0` package and `v7` protos. 

## Link(s) to Ticket(s) or Issue(s) resolved by this PR

## Are these changes tested and documented?

- [x] If tested, please describe how. If not, why tests are not needed.
-- added unit tests for relevant new functions. Tested against local
chain.
- [x] If documented, please describe where. If not, describe why docs
are not needed. -- added to autocli
- [x] Added to `Unreleased` section of `CHANGELOG.md`?
  • Loading branch information
kpeluso authored Dec 17, 2024
2 parents c790685 + b532002 commit 2798ba3
Show file tree
Hide file tree
Showing 51 changed files with 191,586 additions and 2,779 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,7 @@ dist/
*.sublime-workspace

# fuzzer config
test/fuzz/.config.json
test/fuzz/.config.json

allora.log

14 changes: 5 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,31 +61,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

* [#694](https://github.com/allora-network/allora-chain/pull/694) Make fuzzer whitelist aware
* [#708](https://github.com/allora-network/allora-chain/pull/708) Add Emission Enabled bolean flag to Mint Module
* [#703](https://github.com/allora-network/allora-chain/pull/703) Add outlier detection to inferences

### Changed

### Deprecated

### Removed

### Added

* [#694](https://github.com/allora-network/allora-chain/pull/694) Make fuzzer whitelist aware
* [#708](https://github.com/allora-network/allora-chain/pull/708) Add Emission Enabled bolean flag to Mint Module

### Fixed

* [#702](https://github.com/allora-network/allora-chain/pull/702) Adjust score normalization to consider more scores samples
* [#699](https://github.com/allora-network/allora-chain/pull/699) Make install script manage new release assets naming
* [#704](https://github.com/allora-network/allora-chain/pull/704) Correct Discrepancies with Whitepaper modified reward fractions vs plain EMA
* [#700](https://github.com/allora-network/allora-chain/pull/700) Allow clients to unmarshall old transactions

### Security

# [Released]

### Fixed

* [#700](https://github.com/allora-network/allora-chain/pull/700) Allow clients to unmarshall old transactions

## v0.7.0

### Added
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ For `x/emissions`:
1. Add code to the tx that allows us to set new params
5. Update any tests where all params need to be specified
6. Update any external docs here:
1. https://docs.allora.network/docs/chain-parameters
1. https://docs.allora.network/devs/reference/params/chain

For `x/mint`:
__TBD__
Expand Down
5 changes: 3 additions & 2 deletions Dockerfile.upgrade
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ FROM golang:1.22-bookworm AS builder

ENV GO111MODULE=on
ENV GOMODCACHE=/gocache
ENV BASELINE_VERSION_TAG=v0.6.6
ENV UPGRADE_VERSION_TAG=v0.7.0
ENV BASELINE_VERSION_TAG=v0.7.0
ENV UPGRADE_VERSION_TAG=v0.8.0
ENV GIT_STASH_MESSAGE="Docker build"


ADD . /src
WORKDIR /src

Expand Down
11 changes: 10 additions & 1 deletion app/upgrades/v0_8_0/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
upgradetypes "cosmossdk.io/x/upgrade/types"
"github.com/allora-network/allora-chain/app/keepers"
"github.com/allora-network/allora-chain/app/upgrades"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
)

Expand All @@ -26,6 +27,14 @@ func CreateUpgradeHandler(
keepers *keepers.AppKeepers,
) upgradetypes.UpgradeHandler {
return func(ctx context.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
return moduleManager.RunMigrations(ctx, configurator, vm)
sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx.Logger().Info("RUN MIGRATIONS")
vm, err := moduleManager.RunMigrations(ctx, configurator, vm)
if err != nil {
return vm, err
}

sdkCtx.Logger().Info("MIGRATIONS COMPLETED")
return vm, nil
}
}
49 changes: 49 additions & 0 deletions math/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -567,3 +567,52 @@ func GetQuantileOfDecs(
}
return ret, nil
}

// MedianAbsoluteDeviation calculates the median absolute deviation of a slice of Dec values.
// If an error occurs, returns (Dec{}, Dec{}, error).
// For empty slices, returns (ZeroDec(), ZeroDec(), nil).
// For single-element slices, returns (ZeroDec(), value, nil).
func MedianAbsoluteDeviation(data []Dec) (medianAbsoluteDeviation Dec, median Dec, err error) {
// Check for NaN values first, consistent with other functions
for _, v := range data {
if v.isNaN {
return Dec{}, Dec{}, errorsmod.Wrap(ErrNaN, "median absolute deviation input data contains NaN values")
}
}

if len(data) == 0 {
return ZeroDec(), ZeroDec(), nil
}

if len(data) == 1 {
return ZeroDec(), data[0], nil // MAD of single value is 0
}

// Calculate the median of the original data
median, err = Median(data)
if err != nil {
return Dec{}, Dec{}, err
}

// Calculate absolute deviations
absDevs := make([]Dec, len(data))
for i, v := range data {
diff, err := v.Sub(median)
if err != nil {
return Dec{}, Dec{}, errorsmod.Wrap(err, "MAD: error calculating difference")
}
absDiff, err := diff.Abs()
if err != nil {
return Dec{}, Dec{}, errorsmod.Wrap(err, "MAD: error calculating absolute difference")
}
absDevs[i] = absDiff
}

// Calculate the median of the absolute deviations
medianAbsoluteDeviation, err = Median(absDevs)
if err != nil {
return Dec{}, Dec{}, err
}

return medianAbsoluteDeviation, median, nil
}
114 changes: 114 additions & 0 deletions math/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -744,3 +744,117 @@ func TestGetQuantileOfScoresCsv(t *testing.T) {
alloratestutil.InEpsilon5Dec(t, result, expected)
}
}

func TestMedianAbsoluteDeviation(t *testing.T) {
tests := []struct {
name string
input []alloraMath.Dec
wantMad alloraMath.Dec
wantMedian alloraMath.Dec
wantErr bool
}{
{
name: "empty slice",
input: []alloraMath.Dec{},
wantMad: alloraMath.ZeroDec(),
wantMedian: alloraMath.ZeroDec(),
wantErr: false,
},
{
name: "single value",
input: []alloraMath.Dec{alloraMath.NewDecFromInt64(5)},
wantMad: alloraMath.ZeroDec(),
wantMedian: alloraMath.NewDecFromInt64(5),
wantErr: false,
},
{
name: "simple odd length array",
input: []alloraMath.Dec{
alloraMath.NewDecFromInt64(1),
alloraMath.NewDecFromInt64(2),
alloraMath.NewDecFromInt64(3),
alloraMath.NewDecFromInt64(4),
alloraMath.NewDecFromInt64(5),
},
wantMad: alloraMath.NewDecFromInt64(1), // deviations=[2,1,0,1,2], median of deviations=1
wantMedian: alloraMath.NewDecFromInt64(3), // median=3
wantErr: false,
},
{
name: "simple even length array",
input: []alloraMath.Dec{
alloraMath.NewDecFromInt64(1),
alloraMath.NewDecFromInt64(2),
alloraMath.NewDecFromInt64(4),
alloraMath.NewDecFromInt64(5),
},
wantMad: alloraMath.MustNewDecFromString("1.5"),
wantMedian: alloraMath.NewDecFromInt64(3),
wantErr: false,
},
{
name: "decimal values",
input: []alloraMath.Dec{
alloraMath.MustNewDecFromString("1.5"),
alloraMath.MustNewDecFromString("2.3"),
alloraMath.MustNewDecFromString("3.7"),
alloraMath.MustNewDecFromString("4.2"),
alloraMath.MustNewDecFromString("5.8"),
},
// median = 3.7
// deviations = [2.2, 1.4, 0, 0.5, 2.1]
// median of deviations = 1.4
wantMad: alloraMath.MustNewDecFromString("1.4"),
wantMedian: alloraMath.MustNewDecFromString("3.7"),
wantErr: false,
},
{
name: "array with NaN",
input: []alloraMath.Dec{
alloraMath.NewDecFromInt64(1),
alloraMath.NewNaN(),
alloraMath.NewDecFromInt64(3),
},
wantMad: alloraMath.Dec{},
wantMedian: alloraMath.Dec{},
wantErr: true,
},
{
name: "array with identical values",
input: []alloraMath.Dec{
alloraMath.NewDecFromInt64(5),
alloraMath.NewDecFromInt64(5),
alloraMath.NewDecFromInt64(5),
},
wantMad: alloraMath.ZeroDec(), // all deviations are 0
wantMedian: alloraMath.NewDecFromInt64(5), // median is 5
wantErr: false,
},
{
name: "array with outliers",
input: []alloraMath.Dec{
alloraMath.NewDecFromInt64(1000),
alloraMath.NewDecFromInt64(11),
alloraMath.NewDecFromInt64(12),
},
wantMad: alloraMath.MustNewDecFromString("1"),
wantMedian: alloraMath.MustNewDecFromString("12"),
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotMad, gotMedian, err := alloraMath.MedianAbsoluteDeviation(tt.input)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.True(t, gotMad.Equal(tt.wantMad),
"mad: got %v want %v", gotMad, tt.wantMad)
require.True(t, gotMedian.Equal(tt.wantMedian),
"median: got %v want %v", gotMedian, tt.wantMedian)
})
}
}
15 changes: 12 additions & 3 deletions test/generate_genesis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ INVESTORS_WALLET_TOKENS=$(echo '3.105*10^26' | bc | cut -f 1 -d '.') # 31.05% of
TEAM_WALLET_NAME="team"
TEAM_WALLET_TOKENS=$(echo '1.75*10^26' | bc | cut -f 1 -d '.') # 17.5% of total token supply of 1e27

VALIDATOR_TOKENS=$(echo '(10^26 - 100*10^18)/3' | bc) # 100M allo - 100 allo
# VALIDATOR_TOKENS=$(echo '(10^26 - 100*10^18)/3' | bc) # 100M allo - 100 allo
# Calculate validator tokens
VALIDATOR_TOKENS=$(echo '(10^26 - 100*10^18)/3' | bc) # 100M allo - 100 allo for staking
VALIDATOR_SPENDING_TOKENS="100000000" # extra for voting and other transactions
VALIDATOR_TOTAL_TOKENS=$(echo "${VALIDATOR_TOKENS} + ${VALIDATOR_SPENDING_TOKENS}" | bc)
echo "VALIDATOR_TOTAL_TOKENS: ${VALIDATOR_TOTAL_TOKENS}, VALIDATOR_TOKENS: ${VALIDATOR_TOKENS}, VALIDATOR_SPENDING_TOKENS: ${VALIDATOR_SPENDING_TOKENS}"

COMMON_HOME_DIR="${COMMON_HOME_DIR:-$(pwd)}"

allorad=$(which allorad)
Expand All @@ -49,10 +55,12 @@ for ((i=0; i<$VALIDATOR_NUMBER; i++)); do
$allorad --home=$genesisHome keys add $valName \
--keyring-backend $keyringBackend > $COMMON_HOME_DIR/$valName.account_info 2>&1

echo "Fund $valName account to genesis"
echo "Fund $valName account to genesis, VALIDATOR_TOKENS: ${VALIDATOR_TOKENS} ${DENOM} "
echo "$allorad --home=$genesisHome genesis add-genesis-account $valName ${VALIDATOR_TOKENS}${DENOM},${VALIDATOR_SPENDING_TOKENS}${DENOM} --keyring-backend $keyringBackend"
$allorad --home=$genesisHome genesis add-genesis-account \
$valName ${VALIDATOR_TOKENS}${DENOM} \
$valName ${VALIDATOR_TOTAL_TOKENS}${DENOM} \
--keyring-backend $keyringBackend

done

echo "Generate $UPSHOT_WALLET_NAME account"
Expand Down Expand Up @@ -115,6 +123,7 @@ for ((i=0; i<$VALIDATOR_NUMBER; i++)); do
# Symlink keyring-test to have keys
ln -sfr $genesisHome/keyring-test $valHome/keyring-test

echo "Generating gentx for $valName, VALIDATOR_TOKENS: ${VALIDATOR_TOKENS} ${DENOM} at $gentxDir/$valName.json"
$allorad --home=$valHome genesis gentx $valName ${VALIDATOR_TOKENS}${DENOM} \
--chain-id $CHAIN_ID --keyring-backend $keyringBackend \
--moniker="$valName" \
Expand Down
6 changes: 6 additions & 0 deletions test/integration/update_params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ func UpdateParamsChecks(m testCommon.TestConfig) {
GlobalWhitelistEnabled: nil,
TopicCreatorWhitelistEnabled: nil,
MinExperiencedWorkerRegrets: nil,
InferenceOutlierDetectionThreshold: nil,
InferenceOutlierDetectionAlpha: nil,
},
}
txResp, err := m.Client.BroadcastTx(ctx, m.AliceAcc, updateParamRequest)
Expand Down Expand Up @@ -148,6 +150,8 @@ func UpdateParamsChecks(m testCommon.TestConfig) {
GlobalWhitelistEnabled: nil,
TopicCreatorWhitelistEnabled: nil,
MinExperiencedWorkerRegrets: nil,
InferenceOutlierDetectionThreshold: nil,
InferenceOutlierDetectionAlpha: nil,
},
}
_, err = m.Client.BroadcastTx(ctx, m.BobAcc, updateParamRequest)
Expand Down Expand Up @@ -211,6 +215,8 @@ func UpdateParamsChecks(m testCommon.TestConfig) {
GlobalWhitelistEnabled: nil,
TopicCreatorWhitelistEnabled: nil,
MinExperiencedWorkerRegrets: nil,
InferenceOutlierDetectionThreshold: nil,
InferenceOutlierDetectionAlpha: nil,
},
}
txResp, err = m.Client.BroadcastTx(ctx, m.AliceAcc, updateParamRequest)
Expand Down
9 changes: 5 additions & 4 deletions test/integration/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"time"

upgradetypes "cosmossdk.io/x/upgrade/types"
"github.com/allora-network/allora-chain/app/upgrades/v0_7_0"
v0_8_0 "github.com/allora-network/allora-chain/app/upgrades/v0_8_0"
testCommon "github.com/allora-network/allora-chain/test/common"
sdktypes "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
Expand Down Expand Up @@ -57,7 +57,7 @@ func voteOnProposal(m testCommon.TestConfig, proposalId uint64) {
// propose an upgrade to the v0.5.0 software version
func proposeUpgrade(m testCommon.TestConfig) (proposalId uint64, proposalHeight int64) {
ctx := context.Background()
name := v0_7_0.UpgradeName
name := v0_8_0.UpgradeName
summary := "Upgrade to " + name + " software version"

currHeight, err := m.Client.BlockHeight(ctx)
Expand Down Expand Up @@ -129,6 +129,7 @@ func getEmissionsVersion(m testCommon.TestConfig) uint64 {
ModuleName: "emissions",
}
moduleVersions, err := m.Client.QueryUpgrade().ModuleVersions(ctx, queryModuleVersionsRequest)
m.T.Logf("Module Versions: %+v", moduleVersions)
require.NoError(m.T, err)
require.NotNil(m.T, moduleVersions)
require.Len(m.T, moduleVersions.ModuleVersions, 1)
Expand Down Expand Up @@ -161,7 +162,7 @@ func getAppliedVersionHeight(m testCommon.TestConfig, version string) int64 {
}

func UpgradeChecks(m testCommon.TestConfig) {
versionName := v0_7_0.UpgradeName
versionName := v0_8_0.UpgradeName
m.T.Log("--- Getting Emissions Module Version Before Upgrade ---")
emissionsVersionBefore := getEmissionsVersion(m)
m.T.Logf("--- Propose Upgrade to %s software version from v0 (%d) ---", versionName, emissionsVersionBefore)
Expand All @@ -178,5 +179,5 @@ func UpgradeChecks(m testCommon.TestConfig) {
require.Greater(m.T, emissionsVersionAfter, emissionsVersionBefore)
height := getAppliedVersionHeight(m, versionName)
m.T.Log("--- Checking upgrade has been applied at the proposed height ---")
require.Equal(m.T, proposalHeight, height)
require.Equal(m.T, height, proposalHeight)
}
11 changes: 11 additions & 0 deletions x/emissions/api/emissions/v2/codec.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package emissionsv2

import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
Expand All @@ -26,3 +27,13 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
&MsgInsertReputerPayload{},
)
}

// So we need to register types like:
func RegisterTypes(registry *codec.LegacyAmino) {
// Internal types used by requests
registry.RegisterConcrete(&OptionalParams{}, "emissions/v2/OptionalParams", nil) //nolint:exhaustruct
registry.RegisterConcrete(&WorkerDataBundle{}, "emissions/v2/WorkerDataBundle", nil) //nolint:exhaustruct
registry.RegisterConcrete(&ReputerValueBundle{}, "emissions/v2/ReputerValueBundle", nil) //nolint:exhaustruct
registry.RegisterConcrete(&WorkerDataBundles{}, "emissions/v2/WorkerDataBundles", nil) //nolint:exhaustruct
registry.RegisterConcrete(&ReputerValueBundles{}, "emissions/v2/ReputerValueBundles", nil) //nolint:exhaustruct
}
Loading

0 comments on commit 2798ba3

Please sign in to comment.