From bbd64fdd8a1d2c5161caa63611b568839a65780a Mon Sep 17 00:00:00 2001 From: leonz789 Date: Tue, 22 Oct 2024 10:33:09 +0800 Subject: [PATCH 01/22] introduce slashing for oracle service --- app/app.go | 1 + proto/exocore/oracle/v1/params.proto | 45 +- proto/exocore/oracle/v1/slashing.proto | 12 + testutil/keeper/oracle.go | 2 + x/delegation/keeper/abci.go | 1 + x/delegation/keeper/delegation_state.go | 1 + x/operator/keeper/slash.go | 3 +- x/operator/keeper/usd_value.go | 1 - x/oracle/keeper/aggregator/aggregator.go | 33 +- x/oracle/keeper/aggregator/calculator.go | 1 - x/oracle/keeper/aggregator/context.go | 65 ++- x/oracle/keeper/aggregator/worker.go | 75 ++- x/oracle/keeper/common/expected_keepers.go | 10 +- x/oracle/keeper/keeper.go | 3 + x/oracle/keeper/slashing.go | 108 ++++ x/oracle/module.go | 168 +++++- x/oracle/types/events.go | 13 +- x/oracle/types/expected_keepers.go | 6 + x/oracle/types/key_slashing.go | 24 + x/oracle/types/params.pb.go | 643 +++++++++++++++++++-- x/oracle/types/slashing.pb.go | 426 ++++++++++++++ x/oracle/types/types.go | 9 + 22 files changed, 1594 insertions(+), 56 deletions(-) create mode 100644 proto/exocore/oracle/v1/slashing.proto create mode 100644 x/oracle/keeper/slashing.go create mode 100644 x/oracle/types/key_slashing.go create mode 100644 x/oracle/types/slashing.pb.go diff --git a/app/app.go b/app/app.go index f84763c36..1bc932d13 100644 --- a/app/app.go +++ b/app/app.go @@ -588,6 +588,7 @@ func NewExocoreApp( appCodec, keys[oracleTypes.StoreKey], memKeys[oracleTypes.MemStoreKey], app.GetSubspace(oracleTypes.ModuleName), app.StakingKeeper, &app.DelegationKeeper, &app.AssetsKeeper, authAddrString, + &app.SlashingKeeper, ) // the SDK slashing module is used to slash validators in the case of downtime. it tracks diff --git a/proto/exocore/oracle/v1/params.proto b/proto/exocore/oracle/v1/params.proto index 1407a062d..0bfaa7f7b 100644 --- a/proto/exocore/oracle/v1/params.proto +++ b/proto/exocore/oracle/v1/params.proto @@ -4,7 +4,10 @@ package exocore.oracle.v1; import "exocore/oracle/v1/info.proto"; import "exocore/oracle/v1/token_feeder.proto"; import "gogoproto/gogo.proto"; - +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "cosmos_proto/cosmos.proto"; +import "amino/amino.proto"; option go_package = "github.com/ExocoreNetwork/exocore/x/oracle/types"; // Params defines the parameters for the module. @@ -32,6 +35,9 @@ message Params { int32 max_det_id = 10; // for each token, only keep max_size_prices round of prices int32 max_size_prices = 11; + + // slashing defined the slashing related params + SlashingParams slashing = 12; } // ConsensusMode defines the consensus mode for the prices. @@ -42,4 +48,39 @@ enum ConsensusMode { // CONSENSUS_MODE_ASAP defines the mode to get final price immediately when the voting power // exceeds the threshold. CONSENSUS_MODE_ASAP = 1 [(gogoproto.enumvalue_customname) = "ConsensusModeASAP"]; -} \ No newline at end of file +} + +// slashing related params +message SlashingParams { + int64 reported_rounds_window = 1; + bytes min_reported_per_window = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; + google.protobuf.Duration oracle_miss_jail_duration = 3 + [(gogoproto.nullable) = false, (amino.dont_omitempty) = true, (gogoproto.stdduration) = true]; + google.protobuf.Duration oracle_malicious_jail_duration =4 + [(gogoproto.nullable) = false, (amino.dont_omitempty) = true, (gogoproto.stdduration) = true]; + bytes slash_fraction_miss_report = 5 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; + bytes slash_fraction_malicious_report = 6 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; + bytes slash_fraction_miss = 7 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; + bytes slash_fraction_malicious = 8 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; + +} diff --git a/proto/exocore/oracle/v1/slashing.proto b/proto/exocore/oracle/v1/slashing.proto new file mode 100644 index 000000000..7a28be032 --- /dev/null +++ b/proto/exocore/oracle/v1/slashing.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +package exocore.oracle.v1; + +option go_package = "github.com/ExocoreNetwork/exocore/x/oracle/types"; + +message ValidatorReportInfo { + string address = 1; + int64 startHeight = 2; + int64 index_offset = 3; + int64 missed_rounds_counter = 4; +} diff --git a/testutil/keeper/oracle.go b/testutil/keeper/oracle.go index 4308d54df..646eb86f9 100644 --- a/testutil/keeper/oracle.go +++ b/testutil/keeper/oracle.go @@ -21,6 +21,7 @@ import ( assetskeeper "github.com/ExocoreNetwork/exocore/x/assets/keeper" delegationkeeper "github.com/ExocoreNetwork/exocore/x/delegation/keeper" dogfoodkeeper "github.com/ExocoreNetwork/exocore/x/dogfood/keeper" + slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" "github.com/stretchr/testify/require" ) @@ -52,6 +53,7 @@ func OracleKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { delegationkeeper.Keeper{}, assetskeeper.Keeper{}, authtypes.NewModuleAddress(govtypes.ModuleName).String(), + slashingkeeper.Keeper{}, ) ctx := sdk.NewContext(stateStore, tmproto.Header{ diff --git a/x/delegation/keeper/abci.go b/x/delegation/keeper/abci.go index 47ca02748..d89be5616 100644 --- a/x/delegation/keeper/abci.go +++ b/x/delegation/keeper/abci.go @@ -116,6 +116,7 @@ func (k *Keeper) EndBlock( continue } + // TODO: the field IsPending in types.UndelegationRecord is useless since when a record is completed it will be removed, so the record is either existing&pending or unexist&completed, and the IsPending is not used nowhere(like slashFromUndelegation doesn't check this field either), good to remove this field. And types.UndelegationRecord is actually PendingUndelegationRecord // delete the Undelegation records that have been complemented err = k.DeleteUndelegationRecord(cc, record) if err != nil { diff --git a/x/delegation/keeper/delegation_state.go b/x/delegation/keeper/delegation_state.go index 340d585dd..29ac28491 100644 --- a/x/delegation/keeper/delegation_state.go +++ b/x/delegation/keeper/delegation_state.go @@ -303,6 +303,7 @@ func (k *Keeper) SetStakerShareToZero(ctx sdk.Context, operator, assetID string, singleStateKey := assetstype.GetJoinedStoreKey(stakerID, assetID, operator) value := store.Get(singleStateKey) if value != nil { + // TODO: check if pendingUndelegation==0 => just delete this item instead of update share to zero, otherwise this item will be left in the storage forever with zero value delegationState := delegationtype.DelegationAmounts{} k.cdc.MustUnmarshal(value, &delegationState) delegationState.UndelegatableShare = sdkmath.LegacyNewDec(0) diff --git a/x/operator/keeper/slash.go b/x/operator/keeper/slash.go index 1f1c6a58d..f5be6d8e6 100644 --- a/x/operator/keeper/slash.go +++ b/x/operator/keeper/slash.go @@ -23,7 +23,7 @@ func GetSlashIDForDogfood(infraction stakingtypes.Infraction, infractionHeight i return strings.Join([]string{hexutil.EncodeUint64(uint64(infraction)), hexutil.EncodeUint64(uint64(infractionHeight))}, utils.DelimiterForID) } -// SlashFromUndelegation executes the slash from an undelegation +// SlashFromUndelegation executes the slash from an undelegation, reduce the .ActualCompletedAmount from undelegationRecords func SlashFromUndelegation(undelegation *delegationtype.UndelegationRecord, slashProportion sdkmath.LegacyDec) *types.SlashFromUndelegation { if undelegation.ActualCompletedAmount.IsZero() { return nil @@ -136,6 +136,7 @@ func (k *Keeper) SlashAssets(ctx sdk.Context, parameter *types.SlashInputInfo) ( state.OperatorShare = sdkmath.LegacyNewDec(0) } state.TotalAmount = remainingAmount + // TODO: check if pendingUndelegation also zero => delete this item, and this operator should be opted out if all aasets falls to 0 since the miniself is not satisfied then. executionInfo.SlashAssetsPool = append(executionInfo.SlashAssetsPool, types.SlashFromAssetsPool{ AssetID: assetID, Amount: slashAmount, diff --git a/x/operator/keeper/usd_value.go b/x/operator/keeper/usd_value.go index fc1fdb5f2..a826aa8bf 100644 --- a/x/operator/keeper/usd_value.go +++ b/x/operator/keeper/usd_value.go @@ -348,7 +348,6 @@ func (k *Keeper) CalculateUSDValueForOperator( } // iterate all assets owned by the operator to calculate its voting power opFuncToIterateAssets := func(assetID string, state *assetstype.OperatorAssetInfo) error { - // var price operatortypes.Price var price oracletype.Price var decimal uint32 if isForSlash { diff --git a/x/oracle/keeper/aggregator/aggregator.go b/x/oracle/keeper/aggregator/aggregator.go index 48e7778cd..ea7871d87 100644 --- a/x/oracle/keeper/aggregator/aggregator.go +++ b/x/oracle/keeper/aggregator/aggregator.go @@ -2,6 +2,7 @@ package aggregator import ( "math/big" + "sort" "github.com/ExocoreNetwork/exocore/x/oracle/keeper/common" "github.com/ExocoreNetwork/exocore/x/oracle/types" @@ -124,6 +125,7 @@ func (agg *aggregator) fillPrice(pSources []*types.PriceSource, validator string pTR.price = new(big.Int).Set(priceTmp.price) pTR.detRoundID = priceTmp.detRoundID pTR.timestamp = priceTmp.timestamp + break } } } @@ -151,7 +153,7 @@ func (agg *aggregator) confirmDSPrice(confirmedRounds []*confirmedPrice) { price.detRoundID = priceSourceRound.detID price.timestamp = priceSourceRound.timestamp price.price = priceSourceRound.price - } // else TODO: panice in V1 + } // else TODO: panic in V1 } } } @@ -191,6 +193,35 @@ func (agg *aggregator) aggregate() *big.Int { return agg.finalPrice } +// TODO: this only suites for DS. check source type for extension +// GetFinaPriceListForFeederIDs retrieve final price info as an array ordered by sourceID asc +func (agg *aggregator) getFinalPriceList(feederID uint64) []*types.AggFinalPrice { + sourceIDs := make([]uint64, 0, len(agg.dsPrices)) + for sID := range agg.dsPrices { + sourceIDs = append(sourceIDs, sID) + } + sort.Slice(sourceIDs, func(i, j int) bool { + return sourceIDs[i] < sourceIDs[j] + }) + ret := make([]*types.AggFinalPrice, 0, len(sourceIDs)) + for _, sID := range sourceIDs { + for _, report := range agg.reports { + price := report.prices[sID] + if price == nil || price.detRoundID != agg.dsPrices[sID] { + // the DetID mismatch should not happen + continue + } + ret = append(ret, &types.AggFinalPrice{ + FeederID: feederID, + SourceID: sID, + DetID: price.detRoundID, + Price: price.price.String(), + }) + } + } + return ret +} + func newAggregator(validatorSetLength int, totalPower *big.Int) *aggregator { return &aggregator{ reports: make([]*reportPrice, 0, validatorSetLength), diff --git a/x/oracle/keeper/aggregator/calculator.go b/x/oracle/keeper/aggregator/calculator.go index 9ee504d25..201285ce2 100644 --- a/x/oracle/keeper/aggregator/calculator.go +++ b/x/oracle/keeper/aggregator/calculator.go @@ -52,7 +52,6 @@ func (r *roundPrices) updatePriceAndPower(pw *priceAndPower, totalPower *big.Int updated = true if common.ExceedsThreshold(pw.power, totalPower) { r.price = pw.price - // r.confirmed = true confirmed = true } } diff --git a/x/oracle/keeper/aggregator/context.go b/x/oracle/keeper/aggregator/context.go index 591f653d5..aed919073 100644 --- a/x/oracle/keeper/aggregator/context.go +++ b/x/oracle/keeper/aggregator/context.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "math/big" + "sort" "github.com/ExocoreNetwork/exocore/x/oracle/keeper/cache" "github.com/ExocoreNetwork/exocore/x/oracle/keeper/common" @@ -159,11 +160,23 @@ func (agc *AggregatorContext) FillPrice(msg *types.MsgCreatePrice) (*PriceItemKV agc.aggregators[msg.FeederID] = feederWorker } + // if feederWorker.sealed { + // // record this message for performance evaluate(used for slashing) + // return nil, nil, types.ErrPriceProposalIgnored.Wrap("price aggregation for this round has sealed") + // } + + // list4Calculator, list4Aggregator := w.f.filtrate(msg) if feederWorker.sealed { + if _, list4Aggregator := feederWorker.filtrate(msg); list4Aggregator != nil { + // record this message for performance evaluation(used for slashing) + feederWorker.recordMessage(msg.Creator, msg.FeederID, list4Aggregator) + } return nil, nil, types.ErrPriceProposalIgnored.Wrap("price aggregation for this round has sealed") } if listFilled := feederWorker.do(msg); listFilled != nil { + // record this message for performance evaluation(used for slashing) + feederWorker.recordMessage(msg.Creator, msg.FeederID, listFilled) if finalPrice := feederWorker.aggregate(); finalPrice != nil { agc.rounds[msg.FeederID].status = roundStatusClosed feederWorker.seal() @@ -196,16 +209,32 @@ func (agc *AggregatorContext) NewCreatePrice(_ sdk.Context, msg *types.MsgCreate // including possible aggregation and state update // when validatorSet update, set force to true, to seal all alive round // returns: 1st successful sealed, need to be written to KVStore, 2nd: failed sealed tokenID, use previous price to write to KVStore -func (agc *AggregatorContext) SealRound(ctx sdk.Context, force bool) (success []*PriceItemKV, failed []uint64, sealed []uint64) { - for feederID, round := range agc.rounds { +func (agc *AggregatorContext) SealRound(ctx sdk.Context, force bool) (success []*PriceItemKV, failed []uint64, sealed []uint64, windowClosed []uint64) { + feederIDs := make([]uint64, 0, len(agc.rounds)) + for fID, _ := range agc.rounds { + feederIDs = append(feederIDs, fID) + } + sort.Slice(feederIDs, func(i, j int) bool { + return feederIDs[i] < feederIDs[j] + }) + // make sure feederIDs are accessed in order to calculate the indexOffset for slashing + for _, feederID := range feederIDs { + round := agc.rounds[feederID] if round.status == roundStatusOpen { feeder := agc.params.GetTokenFeeder(feederID) // TODO: for mode=1, we don't do aggregate() here, since if it donesn't success in the transaction execution stage, it won't success here // but it's not always the same for other modes, switch modes switch common.Mode { case types.ConsensusModeASAP: + offset := uint64(ctx.BlockHeight()) - round.basedBlock expired := feeder.EndBlock > 0 && uint64(ctx.BlockHeight()) >= feeder.EndBlock - outOfWindow := uint64(ctx.BlockHeight())-round.basedBlock >= uint64(common.MaxNonce) + outOfWindow := offset >= uint64(common.MaxNonce) + + // an open round reach its end of window, increase offsetIndex for active valdiator and chech the performance(missing/malicious) + if round.status == roundStatusOpen && offset == uint64(common.MaxNonce) { + windowClosed = append(windowClosed, feederID) + } + if expired || outOfWindow || force { failed = append(failed, feeder.TokenID) if expired { @@ -227,7 +256,7 @@ func (agc *AggregatorContext) SealRound(ctx sdk.Context, force bool) (success [] sealed = append(sealed, feederID) } } - return success, failed, sealed + return success, failed, sealed, windowClosed } // PrepareEndBlock is called at EndBlock stage, to prepare the roundInfo for the next block(of input block) @@ -335,6 +364,34 @@ func (agc *AggregatorContext) GetParamsMaxSizePrices() uint64 { return uint64(agc.params.MaxSizePrices) } +// GetFinalPriceListForFeederIDs get final price list for required feederIDs in format []{feederID, sourceID, detID, price} with asc of {feederID, sourceID} +// feederIDs is required to be ordered asc +func (agc *AggregatorContext) GetFinalPriceListForFeederIDs(feederIDs []uint64) []*types.AggFinalPrice { + ret := make([]*types.AggFinalPrice, 0, len(feederIDs)) + for _, feederID := range feederIDs { + feederWorker := agc.aggregators[feederID] + if feederWorker != nil { + if pList := feederWorker.getFinalPriceList(feederID); len(pList) > 0 { + ret = append(ret, pList...) + } + } + } + return ret +} + +func (agc *AggregatorContext) PerformanceReview(finalPrice *types.AggFinalPrice, validator string) (exist, matched bool) { + feederWorker := agc.aggregators[finalPrice.FeederID] + if feederWorker == nil { + // should not happen + // something wrong happened in the agc, so we just skip this round by treat the validator as effective&honest + exist = true + matched = true + return + } + exist, matched = feederWorker.check(validator, finalPrice.FeederID, finalPrice.SourceID, finalPrice.Price, finalPrice.DetID) + return +} + // NewAggregatorContext returns a new instance of AggregatorContext func NewAggregatorContext() *AggregatorContext { return &AggregatorContext{ diff --git a/x/oracle/keeper/aggregator/worker.go b/x/oracle/keeper/aggregator/worker.go index bbf7dcf2f..191acf419 100644 --- a/x/oracle/keeper/aggregator/worker.go +++ b/x/oracle/keeper/aggregator/worker.go @@ -20,14 +20,79 @@ type worker struct { // when enough data(exceeds threshold) collected, aggregate to conduct the final price a *aggregator ctx *AggregatorContext + // TODO: move outside into context through .ctx + records recordMsg } -func (w *worker) do(msg *types.MsgCreatePrice) []*types.PriceSource { - accAddress, _ := sdk.AccAddressFromBech32(msg.Creator) +// recordKey used to retrieve messages from records to evaluate that if a validator report proper price for a specific feederID+sourceID +type recordKey struct { + validator string + feederID uint64 + sourceID uint64 +} + +// recordMsg define wrap the map for fast access to validator's message info +type recordMsg map[recordKey][]*types.PriceTimeDetID + +func newRecordMsg() recordMsg { + return make(map[recordKey][]*types.PriceTimeDetID) +} + +func (r recordMsg) has(validator string, feederID, sourceID uint64) bool { + _, ok := r[recordKey{validator, feederID, sourceID}] + return ok +} + +func (r recordMsg) get(validator string, feederID, sourceID uint64) []*types.PriceTimeDetID { + v, _ := r[recordKey{validator, feederID, sourceID}] + return v +} + +func (r recordMsg) check(validator string, feederID, sourceID uint64, price, detID string) (exist, matched bool) { + prices := r.get(validator, feederID, sourceID) + for _, p := range prices { + if p.DetID == detID { + exist = true + if p.Price == price { + matched = true + } + } + } + return +} + +func (r recordMsg) set(creator string, feederID uint64, priceSources []*types.PriceSource) { + accAddress, _ := sdk.AccAddressFromBech32(creator) validator := sdk.ConsAddress(accAddress).String() - power := w.ctx.validatorsPower[validator] + for _, price := range priceSources { + r[recordKey{validator, feederID, price.SourceID}] = price.Prices + } +} + +// GetFinalPriceList relies requirement to aggregator inside them to get final price list +// []{feederID, sourceID, detID, price} in asc order of {soruceID} +func (w *worker) getFinalPriceList(feederID uint64) []*types.AggFinalPrice { + return w.a.getFinalPriceList(feederID) +} + +func (w *worker) filtrate(msg *types.MsgCreatePrice) (list4Calculator []*types.PriceSource, list4Aggregator []*types.PriceSource) { + return w.f.filtrate(msg) +} + +func (w *worker) recordMessage(creator string, feederID uint64, priceSources []*types.PriceSource) { + w.records.set(creator, feederID, priceSources) +} + +func (w *worker) check(validator string, feederID, sourceID uint64, price, detID string) (exist, matched bool) { + return w.records.check(validator, feederID, sourceID, price, detID) +} + +func (w *worker) do(msg *types.MsgCreatePrice) []*types.PriceSource { list4Calculator, list4Aggregator := w.f.filtrate(msg) if list4Aggregator != nil { + accAddress, _ := sdk.AccAddressFromBech32(msg.Creator) + validator := sdk.ConsAddress(accAddress).String() + power := w.ctx.validatorsPower[validator] w.a.fillPrice(list4Aggregator, validator, power) if confirmedRounds := w.c.fillPrice(list4Calculator, validator, power); confirmedRounds != nil { w.a.confirmDSPrice(confirmedRounds) @@ -49,7 +114,8 @@ func (w *worker) seal() { w.price = w.a.aggregate().String() w.f = nil w.c = nil - w.a = nil + // aggregator is kept for performance evaluation + // w.a = nil } // newWorker new a instance for a tokenFeeder's specific round @@ -60,5 +126,6 @@ func newWorker(feederID uint64, agc *AggregatorContext) *worker { a: newAggregator(len(agc.validatorsPower), agc.totalPower), decimal: agc.params.GetTokenInfo(feederID).Decimal, ctx: agc, + records: newRecordMsg(), } } diff --git a/x/oracle/keeper/common/expected_keepers.go b/x/oracle/keeper/common/expected_keepers.go index 6e68f8695..caf9130fe 100644 --- a/x/oracle/keeper/common/expected_keepers.go +++ b/x/oracle/keeper/common/expected_keepers.go @@ -1,13 +1,14 @@ package common import ( + "cosmossdk.io/math" sdkmath "cosmossdk.io/math" dogfoodkeeper "github.com/ExocoreNetwork/exocore/x/dogfood/keeper" dogfoodtypes "github.com/ExocoreNetwork/exocore/x/dogfood/types" "github.com/ExocoreNetwork/exocore/x/oracle/types" abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" - stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) type Price struct { @@ -53,9 +54,12 @@ var _ KeeperDogfood = dogfoodkeeper.Keeper{} type KeeperDogfood = interface { GetLastTotalPower(ctx sdk.Context) sdkmath.Int - IterateBondedValidatorsByPower(ctx sdk.Context, fn func(index int64, validator stakingTypes.ValidatorI) (stop bool)) + IterateBondedValidatorsByPower(ctx sdk.Context, fn func(index int64, validator stakingtypes.ValidatorI) (stop bool)) GetValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate - GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator stakingTypes.Validator, found bool) + GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator stakingtypes.Validator, found bool) GetAllExocoreValidators(ctx sdk.Context) (validators []dogfoodtypes.ExocoreValidator) + ValidatorByConsAddr(ctx sdk.Context, addr sdk.ConsAddress) stakingtypes.ValidatorI + SlashWithInfractionReason(ctx sdk.Context, addr sdk.ConsAddress, infractionHeight, power int64, slashFactor sdk.Dec, infraction stakingtypes.Infraction) math.Int + Jail(ctx sdk.Context, addr sdk.ConsAddress) } diff --git a/x/oracle/keeper/keeper.go b/x/oracle/keeper/keeper.go index 8ec37b5f9..161ab3b42 100644 --- a/x/oracle/keeper/keeper.go +++ b/x/oracle/keeper/keeper.go @@ -25,6 +25,7 @@ type ( common.KeeperDogfood delegationKeeper types.DelegationKeeper assetsKeeper types.AssetsKeeper + types.SlashingKeeper } ) @@ -39,6 +40,7 @@ func NewKeeper( delegationKeeper types.DelegationKeeper, assetsKeeper types.AssetsKeeper, authority string, + slashingKeeper types.SlashingKeeper, ) Keeper { // ensure authority is a valid bech32 address if _, err := sdk.AccAddressFromBech32(authority); err != nil { @@ -58,6 +60,7 @@ func NewKeeper( delegationKeeper: delegationKeeper, assetsKeeper: assetsKeeper, authority: authority, + SlashingKeeper: slashingKeeper, } } diff --git a/x/oracle/keeper/slashing.go b/x/oracle/keeper/slashing.go new file mode 100644 index 000000000..eedde3394 --- /dev/null +++ b/x/oracle/keeper/slashing.go @@ -0,0 +1,108 @@ +package keeper + +import ( + "time" + + "github.com/ExocoreNetwork/exocore/x/oracle/types" + sdk "github.com/cosmos/cosmos-sdk/types" + gogotypes "github.com/cosmos/gogoproto/types" +) + +// InitValidatorReportInfo creates an new item for a first seen validator to tracking their performance +func (k Keeper) InitValidatorReportInfo(ctx sdk.Context, validator string, height int64) { + store := ctx.KVStore(k.storeKey) + key := types.SlashingValidatorReportInfoKey(validator) + if !store.Has(key) { + // set the record for validator to tracking performance of oracle service + reportInfo := &types.ValidatorReportInfo{ + Address: validator, + StartHeight: height, + } + bz := k.cdc.MustMarshal(reportInfo) + store.Set(key, bz) + } +} + +// SetValidatorReportInfo sets the validator reporting info to a valdiator +func (k Keeper) SetValidatorReportInfo(ctx sdk.Context, validator string, info types.ValidatorReportInfo) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&info) + store.Set(types.SlashingValidatorReportInfoKey(validator), bz) +} + +// GetValidatorReportInfo retruns the ValidatorReportInfo for a specific validator +func (k Keeper) GetValidatorReportInfo(ctx sdk.Context, validator string) (info types.ValidatorReportInfo, found bool) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.SlashingValidatorReportInfoKey(validator)) + if bz == nil { + return + } + k.cdc.MustUnmarshal(bz, &info) + found = true + return +} + +// SetValidatorMissedBlockBitArray sets the bit that checks if the validator has +// missed a round to report price in the current window +func (k Keeper) SetValidatorMissedRoundBitArray(ctx sdk.Context, validator string, index uint64, missed bool) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&gogotypes.BoolValue{Value: missed}) + store.Set(types.SlashingMissedBitArrayKey(validator, index), bz) +} + +// GetValidatorMissedBlocks returns array of missed rounds for given validator +func (k Keeper) GetValidatorMissedRoundBitArray(ctx sdk.Context, validator string, index uint64) bool { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.SlashingMissedBitArrayKey(validator, index)) + if bz == nil { + return false + } + var missed gogotypes.BoolValue + k.cdc.MustUnmarshal(bz, &missed) + return missed.Value +} + +// GetReportedBlocksWindow sliding window for reporting slashing +func (k Keeper) GetReportedRoundsWindow(ctx sdk.Context) int64 { + return k.GetParams(ctx).Slashing.ReportedRoundsWindow +} + +// GetSlashFractionMiss fraction of power slashed for missed rounds +func (k Keeper) GetSlashFractionMiss(ctx sdk.Context) (res sdk.Dec) { + return k.GetParams(ctx).Slashing.SlashFractionMiss +} + +// GetSlashFractionMiss fraction of power slashed for missed rounds +func (k Keeper) GetSlashFractionMalicious(ctx sdk.Context) (res sdk.Dec) { + return k.GetParams(ctx).Slashing.SlashFractionMalicious +} + +// GetMinReportedPerWindow minimum blocks repored prices per window +func (k Keeper) GetMinReportedPerWindow(ctx sdk.Context) int64 { + params := k.GetParams(ctx) + reportedRoundsWindow := k.GetReportedRoundsWindow(ctx) + + // NOTE: RoundInt64 will never panic as minReportedPerWindow is + // less than 1. + return params.Slashing.MinReportedPerWindow.MulInt64(reportedRoundsWindow).RoundInt64() +} + +// MissJailDuration miss unbond duration +func (k Keeper) GetMissJailDuration(ctx sdk.Context) (res time.Duration) { + return k.GetParams(ctx).Slashing.OracleMissJailDuration +} + +// MissJailDuration miss unbond duration +func (k Keeper) GetMaliciousJailDuration(ctx sdk.Context) (res time.Duration) { + return k.GetParams(ctx).Slashing.OracleMaliciousJailDuration +} + +// clearValidatorMissedBlockBitArray deletes every instance of ValidatorMissedBlockBitArray in the store +func (k Keeper) ClearValidatorMissedBlockBitArray(ctx sdk.Context, validator string) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, types.SlashingMissedBitArrayPrefix(validator)) + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + store.Delete(iterator.Key()) + } +} diff --git a/x/oracle/module.go b/x/oracle/module.go index 8e089d0b3..eca337d69 100644 --- a/x/oracle/module.go +++ b/x/oracle/module.go @@ -24,6 +24,7 @@ import ( cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) var ( @@ -157,7 +158,12 @@ func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { // TODO: try better way to init caches and aggregatorContext than beginBlock once.Do(func() { _ = keeper.GetCaches() - _ = keeper.GetAggregatorContext(ctx, am.keeper) + agc := keeper.GetAggregatorContext(ctx, am.keeper) + validatorPowers := agc.GetValidatorPowers() + // set validatorReportInfo to track performance + for validator, _ := range validatorPowers { + am.keeper.InitValidatorReportInfo(ctx, validator, ctx.BlockHeight()) + } }) } @@ -169,11 +175,17 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val agc := keeper.GetAggregatorContext(ctx, am.keeper) logger := am.keeper.Logger(ctx) + height := ctx.BlockHeight() if len(validatorUpdates) > 0 { validatorList := make(map[string]*big.Int) for _, vu := range validatorUpdates { pubKey, _ := cryptocodec.FromTmProtoPublicKey(vu.PubKey) - validatorList[sdk.ConsAddress(pubKey.Address()).String()] = big.NewInt(vu.Power) + validatorStr := sdk.ConsAddress(pubKey.Address()).String() + validatorList[validatorStr] = big.NewInt(vu.Power) + // add possible new added validator info for slashing tracking + if vu.Power > 0 { + am.keeper.InitValidatorReportInfo(ctx, validatorStr, height) + } } // update validator set information in cache cs.AddCache(cache.ItemV(validatorList)) @@ -183,15 +195,161 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val agc.SetValidatorPowers(validatorPowers) // TODO: seal all alive round since validatorSet changed here forceSeal = true - logger.Info("validator set changed, force seal all active rounds", "height", ctx.BlockHeight()) + logger.Info("validator set changed, force seal all active rounds", "height", height) } // TODO: for v1 use mode==1, just check the failed feeders - _, failed, sealed := agc.SealRound(ctx, forceSeal) + _, failed, sealed, windowClosed := agc.SealRound(ctx, forceSeal) + // update&check slashing info + validatorPowers := agc.GetValidatorPowers() + for validator, power := range validatorPowers { + reportedInfo, found := am.keeper.GetValidatorReportInfo(ctx, validator) + if !found { + logger.Error(fmt.Sprintf("Expected report info for validator %s but not found", validator)) + continue + } + // TODO: for the round calculation, now only sourceID=1 is used so {feederID, sourceID} have only one value for each feederID which corresponding to one round. + // But when we came to multiple sources, we should consider the round corresponding to feedeerID instead of {feederID, srouceID} + for _, finalPrice := range agc.GetFinalPriceListForFeederIDs(windowClosed) { + exist, matched := agc.PerformanceReview(finalPrice, validator) + if exist && !matched { + // TODO: malicious price, just slash&jail immediately + logger.Info( + "confirmed malicious price", + "validator", validator, + "infraction_height", height, + "infraction_time", ctx.BlockTime(), + "feederID", finalPrice.FeederID, + "detID", finalPrice.DetID, + "sourceID", finalPrice.SourceID, + "finalPrice", finalPrice.Price, + ) + consAddr, err := sdk.ConsAddressFromBech32(validator) + if err != nil { + panic("invalid consAddr string") + } + + operator := am.keeper.ValidatorByConsAddr(ctx, consAddr) + if operator != nil && !operator.IsJailed() { + coinsBurned := am.keeper.SlashWithInfractionReason(ctx, consAddr, height, power.Int64(), am.keeper.GetSlashFractionMalicious(ctx), stakingtypes.Infraction_INFRACTION_UNSPECIFIED) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeOracleSlash, + sdk.NewAttribute(types.AttributeKeyValidatorKey, validator), + sdk.NewAttribute(types.AttributeKeyPower, fmt.Sprintf("%d", power)), + sdk.NewAttribute(types.AttributeKeyReason, types.AttributeValueMaliciousReportPrice), + sdk.NewAttribute(types.AttributeKeyJailed, validator), + sdk.NewAttribute(types.AttributeKeyBurnedCoins, coinsBurned.String()), + ), + ) + am.keeper.Jail(ctx, consAddr) + jailUntil := ctx.BlockHeader().Time.Add(am.keeper.GetMaliciousJailDuration(ctx)) + am.keeper.JailUntil(ctx, consAddr, jailUntil) + reportedInfo.MissedRoundsCounter = 0 + reportedInfo.IndexOffset = 0 + am.keeper.ClearValidatorMissedBlockBitArray(ctx, validator) + } + continue + } + + index := uint64(reportedInfo.IndexOffset % am.keeper.GetReportedRoundsWindow(ctx)) + reportedInfo.IndexOffset++ + // Update reported round bit array & counter + // This counter just tracks the sum of the bit array + // That way we avoid needing to read/write the whole array each time + previous := am.keeper.GetValidatorMissedRoundBitArray(ctx, validator, index) + missed := !exist + switch { + case !previous && missed: + // Array value has changed from not missed to missed, increment counter + am.keeper.SetValidatorMissedRoundBitArray(ctx, validator, index, true) + reportedInfo.MissedRoundsCounter++ + case previous && !missed: + // Array value has changed from missed to not missed, decrement counter + am.keeper.SetValidatorMissedRoundBitArray(ctx, validator, index, false) + reportedInfo.MissedRoundsCounter-- + default: + // Array value at this index has not changed, no need to update counter + } + + minReportedPerWindow := am.keeper.GetMinReportedPerWindow(ctx) + + if missed { + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeOracleLiveness, + sdk.NewAttribute(types.AttributeKeyValidatorKey, validator), + sdk.NewAttribute(types.AttributeKeyMissedRounds, fmt.Sprintf("%d", reportedInfo.MissedRoundsCounter)), + sdk.NewAttribute(types.AttributeKeyHeight, fmt.Sprintf("%d", height)), + ), + ) + + logger.Debug( + "absent validator", + "height", ctx.BlockHeight(), + "validator", validator, + "missed", reportedInfo.MissedRoundsCounter, + "threshold", minReportedPerWindow, + ) + } + + minHeight := reportedInfo.StartHeight + am.keeper.GetReportedRoundsWindow(ctx) + maxMissed := am.keeper.GetReportedRoundsWindow(ctx) - minReportedPerWindow + // if we are past the minimum height and the validator has missed too many rounds reporting prices, punish them + if height > minHeight && reportedInfo.MissedRoundsCounter > maxMissed { + consAddr, err := sdk.ConsAddressFromBech32(validator) + if err != nil { + panic("invalid consAddr string") + } + operator := am.keeper.ValidatorByConsAddr(ctx, consAddr) + if operator != nil && !operator.IsJailed() { + // missing rounds confirmed: slash and jail the validator + coinsBurned := am.keeper.SlashWithInfractionReason(ctx, consAddr, height, power.Int64(), am.keeper.GetSlashFractionMiss(ctx), stakingtypes.Infraction_INFRACTION_UNSPECIFIED) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeOracleSlash, + sdk.NewAttribute(types.AttributeKeyValidatorKey, validator), + sdk.NewAttribute(types.AttributeKeyPower, fmt.Sprintf("%d", power)), + sdk.NewAttribute(types.AttributeKeyReason, types.AttributeValueMissingReportPrice), + sdk.NewAttribute(types.AttributeKeyJailed, validator), + sdk.NewAttribute(types.AttributeKeyBurnedCoins, coinsBurned.String()), + ), + ) + am.keeper.Jail(ctx, consAddr) + jailUntil := ctx.BlockHeader().Time.Add(am.keeper.GetMissJailDuration(ctx)) + am.keeper.JailUntil(ctx, consAddr, jailUntil) + + // We need to reset the counter & array so that the validator won't be immediately slashed for miss report info upon rebonding. + reportedInfo.MissedRoundsCounter = 0 + reportedInfo.IndexOffset = 0 + am.keeper.ClearValidatorMissedBlockBitArray(ctx, validator) + + logger.Info( + "slashing and jailing validator due to liveness fault", + "height", height, + "validator", consAddr.String(), + "min_height", minHeight, + "threshold", minReportedPerWindow, + "slashed", am.keeper.GetSlashFractionMiss(ctx).String(), + "jailed_until", jailUntil, + ) + } else { + // validator was (a) not found or (b) already jailed so we do not slash + logger.Info( + "validator would have been slashed for too many missed repoerting price, but was either not found in store or already jailed", + "validator", validator, + ) + } + } + // Set the updated reportInfo + am.keeper.SetValidatorReportInfo(ctx, validator, reportedInfo) + } + } + for _, feederID := range sealed { am.keeper.RemoveNonceWithFeederIDForValidators(ctx, feederID, agc.GetValidators()) } - // append new round with previous price for fail-seal token + // append new round with previous price for fail-sealed token for _, tokenID := range failed { prevPrice, nextRoundID := am.keeper.GrowRoundID(ctx, tokenID) logger.Info("add new round with previous price under fail aggregation", "tokenID", tokenID, "roundID", nextRoundID, "price", prevPrice) diff --git a/x/oracle/types/events.go b/x/oracle/types/events.go index f8c61132f..6d7cb8019 100644 --- a/x/oracle/types/events.go +++ b/x/oracle/types/events.go @@ -1,7 +1,9 @@ package types const ( - EventTypeCreatePrice = "create_price" + EventTypeCreatePrice = "create_price" + EventTypeOracleLiveness = "oracle_liveness" + EventTypeOracleSlash = "oracle_slash" AttributeKeyFeederID = "feeder_id" AttributeKeyTokenID = "token_id" @@ -14,10 +16,19 @@ const ( AttributeKeyFeederIDs = "feeder_ids" AttributeKeyNativeTokenUpdate = "native_token_update" AttributeKeyNativeTokenChange = "native_token_change" + AttributeKeyValidatorKey = "validator" + AttributeKeyMissedRounds = "missed_rounds" + AttributeKeyHeight = "height" + AttributeKeyPower = "power" + AttributeKeyReason = "reason" + AttributeKeyJailed = "jailed" + AttributeKeyBurnedCoins = "burned_coins" AttributeValuePriceUpdatedSuccess = "success" AttributeValueParamsUpdatedSuccess = "success" AttributeValueNativeTokenUpdate = "update" AttributeValueNativeTokenDeposit = "deposit" AttributeValueNativeTokenWithdraw = "withdraw" + AttributeValueMissingReportPrice = "missing_report_price" + AttributeValueMaliciousReportPrice = "missing_report_price" ) diff --git a/x/oracle/types/expected_keepers.go b/x/oracle/types/expected_keepers.go index ee9c09b0f..d19ad53d0 100644 --- a/x/oracle/types/expected_keepers.go +++ b/x/oracle/types/expected_keepers.go @@ -1,6 +1,8 @@ package types import ( + time "time" + sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -26,3 +28,7 @@ type DelegationKeeper interface { type AssetsKeeper interface { GetAssetsDecimal(ctx sdk.Context, assets map[string]interface{}) (decimals map[string]uint32, err error) } + +type SlashingKeeper interface { + JailUntil(sdk.Context, sdk.ConsAddress, time.Time) +} diff --git a/x/oracle/types/key_slashing.go b/x/oracle/types/key_slashing.go new file mode 100644 index 000000000..a5d64d5c6 --- /dev/null +++ b/x/oracle/types/key_slashing.go @@ -0,0 +1,24 @@ +package types + +// const ( +// SlashingPrefix = "Slashing/" +// ) + +var ( + SlashingPrefix = []byte("Slashing/") + ValidatorReportInfoPrefix = append(SlashingPrefix, []byte("validator/value/")...) + MissedBitArrayPrefix = append(SlashingPrefix, []byte("missed/value/")...) +) + +func SlashingValidatorReportInfoKey(validator string) []byte { + return append(ValidatorReportInfoPrefix, []byte(validator)...) +} + +func SlashingMissedBitArrayPrefix(validator string) []byte { + key := append([]byte(validator), DelimiterForCombinedKey) + return append(MissedBitArrayPrefix, key...) +} + +func SlashingMissedBitArrayKey(validator string, index uint64) []byte { + return append(SlashingMissedBitArrayPrefix(validator), Uint64Bytes(index)...) +} diff --git a/x/oracle/types/params.pb.go b/x/oracle/types/params.pb.go index ced645ef2..d078f3c8f 100644 --- a/x/oracle/types/params.pb.go +++ b/x/oracle/types/params.pb.go @@ -5,17 +5,25 @@ package types import ( fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/protobuf/types/known/durationpb" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" + time "time" ) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +var _ = time.Kitchen // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. @@ -76,6 +84,8 @@ type Params struct { MaxDetId int32 `protobuf:"varint,10,opt,name=max_det_id,json=maxDetId,proto3" json:"max_det_id,omitempty"` // for each token, only keep max_size_prices round of prices MaxSizePrices int32 `protobuf:"varint,11,opt,name=max_size_prices,json=maxSizePrices,proto3" json:"max_size_prices,omitempty"` + // slashing defined the slashing related params + Slashing *SlashingParams `protobuf:"bytes,12,opt,name=slashing,proto3" json:"slashing,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -187,47 +197,142 @@ func (m *Params) GetMaxSizePrices() int32 { return 0 } +func (m *Params) GetSlashing() *SlashingParams { + if m != nil { + return m.Slashing + } + return nil +} + +// slashing related params +type SlashingParams struct { + ReportedRoundsWindow int64 `protobuf:"varint,1,opt,name=reported_rounds_window,json=reportedRoundsWindow,proto3" json:"reported_rounds_window,omitempty"` + MinReportedPerWindow github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=min_reported_per_window,json=minReportedPerWindow,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_reported_per_window"` + OracleMissJailDuration time.Duration `protobuf:"bytes,3,opt,name=oracle_miss_jail_duration,json=oracleMissJailDuration,proto3,stdduration" json:"oracle_miss_jail_duration"` + OracleMaliciousJailDuration time.Duration `protobuf:"bytes,4,opt,name=oracle_malicious_jail_duration,json=oracleMaliciousJailDuration,proto3,stdduration" json:"oracle_malicious_jail_duration"` + SlashFractionMissReport github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=slash_fraction_miss_report,json=slashFractionMissReport,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_miss_report"` + SlashFractionMaliciousReport github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=slash_fraction_malicious_report,json=slashFractionMaliciousReport,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_malicious_report"` + SlashFractionMiss github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,7,opt,name=slash_fraction_miss,json=slashFractionMiss,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_miss"` + SlashFractionMalicious github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,8,opt,name=slash_fraction_malicious,json=slashFractionMalicious,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_malicious"` +} + +func (m *SlashingParams) Reset() { *m = SlashingParams{} } +func (m *SlashingParams) String() string { return proto.CompactTextString(m) } +func (*SlashingParams) ProtoMessage() {} +func (*SlashingParams) Descriptor() ([]byte, []int) { + return fileDescriptor_72f39bba4594b794, []int{1} +} +func (m *SlashingParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SlashingParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SlashingParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SlashingParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_SlashingParams.Merge(m, src) +} +func (m *SlashingParams) XXX_Size() int { + return m.Size() +} +func (m *SlashingParams) XXX_DiscardUnknown() { + xxx_messageInfo_SlashingParams.DiscardUnknown(m) +} + +var xxx_messageInfo_SlashingParams proto.InternalMessageInfo + +func (m *SlashingParams) GetReportedRoundsWindow() int64 { + if m != nil { + return m.ReportedRoundsWindow + } + return 0 +} + +func (m *SlashingParams) GetOracleMissJailDuration() time.Duration { + if m != nil { + return m.OracleMissJailDuration + } + return 0 +} + +func (m *SlashingParams) GetOracleMaliciousJailDuration() time.Duration { + if m != nil { + return m.OracleMaliciousJailDuration + } + return 0 +} + func init() { proto.RegisterEnum("exocore.oracle.v1.ConsensusMode", ConsensusMode_name, ConsensusMode_value) proto.RegisterType((*Params)(nil), "exocore.oracle.v1.Params") + proto.RegisterType((*SlashingParams)(nil), "exocore.oracle.v1.SlashingParams") } func init() { proto.RegisterFile("exocore/oracle/v1/params.proto", fileDescriptor_72f39bba4594b794) } var fileDescriptor_72f39bba4594b794 = []byte{ - // 511 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xbf, 0x6f, 0xd3, 0x40, - 0x14, 0xc7, 0x6d, 0xf2, 0xa3, 0xed, 0x85, 0x40, 0x7b, 0x80, 0x74, 0x98, 0xe0, 0x5a, 0x08, 0xa1, - 0x88, 0xc1, 0x6e, 0x1b, 0x26, 0xc4, 0x92, 0x26, 0xa9, 0x14, 0xa4, 0xa6, 0x91, 0x4d, 0x16, 0x16, - 0xcb, 0xb1, 0x5f, 0x12, 0xab, 0xb1, 0x2f, 0xba, 0x73, 0x8a, 0xe9, 0xca, 0x82, 0x3a, 0x31, 0xb2, - 0x54, 0x42, 0xe2, 0x9f, 0x61, 0xec, 0xc8, 0x88, 0x92, 0x7f, 0x83, 0x01, 0xf9, 0xec, 0x94, 0xa6, - 0x49, 0xb7, 0xbb, 0xf7, 0xfd, 0x7c, 0xf4, 0x9e, 0x9e, 0x1e, 0x52, 0x21, 0xa6, 0x2e, 0x65, 0x60, - 0x50, 0xe6, 0xb8, 0x63, 0x30, 0xce, 0xf6, 0x8d, 0x89, 0xc3, 0x9c, 0x80, 0xeb, 0x13, 0x46, 0x23, - 0x8a, 0x77, 0xb2, 0x5c, 0x4f, 0x73, 0xfd, 0x6c, 0x5f, 0xa9, 0xac, 0x2a, 0x7e, 0x38, 0xa0, 0xa9, - 0xa0, 0xbc, 0x5c, 0x4d, 0x23, 0x7a, 0x0a, 0xa1, 0x3d, 0x00, 0xf0, 0x80, 0x65, 0xd4, 0xe3, 0x21, - 0x1d, 0x52, 0xf1, 0x34, 0x92, 0x57, 0x5a, 0x7d, 0xf1, 0x37, 0x87, 0x8a, 0x5d, 0xd1, 0x1d, 0xef, - 0xa1, 0xa2, 0x3b, 0x72, 0xfc, 0x90, 0x13, 0x59, 0xcb, 0x55, 0x4b, 0x07, 0x44, 0x5f, 0x19, 0x44, - 0x6f, 0x24, 0x80, 0x99, 0x71, 0x89, 0x21, 0x1a, 0x71, 0x72, 0xef, 0x4e, 0xe3, 0x43, 0x02, 0x98, - 0x19, 0x87, 0x6b, 0x68, 0x83, 0xd3, 0x29, 0x73, 0x81, 0x93, 0x9c, 0x50, 0x9e, 0xae, 0x51, 0x2c, - 0x41, 0x98, 0x0b, 0x12, 0xd7, 0x50, 0x81, 0x4d, 0xc7, 0xc0, 0x49, 0x5e, 0x28, 0xcf, 0xd7, 0x28, - 0xe6, 0x74, 0x0c, 0x99, 0x96, 0xb2, 0xb8, 0x81, 0xca, 0x37, 0x97, 0xc0, 0x49, 0x41, 0xc8, 0xea, - 0x5d, 0x23, 0x1e, 0x09, 0xcc, 0xbc, 0x1f, 0xfd, 0xff, 0x70, 0xfc, 0x0c, 0x6d, 0x05, 0x4e, 0x6c, - 0x87, 0x34, 0x74, 0x81, 0x14, 0x35, 0xb9, 0x5a, 0x30, 0x37, 0x03, 0x27, 0xee, 0x24, 0x7f, 0xbc, - 0x8b, 0x4a, 0xd1, 0x88, 0x01, 0x1f, 0xd1, 0xb1, 0x67, 0x3b, 0x64, 0x43, 0xc4, 0xe8, 0xba, 0x54, - 0x5f, 0x06, 0xfa, 0x64, 0xf3, 0x16, 0x70, 0x88, 0xdf, 0xa0, 0x7c, 0x40, 0x3d, 0x20, 0x5b, 0x9a, - 0x5c, 0x7d, 0x70, 0xa0, 0xad, 0xdb, 0x37, 0x0d, 0x39, 0x84, 0x7c, 0xca, 0x8f, 0xa9, 0x07, 0xa6, - 0xa0, 0x71, 0x05, 0xa1, 0x64, 0x28, 0x0f, 0x22, 0xdb, 0xf7, 0x08, 0xba, 0x9e, 0xaa, 0x09, 0x51, - 0xdb, 0xc3, 0xaf, 0xd0, 0xc3, 0x24, 0xe5, 0xfe, 0x39, 0xd8, 0x13, 0xe6, 0x27, 0x9b, 0x2e, 0x09, - 0xa4, 0x1c, 0x38, 0xb1, 0xe5, 0x9f, 0x43, 0x57, 0x14, 0xdf, 0xe6, 0xbf, 0xff, 0xd8, 0x95, 0x5e, - 0x7f, 0x91, 0x51, 0x79, 0xa9, 0x07, 0x7e, 0x87, 0x94, 0xc6, 0x49, 0xc7, 0x6a, 0x75, 0xac, 0x9e, - 0x65, 0x1f, 0x9f, 0x34, 0x5b, 0x76, 0xaf, 0x63, 0x75, 0x5b, 0x8d, 0xf6, 0x51, 0xbb, 0xd5, 0xdc, - 0x96, 0x94, 0xca, 0xc5, 0xa5, 0x46, 0x96, 0x94, 0x5e, 0xc8, 0x27, 0xe0, 0xfa, 0x03, 0x1f, 0x3c, - 0xac, 0xa3, 0x47, 0xb7, 0xec, 0xba, 0x55, 0xef, 0x6e, 0xcb, 0xca, 0x93, 0x8b, 0x4b, 0x6d, 0x67, - 0x49, 0x4b, 0x02, 0x25, 0xff, 0xf5, 0xa7, 0x2a, 0x1d, 0xbe, 0xff, 0x35, 0x53, 0xe5, 0xab, 0x99, - 0x2a, 0xff, 0x99, 0xa9, 0xf2, 0xb7, 0xb9, 0x2a, 0x5d, 0xcd, 0x55, 0xe9, 0xf7, 0x5c, 0x95, 0x3e, - 0xee, 0x0d, 0xfd, 0x68, 0x34, 0xed, 0xeb, 0x2e, 0x0d, 0x8c, 0x56, 0xba, 0x9d, 0x0e, 0x44, 0x9f, - 0x28, 0x3b, 0x35, 0x16, 0x47, 0x1f, 0x2f, 0xce, 0x3e, 0xfa, 0x3c, 0x01, 0xde, 0x2f, 0x8a, 0xbb, - 0xae, 0xfd, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xf5, 0xbe, 0x10, 0x4f, 0x66, 0x03, 0x00, 0x00, + // 846 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xbf, 0x6f, 0xdb, 0x46, + 0x18, 0x15, 0x63, 0x59, 0x71, 0xce, 0x76, 0x1a, 0x5f, 0x5c, 0xe7, 0xa4, 0xa8, 0x14, 0x1b, 0x14, + 0x81, 0x10, 0xa0, 0x64, 0x62, 0x65, 0x2a, 0xda, 0xc1, 0xfa, 0x61, 0xc0, 0x01, 0xac, 0x08, 0x54, + 0x8d, 0x02, 0x5d, 0x88, 0x13, 0x79, 0x92, 0x2e, 0x26, 0x79, 0xc4, 0x1d, 0x19, 0xab, 0x5e, 0xbb, + 0x14, 0x99, 0x3a, 0x66, 0x09, 0x50, 0xa0, 0x4b, 0xc7, 0xee, 0xfd, 0x07, 0x3c, 0x66, 0x2c, 0x3a, + 0xa4, 0x85, 0x3d, 0xf4, 0xdf, 0x28, 0x78, 0x3c, 0xaa, 0xd6, 0x0f, 0x0f, 0xd1, 0x62, 0xf3, 0xee, + 0xbd, 0xf7, 0xbd, 0x7b, 0x1f, 0xef, 0x13, 0x81, 0x4e, 0x26, 0xcc, 0x65, 0x9c, 0x58, 0x8c, 0x63, + 0xd7, 0x27, 0xd6, 0xeb, 0x67, 0x56, 0x84, 0x39, 0x0e, 0x84, 0x19, 0x71, 0x16, 0x33, 0xb8, 0xa3, + 0x70, 0x33, 0xc3, 0xcd, 0xd7, 0xcf, 0x2a, 0xd5, 0x45, 0x09, 0x0d, 0x87, 0x2c, 0x13, 0x54, 0xbe, + 0x58, 0x44, 0x63, 0x76, 0x4a, 0x42, 0x67, 0x48, 0x88, 0x47, 0xb8, 0x62, 0xed, 0x8e, 0xd8, 0x88, + 0xc9, 0x47, 0x2b, 0x7d, 0x52, 0xbb, 0xfa, 0x88, 0xb1, 0x91, 0x4f, 0x2c, 0xb9, 0x1a, 0x24, 0x43, + 0xcb, 0x4b, 0x38, 0x8e, 0x29, 0x0b, 0x15, 0x5e, 0x9b, 0xc7, 0x63, 0x1a, 0x10, 0x11, 0xe3, 0x20, + 0x52, 0x84, 0xb2, 0xcb, 0x44, 0xc0, 0x84, 0x93, 0x55, 0xce, 0x16, 0x0a, 0xda, 0xc1, 0x01, 0x0d, + 0x99, 0x25, 0xff, 0x66, 0x5b, 0x8f, 0xfe, 0x28, 0x82, 0x52, 0x4f, 0x86, 0x85, 0x4f, 0x41, 0xc9, + 0x1d, 0x63, 0x1a, 0x0a, 0xa4, 0x19, 0x6b, 0xf5, 0xcd, 0x7d, 0x64, 0x2e, 0xe4, 0x36, 0x5b, 0x29, + 0xc1, 0x56, 0xbc, 0x54, 0x21, 0x73, 0x09, 0x74, 0xeb, 0x46, 0xc5, 0xb7, 0x29, 0xc1, 0x56, 0x3c, + 0xd8, 0x00, 0xb7, 0x05, 0x4b, 0xb8, 0x4b, 0x04, 0x5a, 0x93, 0x92, 0xf2, 0x12, 0x49, 0x5f, 0x32, + 0xec, 0x9c, 0x09, 0x1b, 0x60, 0x9d, 0x27, 0x3e, 0x11, 0xa8, 0x28, 0x25, 0x9f, 0x2d, 0x91, 0xd8, + 0x89, 0x4f, 0x94, 0x2c, 0xe3, 0xc2, 0x16, 0xd8, 0xbe, 0xde, 0x73, 0x81, 0xd6, 0xa5, 0x58, 0xbf, + 0xe9, 0x88, 0x87, 0x92, 0x66, 0x6f, 0xc5, 0xff, 0x2f, 0x04, 0x7c, 0x08, 0xee, 0x04, 0x78, 0xe2, + 0x84, 0x2c, 0x74, 0x09, 0x2a, 0x19, 0x5a, 0x7d, 0xdd, 0xde, 0x08, 0xf0, 0xa4, 0x9b, 0xae, 0x61, + 0x0d, 0x6c, 0xc6, 0x63, 0x4e, 0xc4, 0x98, 0xf9, 0x9e, 0x83, 0xd1, 0x6d, 0x09, 0x83, 0xe9, 0xd6, + 0xc1, 0x2c, 0x61, 0x80, 0x36, 0xe6, 0x08, 0x4d, 0xf8, 0x1c, 0x14, 0x03, 0xe6, 0x11, 0x74, 0xc7, + 0xd0, 0xea, 0x77, 0xf7, 0x8d, 0x65, 0xfd, 0x66, 0xa1, 0x20, 0xa1, 0x48, 0xc4, 0x31, 0xf3, 0x88, + 0x2d, 0xd9, 0xb0, 0x0a, 0x40, 0x7a, 0x28, 0x8f, 0xc4, 0x0e, 0xf5, 0x10, 0x98, 0x9e, 0xaa, 0x4d, + 0xe2, 0x23, 0x0f, 0x3e, 0x06, 0x9f, 0xa4, 0xa8, 0xa0, 0xe7, 0xc4, 0x89, 0x38, 0x4d, 0x3b, 0xbd, + 0x29, 0x29, 0xdb, 0x01, 0x9e, 0xf4, 0xe9, 0x39, 0xe9, 0xc9, 0x4d, 0xf8, 0x0d, 0xd8, 0x10, 0x3e, + 0x16, 0x63, 0x1a, 0x8e, 0xd0, 0x96, 0xa1, 0xd5, 0x37, 0xf7, 0x3f, 0x5f, 0xf6, 0x2a, 0x14, 0x25, + 0xbb, 0x22, 0xf6, 0x54, 0xf2, 0x55, 0xf1, 0xed, 0x2f, 0xb5, 0xc2, 0xa3, 0x8b, 0x12, 0xb8, 0x3b, + 0x4b, 0x81, 0xcf, 0xc1, 0x1e, 0x27, 0x11, 0xe3, 0x31, 0xf1, 0x1c, 0xce, 0x92, 0xd0, 0x13, 0xce, + 0x19, 0x0d, 0x3d, 0x76, 0x86, 0x34, 0x43, 0xab, 0xaf, 0xd9, 0xbb, 0x39, 0x6a, 0x4b, 0xf0, 0x3b, + 0x89, 0xc1, 0x57, 0xe0, 0x41, 0x40, 0x43, 0x67, 0xaa, 0x8c, 0x08, 0xcf, 0x65, 0xb7, 0x0c, 0xad, + 0xbe, 0xd5, 0x6c, 0x5c, 0x7c, 0xa8, 0x15, 0xfe, 0xfa, 0x50, 0x7b, 0x3c, 0xa2, 0xf1, 0x38, 0x19, + 0x98, 0x2e, 0x0b, 0xd4, 0xdd, 0x56, 0xff, 0xbe, 0x14, 0xde, 0xa9, 0x15, 0xff, 0x10, 0x11, 0x61, + 0xb6, 0x89, 0xfb, 0xdb, 0xbf, 0xbf, 0x3f, 0xd1, 0xec, 0xdd, 0x80, 0x86, 0xb6, 0x2a, 0xd9, 0x23, + 0x5c, 0x79, 0xb9, 0xa0, 0x9c, 0x05, 0x74, 0x02, 0x2a, 0x84, 0xf3, 0x0a, 0x53, 0xdf, 0xc9, 0x87, + 0x0c, 0xad, 0xc9, 0x56, 0x94, 0xcd, 0x6c, 0xca, 0xcc, 0x7c, 0xca, 0xcc, 0xb6, 0x22, 0x34, 0xb7, + 0xd3, 0x83, 0xbc, 0xfd, 0xbb, 0xa6, 0x65, 0x16, 0x7b, 0x59, 0xa9, 0x63, 0x2a, 0xc4, 0x0b, 0x4c, + 0xfd, 0x9c, 0x06, 0x03, 0xa0, 0xe7, 0x26, 0xd8, 0xa7, 0x2e, 0x65, 0xc9, 0xbc, 0x53, 0xf1, 0x23, + 0x9d, 0x1e, 0x2a, 0xa7, 0xbc, 0xdc, 0x8c, 0x5d, 0x04, 0x2a, 0xf2, 0xd5, 0x38, 0x43, 0x8e, 0xdd, + 0x74, 0x27, 0xcb, 0x96, 0xf5, 0x13, 0xad, 0xaf, 0xde, 0xc2, 0x07, 0xb2, 0xec, 0xa1, 0xaa, 0x9a, + 0xc6, 0xcc, 0x1a, 0x0a, 0xcf, 0x41, 0x6d, 0xde, 0x71, 0x1a, 0x54, 0xd9, 0x96, 0x56, 0xb7, 0xad, + 0xce, 0xda, 0xe6, 0x95, 0x95, 0xb7, 0x0b, 0xee, 0x2f, 0x49, 0x2b, 0x27, 0x70, 0x45, 0xbf, 0x9d, + 0x85, 0x98, 0x30, 0x00, 0xe8, 0xa6, 0x80, 0x72, 0x94, 0x57, 0x74, 0xda, 0x5b, 0x9e, 0xec, 0xc9, + 0x8f, 0x1a, 0xd8, 0x9e, 0x99, 0x76, 0xf8, 0x35, 0xa8, 0xb4, 0x5e, 0x76, 0xfb, 0x9d, 0x6e, 0xff, + 0xa4, 0xef, 0x1c, 0xbf, 0x6c, 0x77, 0x9c, 0x93, 0x6e, 0xbf, 0xd7, 0x69, 0x1d, 0x1d, 0x1e, 0x75, + 0xda, 0xf7, 0x0a, 0x95, 0xea, 0x9b, 0x77, 0x06, 0x9a, 0x91, 0x9c, 0x84, 0x22, 0x22, 0x2e, 0x1d, + 0x52, 0xe2, 0x41, 0x13, 0xdc, 0x9f, 0x53, 0x1f, 0xf4, 0x0f, 0x7a, 0xf7, 0xb4, 0xca, 0xa7, 0x6f, + 0xde, 0x19, 0x3b, 0x33, 0xb2, 0x14, 0xa8, 0x14, 0x7f, 0xfa, 0x55, 0x2f, 0x34, 0x5f, 0x5c, 0x5c, + 0xea, 0xda, 0xfb, 0x4b, 0x5d, 0xfb, 0xe7, 0x52, 0xd7, 0x7e, 0xbe, 0xd2, 0x0b, 0xef, 0xaf, 0xf4, + 0xc2, 0x9f, 0x57, 0x7a, 0xe1, 0xfb, 0xa7, 0xd7, 0x42, 0x76, 0xb2, 0xdf, 0x89, 0x2e, 0x89, 0xcf, + 0x18, 0x3f, 0xb5, 0xf2, 0xaf, 0xdd, 0x24, 0xff, 0xde, 0xc9, 0xc8, 0x83, 0x92, 0xbc, 0xd2, 0x8d, + 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x0e, 0xc5, 0x76, 0x6f, 0x5f, 0x07, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -250,6 +355,18 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Slashing != nil { + { + size, err := m.Slashing.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + } if m.MaxSizePrices != 0 { i = encodeVarintParams(dAtA, i, uint64(m.MaxSizePrices)) i-- @@ -353,6 +470,100 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *SlashingParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SlashingParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SlashingParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.SlashFractionMalicious.Size() + i -= size + if _, err := m.SlashFractionMalicious.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + { + size := m.SlashFractionMiss.Size() + i -= size + if _, err := m.SlashFractionMiss.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + { + size := m.SlashFractionMaliciousReport.Size() + i -= size + if _, err := m.SlashFractionMaliciousReport.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + { + size := m.SlashFractionMissReport.Size() + i -= size + if _, err := m.SlashFractionMissReport.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + n2, err2 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.OracleMaliciousJailDuration, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.OracleMaliciousJailDuration):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintParams(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0x22 + n3, err3 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.OracleMissJailDuration, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.OracleMissJailDuration):]) + if err3 != nil { + return 0, err3 + } + i -= n3 + i = encodeVarintParams(dAtA, i, uint64(n3)) + i-- + dAtA[i] = 0x1a + { + size := m.MinReportedPerWindow.Size() + i -= size + if _, err := m.MinReportedPerWindow.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.ReportedRoundsWindow != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.ReportedRoundsWindow)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintParams(dAtA []byte, offset int, v uint64) int { offset -= sovParams(v) base := offset @@ -418,6 +629,36 @@ func (m *Params) Size() (n int) { if m.MaxSizePrices != 0 { n += 1 + sovParams(uint64(m.MaxSizePrices)) } + if m.Slashing != nil { + l = m.Slashing.Size() + n += 1 + l + sovParams(uint64(l)) + } + return n +} + +func (m *SlashingParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ReportedRoundsWindow != 0 { + n += 1 + sovParams(uint64(m.ReportedRoundsWindow)) + } + l = m.MinReportedPerWindow.Size() + n += 1 + l + sovParams(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.OracleMissJailDuration) + n += 1 + l + sovParams(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.OracleMaliciousJailDuration) + n += 1 + l + sovParams(uint64(l)) + l = m.SlashFractionMissReport.Size() + n += 1 + l + sovParams(uint64(l)) + l = m.SlashFractionMaliciousReport.Size() + n += 1 + l + sovParams(uint64(l)) + l = m.SlashFractionMiss.Size() + n += 1 + l + sovParams(uint64(l)) + l = m.SlashFractionMalicious.Size() + n += 1 + l + sovParams(uint64(l)) return n } @@ -740,6 +981,342 @@ func (m *Params) Unmarshal(dAtA []byte) error { break } } + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Slashing", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Slashing == nil { + m.Slashing = &SlashingParams{} + } + if err := m.Slashing.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SlashingParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SlashingParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SlashingParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReportedRoundsWindow", wireType) + } + m.ReportedRoundsWindow = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ReportedRoundsWindow |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinReportedPerWindow", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MinReportedPerWindow.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OracleMissJailDuration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.OracleMissJailDuration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OracleMaliciousJailDuration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.OracleMaliciousJailDuration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SlashFractionMissReport", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SlashFractionMissReport.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SlashFractionMaliciousReport", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SlashFractionMaliciousReport.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SlashFractionMiss", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SlashFractionMiss.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SlashFractionMalicious", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SlashFractionMalicious.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/oracle/types/slashing.pb.go b/x/oracle/types/slashing.pb.go new file mode 100644 index 000000000..d61331489 --- /dev/null +++ b/x/oracle/types/slashing.pb.go @@ -0,0 +1,426 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: exocore/oracle/v1/slashing.proto + +package types + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type ValidatorReportInfo struct { + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + StartHeight int64 `protobuf:"varint,2,opt,name=startHeight,proto3" json:"startHeight,omitempty"` + IndexOffset int64 `protobuf:"varint,3,opt,name=index_offset,json=indexOffset,proto3" json:"index_offset,omitempty"` + MissedRoundsCounter int64 `protobuf:"varint,4,opt,name=missed_rounds_counter,json=missedRoundsCounter,proto3" json:"missed_rounds_counter,omitempty"` +} + +func (m *ValidatorReportInfo) Reset() { *m = ValidatorReportInfo{} } +func (m *ValidatorReportInfo) String() string { return proto.CompactTextString(m) } +func (*ValidatorReportInfo) ProtoMessage() {} +func (*ValidatorReportInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_27165252f41a09d2, []int{0} +} +func (m *ValidatorReportInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ValidatorReportInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ValidatorReportInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ValidatorReportInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ValidatorReportInfo.Merge(m, src) +} +func (m *ValidatorReportInfo) XXX_Size() int { + return m.Size() +} +func (m *ValidatorReportInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ValidatorReportInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ValidatorReportInfo proto.InternalMessageInfo + +func (m *ValidatorReportInfo) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *ValidatorReportInfo) GetStartHeight() int64 { + if m != nil { + return m.StartHeight + } + return 0 +} + +func (m *ValidatorReportInfo) GetIndexOffset() int64 { + if m != nil { + return m.IndexOffset + } + return 0 +} + +func (m *ValidatorReportInfo) GetMissedRoundsCounter() int64 { + if m != nil { + return m.MissedRoundsCounter + } + return 0 +} + +func init() { + proto.RegisterType((*ValidatorReportInfo)(nil), "exocore.oracle.v1.ValidatorReportInfo") +} + +func init() { proto.RegisterFile("exocore/oracle/v1/slashing.proto", fileDescriptor_27165252f41a09d2) } + +var fileDescriptor_27165252f41a09d2 = []byte{ + // 260 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0x31, 0x4e, 0x84, 0x40, + 0x14, 0x86, 0x19, 0xd7, 0x68, 0x1c, 0x6d, 0x64, 0x63, 0x42, 0x35, 0x41, 0xab, 0xad, 0xc0, 0xd5, + 0x1b, 0x68, 0x4c, 0xd4, 0x42, 0x13, 0x0a, 0x0b, 0x1b, 0x32, 0xcb, 0x3c, 0x60, 0x22, 0xcb, 0x23, + 0x33, 0x8f, 0x15, 0x6f, 0xe1, 0x31, 0x3c, 0x8a, 0xe5, 0x96, 0x96, 0x06, 0x2e, 0x62, 0xc2, 0x48, + 0xb2, 0xe5, 0xfb, 0xbf, 0xaf, 0x79, 0x1f, 0x0f, 0xa1, 0xc3, 0x0c, 0x0d, 0xc4, 0x68, 0x64, 0x56, + 0x41, 0xbc, 0x59, 0xc6, 0xb6, 0x92, 0xb6, 0xd4, 0x75, 0x11, 0x35, 0x06, 0x09, 0xfd, 0xd3, 0x7f, + 0x23, 0x72, 0x46, 0xb4, 0x59, 0x5e, 0x7c, 0x31, 0x3e, 0x7f, 0x91, 0x95, 0x56, 0x92, 0xd0, 0x24, + 0xd0, 0xa0, 0xa1, 0x87, 0x3a, 0x47, 0x3f, 0xe0, 0x87, 0x52, 0x29, 0x03, 0xd6, 0x06, 0x2c, 0x64, + 0x8b, 0xa3, 0x64, 0x3a, 0xfd, 0x90, 0x1f, 0x5b, 0x92, 0x86, 0xee, 0x41, 0x17, 0x25, 0x05, 0x7b, + 0x21, 0x5b, 0xcc, 0x92, 0xdd, 0xc9, 0x3f, 0xe7, 0x27, 0xba, 0x56, 0xd0, 0xa5, 0x98, 0xe7, 0x16, + 0x28, 0x98, 0x39, 0x65, 0xdc, 0x9e, 0xc7, 0xc9, 0xbf, 0xe2, 0x67, 0x6b, 0x6d, 0x2d, 0xa8, 0xd4, + 0x60, 0x5b, 0x2b, 0x9b, 0x66, 0xd8, 0xd6, 0x04, 0x26, 0xd8, 0x1f, 0xdd, 0xb9, 0x83, 0xc9, 0xc8, + 0x6e, 0x1d, 0xba, 0x79, 0xfc, 0xee, 0x05, 0xdb, 0xf6, 0x82, 0xfd, 0xf6, 0x82, 0x7d, 0x0e, 0xc2, + 0xdb, 0x0e, 0xc2, 0xfb, 0x19, 0x84, 0xf7, 0x7a, 0x59, 0x68, 0x2a, 0xdb, 0x55, 0x94, 0xe1, 0x3a, + 0xbe, 0x73, 0x2f, 0x3e, 0x01, 0xbd, 0xa3, 0x79, 0x8b, 0xa7, 0x26, 0xdd, 0x54, 0x85, 0x3e, 0x1a, + 0xb0, 0xab, 0x83, 0x31, 0xc8, 0xf5, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe4, 0xb2, 0x22, 0x5e, + 0x34, 0x01, 0x00, 0x00, +} + +func (m *ValidatorReportInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ValidatorReportInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ValidatorReportInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MissedRoundsCounter != 0 { + i = encodeVarintSlashing(dAtA, i, uint64(m.MissedRoundsCounter)) + i-- + dAtA[i] = 0x20 + } + if m.IndexOffset != 0 { + i = encodeVarintSlashing(dAtA, i, uint64(m.IndexOffset)) + i-- + dAtA[i] = 0x18 + } + if m.StartHeight != 0 { + i = encodeVarintSlashing(dAtA, i, uint64(m.StartHeight)) + i-- + dAtA[i] = 0x10 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintSlashing(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintSlashing(dAtA []byte, offset int, v uint64) int { + offset -= sovSlashing(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ValidatorReportInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovSlashing(uint64(l)) + } + if m.StartHeight != 0 { + n += 1 + sovSlashing(uint64(m.StartHeight)) + } + if m.IndexOffset != 0 { + n += 1 + sovSlashing(uint64(m.IndexOffset)) + } + if m.MissedRoundsCounter != 0 { + n += 1 + sovSlashing(uint64(m.MissedRoundsCounter)) + } + return n +} + +func sovSlashing(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozSlashing(x uint64) (n int) { + return sovSlashing(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ValidatorReportInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSlashing + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ValidatorReportInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ValidatorReportInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSlashing + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthSlashing + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthSlashing + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field StartHeight", wireType) + } + m.StartHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSlashing + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.StartHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IndexOffset", wireType) + } + m.IndexOffset = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSlashing + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.IndexOffset |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MissedRoundsCounter", wireType) + } + m.MissedRoundsCounter = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSlashing + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MissedRoundsCounter |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipSlashing(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthSlashing + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipSlashing(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSlashing + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSlashing + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSlashing + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthSlashing + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupSlashing + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthSlashing + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthSlashing = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowSlashing = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupSlashing = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/oracle/types/types.go b/x/oracle/types/types.go index 18135f518..09365b51a 100644 --- a/x/oracle/types/types.go +++ b/x/oracle/types/types.go @@ -36,11 +36,20 @@ type Price struct { Decimal uint8 } +type AggFinalPrice struct { + FeederID uint64 + SourceID uint64 + DetID string + Price string +} + const ( DefaultPriceValue = 1 DefaultPriceDecimal = 0 ) +var DelimiterForCombinedKey = byte('/') + func Uint64Bytes(value uint64) []byte { valueBytes := make([]byte, 8) binary.BigEndian.PutUint64(valueBytes, value) From 922a749ac2e89cc83764c04a47291c6ea5c38367 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Tue, 22 Oct 2024 23:14:20 +0800 Subject: [PATCH 02/22] add slashing info for genesis, export/init --- proto/exocore/oracle/v1/genesis.proto | 24 +- proto/exocore/oracle/v1/params.proto | 16 +- x/oracle/genesis.go | 32 +- x/oracle/keeper/slashing.go | 47 +- x/oracle/module.go | 4 +- x/oracle/types/genesis.go | 7 + x/oracle/types/genesis.pb.go | 639 ++++++++++++++++++++++++-- x/oracle/types/genesis_test.go | 12 +- x/oracle/types/key_slashing.go | 4 - x/oracle/types/params.go | 25 + x/oracle/types/params.pb.go | 212 +++------ 11 files changed, 809 insertions(+), 213 deletions(-) diff --git a/proto/exocore/oracle/v1/genesis.proto b/proto/exocore/oracle/v1/genesis.proto index 512db1f02..4d88c7663 100644 --- a/proto/exocore/oracle/v1/genesis.proto +++ b/proto/exocore/oracle/v1/genesis.proto @@ -9,6 +9,7 @@ import "exocore/oracle/v1/params.proto"; import "exocore/oracle/v1/prices.proto"; import "exocore/oracle/v1/recent_msg.proto"; import "exocore/oracle/v1/recent_params.proto"; +import "exocore/oracle/v1/slashing.proto"; import "exocore/oracle/v1/validator_update_block.proto"; import "gogoproto/gogo.proto"; @@ -18,10 +19,12 @@ option go_package = "github.com/ExocoreNetwork/exocore/x/oracle/types"; message GenesisState { // module params Params params = 1 [(gogoproto.nullable) = false]; - // prices of all tokens + + // prices of all tokens including NST repeated Prices prices_list = 2 [(gogoproto.nullable) = false]; //TODO: userDefinedTokenFeeder + // information for memory-cache recovery // latest block on which the validator set be updated ValidatorUpdateBlock validator_update_block = 3; // index for the cached recent params @@ -32,10 +35,18 @@ message GenesisState { repeated RecentMsg recent_msg_list = 6[(gogoproto.nullable) = false]; // cached recent params repeated RecentParams recent_params_list = 7[(gogoproto.nullable) = false]; + + // information for NST related // stakerInfos for each nst token repeated StakerInfosAssets staker_infos_assets = 8[(gogoproto.nullable) = false]; // stakerList for each nst token repeated StakerListAssets staker_list_assets = 9[(gogoproto.nullable) = false]; + + // information for slashing history + // ValidatorReportInfo records all the validatorReportInfos + repeated ValidatorReportInfo report_infos = 10[(gogoproto.nullable)=false]; + // ValidatorMissedRounds records missedRounds for all validators seen + repeated ValidatorMissedRounds missed_rounds = 11[(gogoproto.nullable)=false]; } // stakerInfosAssets bond stakerinfos to their related assets id @@ -53,3 +64,14 @@ message StakerListAssets { // stakerList StakerList staker_list = 2; } + +// ValidatorMissedRounds record missed rounds indexes for a validator which consAddr corresponding to the address +message ValidatorMissedRounds { + string address = 1; + repeated MissedRound missed_rounds = 2; +} + +message MissedRound { + int64 index = 1; + bool missed = 2; +} diff --git a/proto/exocore/oracle/v1/params.proto b/proto/exocore/oracle/v1/params.proto index 0bfaa7f7b..a7794e0b6 100644 --- a/proto/exocore/oracle/v1/params.proto +++ b/proto/exocore/oracle/v1/params.proto @@ -36,7 +36,7 @@ message Params { // for each token, only keep max_size_prices round of prices int32 max_size_prices = 11; - // slashing defined the slashing related params + // slashing defines the slashing related params SlashingParams slashing = 12; } @@ -62,22 +62,12 @@ message SlashingParams { [(gogoproto.nullable) = false, (amino.dont_omitempty) = true, (gogoproto.stdduration) = true]; google.protobuf.Duration oracle_malicious_jail_duration =4 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true, (gogoproto.stdduration) = true]; - bytes slash_fraction_miss_report = 5 [ + bytes slash_fraction_miss = 5 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; - bytes slash_fraction_malicious_report = 6 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false, - (amino.dont_omitempty) = true - ]; - bytes slash_fraction_miss = 7 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false, - (amino.dont_omitempty) = true - ]; - bytes slash_fraction_malicious = 8 [ + bytes slash_fraction_malicious = 6 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false, (amino.dont_omitempty) = true diff --git a/x/oracle/genesis.go b/x/oracle/genesis.go index 084caa580..9085279eb 100644 --- a/x/oracle/genesis.go +++ b/x/oracle/genesis.go @@ -40,6 +40,16 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) for _, elem := range genState.StakerInfosAssets { k.SetStakerInfos(ctx, elem.AssetId, elem.StakerInfos) } + // set validatorReportInfos + for _, elem := range genState.ReportInfos { + k.SetValidatorReportInfo(ctx, elem.Address, elem) + } + // set vlidatorMissedRounds + for _, elem := range genState.MissedRounds { + for _, missedRound := range elem.MissedRounds { + k.SetValidatorMissedRoundBitArray(ctx, elem.Address, uint64(missedRound.Index), missedRound.Missed) + } + } // this line is used by starport scaffolding # genesis/module/init k.SetParams(ctx, genState.Params) } @@ -47,9 +57,13 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) // ExportGenesis returns the module's exported genesis func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { genesis := types.DefaultGenesis() + // params genesis.Params = k.GetParams(ctx) + // priceList genesis.PricesList = k.GetAllPrices(ctx) + + // cache recovery related, used by agc // Get all validatorUpdateBlock validatorUpdateBlock, found := k.GetValidatorUpdateBlock(ctx) if found { @@ -67,9 +81,25 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { } genesis.RecentMsgList = k.GetAllRecentMsg(ctx) genesis.RecentParamsList = k.GetAllRecentParams(ctx) - // TODO: export stakerListAssets, and stakerInfosAssets + + // NST related genesis.StakerInfosAssets = k.GetAllStakerInfosAssets(ctx) genesis.StakerListAssets = k.GetAllStakerListAssets(ctx) + + // slashing related + reportInfos := make([]types.ValidatorReportInfo, 0) + validatorMissedRounds := make([]types.ValidatorMissedRounds, 0) + k.IterateValidatorReportInfos(ctx, func(validator string, reportInfo types.ValidatorReportInfo) bool { + reportInfos = append(reportInfos, reportInfo) + missedRounds := k.GetValidatorMissedRounds(ctx, validator) + validatorMissedRounds = append(validatorMissedRounds, types.ValidatorMissedRounds{ + Address: validator, + MissedRounds: missedRounds, + }) + return false + }) + genesis.ReportInfos = reportInfos + genesis.MissedRounds = validatorMissedRounds // this line is used by starport scaffolding # genesis/module/export return genesis diff --git a/x/oracle/keeper/slashing.go b/x/oracle/keeper/slashing.go index eedde3394..f9bc86db7 100644 --- a/x/oracle/keeper/slashing.go +++ b/x/oracle/keeper/slashing.go @@ -4,6 +4,7 @@ import ( "time" "github.com/ExocoreNetwork/exocore/x/oracle/types" + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" gogotypes "github.com/cosmos/gogoproto/types" ) @@ -97,8 +98,52 @@ func (k Keeper) GetMaliciousJailDuration(ctx sdk.Context) (res time.Duration) { return k.GetParams(ctx).Slashing.OracleMaliciousJailDuration } +// IterateValidatorReportedInfos iterates over the stored reportInfo +// and performs a callback function +func (k Keeper) IterateValidatorReportInfos(ctx sdk.Context, handler func(address string, reportInfo types.ValidatorReportInfo) (stop bool)) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ValidatorReportInfoPrefix) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + for ; iterator.Valid(); iterator.Next() { + address := string(iterator.Key()) + var info types.ValidatorReportInfo + k.cdc.MustUnmarshal(iterator.Value(), &info) + if handler(address, info) { + break + } + } + iterator.Close() +} + +func (k Keeper) IterateValidatorMissedRoundBitArray(ctx sdk.Context, validator string, handler func(index int64, missed bool) (strop bool)) { + // store := prefix.NewStore(ctx.KVStore(k.storeKey), types.SlashingMissedBitArrayPrefix(validator)) + store := ctx.KVStore(k.storeKey) + index := int64(0) + // Array may be sparse + for ; index < k.GetReportedRoundsWindow(ctx); index++ { + var missed gogotypes.BoolValue + bz := store.Get(types.SlashingMissedBitArrayKey(validator, uint64(index))) + if bz == nil { + continue + } + + k.cdc.MustUnmarshal(bz, &missed) + if handler(index, missed.Value) { + break + } + } +} + +func (k Keeper) GetValidatorMissedRounds(ctx sdk.Context, address string) []*types.MissedRound { + missedRounds := []*types.MissedRound{} + k.IterateValidatorMissedRoundBitArray(ctx, address, func(index int64, missed bool) (stop bool) { + missedRounds = append(missedRounds, types.NewMissedRound(index, missed)) + return false + }) + return missedRounds +} + // clearValidatorMissedBlockBitArray deletes every instance of ValidatorMissedBlockBitArray in the store -func (k Keeper) ClearValidatorMissedBlockBitArray(ctx sdk.Context, validator string) { +func (k Keeper) ClearValidatorMissedRoundBitArray(ctx sdk.Context, validator string) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, types.SlashingMissedBitArrayPrefix(validator)) defer iterator.Close() diff --git a/x/oracle/module.go b/x/oracle/module.go index eca337d69..609928a12 100644 --- a/x/oracle/module.go +++ b/x/oracle/module.go @@ -247,7 +247,7 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val am.keeper.JailUntil(ctx, consAddr, jailUntil) reportedInfo.MissedRoundsCounter = 0 reportedInfo.IndexOffset = 0 - am.keeper.ClearValidatorMissedBlockBitArray(ctx, validator) + am.keeper.ClearValidatorMissedRoundBitArray(ctx, validator) } continue } @@ -322,7 +322,7 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val // We need to reset the counter & array so that the validator won't be immediately slashed for miss report info upon rebonding. reportedInfo.MissedRoundsCounter = 0 reportedInfo.IndexOffset = 0 - am.keeper.ClearValidatorMissedBlockBitArray(ctx, validator) + am.keeper.ClearValidatorMissedRoundBitArray(ctx, validator) logger.Info( "slashing and jailing validator due to liveness fault", diff --git a/x/oracle/types/genesis.go b/x/oracle/types/genesis.go index d1768b13e..46f4a0d57 100644 --- a/x/oracle/types/genesis.go +++ b/x/oracle/types/genesis.go @@ -35,6 +35,13 @@ func NewGenesisState(p Params) *GenesisState { } } +func NewMissedRound(index int64, missed bool) *MissedRound { + return &MissedRound{ + Index: index, + Missed: missed, + } +} + // Validate performs basic genesis state validation returning an error upon any // failure. func (gs GenesisState) Validate() error { diff --git a/x/oracle/types/genesis.pb.go b/x/oracle/types/genesis.pb.go index dbd1c437f..7e3e9e917 100644 --- a/x/oracle/types/genesis.pb.go +++ b/x/oracle/types/genesis.pb.go @@ -27,9 +27,10 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type GenesisState struct { // module params Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` - // prices of all tokens + // prices of all tokens including NST PricesList []Prices `protobuf:"bytes,2,rep,name=prices_list,json=pricesList,proto3" json:"prices_list"` //TODO: userDefinedTokenFeeder + // information for memory-cache recovery // latest block on which the validator set be updated ValidatorUpdateBlock *ValidatorUpdateBlock `protobuf:"bytes,3,opt,name=validator_update_block,json=validatorUpdateBlock,proto3" json:"validator_update_block,omitempty"` // index for the cached recent params @@ -40,10 +41,16 @@ type GenesisState struct { RecentMsgList []RecentMsg `protobuf:"bytes,6,rep,name=recent_msg_list,json=recentMsgList,proto3" json:"recent_msg_list"` // cached recent params RecentParamsList []RecentParams `protobuf:"bytes,7,rep,name=recent_params_list,json=recentParamsList,proto3" json:"recent_params_list"` + // information for NST related // stakerInfos for each nst token StakerInfosAssets []StakerInfosAssets `protobuf:"bytes,8,rep,name=staker_infos_assets,json=stakerInfosAssets,proto3" json:"staker_infos_assets"` // stakerList for each nst token StakerListAssets []StakerListAssets `protobuf:"bytes,9,rep,name=staker_list_assets,json=stakerListAssets,proto3" json:"staker_list_assets"` + // information for slashing history + // ValidatorReportInfo records all the validatorReportInfos + ReportInfos []ValidatorReportInfo `protobuf:"bytes,10,rep,name=report_infos,json=reportInfos,proto3" json:"report_infos"` + // ValidatorMissedRounds records missedRounds for all validators seen + MissedRounds []ValidatorMissedRounds `protobuf:"bytes,11,rep,name=missed_rounds,json=missedRounds,proto3" json:"missed_rounds"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -142,6 +149,20 @@ func (m *GenesisState) GetStakerListAssets() []StakerListAssets { return nil } +func (m *GenesisState) GetReportInfos() []ValidatorReportInfo { + if m != nil { + return m.ReportInfos + } + return nil +} + +func (m *GenesisState) GetMissedRounds() []ValidatorMissedRounds { + if m != nil { + return m.MissedRounds + } + return nil +} + // stakerInfosAssets bond stakerinfos to their related assets id type StakerInfosAssets struct { // asset_id tells the assetid which the stakerInfos belong to @@ -252,51 +273,166 @@ func (m *StakerListAssets) GetStakerList() *StakerList { return nil } +// ValidatorMissedRounds record missed rounds indexes for a validator which consAddr corresponding to the address +type ValidatorMissedRounds struct { + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + MissedRounds []*MissedRound `protobuf:"bytes,2,rep,name=missed_rounds,json=missedRounds,proto3" json:"missed_rounds,omitempty"` +} + +func (m *ValidatorMissedRounds) Reset() { *m = ValidatorMissedRounds{} } +func (m *ValidatorMissedRounds) String() string { return proto.CompactTextString(m) } +func (*ValidatorMissedRounds) ProtoMessage() {} +func (*ValidatorMissedRounds) Descriptor() ([]byte, []int) { + return fileDescriptor_6b68ac5b0c7f4305, []int{3} +} +func (m *ValidatorMissedRounds) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ValidatorMissedRounds) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ValidatorMissedRounds.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ValidatorMissedRounds) XXX_Merge(src proto.Message) { + xxx_messageInfo_ValidatorMissedRounds.Merge(m, src) +} +func (m *ValidatorMissedRounds) XXX_Size() int { + return m.Size() +} +func (m *ValidatorMissedRounds) XXX_DiscardUnknown() { + xxx_messageInfo_ValidatorMissedRounds.DiscardUnknown(m) +} + +var xxx_messageInfo_ValidatorMissedRounds proto.InternalMessageInfo + +func (m *ValidatorMissedRounds) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *ValidatorMissedRounds) GetMissedRounds() []*MissedRound { + if m != nil { + return m.MissedRounds + } + return nil +} + +type MissedRound struct { + Index int64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` + Missed bool `protobuf:"varint,2,opt,name=missed,proto3" json:"missed,omitempty"` +} + +func (m *MissedRound) Reset() { *m = MissedRound{} } +func (m *MissedRound) String() string { return proto.CompactTextString(m) } +func (*MissedRound) ProtoMessage() {} +func (*MissedRound) Descriptor() ([]byte, []int) { + return fileDescriptor_6b68ac5b0c7f4305, []int{4} +} +func (m *MissedRound) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MissedRound) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MissedRound.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MissedRound) XXX_Merge(src proto.Message) { + xxx_messageInfo_MissedRound.Merge(m, src) +} +func (m *MissedRound) XXX_Size() int { + return m.Size() +} +func (m *MissedRound) XXX_DiscardUnknown() { + xxx_messageInfo_MissedRound.DiscardUnknown(m) +} + +var xxx_messageInfo_MissedRound proto.InternalMessageInfo + +func (m *MissedRound) GetIndex() int64 { + if m != nil { + return m.Index + } + return 0 +} + +func (m *MissedRound) GetMissed() bool { + if m != nil { + return m.Missed + } + return false +} + func init() { proto.RegisterType((*GenesisState)(nil), "exocore.oracle.v1.GenesisState") proto.RegisterType((*StakerInfosAssets)(nil), "exocore.oracle.v1.StakerInfosAssets") proto.RegisterType((*StakerListAssets)(nil), "exocore.oracle.v1.StakerListAssets") + proto.RegisterType((*ValidatorMissedRounds)(nil), "exocore.oracle.v1.ValidatorMissedRounds") + proto.RegisterType((*MissedRound)(nil), "exocore.oracle.v1.MissedRound") } func init() { proto.RegisterFile("exocore/oracle/v1/genesis.proto", fileDescriptor_6b68ac5b0c7f4305) } var fileDescriptor_6b68ac5b0c7f4305 = []byte{ - // 555 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x94, 0x5b, 0x6f, 0xd3, 0x30, - 0x14, 0x80, 0xdb, 0xdd, 0xe7, 0x0e, 0x68, 0xbd, 0x09, 0x65, 0x15, 0x4b, 0x47, 0x19, 0x62, 0x12, - 0x52, 0xc2, 0xe0, 0x81, 0x37, 0x34, 0x2a, 0x21, 0xd4, 0x71, 0x11, 0x4a, 0xb9, 0x48, 0x93, 0x50, - 0xe4, 0xa6, 0x26, 0x58, 0x6d, 0xe3, 0xca, 0xf6, 0x4a, 0xf9, 0x17, 0xfc, 0xac, 0x3d, 0xee, 0x91, - 0x27, 0x04, 0xed, 0x1f, 0x41, 0x39, 0x76, 0x58, 0x73, 0x69, 0x79, 0x4b, 0x8e, 0xbf, 0xf3, 0xf9, - 0x9c, 0x63, 0xcb, 0xa8, 0x41, 0x27, 0x3c, 0xe0, 0x82, 0xba, 0x5c, 0x90, 0x60, 0x40, 0xdd, 0xf1, - 0x89, 0x1b, 0xd2, 0x88, 0x4a, 0x26, 0x9d, 0x91, 0xe0, 0x8a, 0xe3, 0x9a, 0x01, 0x1c, 0x0d, 0x38, - 0xe3, 0x93, 0xfa, 0x71, 0x3e, 0x87, 0x45, 0x3d, 0x3a, 0xf1, 0x05, 0x0d, 0x68, 0xa4, 0xfc, 0xa1, - 0x0c, 0x75, 0x72, 0xfd, 0xe1, 0x7f, 0xc8, 0x11, 0x11, 0x64, 0x68, 0x76, 0xaa, 0x1f, 0xe5, 0xe1, - 0x88, 0x28, 0x36, 0xa6, 0xbe, 0xe2, 0x7d, 0x1a, 0x19, 0xca, 0xce, 0x53, 0x29, 0x4b, 0xd1, 0xba, - 0x60, 0x01, 0x4d, 0xd6, 0x9b, 0xf9, 0xf5, 0x5c, 0xd9, 0xf7, 0x17, 0x32, 0xa9, 0xad, 0x9c, 0x3c, - 0x36, 0x26, 0x03, 0xd6, 0x23, 0x8a, 0x0b, 0xff, 0x62, 0xd4, 0x23, 0x8a, 0xfa, 0xdd, 0x01, 0x0f, - 0xfa, 0x86, 0xdf, 0x0b, 0x79, 0xc8, 0xe1, 0xd3, 0x8d, 0xbf, 0x74, 0xb4, 0xf9, 0x67, 0x1d, 0xed, - 0xbc, 0xd4, 0x23, 0xef, 0x28, 0xa2, 0x28, 0x7e, 0x8a, 0x36, 0xf4, 0x36, 0x56, 0xf9, 0xb0, 0x7c, - 0x5c, 0x79, 0xbc, 0xef, 0xe4, 0x8e, 0xc0, 0x79, 0x07, 0x40, 0x6b, 0xed, 0xf2, 0x57, 0xa3, 0xe4, - 0x19, 0x1c, 0x9f, 0xa2, 0x8a, 0x6e, 0xd5, 0x1f, 0x30, 0xa9, 0xac, 0x95, 0xc3, 0xd5, 0x45, 0xd9, - 0x40, 0x99, 0x6c, 0xa4, 0x73, 0x5e, 0x33, 0xa9, 0xf0, 0x67, 0x74, 0xbb, 0xb8, 0x03, 0x6b, 0x15, - 0x4a, 0x79, 0x50, 0x20, 0xfb, 0x98, 0x24, 0x7c, 0x00, 0xbe, 0x15, 0xe3, 0xde, 0xde, 0xb8, 0x20, - 0x8a, 0xdf, 0xa3, 0xdd, 0x82, 0xe3, 0xb7, 0xd6, 0xc0, 0x7d, 0x54, 0xe0, 0x6e, 0xc7, 0xb4, 0x07, - 0xb0, 0xee, 0xd8, 0xab, 0xb1, 0x6c, 0x08, 0xbf, 0x42, 0xd5, 0xec, 0xf5, 0xb3, 0xd6, 0x41, 0x79, - 0x77, 0xb9, 0xf2, 0x8d, 0x0c, 0xbd, 0x9b, 0x2c, 0xf5, 0x8f, 0xcf, 0xd0, 0xad, 0x6b, 0x8d, 0x9e, - 0xe3, 0x06, 0xcc, 0xf1, 0x4e, 0x81, 0xeb, 0x5f, 0x9a, 0x19, 0xe5, 0x0d, 0x91, 0x04, 0x60, 0x9a, - 0x1d, 0x84, 0x53, 0x8d, 0x6a, 0xdd, 0x26, 0xe8, 0x1a, 0x0b, 0x75, 0xa9, 0xa3, 0xad, 0x8a, 0xb9, - 0x18, 0x48, 0xcf, 0xd1, 0xae, 0x54, 0xa4, 0x4f, 0x85, 0xcf, 0xa2, 0x2f, 0x5c, 0xfa, 0x44, 0x4a, - 0xaa, 0xa4, 0xb5, 0x05, 0xd6, 0xa2, 0x19, 0x76, 0x80, 0x6e, 0xc7, 0xf0, 0x73, 0x60, 0x8d, 0xba, - 0x26, 0xb3, 0x0b, 0xf8, 0x13, 0xc2, 0xc6, 0x1d, 0x57, 0x9a, 0xa8, 0xb7, 0x41, 0x7d, 0x6f, 0xa1, - 0x3a, 0x2e, 0x2b, 0x65, 0xae, 0xca, 0x4c, 0xbc, 0x39, 0x42, 0xb5, 0x5c, 0x19, 0x78, 0x1f, 0x6d, - 0xc1, 0x0e, 0x3e, 0xeb, 0xc1, 0x4d, 0xdf, 0xf6, 0x36, 0xe1, 0xbf, 0xdd, 0xc3, 0xa7, 0x68, 0x67, - 0xbe, 0x49, 0x73, 0x95, 0x0f, 0x96, 0x76, 0xe7, 0x55, 0xe6, 0x1a, 0x6a, 0x0e, 0x51, 0x35, 0x5b, - 0xdd, 0xb2, 0x0d, 0x9f, 0xa1, 0xca, 0x5c, 0xe7, 0xd6, 0x0a, 0x5c, 0x9f, 0x83, 0xa5, 0x2d, 0x7b, - 0xe8, 0xba, 0xcd, 0xd6, 0xd9, 0xe5, 0xd4, 0x2e, 0x5f, 0x4d, 0xed, 0xf2, 0xef, 0xa9, 0x5d, 0xfe, - 0x31, 0xb3, 0x4b, 0x57, 0x33, 0xbb, 0xf4, 0x73, 0x66, 0x97, 0xce, 0x1f, 0x85, 0x4c, 0x7d, 0xbd, - 0xe8, 0x3a, 0x01, 0x1f, 0xba, 0x2f, 0xb4, 0xee, 0x2d, 0x55, 0xdf, 0xb8, 0xe8, 0xbb, 0xc9, 0xf3, - 0x31, 0x49, 0x1e, 0x10, 0xf5, 0x7d, 0x44, 0x65, 0x77, 0x03, 0xde, 0x85, 0x27, 0x7f, 0x03, 0x00, - 0x00, 0xff, 0xff, 0x17, 0x12, 0x12, 0xc9, 0x9b, 0x05, 0x00, 0x00, + // 681 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x94, 0xdd, 0x4e, 0x13, 0x41, + 0x14, 0xc7, 0x5b, 0x3e, 0x5a, 0x38, 0x2d, 0xda, 0x0e, 0x48, 0x16, 0x22, 0x0b, 0x56, 0x54, 0x12, + 0x93, 0xad, 0xe8, 0x85, 0x17, 0x26, 0x06, 0x31, 0xc6, 0x80, 0xa2, 0x66, 0xeb, 0x47, 0x42, 0x62, + 0x36, 0x4b, 0x77, 0x2c, 0x93, 0xb6, 0x3b, 0xcd, 0xcc, 0x50, 0xf1, 0x09, 0xbc, 0xf5, 0xb1, 0xb8, + 0xe4, 0xd2, 0x2b, 0x63, 0xe0, 0x45, 0xcc, 0x9e, 0x99, 0x85, 0xed, 0xee, 0xb6, 0xde, 0xed, 0x9c, + 0xf9, 0x9f, 0xdf, 0x39, 0xf3, 0x3f, 0xb3, 0x03, 0xeb, 0xf4, 0x94, 0xb7, 0xb9, 0xa0, 0x4d, 0x2e, + 0xfc, 0x76, 0x8f, 0x36, 0x87, 0xdb, 0xcd, 0x0e, 0x0d, 0xa9, 0x64, 0xd2, 0x19, 0x08, 0xae, 0x38, + 0xa9, 0x1b, 0x81, 0xa3, 0x05, 0xce, 0x70, 0x7b, 0x75, 0x2b, 0x9b, 0xc3, 0xc2, 0x80, 0x9e, 0x7a, + 0x82, 0xb6, 0x69, 0xa8, 0xbc, 0xbe, 0xec, 0xe8, 0xe4, 0xd5, 0x87, 0xff, 0x51, 0x0e, 0x7c, 0xe1, + 0xf7, 0x4d, 0xa5, 0xd5, 0xcd, 0xac, 0x38, 0xf4, 0x15, 0x1b, 0x52, 0x4f, 0xf1, 0x2e, 0x0d, 0x8d, + 0xca, 0xce, 0xaa, 0x46, 0x28, 0x79, 0xfb, 0x82, 0xb5, 0x69, 0xbc, 0xdf, 0xc8, 0xee, 0x67, 0xda, + 0xbe, 0x37, 0x56, 0x33, 0x52, 0x6a, 0x23, 0x2b, 0x93, 0x3d, 0x5f, 0x1e, 0xb3, 0x30, 0x06, 0x39, + 0x59, 0xc5, 0xd0, 0xef, 0xb1, 0xc0, 0x57, 0x5c, 0x78, 0x27, 0x83, 0xc0, 0x57, 0xd4, 0x3b, 0xea, + 0xf1, 0x76, 0xd7, 0xe8, 0x97, 0x3a, 0xbc, 0xc3, 0xf1, 0xb3, 0x19, 0x7d, 0xe9, 0x68, 0xe3, 0x67, + 0x19, 0xaa, 0xaf, 0xf5, 0x50, 0x5a, 0xca, 0x57, 0x94, 0x3c, 0x85, 0x92, 0x6e, 0xc4, 0x2a, 0x6e, + 0x14, 0xb7, 0x2a, 0x8f, 0x57, 0x9c, 0xcc, 0x90, 0x9c, 0x0f, 0x28, 0xd8, 0x9d, 0x39, 0xfb, 0xb3, + 0x5e, 0x70, 0x8d, 0x9c, 0xec, 0x40, 0x45, 0x9b, 0xe1, 0xf5, 0x98, 0x54, 0xd6, 0xd4, 0xc6, 0xf4, + 0xb8, 0x6c, 0x54, 0x99, 0x6c, 0xd0, 0x39, 0x6f, 0x99, 0x54, 0xe4, 0x2b, 0x2c, 0xe7, 0x9f, 0xc0, + 0x9a, 0xc6, 0x56, 0x1e, 0xe4, 0xc0, 0x3e, 0xc7, 0x09, 0x9f, 0x50, 0xbf, 0x1b, 0xc9, 0xdd, 0xa5, + 0x61, 0x4e, 0x94, 0x7c, 0x84, 0xc5, 0x9c, 0x0b, 0x62, 0xcd, 0x20, 0x7b, 0x33, 0x87, 0xbd, 0x17, + 0xa9, 0x5d, 0x14, 0xeb, 0x13, 0xbb, 0x75, 0x96, 0x0e, 0x91, 0x37, 0x50, 0x4b, 0x5f, 0x50, 0x6b, + 0x16, 0x91, 0x77, 0x26, 0x23, 0x0f, 0x64, 0xc7, 0xbd, 0xc1, 0x46, 0xd6, 0x64, 0x1f, 0x6e, 0x5e, + 0x63, 0xb4, 0x8f, 0x25, 0xf4, 0xf1, 0x76, 0x0e, 0xeb, 0x2a, 0xcd, 0x58, 0xb9, 0x20, 0xe2, 0x00, + 0xba, 0xd9, 0x02, 0x32, 0x72, 0x50, 0x8d, 0x2b, 0x23, 0x6e, 0x7d, 0x2c, 0x6e, 0x64, 0xb4, 0x35, + 0x91, 0x88, 0x21, 0xf4, 0x10, 0x16, 0xa5, 0xf2, 0xbb, 0x54, 0x78, 0x2c, 0xfc, 0xc6, 0xa5, 0xe7, + 0x4b, 0x49, 0x95, 0xb4, 0xe6, 0x90, 0x9a, 0xe7, 0x61, 0x0b, 0xd5, 0x7b, 0x91, 0xf8, 0x05, 0x6a, + 0x0d, 0xba, 0x2e, 0xd3, 0x1b, 0xe4, 0x0b, 0x10, 0xc3, 0x8e, 0x3a, 0x8d, 0xd1, 0xf3, 0x88, 0xbe, + 0x3b, 0x16, 0x1d, 0xb5, 0x35, 0x42, 0xae, 0xc9, 0x54, 0x9c, 0xbc, 0x87, 0xaa, 0xa0, 0x03, 0x2e, + 0x94, 0x6e, 0xda, 0x02, 0x44, 0xde, 0x9f, 0x74, 0x9b, 0x5c, 0xd4, 0x47, 0xdd, 0x19, 0x6a, 0x45, + 0x5c, 0x45, 0x24, 0x69, 0xc1, 0x42, 0x9f, 0x49, 0x49, 0x03, 0x4f, 0xf0, 0x93, 0x30, 0x90, 0x56, + 0x05, 0x89, 0x5b, 0x93, 0x88, 0x07, 0x98, 0xe0, 0xa2, 0xde, 0x30, 0xab, 0xfd, 0x44, 0xac, 0x31, + 0x80, 0x7a, 0xc6, 0x2c, 0xb2, 0x02, 0x73, 0xe8, 0x83, 0xc7, 0x02, 0xfc, 0x1f, 0xe7, 0xdd, 0x32, + 0xae, 0xf7, 0x02, 0xb2, 0x03, 0xd5, 0xe4, 0x28, 0xcc, 0x0f, 0xb7, 0x36, 0x71, 0x06, 0x6e, 0x25, + 0x61, 0x7b, 0xa3, 0x0f, 0xb5, 0xb4, 0x87, 0x93, 0x0a, 0x3e, 0x87, 0x4a, 0x62, 0x3e, 0xd6, 0x14, + 0x5e, 0xf2, 0xb5, 0x89, 0x83, 0x71, 0xe1, 0x7a, 0x18, 0x8d, 0x21, 0xdc, 0xca, 0x75, 0x83, 0x58, + 0x50, 0xf6, 0x83, 0x40, 0x50, 0x29, 0xaf, 0x4a, 0xea, 0x25, 0x79, 0x99, 0x36, 0x5a, 0x1f, 0xd2, + 0xce, 0x29, 0x9a, 0x20, 0xa6, 0x8c, 0x7d, 0x06, 0x95, 0xc4, 0x26, 0x59, 0x82, 0x59, 0xfc, 0xeb, + 0xb0, 0xd6, 0xb4, 0xab, 0x17, 0x64, 0x19, 0x4a, 0x3a, 0x09, 0xcf, 0x35, 0xe7, 0x9a, 0xd5, 0xee, + 0xfe, 0xd9, 0x85, 0x5d, 0x3c, 0xbf, 0xb0, 0x8b, 0x7f, 0x2f, 0xec, 0xe2, 0xaf, 0x4b, 0xbb, 0x70, + 0x7e, 0x69, 0x17, 0x7e, 0x5f, 0xda, 0x85, 0xc3, 0x47, 0x1d, 0xa6, 0x8e, 0x4f, 0x8e, 0x9c, 0x36, + 0xef, 0x37, 0x5f, 0xe9, 0x76, 0xde, 0x51, 0xf5, 0x9d, 0x8b, 0x6e, 0x33, 0x7e, 0x99, 0x4f, 0xe3, + 0xb7, 0x59, 0xfd, 0x18, 0x50, 0x79, 0x54, 0xc2, 0x27, 0xf7, 0xc9, 0xbf, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xb7, 0x4f, 0x3f, 0x85, 0x18, 0x07, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -319,6 +455,34 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.MissedRounds) > 0 { + for iNdEx := len(m.MissedRounds) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.MissedRounds[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + } + } + if len(m.ReportInfos) > 0 { + for iNdEx := len(m.ReportInfos) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ReportInfos[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + } + } if len(m.StakerListAssets) > 0 { for iNdEx := len(m.StakerListAssets) - 1; iNdEx >= 0; iNdEx-- { { @@ -524,6 +688,88 @@ func (m *StakerListAssets) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *ValidatorMissedRounds) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ValidatorMissedRounds) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ValidatorMissedRounds) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MissedRounds) > 0 { + for iNdEx := len(m.MissedRounds) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.MissedRounds[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MissedRound) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MissedRound) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MissedRound) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Missed { + i-- + if m.Missed { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if m.Index != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { offset -= sovGenesis(v) base := offset @@ -585,6 +831,18 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } + if len(m.ReportInfos) > 0 { + for _, e := range m.ReportInfos { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.MissedRounds) > 0 { + for _, e := range m.MissedRounds { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } return n } @@ -624,6 +882,40 @@ func (m *StakerListAssets) Size() (n int) { return n } +func (m *ValidatorMissedRounds) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if len(m.MissedRounds) > 0 { + for _, e := range m.MissedRounds { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *MissedRound) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Index != 0 { + n += 1 + sovGenesis(uint64(m.Index)) + } + if m.Missed { + n += 2 + } + return n +} + func sovGenesis(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -970,6 +1262,74 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ReportInfos", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ReportInfos = append(m.ReportInfos, ValidatorReportInfo{}) + if err := m.ReportInfos[len(m.ReportInfos)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MissedRounds", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MissedRounds = append(m.MissedRounds, ValidatorMissedRounds{}) + if err := m.MissedRounds[len(m.MissedRounds)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) @@ -1225,6 +1585,211 @@ func (m *StakerListAssets) Unmarshal(dAtA []byte) error { } return nil } +func (m *ValidatorMissedRounds) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ValidatorMissedRounds: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ValidatorMissedRounds: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MissedRounds", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MissedRounds = append(m.MissedRounds, &MissedRound{}) + if err := m.MissedRounds[len(m.MissedRounds)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MissedRound) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MissedRound: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MissedRound: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Missed", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Missed = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipGenesis(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/oracle/types/genesis_test.go b/x/oracle/types/genesis_test.go index 76a7843fc..bb9446ea3 100644 --- a/x/oracle/types/genesis_test.go +++ b/x/oracle/types/genesis_test.go @@ -2,7 +2,9 @@ package types_test import ( "testing" + time "time" + sdkmath "cosmossdk.io/math" "github.com/ExocoreNetwork/exocore/x/oracle/types" "github.com/stretchr/testify/require" ) @@ -55,6 +57,14 @@ func TestGenesisState_Validate(t *testing.T) { Mode: types.ConsensusModeASAP, MaxDetId: 5, MaxSizePrices: 100, + Slashing: &types.SlashingParams{ + ReportedRoundsWindow: 100, + MinReportedPerWindow: sdkmath.LegacyNewDec(1).Quo(sdkmath.LegacyNewDec(2)), + OracleMissJailDuration: 600 * time.Second, + OracleMaliciousJailDuration: 30 * 24 * time.Hour, + SlashFractionMiss: sdkmath.LegacyNewDec(1).Quo(sdkmath.LegacyNewDec(20)), + SlashFractionMalicious: sdkmath.LegacyNewDec(1).Quo(sdkmath.LegacyNewDec(10)), + }, }, // this line is used by starport scaffolding # types/genesis/validField }, @@ -151,7 +161,7 @@ func TestGenesisState_Validate(t *testing.T) { valid: false, }, { - desc: "valid", + desc: "invalid", genState: &types.GenesisState{ StakerListAssets: []types.StakerListAssets{ { diff --git a/x/oracle/types/key_slashing.go b/x/oracle/types/key_slashing.go index a5d64d5c6..ec5f13ee2 100644 --- a/x/oracle/types/key_slashing.go +++ b/x/oracle/types/key_slashing.go @@ -1,9 +1,5 @@ package types -// const ( -// SlashingPrefix = "Slashing/" -// ) - var ( SlashingPrefix = []byte("Slashing/") ValidatorReportInfoPrefix = append(SlashingPrefix, []byte("validator/value/")...) diff --git a/x/oracle/types/params.go b/x/oracle/types/params.go index 71b148610..6cef546e8 100644 --- a/x/oracle/types/params.go +++ b/x/oracle/types/params.go @@ -3,7 +3,9 @@ package types import ( "errors" "strings" + "time" + sdkmath "cosmossdk.io/math" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" "gopkg.in/yaml.v2" ) @@ -14,6 +16,7 @@ var ( KeySources = []byte("Sources") KeyRules = []byte("Rules") KeyTokenFeeders = []byte("TokenFeeders") + oneDec = sdkmath.LegacyNewDec(1) ) var _ paramtypes.ParamSet = (*Params)(nil) @@ -103,6 +106,14 @@ func DefaultParams() Params { Mode: ConsensusModeASAP, MaxDetId: 5, MaxSizePrices: 100, + Slashing: &SlashingParams{ + ReportedRoundsWindow: 100, + MinReportedPerWindow: sdkmath.LegacyNewDec(1).Quo(sdkmath.LegacyNewDec(2)), + OracleMissJailDuration: 600 * time.Second, + OracleMaliciousJailDuration: 30 * 24 * time.Hour, + SlashFractionMiss: sdkmath.LegacyNewDec(1).Quo(sdkmath.LegacyNewDec(20)), + SlashFractionMalicious: sdkmath.LegacyNewDec(1).Quo(sdkmath.LegacyNewDec(10)), + }, } } @@ -129,6 +140,20 @@ func (p Params) Validate() error { return ErrInvalidParams.Wrapf("invalid maxNonce/maxDetID/Threshold/Mode/MaxSizePrices: %d, %d, %d, %d, %d, %d", p.MaxNonce, p.MaxDetId, p.ThresholdA, p.ThresholdB, p.Mode, p.MaxSizePrices) } + slashing := p.Slashing + + if slashing == nil { + return ErrInvalidParams.Wrap("slashing params must not be nil") + } + + if slashing.ReportedRoundsWindow < 1 || + slashing.MinReportedPerWindow.GT(oneDec) || !slashing.MinReportedPerWindow.IsPositive() || + slashing.SlashFractionMiss.GT(oneDec) || !slashing.SlashFractionMiss.IsPositive() || + slashing.SlashFractionMalicious.GT(oneDec) || !slashing.SlashFractionMalicious.IsPositive() || + slashing.OracleMissJailDuration <= 0 || slashing.OracleMaliciousJailDuration <= 0 { + return ErrInvalidParams.Wrapf("invalid slashing params: reported_window/min_reported_per_window/oracle_miss_jail_duration/oracle_malicious_jail_duration/slash_fraction_miss/slash_fraction_malicious:%v,%v,%v,%v,%v,%v", slashing.ReportedRoundsWindow, slashing.MinReportedPerWindow, slashing.OracleMissJailDuration, slashing.OracleMaliciousJailDuration, slashing.SlashFractionMiss, slashing.SlashFractionMalicious) + } + // validate tokenFeeders feeders := make(map[uint64]*TokenFeeder) for fID, feeder := range p.TokenFeeders { diff --git a/x/oracle/types/params.pb.go b/x/oracle/types/params.pb.go index d078f3c8f..80499d674 100644 --- a/x/oracle/types/params.pb.go +++ b/x/oracle/types/params.pb.go @@ -84,7 +84,7 @@ type Params struct { MaxDetId int32 `protobuf:"varint,10,opt,name=max_det_id,json=maxDetId,proto3" json:"max_det_id,omitempty"` // for each token, only keep max_size_prices round of prices MaxSizePrices int32 `protobuf:"varint,11,opt,name=max_size_prices,json=maxSizePrices,proto3" json:"max_size_prices,omitempty"` - // slashing defined the slashing related params + // slashing defines the slashing related params Slashing *SlashingParams `protobuf:"bytes,12,opt,name=slashing,proto3" json:"slashing,omitempty"` } @@ -206,14 +206,12 @@ func (m *Params) GetSlashing() *SlashingParams { // slashing related params type SlashingParams struct { - ReportedRoundsWindow int64 `protobuf:"varint,1,opt,name=reported_rounds_window,json=reportedRoundsWindow,proto3" json:"reported_rounds_window,omitempty"` - MinReportedPerWindow github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=min_reported_per_window,json=minReportedPerWindow,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_reported_per_window"` - OracleMissJailDuration time.Duration `protobuf:"bytes,3,opt,name=oracle_miss_jail_duration,json=oracleMissJailDuration,proto3,stdduration" json:"oracle_miss_jail_duration"` - OracleMaliciousJailDuration time.Duration `protobuf:"bytes,4,opt,name=oracle_malicious_jail_duration,json=oracleMaliciousJailDuration,proto3,stdduration" json:"oracle_malicious_jail_duration"` - SlashFractionMissReport github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=slash_fraction_miss_report,json=slashFractionMissReport,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_miss_report"` - SlashFractionMaliciousReport github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=slash_fraction_malicious_report,json=slashFractionMaliciousReport,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_malicious_report"` - SlashFractionMiss github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,7,opt,name=slash_fraction_miss,json=slashFractionMiss,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_miss"` - SlashFractionMalicious github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,8,opt,name=slash_fraction_malicious,json=slashFractionMalicious,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_malicious"` + ReportedRoundsWindow int64 `protobuf:"varint,1,opt,name=reported_rounds_window,json=reportedRoundsWindow,proto3" json:"reported_rounds_window,omitempty"` + MinReportedPerWindow github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=min_reported_per_window,json=minReportedPerWindow,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_reported_per_window"` + OracleMissJailDuration time.Duration `protobuf:"bytes,3,opt,name=oracle_miss_jail_duration,json=oracleMissJailDuration,proto3,stdduration" json:"oracle_miss_jail_duration"` + OracleMaliciousJailDuration time.Duration `protobuf:"bytes,4,opt,name=oracle_malicious_jail_duration,json=oracleMaliciousJailDuration,proto3,stdduration" json:"oracle_malicious_jail_duration"` + SlashFractionMiss github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=slash_fraction_miss,json=slashFractionMiss,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_miss"` + SlashFractionMalicious github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=slash_fraction_malicious,json=slashFractionMalicious,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_malicious"` } func (m *SlashingParams) Reset() { *m = SlashingParams{} } @@ -279,60 +277,58 @@ func init() { func init() { proto.RegisterFile("exocore/oracle/v1/params.proto", fileDescriptor_72f39bba4594b794) } var fileDescriptor_72f39bba4594b794 = []byte{ - // 846 bytes of a gzipped FileDescriptorProto + // 814 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xbf, 0x6f, 0xdb, 0x46, - 0x18, 0x15, 0x63, 0x59, 0x71, 0xce, 0x76, 0x1a, 0x5f, 0x5c, 0xe7, 0xa4, 0xa8, 0x14, 0x1b, 0x14, + 0x14, 0x16, 0xa3, 0x1f, 0x71, 0x4e, 0x56, 0x1a, 0x5d, 0x5c, 0xf7, 0xa4, 0xb8, 0x14, 0x1b, 0x14, 0x81, 0x10, 0xa0, 0x64, 0x62, 0x65, 0x2a, 0xda, 0xc1, 0xfa, 0x61, 0xc0, 0x01, 0xac, 0x08, 0x54, - 0x8d, 0x02, 0x5d, 0x88, 0x13, 0x79, 0x92, 0x2e, 0x26, 0x79, 0xc4, 0x1d, 0x19, 0xab, 0x5e, 0xbb, - 0x14, 0x99, 0x3a, 0x66, 0x09, 0x50, 0xa0, 0x4b, 0xc7, 0xee, 0xfd, 0x07, 0x3c, 0x66, 0x2c, 0x3a, - 0xa4, 0x85, 0x3d, 0xf4, 0xdf, 0x28, 0x78, 0x3c, 0xaa, 0xd6, 0x0f, 0x0f, 0xd1, 0x62, 0xf3, 0xee, - 0xbd, 0xf7, 0xbd, 0x7b, 0x1f, 0xef, 0x13, 0x81, 0x4e, 0x26, 0xcc, 0x65, 0x9c, 0x58, 0x8c, 0x63, - 0xd7, 0x27, 0xd6, 0xeb, 0x67, 0x56, 0x84, 0x39, 0x0e, 0x84, 0x19, 0x71, 0x16, 0x33, 0xb8, 0xa3, - 0x70, 0x33, 0xc3, 0xcd, 0xd7, 0xcf, 0x2a, 0xd5, 0x45, 0x09, 0x0d, 0x87, 0x2c, 0x13, 0x54, 0xbe, - 0x58, 0x44, 0x63, 0x76, 0x4a, 0x42, 0x67, 0x48, 0x88, 0x47, 0xb8, 0x62, 0xed, 0x8e, 0xd8, 0x88, - 0xc9, 0x47, 0x2b, 0x7d, 0x52, 0xbb, 0xfa, 0x88, 0xb1, 0x91, 0x4f, 0x2c, 0xb9, 0x1a, 0x24, 0x43, - 0xcb, 0x4b, 0x38, 0x8e, 0x29, 0x0b, 0x15, 0x5e, 0x9b, 0xc7, 0x63, 0x1a, 0x10, 0x11, 0xe3, 0x20, - 0x52, 0x84, 0xb2, 0xcb, 0x44, 0xc0, 0x84, 0x93, 0x55, 0xce, 0x16, 0x0a, 0xda, 0xc1, 0x01, 0x0d, - 0x99, 0x25, 0xff, 0x66, 0x5b, 0x8f, 0xfe, 0x28, 0x82, 0x52, 0x4f, 0x86, 0x85, 0x4f, 0x41, 0xc9, - 0x1d, 0x63, 0x1a, 0x0a, 0xa4, 0x19, 0x6b, 0xf5, 0xcd, 0x7d, 0x64, 0x2e, 0xe4, 0x36, 0x5b, 0x29, - 0xc1, 0x56, 0xbc, 0x54, 0x21, 0x73, 0x09, 0x74, 0xeb, 0x46, 0xc5, 0xb7, 0x29, 0xc1, 0x56, 0x3c, - 0xd8, 0x00, 0xb7, 0x05, 0x4b, 0xb8, 0x4b, 0x04, 0x5a, 0x93, 0x92, 0xf2, 0x12, 0x49, 0x5f, 0x32, - 0xec, 0x9c, 0x09, 0x1b, 0x60, 0x9d, 0x27, 0x3e, 0x11, 0xa8, 0x28, 0x25, 0x9f, 0x2d, 0x91, 0xd8, - 0x89, 0x4f, 0x94, 0x2c, 0xe3, 0xc2, 0x16, 0xd8, 0xbe, 0xde, 0x73, 0x81, 0xd6, 0xa5, 0x58, 0xbf, - 0xe9, 0x88, 0x87, 0x92, 0x66, 0x6f, 0xc5, 0xff, 0x2f, 0x04, 0x7c, 0x08, 0xee, 0x04, 0x78, 0xe2, - 0x84, 0x2c, 0x74, 0x09, 0x2a, 0x19, 0x5a, 0x7d, 0xdd, 0xde, 0x08, 0xf0, 0xa4, 0x9b, 0xae, 0x61, - 0x0d, 0x6c, 0xc6, 0x63, 0x4e, 0xc4, 0x98, 0xf9, 0x9e, 0x83, 0xd1, 0x6d, 0x09, 0x83, 0xe9, 0xd6, - 0xc1, 0x2c, 0x61, 0x80, 0x36, 0xe6, 0x08, 0x4d, 0xf8, 0x1c, 0x14, 0x03, 0xe6, 0x11, 0x74, 0xc7, - 0xd0, 0xea, 0x77, 0xf7, 0x8d, 0x65, 0xfd, 0x66, 0xa1, 0x20, 0xa1, 0x48, 0xc4, 0x31, 0xf3, 0x88, - 0x2d, 0xd9, 0xb0, 0x0a, 0x40, 0x7a, 0x28, 0x8f, 0xc4, 0x0e, 0xf5, 0x10, 0x98, 0x9e, 0xaa, 0x4d, - 0xe2, 0x23, 0x0f, 0x3e, 0x06, 0x9f, 0xa4, 0xa8, 0xa0, 0xe7, 0xc4, 0x89, 0x38, 0x4d, 0x3b, 0xbd, - 0x29, 0x29, 0xdb, 0x01, 0x9e, 0xf4, 0xe9, 0x39, 0xe9, 0xc9, 0x4d, 0xf8, 0x0d, 0xd8, 0x10, 0x3e, - 0x16, 0x63, 0x1a, 0x8e, 0xd0, 0x96, 0xa1, 0xd5, 0x37, 0xf7, 0x3f, 0x5f, 0xf6, 0x2a, 0x14, 0x25, - 0xbb, 0x22, 0xf6, 0x54, 0xf2, 0x55, 0xf1, 0xed, 0x2f, 0xb5, 0xc2, 0xa3, 0x8b, 0x12, 0xb8, 0x3b, - 0x4b, 0x81, 0xcf, 0xc1, 0x1e, 0x27, 0x11, 0xe3, 0x31, 0xf1, 0x1c, 0xce, 0x92, 0xd0, 0x13, 0xce, - 0x19, 0x0d, 0x3d, 0x76, 0x86, 0x34, 0x43, 0xab, 0xaf, 0xd9, 0xbb, 0x39, 0x6a, 0x4b, 0xf0, 0x3b, - 0x89, 0xc1, 0x57, 0xe0, 0x41, 0x40, 0x43, 0x67, 0xaa, 0x8c, 0x08, 0xcf, 0x65, 0xb7, 0x0c, 0xad, - 0xbe, 0xd5, 0x6c, 0x5c, 0x7c, 0xa8, 0x15, 0xfe, 0xfa, 0x50, 0x7b, 0x3c, 0xa2, 0xf1, 0x38, 0x19, - 0x98, 0x2e, 0x0b, 0xd4, 0xdd, 0x56, 0xff, 0xbe, 0x14, 0xde, 0xa9, 0x15, 0xff, 0x10, 0x11, 0x61, - 0xb6, 0x89, 0xfb, 0xdb, 0xbf, 0xbf, 0x3f, 0xd1, 0xec, 0xdd, 0x80, 0x86, 0xb6, 0x2a, 0xd9, 0x23, - 0x5c, 0x79, 0xb9, 0xa0, 0x9c, 0x05, 0x74, 0x02, 0x2a, 0x84, 0xf3, 0x0a, 0x53, 0xdf, 0xc9, 0x87, - 0x0c, 0xad, 0xc9, 0x56, 0x94, 0xcd, 0x6c, 0xca, 0xcc, 0x7c, 0xca, 0xcc, 0xb6, 0x22, 0x34, 0xb7, - 0xd3, 0x83, 0xbc, 0xfd, 0xbb, 0xa6, 0x65, 0x16, 0x7b, 0x59, 0xa9, 0x63, 0x2a, 0xc4, 0x0b, 0x4c, - 0xfd, 0x9c, 0x06, 0x03, 0xa0, 0xe7, 0x26, 0xd8, 0xa7, 0x2e, 0x65, 0xc9, 0xbc, 0x53, 0xf1, 0x23, - 0x9d, 0x1e, 0x2a, 0xa7, 0xbc, 0xdc, 0x8c, 0x5d, 0x04, 0x2a, 0xf2, 0xd5, 0x38, 0x43, 0x8e, 0xdd, - 0x74, 0x27, 0xcb, 0x96, 0xf5, 0x13, 0xad, 0xaf, 0xde, 0xc2, 0x07, 0xb2, 0xec, 0xa1, 0xaa, 0x9a, - 0xc6, 0xcc, 0x1a, 0x0a, 0xcf, 0x41, 0x6d, 0xde, 0x71, 0x1a, 0x54, 0xd9, 0x96, 0x56, 0xb7, 0xad, - 0xce, 0xda, 0xe6, 0x95, 0x95, 0xb7, 0x0b, 0xee, 0x2f, 0x49, 0x2b, 0x27, 0x70, 0x45, 0xbf, 0x9d, - 0x85, 0x98, 0x30, 0x00, 0xe8, 0xa6, 0x80, 0x72, 0x94, 0x57, 0x74, 0xda, 0x5b, 0x9e, 0xec, 0xc9, - 0x8f, 0x1a, 0xd8, 0x9e, 0x99, 0x76, 0xf8, 0x35, 0xa8, 0xb4, 0x5e, 0x76, 0xfb, 0x9d, 0x6e, 0xff, - 0xa4, 0xef, 0x1c, 0xbf, 0x6c, 0x77, 0x9c, 0x93, 0x6e, 0xbf, 0xd7, 0x69, 0x1d, 0x1d, 0x1e, 0x75, - 0xda, 0xf7, 0x0a, 0x95, 0xea, 0x9b, 0x77, 0x06, 0x9a, 0x91, 0x9c, 0x84, 0x22, 0x22, 0x2e, 0x1d, - 0x52, 0xe2, 0x41, 0x13, 0xdc, 0x9f, 0x53, 0x1f, 0xf4, 0x0f, 0x7a, 0xf7, 0xb4, 0xca, 0xa7, 0x6f, - 0xde, 0x19, 0x3b, 0x33, 0xb2, 0x14, 0xa8, 0x14, 0x7f, 0xfa, 0x55, 0x2f, 0x34, 0x5f, 0x5c, 0x5c, - 0xea, 0xda, 0xfb, 0x4b, 0x5d, 0xfb, 0xe7, 0x52, 0xd7, 0x7e, 0xbe, 0xd2, 0x0b, 0xef, 0xaf, 0xf4, - 0xc2, 0x9f, 0x57, 0x7a, 0xe1, 0xfb, 0xa7, 0xd7, 0x42, 0x76, 0xb2, 0xdf, 0x89, 0x2e, 0x89, 0xcf, - 0x18, 0x3f, 0xb5, 0xf2, 0xaf, 0xdd, 0x24, 0xff, 0xde, 0xc9, 0xc8, 0x83, 0x92, 0xbc, 0xd2, 0x8d, - 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x0e, 0xc5, 0x76, 0x6f, 0x5f, 0x07, 0x00, 0x00, + 0x8d, 0x02, 0x5d, 0x88, 0x13, 0x79, 0x92, 0x2e, 0x26, 0x79, 0xc4, 0x1d, 0x19, 0xab, 0x59, 0xbb, + 0x14, 0x99, 0x3a, 0x66, 0x09, 0x50, 0xa0, 0x4b, 0xc7, 0xee, 0xfd, 0x07, 0x32, 0x66, 0x2c, 0x32, + 0xa4, 0x85, 0x3d, 0xf4, 0xdf, 0x28, 0x78, 0x3c, 0xaa, 0x91, 0xac, 0x0c, 0xf1, 0x22, 0xf1, 0xde, + 0xf7, 0x7d, 0xef, 0x7b, 0xef, 0xf1, 0x9e, 0x04, 0x74, 0xb2, 0x60, 0x2e, 0xe3, 0xc4, 0x62, 0x1c, + 0xbb, 0x3e, 0xb1, 0x9e, 0x3d, 0xb4, 0x22, 0xcc, 0x71, 0x20, 0xcc, 0x88, 0xb3, 0x98, 0xc1, 0xba, + 0xc2, 0xcd, 0x0c, 0x37, 0x9f, 0x3d, 0x6c, 0xee, 0x5d, 0x96, 0xd0, 0x70, 0xca, 0x32, 0x41, 0xf3, + 0xcb, 0xcb, 0x68, 0xcc, 0x4e, 0x49, 0xe8, 0x4c, 0x09, 0xf1, 0x08, 0x57, 0xac, 0x9d, 0x19, 0x9b, + 0x31, 0xf9, 0x68, 0xa5, 0x4f, 0x2a, 0xaa, 0xcf, 0x18, 0x9b, 0xf9, 0xc4, 0x92, 0xa7, 0x49, 0x32, + 0xb5, 0xbc, 0x84, 0xe3, 0x98, 0xb2, 0x50, 0xe1, 0xad, 0x75, 0x3c, 0xa6, 0x01, 0x11, 0x31, 0x0e, + 0x22, 0x45, 0x68, 0xb8, 0x4c, 0x04, 0x4c, 0x38, 0x59, 0xe6, 0xec, 0xa0, 0xa0, 0x3a, 0x0e, 0x68, + 0xc8, 0x2c, 0xf9, 0x99, 0x85, 0xee, 0xfe, 0x59, 0x02, 0x95, 0x91, 0x6c, 0x16, 0x3e, 0x00, 0x15, + 0x77, 0x8e, 0x69, 0x28, 0x90, 0x66, 0x14, 0xdb, 0xd5, 0x7d, 0x64, 0x5e, 0xea, 0xdb, 0xec, 0xa5, + 0x04, 0x5b, 0xf1, 0x52, 0x85, 0xec, 0x4b, 0xa0, 0x6b, 0x1f, 0x54, 0x7c, 0x97, 0x12, 0x6c, 0xc5, + 0x83, 0x1d, 0x70, 0x5d, 0xb0, 0x84, 0xbb, 0x44, 0xa0, 0xa2, 0x94, 0x34, 0x36, 0x48, 0xc6, 0x92, + 0x61, 0xe7, 0x4c, 0xd8, 0x01, 0x65, 0x9e, 0xf8, 0x44, 0xa0, 0x92, 0x94, 0x7c, 0xbe, 0x41, 0x62, + 0x27, 0x3e, 0x51, 0xb2, 0x8c, 0x0b, 0x7b, 0xa0, 0xf6, 0xfe, 0xcc, 0x05, 0x2a, 0x4b, 0xb1, 0xfe, + 0xa1, 0x12, 0x0f, 0x25, 0xcd, 0xde, 0x8e, 0xff, 0x3f, 0x08, 0x78, 0x07, 0xdc, 0x08, 0xf0, 0xc2, + 0x09, 0x59, 0xe8, 0x12, 0x54, 0x31, 0xb4, 0x76, 0xd9, 0xde, 0x0a, 0xf0, 0x62, 0x98, 0x9e, 0x61, + 0x0b, 0x54, 0xe3, 0x39, 0x27, 0x62, 0xce, 0x7c, 0xcf, 0xc1, 0xe8, 0xba, 0x84, 0xc1, 0x32, 0x74, + 0xb0, 0x4a, 0x98, 0xa0, 0xad, 0x35, 0x42, 0x17, 0x3e, 0x02, 0xa5, 0x80, 0x79, 0x04, 0xdd, 0x30, + 0xb4, 0xf6, 0xcd, 0x7d, 0x63, 0xd3, 0xbc, 0x59, 0x28, 0x48, 0x28, 0x12, 0x71, 0xcc, 0x3c, 0x62, + 0x4b, 0x36, 0xdc, 0x03, 0x20, 0x2d, 0xca, 0x23, 0xb1, 0x43, 0x3d, 0x04, 0x96, 0x55, 0xf5, 0x49, + 0x7c, 0xe4, 0xc1, 0x7b, 0xe0, 0x93, 0x14, 0x15, 0xf4, 0x39, 0x71, 0x22, 0x4e, 0xd3, 0x49, 0x57, + 0x25, 0xa5, 0x16, 0xe0, 0xc5, 0x98, 0x3e, 0x27, 0x23, 0x19, 0x84, 0xdf, 0x82, 0x2d, 0xe1, 0x63, + 0x31, 0xa7, 0xe1, 0x0c, 0x6d, 0x1b, 0x5a, 0xbb, 0xba, 0xff, 0xc5, 0xa6, 0x57, 0xa1, 0x28, 0xd9, + 0x15, 0xb1, 0x97, 0x92, 0xaf, 0x4b, 0x2f, 0x7f, 0x6d, 0x15, 0xee, 0xbe, 0x2d, 0x81, 0x9b, 0xab, + 0x14, 0xf8, 0x08, 0xec, 0x72, 0x12, 0x31, 0x1e, 0x13, 0xcf, 0xe1, 0x2c, 0x09, 0x3d, 0xe1, 0x9c, + 0xd1, 0xd0, 0x63, 0x67, 0x48, 0x33, 0xb4, 0x76, 0xd1, 0xde, 0xc9, 0x51, 0x5b, 0x82, 0xdf, 0x4b, + 0x0c, 0x3e, 0x05, 0x9f, 0x05, 0x34, 0x74, 0x96, 0xca, 0x88, 0xf0, 0x5c, 0x76, 0xcd, 0xd0, 0xda, + 0xdb, 0xdd, 0xce, 0xeb, 0x77, 0xad, 0xc2, 0xdb, 0x77, 0xad, 0x7b, 0x33, 0x1a, 0xcf, 0x93, 0x89, + 0xe9, 0xb2, 0x40, 0xdd, 0x6d, 0xf5, 0xf5, 0x95, 0xf0, 0x4e, 0xad, 0xf8, 0xc7, 0x88, 0x08, 0xb3, + 0x4f, 0xdc, 0xdf, 0xff, 0xfd, 0xe3, 0xbe, 0x66, 0xef, 0x04, 0x34, 0xb4, 0x55, 0xca, 0x11, 0xe1, + 0xca, 0xcb, 0x05, 0x8d, 0xac, 0x41, 0x27, 0xa0, 0x42, 0x38, 0x4f, 0x31, 0xf5, 0x9d, 0x7c, 0xc9, + 0x50, 0x51, 0x8e, 0xa2, 0x61, 0x66, 0x5b, 0x66, 0xe6, 0x5b, 0x66, 0xf6, 0x15, 0xa1, 0x5b, 0x4b, + 0x0b, 0x79, 0xf9, 0x77, 0x4b, 0xcb, 0x2c, 0x76, 0xb3, 0x54, 0xc7, 0x54, 0x88, 0xc7, 0x98, 0xfa, + 0x39, 0x0d, 0x06, 0x40, 0xcf, 0x4d, 0xb0, 0x4f, 0x5d, 0xca, 0x92, 0x75, 0xa7, 0xd2, 0x47, 0x3a, + 0xdd, 0x51, 0x4e, 0x79, 0xba, 0x15, 0x3b, 0x17, 0xdc, 0x96, 0xaf, 0xc6, 0x99, 0x72, 0xec, 0xa6, + 0x11, 0xd9, 0x1b, 0x2a, 0x5f, 0x7d, 0x76, 0x75, 0x99, 0xef, 0x50, 0xa5, 0x4b, 0xfb, 0x83, 0x01, + 0x40, 0xeb, 0x26, 0x79, 0x31, 0x72, 0x39, 0xae, 0xe8, 0xb4, 0xbb, 0xea, 0x94, 0xa7, 0xbc, 0xff, + 0x93, 0x06, 0x6a, 0x2b, 0xf7, 0x1f, 0x7e, 0x03, 0x9a, 0xbd, 0x27, 0xc3, 0xf1, 0x60, 0x38, 0x3e, + 0x19, 0x3b, 0xc7, 0x4f, 0xfa, 0x03, 0xe7, 0x64, 0x38, 0x1e, 0x0d, 0x7a, 0x47, 0x87, 0x47, 0x83, + 0xfe, 0xad, 0x42, 0x73, 0xef, 0xc5, 0x2b, 0x03, 0xad, 0x48, 0x4e, 0x42, 0x11, 0x11, 0x97, 0x4e, + 0x29, 0xf1, 0xa0, 0x09, 0x6e, 0xaf, 0xa9, 0x0f, 0xc6, 0x07, 0xa3, 0x5b, 0x5a, 0xf3, 0xd3, 0x17, + 0xaf, 0x8c, 0xfa, 0x8a, 0x2c, 0x05, 0x9a, 0xa5, 0x9f, 0x7f, 0xd3, 0x0b, 0xdd, 0xc7, 0xaf, 0xcf, + 0x75, 0xed, 0xcd, 0xb9, 0xae, 0xfd, 0x73, 0xae, 0x6b, 0xbf, 0x5c, 0xe8, 0x85, 0x37, 0x17, 0x7a, + 0xe1, 0xaf, 0x0b, 0xbd, 0xf0, 0xc3, 0x83, 0xf7, 0x9a, 0x1c, 0x64, 0x9b, 0x33, 0x24, 0xf1, 0x19, + 0xe3, 0xa7, 0x56, 0xfe, 0xfb, 0xbf, 0xc8, 0xff, 0x01, 0x64, 0xcb, 0x93, 0x8a, 0x7c, 0xc9, 0x9d, + 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x6d, 0x9c, 0xf6, 0x5c, 0x71, 0x06, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -499,7 +495,7 @@ func (m *SlashingParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintParams(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x42 + dAtA[i] = 0x32 { size := m.SlashFractionMiss.Size() i -= size @@ -509,26 +505,6 @@ func (m *SlashingParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintParams(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x3a - { - size := m.SlashFractionMaliciousReport.Size() - i -= size - if _, err := m.SlashFractionMaliciousReport.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintParams(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x32 - { - size := m.SlashFractionMissReport.Size() - i -= size - if _, err := m.SlashFractionMissReport.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintParams(dAtA, i, uint64(size)) - } - i-- dAtA[i] = 0x2a n2, err2 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.OracleMaliciousJailDuration, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.OracleMaliciousJailDuration):]) if err2 != nil { @@ -651,10 +627,6 @@ func (m *SlashingParams) Size() (n int) { n += 1 + l + sovParams(uint64(l)) l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.OracleMaliciousJailDuration) n += 1 + l + sovParams(uint64(l)) - l = m.SlashFractionMissReport.Size() - n += 1 + l + sovParams(uint64(l)) - l = m.SlashFractionMaliciousReport.Size() - n += 1 + l + sovParams(uint64(l)) l = m.SlashFractionMiss.Size() n += 1 + l + sovParams(uint64(l)) l = m.SlashFractionMalicious.Size() @@ -1186,72 +1158,6 @@ func (m *SlashingParams) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SlashFractionMissReport", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowParams - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthParams - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthParams - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.SlashFractionMissReport.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SlashFractionMaliciousReport", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowParams - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthParams - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthParams - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.SlashFractionMaliciousReport.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 7: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field SlashFractionMiss", wireType) } @@ -1284,7 +1190,7 @@ func (m *SlashingParams) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 8: + case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field SlashFractionMalicious", wireType) } From d271af8d16f0796b744b8372d851a3a029c3da48 Mon Sep 17 00:00:00 2001 From: X Date: Wed, 30 Oct 2024 16:01:29 +0800 Subject: [PATCH 03/22] Update x/oracle/types/events.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- x/oracle/types/events.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/oracle/types/events.go b/x/oracle/types/events.go index 6d7cb8019..d140aa712 100644 --- a/x/oracle/types/events.go +++ b/x/oracle/types/events.go @@ -30,5 +30,5 @@ const ( AttributeValueNativeTokenDeposit = "deposit" AttributeValueNativeTokenWithdraw = "withdraw" AttributeValueMissingReportPrice = "missing_report_price" - AttributeValueMaliciousReportPrice = "missing_report_price" + AttributeValueMaliciousReportPrice = "malicious_report_price" ) From e7c5a8ddd285e6b785477f6281e9a6c194281464 Mon Sep 17 00:00:00 2001 From: X Date: Wed, 30 Oct 2024 16:06:16 +0800 Subject: [PATCH 04/22] Update x/oracle/types/genesis_test.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- x/oracle/types/genesis_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/oracle/types/genesis_test.go b/x/oracle/types/genesis_test.go index bb9446ea3..bf73106b9 100644 --- a/x/oracle/types/genesis_test.go +++ b/x/oracle/types/genesis_test.go @@ -2,7 +2,7 @@ package types_test import ( "testing" - time "time" + "time" sdkmath "cosmossdk.io/math" "github.com/ExocoreNetwork/exocore/x/oracle/types" From bfa4d7bc2116755225421df3885803476018f6d1 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Fri, 1 Nov 2024 10:17:04 +0800 Subject: [PATCH 05/22] e2e test network --- testutil/network/delegation_data.go | 0 testutil/network/genesis_data.go | 55 ++++++++ testutil/network/network.go | 52 +++++--- testutil/network/network_test.go | 3 - testutil/network/util.go | 196 +++++++++++++++++++++++++++- x/oracle/keeper/nonce.go | 3 +- 6 files changed, 289 insertions(+), 20 deletions(-) create mode 100644 testutil/network/delegation_data.go create mode 100644 testutil/network/genesis_data.go diff --git a/testutil/network/delegation_data.go b/testutil/network/delegation_data.go new file mode 100644 index 000000000..e69de29bb diff --git a/testutil/network/genesis_data.go b/testutil/network/genesis_data.go new file mode 100644 index 000000000..4dd0e6da8 --- /dev/null +++ b/testutil/network/genesis_data.go @@ -0,0 +1,55 @@ +package network + +import ( + sdkmath "cosmossdk.io/math" + assetstypes "github.com/ExocoreNetwork/exocore/x/assets/types" + delegationtypes "github.com/ExocoreNetwork/exocore/x/delegation/types" + dogfoodtypes "github.com/ExocoreNetwork/exocore/x/dogfood/types" + operatortypes "github.com/ExocoreNetwork/exocore/x/operator/types" +) + +var ( + DefaultGenStateAssets = assetstypes.GenesisState{ + Params: assetstypes.Params{ + ExocoreLzAppAddress: "0x3e108c058e8066da635321dc3018294ca82ddedf", + ExocoreLzAppEventTopic: assetstypes.DefaultParams().ExocoreLzAppEventTopic, + }, + ClientChains: []assetstypes.ClientChainInfo{ + { + Name: "Example EVM chain", + MetaInfo: "Example EVM chain metaInfo", + LayerZeroChainID: 101, + AddressLength: 20, + }, + }, + Tokens: []assetstypes.StakingAssetInfo{ + { + // for test this token will be registered on ETH in oracle module + AssetBasicInfo: assetstypes.AssetInfo{ + Name: "Tether USD", + MetaInfo: "Tether USD token", + Address: "0xdac17f958d2ee523a2206206994597c13d831ec7", + LayerZeroChainID: 101, + }, + StakingTotalAmount: sdkmath.NewInt(5000), + }, + { + AssetBasicInfo: assetstypes.AssetInfo{ + Name: "NST ETH", + MetaInfo: "native restaking ETH", + Address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + LayerZeroChainID: 101, + }, + StakingTotalAmount: sdkmath.NewInt(5000), + }, + }, + } + + // DefaultGenStateOperator = operatortypes.GenesisState{} + DefaultGenStateOperator = *operatortypes.DefaultGenesis() + + // DefaultGenStateDelegation = delegationtypes.GenesisState{} + DefaultGenStateDelegation = *delegationtypes.DefaultGenesis() + + DefaultGenStateDogfood = *dogfoodtypes.DefaultGenesis() +) diff --git a/testutil/network/network.go b/testutil/network/network.go index 327e90c55..9689b9390 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -10,6 +10,7 @@ import ( "net/url" "os" "path/filepath" + "sort" "strings" "sync" "testing" @@ -52,6 +53,8 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/evmos/evmos/v16/crypto/hd" + // ekeyring "github.com/evmos/evmos/v16/crypto/keyring" + "github.com/evmos/evmos/v16/encoding" "github.com/evmos/evmos/v16/server/config" evmostypes "github.com/evmos/evmos/v16/types" @@ -77,9 +80,9 @@ type Config struct { AppConstructor AppConstructor // the ABCI application constructor GenesisState simapp.GenesisState // custom gensis state to provide TimeoutCommit time.Duration // the consensus commitment timeout - AccountTokens math.Int // the amount of unique validator tokens (e.g. 1000node0) - StakingTokens math.Int // the amount of tokens each validator has available to stake - BondedTokens math.Int // the amount of tokens each validator stakes + AccountTokens math.Int // the amount of system tokens(e.g. 1000hua) + StakingTokens math.Int // the amount of tokens each validator for every supported asset has available to stake + BondedTokens math.Int // the amount of tokens each validator stakes for every supporte asset NumValidators int // the total number of validators to create and bond ChainID string // the network chain-id BondDenom string // the staking bond denomination @@ -113,14 +116,15 @@ func DefaultConfig() Config { NumValidators: 4, BondDenom: "hua", MinGasPrices: fmt.Sprintf("0.000006%s", evmostypes.AttoEvmos), - AccountTokens: sdk.TokensFromConsensusPower(1000000000000000000, evmostypes.PowerReduction), - StakingTokens: sdk.TokensFromConsensusPower(500000000000000000, evmostypes.PowerReduction), - BondedTokens: sdk.TokensFromConsensusPower(100000000000000000, evmostypes.PowerReduction), + AccountTokens: sdk.TokensFromConsensusPower(1000, evmostypes.PowerReduction), + StakingTokens: sdk.TokensFromConsensusPower(500, evmostypes.PowerReduction), + BondedTokens: sdk.TokensFromConsensusPower(200, evmostypes.PowerReduction), PruningStrategy: pruningtypes.PruningOptionNothing, CleanupDir: true, SigningAlgo: string(hd.EthSecp256k1Type), KeyringOptions: []keyring.Option{hd.EthSecp256k1Option()}, - PrintMnemonic: false, + // KeyringOptions: []keyring.Option{ekeyring.Option()}, + PrintMnemonic: false, } } @@ -235,6 +239,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { monikers := make([]string, cfg.NumValidators) nodeIDs := make([]string, cfg.NumValidators) valPubKeys := make([]cryptotypes.PubKey, cfg.NumValidators) + addressesIPs := make([]string, cfg.NumValidators) var ( genAccounts []authtypes.GenesisAccount @@ -334,8 +339,8 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { ctx.Logger = logger nodeDirName := fmt.Sprintf("node%d", i) - nodeDir := filepath.Join(network.BaseDir, nodeDirName, "evmosd") - clientDir := filepath.Join(network.BaseDir, nodeDirName, "evmoscli") + nodeDir := filepath.Join(network.BaseDir, nodeDirName, "exocored") + clientDir := filepath.Join(network.BaseDir, nodeDirName, "exocorecli") gentxsDir := filepath.Join(network.BaseDir, "gentxs") err := os.MkdirAll(filepath.Join(nodeDir, "config"), 0o750) @@ -366,11 +371,18 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { tmCfg.P2P.AddrBookStrict = false tmCfg.P2P.AllowDuplicateIP = true + // initialize nodekey, consensus_priv_key under nodeDir nodeID, pubKey, err := genutil.InitializeNodeValidatorFiles(tmCfg) if err != nil { return nil, err } + + p2pURL, err := url.Parse(p2pAddr) + if err != nil { + return nil, err + } nodeIDs[i] = nodeID + addressesIPs[i] = fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port()) valPubKeys[i] = pubKey kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.Codec, cfg.KeyringOptions...) @@ -401,7 +413,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { return nil, err } - // save private key seed words + // save private key seed words of account used as validator err = WriteFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz) if err != nil { return nil, err @@ -436,14 +448,15 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { return nil, err } - p2pURL, err := url.Parse(p2pAddr) - if err != nil { - return nil, err - } + // p2pURL, err := url.Parse(p2pAddr) + // if err != nil { + // return nil, err + // } memo := fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port()) fee := sdk.NewCoins(sdk.NewCoin(cfg.BondDenom, sdk.NewInt(0))) txBuilder := cfg.TxConfig.NewTxBuilder() + err = txBuilder.SetMsgs(createValMsg) if err != nil { return nil, err @@ -472,7 +485,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { return nil, err } - customAppTemplate, _ := config.AppConfig(evmostypes.AttoEvmos) + customAppTemplate, _ := config.AppConfig("hua") srvconfig.SetConfigTemplate(customAppTemplate) srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appCfg) @@ -510,6 +523,15 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { } } + sort.Strings(addressesIPs) + // set persistentPeers for tendermintConfig and write into configFile for each valdiator + for i := 0; i < cfg.NumValidators; i++ { + cfgTmp := network.Validators[i].Ctx.Config + cfgTmp.P2P.PersistentPeers = strings.Join(append(addressesIPs[0:i], addressesIPs[i+1:]...), ",") + tmcfg.WriteConfigFile(filepath.Join(cfgTmp.RootDir, "config", "config.toml"), cfgTmp) + } + + // cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) err := initGenFiles(cfg, genAccounts, genBalances, genFiles) if err != nil { return nil, err diff --git a/testutil/network/network_test.go b/testutil/network/network_test.go index 00cb4d89a..c9a7db752 100644 --- a/testutil/network/network_test.go +++ b/testutil/network/network_test.go @@ -1,6 +1,3 @@ -//go:build norace -// +build norace - package network_test import ( diff --git a/testutil/network/util.go b/testutil/network/util.go index d9f868d2e..47761198b 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -6,6 +6,7 @@ import ( "path/filepath" "time" + sdkmath "cosmossdk.io/math" tmos "github.com/cometbft/cometbft/libs/os" "github.com/cometbft/cometbft/node" "github.com/cometbft/cometbft/p2p" @@ -14,8 +15,15 @@ import ( "github.com/cometbft/cometbft/rpc/client/local" "github.com/cometbft/cometbft/types" tmtime "github.com/cometbft/cometbft/types/time" + sdk "github.com/cosmos/cosmos-sdk/types" + sdktypes "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/ethclient" + assetstypes "github.com/ExocoreNetwork/exocore/x/assets/types" + delegationtypes "github.com/ExocoreNetwork/exocore/x/delegation/types" + dogfoodtypes "github.com/ExocoreNetwork/exocore/x/dogfood/types" + operatortypes "github.com/ExocoreNetwork/exocore/x/operator/types" + oracletypes "github.com/ExocoreNetwork/exocore/x/oracle/types" "github.com/cosmos/cosmos-sdk/server/api" servergrpc "github.com/cosmos/cosmos-sdk/server/grpc" srvtypes "github.com/cosmos/cosmos-sdk/server/types" @@ -26,8 +34,11 @@ import ( genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/evmos/evmos/v16/server" + evmostypes "github.com/evmos/evmos/v16/types" evmtypes "github.com/evmos/evmos/v16/x/evm/types" ) @@ -145,13 +156,14 @@ func startInProcess(cfg Config, val *Validator) error { return nil } +// collectGenFiles doesn't actually actually collect gentx and fill into genesis since we use dogfood to replace staking module. Modify genesisfile to fill validator related information in genesisfile func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error { genTime := tmtime.Now() for i := 0; i < cfg.NumValidators; i++ { tmCfg := vals[i].Ctx.Config - nodeDir := filepath.Join(outputDir, vals[i].Moniker, "evmosd") + nodeDir := filepath.Join(outputDir, vals[i].Moniker, "exocored") gentxsDir := filepath.Join(outputDir, "gentxs") tmCfg.Moniker = vals[i].Moniker @@ -216,6 +228,22 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance evmGenState.Params.EvmDenom = cfg.BondDenom cfg.GenesisState[evmtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&evmGenState) + // set validators related modules: assets, operator, dogfood + var assetsGenState assetstypes.GenesisState + cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[assetstypes.ModuleName], &assetsGenState) + NewGenStateAssets(&assetsGenState) + cfg.GenesisState[assetstypes.ModuleName] = cfg.Codec.MustMarshalJSON(&assetsGenState) + + var operatorGenState operatortypes.GenesisState + cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[assetstypes.ModuleName], &operatorGenState) + + var dogfoodGenState dogfoodtypes.GenesisState + cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[assetstypes.ModuleName], &dogfoodGenState) + + // set oracle genesis statse + var oracleGenState oracletypes.GenesisState + cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[assetstypes.ModuleName], &oracleGenState) + appGenStateJSON, err := json.MarshalIndent(cfg.GenesisState, "", " ") if err != nil { return err @@ -247,3 +275,169 @@ func WriteFile(name string, dir string, contents []byte) error { return tmos.WriteFile(file, contents, 0o644) } + +// set deposits and operator_assets for assets genesisState +func NewGenStateAssets(operatorAccAddresses []sdktypes.AccAddress, depositAmount, stakingAmount sdkmath.Int) (assetstypes.GenesisState, error) { + if stakingAmount.GT(depositAmount) { + return DefaultGenStateAssets, fmt.Errorf("stakingAmount %v should be less than depositAmount %v", stakingAmount, depositAmount) + } + n := len(operatorAccAddresses) + nInt := sdkmath.NewInt(int64(n)) + totalDepositAmount := depositAmount.Mul(nInt) + depositsByStakers := make([]assetstypes.DepositsByStaker, 0, len(DefaultGenStateAssets.Tokens)*n) + operatorsAssets := make([]assetstypes.AssetsByOperator, 0, n) + nAssets := len(DefaultGenStateAssets.Tokens) + for i := 0; i < nAssets; i++ { + DefaultGenStateAssets.Tokens[i].StakingTotalAmount = totalDepositAmount + } + for _, operatorAccAddress := range operatorAccAddresses { + // use the same address []byte for operator(exo..) and staker(0x...), both derived from the same pubkey and since evmos use ethsecp256k1, this address is generated from keccak-256(.) instead of ripemd160(sha256(.)) + stakerAddrStr := hexutil.Encode(operatorAccAddress) + depositsByAssets := make([]assetstypes.DepositByAsset, 0, nAssets) + assetsStates := make([]assetstypes.AssetByID, 0, nAssets) + stakerID := "" + assetID := "" + for _, asset := range DefaultGenStateAssets.Tokens { + stakerID, assetID = assetstypes.GetStakerIDAndAssetIDFromStr(asset.AssetBasicInfo.LayerZeroChainID, stakerAddrStr, asset.AssetBasicInfo.Address) + depositsByAssets = append(depositsByAssets, assetstypes.DepositByAsset{ + AssetID: assetID, + Info: assetstypes.StakerAssetInfo{ + TotalDepositAmount: depositAmount, + WithdrawableAmount: depositAmount.Sub(stakingAmount), + PendingUndelegationAmount: sdkmath.ZeroInt(), + }, + }) + assetsStates = append(assetsStates, assetstypes.AssetByID{ + AssetID: assetID, + Info: assetstypes.OperatorAssetInfo{ + TotalAmount: stakingAmount, + PendingUndelegationAmount: sdkmath.ZeroInt(), + TotalShare: sdkmath.LegacyNewDecFromInt(stakingAmount), + // only take self delegation for genesis state + OperatorShare: sdkmath.LegacyNewDecFromInt(stakingAmount), + }, + }) + } + depositsByStakers = append(depositsByStakers, assetstypes.DepositsByStaker{ + StakerID: stakerID, + Deposits: depositsByAssets, + }) + operatorsAssets = append(operatorsAssets, assetstypes.AssetsByOperator{ + Operator: operatorAccAddress.String(), + AssetsState: assetsStates, + }) + } + + DefaultGenStateAssets.Deposits = depositsByStakers + DefaultGenStateAssets.OperatorAssets = operatorsAssets + + return DefaultGenStateAssets, nil +} + +// stakingAmount, each operator opt in evry AVS with stakingAmount of every assets +// each avs suppport all assets +// each operator opts in every avs +// each operator deposited and self staked all assets with: (depsitAmount, stakingAmount) +// intial price for every asset is 1 USD +func NewGenStateOperator(operatorAccAddresses []sdktypes.AccAddress, consPubKeys []string, commissionRate sdkmath.LegacyDec, chainID string, optedAVSAddresses []string, stakingAmount sdkmath.Int, genStateAssets assetstypes.GenesisState) (operatortypes.GenesisState, error) { + // total stakingAmount one operator holds among all assets + stakingAmount = stakingAmount.Mul(sdkmath.NewInt(int64(len(genStateAssets.Tokens)))) + if len(operatorAccAddresses) != len(consPubKeys) { + return DefaultGenStateOperator, fmt.Errorf("length of operatorAccAddresses %d should be equal to length of consPubKeys %d", len(operatorAccAddresses), len(consPubKeys)) + } + n := len(operatorAccAddresses) + totalStakingAmount := stakingAmount.Mul(sdkmath.NewInt(int64(n))) + for i, operatorAccAddress := range operatorAccAddresses { + // operators + DefaultGenStateOperator.Operators = append(DefaultGenStateOperator.Operators, operatortypes.OperatorDetail{ + OperatorAddress: operatorAccAddress.String(), + OperatorInfo: operatortypes.OperatorInfo{ + EarningsAddr: operatorAccAddress.String(), + OperatorMetaInfo: fmt.Sprintf("operator_%d", i), + Commission: stakingtypes.Commission{ + CommissionRates: stakingtypes.CommissionRates{ + Rate: commissionRate, + MaxRate: commissionRate.Mul(sdkmath.LegacyNewDec(2)), + MaxChangeRate: sdkmath.LegacyNewDecWithPrec(1, 1), + }, + }, + }, + }) + // operator_records + DefaultGenStateOperator.OperatorRecords = append(DefaultGenStateOperator.OperatorRecords, operatortypes.OperatorConsKeyRecord{ + OperatorAddress: operatorAccAddress.String(), + Chains: []operatortypes.ChainDetails{ + { + ChainID: chainID, + ConsensusKey: consPubKeys[i], + }, + }, + }) + // OptStates + for _, AVSAddress := range optedAVSAddresses { + DefaultGenStateOperator.OptStates = append(DefaultGenStateOperator.OptStates, operatortypes.OptedState{ + Key: operatorAccAddress.String() + "/" + AVSAddress, + OptInfo: operatortypes.OptedInfo{ + OptedInHeight: 1, + OptedOutHeight: 18446744073709551615, + Jailed: false, + }, + }) + // OperatorUSDValues + // the price unit of assets is 1 not decimal 18 + stakingValue := sdktypes.TokensToConsensusPower(stakingAmount, evmostypes.PowerReduction) + DefaultGenStateOperator.OperatorUSDValues = append(DefaultGenStateOperator.OperatorUSDValues, operatortypes.OperatorUSDValue{ + Key: AVSAddress + "/" + operatorAccAddress.String(), + OptedUSDValue: operatortypes.OperatorOptedUSDValue{ + SelfUSDValue: sdkmath.LegacyNewDec(stakingValue), + TotalUSDValue: sdkmath.LegacyNewDec(stakingValue), + ActiveUSDValue: sdkmath.LegacyNewDec(stakingValue), + }, + }) + } + } + // AVSUSDValues + for _, AVSAddress := range optedAVSAddresses { + DefaultGenStateOperator.AVSUSDValues = append(DefaultGenStateOperator.AVSUSDValues, operatortypes.AVSUSDValue{ + AVSAddr: AVSAddress, + Value: operatortypes.DecValueField{ + // the price unit of assets is 1 not decimal 18 + Amount: sdkmath.LegacyNewDec(sdktypes.TokensToConsensusPower(totalStakingAmount, evmostypes.PowerReduction)), + }, + }) + } + return DefaultGenStateOperator, nil +} + +func NewGenStateDogfood(consPubKeys []string, powers []sdkmath.LegacyDec, stakingAmount sdkmath.Int, genStateAssets assetstypes.GenesisState) (dogfoodtypes.GenesisState, error) { + power := sdktypes.TokensToConsensusPower(stakingAmount.Mul(sdkmath.NewInt(int64(len(genStateAssets.Tokens)))), evmostypes.PowerReduction) + // if len(consPubKeys) != len(powers) { + // return DefaultGenStateDogfood, fmt.Errorf("lenght of consensusKey %d should be equal to length of powers %d", len(consPubKeys), len(powers)) + // } + DefaultGenStateDogfood.Params.EpochIdentifier = "minute" + DefaultGenStateDogfood.Params.EpochsUntilUnbonded = 5 + DefaultGenStateDogfood.Params.MinSelfDelegation = sdkmath.NewInt(100) + assetIDs := make(map[string]bool) + for _, assetID := range DefaultGenStateDogfood.Params.AssetIDs { + assetIDs[assetID] = true + } + for _, asset := range genStateAssets.Tokens { + _, assetID := assetstypes.GetStakerIDAndAssetIDFromStr(asset.AssetBasicInfo.LayerZeroChainID, "", asset.AssetBasicInfo.Address) + if assetIDs[assetID] { + continue + } + DefaultGenStateDogfood.Params.AssetIDs = append(DefaultGenStateDogfood.Params.AssetIDs, assetID) + } + for _, consPubKey := range consPubKeys { + DefaultGenStateDogfood.ValSet = append(DefaultGenStateDogfood.ValSet, dogfoodtypes.GenesisValidator{ + PublicKey: consPubKey, + Power: power, + }) + } + DefaultGenStateDogfood.LastTotalPower = sdkmath.NewInt(power * int64(len(consPubKeys))) + return DefaultGenStateDogfood, nil +} + +func NewGenStateDelegation(operatorAccAddresses []sdk.AccAddress, genStateAssets assetstypes.GenesisState) (delegationtypes.GenesisState, error) { + return DefaultGenStateDelegation, nil +} diff --git a/x/oracle/keeper/nonce.go b/x/oracle/keeper/nonce.go index dd2bc16be..b4a5e6fed 100644 --- a/x/oracle/keeper/nonce.go +++ b/x/oracle/keeper/nonce.go @@ -2,6 +2,7 @@ package keeper import ( "errors" + "fmt" "github.com/ExocoreNetwork/exocore/x/oracle/keeper/common" "github.com/ExocoreNetwork/exocore/x/oracle/types" @@ -127,7 +128,7 @@ func (k Keeper) CheckAndIncreaseNonce(ctx sdk.Context, validator string, feederI } return 0, errors.New("feeder not found") } - return 0, errors.New("validator not found") + return 0, fmt.Errorf("validator for the consKey which signed the create-price tx is not included in active validator set, signer consAddr:%s", validator) } // internal usage for avoiding duplicated 'NewStore' From f0b82ebeee072d005401c9bc63a2e09ad79b12b9 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Mon, 4 Nov 2024 10:05:41 +0800 Subject: [PATCH 06/22] fix multiple-validators network fail --- precompiles/assets/assets_test.go | 2 - testutil/network/delegation_data.go | 0 testutil/network/genesis_data.go | 26 +++- testutil/network/network.go | 112 ++++---------- testutil/network/network_test.go | 6 +- testutil/network/util.go | 140 +++++++++++------- x/oracle/keeper/keeper.go | 13 ++ x/oracle/keeper/keeper_suite_test.go | 29 ++-- x/oracle/keeper/msg_server_create_price.go | 8 +- .../keeper/msg_server_create_price_test.go | 24 +-- x/oracle/keeper/msg_server_update_params.go | 4 +- .../keeper/msg_server_update_params_test.go | 1 + x/oracle/keeper/params.go | 8 +- x/oracle/keeper/prices.go | 14 +- x/oracle/keeper/single.go | 82 +++++----- x/oracle/module.go | 18 +-- 16 files changed, 248 insertions(+), 239 deletions(-) delete mode 100644 testutil/network/delegation_data.go diff --git a/precompiles/assets/assets_test.go b/precompiles/assets/assets_test.go index e42083492..29af74c51 100644 --- a/precompiles/assets/assets_test.go +++ b/precompiles/assets/assets_test.go @@ -1,7 +1,6 @@ package assets_test import ( - "fmt" "math/big" "strings" @@ -316,7 +315,6 @@ func (s *AssetsPrecompileSuite) TestRunWithdrawPrincipal() { OpAmount: depositAmount, } err := s.App.AssetsKeeper.PerformDepositOrWithdraw(s.Ctx, params) - fmt.Println("Debug---", assetAddress, len(assetAddress)) s.Require().NoError(err) } diff --git a/testutil/network/delegation_data.go b/testutil/network/delegation_data.go deleted file mode 100644 index e69de29bb..000000000 diff --git a/testutil/network/genesis_data.go b/testutil/network/genesis_data.go index 4dd0e6da8..108d7d2aa 100644 --- a/testutil/network/genesis_data.go +++ b/testutil/network/genesis_data.go @@ -6,9 +6,13 @@ import ( delegationtypes "github.com/ExocoreNetwork/exocore/x/delegation/types" dogfoodtypes "github.com/ExocoreNetwork/exocore/x/dogfood/types" operatortypes "github.com/ExocoreNetwork/exocore/x/operator/types" + oracletypes "github.com/ExocoreNetwork/exocore/x/oracle/types" ) var ( + // DefaultGenStateAssets only includes two assets, one for ETH and the other for NST ETH + // For the contract address of asset-ETH we filled with the address of USDT, that's ok for test + // we bond both tokens to the price of ETH in oracle module DefaultGenStateAssets = assetstypes.GenesisState{ Params: assetstypes.Params{ ExocoreLzAppAddress: "0x3e108c058e8066da635321dc3018294ca82ddedf", @@ -26,8 +30,9 @@ var ( { // for test this token will be registered on ETH in oracle module AssetBasicInfo: assetstypes.AssetInfo{ - Name: "Tether USD", - MetaInfo: "Tether USD token", + Name: "ETH", + MetaInfo: "Ethereum native token", + // the address is of USDT_Etheruem, but that's ok Address: "0xdac17f958d2ee523a2206206994597c13d831ec7", LayerZeroChainID: 101, }, @@ -45,11 +50,20 @@ var ( }, } - // DefaultGenStateOperator = operatortypes.GenesisState{} - DefaultGenStateOperator = *operatortypes.DefaultGenesis() + DefaultGenStateOperator = operatortypes.GenesisState{} + // DefaultGenStateOperator = *operatortypes.DefaultGenesis() - // DefaultGenStateDelegation = delegationtypes.GenesisState{} - DefaultGenStateDelegation = *delegationtypes.DefaultGenesis() + DefaultGenStateDelegation = delegationtypes.GenesisState{} + // DefaultGenStateDelegation = *delegationtypes.DefaultGenesis() DefaultGenStateDogfood = *dogfoodtypes.DefaultGenesis() + + DefaultGenStateOracle = *oracletypes.DefaultGenesis() ) + +func init() { + // bond assetsIDs of ETH, NSTETH to ETH price + DefaultGenStateOracle.Params.Tokens[1].AssetID = "0xdac17f958d2ee523a2206206994597c13d831ec7_0x65,0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_0x65" + // set ETH tokenfeeder's 'StartBaseBlock' to 10 + DefaultGenStateOracle.Params.TokenFeeders[1].StartBaseBlock = 10 +} diff --git a/testutil/network/network.go b/testutil/network/network.go index 9689b9390..a6d5d7429 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -17,6 +17,7 @@ import ( "time" "cosmossdk.io/math" + sdkmath "cosmossdk.io/math" dbm "github.com/cometbft/cometbft-db" tmcfg "github.com/cometbft/cometbft/config" tmflags "github.com/cometbft/cometbft/libs/cli/flags" @@ -34,7 +35,6 @@ import ( "github.com/ExocoreNetwork/exocore/app" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -50,7 +50,6 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/genutil" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/evmos/evmos/v16/crypto/hd" // ekeyring "github.com/evmos/evmos/v16/crypto/keyring" @@ -81,21 +80,21 @@ type Config struct { GenesisState simapp.GenesisState // custom gensis state to provide TimeoutCommit time.Duration // the consensus commitment timeout AccountTokens math.Int // the amount of system tokens(e.g. 1000hua) - StakingTokens math.Int // the amount of tokens each validator for every supported asset has available to stake - BondedTokens math.Int // the amount of tokens each validator stakes for every supporte asset - NumValidators int // the total number of validators to create and bond - ChainID string // the network chain-id - BondDenom string // the staking bond denomination - MinGasPrices string // the minimum gas prices each validator will accept - PruningStrategy string // the pruning strategy each validator will have - SigningAlgo string // signing algorithm for keys - RPCAddress string // RPC listen address (including port) - JSONRPCAddress string // JSON-RPC listen address (including port) - APIAddress string // REST API listen address (including port) - GRPCAddress string // GRPC server listen address (including port) - EnableTMLogging bool // enable Tendermint logging to STDOUT - CleanupDir bool // remove base temporary directory during cleanup - PrintMnemonic bool // print the mnemonic of first validator as log output for testing + DepositedTokens math.Int + StakingTokens math.Int // the amount of tokens each validator stakes for every supporte asset + NumValidators int // the total number of validators to create and bond + ChainID string // the network chain-id + BondDenom string // the staking bond denomination + MinGasPrices string // the minimum gas prices each validator will accept + PruningStrategy string // the pruning strategy each validator will have + SigningAlgo string // signing algorithm for keys + RPCAddress string // RPC listen address (including port) + JSONRPCAddress string // JSON-RPC listen address (including port) + APIAddress string // REST API listen address (including port) + GRPCAddress string // GRPC server listen address (including port) + EnableTMLogging bool // enable Tendermint logging to STDOUT + CleanupDir bool // remove base temporary directory during cleanup + PrintMnemonic bool // print the mnemonic of first validator as log output for testing } // DefaultConfig returns a sane default configuration suitable for nearly all @@ -115,16 +114,15 @@ func DefaultConfig() Config { ChainID: chainID, NumValidators: 4, BondDenom: "hua", - MinGasPrices: fmt.Sprintf("0.000006%s", evmostypes.AttoEvmos), + MinGasPrices: fmt.Sprintf("0.000006%s", "hua"), AccountTokens: sdk.TokensFromConsensusPower(1000, evmostypes.PowerReduction), - StakingTokens: sdk.TokensFromConsensusPower(500, evmostypes.PowerReduction), - BondedTokens: sdk.TokensFromConsensusPower(200, evmostypes.PowerReduction), + DepositedTokens: sdk.TokensFromConsensusPower(500, evmostypes.PowerReduction), + StakingTokens: sdk.TokensFromConsensusPower(200, evmostypes.PowerReduction), PruningStrategy: pruningtypes.PruningOptionNothing, CleanupDir: true, SigningAlgo: string(hd.EthSecp256k1Type), KeyringOptions: []keyring.Option{hd.EthSecp256k1Option()}, - // KeyringOptions: []keyring.Option{ekeyring.Option()}, - PrintMnemonic: false, + PrintMnemonic: false, } } @@ -341,7 +339,6 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { nodeDirName := fmt.Sprintf("node%d", i) nodeDir := filepath.Join(network.BaseDir, nodeDirName, "exocored") clientDir := filepath.Join(network.BaseDir, nodeDirName, "exocorecli") - gentxsDir := filepath.Join(network.BaseDir, "gentxs") err := os.MkdirAll(filepath.Join(nodeDir, "config"), 0o750) if err != nil { @@ -421,7 +418,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { balances := sdk.NewCoins( sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens), - sdk.NewCoin(cfg.BondDenom, cfg.StakingTokens), + sdk.NewCoin(cfg.BondDenom, cfg.DepositedTokens), ) genFiles = append(genFiles, tmCfg.GenesisFile()) @@ -431,60 +428,6 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { CodeHash: common.BytesToHash(evmtypes.EmptyCodeHash).Hex(), }) - commission, err := sdk.NewDecFromStr("0.5") - if err != nil { - return nil, err - } - - createValMsg, err := stakingtypes.NewMsgCreateValidator( - sdk.ValAddress(addr), - valPubKeys[i], - sdk.NewCoin(cfg.BondDenom, cfg.BondedTokens), - stakingtypes.NewDescription(nodeDirName, "", "", "", ""), - stakingtypes.NewCommissionRates(commission, sdk.OneDec(), sdk.OneDec()), - sdk.OneInt(), - ) - if err != nil { - return nil, err - } - - // p2pURL, err := url.Parse(p2pAddr) - // if err != nil { - // return nil, err - // } - - memo := fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port()) - fee := sdk.NewCoins(sdk.NewCoin(cfg.BondDenom, sdk.NewInt(0))) - txBuilder := cfg.TxConfig.NewTxBuilder() - - err = txBuilder.SetMsgs(createValMsg) - if err != nil { - return nil, err - } - txBuilder.SetFeeAmount(fee) // Arbitrary fee - txBuilder.SetGasLimit(1000000) // Need at least 100386 - txBuilder.SetMemo(memo) - - txFactory := tx.Factory{} - txFactory = txFactory. - WithChainID(cfg.ChainID). - WithMemo(memo). - WithKeybase(kb). - WithTxConfig(cfg.TxConfig) - - if err := tx.Sign(txFactory, nodeDirName, txBuilder, true); err != nil { - return nil, err - } - - txBz, err := cfg.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) - if err != nil { - return nil, err - } - - if err := WriteFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz); err != nil { - return nil, err - } - customAppTemplate, _ := config.AppConfig("hua") srvconfig.SetConfigTemplate(customAppTemplate) srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appCfg) @@ -527,16 +470,15 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { // set persistentPeers for tendermintConfig and write into configFile for each valdiator for i := 0; i < cfg.NumValidators; i++ { cfgTmp := network.Validators[i].Ctx.Config - cfgTmp.P2P.PersistentPeers = strings.Join(append(addressesIPs[0:i], addressesIPs[i+1:]...), ",") + IPs := make([]string, 0, cfg.NumValidators-1) + IPs = append(IPs, addressesIPs[0:i]...) + IPs = append(IPs, addressesIPs[i+1:]...) + cfgTmp.P2P.PersistentPeers = strings.Join(IPs, ",") tmcfg.WriteConfigFile(filepath.Join(cfgTmp.RootDir, "config", "config.toml"), cfgTmp) } - // cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) - err := initGenFiles(cfg, genAccounts, genBalances, genFiles) - if err != nil { - return nil, err - } - err = collectGenFiles(cfg, network.Validators, network.BaseDir) + commissionRate, _ := sdkmath.LegacyNewDecFromStr("0.5") + err := initGenFiles(cfg, genAccounts, genBalances, genFiles, network.Validators, commissionRate) if err != nil { return nil, err } diff --git a/testutil/network/network_test.go b/testutil/network/network_test.go index c9a7db752..4836a75b8 100644 --- a/testutil/network/network_test.go +++ b/testutil/network/network_test.go @@ -26,13 +26,15 @@ func (s *IntegrationTestSuite) SetupSuite() { var err error cfg := exocorenetwork.DefaultConfig() cfg.JSONRPCAddress = config.DefaultJSONRPCAddress - cfg.NumValidators = 1 + cfg.NumValidators = 3 + cfg.CleanupDir = false + cfg.EnableTMLogging = true s.network, err = network.New(s.T(), s.T().TempDir(), cfg) s.Require().NoError(err) s.Require().NotNil(s.network) - _, err = s.network.WaitForHeight(2) + _, err = s.network.WaitForHeightWithTimeout(2, 300*time.Second) s.Require().NoError(err) if s.network.Validators[0].JSONRPCClient == nil { diff --git a/testutil/network/util.go b/testutil/network/util.go index 47761198b..8a78658a0 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -14,12 +14,12 @@ import ( "github.com/cometbft/cometbft/proxy" "github.com/cometbft/cometbft/rpc/client/local" "github.com/cometbft/cometbft/types" - tmtime "github.com/cometbft/cometbft/types/time" sdk "github.com/cosmos/cosmos-sdk/types" sdktypes "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/ethclient" assetstypes "github.com/ExocoreNetwork/exocore/x/assets/types" + avstypes "github.com/ExocoreNetwork/exocore/x/avs/types" delegationtypes "github.com/ExocoreNetwork/exocore/x/delegation/types" dogfoodtypes "github.com/ExocoreNetwork/exocore/x/dogfood/types" operatortypes "github.com/ExocoreNetwork/exocore/x/operator/types" @@ -30,12 +30,11 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" - "github.com/cosmos/cosmos-sdk/x/genutil" - genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + cmttime "github.com/cometbft/cometbft/types/time" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/evmos/evmos/v16/server" evmostypes "github.com/evmos/evmos/v16/types" @@ -156,43 +155,7 @@ func startInProcess(cfg Config, val *Validator) error { return nil } -// collectGenFiles doesn't actually actually collect gentx and fill into genesis since we use dogfood to replace staking module. Modify genesisfile to fill validator related information in genesisfile -func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error { - genTime := tmtime.Now() - - for i := 0; i < cfg.NumValidators; i++ { - tmCfg := vals[i].Ctx.Config - - nodeDir := filepath.Join(outputDir, vals[i].Moniker, "exocored") - gentxsDir := filepath.Join(outputDir, "gentxs") - - tmCfg.Moniker = vals[i].Moniker - tmCfg.SetRoot(nodeDir) - - initCfg := genutiltypes.NewInitConfig(cfg.ChainID, gentxsDir, vals[i].NodeID, vals[i].PubKey) - - genFile := tmCfg.GenesisFile() - genDoc, err := types.GenesisDocFromFile(genFile) - if err != nil { - return err - } - - appState, err := genutil.GenAppStateFromConfig(cfg.Codec, cfg.TxConfig, - tmCfg, initCfg, *genDoc, banktypes.GenesisBalancesIterator{}, genutiltypes.DefaultMessageValidator) - if err != nil { - return err - } - - // overwrite each validator's genesis file to have a canonical genesis time - if err := genutil.ExportGenesisFileWithTime(genFile, cfg.ChainID, nil, appState, genTime); err != nil { - return err - } - } - - return nil -} - -func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalances []banktypes.Balance, genFiles []string) error { +func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalances []banktypes.Balance, genFiles []string, validators []*Validator, commissionRate sdkmath.LegacyDec) error { // set the accounts in the genesis state var authGenState authtypes.GenesisState cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[authtypes.ModuleName], &authGenState) @@ -229,20 +192,45 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance cfg.GenesisState[evmtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&evmGenState) // set validators related modules: assets, operator, dogfood - var assetsGenState assetstypes.GenesisState - cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[assetstypes.ModuleName], &assetsGenState) - NewGenStateAssets(&assetsGenState) + operatorAccAddresses := make([]sdk.AccAddress, 0, len(validators)) + consPubKeys := make([]string, 0, len(validators)) + for _, validator := range validators { + operatorAccAddresses = append(operatorAccAddresses, validator.Address) + // the bytes in vmmostype, tmproto, tmcryptointerface are actually the same, we skip the conversion in test scenario + consPubKeys = append(consPubKeys, hexutil.Encode(validator.PubKey.Bytes())) + } + + assetsGenState, err := NewGenStateAssets(operatorAccAddresses, cfg.DepositedTokens, cfg.StakingTokens) + if err != nil { + return err + } cfg.GenesisState[assetstypes.ModuleName] = cfg.Codec.MustMarshalJSON(&assetsGenState) - var operatorGenState operatortypes.GenesisState - cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[assetstypes.ModuleName], &operatorGenState) + avsAddrStr := avstypes.GenerateAVSAddr(avstypes.ChainIDWithoutRevision(cfg.ChainID)) + operatorGenState, err := NewGenStateOperator(operatorAccAddresses, consPubKeys, commissionRate, cfg.ChainID, []string{avsAddrStr}, cfg.StakingTokens, assetsGenState) + if err != nil { + return err + } + cfg.GenesisState[operatortypes.ModuleName] = cfg.Codec.MustMarshalJSON(&operatorGenState) - var dogfoodGenState dogfoodtypes.GenesisState - cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[assetstypes.ModuleName], &dogfoodGenState) + dogfoodGenState, err := NewGenStateDogfood(consPubKeys, cfg.StakingTokens, assetsGenState) + if err != nil { + return err + } + cfg.GenesisState[dogfoodtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&dogfoodGenState) + + delegationGenState, err := NewGenStateDelegation(operatorAccAddresses, cfg.StakingTokens, assetsGenState) + if err != nil { + return err + } + cfg.GenesisState[delegationtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&delegationGenState) // set oracle genesis statse - var oracleGenState oracletypes.GenesisState - cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[assetstypes.ModuleName], &oracleGenState) + oracleGenState, err := NewGenStateOracle() + if err != nil { + return err + } + cfg.GenesisState[oracletypes.ModuleName] = cfg.Codec.MustMarshalJSON(&oracleGenState) appGenStateJSON, err := json.MarshalIndent(cfg.GenesisState, "", " ") if err != nil { @@ -256,7 +244,15 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance } // generate empty genesis files for each validator and save + gTime := cmttime.Now() for i := 0; i < cfg.NumValidators; i++ { + if genDoc.InitialHeight == 0 { + genDoc.InitialHeight = 1 + } + genDoc.GenesisTime = gTime + if err := genDoc.ValidateAndComplete(); err != nil { + return err + } if err := genDoc.SaveAs(genFiles[i]); err != nil { return err } @@ -276,6 +272,8 @@ func WriteFile(name string, dir string, contents []byte) error { return tmos.WriteFile(file, contents, 0o644) } +// The NewGenState.. is mainlly used for validatorset related config + // set deposits and operator_assets for assets genesisState func NewGenStateAssets(operatorAccAddresses []sdktypes.AccAddress, depositAmount, stakingAmount sdkmath.Int) (assetstypes.GenesisState, error) { if stakingAmount.GT(depositAmount) { @@ -338,7 +336,7 @@ func NewGenStateAssets(operatorAccAddresses []sdktypes.AccAddress, depositAmount // each avs suppport all assets // each operator opts in every avs // each operator deposited and self staked all assets with: (depsitAmount, stakingAmount) -// intial price for every asset is 1 USD +// initial price for every asset is 1 USD func NewGenStateOperator(operatorAccAddresses []sdktypes.AccAddress, consPubKeys []string, commissionRate sdkmath.LegacyDec, chainID string, optedAVSAddresses []string, stakingAmount sdkmath.Int, genStateAssets assetstypes.GenesisState) (operatortypes.GenesisState, error) { // total stakingAmount one operator holds among all assets stakingAmount = stakingAmount.Mul(sdkmath.NewInt(int64(len(genStateAssets.Tokens)))) @@ -368,7 +366,7 @@ func NewGenStateOperator(operatorAccAddresses []sdktypes.AccAddress, consPubKeys OperatorAddress: operatorAccAddress.String(), Chains: []operatortypes.ChainDetails{ { - ChainID: chainID, + ChainID: avstypes.ChainIDWithoutRevision(chainID), ConsensusKey: consPubKeys[i], }, }, @@ -409,11 +407,11 @@ func NewGenStateOperator(operatorAccAddresses []sdktypes.AccAddress, consPubKeys return DefaultGenStateOperator, nil } -func NewGenStateDogfood(consPubKeys []string, powers []sdkmath.LegacyDec, stakingAmount sdkmath.Int, genStateAssets assetstypes.GenesisState) (dogfoodtypes.GenesisState, error) { +// NewGenStateDogfood generates dogfood genesis state from default +// stakingAmount is the amount each operator have for every single asset defined in assets module, so for a single operator the total stakingAmount they have is stakingAmount*count(assets) +// assets genesis state is required as input argument to provide assets information. It should be called with NewGenStateAssets to update default assets genesis state for test +func NewGenStateDogfood(consPubKeys []string, stakingAmount sdkmath.Int, genStateAssets assetstypes.GenesisState) (dogfoodtypes.GenesisState, error) { power := sdktypes.TokensToConsensusPower(stakingAmount.Mul(sdkmath.NewInt(int64(len(genStateAssets.Tokens)))), evmostypes.PowerReduction) - // if len(consPubKeys) != len(powers) { - // return DefaultGenStateDogfood, fmt.Errorf("lenght of consensusKey %d should be equal to length of powers %d", len(consPubKeys), len(powers)) - // } DefaultGenStateDogfood.Params.EpochIdentifier = "minute" DefaultGenStateDogfood.Params.EpochsUntilUnbonded = 5 DefaultGenStateDogfood.Params.MinSelfDelegation = sdkmath.NewInt(100) @@ -438,6 +436,36 @@ func NewGenStateDogfood(consPubKeys []string, powers []sdkmath.LegacyDec, stakin return DefaultGenStateDogfood, nil } -func NewGenStateDelegation(operatorAccAddresses []sdk.AccAddress, genStateAssets assetstypes.GenesisState) (delegationtypes.GenesisState, error) { +func NewGenStateDelegation(operatorAccAddresses []sdk.AccAddress, stakingAmount sdkmath.Int, genStateAssets assetstypes.GenesisState) (delegationtypes.GenesisState, error) { + for _, operator := range operatorAccAddresses { + stakerIDsLinked := make(map[string]bool) + for _, asset := range genStateAssets.Tokens { + stakerID, assetID := assetstypes.GetStakerIDAndAssetIDFromStr(asset.AssetBasicInfo.LayerZeroChainID, hexutil.Encode(operator), asset.AssetBasicInfo.Address) + if !stakerIDsLinked[stakerID] { + DefaultGenStateDelegation.Associations = append(DefaultGenStateDelegation.Associations, delegationtypes.StakerToOperator{ + StakerID: stakerID, + Operator: operator.String(), + }) + stakerIDsLinked[stakerID] = true + } + DefaultGenStateDelegation.DelegationStates = append(DefaultGenStateDelegation.DelegationStates, delegationtypes.DelegationStates{ + Key: stakerID + "/" + assetID + "/" + operator.String(), + States: delegationtypes.DelegationAmounts{ + UndelegatableShare: sdkmath.LegacyNewDecFromInt(stakingAmount), + WaitUndelegationAmount: sdkmath.ZeroInt(), + }, + }) + DefaultGenStateDelegation.StakersByOperator = append(DefaultGenStateDelegation.StakersByOperator, delegationtypes.StakersByOperator{ + Key: operator.String() + "/" + assetID, + Stakers: []string{ + stakerID, + }, + }) + } + } return DefaultGenStateDelegation, nil } + +func NewGenStateOracle() (oracletypes.GenesisState, error) { + return DefaultGenStateOracle, nil +} diff --git a/x/oracle/keeper/keeper.go b/x/oracle/keeper/keeper.go index 8ec37b5f9..fa8fc033d 100644 --- a/x/oracle/keeper/keeper.go +++ b/x/oracle/keeper/keeper.go @@ -11,11 +11,20 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + "github.com/ExocoreNetwork/exocore/x/oracle/keeper/aggregator" + "github.com/ExocoreNetwork/exocore/x/oracle/keeper/cache" "github.com/ExocoreNetwork/exocore/x/oracle/keeper/common" "github.com/ExocoreNetwork/exocore/x/oracle/types" ) type ( + memoryStore struct { + cs *cache.Cache + agc *aggregator.AggregatorContext + agcCheckTx *aggregator.AggregatorContext + updatedFeederIDs []string + } + Keeper struct { cdc codec.BinaryCodec storeKey storetypes.StoreKey @@ -25,6 +34,9 @@ type ( common.KeeperDogfood delegationKeeper types.DelegationKeeper assetsKeeper types.AssetsKeeper + + // wrap all four memory cache into one pointer to track them among cpoies of Keeper (msgServer, module) + memStore *memoryStore } ) @@ -58,6 +70,7 @@ func NewKeeper( delegationKeeper: delegationKeeper, assetsKeeper: assetsKeeper, authority: authority, + memStore: new(memoryStore), } } diff --git a/x/oracle/keeper/keeper_suite_test.go b/x/oracle/keeper/keeper_suite_test.go index 983c84a6b..3bc01c6b0 100644 --- a/x/oracle/keeper/keeper_suite_test.go +++ b/x/oracle/keeper/keeper_suite_test.go @@ -67,17 +67,19 @@ func TestKeeper(t *testing.T) { suite.Run(t, ks) - resetSingle() + resetSingle(ks.App.OracleKeeper) RegisterFailHandler(Fail) RunSpecs(t, "Keeper Suite") } func (suite *KeeperSuite) Reset() { - var ctxW context.Context - suite.ms, ctxW, suite.k = setupMsgServer(suite.t) - suite.ctx = sdk.UnwrapSDKContext(ctxW) + p4Test := types.DefaultParams() + p4Test.TokenFeeders[1].StartBaseBlock = 1 + suite.k.SetParams(suite.ctx, p4Test) + suite.ctx = suite.ctx.WithBlockHeight(12) + suite.ctrl = gomock.NewController(suite.t) - resetSingle() + resetSingle(suite.App.OracleKeeper) } func (suite *KeeperSuite) SetupTest() { @@ -99,10 +101,19 @@ func (suite *KeeperSuite) SetupTest() { validators := suite.ValSet.Validators suite.valAddr1, _ = sdk.ValAddressFromBech32(sdk.ValAddress(validators[0].Address).String()) suite.valAddr2, _ = sdk.ValAddressFromBech32(sdk.ValAddress(validators[1].Address).String()) - resetSingle() + resetSingle(suite.App.OracleKeeper) + + suite.k = suite.App.OracleKeeper + suite.ms = keeper.NewMsgServerImpl(suite.App.OracleKeeper) + suite.ctx = suite.Ctx + // Initialize params + p4Test := types.DefaultParams() + p4Test.TokenFeeders[1].StartBaseBlock = 1 + suite.k.SetParams(suite.ctx, p4Test) + suite.ctx = suite.ctx.WithBlockHeight(12) } -func resetSingle() { - keeper.ResetAggregatorContext() - keeper.ResetCache() +func resetSingle(k keeper.Keeper) { + k.ResetAggregatorContext() + k.ResetCache() } diff --git a/x/oracle/keeper/msg_server_create_price.go b/x/oracle/keeper/msg_server_create_price.go index 7eca28a82..9a7062126 100644 --- a/x/oracle/keeper/msg_server_create_price.go +++ b/x/oracle/keeper/msg_server_create_price.go @@ -30,7 +30,7 @@ func (ms msgServer) CreatePrice(goCtx context.Context, msg *types.MsgCreatePrice return nil, types.ErrPriceProposalFormatInvalid.Wrap(err.Error()) } - agc := GetAggregatorContext(ctx, ms.Keeper) + agc := ms.Keeper.GetAggregatorContext(ctx) newItem, caches, err := agc.NewCreatePrice(ctx, msg) if err != nil { logger.Info("price proposal failed", "error", err, "height", ctx.BlockHeight(), "feederID", msg.FeederID) @@ -70,11 +70,11 @@ func (ms msgServer) CreatePrice(goCtx context.Context, msg *types.MsgCreatePrice sdk.NewAttribute(types.AttributeKeyPriceUpdated, types.AttributeValuePriceUpdatedSuccess)), ) if !ctx.IsCheckTx() { - cs.RemoveCache(caches) + ms.Keeper.GetCaches().RemoveCache(caches) } - AppendUpdatedFeederIDs(msg.FeederID) + ms.Keeper.AppendUpdatedFeederIDs(msg.FeederID) } else if !ctx.IsCheckTx() { - cs.AddCache(caches) + ms.Keeper.GetCaches().AddCache(caches) } return &types.MsgCreatePriceResponse{}, nil diff --git a/x/oracle/keeper/msg_server_create_price_test.go b/x/oracle/keeper/msg_server_create_price_test.go index 211fe907a..3b5b3121f 100644 --- a/x/oracle/keeper/msg_server_create_price_test.go +++ b/x/oracle/keeper/msg_server_create_price_test.go @@ -6,7 +6,6 @@ import ( math "cosmossdk.io/math" dogfoodkeeper "github.com/ExocoreNetwork/exocore/x/dogfood/keeper" dogfoodtypes "github.com/ExocoreNetwork/exocore/x/dogfood/types" - "github.com/ExocoreNetwork/exocore/x/oracle/keeper" "github.com/ExocoreNetwork/exocore/x/oracle/keeper/cache" "github.com/ExocoreNetwork/exocore/x/oracle/keeper/testdata" "github.com/ExocoreNetwork/exocore/x/oracle/types" @@ -45,7 +44,7 @@ var _ = Describe("MsgCreatePrice", func() { } }) - Expect(ks.ctx.BlockHeight()).To(Equal(int64(2))) + Expect(ks.ctx.BlockHeight()).To(Equal(int64(12))) }) AfterEach(func() { @@ -61,11 +60,12 @@ var _ = Describe("MsgCreatePrice", func() { Creator: ks.mockConsAddr1.String(), FeederID: 1, Prices: testdata.PS1, - BasedBlock: 1, + BasedBlock: 11, Nonce: 1, }) - c = keeper.GetCaches() + c = ks.App.OracleKeeper.GetCaches() + // c = ks.ms.Keeper.GetCaches() var pRes cache.ItemP c.GetCache(&pRes) p4Test := types.DefaultParams() @@ -82,7 +82,7 @@ var _ = Describe("MsgCreatePrice", func() { Creator: ks.mockConsAddr2.String(), FeederID: 1, Prices: testdata.PS2, - BasedBlock: 1, + BasedBlock: 11, Nonce: 1, }, ) @@ -94,7 +94,7 @@ var _ = Describe("MsgCreatePrice", func() { Creator: ks.mockConsAddr3.String(), FeederID: 1, Prices: testdata.PS4, - BasedBlock: 1, + BasedBlock: 11, Nonce: 1, }, ) @@ -103,13 +103,19 @@ var _ = Describe("MsgCreatePrice", func() { prices := ks.k.GetAllPrices(sdk.UnwrapSDKContext(ks.ctx)) Expect(prices[0]).Should(BeEquivalentTo(types.Prices{ TokenID: 1, - NextRoundID: 2, + NextRoundID: 3, PriceList: []*types.PriceTimeRound{ + { + Price: "1", + Decimal: 0, + Timestamp: "", + RoundID: 1, + }, { Price: testdata.PTD2.Price, Decimal: testdata.PTD2.Decimal, - Timestamp: prices[0].PriceList[0].Timestamp, - RoundID: 1, + Timestamp: prices[0].PriceList[1].Timestamp, + RoundID: 2, }, }, })) diff --git a/x/oracle/keeper/msg_server_update_params.go b/x/oracle/keeper/msg_server_update_params.go index 400dd7de8..87f35f2c4 100644 --- a/x/oracle/keeper/msg_server_update_params.go +++ b/x/oracle/keeper/msg_server_update_params.go @@ -66,7 +66,7 @@ func (ms msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdatePara } // set updated new params ms.SetParams(ctx, p) - _ = GetAggregatorContext(ctx, ms.Keeper) - cs.AddCache(cache.ItemP(p)) + _ = ms.Keeper.GetAggregatorContext(ctx) + ms.Keeper.GetCaches().AddCache(cache.ItemP(p)) return &types.MsgUpdateParamsResponse{}, nil } diff --git a/x/oracle/keeper/msg_server_update_params_test.go b/x/oracle/keeper/msg_server_update_params_test.go index f4a09062c..6792d02e7 100644 --- a/x/oracle/keeper/msg_server_update_params_test.go +++ b/x/oracle/keeper/msg_server_update_params_test.go @@ -166,6 +166,7 @@ var _ = Describe("MsgUpdateParams", Ordered, func() { Context("update TokenFeeders", func() { It("update StartBaseBlock for TokenFeeder", func() { + ks.ctx = ks.ctx.WithBlockHeight(2) p := defaultParams p.TokenFeeders[1].StartBaseBlock = 10 ks.k.SetParams(ks.ctx, p) diff --git a/x/oracle/keeper/params.go b/x/oracle/keeper/params.go index 18db1ea69..9f7ccff5a 100644 --- a/x/oracle/keeper/params.go +++ b/x/oracle/keeper/params.go @@ -74,8 +74,8 @@ func (k Keeper) RegisterNewTokenAndSetTokenFeeder(ctx sdk.Context, oInfo *types. t.AssetID = strings.Join([]string{t.AssetID, oInfo.AssetID}, ",") k.SetParams(ctx, p) if !ctx.IsCheckTx() { - _ = GetAggregatorContext(ctx, k) - cs.AddCache(cache.ItemP(p)) + _ = k.GetAggregatorContext(ctx) + k.GetCaches().AddCache(cache.ItemP(p)) } // there should have been existing tokenFeeder running(currently we register tokens from assets-module and with infinite endBlock) return nil @@ -108,8 +108,8 @@ func (k Keeper) RegisterNewTokenAndSetTokenFeeder(ctx sdk.Context, oInfo *types. // skip cache update if this is not deliverTx // for normal cosmostx, checkTx will skip actual message exucution and do anteHandler only, but from ethc.callContract the message will be executed without anteHandler check as checkTx mode. if !ctx.IsCheckTx() { - _ = GetAggregatorContext(ctx, k) - cs.AddCache(cache.ItemP(p)) + _ = k.GetAggregatorContext(ctx) + k.GetCaches().AddCache(cache.ItemP(p)) } return nil } diff --git a/x/oracle/keeper/prices.go b/x/oracle/keeper/prices.go index 309054245..1c5e33a06 100644 --- a/x/oracle/keeper/prices.go +++ b/x/oracle/keeper/prices.go @@ -57,8 +57,8 @@ func (k Keeper) GetSpecifiedAssetsPrice(ctx sdk.Context, assetID string) (types. var p types.Params // get params from cache if exists - if agc != nil { - p = agc.GetParams() + if k.memStore.agc != nil { + p = k.memStore.agc.GetParams() } else { p = k.GetParams(ctx) } @@ -91,8 +91,8 @@ func (k Keeper) GetSpecifiedAssetsPrice(ctx sdk.Context, assetID string) (types. func (k Keeper) GetMultipleAssetsPrices(ctx sdk.Context, assets map[string]interface{}) (prices map[string]types.Price, err error) { var p types.Params // get params from cache if exists - if agc != nil { - p = agc.GetParams() + if k.memStore.agc != nil { + p = k.memStore.agc.GetParams() } else { p = k.GetParams(ctx) } @@ -201,7 +201,7 @@ func (k Keeper) AppendPriceTR(ctx sdk.Context, tokenID uint64, priceTR types.Pri store := k.getPriceTRStore(ctx, tokenID) b := k.cdc.MustMarshal(&priceTR) store.Set(types.PricesRoundKey(nextRoundID), b) - if expiredRoundID := nextRoundID - agc.GetParamsMaxSizePrices(); expiredRoundID > 0 { + if expiredRoundID := nextRoundID - k.memStore.agc.GetParamsMaxSizePrices(); expiredRoundID > 0 { store.Delete(types.PricesRoundKey(expiredRoundID)) } roundID := k.IncreaseNextRoundID(ctx, tokenID) @@ -210,8 +210,8 @@ func (k Keeper) AppendPriceTR(ctx sdk.Context, tokenID uint64, priceTR types.Pri // TODO: set hooks as a genral approach var p types.Params // get params from cache if exists - if agc != nil { - p = agc.GetParams() + if k.memStore.agc != nil { + p = k.memStore.agc.GetParams() } else { p = k.GetParams(ctx) } diff --git a/x/oracle/keeper/single.go b/x/oracle/keeper/single.go index c1f60e652..cf665cff3 100644 --- a/x/oracle/keeper/single.go +++ b/x/oracle/keeper/single.go @@ -11,58 +11,52 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -var updatedFeederIDs []string - -var cs *cache.Cache - -var agc, agcCheckTx *aggregator.AggregatorContext - -func GetCaches() *cache.Cache { - if cs != nil { - return cs +func (k *Keeper) GetCaches() *cache.Cache { + if k.memStore.cs != nil { + return k.memStore.cs } - cs = cache.NewCache() - return cs + k.memStore.cs = cache.NewCache() + return k.memStore.cs } // GetAggregatorContext returns singleton aggregatorContext used to calculate final price for each round of each tokenFeeder -func GetAggregatorContext(ctx sdk.Context, k Keeper) *aggregator.AggregatorContext { +func (k *Keeper) GetAggregatorContext(ctx sdk.Context) *aggregator.AggregatorContext { if ctx.IsCheckTx() { - if agcCheckTx != nil { - return agcCheckTx + if k.memStore.agcCheckTx != nil { + return k.memStore.agcCheckTx } - if agc == nil { - c := GetCaches() + if k.memStore.agc == nil { + c := k.GetCaches() c.ResetCaches() - agcCheckTx = aggregator.NewAggregatorContext() - if ok := recacheAggregatorContext(ctx, agcCheckTx, k, c); !ok { + k.memStore.agcCheckTx = aggregator.NewAggregatorContext() + if ok := k.recacheAggregatorContext(ctx, k.memStore.agcCheckTx, c); !ok { // this is the very first time oracle has been started, fill relalted info as initialization - initAggregatorContext(ctx, agcCheckTx, k, c) + initAggregatorContext(ctx, k.memStore.agcCheckTx, k, c) } - return agcCheckTx + return k.memStore.agcCheckTx } - agcCheckTx = agc.Copy4CheckTx() - return agcCheckTx + k.memStore.agcCheckTx = k.memStore.agc.Copy4CheckTx() + return k.memStore.agcCheckTx } - if agc != nil { - return agc + if k.memStore.agc != nil { + return k.memStore.agc } - c := GetCaches() + c := k.GetCaches() c.ResetCaches() - agc = aggregator.NewAggregatorContext() - if ok := recacheAggregatorContext(ctx, agc, k, c); !ok { + k.memStore.agc = aggregator.NewAggregatorContext() + if ok := k.recacheAggregatorContext(ctx, k.memStore.agc, c); !ok { // this is the very first time oracle has been started, fill relalted info as initialization - initAggregatorContext(ctx, agc, k, c) + initAggregatorContext(ctx, k.memStore.agc, k, c) } else { // this is when a node restart and use the persistent state to refill cache, we don't need to commit these data again c.SkipCommit() } - return agc + return k.memStore.agc } -func recacheAggregatorContext(ctx sdk.Context, agc *aggregator.AggregatorContext, k Keeper, c *cache.Cache) bool { +func (k Keeper) recacheAggregatorContext(ctx sdk.Context, agc *aggregator.AggregatorContext, c *cache.Cache) bool { logger := k.Logger(ctx) from := ctx.BlockHeight() - int64(common.MaxNonce) + 1 to := ctx.BlockHeight() @@ -163,7 +157,7 @@ func recacheAggregatorContext(ctx sdk.Context, agc *aggregator.AggregatorContext return true } -func initAggregatorContext(ctx sdk.Context, agc *aggregator.AggregatorContext, k common.KeeperOracle, c *cache.Cache) { +func initAggregatorContext(ctx sdk.Context, agc *aggregator.AggregatorContext, k *Keeper, c *cache.Cache) { ctx.Logger().Info("initAggregatorContext", "height", ctx.BlockHeight()) // set params p := k.GetParams(ctx) @@ -187,16 +181,16 @@ func initAggregatorContext(ctx sdk.Context, agc *aggregator.AggregatorContext, k agc.PrepareRoundEndBlock(uint64(ctx.BlockHeight()) - 1) } -func ResetAggregatorContext() { - agc = nil +func (k *Keeper) ResetAggregatorContext() { + k.memStore.agc = nil } -func ResetCache() { - cs = nil +func (k *Keeper) ResetCache() { + k.memStore.cs = nil } -func ResetAggregatorContextCheckTx() { - agcCheckTx = nil +func (k *Keeper) ResetAggregatorContextCheckTx() { + k.memStore.agcCheckTx = nil } func setCommonParams(p *types.Params) { @@ -207,16 +201,16 @@ func setCommonParams(p *types.Params) { common.Mode = p.Mode } -func ResetUpdatedFeederIDs() { - if updatedFeederIDs != nil { - updatedFeederIDs = nil +func (k *Keeper) ResetUpdatedFeederIDs() { + if k.memStore.updatedFeederIDs != nil { + k.memStore.updatedFeederIDs = nil } } -func GetUpdatedFeederIDs() []string { - return updatedFeederIDs +func (k Keeper) GetUpdatedFeederIDs() []string { + return k.memStore.updatedFeederIDs } -func AppendUpdatedFeederIDs(id uint64) { - updatedFeederIDs = append(updatedFeederIDs, strconv.FormatUint(id, 10)) +func (k *Keeper) AppendUpdatedFeederIDs(id uint64) { + k.memStore.updatedFeederIDs = append(k.memStore.updatedFeederIDs, strconv.FormatUint(id, 10)) } diff --git a/x/oracle/module.go b/x/oracle/module.go index 8e089d0b3..d98a8c6ac 100644 --- a/x/oracle/module.go +++ b/x/oracle/module.go @@ -155,18 +155,18 @@ func (AppModule) ConsensusVersion() uint64 { return 1 } func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { // init caches and aggregatorContext for node restart // TODO: try better way to init caches and aggregatorContext than beginBlock - once.Do(func() { - _ = keeper.GetCaches() - _ = keeper.GetAggregatorContext(ctx, am.keeper) - }) + // once.Do(func() { + _ = am.keeper.GetCaches() + _ = am.keeper.GetAggregatorContext(ctx) + // }) } // EndBlock contains the logic that is automatically triggered at the end of each block func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { - cs := keeper.GetCaches() + cs := am.keeper.GetCaches() validatorUpdates := am.keeper.GetValidatorUpdates(ctx) forceSeal := false - agc := keeper.GetAggregatorContext(ctx, am.keeper) + agc := am.keeper.GetAggregatorContext(ctx) logger := am.keeper.Logger(ctx) if len(validatorUpdates) > 0 { @@ -197,7 +197,7 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val logger.Info("add new round with previous price under fail aggregation", "tokenID", tokenID, "roundID", nextRoundID, "price", prevPrice) } - keeper.ResetAggregatorContextCheckTx() + am.keeper.ResetAggregatorContextCheckTx() if _, _, paramsUpdated := cs.CommitCache(ctx, false, am.keeper); paramsUpdated { var p cache.ItemP @@ -210,14 +210,14 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val )) } - if feederIDs := keeper.GetUpdatedFeederIDs(); len(feederIDs) > 0 { + if feederIDs := am.keeper.GetUpdatedFeederIDs(); len(feederIDs) > 0 { feederIDsStr := strings.Join(feederIDs, "_") ctx.EventManager().EmitEvent(sdk.NewEvent( types.EventTypeCreatePrice, sdk.NewAttribute(types.AttributeKeyPriceUpdated, types.AttributeValuePriceUpdatedSuccess), sdk.NewAttribute(types.AttributeKeyFeederIDs, feederIDsStr), )) - keeper.ResetUpdatedFeederIDs() + am.keeper.ResetUpdatedFeederIDs() } newRoundFeederIDs := agc.PrepareRoundEndBlock(uint64(ctx.BlockHeight())) From 36e54dd48b12980d87177012e600157895afdd2a Mon Sep 17 00:00:00 2001 From: leonz789 Date: Wed, 6 Nov 2024 10:07:54 +0800 Subject: [PATCH 07/22] add gentx, querycli, ed25519_keyring --- crypto/algo_ed25519.go | 55 +++++++++++++++++++++ testutil/network/network.go | 53 +++++++++++---------- testutil/network/network_test.go | 16 ++++++- testutil/network/query.go | 35 ++++++++++++++ testutil/network/tx.go | 82 ++++++++++++++++++++++++++++++++ testutil/network/util.go | 6 +-- 6 files changed, 218 insertions(+), 29 deletions(-) create mode 100644 crypto/algo_ed25519.go create mode 100644 testutil/network/query.go create mode 100644 testutil/network/tx.go diff --git a/crypto/algo_ed25519.go b/crypto/algo_ed25519.go new file mode 100644 index 000000000..5be09d03c --- /dev/null +++ b/crypto/algo_ed25519.go @@ -0,0 +1,55 @@ +package crypto + +import ( + // "github.com/cometbft/cometbft/crypto/ed25519" + cryptoed25519 "crypto/ed25519" + + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + "github.com/cosmos/go-bip39" + + // "github.com/evmos/evmos/v16/crypto/ethsecp256k1" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + evmoshd "github.com/evmos/evmos/v16/crypto/hd" +) + +var ( + SupportedAlgorithms = keyring.SigningAlgoList{evmoshd.EthSecp256k1, hd.Secp256k1} + Ed25519 = ed25519Algo{} +) + +type ed25519Algo struct{} + +func (e ed25519Algo) Name() hd.PubKeyType { + return hd.Ed25519Type +} + +// Derive derives and returns the ed25519 private key +// for ed25519, this is mainly used for test, we don't actually generate ed25519 from the path defined from slip0010, we ignore the path, and retrieve seed from mnemonic directly, then use that seed as secret to generate keys through ed25519 +func (e ed25519Algo) Derive() hd.DeriveFn { + return func(mnemonic, bip39Passphrase, path string) ([]byte, error) { + seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) + if err != nil { + return nil, err + } + return ed25519.GenPrivKeyFromSecret(seed).Bytes(), nil + } +} + +// Generate will be used to import privateKey from hex through keyring, so we just return the bz as privateKey instead of seed +func (e ed25519Algo) Generate() hd.GenerateFn { + return func(bz []byte) cryptotypes.PrivKey { + return &ed25519.PrivKey{ + Key: cryptoed25519.PrivateKey(bz), + } + } +} + +// Ed25519Option this option is mainly used for test +func Ed25519Option() keyring.Option { + return func(options *keyring.Options) { + options.SupportedAlgos = SupportedAlgorithms + } +} diff --git a/testutil/network/network.go b/testutil/network/network.go index a6d5d7429..242eae7b2 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -84,17 +84,18 @@ type Config struct { StakingTokens math.Int // the amount of tokens each validator stakes for every supporte asset NumValidators int // the total number of validators to create and bond ChainID string // the network chain-id - BondDenom string // the staking bond denomination - MinGasPrices string // the minimum gas prices each validator will accept - PruningStrategy string // the pruning strategy each validator will have - SigningAlgo string // signing algorithm for keys - RPCAddress string // RPC listen address (including port) - JSONRPCAddress string // JSON-RPC listen address (including port) - APIAddress string // REST API listen address (including port) - GRPCAddress string // GRPC server listen address (including port) - EnableTMLogging bool // enable Tendermint logging to STDOUT - CleanupDir bool // remove base temporary directory during cleanup - PrintMnemonic bool // print the mnemonic of first validator as log output for testing + // BondDenom string // the staking bond denomination + NativeDenom string // denomination for native token + MinGasPrices string // the minimum gas prices each validator will accept + PruningStrategy string // the pruning strategy each validator will have + SigningAlgo string // signing algorithm for keys + RPCAddress string // RPC listen address (including port) + JSONRPCAddress string // JSON-RPC listen address (including port) + APIAddress string // REST API listen address (including port) + GRPCAddress string // GRPC server listen address (including port) + EnableTMLogging bool // enable Tendermint logging to STDOUT + CleanupDir bool // remove base temporary directory during cleanup + PrintMnemonic bool // print the mnemonic of first validator as log output for testing } // DefaultConfig returns a sane default configuration suitable for nearly all @@ -110,19 +111,21 @@ func DefaultConfig() Config { AccountRetriever: authtypes.AccountRetriever{}, AppConstructor: NewAppConstructor(encCfg, chainID), GenesisState: app.ModuleBasics.DefaultGenesis(encCfg.Codec), - TimeoutCommit: 3 * time.Second, + TimeoutCommit: 2 * time.Second, ChainID: chainID, NumValidators: 4, - BondDenom: "hua", - MinGasPrices: fmt.Sprintf("0.000006%s", "hua"), - AccountTokens: sdk.TokensFromConsensusPower(1000, evmostypes.PowerReduction), - DepositedTokens: sdk.TokensFromConsensusPower(500, evmostypes.PowerReduction), - StakingTokens: sdk.TokensFromConsensusPower(200, evmostypes.PowerReduction), - PruningStrategy: pruningtypes.PruningOptionNothing, - CleanupDir: true, - SigningAlgo: string(hd.EthSecp256k1Type), - KeyringOptions: []keyring.Option{hd.EthSecp256k1Option()}, - PrintMnemonic: false, + // BondDenom: "hua", + NativeDenom: "hua", + // MinGasPrices: fmt.Sprintf("0.000006%s", "exo"), + MinGasPrices: "10hua", + AccountTokens: sdk.TokensFromConsensusPower(1000, evmostypes.PowerReduction), + DepositedTokens: sdk.TokensFromConsensusPower(500, evmostypes.PowerReduction), + StakingTokens: sdk.TokensFromConsensusPower(200, evmostypes.PowerReduction), + PruningStrategy: pruningtypes.PruningOptionNothing, + CleanupDir: true, + SigningAlgo: string(hd.EthSecp256k1Type), + KeyringOptions: []keyring.Option{hd.EthSecp256k1Option()}, + PrintMnemonic: false, } } @@ -250,6 +253,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { // generate private keys, node IDs, and initial transactions for i := 0; i < cfg.NumValidators; i++ { appCfg := config.DefaultConfig() + appCfg.MinGasPrices = cfg.MinGasPrices appCfg.Pruning = cfg.PruningStrategy appCfg.MinGasPrices = cfg.MinGasPrices appCfg.API.Enable = true @@ -417,8 +421,9 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { } balances := sdk.NewCoins( - sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens), - sdk.NewCoin(cfg.BondDenom, cfg.DepositedTokens), + // sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens), + // sdk.NewCoin(cfg.BondDenom, cfg.DepositedTokens), + sdk.NewCoin(cfg.NativeDenom, cfg.AccountTokens), ) genFiles = append(genFiles, tmCfg.GenesisFile()) diff --git a/testutil/network/network_test.go b/testutil/network/network_test.go index 4836a75b8..687e83608 100644 --- a/testutil/network/network_test.go +++ b/testutil/network/network_test.go @@ -1,6 +1,7 @@ package network_test import ( + "context" "fmt" "testing" "time" @@ -12,6 +13,9 @@ import ( "github.com/evmos/evmos/v16/server/config" exocorenetwork "github.com/ExocoreNetwork/exocore/testutil/network" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) type IntegrationTestSuite struct { @@ -27,8 +31,8 @@ func (s *IntegrationTestSuite) SetupSuite() { cfg := exocorenetwork.DefaultConfig() cfg.JSONRPCAddress = config.DefaultJSONRPCAddress cfg.NumValidators = 3 - cfg.CleanupDir = false - cfg.EnableTMLogging = true + cfg.CleanupDir = true + cfg.EnableTMLogging = false s.network, err = network.New(s.T(), s.T().TempDir(), cfg) s.Require().NoError(err) @@ -56,6 +60,14 @@ func (s *IntegrationTestSuite) TestNetwork_Liveness() { latestHeight, err := s.network.LatestHeight() s.Require().NoError(err, "latest height failed") s.Require().GreaterOrEqual(latestHeight, h) + + res, err := s.network.QueryBank().Balance(context.Background(), &banktypes.QueryBalanceRequest{ + Address: s.network.Validators[0].Address.String(), + Denom: s.network.Config.NativeDenom, + }) + s.Require().NoError(err, "query for validator's balance fail") + + s.Require().Equal(sdk.NewCoin(s.network.Config.NativeDenom, s.network.Config.AccountTokens), *res.Balance) } func TestIntegrationTestSuite(t *testing.T) { diff --git a/testutil/network/query.go b/testutil/network/query.go new file mode 100644 index 000000000..de143eb4d --- /dev/null +++ b/testutil/network/query.go @@ -0,0 +1,35 @@ +package network + +import ( + assetstypes "github.com/ExocoreNetwork/exocore/x/assets/types" + avstypes "github.com/ExocoreNetwork/exocore/x/avs/types" + dogfoodtypes "github.com/ExocoreNetwork/exocore/x/dogfood/types" + operatortypes "github.com/ExocoreNetwork/exocore/x/operator/types" + oracletypes "github.com/ExocoreNetwork/exocore/x/oracle/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func (n *Network) QueryOracle() oracletypes.QueryClient { + return oracletypes.NewQueryClient(n.Validators[0].ClientCtx) +} + +func (n *Network) QueryBank() banktypes.QueryClient { + return banktypes.NewQueryClient(n.Validators[0].ClientCtx) + +} + +func (n *Network) QueryAssets() assetstypes.QueryClient { + return assetstypes.NewQueryClient(n.Validators[0].ClientCtx) +} + +func (n *Network) QueryOperator() operatortypes.QueryClient { + return operatortypes.NewQueryClient(n.Validators[0].ClientCtx) +} + +func (n *Network) QueryAVS() avstypes.QueryClient { + return avstypes.NewQueryClient(n.Validators[0].ClientCtx) +} + +func (n *Network) QueryDogfood() dogfoodtypes.QueryClient { + return dogfoodtypes.NewQueryClient(n.Validators[0].ClientCtx) +} diff --git a/testutil/network/tx.go b/testutil/network/tx.go new file mode 100644 index 000000000..63bd143db --- /dev/null +++ b/testutil/network/tx.go @@ -0,0 +1,82 @@ +package network + +import ( + // "github.com/cosmos/cosmos-sdk/client" + "context" + + sdkmath "cosmossdk.io/math" + ctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + sdktx "github.com/cosmos/cosmos-sdk/types/tx" +) + +// GenSignedTx construct a tx with input messages and sign it privatekey stored in keyring +func (n *Network) GenSignedTx(msgs []sdk.Msg, keyName string) ([]byte, error) { + val := n.Validators[0] + ctx := val.ClientCtx + record, err := ctx.Keyring.Key(keyName) + if err != nil { + return nil, err + } + acc, err := record.GetAddress() + if err != nil { + return nil, err + } + txConfig := ctx.TxConfig + txBuilder := txConfig.NewTxBuilder() + txClient := sdktx.NewServiceClient(ctx) + txBuilder.SetMsgs(msgs...) + txBytes, _ := txConfig.TxEncoder()(txBuilder.GetTx()) + // simulate tx to get estimate gasLimit + gasInfo, _ := txClient.Simulate(context.Background(), &sdktx.SimulateRequest{ + TxBytes: txBytes, + }) + gasLimit := gasInfo.GasInfo.GasUsed + gasLimitInt := sdkmath.NewIntFromUint64(gasLimit) + // adjustment + gasLimitInt = gasLimitInt.Add(sdkmath.NewInt(100000)) + l := len(n.Config.MinGasPrices) - len(n.Config.NativeDenom) + fee := sdkmath.ZeroInt() + if l > 0 { + minGasPriceStr := n.Config.MinGasPrices[:l] + minGasPrice, _ := sdkmath.NewIntFromString(minGasPriceStr) + if err != nil { + return nil, err + } + fee = gasLimitInt.Mul(minGasPrice) + } + + txBuilder.SetGasLimit(gasLimit) + txBuilder.SetFeeAmount(sdk.Coins{sdk.NewCoin(n.Config.NativeDenom, fee)}) + num, seq, err := ctx.AccountRetriever.GetAccountNumberSequence(ctx, acc) + if err != nil { + return nil, err + } + txf := tx.Factory{}. + WithChainID(ctx.ChainID). + WithKeybase(ctx.Keyring). + WithTxConfig(txConfig). + WithAccountNumber(num). + WithSequence(seq) + + if err := tx.Sign(txf, keyName, txBuilder, true); err != nil { + return nil, err + } + + signedTx := txBuilder.GetTx() + if txBytes, err = txConfig.TxEncoder()(signedTx); err != nil { + return nil, err + } + + return txBytes, nil +} + +func (n *Network) SendTx(msgs []sdk.Msg, keyName string) (*ctypes.ResultBroadcastTx, error) { + signedTxBytes, err := n.GenSignedTx(msgs, keyName) + if err != nil { + return nil, err + } + // txClient.BraodcastTx() + return n.Validators[0].RPCClient.BroadcastTxSync(context.Background(), signedTxBytes) +} diff --git a/testutil/network/util.go b/testutil/network/util.go index 8a78658a0..0abd6c87d 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -176,19 +176,19 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance var govGenState govv1.GenesisState cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[govtypes.ModuleName], &govGenState) - govGenState.Params.MinDeposit[0].Denom = cfg.BondDenom + govGenState.Params.MinDeposit[0].Denom = cfg.NativeDenom cfg.GenesisState[govtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&govGenState) var crisisGenState crisistypes.GenesisState cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[crisistypes.ModuleName], &crisisGenState) - crisisGenState.ConstantFee.Denom = cfg.BondDenom + crisisGenState.ConstantFee.Denom = cfg.NativeDenom cfg.GenesisState[crisistypes.ModuleName] = cfg.Codec.MustMarshalJSON(&crisisGenState) var evmGenState evmtypes.GenesisState cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[evmtypes.ModuleName], &evmGenState) - evmGenState.Params.EvmDenom = cfg.BondDenom + evmGenState.Params.EvmDenom = cfg.NativeDenom cfg.GenesisState[evmtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&evmGenState) // set validators related modules: assets, operator, dogfood From ea053c2046f01d317ec982ea43fde3e3841f8bec Mon Sep 17 00:00:00 2001 From: leonz789 Date: Wed, 6 Nov 2024 10:30:01 +0800 Subject: [PATCH 08/22] fix typos, duplicate imports --- x/oracle/keeper/common/expected_keepers.go | 3 +-- x/oracle/keeper/slashing.go | 6 +++--- x/oracle/module.go | 2 +- x/oracle/types/events.go | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/x/oracle/keeper/common/expected_keepers.go b/x/oracle/keeper/common/expected_keepers.go index caf9130fe..f668d139b 100644 --- a/x/oracle/keeper/common/expected_keepers.go +++ b/x/oracle/keeper/common/expected_keepers.go @@ -1,7 +1,6 @@ package common import ( - "cosmossdk.io/math" sdkmath "cosmossdk.io/math" dogfoodkeeper "github.com/ExocoreNetwork/exocore/x/dogfood/keeper" dogfoodtypes "github.com/ExocoreNetwork/exocore/x/dogfood/types" @@ -60,6 +59,6 @@ type KeeperDogfood = interface { GetAllExocoreValidators(ctx sdk.Context) (validators []dogfoodtypes.ExocoreValidator) ValidatorByConsAddr(ctx sdk.Context, addr sdk.ConsAddress) stakingtypes.ValidatorI - SlashWithInfractionReason(ctx sdk.Context, addr sdk.ConsAddress, infractionHeight, power int64, slashFactor sdk.Dec, infraction stakingtypes.Infraction) math.Int + SlashWithInfractionReason(ctx sdk.Context, addr sdk.ConsAddress, infractionHeight, power int64, slashFactor sdk.Dec, infraction stakingtypes.Infraction) sdkmath.Int Jail(ctx sdk.Context, addr sdk.ConsAddress) } diff --git a/x/oracle/keeper/slashing.go b/x/oracle/keeper/slashing.go index f9bc86db7..5b3277ac5 100644 --- a/x/oracle/keeper/slashing.go +++ b/x/oracle/keeper/slashing.go @@ -9,7 +9,7 @@ import ( gogotypes "github.com/cosmos/gogoproto/types" ) -// InitValidatorReportInfo creates an new item for a first seen validator to tracking their performance +// InitValidatorReportInfo creates a new item for a first-seen validator to track their performance func (k Keeper) InitValidatorReportInfo(ctx sdk.Context, validator string, height int64) { store := ctx.KVStore(k.storeKey) key := types.SlashingValidatorReportInfoKey(validator) @@ -24,7 +24,7 @@ func (k Keeper) InitValidatorReportInfo(ctx sdk.Context, validator string, heigh } } -// SetValidatorReportInfo sets the validator reporting info to a valdiator +// SetValidatorReportInfo sets the reporting info for a validator func (k Keeper) SetValidatorReportInfo(ctx sdk.Context, validator string, info types.ValidatorReportInfo) { store := ctx.KVStore(k.storeKey) bz := k.cdc.MustMarshal(&info) @@ -114,7 +114,7 @@ func (k Keeper) IterateValidatorReportInfos(ctx sdk.Context, handler func(addres iterator.Close() } -func (k Keeper) IterateValidatorMissedRoundBitArray(ctx sdk.Context, validator string, handler func(index int64, missed bool) (strop bool)) { +func (k Keeper) IterateValidatorMissedRoundBitArray(ctx sdk.Context, validator string, handler func(index int64, missed bool) (stop bool)) { // store := prefix.NewStore(ctx.KVStore(k.storeKey), types.SlashingMissedBitArrayPrefix(validator)) store := ctx.KVStore(k.storeKey) index := int64(0) diff --git a/x/oracle/module.go b/x/oracle/module.go index 609928a12..d5a128c10 100644 --- a/x/oracle/module.go +++ b/x/oracle/module.go @@ -209,7 +209,7 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val continue } // TODO: for the round calculation, now only sourceID=1 is used so {feederID, sourceID} have only one value for each feederID which corresponding to one round. - // But when we came to multiple sources, we should consider the round corresponding to feedeerID instead of {feederID, srouceID} + // But when we came to multiple sources, we should consider the round corresponding to feedeerID instead of {feederID, sourceID} for _, finalPrice := range agc.GetFinalPriceListForFeederIDs(windowClosed) { exist, matched := agc.PerformanceReview(finalPrice, validator) if exist && !matched { diff --git a/x/oracle/types/events.go b/x/oracle/types/events.go index d140aa712..3a0d42c2b 100644 --- a/x/oracle/types/events.go +++ b/x/oracle/types/events.go @@ -16,7 +16,7 @@ const ( AttributeKeyFeederIDs = "feeder_ids" AttributeKeyNativeTokenUpdate = "native_token_update" AttributeKeyNativeTokenChange = "native_token_change" - AttributeKeyValidatorKey = "validator" + AttributeKeyValidatorKey = "validator_key" AttributeKeyMissedRounds = "missed_rounds" AttributeKeyHeight = "height" AttributeKeyPower = "power" From 1fd83d46de217a21a1b369910195bb79da9e7742 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Fri, 8 Nov 2024 10:18:32 +0800 Subject: [PATCH 09/22] add test cases for basic bank/send, oracle/create-price --- crypto/algo_ed25519.go | 2 +- go.mod | 1 + tests/e2e/bank/bank_test.go | 16 ++++++ tests/e2e/bank/query.go | 13 +++++ tests/e2e/bank/suite.go | 26 ++++++++++ tests/e2e/bank/test.result | 0 tests/e2e/bank/tx.go | 47 +++++++++++++++++ tests/e2e/basesuite.go | 26 ++++++++++ tests/e2e/oracle/oracle_test.go | 16 ++++++ tests/e2e/oracle/suite.go | 26 ++++++++++ tests/e2e/oracle/tx.go | 39 +++++++++++++++ tests/e2e/util.go | 37 ++++++++++++++ testutil/network/network.go | 39 ++++++++++----- testutil/network/tx.go | 89 ++++++++------------------------- testutil/network/tx_internal.go | 89 +++++++++++++++++++++++++++++++++ testutil/network/util.go | 16 ++++++ 16 files changed, 402 insertions(+), 80 deletions(-) create mode 100644 tests/e2e/bank/bank_test.go create mode 100644 tests/e2e/bank/query.go create mode 100644 tests/e2e/bank/suite.go create mode 100644 tests/e2e/bank/test.result create mode 100644 tests/e2e/bank/tx.go create mode 100644 tests/e2e/basesuite.go create mode 100644 tests/e2e/oracle/oracle_test.go create mode 100644 tests/e2e/oracle/suite.go create mode 100644 tests/e2e/oracle/tx.go create mode 100644 tests/e2e/util.go create mode 100644 testutil/network/tx_internal.go diff --git a/crypto/algo_ed25519.go b/crypto/algo_ed25519.go index 5be09d03c..ded767401 100644 --- a/crypto/algo_ed25519.go +++ b/crypto/algo_ed25519.go @@ -16,7 +16,7 @@ import ( ) var ( - SupportedAlgorithms = keyring.SigningAlgoList{evmoshd.EthSecp256k1, hd.Secp256k1} + SupportedAlgorithms = keyring.SigningAlgoList{evmoshd.EthSecp256k1, hd.Secp256k1, Ed25519} Ed25519 = ed25519Algo{} ) diff --git a/go.mod b/go.mod index 6c0fa830a..34be7cc96 100644 --- a/go.mod +++ b/go.mod @@ -263,6 +263,7 @@ replace ( github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // use Cosmos-SDK fork to enable Ledger functionality github.com/cosmos/cosmos-sdk => github.com/evmos/cosmos-sdk v0.47.5-evmos.2 + //fix cosmos-sdk error github.com/cosmos/gogoproto => github.com/cosmos/gogoproto v1.4.10 // use Evmos geth fork diff --git a/tests/e2e/bank/bank_test.go b/tests/e2e/bank/bank_test.go new file mode 100644 index 000000000..773cf5681 --- /dev/null +++ b/tests/e2e/bank/bank_test.go @@ -0,0 +1,16 @@ +package bank + +import ( + "testing" + + "github.com/ExocoreNetwork/exocore/testutil/network" + "github.com/stretchr/testify/suite" +) + +func TestE2ETestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + cfg.CleanupDir = true + cfg.EnableTMLogging = false + suite.Run(t, NewE2ETestSuite(cfg)) +} diff --git a/tests/e2e/bank/query.go b/tests/e2e/bank/query.go new file mode 100644 index 000000000..78c8abd65 --- /dev/null +++ b/tests/e2e/bank/query.go @@ -0,0 +1,13 @@ +package bank + +import ( + "github.com/ExocoreNetwork/exocore/tests/e2e" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (s *E2ETestSuite) TestQeuryBalance() { + res, err := e2e.QueryNativeCoinBalance(s.network.Validators[0].Address, s.network) + s.Require().NoError(err) + s.Require().Equal(sdk.NewCoin(s.network.Config.NativeDenom, s.network.Config.AccountTokens), *res.Balance) + s.Require().Equal(e2e.NewNativeCoin(s.network.Config.AccountTokens, s.network), *res.Balance) +} diff --git a/tests/e2e/bank/suite.go b/tests/e2e/bank/suite.go new file mode 100644 index 000000000..1566f26fd --- /dev/null +++ b/tests/e2e/bank/suite.go @@ -0,0 +1,26 @@ +package bank + +import ( + "github.com/ExocoreNetwork/exocore/testutil/network" + "github.com/stretchr/testify/suite" +) + +type E2ETestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network +} + +func NewE2ETestSuite(cfg network.Config) *E2ETestSuite { + return &E2ETestSuite{cfg: cfg} +} + +func (s *E2ETestSuite) SetupSuite() { + s.T().Log("setting up e2e test suite") + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) + _, err = s.network.WaitForHeight(2) + s.Require().NoError(err) +} diff --git a/tests/e2e/bank/test.result b/tests/e2e/bank/test.result new file mode 100644 index 000000000..e69de29bb diff --git a/tests/e2e/bank/tx.go b/tests/e2e/bank/tx.go new file mode 100644 index 000000000..801301a29 --- /dev/null +++ b/tests/e2e/bank/tx.go @@ -0,0 +1,47 @@ +package bank + +import ( + sdkmath "cosmossdk.io/math" + "github.com/ExocoreNetwork/exocore/tests/e2e" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func (s *E2ETestSuite) TestSendCoin() { + kr := s.network.Validators[0].ClientCtx.Keyring + // generate a new account with ethsecp256k1 to recieve/send native coins (hua) + toAddr, err := e2e.GenerateAccAddress(kr, "user1") + s.Require().NoError(err) + // generate sendCoin msg + fromAddr := s.network.Validators[0].Address + msg := banktypes.NewMsgSend(fromAddr, toAddr, sdk.NewCoins(sdk.NewCoin(s.network.Config.NativeDenom, sdkmath.NewInt(2000000)))) + + // send sendCoinMsg + err = s.network.SendTx([]sdk.Msg{msg}, s.network.Validators[0].ClientCtx.FromName, kr) + s.Require().NoError(err) + + // wait to next block for tx to be included + err = s.network.WaitForNextBlock() + s.Require().NoError(err) + + // check user1's balance + res, err := e2e.QueryNativeCoinBalance(toAddr, s.network) + s.Require().NoError(err) + s.Require().Equal(e2e.NewNativeCoin(sdkmath.NewInt(2000000), s.network), *res.Balance) + + toAddr2, _ := e2e.GenerateAccAddress(kr, "user2") + + msg = banktypes.NewMsgSend(toAddr, toAddr2, sdk.NewCoins(sdk.NewCoin(s.network.Config.NativeDenom, sdkmath.NewInt(100)))) + // send sendCoinMsg + err = s.network.SendTx([]sdk.Msg{msg}, "user1", kr) + s.Require().NoError(err) + + // wait to next block for tx to be included + err = s.network.WaitForNextBlock() + s.Require().NoError(err) + + // check user2's balance + res, err = e2e.QueryNativeCoinBalance(toAddr2, s.network) + s.Require().NoError(err) + s.Require().Equal(e2e.NewNativeCoin(sdkmath.NewInt(100), s.network), *res.Balance) +} diff --git a/tests/e2e/basesuite.go b/tests/e2e/basesuite.go new file mode 100644 index 000000000..aa19de429 --- /dev/null +++ b/tests/e2e/basesuite.go @@ -0,0 +1,26 @@ +package e2e + +import ( + "github.com/ExocoreNetwork/exocore/testutil/network" + "github.com/stretchr/testify/suite" +) + +type BaseSuite struct { + suite.Suite + + Cfg network.Config + Network *network.Network +} + +func NewBaseSuite(cfg network.Config) *BaseSuite { + return &BaseSuite{Cfg: cfg} +} + +func (s *BaseSuite) SetupSuite() { + s.T().Log("setting up e2e test suite") + var err error + s.Network, err = network.New(s.T(), s.T().TempDir(), s.Cfg) + s.Require().NoError(err) + _, err = s.Network.WaitForHeight(2) + s.Require().NoError(err) +} diff --git a/tests/e2e/oracle/oracle_test.go b/tests/e2e/oracle/oracle_test.go new file mode 100644 index 000000000..af0a31760 --- /dev/null +++ b/tests/e2e/oracle/oracle_test.go @@ -0,0 +1,16 @@ +package oracle + +import ( + "testing" + + "github.com/ExocoreNetwork/exocore/testutil/network" + "github.com/stretchr/testify/suite" +) + +func TestE2ESuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + cfg.CleanupDir = true + cfg.EnableTMLogging = true + suite.Run(t, NewE2ETestSuite(cfg)) +} diff --git a/tests/e2e/oracle/suite.go b/tests/e2e/oracle/suite.go new file mode 100644 index 000000000..238b55121 --- /dev/null +++ b/tests/e2e/oracle/suite.go @@ -0,0 +1,26 @@ +package oracle + +import ( + "github.com/ExocoreNetwork/exocore/testutil/network" + "github.com/stretchr/testify/suite" +) + +type E2ETestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network +} + +func NewE2ETestSuite(cfg network.Config) *E2ETestSuite { + return &E2ETestSuite{cfg: cfg} +} + +func (s *E2ETestSuite) SetupSuite() { + s.T().Log("setting up e2e test suite") + var err error + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) + _, err = s.network.WaitForHeight(2) + s.Require().NoError(err) +} diff --git a/tests/e2e/oracle/tx.go b/tests/e2e/oracle/tx.go new file mode 100644 index 000000000..e429f13e7 --- /dev/null +++ b/tests/e2e/oracle/tx.go @@ -0,0 +1,39 @@ +package oracle + +import ( + "time" + + oracletypes "github.com/ExocoreNetwork/exocore/x/oracle/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const layout = "2006-01-02 15:04:05" + +func (s *E2ETestSuite) TestCreatePriceLST() { + kr := s.network.Validators[0].ClientCtx.Keyring + s.network.WaitForHeight(10) + creator := sdk.AccAddress(s.network.Validators[0].PubKey.Address()) + priceSource := oracletypes.PriceSource{ + SourceID: 1, + Prices: []*oracletypes.PriceTimeDetID{ + { + Price: "999123", + Decimal: 3, + Timestamp: time.Now().UTC().Format(layout), + DetID: "9", + }, + }, + } + msg := oracletypes.NewMsgCreatePrice(creator.String(), 1, []*oracletypes.PriceSource{&priceSource}, 10, 1) + s.network.SendTx([]sdk.Msg{msg}, "validator0", kr) + + s.network.WaitForHeight(12) +} + +func (s *E2ETestSuite) TestCreatePriceNST() { + +} + +func (s *E2ETestSuite) TestSlashing() { + +} diff --git a/tests/e2e/util.go b/tests/e2e/util.go new file mode 100644 index 000000000..777e584ad --- /dev/null +++ b/tests/e2e/util.go @@ -0,0 +1,37 @@ +package e2e + +import ( + "context" + + sdkmath "cosmossdk.io/math" + "github.com/ExocoreNetwork/exocore/testutil/network" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/evmos/evmos/v16/crypto/hd" +) + +// func (s *E2ETestSuite) queryNativeCoinBalance(address sdk.AccAddress, n *network.Network) (*banktypes.QueryBalanceResponse, error) { +func QueryNativeCoinBalance(address sdk.AccAddress, n *network.Network) (*banktypes.QueryBalanceResponse, error) { + return n.QueryBank().Balance(context.Background(), &banktypes.QueryBalanceRequest{ + Address: address.String(), + // Denom: s.network.Config.NativeDenom, + Denom: n.Config.NativeDenom, + }) +} + +// func (s *E2ETestSuite) newNativeCoin(amount sdkmath.Int, n *network.Network) sdk.Coin { +func NewNativeCoin(amount sdkmath.Int, n *network.Network) sdk.Coin { + // return sdk.NewCoin(s.network.Config.NativeDenom, amount) + return sdk.NewCoin(n.Config.NativeDenom, amount) +} + +func GenerateAccAddress(kr keyring.Keyring, name string) (sdk.AccAddress, error) { + // generate a new account with ethsecp256k1 + r, _, err := kr.NewMnemonic(name, keyring.English, sdk.GetConfig().GetFullBIP44Path(), "", hd.EthSecp256k1) + if err != nil { + return nil, err + } + addr, _ := r.GetAddress() + return addr, nil +} diff --git a/testutil/network/network.go b/testutil/network/network.go index 242eae7b2..f5acaf2b1 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -50,6 +50,9 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/genutil" + + exocorecrypto "github.com/ExocoreNetwork/exocore/crypto" + cosmoshd "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/evmos/evmos/v16/crypto/hd" // ekeyring "github.com/evmos/evmos/v16/crypto/keyring" @@ -124,8 +127,9 @@ func DefaultConfig() Config { PruningStrategy: pruningtypes.PruningOptionNothing, CleanupDir: true, SigningAlgo: string(hd.EthSecp256k1Type), - KeyringOptions: []keyring.Option{hd.EthSecp256k1Option()}, - PrintMnemonic: false, + // KeyringOptions: []keyring.Option{hd.EthSecp256k1Option()}, + KeyringOptions: []keyring.Option{exocorecrypto.Ed25519Option()}, + PrintMnemonic: false, } } @@ -335,7 +339,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { logger := log.NewNopLogger() if cfg.EnableTMLogging { logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - logger, _ = tmflags.ParseLogLevel("info", logger, tmcfg.DefaultLogLevel) + logger, _ = tmflags.ParseLogLevel("debug", logger, tmcfg.DefaultLogLevel) } ctx.Logger = logger @@ -372,8 +376,23 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { tmCfg.P2P.AddrBookStrict = false tmCfg.P2P.AllowDuplicateIP = true + kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.Codec, cfg.KeyringOptions...) + if err != nil { + return nil, err + } + + keyringAlgos, _ := kb.SupportedAlgorithms() + algo, err := keyring.NewSigningAlgoFromString(string(cosmoshd.Ed25519Type), keyringAlgos) + if err != nil { + return nil, err + } + _, mnemonic, err := kb.NewMnemonic(fmt.Sprintf("valconskey%d", i), keyring.English, sdk.GetConfig().GetBech32AccountPubPrefix(), keyring.DefaultBIP39Passphrase, algo) + if err != nil { + return nil, err + } + // initialize nodekey, consensus_priv_key under nodeDir - nodeID, pubKey, err := genutil.InitializeNodeValidatorFiles(tmCfg) + nodeID, pubKey, err := genutil.InitializeNodeValidatorFilesFromMnemonic(tmCfg, mnemonic) if err != nil { return nil, err } @@ -386,13 +405,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { addressesIPs[i] = fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port()) valPubKeys[i] = pubKey - kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.Codec, cfg.KeyringOptions...) - if err != nil { - return nil, err - } - - keyringAlgos, _ := kb.SupportedAlgorithms() - algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos) + algo, err = keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos) if err != nil { return nil, err } @@ -453,7 +466,9 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { WithCodec(cfg.Codec). WithLegacyAmino(cfg.LegacyAmino). WithTxConfig(cfg.TxConfig). - WithAccountRetriever(cfg.AccountRetriever) + WithAccountRetriever(cfg.AccountRetriever). + WithFromName(nodeDirName). + WithFrom(addr.String()) network.Validators[i] = &Validator{ AppConfig: appCfg, diff --git a/testutil/network/tx.go b/testutil/network/tx.go index 63bd143db..4bd970ea9 100644 --- a/testutil/network/tx.go +++ b/testutil/network/tx.go @@ -1,82 +1,37 @@ package network import ( - // "github.com/cosmos/cosmos-sdk/client" - "context" - - sdkmath "cosmossdk.io/math" - ctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" - sdktx "github.com/cosmos/cosmos-sdk/types/tx" + "github.com/cosmos/cosmos-sdk/types/tx/signing" ) -// GenSignedTx construct a tx with input messages and sign it privatekey stored in keyring -func (n *Network) GenSignedTx(msgs []sdk.Msg, keyName string) ([]byte, error) { - val := n.Validators[0] - ctx := val.ClientCtx - record, err := ctx.Keyring.Key(keyName) +// SendTx construct and sign that tx with input msgs +func (n *Network) SendTx(msgs []sdk.Msg, keyName string, keyring keyring.Keyring) error { + ctx := n.Validators[0].ClientCtx + record, err := keyring.Key(keyName) if err != nil { - return nil, err + return err } acc, err := record.GetAddress() if err != nil { - return nil, err - } - txConfig := ctx.TxConfig - txBuilder := txConfig.NewTxBuilder() - txClient := sdktx.NewServiceClient(ctx) - txBuilder.SetMsgs(msgs...) - txBytes, _ := txConfig.TxEncoder()(txBuilder.GetTx()) - // simulate tx to get estimate gasLimit - gasInfo, _ := txClient.Simulate(context.Background(), &sdktx.SimulateRequest{ - TxBytes: txBytes, - }) - gasLimit := gasInfo.GasInfo.GasUsed - gasLimitInt := sdkmath.NewIntFromUint64(gasLimit) - // adjustment - gasLimitInt = gasLimitInt.Add(sdkmath.NewInt(100000)) - l := len(n.Config.MinGasPrices) - len(n.Config.NativeDenom) - fee := sdkmath.ZeroInt() - if l > 0 { - minGasPriceStr := n.Config.MinGasPrices[:l] - minGasPrice, _ := sdkmath.NewIntFromString(minGasPriceStr) - if err != nil { - return nil, err - } - fee = gasLimitInt.Mul(minGasPrice) - } - - txBuilder.SetGasLimit(gasLimit) - txBuilder.SetFeeAmount(sdk.Coins{sdk.NewCoin(n.Config.NativeDenom, fee)}) - num, seq, err := ctx.AccountRetriever.GetAccountNumberSequence(ctx, acc) - if err != nil { - return nil, err + return err } + ctx.FromAddress = acc + ctx.FromName = keyName + ctx.SkipConfirm = true txf := tx.Factory{}. WithChainID(ctx.ChainID). - WithKeybase(ctx.Keyring). - WithTxConfig(txConfig). - WithAccountNumber(num). - WithSequence(seq) - - if err := tx.Sign(txf, keyName, txBuilder, true); err != nil { - return nil, err - } - - signedTx := txBuilder.GetTx() - if txBytes, err = txConfig.TxEncoder()(signedTx); err != nil { - return nil, err - } - - return txBytes, nil -} - -func (n *Network) SendTx(msgs []sdk.Msg, keyName string) (*ctypes.ResultBroadcastTx, error) { - signedTxBytes, err := n.GenSignedTx(msgs, keyName) - if err != nil { - return nil, err - } - // txClient.BraodcastTx() - return n.Validators[0].RPCClient.BroadcastTxSync(context.Background(), signedTxBytes) + WithKeybase(keyring). + WithTxConfig(ctx.TxConfig). + WithSignMode(signing.SignMode_SIGN_MODE_DIRECT). + WithGasAdjustment(1.5). + WithAccountRetriever(ctx.AccountRetriever). + WithGasPrices(n.Config.MinGasPrices). + WithSimulateAndExecute(true) + + ctx.BroadcastMode = flags.BroadcastSync + return tx.BroadcastTx(ctx, txf, msgs...) } diff --git a/testutil/network/tx_internal.go b/testutil/network/tx_internal.go new file mode 100644 index 000000000..14eb876dc --- /dev/null +++ b/testutil/network/tx_internal.go @@ -0,0 +1,89 @@ +package network + +import ( + "context" + "fmt" + + sdkmath "cosmossdk.io/math" + ctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + sdk "github.com/cosmos/cosmos-sdk/types" + sdktx "github.com/cosmos/cosmos-sdk/types/tx" +) + +func (n *Network) SendTxInternal(msgs []sdk.Msg, keyName string, kr keyring.Keyring) (*ctypes.ResultBroadcastTx, error) { + signedTxBytes, err := n.genSignedTxInternal(msgs, keyName, kr) + if err != nil { + return nil, err + } + // txClient.BroadcastTx() + return n.Validators[0].RPCClient.BroadcastTxSync(context.Background(), signedTxBytes) +} + +// GenSignedTx construct a tx with input messages and sign it privatekey stored in keyring +func (n *Network) genSignedTxInternal(msgs []sdk.Msg, keyName string, kr keyring.Keyring) ([]byte, error) { + val := n.Validators[0] + ctx := val.ClientCtx + + // record, err := ctx.Keyring.Key(keyName) + record, err := kr.Key(keyName) + if err != nil { + return nil, err + } + acc, err := record.GetAddress() + if err != nil { + return nil, err + } + txConfig := ctx.TxConfig + txBuilder := txConfig.NewTxBuilder() + txClient := sdktx.NewServiceClient(ctx) + if err = txBuilder.SetMsgs(msgs...); err != nil { + return nil, err + } + txBytes, _ := txConfig.TxEncoder()(txBuilder.GetTx()) + // simulate tx to get estimate gasLimit + gasInfo, err := txClient.Simulate(context.Background(), &sdktx.SimulateRequest{ + TxBytes: txBytes, + }) + fmt.Println("debug--err", err) + + // adjustment + gasLimit := uint64(float64(gasInfo.GasInfo.GasUsed) * 1.5) + gasLimitInt := sdkmath.NewIntFromUint64(gasLimit) + l := len(n.Config.MinGasPrices) - len(n.Config.NativeDenom) + fee := sdkmath.ZeroInt() + if l > 0 { + minGasPriceStr := n.Config.MinGasPrices[:l] + minGasPrice, _ := sdkmath.NewIntFromString(minGasPriceStr) + if err != nil { + return nil, err + } + fee = gasLimitInt.Mul(minGasPrice) + } + + txBuilder.SetGasLimit(gasLimit) + txBuilder.SetFeeAmount(sdk.Coins{sdk.NewCoin(n.Config.NativeDenom, fee)}) + num, seq, err := ctx.AccountRetriever.GetAccountNumberSequence(ctx, acc) + if err != nil { + return nil, err + } + txf := tx.Factory{}. + WithChainID(ctx.ChainID). + // WithKeybase(ctx.Keyring). + WithKeybase(kr). + WithTxConfig(txConfig). + WithAccountNumber(num). + WithSequence(seq) + + if err := tx.Sign(txf, keyName, txBuilder, true); err != nil { + return nil, err + } + + signedTx := txBuilder.GetTx() + if txBytes, err = txConfig.TxEncoder()(signedTx); err != nil { + return nil, err + } + + return txBytes, nil +} diff --git a/testutil/network/util.go b/testutil/network/util.go index 0abd6c87d..dcc1aaa01 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -39,6 +39,7 @@ import ( "github.com/evmos/evmos/v16/server" evmostypes "github.com/evmos/evmos/v16/types" evmtypes "github.com/evmos/evmos/v16/x/evm/types" + feemarkettypes "github.com/evmos/evmos/v16/x/feemarket/types" ) func startInProcess(cfg Config, val *Validator) error { @@ -168,9 +169,24 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance authGenState.Accounts = append(authGenState.Accounts, accounts...) cfg.GenesisState[authtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&authGenState) + var feemarketGenState feemarkettypes.GenesisState + cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[feemarkettypes.ModuleName], &feemarketGenState) + l := len(cfg.MinGasPrices) - len(cfg.NativeDenom) + minGasPrice := sdkmath.ZeroInt() + if l > 0 { + minGasPriceStr := cfg.MinGasPrices[:l] + minGasPrice, _ = sdkmath.NewIntFromString(minGasPriceStr) + if err != nil { + return err + } + } + feemarketGenState.Params.BaseFee = minGasPrice + cfg.GenesisState[feemarkettypes.ModuleName] = cfg.Codec.MustMarshalJSON(&feemarketGenState) + // set the balances in the genesis state var bankGenState banktypes.GenesisState bankGenState.Balances = genBalances + bankGenState.Params.DefaultSendEnabled = true cfg.GenesisState[banktypes.ModuleName] = cfg.Codec.MustMarshalJSON(&bankGenState) var govGenState govv1.GenesisState From c5d3628f7a3ace15c7739f77cd0e5a55e05e9640 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Fri, 8 Nov 2024 18:30:42 +0800 Subject: [PATCH 10/22] typos --- proto/exocore/oracle/v1/genesis.proto | 6 +- proto/exocore/oracle/v1/slashing.proto | 7 +- x/oracle/genesis.go | 8 +- x/oracle/keeper/slashing.go | 10 +- x/oracle/module.go | 2 +- x/oracle/types/genesis.pb.go | 137 +++++++++++++------------ x/oracle/types/params.go | 23 +++-- x/oracle/types/slashing.pb.go | 47 +++++---- 8 files changed, 133 insertions(+), 107 deletions(-) diff --git a/proto/exocore/oracle/v1/genesis.proto b/proto/exocore/oracle/v1/genesis.proto index 4d88c7663..5d8065e33 100644 --- a/proto/exocore/oracle/v1/genesis.proto +++ b/proto/exocore/oracle/v1/genesis.proto @@ -44,9 +44,9 @@ message GenesisState { // information for slashing history // ValidatorReportInfo records all the validatorReportInfos - repeated ValidatorReportInfo report_infos = 10[(gogoproto.nullable)=false]; + repeated ValidatorReportInfo validator_report_infos = 10[(gogoproto.nullable)=false]; // ValidatorMissedRounds records missedRounds for all validators seen - repeated ValidatorMissedRounds missed_rounds = 11[(gogoproto.nullable)=false]; + repeated ValidatorMissedRounds validator_missed_rounds = 11[(gogoproto.nullable)=false]; } // stakerInfosAssets bond stakerinfos to their related assets id @@ -67,7 +67,9 @@ message StakerListAssets { // ValidatorMissedRounds record missed rounds indexes for a validator which consAddr corresponding to the address message ValidatorMissedRounds { + // address of validator string address = 1; + // missed_rounds tells how many rounds this validtor had missed for current windo repeated MissedRound missed_rounds = 2; } diff --git a/proto/exocore/oracle/v1/slashing.proto b/proto/exocore/oracle/v1/slashing.proto index 7a28be032..a74d076a9 100644 --- a/proto/exocore/oracle/v1/slashing.proto +++ b/proto/exocore/oracle/v1/slashing.proto @@ -4,9 +4,14 @@ package exocore.oracle.v1; option go_package = "github.com/ExocoreNetwork/exocore/x/oracle/types"; +// ValidatorReportInfo represents the information to describe the miss status of a validator reporting prices message ValidatorReportInfo { + // address of the validtor string address = 1; - int64 startHeight = 2; + // start_height for the performance round of the configured window of rounds + int64 start_height = 2; + // index_offset track the offset of current window int64 index_offset = 3; + // missed_rounds_counter counts the number of missed rounds for this window int64 missed_rounds_counter = 4; } diff --git a/x/oracle/genesis.go b/x/oracle/genesis.go index 9085279eb..8c4223acc 100644 --- a/x/oracle/genesis.go +++ b/x/oracle/genesis.go @@ -41,11 +41,11 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) k.SetStakerInfos(ctx, elem.AssetId, elem.StakerInfos) } // set validatorReportInfos - for _, elem := range genState.ReportInfos { + for _, elem := range genState.ValidatorReportInfos { k.SetValidatorReportInfo(ctx, elem.Address, elem) } // set vlidatorMissedRounds - for _, elem := range genState.MissedRounds { + for _, elem := range genState.ValidatorMissedRounds { for _, missedRound := range elem.MissedRounds { k.SetValidatorMissedRoundBitArray(ctx, elem.Address, uint64(missedRound.Index), missedRound.Missed) } @@ -98,8 +98,8 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { }) return false }) - genesis.ReportInfos = reportInfos - genesis.MissedRounds = validatorMissedRounds + genesis.ValidatorReportInfos = reportInfos + genesis.ValidatorMissedRounds = validatorMissedRounds // this line is used by starport scaffolding # genesis/module/export return genesis diff --git a/x/oracle/keeper/slashing.go b/x/oracle/keeper/slashing.go index 5b3277ac5..804f00b3c 100644 --- a/x/oracle/keeper/slashing.go +++ b/x/oracle/keeper/slashing.go @@ -43,7 +43,7 @@ func (k Keeper) GetValidatorReportInfo(ctx sdk.Context, validator string) (info return } -// SetValidatorMissedBlockBitArray sets the bit that checks if the validator has +// SetValidatorMissedRoundBitArray sets the bit that checks if the validator has // missed a round to report price in the current window func (k Keeper) SetValidatorMissedRoundBitArray(ctx sdk.Context, validator string, index uint64, missed bool) { store := ctx.KVStore(k.storeKey) @@ -63,7 +63,7 @@ func (k Keeper) GetValidatorMissedRoundBitArray(ctx sdk.Context, validator strin return missed.Value } -// GetReportedBlocksWindow sliding window for reporting slashing +// GetReportedRoundsWindow returns the sliding window size for reporting slashing func (k Keeper) GetReportedRoundsWindow(ctx sdk.Context) int64 { return k.GetParams(ctx).Slashing.ReportedRoundsWindow } @@ -73,7 +73,7 @@ func (k Keeper) GetSlashFractionMiss(ctx sdk.Context) (res sdk.Dec) { return k.GetParams(ctx).Slashing.SlashFractionMiss } -// GetSlashFractionMiss fraction of power slashed for missed rounds +// GetSlashFractionMalicious fraction returns the fraction of power slashed for malicious behavior func (k Keeper) GetSlashFractionMalicious(ctx sdk.Context) (res sdk.Dec) { return k.GetParams(ctx).Slashing.SlashFractionMalicious } @@ -88,12 +88,12 @@ func (k Keeper) GetMinReportedPerWindow(ctx sdk.Context) int64 { return params.Slashing.MinReportedPerWindow.MulInt64(reportedRoundsWindow).RoundInt64() } -// MissJailDuration miss unbond duration +// GetMissJailDuration returns the jail duration for a validator who misses reports func (k Keeper) GetMissJailDuration(ctx sdk.Context) (res time.Duration) { return k.GetParams(ctx).Slashing.OracleMissJailDuration } -// MissJailDuration miss unbond duration +// GetMaliciousJailDuration returns the jail duration for malicious validator behavior func (k Keeper) GetMaliciousJailDuration(ctx sdk.Context) (res time.Duration) { return k.GetParams(ctx).Slashing.OracleMaliciousJailDuration } diff --git a/x/oracle/module.go b/x/oracle/module.go index d5a128c10..fee83ff7d 100644 --- a/x/oracle/module.go +++ b/x/oracle/module.go @@ -161,7 +161,7 @@ func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { agc := keeper.GetAggregatorContext(ctx, am.keeper) validatorPowers := agc.GetValidatorPowers() // set validatorReportInfo to track performance - for validator, _ := range validatorPowers { + for validator := range validatorPowers { am.keeper.InitValidatorReportInfo(ctx, validator, ctx.BlockHeight()) } }) diff --git a/x/oracle/types/genesis.pb.go b/x/oracle/types/genesis.pb.go index 7e3e9e917..bd6e7b42a 100644 --- a/x/oracle/types/genesis.pb.go +++ b/x/oracle/types/genesis.pb.go @@ -48,9 +48,9 @@ type GenesisState struct { StakerListAssets []StakerListAssets `protobuf:"bytes,9,rep,name=staker_list_assets,json=stakerListAssets,proto3" json:"staker_list_assets"` // information for slashing history // ValidatorReportInfo records all the validatorReportInfos - ReportInfos []ValidatorReportInfo `protobuf:"bytes,10,rep,name=report_infos,json=reportInfos,proto3" json:"report_infos"` + ValidatorReportInfos []ValidatorReportInfo `protobuf:"bytes,10,rep,name=validator_report_infos,json=validatorReportInfos,proto3" json:"validator_report_infos"` // ValidatorMissedRounds records missedRounds for all validators seen - MissedRounds []ValidatorMissedRounds `protobuf:"bytes,11,rep,name=missed_rounds,json=missedRounds,proto3" json:"missed_rounds"` + ValidatorMissedRounds []ValidatorMissedRounds `protobuf:"bytes,11,rep,name=validator_missed_rounds,json=validatorMissedRounds,proto3" json:"validator_missed_rounds"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -149,16 +149,16 @@ func (m *GenesisState) GetStakerListAssets() []StakerListAssets { return nil } -func (m *GenesisState) GetReportInfos() []ValidatorReportInfo { +func (m *GenesisState) GetValidatorReportInfos() []ValidatorReportInfo { if m != nil { - return m.ReportInfos + return m.ValidatorReportInfos } return nil } -func (m *GenesisState) GetMissedRounds() []ValidatorMissedRounds { +func (m *GenesisState) GetValidatorMissedRounds() []ValidatorMissedRounds { if m != nil { - return m.MissedRounds + return m.ValidatorMissedRounds } return nil } @@ -275,7 +275,9 @@ func (m *StakerListAssets) GetStakerList() *StakerList { // ValidatorMissedRounds record missed rounds indexes for a validator which consAddr corresponding to the address type ValidatorMissedRounds struct { - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // address of validator + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // missed_rounds tells how many rounds this validtor had missed for current windo MissedRounds []*MissedRound `protobuf:"bytes,2,rep,name=missed_rounds,json=missedRounds,proto3" json:"missed_rounds,omitempty"` } @@ -389,50 +391,51 @@ func init() { func init() { proto.RegisterFile("exocore/oracle/v1/genesis.proto", fileDescriptor_6b68ac5b0c7f4305) } var fileDescriptor_6b68ac5b0c7f4305 = []byte{ - // 681 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x94, 0xdd, 0x4e, 0x13, 0x41, - 0x14, 0xc7, 0x5b, 0x3e, 0x5a, 0x38, 0x2d, 0xda, 0x0e, 0x48, 0x16, 0x22, 0x0b, 0x56, 0x54, 0x12, - 0x93, 0xad, 0xe8, 0x85, 0x17, 0x26, 0x06, 0x31, 0xc6, 0x80, 0xa2, 0x66, 0xeb, 0x47, 0x42, 0x62, - 0x36, 0x4b, 0x77, 0x2c, 0x93, 0xb6, 0x3b, 0xcd, 0xcc, 0x50, 0xf1, 0x09, 0xbc, 0xf5, 0xb1, 0xb8, - 0xe4, 0xd2, 0x2b, 0x63, 0xe0, 0x45, 0xcc, 0x9e, 0x99, 0x85, 0xed, 0xee, 0xb6, 0xde, 0xed, 0x9c, - 0xf9, 0x9f, 0xdf, 0x39, 0xf3, 0x3f, 0xb3, 0x03, 0xeb, 0xf4, 0x94, 0xb7, 0xb9, 0xa0, 0x4d, 0x2e, - 0xfc, 0x76, 0x8f, 0x36, 0x87, 0xdb, 0xcd, 0x0e, 0x0d, 0xa9, 0x64, 0xd2, 0x19, 0x08, 0xae, 0x38, - 0xa9, 0x1b, 0x81, 0xa3, 0x05, 0xce, 0x70, 0x7b, 0x75, 0x2b, 0x9b, 0xc3, 0xc2, 0x80, 0x9e, 0x7a, - 0x82, 0xb6, 0x69, 0xa8, 0xbc, 0xbe, 0xec, 0xe8, 0xe4, 0xd5, 0x87, 0xff, 0x51, 0x0e, 0x7c, 0xe1, - 0xf7, 0x4d, 0xa5, 0xd5, 0xcd, 0xac, 0x38, 0xf4, 0x15, 0x1b, 0x52, 0x4f, 0xf1, 0x2e, 0x0d, 0x8d, - 0xca, 0xce, 0xaa, 0x46, 0x28, 0x79, 0xfb, 0x82, 0xb5, 0x69, 0xbc, 0xdf, 0xc8, 0xee, 0x67, 0xda, - 0xbe, 0x37, 0x56, 0x33, 0x52, 0x6a, 0x23, 0x2b, 0x93, 0x3d, 0x5f, 0x1e, 0xb3, 0x30, 0x06, 0x39, - 0x59, 0xc5, 0xd0, 0xef, 0xb1, 0xc0, 0x57, 0x5c, 0x78, 0x27, 0x83, 0xc0, 0x57, 0xd4, 0x3b, 0xea, - 0xf1, 0x76, 0xd7, 0xe8, 0x97, 0x3a, 0xbc, 0xc3, 0xf1, 0xb3, 0x19, 0x7d, 0xe9, 0x68, 0xe3, 0x67, - 0x19, 0xaa, 0xaf, 0xf5, 0x50, 0x5a, 0xca, 0x57, 0x94, 0x3c, 0x85, 0x92, 0x6e, 0xc4, 0x2a, 0x6e, - 0x14, 0xb7, 0x2a, 0x8f, 0x57, 0x9c, 0xcc, 0x90, 0x9c, 0x0f, 0x28, 0xd8, 0x9d, 0x39, 0xfb, 0xb3, - 0x5e, 0x70, 0x8d, 0x9c, 0xec, 0x40, 0x45, 0x9b, 0xe1, 0xf5, 0x98, 0x54, 0xd6, 0xd4, 0xc6, 0xf4, - 0xb8, 0x6c, 0x54, 0x99, 0x6c, 0xd0, 0x39, 0x6f, 0x99, 0x54, 0xe4, 0x2b, 0x2c, 0xe7, 0x9f, 0xc0, - 0x9a, 0xc6, 0x56, 0x1e, 0xe4, 0xc0, 0x3e, 0xc7, 0x09, 0x9f, 0x50, 0xbf, 0x1b, 0xc9, 0xdd, 0xa5, - 0x61, 0x4e, 0x94, 0x7c, 0x84, 0xc5, 0x9c, 0x0b, 0x62, 0xcd, 0x20, 0x7b, 0x33, 0x87, 0xbd, 0x17, - 0xa9, 0x5d, 0x14, 0xeb, 0x13, 0xbb, 0x75, 0x96, 0x0e, 0x91, 0x37, 0x50, 0x4b, 0x5f, 0x50, 0x6b, - 0x16, 0x91, 0x77, 0x26, 0x23, 0x0f, 0x64, 0xc7, 0xbd, 0xc1, 0x46, 0xd6, 0x64, 0x1f, 0x6e, 0x5e, - 0x63, 0xb4, 0x8f, 0x25, 0xf4, 0xf1, 0x76, 0x0e, 0xeb, 0x2a, 0xcd, 0x58, 0xb9, 0x20, 0xe2, 0x00, - 0xba, 0xd9, 0x02, 0x32, 0x72, 0x50, 0x8d, 0x2b, 0x23, 0x6e, 0x7d, 0x2c, 0x6e, 0x64, 0xb4, 0x35, - 0x91, 0x88, 0x21, 0xf4, 0x10, 0x16, 0xa5, 0xf2, 0xbb, 0x54, 0x78, 0x2c, 0xfc, 0xc6, 0xa5, 0xe7, - 0x4b, 0x49, 0x95, 0xb4, 0xe6, 0x90, 0x9a, 0xe7, 0x61, 0x0b, 0xd5, 0x7b, 0x91, 0xf8, 0x05, 0x6a, - 0x0d, 0xba, 0x2e, 0xd3, 0x1b, 0xe4, 0x0b, 0x10, 0xc3, 0x8e, 0x3a, 0x8d, 0xd1, 0xf3, 0x88, 0xbe, - 0x3b, 0x16, 0x1d, 0xb5, 0x35, 0x42, 0xae, 0xc9, 0x54, 0x9c, 0xbc, 0x87, 0xaa, 0xa0, 0x03, 0x2e, - 0x94, 0x6e, 0xda, 0x02, 0x44, 0xde, 0x9f, 0x74, 0x9b, 0x5c, 0xd4, 0x47, 0xdd, 0x19, 0x6a, 0x45, - 0x5c, 0x45, 0x24, 0x69, 0xc1, 0x42, 0x9f, 0x49, 0x49, 0x03, 0x4f, 0xf0, 0x93, 0x30, 0x90, 0x56, - 0x05, 0x89, 0x5b, 0x93, 0x88, 0x07, 0x98, 0xe0, 0xa2, 0xde, 0x30, 0xab, 0xfd, 0x44, 0xac, 0x31, - 0x80, 0x7a, 0xc6, 0x2c, 0xb2, 0x02, 0x73, 0xe8, 0x83, 0xc7, 0x02, 0xfc, 0x1f, 0xe7, 0xdd, 0x32, - 0xae, 0xf7, 0x02, 0xb2, 0x03, 0xd5, 0xe4, 0x28, 0xcc, 0x0f, 0xb7, 0x36, 0x71, 0x06, 0x6e, 0x25, - 0x61, 0x7b, 0xa3, 0x0f, 0xb5, 0xb4, 0x87, 0x93, 0x0a, 0x3e, 0x87, 0x4a, 0x62, 0x3e, 0xd6, 0x14, - 0x5e, 0xf2, 0xb5, 0x89, 0x83, 0x71, 0xe1, 0x7a, 0x18, 0x8d, 0x21, 0xdc, 0xca, 0x75, 0x83, 0x58, - 0x50, 0xf6, 0x83, 0x40, 0x50, 0x29, 0xaf, 0x4a, 0xea, 0x25, 0x79, 0x99, 0x36, 0x5a, 0x1f, 0xd2, - 0xce, 0x29, 0x9a, 0x20, 0xa6, 0x8c, 0x7d, 0x06, 0x95, 0xc4, 0x26, 0x59, 0x82, 0x59, 0xfc, 0xeb, - 0xb0, 0xd6, 0xb4, 0xab, 0x17, 0x64, 0x19, 0x4a, 0x3a, 0x09, 0xcf, 0x35, 0xe7, 0x9a, 0xd5, 0xee, - 0xfe, 0xd9, 0x85, 0x5d, 0x3c, 0xbf, 0xb0, 0x8b, 0x7f, 0x2f, 0xec, 0xe2, 0xaf, 0x4b, 0xbb, 0x70, - 0x7e, 0x69, 0x17, 0x7e, 0x5f, 0xda, 0x85, 0xc3, 0x47, 0x1d, 0xa6, 0x8e, 0x4f, 0x8e, 0x9c, 0x36, - 0xef, 0x37, 0x5f, 0xe9, 0x76, 0xde, 0x51, 0xf5, 0x9d, 0x8b, 0x6e, 0x33, 0x7e, 0x99, 0x4f, 0xe3, - 0xb7, 0x59, 0xfd, 0x18, 0x50, 0x79, 0x54, 0xc2, 0x27, 0xf7, 0xc9, 0xbf, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xb7, 0x4f, 0x3f, 0x85, 0x18, 0x07, 0x00, 0x00, + // 691 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x94, 0xdd, 0x6e, 0xd3, 0x30, + 0x14, 0xc7, 0xdb, 0x7d, 0xb4, 0xdb, 0xe9, 0x06, 0xad, 0xf7, 0x41, 0x36, 0xb1, 0x6c, 0x94, 0x01, + 0x93, 0x90, 0x52, 0x06, 0x17, 0x5c, 0x20, 0xa1, 0x31, 0x84, 0xd0, 0x06, 0x43, 0x28, 0xe3, 0x43, + 0x9a, 0x84, 0xa2, 0xb4, 0xf1, 0x3a, 0xab, 0x6d, 0x5c, 0xd9, 0x5e, 0x18, 0x6f, 0xc1, 0x8b, 0xf0, + 0x1e, 0xbb, 0xdc, 0x25, 0x57, 0x08, 0xad, 0x2f, 0x82, 0x72, 0x9c, 0xac, 0x49, 0x93, 0x96, 0xbb, + 0xd8, 0xe7, 0x7f, 0x7e, 0xe7, 0xf8, 0x7f, 0xec, 0xc0, 0x26, 0xbd, 0xe0, 0x2d, 0x2e, 0x68, 0x83, + 0x0b, 0xb7, 0xd5, 0xa5, 0x8d, 0x60, 0xb7, 0xd1, 0xa6, 0x3e, 0x95, 0x4c, 0x5a, 0x7d, 0xc1, 0x15, + 0x27, 0xb5, 0x48, 0x60, 0x69, 0x81, 0x15, 0xec, 0xae, 0xef, 0x64, 0x73, 0x98, 0xef, 0xd1, 0x0b, + 0x47, 0xd0, 0x16, 0xf5, 0x95, 0xd3, 0x93, 0x6d, 0x9d, 0xbc, 0xfe, 0xf8, 0x3f, 0xca, 0xbe, 0x2b, + 0xdc, 0x5e, 0x54, 0x69, 0x7d, 0x3b, 0x2b, 0xf6, 0x5d, 0xc5, 0x02, 0xea, 0x28, 0xde, 0xa1, 0x7e, + 0xa4, 0x32, 0xb3, 0xaa, 0x14, 0x25, 0x2f, 0x2e, 0x58, 0x8b, 0xc6, 0xf1, 0x7a, 0x36, 0x9e, 0x69, + 0xfb, 0xc1, 0x58, 0x4d, 0xaa, 0xd4, 0x56, 0x56, 0x26, 0xbb, 0xae, 0x3c, 0x63, 0x7e, 0x0c, 0xb2, + 0xb2, 0x8a, 0xc0, 0xed, 0x32, 0xcf, 0x55, 0x5c, 0x38, 0xe7, 0x7d, 0xcf, 0x55, 0xd4, 0x69, 0x76, + 0x79, 0xab, 0x13, 0xe9, 0x97, 0xdb, 0xbc, 0xcd, 0xf1, 0xb3, 0x11, 0x7e, 0xe9, 0xdd, 0xfa, 0xaf, + 0x32, 0x2c, 0xbc, 0xd5, 0x43, 0x39, 0x56, 0xae, 0xa2, 0xe4, 0x39, 0x94, 0x74, 0x23, 0x46, 0x71, + 0xab, 0xb8, 0x53, 0x79, 0xba, 0x66, 0x65, 0x86, 0x64, 0x7d, 0x44, 0xc1, 0xfe, 0xcc, 0xe5, 0x9f, + 0xcd, 0x82, 0x1d, 0xc9, 0xc9, 0x1e, 0x54, 0xb4, 0x19, 0x4e, 0x97, 0x49, 0x65, 0x4c, 0x6d, 0x4d, + 0x8f, 0xcb, 0x46, 0x55, 0x94, 0x0d, 0x3a, 0xe7, 0x3d, 0x93, 0x8a, 0x7c, 0x83, 0xd5, 0xfc, 0x13, + 0x18, 0xd3, 0xd8, 0xca, 0xa3, 0x1c, 0xd8, 0x97, 0x38, 0xe1, 0x33, 0xea, 0xf7, 0x43, 0xb9, 0xbd, + 0x1c, 0xe4, 0xec, 0x92, 0x4f, 0xb0, 0x94, 0x73, 0x41, 0x8c, 0x19, 0x64, 0x6f, 0xe7, 0xb0, 0x0f, + 0x42, 0xb5, 0x8d, 0x62, 0x7d, 0x62, 0xbb, 0xc6, 0x46, 0xb7, 0xc8, 0x3b, 0xa8, 0x8e, 0x5e, 0x50, + 0x63, 0x16, 0x91, 0xf7, 0x26, 0x23, 0x8f, 0x64, 0xdb, 0xbe, 0xc5, 0x52, 0x6b, 0x72, 0x08, 0xb7, + 0x87, 0x18, 0xed, 0x63, 0x09, 0x7d, 0xbc, 0x9b, 0xc3, 0xba, 0x49, 0x8b, 0xac, 0x5c, 0x14, 0xf1, + 0x06, 0xba, 0x79, 0x0c, 0x24, 0x75, 0x50, 0x8d, 0x2b, 0x23, 0x6e, 0x73, 0x2c, 0x2e, 0x35, 0xda, + 0xaa, 0x48, 0xec, 0x21, 0xf4, 0x04, 0x96, 0xa4, 0x72, 0x3b, 0x54, 0x38, 0xcc, 0x3f, 0xe5, 0xd2, + 0x71, 0xa5, 0xa4, 0x4a, 0x1a, 0x73, 0x48, 0xcd, 0xf3, 0xf0, 0x18, 0xd5, 0x07, 0xa1, 0xf8, 0x15, + 0x6a, 0x23, 0x74, 0x4d, 0x8e, 0x06, 0xc8, 0x57, 0x20, 0x11, 0x3b, 0xec, 0x34, 0x46, 0xcf, 0x23, + 0xfa, 0xfe, 0x58, 0x74, 0xd8, 0x56, 0x8a, 0x5c, 0x95, 0x23, 0xfb, 0xa4, 0x99, 0xbc, 0x57, 0x82, + 0xf6, 0xb9, 0x50, 0xba, 0x7d, 0x03, 0x10, 0xfe, 0x70, 0xd2, 0xbd, 0xb2, 0x51, 0x1f, 0xf6, 0x19, + 0xf1, 0x87, 0x97, 0x6b, 0x18, 0x92, 0xe4, 0x14, 0xee, 0x0c, 0x6b, 0xf4, 0x98, 0x94, 0xd4, 0x73, + 0x04, 0x3f, 0xf7, 0x3d, 0x69, 0x54, 0xb0, 0xc8, 0xce, 0xa4, 0x22, 0x47, 0x98, 0x60, 0xa3, 0x3e, + 0x2a, 0xb3, 0x12, 0xe4, 0x05, 0xeb, 0x7d, 0xa8, 0x65, 0x2c, 0x25, 0x6b, 0x30, 0x87, 0x6e, 0x39, + 0xcc, 0xc3, 0x57, 0x3b, 0x6f, 0x97, 0x71, 0x7d, 0xe0, 0x91, 0x3d, 0x58, 0x48, 0x0e, 0x2c, 0x7a, + 0x96, 0x1b, 0x13, 0x27, 0x65, 0x57, 0x12, 0xc3, 0xa9, 0xf7, 0xa0, 0x3a, 0xea, 0xf4, 0xa4, 0x82, + 0x2f, 0xa1, 0x92, 0x98, 0xa2, 0x31, 0x85, 0x4f, 0x61, 0x63, 0xe2, 0xf8, 0x6c, 0x18, 0x8e, 0xac, + 0x1e, 0xc0, 0x4a, 0xae, 0x2d, 0xc4, 0x80, 0xb2, 0xeb, 0x79, 0x82, 0x4a, 0x79, 0x53, 0x52, 0x2f, + 0xc9, 0x6b, 0x58, 0x4c, 0x3b, 0xae, 0x0f, 0x69, 0xe6, 0x14, 0x4d, 0x10, 0xed, 0x85, 0x5e, 0xd2, + 0xd8, 0x17, 0x50, 0x49, 0x04, 0xc9, 0x32, 0xcc, 0xe2, 0xdb, 0xc4, 0x5a, 0xd3, 0xb6, 0x5e, 0x90, + 0x55, 0x28, 0xe9, 0x24, 0x3c, 0xd7, 0x9c, 0x1d, 0xad, 0xf6, 0x0f, 0x2f, 0xaf, 0xcd, 0xe2, 0xd5, + 0xb5, 0x59, 0xfc, 0x7b, 0x6d, 0x16, 0x7f, 0x0e, 0xcc, 0xc2, 0xd5, 0xc0, 0x2c, 0xfc, 0x1e, 0x98, + 0x85, 0x93, 0x27, 0x6d, 0xa6, 0xce, 0xce, 0x9b, 0x56, 0x8b, 0xf7, 0x1a, 0x6f, 0x74, 0x3b, 0x1f, + 0xa8, 0xfa, 0xce, 0x45, 0xa7, 0x11, 0xff, 0xbf, 0x2f, 0xe2, 0x3f, 0xb8, 0xfa, 0xd1, 0xa7, 0xb2, + 0x59, 0xc2, 0x1f, 0xf3, 0xb3, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa7, 0xe5, 0x58, 0x7c, 0x3e, + 0x07, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -455,10 +458,10 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.MissedRounds) > 0 { - for iNdEx := len(m.MissedRounds) - 1; iNdEx >= 0; iNdEx-- { + if len(m.ValidatorMissedRounds) > 0 { + for iNdEx := len(m.ValidatorMissedRounds) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.MissedRounds[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.ValidatorMissedRounds[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -469,10 +472,10 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x5a } } - if len(m.ReportInfos) > 0 { - for iNdEx := len(m.ReportInfos) - 1; iNdEx >= 0; iNdEx-- { + if len(m.ValidatorReportInfos) > 0 { + for iNdEx := len(m.ValidatorReportInfos) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.ReportInfos[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.ValidatorReportInfos[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -831,14 +834,14 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } - if len(m.ReportInfos) > 0 { - for _, e := range m.ReportInfos { + if len(m.ValidatorReportInfos) > 0 { + for _, e := range m.ValidatorReportInfos { l = e.Size() n += 1 + l + sovGenesis(uint64(l)) } } - if len(m.MissedRounds) > 0 { - for _, e := range m.MissedRounds { + if len(m.ValidatorMissedRounds) > 0 { + for _, e := range m.ValidatorMissedRounds { l = e.Size() n += 1 + l + sovGenesis(uint64(l)) } @@ -1264,7 +1267,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 10: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ReportInfos", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorReportInfos", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1291,14 +1294,14 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ReportInfos = append(m.ReportInfos, ValidatorReportInfo{}) - if err := m.ReportInfos[len(m.ReportInfos)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.ValidatorReportInfos = append(m.ValidatorReportInfos, ValidatorReportInfo{}) + if err := m.ValidatorReportInfos[len(m.ValidatorReportInfos)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex case 11: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MissedRounds", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorMissedRounds", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1325,8 +1328,8 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.MissedRounds = append(m.MissedRounds, ValidatorMissedRounds{}) - if err := m.MissedRounds[len(m.MissedRounds)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.ValidatorMissedRounds = append(m.ValidatorMissedRounds, ValidatorMissedRounds{}) + if err := m.ValidatorMissedRounds[len(m.ValidatorMissedRounds)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/x/oracle/types/params.go b/x/oracle/types/params.go index 6cef546e8..1e72de69e 100644 --- a/x/oracle/types/params.go +++ b/x/oracle/types/params.go @@ -146,12 +146,23 @@ func (p Params) Validate() error { return ErrInvalidParams.Wrap("slashing params must not be nil") } - if slashing.ReportedRoundsWindow < 1 || - slashing.MinReportedPerWindow.GT(oneDec) || !slashing.MinReportedPerWindow.IsPositive() || - slashing.SlashFractionMiss.GT(oneDec) || !slashing.SlashFractionMiss.IsPositive() || - slashing.SlashFractionMalicious.GT(oneDec) || !slashing.SlashFractionMalicious.IsPositive() || - slashing.OracleMissJailDuration <= 0 || slashing.OracleMaliciousJailDuration <= 0 { - return ErrInvalidParams.Wrapf("invalid slashing params: reported_window/min_reported_per_window/oracle_miss_jail_duration/oracle_malicious_jail_duration/slash_fraction_miss/slash_fraction_malicious:%v,%v,%v,%v,%v,%v", slashing.ReportedRoundsWindow, slashing.MinReportedPerWindow, slashing.OracleMissJailDuration, slashing.OracleMaliciousJailDuration, slashing.SlashFractionMiss, slashing.SlashFractionMalicious) + if slashing.ReportedRoundsWindow < 1 { + return ErrInvalidParams.Wrapf("ReportedRoundsWindow must be at least 1, got %d", slashing.ReportedRoundsWindow) + } + if slashing.MinReportedPerWindow.GT(oneDec) || !slashing.MinReportedPerWindow.IsPositive() { + return ErrInvalidParams.Wrapf("MinReportedPerWindow must be in (0, 1], got %v", slashing.MinReportedPerWindow) + } + if slashing.SlashFractionMiss.GT(oneDec) || !slashing.SlashFractionMiss.IsPositive() { + return ErrInvalidParams.Wrapf("SlashFractionMiss must be in (0, 1], got %v", slashing.SlashFractionMiss) + } + if slashing.SlashFractionMalicious.GT(oneDec) || !slashing.SlashFractionMalicious.IsPositive() { + return ErrInvalidParams.Wrapf("SlashFractionMalicious must be in (0, 1], got %v", slashing.SlashFractionMalicious) + } + if slashing.OracleMissJailDuration <= 0 { + return ErrInvalidParams.Wrapf("OracleMissJailDuration must be positive, got %v", slashing.OracleMissJailDuration) + } + if slashing.OracleMaliciousJailDuration <= 0 { + return ErrInvalidParams.Wrapf("OracleMaliciousJailDuration must be positive, got %v", slashing.OracleMaliciousJailDuration) } // validate tokenFeeders diff --git a/x/oracle/types/slashing.pb.go b/x/oracle/types/slashing.pb.go index d61331489..31dfc7395 100644 --- a/x/oracle/types/slashing.pb.go +++ b/x/oracle/types/slashing.pb.go @@ -22,11 +22,16 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// ValidatorReportInfo represents the information to describe the miss status of a validator reporting prices type ValidatorReportInfo struct { - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` - StartHeight int64 `protobuf:"varint,2,opt,name=startHeight,proto3" json:"startHeight,omitempty"` - IndexOffset int64 `protobuf:"varint,3,opt,name=index_offset,json=indexOffset,proto3" json:"index_offset,omitempty"` - MissedRoundsCounter int64 `protobuf:"varint,4,opt,name=missed_rounds_counter,json=missedRoundsCounter,proto3" json:"missed_rounds_counter,omitempty"` + // address of the validtor + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // start_height for the performance round of the configured window of rounds + StartHeight int64 `protobuf:"varint,2,opt,name=start_height,json=startHeight,proto3" json:"start_height,omitempty"` + // index_offset track the offset of current window + IndexOffset int64 `protobuf:"varint,3,opt,name=index_offset,json=indexOffset,proto3" json:"index_offset,omitempty"` + // missed_rounds_counter counts the number of missed rounds for this window + MissedRoundsCounter int64 `protobuf:"varint,4,opt,name=missed_rounds_counter,json=missedRoundsCounter,proto3" json:"missed_rounds_counter,omitempty"` } func (m *ValidatorReportInfo) Reset() { *m = ValidatorReportInfo{} } @@ -98,23 +103,23 @@ func init() { proto.RegisterFile("exocore/oracle/v1/slashing.proto", fileDescrip var fileDescriptor_27165252f41a09d2 = []byte{ // 260 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0x31, 0x4e, 0x84, 0x40, - 0x14, 0x86, 0x19, 0xd7, 0x68, 0x1c, 0x6d, 0x64, 0x63, 0x42, 0x35, 0x41, 0xab, 0xad, 0xc0, 0xd5, - 0x1b, 0x68, 0x4c, 0xd4, 0x42, 0x13, 0x0a, 0x0b, 0x1b, 0x32, 0xcb, 0x3c, 0x60, 0x22, 0xcb, 0x23, - 0x33, 0x8f, 0x15, 0x6f, 0xe1, 0x31, 0x3c, 0x8a, 0xe5, 0x96, 0x96, 0x06, 0x2e, 0x62, 0xc2, 0x48, - 0xb2, 0xe5, 0xfb, 0xbf, 0xaf, 0x79, 0x1f, 0x0f, 0xa1, 0xc3, 0x0c, 0x0d, 0xc4, 0x68, 0x64, 0x56, - 0x41, 0xbc, 0x59, 0xc6, 0xb6, 0x92, 0xb6, 0xd4, 0x75, 0x11, 0x35, 0x06, 0x09, 0xfd, 0xd3, 0x7f, - 0x23, 0x72, 0x46, 0xb4, 0x59, 0x5e, 0x7c, 0x31, 0x3e, 0x7f, 0x91, 0x95, 0x56, 0x92, 0xd0, 0x24, - 0xd0, 0xa0, 0xa1, 0x87, 0x3a, 0x47, 0x3f, 0xe0, 0x87, 0x52, 0x29, 0x03, 0xd6, 0x06, 0x2c, 0x64, - 0x8b, 0xa3, 0x64, 0x3a, 0xfd, 0x90, 0x1f, 0x5b, 0x92, 0x86, 0xee, 0x41, 0x17, 0x25, 0x05, 0x7b, - 0x21, 0x5b, 0xcc, 0x92, 0xdd, 0xc9, 0x3f, 0xe7, 0x27, 0xba, 0x56, 0xd0, 0xa5, 0x98, 0xe7, 0x16, - 0x28, 0x98, 0x39, 0x65, 0xdc, 0x9e, 0xc7, 0xc9, 0xbf, 0xe2, 0x67, 0x6b, 0x6d, 0x2d, 0xa8, 0xd4, - 0x60, 0x5b, 0x2b, 0x9b, 0x66, 0xd8, 0xd6, 0x04, 0x26, 0xd8, 0x1f, 0xdd, 0xb9, 0x83, 0xc9, 0xc8, - 0x6e, 0x1d, 0xba, 0x79, 0xfc, 0xee, 0x05, 0xdb, 0xf6, 0x82, 0xfd, 0xf6, 0x82, 0x7d, 0x0e, 0xc2, - 0xdb, 0x0e, 0xc2, 0xfb, 0x19, 0x84, 0xf7, 0x7a, 0x59, 0x68, 0x2a, 0xdb, 0x55, 0x94, 0xe1, 0x3a, - 0xbe, 0x73, 0x2f, 0x3e, 0x01, 0xbd, 0xa3, 0x79, 0x8b, 0xa7, 0x26, 0xdd, 0x54, 0x85, 0x3e, 0x1a, - 0xb0, 0xab, 0x83, 0x31, 0xc8, 0xf5, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe4, 0xb2, 0x22, 0x5e, - 0x34, 0x01, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x34, 0x90, 0x31, 0x4e, 0x84, 0x40, + 0x14, 0x86, 0x19, 0xd7, 0x68, 0x44, 0x1b, 0xd9, 0x98, 0x50, 0x4d, 0xd0, 0x6a, 0x2b, 0x70, 0xf5, + 0x06, 0x1a, 0x13, 0xb5, 0xd0, 0x84, 0xc2, 0xc2, 0x86, 0xcc, 0x32, 0x0f, 0x98, 0xc8, 0xf2, 0xc8, + 0xcc, 0x63, 0xc5, 0x5b, 0x78, 0x0d, 0x6f, 0x62, 0xb9, 0xa5, 0xa5, 0x81, 0x8b, 0x18, 0x67, 0x96, + 0xf2, 0x7d, 0xff, 0xd7, 0xbc, 0xcf, 0x8f, 0xa0, 0xc7, 0x1c, 0x35, 0x24, 0xa8, 0x45, 0x5e, 0x43, + 0xb2, 0x59, 0x26, 0xa6, 0x16, 0xa6, 0x52, 0x4d, 0x19, 0xb7, 0x1a, 0x09, 0x83, 0xd3, 0x9d, 0x11, + 0x3b, 0x23, 0xde, 0x2c, 0x2f, 0xbe, 0x98, 0x3f, 0x7f, 0x11, 0xb5, 0x92, 0x82, 0x50, 0xa7, 0xd0, + 0xa2, 0xa6, 0x87, 0xa6, 0xc0, 0x20, 0xf4, 0x0f, 0x85, 0x94, 0x1a, 0x8c, 0x09, 0x59, 0xc4, 0x16, + 0x47, 0xe9, 0x74, 0x06, 0xe7, 0xfe, 0x89, 0x21, 0xa1, 0x29, 0xab, 0x40, 0x95, 0x15, 0x85, 0x7b, + 0x11, 0x5b, 0xcc, 0xd2, 0x63, 0xcb, 0xee, 0x2d, 0xfa, 0x57, 0x54, 0x23, 0xa1, 0xcf, 0xb0, 0x28, + 0x0c, 0x50, 0x38, 0x73, 0x8a, 0x65, 0xcf, 0x16, 0x05, 0x57, 0xfe, 0xd9, 0x5a, 0x19, 0x03, 0x32, + 0xd3, 0xd8, 0x35, 0xd2, 0x64, 0x39, 0x76, 0x0d, 0x81, 0x0e, 0xf7, 0xad, 0x3b, 0x77, 0x63, 0x6a, + 0xb7, 0x5b, 0x37, 0xdd, 0x3c, 0x7e, 0x0f, 0x9c, 0x6d, 0x07, 0xce, 0x7e, 0x07, 0xce, 0x3e, 0x47, + 0xee, 0x6d, 0x47, 0xee, 0xfd, 0x8c, 0xdc, 0x7b, 0xbd, 0x2c, 0x15, 0x55, 0xdd, 0x2a, 0xce, 0x71, + 0x9d, 0xdc, 0xb9, 0x1f, 0x9f, 0x80, 0xde, 0x51, 0xbf, 0x25, 0x53, 0x94, 0x7e, 0xca, 0x42, 0x1f, + 0x2d, 0x98, 0xd5, 0x81, 0x2d, 0x72, 0xfd, 0x17, 0x00, 0x00, 0xff, 0xff, 0xfc, 0xb6, 0xd0, 0xba, + 0x35, 0x01, 0x00, 0x00, } func (m *ValidatorReportInfo) Marshal() (dAtA []byte, err error) { From fcf393f0d14cfe0d7a8d11f9d8525f6625b803de Mon Sep 17 00:00:00 2001 From: leonz789 Date: Fri, 8 Nov 2024 18:44:52 +0800 Subject: [PATCH 11/22] lint --- x/oracle/keeper/aggregator/context.go | 2 +- x/oracle/keeper/aggregator/worker.go | 7 +------ x/oracle/keeper/slashing.go | 1 - 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/x/oracle/keeper/aggregator/context.go b/x/oracle/keeper/aggregator/context.go index aed919073..215fa06e8 100644 --- a/x/oracle/keeper/aggregator/context.go +++ b/x/oracle/keeper/aggregator/context.go @@ -211,7 +211,7 @@ func (agc *AggregatorContext) NewCreatePrice(_ sdk.Context, msg *types.MsgCreate // returns: 1st successful sealed, need to be written to KVStore, 2nd: failed sealed tokenID, use previous price to write to KVStore func (agc *AggregatorContext) SealRound(ctx sdk.Context, force bool) (success []*PriceItemKV, failed []uint64, sealed []uint64, windowClosed []uint64) { feederIDs := make([]uint64, 0, len(agc.rounds)) - for fID, _ := range agc.rounds { + for fID := range agc.rounds { feederIDs = append(feederIDs, fID) } sort.Slice(feederIDs, func(i, j int) bool { diff --git a/x/oracle/keeper/aggregator/worker.go b/x/oracle/keeper/aggregator/worker.go index 191acf419..9662316e0 100644 --- a/x/oracle/keeper/aggregator/worker.go +++ b/x/oracle/keeper/aggregator/worker.go @@ -38,13 +38,8 @@ func newRecordMsg() recordMsg { return make(map[recordKey][]*types.PriceTimeDetID) } -func (r recordMsg) has(validator string, feederID, sourceID uint64) bool { - _, ok := r[recordKey{validator, feederID, sourceID}] - return ok -} - func (r recordMsg) get(validator string, feederID, sourceID uint64) []*types.PriceTimeDetID { - v, _ := r[recordKey{validator, feederID, sourceID}] + v := r[recordKey{validator, feederID, sourceID}] return v } diff --git a/x/oracle/keeper/slashing.go b/x/oracle/keeper/slashing.go index 804f00b3c..f733fb17f 100644 --- a/x/oracle/keeper/slashing.go +++ b/x/oracle/keeper/slashing.go @@ -115,7 +115,6 @@ func (k Keeper) IterateValidatorReportInfos(ctx sdk.Context, handler func(addres } func (k Keeper) IterateValidatorMissedRoundBitArray(ctx sdk.Context, validator string, handler func(index int64, missed bool) (stop bool)) { - // store := prefix.NewStore(ctx.KVStore(k.storeKey), types.SlashingMissedBitArrayPrefix(validator)) store := ctx.KVStore(k.storeKey) index := int64(0) // Array may be sparse From 9a3f4e62ea5ad76e06d2241a390345dcb7fdb8c5 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Fri, 8 Nov 2024 19:17:11 +0800 Subject: [PATCH 12/22] lint, optimize --- proto/exocore/oracle/v1/genesis.proto | 3 + proto/exocore/oracle/v1/params.proto | 10 ++- x/oracle/keeper/aggregator/context.go | 12 ++- x/oracle/keeper/slashing.go | 23 +++--- x/oracle/module.go | 2 +- x/oracle/types/genesis.pb.go | 7 +- x/oracle/types/params.pb.go | 114 ++++++++++++++------------ 7 files changed, 98 insertions(+), 73 deletions(-) diff --git a/proto/exocore/oracle/v1/genesis.proto b/proto/exocore/oracle/v1/genesis.proto index 5d8065e33..45b725f30 100644 --- a/proto/exocore/oracle/v1/genesis.proto +++ b/proto/exocore/oracle/v1/genesis.proto @@ -73,7 +73,10 @@ message ValidatorMissedRounds { repeated MissedRound missed_rounds = 2; } +// MissedRound records if round with index is missed message MissedRound { + // index of the round in current window int64 index = 1; + // if this round is missed bool missed = 2; } diff --git a/proto/exocore/oracle/v1/params.proto b/proto/exocore/oracle/v1/params.proto index a7794e0b6..82b9fc6aa 100644 --- a/proto/exocore/oracle/v1/params.proto +++ b/proto/exocore/oracle/v1/params.proto @@ -1,13 +1,13 @@ syntax = "proto3"; package exocore.oracle.v1; +import "amino/amino.proto"; +import "cosmos_proto/cosmos.proto"; import "exocore/oracle/v1/info.proto"; import "exocore/oracle/v1/token_feeder.proto"; import "gogoproto/gogo.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; -import "cosmos_proto/cosmos.proto"; -import "amino/amino.proto"; option go_package = "github.com/ExocoreNetwork/exocore/x/oracle/types"; // Params defines the parameters for the module. @@ -52,21 +52,27 @@ enum ConsensusMode { // slashing related params message SlashingParams { + // reported_rounds_window defines how many rounds included in one window for performance review of missing report int64 reported_rounds_window = 1; + // min_reported_perwindow defines at least how many rounds should be reported, this is a percentage of reported_rounds_window bytes min_reported_per_window = 2 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; + // oracle_miss_jail_duraion defines the duration one validator should be jailed for missing reporting price google.protobuf.Duration oracle_miss_jail_duration = 3 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true, (gogoproto.stdduration) = true]; + // oracle_malicious_jail_duration defines the duratin one validator should be jailed for malicious behavior google.protobuf.Duration oracle_malicious_jail_duration =4 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true, (gogoproto.stdduration) = true]; + // slash_fraction_miss defines the fractino one validator should be punished with thier staked assets for msissing reporting price bytes slash_fraction_miss = 5 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; + // slash_fraction_miss defines the fractino one validator should be punished with thier staked assets for maliciours behavior bytes slash_fraction_malicious = 6 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false, diff --git a/x/oracle/keeper/aggregator/context.go b/x/oracle/keeper/aggregator/context.go index 215fa06e8..de07c913d 100644 --- a/x/oracle/keeper/aggregator/context.go +++ b/x/oracle/keeper/aggregator/context.go @@ -379,11 +379,17 @@ func (agc *AggregatorContext) GetFinalPriceListForFeederIDs(feederIDs []uint64) return ret } -func (agc *AggregatorContext) PerformanceReview(finalPrice *types.AggFinalPrice, validator string) (exist, matched bool) { +// PerformanceReview compare results to decide whether the validator is effective, honest +func (agc *AggregatorContext) PerformanceReview(ctx sdk.Context, finalPrice *types.AggFinalPrice, validator string) (exist, matched bool) { feederWorker := agc.aggregators[finalPrice.FeederID] if feederWorker == nil { - // should not happen - // something wrong happened in the agc, so we just skip this round by treat the validator as effective&honest + // Log unexpected nil feederWorker for debugging + ctx.Logger().Error( + "unexpected nil feederWorker in PerformanceReview", + "feederID", finalPrice.FeederID, + "validator", validator, + ) + // Treat validator as effective & honest to avoid unfair penalties exist = true matched = true return diff --git a/x/oracle/keeper/slashing.go b/x/oracle/keeper/slashing.go index f733fb17f..ded92a318 100644 --- a/x/oracle/keeper/slashing.go +++ b/x/oracle/keeper/slashing.go @@ -1,6 +1,8 @@ package keeper import ( + "encoding/binary" + "fmt" "time" "github.com/ExocoreNetwork/exocore/x/oracle/types" @@ -114,19 +116,18 @@ func (k Keeper) IterateValidatorReportInfos(ctx sdk.Context, handler func(addres iterator.Close() } +// IterateValidatorMissedRoundBitArrray iterates all missed rounds in one performance window of rounds func (k Keeper) IterateValidatorMissedRoundBitArray(ctx sdk.Context, validator string, handler func(index int64, missed bool) (stop bool)) { - store := ctx.KVStore(k.storeKey) - index := int64(0) - // Array may be sparse - for ; index < k.GetReportedRoundsWindow(ctx); index++ { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.SlashingMissedBitArrayPrefix(validator)) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + index := binary.BigEndian.Uint64(iterator.Key()) var missed gogotypes.BoolValue - bz := store.Get(types.SlashingMissedBitArrayKey(validator, uint64(index))) - if bz == nil { - continue + if err := k.cdc.Unmarshal(iterator.Value(), &missed); err != nil { + panic(fmt.Sprintf("failed to unmarshal missed round: %v", err)) } - - k.cdc.MustUnmarshal(bz, &missed) - if handler(index, missed.Value) { + if handler(int64(index), missed.Value) { break } } @@ -141,7 +142,7 @@ func (k Keeper) GetValidatorMissedRounds(ctx sdk.Context, address string) []*typ return missedRounds } -// clearValidatorMissedBlockBitArray deletes every instance of ValidatorMissedBlockBitArray in the store +// ClearValidatorMissedBlockBitArray deletes every instance of ValidatorMissedBlockBitArray in the store func (k Keeper) ClearValidatorMissedRoundBitArray(ctx sdk.Context, validator string) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, types.SlashingMissedBitArrayPrefix(validator)) diff --git a/x/oracle/module.go b/x/oracle/module.go index fee83ff7d..617b8d59b 100644 --- a/x/oracle/module.go +++ b/x/oracle/module.go @@ -211,7 +211,7 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val // TODO: for the round calculation, now only sourceID=1 is used so {feederID, sourceID} have only one value for each feederID which corresponding to one round. // But when we came to multiple sources, we should consider the round corresponding to feedeerID instead of {feederID, sourceID} for _, finalPrice := range agc.GetFinalPriceListForFeederIDs(windowClosed) { - exist, matched := agc.PerformanceReview(finalPrice, validator) + exist, matched := agc.PerformanceReview(ctx, finalPrice, validator) if exist && !matched { // TODO: malicious price, just slash&jail immediately logger.Info( diff --git a/x/oracle/types/genesis.pb.go b/x/oracle/types/genesis.pb.go index bd6e7b42a..d17864e30 100644 --- a/x/oracle/types/genesis.pb.go +++ b/x/oracle/types/genesis.pb.go @@ -328,9 +328,12 @@ func (m *ValidatorMissedRounds) GetMissedRounds() []*MissedRound { return nil } +// MissedRound records if round with index is missed type MissedRound struct { - Index int64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` - Missed bool `protobuf:"varint,2,opt,name=missed,proto3" json:"missed,omitempty"` + // index of the round in current window + Index int64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` + // if this round is missed + Missed bool `protobuf:"varint,2,opt,name=missed,proto3" json:"missed,omitempty"` } func (m *MissedRound) Reset() { *m = MissedRound{} } diff --git a/x/oracle/types/params.pb.go b/x/oracle/types/params.pb.go index 80499d674..688246c55 100644 --- a/x/oracle/types/params.pb.go +++ b/x/oracle/types/params.pb.go @@ -206,12 +206,18 @@ func (m *Params) GetSlashing() *SlashingParams { // slashing related params type SlashingParams struct { - ReportedRoundsWindow int64 `protobuf:"varint,1,opt,name=reported_rounds_window,json=reportedRoundsWindow,proto3" json:"reported_rounds_window,omitempty"` - MinReportedPerWindow github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=min_reported_per_window,json=minReportedPerWindow,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_reported_per_window"` - OracleMissJailDuration time.Duration `protobuf:"bytes,3,opt,name=oracle_miss_jail_duration,json=oracleMissJailDuration,proto3,stdduration" json:"oracle_miss_jail_duration"` - OracleMaliciousJailDuration time.Duration `protobuf:"bytes,4,opt,name=oracle_malicious_jail_duration,json=oracleMaliciousJailDuration,proto3,stdduration" json:"oracle_malicious_jail_duration"` - SlashFractionMiss github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=slash_fraction_miss,json=slashFractionMiss,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_miss"` - SlashFractionMalicious github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=slash_fraction_malicious,json=slashFractionMalicious,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_malicious"` + // reported_rounds_window defines how many rounds included in one window for performance review of missing report + ReportedRoundsWindow int64 `protobuf:"varint,1,opt,name=reported_rounds_window,json=reportedRoundsWindow,proto3" json:"reported_rounds_window,omitempty"` + // min_reported_perwindow defines at least how many rounds should be reported, this is a percentage of reported_rounds_window + MinReportedPerWindow github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=min_reported_per_window,json=minReportedPerWindow,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_reported_per_window"` + // oracle_miss_jail_duraion defines the duration one validator should be jailed for missing reporting price + OracleMissJailDuration time.Duration `protobuf:"bytes,3,opt,name=oracle_miss_jail_duration,json=oracleMissJailDuration,proto3,stdduration" json:"oracle_miss_jail_duration"` + // oracle_malicious_jail_duration defines the duratin one validator should be jailed for malicious behavior + OracleMaliciousJailDuration time.Duration `protobuf:"bytes,4,opt,name=oracle_malicious_jail_duration,json=oracleMaliciousJailDuration,proto3,stdduration" json:"oracle_malicious_jail_duration"` + // slash_fraction_miss defines the fractino one validator should be punished with thier staked assets for msissing reporting price + SlashFractionMiss github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=slash_fraction_miss,json=slashFractionMiss,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_miss"` + // slash_fraction_miss defines the fractino one validator should be punished with thier staked assets for maliciours behavior + SlashFractionMalicious github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=slash_fraction_malicious,json=slashFractionMalicious,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_malicious"` } func (m *SlashingParams) Reset() { *m = SlashingParams{} } @@ -277,58 +283,58 @@ func init() { func init() { proto.RegisterFile("exocore/oracle/v1/params.proto", fileDescriptor_72f39bba4594b794) } var fileDescriptor_72f39bba4594b794 = []byte{ - // 814 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xbf, 0x6f, 0xdb, 0x46, + // 812 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xbf, 0x6f, 0xdb, 0x46, 0x14, 0x16, 0xa3, 0x1f, 0x71, 0x4e, 0x56, 0x1a, 0x5d, 0x5c, 0xf7, 0xa4, 0xb8, 0x14, 0x1b, 0x14, 0x81, 0x10, 0xa0, 0x64, 0x62, 0x65, 0x2a, 0xda, 0xc1, 0xfa, 0x61, 0xc0, 0x01, 0xac, 0x08, 0x54, 0x8d, 0x02, 0x5d, 0x88, 0x13, 0x79, 0x92, 0x2e, 0x26, 0x79, 0xc4, 0x1d, 0x19, 0xab, 0x59, 0xbb, 0x14, 0x99, 0x3a, 0x66, 0x09, 0x50, 0xa0, 0x4b, 0xc7, 0xee, 0xfd, 0x07, 0x32, 0x66, 0x2c, 0x32, - 0xa4, 0x85, 0x3d, 0xf4, 0xdf, 0x28, 0x78, 0x3c, 0xaa, 0x91, 0xac, 0x0c, 0xf1, 0x22, 0xf1, 0xde, - 0xf7, 0x7d, 0xef, 0x7b, 0xef, 0xf1, 0x9e, 0x04, 0x74, 0xb2, 0x60, 0x2e, 0xe3, 0xc4, 0x62, 0x1c, - 0xbb, 0x3e, 0xb1, 0x9e, 0x3d, 0xb4, 0x22, 0xcc, 0x71, 0x20, 0xcc, 0x88, 0xb3, 0x98, 0xc1, 0xba, - 0xc2, 0xcd, 0x0c, 0x37, 0x9f, 0x3d, 0x6c, 0xee, 0x5d, 0x96, 0xd0, 0x70, 0xca, 0x32, 0x41, 0xf3, - 0xcb, 0xcb, 0x68, 0xcc, 0x4e, 0x49, 0xe8, 0x4c, 0x09, 0xf1, 0x08, 0x57, 0xac, 0x9d, 0x19, 0x9b, - 0x31, 0xf9, 0x68, 0xa5, 0x4f, 0x2a, 0xaa, 0xcf, 0x18, 0x9b, 0xf9, 0xc4, 0x92, 0xa7, 0x49, 0x32, - 0xb5, 0xbc, 0x84, 0xe3, 0x98, 0xb2, 0x50, 0xe1, 0xad, 0x75, 0x3c, 0xa6, 0x01, 0x11, 0x31, 0x0e, - 0x22, 0x45, 0x68, 0xb8, 0x4c, 0x04, 0x4c, 0x38, 0x59, 0xe6, 0xec, 0xa0, 0xa0, 0x3a, 0x0e, 0x68, - 0xc8, 0x2c, 0xf9, 0x99, 0x85, 0xee, 0xfe, 0x59, 0x02, 0x95, 0x91, 0x6c, 0x16, 0x3e, 0x00, 0x15, - 0x77, 0x8e, 0x69, 0x28, 0x90, 0x66, 0x14, 0xdb, 0xd5, 0x7d, 0x64, 0x5e, 0xea, 0xdb, 0xec, 0xa5, - 0x04, 0x5b, 0xf1, 0x52, 0x85, 0xec, 0x4b, 0xa0, 0x6b, 0x1f, 0x54, 0x7c, 0x97, 0x12, 0x6c, 0xc5, - 0x83, 0x1d, 0x70, 0x5d, 0xb0, 0x84, 0xbb, 0x44, 0xa0, 0xa2, 0x94, 0x34, 0x36, 0x48, 0xc6, 0x92, - 0x61, 0xe7, 0x4c, 0xd8, 0x01, 0x65, 0x9e, 0xf8, 0x44, 0xa0, 0x92, 0x94, 0x7c, 0xbe, 0x41, 0x62, - 0x27, 0x3e, 0x51, 0xb2, 0x8c, 0x0b, 0x7b, 0xa0, 0xf6, 0xfe, 0xcc, 0x05, 0x2a, 0x4b, 0xb1, 0xfe, - 0xa1, 0x12, 0x0f, 0x25, 0xcd, 0xde, 0x8e, 0xff, 0x3f, 0x08, 0x78, 0x07, 0xdc, 0x08, 0xf0, 0xc2, - 0x09, 0x59, 0xe8, 0x12, 0x54, 0x31, 0xb4, 0x76, 0xd9, 0xde, 0x0a, 0xf0, 0x62, 0x98, 0x9e, 0x61, - 0x0b, 0x54, 0xe3, 0x39, 0x27, 0x62, 0xce, 0x7c, 0xcf, 0xc1, 0xe8, 0xba, 0x84, 0xc1, 0x32, 0x74, - 0xb0, 0x4a, 0x98, 0xa0, 0xad, 0x35, 0x42, 0x17, 0x3e, 0x02, 0xa5, 0x80, 0x79, 0x04, 0xdd, 0x30, - 0xb4, 0xf6, 0xcd, 0x7d, 0x63, 0xd3, 0xbc, 0x59, 0x28, 0x48, 0x28, 0x12, 0x71, 0xcc, 0x3c, 0x62, - 0x4b, 0x36, 0xdc, 0x03, 0x20, 0x2d, 0xca, 0x23, 0xb1, 0x43, 0x3d, 0x04, 0x96, 0x55, 0xf5, 0x49, - 0x7c, 0xe4, 0xc1, 0x7b, 0xe0, 0x93, 0x14, 0x15, 0xf4, 0x39, 0x71, 0x22, 0x4e, 0xd3, 0x49, 0x57, - 0x25, 0xa5, 0x16, 0xe0, 0xc5, 0x98, 0x3e, 0x27, 0x23, 0x19, 0x84, 0xdf, 0x82, 0x2d, 0xe1, 0x63, - 0x31, 0xa7, 0xe1, 0x0c, 0x6d, 0x1b, 0x5a, 0xbb, 0xba, 0xff, 0xc5, 0xa6, 0x57, 0xa1, 0x28, 0xd9, - 0x15, 0xb1, 0x97, 0x92, 0xaf, 0x4b, 0x2f, 0x7f, 0x6d, 0x15, 0xee, 0xbe, 0x2d, 0x81, 0x9b, 0xab, - 0x14, 0xf8, 0x08, 0xec, 0x72, 0x12, 0x31, 0x1e, 0x13, 0xcf, 0xe1, 0x2c, 0x09, 0x3d, 0xe1, 0x9c, - 0xd1, 0xd0, 0x63, 0x67, 0x48, 0x33, 0xb4, 0x76, 0xd1, 0xde, 0xc9, 0x51, 0x5b, 0x82, 0xdf, 0x4b, - 0x0c, 0x3e, 0x05, 0x9f, 0x05, 0x34, 0x74, 0x96, 0xca, 0x88, 0xf0, 0x5c, 0x76, 0xcd, 0xd0, 0xda, - 0xdb, 0xdd, 0xce, 0xeb, 0x77, 0xad, 0xc2, 0xdb, 0x77, 0xad, 0x7b, 0x33, 0x1a, 0xcf, 0x93, 0x89, - 0xe9, 0xb2, 0x40, 0xdd, 0x6d, 0xf5, 0xf5, 0x95, 0xf0, 0x4e, 0xad, 0xf8, 0xc7, 0x88, 0x08, 0xb3, - 0x4f, 0xdc, 0xdf, 0xff, 0xfd, 0xe3, 0xbe, 0x66, 0xef, 0x04, 0x34, 0xb4, 0x55, 0xca, 0x11, 0xe1, - 0xca, 0xcb, 0x05, 0x8d, 0xac, 0x41, 0x27, 0xa0, 0x42, 0x38, 0x4f, 0x31, 0xf5, 0x9d, 0x7c, 0xc9, - 0x50, 0x51, 0x8e, 0xa2, 0x61, 0x66, 0x5b, 0x66, 0xe6, 0x5b, 0x66, 0xf6, 0x15, 0xa1, 0x5b, 0x4b, - 0x0b, 0x79, 0xf9, 0x77, 0x4b, 0xcb, 0x2c, 0x76, 0xb3, 0x54, 0xc7, 0x54, 0x88, 0xc7, 0x98, 0xfa, - 0x39, 0x0d, 0x06, 0x40, 0xcf, 0x4d, 0xb0, 0x4f, 0x5d, 0xca, 0x92, 0x75, 0xa7, 0xd2, 0x47, 0x3a, - 0xdd, 0x51, 0x4e, 0x79, 0xba, 0x15, 0x3b, 0x17, 0xdc, 0x96, 0xaf, 0xc6, 0x99, 0x72, 0xec, 0xa6, - 0x11, 0xd9, 0x1b, 0x2a, 0x5f, 0x7d, 0x76, 0x75, 0x99, 0xef, 0x50, 0xa5, 0x4b, 0xfb, 0x83, 0x01, - 0x40, 0xeb, 0x26, 0x79, 0x31, 0x72, 0x39, 0xae, 0xe8, 0xb4, 0xbb, 0xea, 0x94, 0xa7, 0xbc, 0xff, - 0x93, 0x06, 0x6a, 0x2b, 0xf7, 0x1f, 0x7e, 0x03, 0x9a, 0xbd, 0x27, 0xc3, 0xf1, 0x60, 0x38, 0x3e, - 0x19, 0x3b, 0xc7, 0x4f, 0xfa, 0x03, 0xe7, 0x64, 0x38, 0x1e, 0x0d, 0x7a, 0x47, 0x87, 0x47, 0x83, - 0xfe, 0xad, 0x42, 0x73, 0xef, 0xc5, 0x2b, 0x03, 0xad, 0x48, 0x4e, 0x42, 0x11, 0x11, 0x97, 0x4e, - 0x29, 0xf1, 0xa0, 0x09, 0x6e, 0xaf, 0xa9, 0x0f, 0xc6, 0x07, 0xa3, 0x5b, 0x5a, 0xf3, 0xd3, 0x17, - 0xaf, 0x8c, 0xfa, 0x8a, 0x2c, 0x05, 0x9a, 0xa5, 0x9f, 0x7f, 0xd3, 0x0b, 0xdd, 0xc7, 0xaf, 0xcf, - 0x75, 0xed, 0xcd, 0xb9, 0xae, 0xfd, 0x73, 0xae, 0x6b, 0xbf, 0x5c, 0xe8, 0x85, 0x37, 0x17, 0x7a, - 0xe1, 0xaf, 0x0b, 0xbd, 0xf0, 0xc3, 0x83, 0xf7, 0x9a, 0x1c, 0x64, 0x9b, 0x33, 0x24, 0xf1, 0x19, - 0xe3, 0xa7, 0x56, 0xfe, 0xfb, 0xbf, 0xc8, 0xff, 0x01, 0x64, 0xcb, 0x93, 0x8a, 0x7c, 0xc9, 0x9d, - 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x6d, 0x9c, 0xf6, 0x5c, 0x71, 0x06, 0x00, 0x00, + 0xa4, 0x85, 0x3d, 0xf4, 0xdf, 0x28, 0x78, 0x3c, 0xaa, 0x91, 0xac, 0x0c, 0xf1, 0x22, 0xf1, 0xdd, + 0xf7, 0x7d, 0xef, 0x7b, 0xef, 0x1d, 0x1f, 0x81, 0x4e, 0x16, 0xcc, 0x65, 0x9c, 0x58, 0x8c, 0x63, + 0xd7, 0x27, 0xd6, 0xb3, 0x87, 0x56, 0x84, 0x39, 0x0e, 0x84, 0x19, 0x71, 0x16, 0x33, 0x58, 0x57, + 0xb8, 0x99, 0xe1, 0xe6, 0xb3, 0x87, 0xcd, 0x3a, 0x0e, 0x68, 0xc8, 0x2c, 0xf9, 0x9b, 0xb1, 0x9a, + 0x0d, 0x97, 0x89, 0x80, 0x09, 0x47, 0x46, 0x56, 0x16, 0x28, 0x68, 0xef, 0xb2, 0x01, 0x0d, 0xa7, + 0xb9, 0xf0, 0xcb, 0xcb, 0x68, 0xcc, 0x4e, 0x49, 0xe8, 0x4c, 0x09, 0xf1, 0x08, 0x57, 0xac, 0x9d, + 0x19, 0x9b, 0xb1, 0x2c, 0x77, 0xfa, 0xa4, 0x4e, 0xf5, 0x19, 0x63, 0x33, 0x9f, 0x58, 0x32, 0x9a, + 0x24, 0x53, 0xcb, 0x4b, 0x38, 0x8e, 0x29, 0x0b, 0x15, 0xde, 0x5a, 0xc7, 0x63, 0x1a, 0x10, 0x11, + 0xe3, 0x20, 0xca, 0x08, 0x77, 0xff, 0x2c, 0x81, 0xca, 0x48, 0x36, 0x0b, 0x1f, 0x80, 0x8a, 0x3b, + 0xc7, 0x34, 0x14, 0x48, 0x33, 0x8a, 0xed, 0xea, 0x3e, 0x32, 0x2f, 0xf5, 0x6d, 0xf6, 0x52, 0x82, + 0xad, 0x78, 0xa9, 0x42, 0x56, 0x2a, 0xd0, 0xb5, 0x0f, 0x2a, 0xbe, 0x4b, 0x09, 0xb6, 0xe2, 0xc1, + 0x0e, 0xb8, 0x2e, 0x58, 0xc2, 0x5d, 0x22, 0x50, 0x51, 0x4a, 0x1a, 0x1b, 0x24, 0x63, 0xc9, 0xb0, + 0x73, 0x26, 0xec, 0x80, 0x32, 0x4f, 0x7c, 0x22, 0x50, 0x49, 0x4a, 0x3e, 0xdf, 0x20, 0xb1, 0x13, + 0x9f, 0x28, 0x59, 0xc6, 0x85, 0x3d, 0x50, 0x7b, 0x7f, 0x8a, 0x02, 0x95, 0xa5, 0x58, 0xff, 0x50, + 0x89, 0x87, 0x92, 0x66, 0x6f, 0xc7, 0xff, 0x07, 0x02, 0xde, 0x01, 0x37, 0x02, 0xbc, 0x70, 0x42, + 0x16, 0xba, 0x04, 0x55, 0x0c, 0xad, 0x5d, 0xb6, 0xb7, 0x02, 0xbc, 0x18, 0xa6, 0x31, 0x6c, 0x81, + 0x6a, 0x3c, 0xe7, 0x44, 0xcc, 0x99, 0xef, 0x39, 0x18, 0x5d, 0x97, 0x30, 0x58, 0x1e, 0x1d, 0xac, + 0x12, 0x26, 0x68, 0x6b, 0x8d, 0xd0, 0x85, 0x8f, 0x40, 0x29, 0x60, 0x1e, 0x41, 0x37, 0x0c, 0xad, + 0x7d, 0x73, 0xdf, 0xd8, 0x34, 0x6f, 0x16, 0x0a, 0x12, 0x8a, 0x44, 0x1c, 0x33, 0x8f, 0xd8, 0x92, + 0x0d, 0xf7, 0x00, 0x48, 0x8b, 0xf2, 0x48, 0xec, 0x50, 0x0f, 0x81, 0x65, 0x55, 0x7d, 0x12, 0x1f, + 0x79, 0xf0, 0x1e, 0xf8, 0x24, 0x45, 0x05, 0x7d, 0x4e, 0x9c, 0x88, 0xd3, 0x74, 0xd2, 0x55, 0x49, + 0xa9, 0x05, 0x78, 0x31, 0xa6, 0xcf, 0xc9, 0x48, 0x1e, 0xc2, 0x6f, 0xc1, 0x96, 0xf0, 0xb1, 0x98, + 0xd3, 0x70, 0x86, 0xb6, 0x0d, 0xad, 0x5d, 0xdd, 0xff, 0x62, 0xd3, 0x55, 0x28, 0x4a, 0xf6, 0x8a, + 0xd8, 0x4b, 0xc9, 0xd7, 0xa5, 0x97, 0xbf, 0xb6, 0x0a, 0x77, 0xdf, 0x96, 0xc0, 0xcd, 0x55, 0x0a, + 0x7c, 0x04, 0x76, 0x39, 0x89, 0x18, 0x8f, 0x89, 0xe7, 0x70, 0x96, 0x84, 0x9e, 0x70, 0xce, 0x68, + 0xe8, 0xb1, 0x33, 0xa4, 0x19, 0x5a, 0xbb, 0x68, 0xef, 0xe4, 0xa8, 0x2d, 0xc1, 0xef, 0x25, 0x06, + 0x9f, 0x82, 0xcf, 0x02, 0x1a, 0x3a, 0x4b, 0x65, 0x44, 0x78, 0x2e, 0xbb, 0x66, 0x68, 0xed, 0xed, + 0x6e, 0xe7, 0xf5, 0xbb, 0x56, 0xe1, 0xed, 0xbb, 0xd6, 0xbd, 0x19, 0x8d, 0xe7, 0xc9, 0xc4, 0x74, + 0x59, 0xa0, 0x76, 0x4c, 0xfd, 0x7d, 0x25, 0xbc, 0x53, 0x2b, 0xfe, 0x31, 0x22, 0xc2, 0xec, 0x13, + 0xf7, 0xf7, 0x7f, 0xff, 0xb8, 0xaf, 0xd9, 0x3b, 0x01, 0x0d, 0x6d, 0x95, 0x72, 0x44, 0xb8, 0xf2, + 0x72, 0x41, 0x23, 0x6b, 0xd0, 0x09, 0xa8, 0x10, 0xce, 0x53, 0x4c, 0x7d, 0x27, 0x5f, 0x1b, 0x54, + 0x94, 0xa3, 0x68, 0x98, 0xd9, 0xde, 0x98, 0xf9, 0xde, 0x98, 0x7d, 0x45, 0xe8, 0xd6, 0xd2, 0x42, + 0x5e, 0xfe, 0xdd, 0xd2, 0x32, 0x8b, 0xdd, 0x2c, 0xd5, 0x31, 0x15, 0xe2, 0x31, 0xa6, 0x7e, 0x4e, + 0x83, 0x01, 0xd0, 0x73, 0x13, 0xec, 0x53, 0x97, 0xb2, 0x64, 0xdd, 0xa9, 0xf4, 0x91, 0x4e, 0x77, + 0x94, 0x53, 0x9e, 0x6e, 0xc5, 0xce, 0x05, 0xb7, 0xe5, 0xd5, 0x38, 0x53, 0x8e, 0xdd, 0xf4, 0x44, + 0xf6, 0x86, 0xca, 0x57, 0x9f, 0x5d, 0x5d, 0xe6, 0x3b, 0x54, 0xe9, 0xd2, 0xfe, 0x60, 0x00, 0xd0, + 0xba, 0x49, 0x5e, 0x8c, 0x5c, 0x8e, 0x2b, 0x3a, 0xed, 0xae, 0x3a, 0xe5, 0x29, 0xef, 0xff, 0xa4, + 0x81, 0xda, 0xca, 0xfb, 0x0f, 0xbf, 0x01, 0xcd, 0xde, 0x93, 0xe1, 0x78, 0x30, 0x1c, 0x9f, 0x8c, + 0x9d, 0xe3, 0x27, 0xfd, 0x81, 0x73, 0x32, 0x1c, 0x8f, 0x06, 0xbd, 0xa3, 0xc3, 0xa3, 0x41, 0xff, + 0x56, 0xa1, 0xb9, 0xf7, 0xe2, 0x95, 0x81, 0x56, 0x24, 0x27, 0xa1, 0x88, 0x88, 0x4b, 0xa7, 0x94, + 0x78, 0xd0, 0x04, 0xb7, 0xd7, 0xd4, 0x07, 0xe3, 0x83, 0xd1, 0x2d, 0xad, 0xf9, 0xe9, 0x8b, 0x57, + 0x46, 0x7d, 0x45, 0x96, 0x02, 0xcd, 0xd2, 0xcf, 0xbf, 0xe9, 0x85, 0xee, 0xe3, 0xd7, 0xe7, 0xba, + 0xf6, 0xe6, 0x5c, 0xd7, 0xfe, 0x39, 0xd7, 0xb5, 0x5f, 0x2e, 0xf4, 0xc2, 0x9b, 0x0b, 0xbd, 0xf0, + 0xd7, 0x85, 0x5e, 0xf8, 0xe1, 0xc1, 0x7b, 0x4d, 0x0e, 0xb2, 0xcd, 0x19, 0x92, 0xf8, 0x8c, 0xf1, + 0x53, 0x2b, 0xff, 0xa2, 0x2f, 0xf2, 0x6f, 0xba, 0x6c, 0x79, 0x52, 0x91, 0x97, 0xdc, 0xf9, 0x2f, + 0x00, 0x00, 0xff, 0xff, 0x67, 0xc3, 0xdd, 0xf6, 0x71, 0x06, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { From e283c6def0ff8586eaf480ba1cc62abf25a9f7ee Mon Sep 17 00:00:00 2001 From: leonz789 Date: Fri, 8 Nov 2024 19:23:02 +0800 Subject: [PATCH 13/22] lint --- proto/exocore/oracle/v1/params.proto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proto/exocore/oracle/v1/params.proto b/proto/exocore/oracle/v1/params.proto index 82b9fc6aa..b3041689e 100644 --- a/proto/exocore/oracle/v1/params.proto +++ b/proto/exocore/oracle/v1/params.proto @@ -54,7 +54,7 @@ enum ConsensusMode { message SlashingParams { // reported_rounds_window defines how many rounds included in one window for performance review of missing report int64 reported_rounds_window = 1; - // min_reported_perwindow defines at least how many rounds should be reported, this is a percentage of reported_rounds_window + // min_reported_perwindow defines at least how many rounds should be reported, this is a percentage of window bytes min_reported_per_window = 2 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false, @@ -66,13 +66,13 @@ message SlashingParams { // oracle_malicious_jail_duration defines the duratin one validator should be jailed for malicious behavior google.protobuf.Duration oracle_malicious_jail_duration =4 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true, (gogoproto.stdduration) = true]; - // slash_fraction_miss defines the fractino one validator should be punished with thier staked assets for msissing reporting price + // slash_fraction_miss defines the fraction one validator should be punished for msissing reporting price bytes slash_fraction_miss = 5 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; - // slash_fraction_miss defines the fractino one validator should be punished with thier staked assets for maliciours behavior + // slash_fraction_miss defines the fractino one validator should be punished for maliciours behavior bytes slash_fraction_malicious = 6 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false, From 99982b06e5b729eb70e2b0437aed1ac61df0bc99 Mon Sep 17 00:00:00 2001 From: X Date: Sat, 9 Nov 2024 16:12:32 +0800 Subject: [PATCH 14/22] Update x/oracle/keeper/slashing.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- x/oracle/keeper/slashing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/oracle/keeper/slashing.go b/x/oracle/keeper/slashing.go index ded92a318..7c75f0c19 100644 --- a/x/oracle/keeper/slashing.go +++ b/x/oracle/keeper/slashing.go @@ -33,7 +33,7 @@ func (k Keeper) SetValidatorReportInfo(ctx sdk.Context, validator string, info t store.Set(types.SlashingValidatorReportInfoKey(validator), bz) } -// GetValidatorReportInfo retruns the ValidatorReportInfo for a specific validator +// GetValidatorReportInfo returns the ValidatorReportInfo for a specific validator func (k Keeper) GetValidatorReportInfo(ctx sdk.Context, validator string) (info types.ValidatorReportInfo, found bool) { store := ctx.KVStore(k.storeKey) bz := store.Get(types.SlashingValidatorReportInfoKey(validator)) From 15c88ea59ba7d22c32af3e6bfb9dd06aa6efb26c Mon Sep 17 00:00:00 2001 From: leonz789 Date: Mon, 11 Nov 2024 16:44:46 +0800 Subject: [PATCH 15/22] fix nil worker --- x/oracle/keeper/aggregator/context.go | 49 +++++++++++++++++---------- x/oracle/module.go | 5 +++ x/oracle/types/params.pb.go | 6 ++-- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/x/oracle/keeper/aggregator/context.go b/x/oracle/keeper/aggregator/context.go index de07c913d..1a938c7cc 100644 --- a/x/oracle/keeper/aggregator/context.go +++ b/x/oracle/keeper/aggregator/context.go @@ -160,12 +160,6 @@ func (agc *AggregatorContext) FillPrice(msg *types.MsgCreatePrice) (*PriceItemKV agc.aggregators[msg.FeederID] = feederWorker } - // if feederWorker.sealed { - // // record this message for performance evaluate(used for slashing) - // return nil, nil, types.ErrPriceProposalIgnored.Wrap("price aggregation for this round has sealed") - // } - - // list4Calculator, list4Aggregator := w.f.filtrate(msg) if feederWorker.sealed { if _, list4Aggregator := feederWorker.filtrate(msg); list4Aggregator != nil { // record this message for performance evaluation(used for slashing) @@ -217,8 +211,14 @@ func (agc *AggregatorContext) SealRound(ctx sdk.Context, force bool) (success [] sort.Slice(feederIDs, func(i, j int) bool { return feederIDs[i] < feederIDs[j] }) + height := uint64(ctx.BlockHeight()) // make sure feederIDs are accessed in order to calculate the indexOffset for slashing + windowClosedMap := make(map[uint64]bool) for _, feederID := range feederIDs { + if agc.windowEnd(feederID, height) { + windowClosed = append(windowClosed, feederID) + windowClosedMap[feederID] = true + } round := agc.rounds[feederID] if round.status == roundStatusOpen { feeder := agc.params.GetTokenFeeder(feederID) @@ -226,25 +226,23 @@ func (agc *AggregatorContext) SealRound(ctx sdk.Context, force bool) (success [] // but it's not always the same for other modes, switch modes switch common.Mode { case types.ConsensusModeASAP: - offset := uint64(ctx.BlockHeight()) - round.basedBlock - expired := feeder.EndBlock > 0 && uint64(ctx.BlockHeight()) >= feeder.EndBlock + offset := height - round.basedBlock + expired := feeder.EndBlock > 0 && height >= feeder.EndBlock outOfWindow := offset >= uint64(common.MaxNonce) // an open round reach its end of window, increase offsetIndex for active valdiator and chech the performance(missing/malicious) - if round.status == roundStatusOpen && offset == uint64(common.MaxNonce) { - windowClosed = append(windowClosed, feederID) - } if expired || outOfWindow || force { failed = append(failed, feeder.TokenID) - if expired { - delete(agc.rounds, feederID) - } else { + if !expired { round.status = roundStatusClosed } // TODO: optimize operformance sealed = append(sealed, feederID) - delete(agc.aggregators, feederID) + if !windowClosedMap[feederID] { + // this should be clear after performanceReview + agc.RemoveWorker(feederID) + } } default: ctx.Logger().Info("mode other than 1 is not support now") @@ -252,7 +250,6 @@ func (agc *AggregatorContext) SealRound(ctx sdk.Context, force bool) (success [] } // all status: 1->2, remove its aggregator if agc.aggregators[feederID] != nil && agc.aggregators[feederID].sealed { - delete(agc.aggregators, feederID) sealed = append(sealed, feederID) } } @@ -308,9 +305,10 @@ func (agc *AggregatorContext) PrepareRoundEndBlock(block uint64) (newRoundFeeder // set nonce for corresponding feederID for new roud start newRoundFeederIDs = append(newRoundFeederIDs, feederIDUint64) // drop previous worker - delete(agc.aggregators, feederIDUint64) + agc.RemoveWorker(feederIDUint64) } else if round.status == roundStatusOpen && left >= uint64(common.MaxNonce) { // this shouldn't happen, if do sealround properly before prepareRound, basically for test only + // TODO: print error log here round.status = roundStatusClosed // TODO: just modify the status here, since sealRound should do all the related seal actions already when parepare invoked } @@ -398,6 +396,23 @@ func (agc *AggregatorContext) PerformanceReview(ctx sdk.Context, finalPrice *typ return } +func (agc AggregatorContext) windowEnd(feederID, height uint64) bool { + feeder := agc.params.TokenFeeders[feederID] + if (feeder.EndBlock > 0 && feeder.EndBlock <= height) || feeder.StartBaseBlock > height { + return false + } + delta := height - feeder.StartBaseBlock + left := delta % feeder.Interval + if left == uint64(common.MaxNonce) { + return true + } + return false +} + +func (agc *AggregatorContext) RemoveWorker(feederID uint64) { + delete(agc.aggregators, feederID) +} + // NewAggregatorContext returns a new instance of AggregatorContext func NewAggregatorContext() *AggregatorContext { return &AggregatorContext{ diff --git a/x/oracle/module.go b/x/oracle/module.go index 617b8d59b..cd1ad5cc2 100644 --- a/x/oracle/module.go +++ b/x/oracle/module.go @@ -200,6 +200,11 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val // TODO: for v1 use mode==1, just check the failed feeders _, failed, sealed, windowClosed := agc.SealRound(ctx, forceSeal) + defer func() { + for _, feederID := range windowClosed { + agc.RemoveWorker(feederID) + } + }() // update&check slashing info validatorPowers := agc.GetValidatorPowers() for validator, power := range validatorPowers { diff --git a/x/oracle/types/params.pb.go b/x/oracle/types/params.pb.go index 688246c55..e1a20d74b 100644 --- a/x/oracle/types/params.pb.go +++ b/x/oracle/types/params.pb.go @@ -208,15 +208,15 @@ func (m *Params) GetSlashing() *SlashingParams { type SlashingParams struct { // reported_rounds_window defines how many rounds included in one window for performance review of missing report ReportedRoundsWindow int64 `protobuf:"varint,1,opt,name=reported_rounds_window,json=reportedRoundsWindow,proto3" json:"reported_rounds_window,omitempty"` - // min_reported_perwindow defines at least how many rounds should be reported, this is a percentage of reported_rounds_window + // min_reported_perwindow defines at least how many rounds should be reported, this is a percentage of window MinReportedPerWindow github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=min_reported_per_window,json=minReportedPerWindow,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_reported_per_window"` // oracle_miss_jail_duraion defines the duration one validator should be jailed for missing reporting price OracleMissJailDuration time.Duration `protobuf:"bytes,3,opt,name=oracle_miss_jail_duration,json=oracleMissJailDuration,proto3,stdduration" json:"oracle_miss_jail_duration"` // oracle_malicious_jail_duration defines the duratin one validator should be jailed for malicious behavior OracleMaliciousJailDuration time.Duration `protobuf:"bytes,4,opt,name=oracle_malicious_jail_duration,json=oracleMaliciousJailDuration,proto3,stdduration" json:"oracle_malicious_jail_duration"` - // slash_fraction_miss defines the fractino one validator should be punished with thier staked assets for msissing reporting price + // slash_fraction_miss defines the fraction one validator should be punished for msissing reporting price SlashFractionMiss github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=slash_fraction_miss,json=slashFractionMiss,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_miss"` - // slash_fraction_miss defines the fractino one validator should be punished with thier staked assets for maliciours behavior + // slash_fraction_miss defines the fractino one validator should be punished for maliciours behavior SlashFractionMalicious github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=slash_fraction_malicious,json=slashFractionMalicious,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"slash_fraction_malicious"` } From 3919611d392475c696a8d98afc5fcd903baf23d9 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Tue, 12 Nov 2024 11:36:55 +0800 Subject: [PATCH 16/22] perf: return immediately before loop ends --- x/oracle/keeper/aggregator/worker.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/oracle/keeper/aggregator/worker.go b/x/oracle/keeper/aggregator/worker.go index 9662316e0..e4a09c3d8 100644 --- a/x/oracle/keeper/aggregator/worker.go +++ b/x/oracle/keeper/aggregator/worker.go @@ -50,6 +50,7 @@ func (r recordMsg) check(validator string, feederID, sourceID uint64, price, det exist = true if p.Price == price { matched = true + return } } } From 4cc106102fef5688d7b109f7cfe5b64a47e00fe4 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Tue, 12 Nov 2024 11:40:02 +0800 Subject: [PATCH 17/22] refactor(oracle) --- x/oracle/keeper/aggregator/context.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/x/oracle/keeper/aggregator/context.go b/x/oracle/keeper/aggregator/context.go index 1a938c7cc..be0a38efb 100644 --- a/x/oracle/keeper/aggregator/context.go +++ b/x/oracle/keeper/aggregator/context.go @@ -403,10 +403,7 @@ func (agc AggregatorContext) windowEnd(feederID, height uint64) bool { } delta := height - feeder.StartBaseBlock left := delta % feeder.Interval - if left == uint64(common.MaxNonce) { - return true - } - return false + return left == uint64(common.MaxNonce) } func (agc *AggregatorContext) RemoveWorker(feederID uint64) { From fe0a6a4fae73efe3197015aaffc6f9bd8aeaf9a1 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Tue, 12 Nov 2024 11:42:31 +0800 Subject: [PATCH 18/22] add test cases for oracle/create-price, fix create-price txsigner --- app/ante/cosmos/sigverify.go | 3 +- crypto/algo_ed25519.go | 13 ++---- go.mod | 3 +- tests/e2e/oracle/create-price.go | 67 +++++++++++++++++++++++++++++++ tests/e2e/oracle/data.go | 44 +++++++++++++++++++++ tests/e2e/oracle/oracle_test.go | 2 +- tests/e2e/oracle/tx.go | 39 ------------------ testutil/network/network.go | 1 - testutil/network/tx.go | 68 ++++++++++++++++++++++++++++---- 9 files changed, 179 insertions(+), 61 deletions(-) create mode 100644 tests/e2e/oracle/create-price.go create mode 100644 tests/e2e/oracle/data.go delete mode 100644 tests/e2e/oracle/tx.go diff --git a/app/ante/cosmos/sigverify.go b/app/ante/cosmos/sigverify.go index c6984f308..3d91e1cdd 100644 --- a/app/ante/cosmos/sigverify.go +++ b/app/ante/cosmos/sigverify.go @@ -70,8 +70,7 @@ func (spkd SetPubKeyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b return ctx, err } for i, pk := range pubKeys { - // addrFromPubk, err := sdk.AccAddressFromBech32(sdk.AccAddress(pk).String()) - if !bytes.Equal(signers[i], pk.Address()) { + if !simulate && !bytes.Equal(signers[i], pk.Address()) { return ctx, sdkerrors.ErrInvalidPubKey.Wrapf("pubKey does not match signer address %s with signer index: %d", signers[i], i) } } diff --git a/crypto/algo_ed25519.go b/crypto/algo_ed25519.go index ded767401..0b0a8ba8d 100644 --- a/crypto/algo_ed25519.go +++ b/crypto/algo_ed25519.go @@ -1,15 +1,11 @@ package crypto import ( - // "github.com/cometbft/cometbft/crypto/ed25519" cryptoed25519 "crypto/ed25519" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - "github.com/cosmos/go-bip39" - - // "github.com/evmos/evmos/v16/crypto/ethsecp256k1" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" evmoshd "github.com/evmos/evmos/v16/crypto/hd" @@ -29,11 +25,10 @@ func (e ed25519Algo) Name() hd.PubKeyType { // Derive derives and returns the ed25519 private key // for ed25519, this is mainly used for test, we don't actually generate ed25519 from the path defined from slip0010, we ignore the path, and retrieve seed from mnemonic directly, then use that seed as secret to generate keys through ed25519 func (e ed25519Algo) Derive() hd.DeriveFn { - return func(mnemonic, bip39Passphrase, path string) ([]byte, error) { - seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) - if err != nil { - return nil, err - } + return func(mnemonic, _, _ string) ([]byte, error) { + // seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) + // don't do transfer to be compatible with the way used in x/genutil/utils.go.InitializeNodeValidatorFilesFromMnemonic + seed := []byte(mnemonic) return ed25519.GenPrivKeyFromSecret(seed).Bytes(), nil } } diff --git a/go.mod b/go.mod index 34be7cc96..ad3d488d7 100644 --- a/go.mod +++ b/go.mod @@ -262,7 +262,8 @@ replace ( // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // use Cosmos-SDK fork to enable Ledger functionality - github.com/cosmos/cosmos-sdk => github.com/evmos/cosmos-sdk v0.47.5-evmos.2 + // github.com/cosmos/cosmos-sdk => github.com/evmos/cosmos-sdk v0.47.5-evmos.2 + github.com/cosmos/cosmos-sdk => /Users/linqing/workplace/github.com/leonz/evmos-cosmossdk/cosmos-sdk //fix cosmos-sdk error github.com/cosmos/gogoproto => github.com/cosmos/gogoproto v1.4.10 diff --git a/tests/e2e/oracle/create-price.go b/tests/e2e/oracle/create-price.go new file mode 100644 index 000000000..388ae149b --- /dev/null +++ b/tests/e2e/oracle/create-price.go @@ -0,0 +1,67 @@ +package oracle + +import ( + "context" + + oracletypes "github.com/ExocoreNetwork/exocore/x/oracle/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +const layout = "2006-01-02 15:04:05" + +func (s *E2ETestSuite) TestCreatePriceLST() { + kr := s.network.Validators[0].ClientCtx.Keyring + creator := sdk.AccAddress(s.network.Validators[0].PubKey.Address()) + priceTest1 := price1.updateTimestamp() + priceTimeDetID := priceTest1.getPriceTimeDetID("9") + priceSource := oracletypes.PriceSource{ + SourceID: 1, + Prices: []*oracletypes.PriceTimeDetID{ + &priceTimeDetID, + }, + } + msg := oracletypes.NewMsgCreatePrice(creator.String(), 1, []*oracletypes.PriceSource{&priceSource}, 10, 1) + + s.moveToAndCheck(10) + + // send create-price from validator-0 + err := s.network.SendTxOracleCreateprice([]sdk.Msg{msg}, "valconskey0", kr) + s.Require().NoError(err) + + // final price not aggregated + _, err = s.network.QueryOracle().LatestPrice(context.Background(), &oracletypes.QueryGetLatestPriceRequest{TokenId: 1}) + errStatus, _ := status.FromError(err) + s.Require().Equal(codes.NotFound, errStatus.Code()) + + s.moveToAndCheck(11) + // send create-price from validator-1 + err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg}, "valconskey1", kr) + + s.moveToAndCheck(12) + + res, err := s.network.QueryOracle().LatestPrice(context.Background(), &oracletypes.QueryGetLatestPriceRequest{TokenId: 1}) + s.Require().NoError(err) + s.Require().Equal(priceTest1.getPriceTimeRound(1), res.Price) +} + +func (s *E2ETestSuite) TestCreatePriceNST() { + +} + +func (s *E2ETestSuite) TestSlashing() { + +} + +func (s *E2ETestSuite) moveToAndCheck(height int64) { + _, err := s.network.WaitForHeight(height) + s.Require().NoError(err) +} + +func (s *E2ETestSuite) moveNAndCheck(n int64) { + for i := int64(0); i < n; i++ { + err := s.network.WaitForNextBlock() + s.Require().NoError(err) + } +} diff --git a/tests/e2e/oracle/data.go b/tests/e2e/oracle/data.go new file mode 100644 index 000000000..3fdc41d9a --- /dev/null +++ b/tests/e2e/oracle/data.go @@ -0,0 +1,44 @@ +package oracle + +import ( + "time" + + oracletypes "github.com/ExocoreNetwork/exocore/x/oracle/types" +) + +type priceTime struct { + Price string + Decimal int32 + Timestamp string +} + +func (p priceTime) getPriceTimeDetID(detID string) oracletypes.PriceTimeDetID { + return oracletypes.PriceTimeDetID{ + Price: p.Price, + Decimal: p.Decimal, + Timestamp: p.Timestamp, + DetID: detID, + } +} +func (p priceTime) getPriceTimeRound(roundID uint64) oracletypes.PriceTimeRound { + return oracletypes.PriceTimeRound{ + Price: p.Price, + Decimal: p.Decimal, + Timestamp: p.Timestamp, + RoundID: roundID, + } +} + +func (p priceTime) updateTimestamp() priceTime { + t := time.Now().UTC().Format(layout) + p.Timestamp = t + return p +} + +var ( + price1 = priceTime{ + Price: "199999", + Decimal: 18, + Timestamp: time.Now().UTC().Format(layout), + } +) diff --git a/tests/e2e/oracle/oracle_test.go b/tests/e2e/oracle/oracle_test.go index af0a31760..67cf8d732 100644 --- a/tests/e2e/oracle/oracle_test.go +++ b/tests/e2e/oracle/oracle_test.go @@ -11,6 +11,6 @@ func TestE2ESuite(t *testing.T) { cfg := network.DefaultConfig() cfg.NumValidators = 1 cfg.CleanupDir = true - cfg.EnableTMLogging = true + // cfg.EnableTMLogging = true suite.Run(t, NewE2ETestSuite(cfg)) } diff --git a/tests/e2e/oracle/tx.go b/tests/e2e/oracle/tx.go deleted file mode 100644 index e429f13e7..000000000 --- a/tests/e2e/oracle/tx.go +++ /dev/null @@ -1,39 +0,0 @@ -package oracle - -import ( - "time" - - oracletypes "github.com/ExocoreNetwork/exocore/x/oracle/types" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -const layout = "2006-01-02 15:04:05" - -func (s *E2ETestSuite) TestCreatePriceLST() { - kr := s.network.Validators[0].ClientCtx.Keyring - s.network.WaitForHeight(10) - creator := sdk.AccAddress(s.network.Validators[0].PubKey.Address()) - priceSource := oracletypes.PriceSource{ - SourceID: 1, - Prices: []*oracletypes.PriceTimeDetID{ - { - Price: "999123", - Decimal: 3, - Timestamp: time.Now().UTC().Format(layout), - DetID: "9", - }, - }, - } - msg := oracletypes.NewMsgCreatePrice(creator.String(), 1, []*oracletypes.PriceSource{&priceSource}, 10, 1) - s.network.SendTx([]sdk.Msg{msg}, "validator0", kr) - - s.network.WaitForHeight(12) -} - -func (s *E2ETestSuite) TestCreatePriceNST() { - -} - -func (s *E2ETestSuite) TestSlashing() { - -} diff --git a/testutil/network/network.go b/testutil/network/network.go index f5acaf2b1..f64fc3c34 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -396,7 +396,6 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { if err != nil { return nil, err } - p2pURL, err := url.Parse(p2pAddr) if err != nil { return nil, err diff --git a/testutil/network/tx.go b/testutil/network/tx.go index 4bd970ea9..372823653 100644 --- a/testutil/network/tx.go +++ b/testutil/network/tx.go @@ -1,37 +1,89 @@ package network import ( + "context" + + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/types/tx/signing" ) // SendTx construct and sign that tx with input msgs func (n *Network) SendTx(msgs []sdk.Msg, keyName string, keyring keyring.Keyring) error { - ctx := n.Validators[0].ClientCtx - record, err := keyring.Key(keyName) + txf, ctx, err := generateTxf(n.Validators[0].ClientCtx, keyName, keyring, 1.5, n.Config.MinGasPrices) if err != nil { return err } - acc, err := record.GetAddress() + return tx.BroadcastTx(ctx, txf, msgs...) +} + +// SendTxOracleCreatePrice consturct and sign that tx with input msgs, it's different from SendTx, since when we use ed25519 for oracle senario, we allowed that signer is an unexists account, this implementation skip the 'accoutn exists' related checks +// Also, if you want to sign some normal message (not oracle-create-price) with ed25519, just use SendTx is fine, we support ed25519 signing in keyring +func (n *Network) SendTxOracleCreateprice(msgs []sdk.Msg, keyName string, keyring keyring.Keyring) error { + txf, ctx, err := generateTxf(n.Validators[0].ClientCtx, keyName, keyring, 1.5, n.Config.MinGasPrices) + if err != nil { + return err + } + // calculate gas + txBytes, err := txf.BuildSimTx(msgs...) + if err != nil { + return err + } + txClient := txtypes.NewServiceClient(ctx) + simRes, err := txClient.Simulate(context.Background(), &txtypes.SimulateRequest{ + TxBytes: txBytes, + }) if err != nil { return err } + gasAdjusted := uint64(txf.GasAdjustment() * float64(simRes.GasInfo.GasUsed)) + txf.WithGas(gasAdjusted) + transaction, err := txf.BuildUnsignedTx(msgs...) + if err != nil { + return err + } + if err := tx.Sign(txf, ctx.GetFromName(), transaction, true); err != nil { + return err + } + txBytes, err = ctx.TxConfig.TxEncoder()(transaction.GetTx()) + if err != nil { + return err + } + res, err := ctx.BroadcastTx(txBytes) + if err != nil { + return err + } + return ctx.PrintProto(res) +} + +func generateTxf(ctx client.Context, keyName string, kr keyring.Keyring, adjustment float64, minGasPrice string) (tx.Factory, client.Context, error) { + var txf tx.Factory + record, err := kr.Key(keyName) + if err != nil { + return txf, ctx, err + } + acc, err := record.GetAddress() + if err != nil { + return txf, ctx, err + } ctx.FromAddress = acc ctx.FromName = keyName ctx.SkipConfirm = true - txf := tx.Factory{}. + txf = tx.Factory{}. WithChainID(ctx.ChainID). - WithKeybase(keyring). + WithKeybase(kr). WithTxConfig(ctx.TxConfig). WithSignMode(signing.SignMode_SIGN_MODE_DIRECT). - WithGasAdjustment(1.5). + WithGasAdjustment(adjustment). WithAccountRetriever(ctx.AccountRetriever). - WithGasPrices(n.Config.MinGasPrices). + WithGasPrices(minGasPrice). WithSimulateAndExecute(true) ctx.BroadcastMode = flags.BroadcastSync - return tx.BroadcastTx(ctx, txf, msgs...) + return txf, ctx, nil } From 63824f549c38aee01042fb83f0b063407bfce624 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Tue, 12 Nov 2024 11:49:34 +0800 Subject: [PATCH 19/22] remove debug dependency --- go.mod | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/go.mod b/go.mod index ad3d488d7..34be7cc96 100644 --- a/go.mod +++ b/go.mod @@ -262,8 +262,7 @@ replace ( // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // use Cosmos-SDK fork to enable Ledger functionality - // github.com/cosmos/cosmos-sdk => github.com/evmos/cosmos-sdk v0.47.5-evmos.2 - github.com/cosmos/cosmos-sdk => /Users/linqing/workplace/github.com/leonz/evmos-cosmossdk/cosmos-sdk + github.com/cosmos/cosmos-sdk => github.com/evmos/cosmos-sdk v0.47.5-evmos.2 //fix cosmos-sdk error github.com/cosmos/gogoproto => github.com/cosmos/gogoproto v1.4.10 From 0967104ea32817b9d88a58bc86a34f643d61cb67 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Wed, 13 Nov 2024 10:21:45 +0800 Subject: [PATCH 20/22] add oracle test cases --- tests/e2e/oracle/create-price.go | 67 --------- tests/e2e/oracle/create_price.go | 184 +++++++++++++++++++++++ tests/e2e/oracle/data.go | 16 ++ tests/e2e/oracle/oracle_test.go | 4 +- testutil/network/network.go | 2 +- x/oracle/keeper/aggregator/aggregator.go | 12 +- x/oracle/keeper/aggregator/calculator.go | 4 +- x/oracle/keeper/aggregator/util.go | 10 ++ 8 files changed, 221 insertions(+), 78 deletions(-) delete mode 100644 tests/e2e/oracle/create-price.go create mode 100644 tests/e2e/oracle/create_price.go create mode 100644 x/oracle/keeper/aggregator/util.go diff --git a/tests/e2e/oracle/create-price.go b/tests/e2e/oracle/create-price.go deleted file mode 100644 index 388ae149b..000000000 --- a/tests/e2e/oracle/create-price.go +++ /dev/null @@ -1,67 +0,0 @@ -package oracle - -import ( - "context" - - oracletypes "github.com/ExocoreNetwork/exocore/x/oracle/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -const layout = "2006-01-02 15:04:05" - -func (s *E2ETestSuite) TestCreatePriceLST() { - kr := s.network.Validators[0].ClientCtx.Keyring - creator := sdk.AccAddress(s.network.Validators[0].PubKey.Address()) - priceTest1 := price1.updateTimestamp() - priceTimeDetID := priceTest1.getPriceTimeDetID("9") - priceSource := oracletypes.PriceSource{ - SourceID: 1, - Prices: []*oracletypes.PriceTimeDetID{ - &priceTimeDetID, - }, - } - msg := oracletypes.NewMsgCreatePrice(creator.String(), 1, []*oracletypes.PriceSource{&priceSource}, 10, 1) - - s.moveToAndCheck(10) - - // send create-price from validator-0 - err := s.network.SendTxOracleCreateprice([]sdk.Msg{msg}, "valconskey0", kr) - s.Require().NoError(err) - - // final price not aggregated - _, err = s.network.QueryOracle().LatestPrice(context.Background(), &oracletypes.QueryGetLatestPriceRequest{TokenId: 1}) - errStatus, _ := status.FromError(err) - s.Require().Equal(codes.NotFound, errStatus.Code()) - - s.moveToAndCheck(11) - // send create-price from validator-1 - err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg}, "valconskey1", kr) - - s.moveToAndCheck(12) - - res, err := s.network.QueryOracle().LatestPrice(context.Background(), &oracletypes.QueryGetLatestPriceRequest{TokenId: 1}) - s.Require().NoError(err) - s.Require().Equal(priceTest1.getPriceTimeRound(1), res.Price) -} - -func (s *E2ETestSuite) TestCreatePriceNST() { - -} - -func (s *E2ETestSuite) TestSlashing() { - -} - -func (s *E2ETestSuite) moveToAndCheck(height int64) { - _, err := s.network.WaitForHeight(height) - s.Require().NoError(err) -} - -func (s *E2ETestSuite) moveNAndCheck(n int64) { - for i := int64(0); i < n; i++ { - err := s.network.WaitForNextBlock() - s.Require().NoError(err) - } -} diff --git a/tests/e2e/oracle/create_price.go b/tests/e2e/oracle/create_price.go new file mode 100644 index 000000000..cb8e5b7e3 --- /dev/null +++ b/tests/e2e/oracle/create_price.go @@ -0,0 +1,184 @@ +package oracle + +import ( + "context" + "time" + + oracletypes "github.com/ExocoreNetwork/exocore/x/oracle/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +const layout = "2006-01-02 15:04:05" + +/* + cases: + we need more than 2/3 power, so that at least 3 out of 4 validators power should be enough + 1. block_1_1: v1 sendPrice{p1}, [no round_1 price after block_1_1 committed], block_1_2:v2&v3 sendPrice{p1}, [got round_1 price{p1} after block_1_2 committed] + 2. block_2_1: v3 sendPrice{p2}, block_2_2: v1 sendPrice{p2}, [no round_2 price after block_2_2 committed], block_2_3:nothing, [got round_2 price{p1} equals to round_1 after block_2_3 committed] + 3. block_3_1: v1 sendPrice{p1}, block_3_2: v2&v3 sendPrice{p2}, block_3_3: v3 sendPrice{p2}, [got final price{p2} after block_3_3 committed] + 4. block_4_1: v1&v2&v3 sendPrice{p1}, [got round_4 price{p1} after block_4_1 committed]] + + --- nonce: +*/ + +func (s *E2ETestSuite) TestCreatePriceLST() { + kr0 := s.network.Validators[0].ClientCtx.Keyring + creator0 := sdk.AccAddress(s.network.Validators[0].PubKey.Address()) + + kr1 := s.network.Validators[1].ClientCtx.Keyring + creator1 := sdk.AccAddress(s.network.Validators[1].PubKey.Address()) + + kr2 := s.network.Validators[2].ClientCtx.Keyring + creator2 := sdk.AccAddress(s.network.Validators[2].PubKey.Address()) + + // kr3 := s.network.Validators[2].ClientCtx.Keyring + // creator3 := sdk.AccAddress(s.network.Validators[2].PubKey.Address()) + + priceTest1R1 := price1.updateTimestamp() + priceTimeDetID1R1 := priceTest1R1.getPriceTimeDetID("9") + priceSource1R1 := oracletypes.PriceSource{ + SourceID: 1, + Prices: []*oracletypes.PriceTimeDetID{ + &priceTimeDetID1R1, + }, + } + + // case_1. + s.moveToAndCheck(10) + // send create-price from validator-0 + msg0 := oracletypes.NewMsgCreatePrice(creator0.String(), 1, []*oracletypes.PriceSource{&priceSource1R1}, 10, 1) + err := s.network.SendTxOracleCreateprice([]sdk.Msg{msg0}, "valconskey0", kr0) + s.Require().NoError(err) + + // query final price + _, err = s.network.QueryOracle().LatestPrice(context.Background(), &oracletypes.QueryGetLatestPriceRequest{TokenId: 1}) + errStatus, _ := status.FromError(err) + s.Require().Equal(codes.NotFound, errStatus.Code()) + + s.moveToAndCheck(11) + // send create-price from validator-1 + msg1 := oracletypes.NewMsgCreatePrice(creator1.String(), 1, []*oracletypes.PriceSource{&priceSource1R1}, 10, 1) + err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg1}, "valconskey1", kr1) + s.Require().NoError(err) + + // send create-price from validator-2 + msg2 := oracletypes.NewMsgCreatePrice(creator2.String(), 1, []*oracletypes.PriceSource{&priceSource1R1}, 10, 1) + err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg2}, "valconskey2", kr2) + s.Require().NoError(err) + + s.moveToAndCheck(12) + // query final price + res, err := s.network.QueryOracle().LatestPrice(context.Background(), &oracletypes.QueryGetLatestPriceRequest{TokenId: 1}) + s.Require().NoError(err) + s.Require().Equal(priceTest1R1.getPriceTimeRound(1), res.Price) + + // case_2. + // timestamp need to be updated + priceTest2R2 := price2.updateTimestamp() + priceTimeDetID2R2 := priceTest2R2.getPriceTimeDetID("10") + priceSource2R2 := oracletypes.PriceSource{ + SourceID: 1, + Prices: []*oracletypes.PriceTimeDetID{ + &priceTimeDetID2R2, + }, + } + msg0 = oracletypes.NewMsgCreatePrice(creator0.String(), 1, []*oracletypes.PriceSource{&priceSource2R2}, 20, 1) + msg2 = oracletypes.NewMsgCreatePrice(creator2.String(), 1, []*oracletypes.PriceSource{&priceSource2R2}, 20, 1) + + s.moveToAndCheck(20) + // send price{p2} from validator-2 + err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg2}, "valconskey2", kr2) + s.Require().NoError(err) + s.moveToAndCheck(21) + // send price{p2} from validator-0 + err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg0}, "valconskey0", kr0) + s.Require().NoError(err) + s.moveToAndCheck(24) + res, err = s.network.QueryOracle().LatestPrice(context.Background(), &oracletypes.QueryGetLatestPriceRequest{TokenId: 1}) + s.Require().NoError(err) + // price update fail, round 2 still have price{p1} + s.Require().Equal(priceTest1R1.getPriceTimeRound(2), res.Price) + + // case_3. + // update timestamp + priceTest2R3 := price2.updateTimestamp() + priceTimeDetID2R3 := priceTest2R3.getPriceTimeDetID("11") + priceSource2R3 := oracletypes.PriceSource{ + SourceID: 1, + Prices: []*oracletypes.PriceTimeDetID{ + &priceTimeDetID2R3, + }, + } + + msg0 = oracletypes.NewMsgCreatePrice(creator0.String(), 1, []*oracletypes.PriceSource{&priceSource2R3}, 30, 1) + msg1 = oracletypes.NewMsgCreatePrice(creator1.String(), 1, []*oracletypes.PriceSource{&priceSource2R3}, 30, 1) + msg2 = oracletypes.NewMsgCreatePrice(creator2.String(), 1, []*oracletypes.PriceSource{&priceSource2R3}, 30, 1) + s.moveToAndCheck(30) + // send price{p2} from validator-0 + err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg0}, "valconskey0", kr0) + s.Require().NoError(err) + s.moveToAndCheck(31) + // send price{p2} from validator-1 + err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg1}, "valconskey1", kr1) + s.Require().NoError(err) + + // send price{p2} from validator-2 + err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg2}, "valconskey2", kr2) + s.Require().NoError(err) + + s.moveToAndCheck(32) + res, err = s.network.QueryOracle().LatestPrice(context.Background(), &oracletypes.QueryGetLatestPriceRequest{TokenId: 1}) + s.Require().NoError(err) + // price updated, round 3 has price{p2} + s.Require().Equal(priceTest2R3.getPriceTimeRound(3), res.Price) + + // case_4. + // update timestamp + // priceTest1R4 := price2.updateTimestamp() + // priceTimeDetID2R3 := priceTest2R3.getPriceTimeDetID("10") + // priceSource2R3 := oracletypes.PriceSource{ + // SourceID: 1, + // Prices: []*oracletypes.PriceTimeDetID{ + // &priceTimeDetID2R3, + // }, + // } + s.moveToAndCheck(40) + priceTest1R4, priceSource1R4 := price1.generateRealTimeStructs("12", 1) + msg0 = oracletypes.NewMsgCreatePrice(creator0.String(), 1, []*oracletypes.PriceSource{&priceSource1R4}, 40, 1) + msg1 = oracletypes.NewMsgCreatePrice(creator1.String(), 1, []*oracletypes.PriceSource{&priceSource1R4}, 40, 1) + msg2 = oracletypes.NewMsgCreatePrice(creator2.String(), 1, []*oracletypes.PriceSource{&priceSource1R4}, 40, 1) + err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg0}, "valconskey0", kr0) + s.Require().NoError(err) + err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg1}, "valconskey1", kr1) + s.Require().NoError(err) + err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg2}, "valconskey2", kr2) + s.Require().NoError(err) + s.moveToAndCheck(42) + res, err = s.network.QueryOracle().LatestPrice(context.Background(), &oracletypes.QueryGetLatestPriceRequest{TokenId: 1}) + s.Require().NoError(err) + // price updated, round 4 has price{p1} + s.Require().Equal(priceTest1R4.getPriceTimeRound(4), res.Price) + +} + +func (s *E2ETestSuite) TestCreatePriceNST() { + +} + +func (s *E2ETestSuite) TestSlashing() { + +} + +func (s *E2ETestSuite) moveToAndCheck(height int64) { + _, err := s.network.WaitForHeightWithTimeout(height, 30*time.Second) + s.Require().NoError(err) +} + +func (s *E2ETestSuite) moveNAndCheck(n int64) { + for i := int64(0); i < n; i++ { + err := s.network.WaitForNextBlock() + s.Require().NoError(err) + } +} diff --git a/tests/e2e/oracle/data.go b/tests/e2e/oracle/data.go index 3fdc41d9a..f3fbb5aeb 100644 --- a/tests/e2e/oracle/data.go +++ b/tests/e2e/oracle/data.go @@ -35,10 +35,26 @@ func (p priceTime) updateTimestamp() priceTime { return p } +func (p priceTime) generateRealTimeStructs(detID string, sourceID uint64) (priceTime, oracletypes.PriceSource) { + retP := p.updateTimestamp() + pTimeDetID := retP.getPriceTimeDetID(detID) + return retP, oracletypes.PriceSource{ + SourceID: 1, + Prices: []*oracletypes.PriceTimeDetID{ + &pTimeDetID, + }, + } +} + var ( price1 = priceTime{ Price: "199999", Decimal: 18, Timestamp: time.Now().UTC().Format(layout), } + price2 = priceTime{ + Price: "299999", + Decimal: 18, + Timestamp: time.Now().UTC().Format(layout), + } ) diff --git a/tests/e2e/oracle/oracle_test.go b/tests/e2e/oracle/oracle_test.go index 67cf8d732..cbe84803f 100644 --- a/tests/e2e/oracle/oracle_test.go +++ b/tests/e2e/oracle/oracle_test.go @@ -9,8 +9,8 @@ import ( func TestE2ESuite(t *testing.T) { cfg := network.DefaultConfig() - cfg.NumValidators = 1 + cfg.NumValidators = 4 cfg.CleanupDir = true - // cfg.EnableTMLogging = true + cfg.EnableTMLogging = true suite.Run(t, NewE2ETestSuite(cfg)) } diff --git a/testutil/network/network.go b/testutil/network/network.go index f64fc3c34..6610b2098 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -339,7 +339,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { logger := log.NewNopLogger() if cfg.EnableTMLogging { logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - logger, _ = tmflags.ParseLogLevel("debug", logger, tmcfg.DefaultLogLevel) + logger, _ = tmflags.ParseLogLevel("info", logger, tmcfg.DefaultLogLevel) } ctx.Logger = logger diff --git a/x/oracle/keeper/aggregator/aggregator.go b/x/oracle/keeper/aggregator/aggregator.go index 48e7778cd..517ba0a4f 100644 --- a/x/oracle/keeper/aggregator/aggregator.go +++ b/x/oracle/keeper/aggregator/aggregator.go @@ -50,9 +50,9 @@ type aggregator struct { func (agg *aggregator) copy4CheckTx() *aggregator { ret := &aggregator{ - finalPrice: big.NewInt(0).Set(agg.finalPrice), - reportPower: big.NewInt(0).Set(agg.reportPower), - totalPower: big.NewInt(0).Set(agg.totalPower), + finalPrice: copyBigInt(agg.finalPrice), + reportPower: copyBigInt(agg.reportPower), + totalPower: copyBigInt(agg.totalPower), reports: make([]*reportPrice, 0, len(agg.reports)), dsPrices: make(map[uint64]string), @@ -62,13 +62,13 @@ func (agg *aggregator) copy4CheckTx() *aggregator { } for _, report := range agg.reports { rTmp := *report - rTmp.price = big.NewInt(0).Set(report.price) - rTmp.power = big.NewInt(0).Set(report.power) + rTmp.price = copyBigInt(report.price) + rTmp.power = copyBigInt(report.power) for k, v := range report.prices { // prices are information submitted by validators, these data will not change under deterministic sources, but with non-deterministic sources they might be overwrite by later prices tmpV := *v - tmpV.price = big.NewInt(0).Set(v.price) + tmpV.price = copyBigInt(v.price) rTmp.prices[k] = &tmpV } diff --git a/x/oracle/keeper/aggregator/calculator.go b/x/oracle/keeper/aggregator/calculator.go index 9ee504d25..86749b6ac 100644 --- a/x/oracle/keeper/aggregator/calculator.go +++ b/x/oracle/keeper/aggregator/calculator.go @@ -75,14 +75,14 @@ func (r *roundPricesList) copy4CheckTx() *roundPricesList { for _, v := range r.roundPricesList { tmpRP := &roundPrices{ detID: v.detID, - price: big.NewInt(0).Set(v.price), + price: copyBigInt(v.price), prices: make([]*priceAndPower, 0, len(v.prices)), timestamp: v.timestamp, } for _, pNP := range v.prices { tmpPNP := *pNP // power will be modified during execution - tmpPNP.power = big.NewInt(0).Set(pNP.power) + tmpPNP.power = copyBigInt(pNP.power) tmpRP.prices = append(tmpRP.prices, &tmpPNP) } diff --git a/x/oracle/keeper/aggregator/util.go b/x/oracle/keeper/aggregator/util.go new file mode 100644 index 000000000..98fd7bd00 --- /dev/null +++ b/x/oracle/keeper/aggregator/util.go @@ -0,0 +1,10 @@ +package aggregator + +import "math/big" + +func copyBigInt(i *big.Int) *big.Int { + if i == nil { + return nil + } + return big.NewInt(0).Set(i) +} From 9ddc0871a5e4fffcab64a477c0658568b18d70ee Mon Sep 17 00:00:00 2001 From: leonz789 Date: Fri, 15 Nov 2024 09:34:26 +0800 Subject: [PATCH 21/22] test: oracle slash e2e test --- tests/e2e/oracle/create_price.go | 31 +++++++++--------------- testutil/network/query.go | 5 ++++ testutil/network/util.go | 1 + x/oracle/keeper/aggregator/aggregator.go | 4 ++- x/oracle/keeper/nonce.go | 2 ++ x/oracle/module.go | 15 +++++------- x/oracle/types/params.go | 2 +- 7 files changed, 29 insertions(+), 31 deletions(-) diff --git a/tests/e2e/oracle/create_price.go b/tests/e2e/oracle/create_price.go index cb8e5b7e3..075d26252 100644 --- a/tests/e2e/oracle/create_price.go +++ b/tests/e2e/oracle/create_price.go @@ -6,6 +6,7 @@ import ( oracletypes "github.com/ExocoreNetwork/exocore/x/oracle/types" sdk "github.com/cosmos/cosmos-sdk/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -45,7 +46,7 @@ func (s *E2ETestSuite) TestCreatePriceLST() { }, } - // case_1. + // case_1. update price to p1 {reporter: v0, v1, v2. miss:v3} s.moveToAndCheck(10) // send create-price from validator-0 msg0 := oracletypes.NewMsgCreatePrice(creator0.String(), 1, []*oracletypes.PriceSource{&priceSource1R1}, 10, 1) @@ -68,13 +69,13 @@ func (s *E2ETestSuite) TestCreatePriceLST() { err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg2}, "valconskey2", kr2) s.Require().NoError(err) - s.moveToAndCheck(12) + s.moveToAndCheck(13) // query final price res, err := s.network.QueryOracle().LatestPrice(context.Background(), &oracletypes.QueryGetLatestPriceRequest{TokenId: 1}) s.Require().NoError(err) s.Require().Equal(priceTest1R1.getPriceTimeRound(1), res.Price) - // case_2. + // case_2. failed to update price to p2, keep p1 // timestamp need to be updated priceTest2R2 := price2.updateTimestamp() priceTimeDetID2R2 := priceTest2R2.getPriceTimeDetID("10") @@ -101,7 +102,7 @@ func (s *E2ETestSuite) TestCreatePriceLST() { // price update fail, round 2 still have price{p1} s.Require().Equal(priceTest1R1.getPriceTimeRound(2), res.Price) - // case_3. + // case_3. update price to p2{reporter:v0,v1,v2, miss:v3}, v3 should be slash for now(require 1 report at least, but got 0) // update timestamp priceTest2R3 := price2.updateTimestamp() priceTimeDetID2R3 := priceTest2R3.getPriceTimeDetID("11") @@ -128,22 +129,17 @@ func (s *E2ETestSuite) TestCreatePriceLST() { err = s.network.SendTxOracleCreateprice([]sdk.Msg{msg2}, "valconskey2", kr2) s.Require().NoError(err) - s.moveToAndCheck(32) + s.moveToAndCheck(33) res, err = s.network.QueryOracle().LatestPrice(context.Background(), &oracletypes.QueryGetLatestPriceRequest{TokenId: 1}) s.Require().NoError(err) // price updated, round 3 has price{p2} s.Require().Equal(priceTest2R3.getPriceTimeRound(3), res.Price) + // case_slahsing: validator 3 is jailed + resSigningInfo, err := s.network.QuerySlashing().SigningInfo(context.Background(), &slashingtypes.QuerySigningInfoRequest{ConsAddress: sdk.ConsAddress(s.network.Validators[3].PubKey.Address()).String()}) + s.Require().NoError(err) + s.Require().True(true, resSigningInfo.ValSigningInfo.JailedUntil.After(time.Now())) - // case_4. - // update timestamp - // priceTest1R4 := price2.updateTimestamp() - // priceTimeDetID2R3 := priceTest2R3.getPriceTimeDetID("10") - // priceSource2R3 := oracletypes.PriceSource{ - // SourceID: 1, - // Prices: []*oracletypes.PriceTimeDetID{ - // &priceTimeDetID2R3, - // }, - // } + // case_4. update price to p1{reporter:v0,v1,v2, miss:v3} s.moveToAndCheck(40) priceTest1R4, priceSource1R4 := price1.generateRealTimeStructs("12", 1) msg0 = oracletypes.NewMsgCreatePrice(creator0.String(), 1, []*oracletypes.PriceSource{&priceSource1R4}, 40, 1) @@ -160,17 +156,12 @@ func (s *E2ETestSuite) TestCreatePriceLST() { s.Require().NoError(err) // price updated, round 4 has price{p1} s.Require().Equal(priceTest1R4.getPriceTimeRound(4), res.Price) - } func (s *E2ETestSuite) TestCreatePriceNST() { } -func (s *E2ETestSuite) TestSlashing() { - -} - func (s *E2ETestSuite) moveToAndCheck(height int64) { _, err := s.network.WaitForHeightWithTimeout(height, 30*time.Second) s.Require().NoError(err) diff --git a/testutil/network/query.go b/testutil/network/query.go index de143eb4d..2c8566cac 100644 --- a/testutil/network/query.go +++ b/testutil/network/query.go @@ -7,6 +7,7 @@ import ( operatortypes "github.com/ExocoreNetwork/exocore/x/operator/types" oracletypes "github.com/ExocoreNetwork/exocore/x/oracle/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" ) func (n *Network) QueryOracle() oracletypes.QueryClient { @@ -33,3 +34,7 @@ func (n *Network) QueryAVS() avstypes.QueryClient { func (n *Network) QueryDogfood() dogfoodtypes.QueryClient { return dogfoodtypes.NewQueryClient(n.Validators[0].ClientCtx) } + +func (n *Network) QuerySlashing() slashingtypes.QueryClient { + return slashingtypes.NewQueryClient(n.Validators[0].ClientCtx) +} diff --git a/testutil/network/util.go b/testutil/network/util.go index dcc1aaa01..1645f9cd7 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -483,5 +483,6 @@ func NewGenStateDelegation(operatorAccAddresses []sdk.AccAddress, stakingAmount } func NewGenStateOracle() (oracletypes.GenesisState, error) { + DefaultGenStateOracle.Params.Slashing.ReportedRoundsWindow = 2 return DefaultGenStateOracle, nil } diff --git a/x/oracle/keeper/aggregator/aggregator.go b/x/oracle/keeper/aggregator/aggregator.go index cc7c1e242..8ebd84492 100644 --- a/x/oracle/keeper/aggregator/aggregator.go +++ b/x/oracle/keeper/aggregator/aggregator.go @@ -17,7 +17,7 @@ type priceWithTimeAndRound struct { type reportPrice struct { validator string - // final price, set to -1 as initial + // final price, nil as initial stands for no aggregated price reached yet price *big.Int // sourceId->priceWithTimeAndRound prices map[uint64]*priceWithTimeAndRound @@ -217,6 +217,8 @@ func (agg *aggregator) getFinalPriceList(feederID uint64) []*types.AggFinalPrice DetID: price.detRoundID, Price: price.price.String(), }) + // {feederID,soruceID} has been found, skip other reports + break } } return ret diff --git a/x/oracle/keeper/nonce.go b/x/oracle/keeper/nonce.go index b4a5e6fed..16c6fb28d 100644 --- a/x/oracle/keeper/nonce.go +++ b/x/oracle/keeper/nonce.go @@ -128,6 +128,8 @@ func (k Keeper) CheckAndIncreaseNonce(ctx sdk.Context, validator string, feederI } return 0, errors.New("feeder not found") } + validatorset := k.GetAggregatorContext(ctx).GetValidators() + ctx.Logger().Debug("current validatorset:%v", validatorset) return 0, fmt.Errorf("validator for the consKey which signed the create-price tx is not included in active validator set, signer consAddr:%s", validator) } diff --git a/x/oracle/module.go b/x/oracle/module.go index 146ca47dd..42300870f 100644 --- a/x/oracle/module.go +++ b/x/oracle/module.go @@ -158,13 +158,11 @@ func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { // TODO: try better way to init caches and aggregatorContext than beginBlock _ = am.keeper.GetCaches() agc := am.keeper.GetAggregatorContext(ctx) - once.Do(func() { - validatorPowers := agc.GetValidatorPowers() - // set validatorReportInfo to track performance - for validator := range validatorPowers { - am.keeper.InitValidatorReportInfo(ctx, validator, ctx.BlockHeight()) - } - }) + validatorPowers := agc.GetValidatorPowers() + // set validatorReportInfo to track performance + for validator := range validatorPowers { + am.keeper.InitValidatorReportInfo(ctx, validator, ctx.BlockHeight()) + } } // EndBlock contains the logic that is automatically triggered at the end of each block @@ -215,7 +213,7 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val } // TODO: for the round calculation, now only sourceID=1 is used so {feederID, sourceID} have only one value for each feederID which corresponding to one round. // But when we came to multiple sources, we should consider the round corresponding to feedeerID instead of {feederID, sourceID} - for _, finalPrice := range agc.GetFinalPriceListForFeederIDs(windowClosed) { + for i, finalPrice := range agc.GetFinalPriceListForFeederIDs(windowClosed) { exist, matched := agc.PerformanceReview(ctx, finalPrice, validator) if exist && !matched { // TODO: malicious price, just slash&jail immediately @@ -276,7 +274,6 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val default: // Array value at this index has not changed, no need to update counter } - minReportedPerWindow := am.keeper.GetMinReportedPerWindow(ctx) if missed { diff --git a/x/oracle/types/params.go b/x/oracle/types/params.go index 1e72de69e..2cb7fbcd6 100644 --- a/x/oracle/types/params.go +++ b/x/oracle/types/params.go @@ -107,7 +107,7 @@ func DefaultParams() Params { MaxDetId: 5, MaxSizePrices: 100, Slashing: &SlashingParams{ - ReportedRoundsWindow: 100, + ReportedRoundsWindow: 30, MinReportedPerWindow: sdkmath.LegacyNewDec(1).Quo(sdkmath.LegacyNewDec(2)), OracleMissJailDuration: 600 * time.Second, OracleMaliciousJailDuration: 30 * 24 * time.Hour, From d01e53ad48ddfbe107c6c82ee1c0564774780637 Mon Sep 17 00:00:00 2001 From: leonz789 Date: Fri, 15 Nov 2024 10:00:03 +0800 Subject: [PATCH 22/22] fix: remove unused var --- x/oracle/module.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/oracle/module.go b/x/oracle/module.go index 42300870f..e76f141c4 100644 --- a/x/oracle/module.go +++ b/x/oracle/module.go @@ -213,7 +213,7 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val } // TODO: for the round calculation, now only sourceID=1 is used so {feederID, sourceID} have only one value for each feederID which corresponding to one round. // But when we came to multiple sources, we should consider the round corresponding to feedeerID instead of {feederID, sourceID} - for i, finalPrice := range agc.GetFinalPriceListForFeederIDs(windowClosed) { + for _, finalPrice := range agc.GetFinalPriceListForFeederIDs(windowClosed) { exist, matched := agc.PerformanceReview(ctx, finalPrice, validator) if exist && !matched { // TODO: malicious price, just slash&jail immediately