Skip to content

Commit

Permalink
V7 testing (#667)
Browse files Browse the repository at this point in the history
Co-authored-by: vish-stride <vishal@stridelabs.co>
Co-authored-by: Aidan Salzmann <aidan@stridelabs.co>
  • Loading branch information
3 people authored Mar 14, 2023
1 parent 0510592 commit ef4808d
Show file tree
Hide file tree
Showing 11 changed files with 194 additions and 325 deletions.
18 changes: 12 additions & 6 deletions app/upgrades/v7/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,14 @@ func CreateUpgradeHandler(
func AddHourEpoch(ctx sdk.Context, k epochskeeper.Keeper) {
ctx.Logger().Info("Adding hour epoch")

startTime := ctx.BlockTime().Truncate(time.Hour)
hourEpoch := epochstypes.EpochInfo{
Identifier: epochstypes.HOUR_EPOCH,
StartTime: time.Time{},
StartTime: startTime,
Duration: time.Hour,
CurrentEpoch: 0,
CurrentEpochStartHeight: 0,
CurrentEpochStartTime: time.Time{},
CurrentEpochStartHeight: ctx.BlockHeight(),
CurrentEpochStartTime: startTime,
EpochCountingStarted: false,
}

Expand Down Expand Up @@ -134,9 +135,12 @@ func AddRedemptionRateSafetyChecks(ctx sdk.Context, k stakeibckeeper.Keeper) {
ctx.Logger().Info("Setting min/max redemption rate safety bounds on each host zone")

// Set new stakeibc params
params := k.GetParams(ctx)
params.DefaultMinRedemptionRateThreshold = stakeibctypes.DefaultMinRedemptionRateThreshold
params.DefaultMaxRedemptionRateThreshold = stakeibctypes.DefaultMaxRedemptionRateThreshold
// In this case, we're using `DefaultParams` because all of our current params are the defaults
// You can verify this by hand by running `strided q stakeibc params`, and comparing the output to the values defined in params.go.
// This is a safer way of adding a new parameter that avoids having to unmarshal using the old types
// In future upgrades, if we are simply modifying parameter values (instead of adding a new parameter),
// we should read in params using GetParams, modify them, and then set them using SetParams
params := stakeibctypes.DefaultParams()
k.SetParams(ctx, params)

// Get default min/max redemption rate
Expand Down Expand Up @@ -194,6 +198,8 @@ func ExecuteProp153(ctx sdk.Context, k bankkeeper.Keeper) error {

// Create reward collector module account for Prop #8
func CreateRewardCollectorModuleAccount(ctx sdk.Context, k authkeeper.AccountKeeper) error {
ctx.Logger().Info("Creating reward collector module account")

rewardCollectorAddress := address.Module(stakeibctypes.RewardCollectorName, []byte(stakeibctypes.RewardCollectorName))
return utils.CreateModuleAccount(ctx, k, rewardCollectorAddress)
}
24 changes: 16 additions & 8 deletions app/upgrades/v7/upgrades_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@ var (
InitialJunoUnbondingFrequency = uint64(4)
ustrd = "ustrd"
)

// The block time here is arbitrary, but it's must start at a time that is not at an even hour
var InitialBlockTime = time.Date(2023, 1, 1, 8, 43, 0, 0, time.UTC) // January 1st 2023 at 8:43 AM
var EpochStartTime = time.Date(2023, 1, 1, 8, 00, 0, 0, time.UTC) // January 1st 2023 at 8:00 AM
var ExpectedHourEpoch = epochstypes.EpochInfo{
Identifier: epochstypes.HOUR_EPOCH,
StartTime: time.Time{},
Duration: time.Hour,
CurrentEpoch: 0,
CurrentEpochStartHeight: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
Identifier: epochstypes.HOUR_EPOCH,
Duration: time.Hour,
CurrentEpoch: 0,
StartTime: EpochStartTime,
CurrentEpochStartTime: EpochStartTime,
}
var ExpectedJunoUnbondingFrequency = uint64(5)
var ExpectedEpochProvisions = sdk.NewDec(1_078_767_123)
Expand Down Expand Up @@ -100,6 +102,9 @@ func (s *UpgradeTestSuite) SetupEpochs() {
s.App.EpochsKeeper.SetEpochInfo(s.Ctx, epochstypes.EpochInfo{
Identifier: epochstypes.STRIDE_EPOCH,
})

// Change the context to be a time that's not rounded on the hour
s.Ctx = s.Ctx.WithBlockTime(InitialBlockTime)
}

// Checks that the hour epoch has been added
Expand All @@ -118,9 +123,12 @@ func (s *UpgradeTestSuite) CheckEpochsAfterUpgrade(epochStarted bool) {
// If the upgrade passed an a block was incremented, the epoch should be started
expectedHourEpoch := ExpectedHourEpoch
if epochStarted {
expectedHourEpoch.EpochCountingStarted = true
expectedHourEpoch.CurrentEpoch = 1
expectedHourEpoch.EpochCountingStarted = true
expectedHourEpoch.CurrentEpochStartHeight = DummyUpgradeHeight
} else {
expectedHourEpoch.EpochCountingStarted = false
expectedHourEpoch.CurrentEpochStartHeight = s.Ctx.BlockHeight()
}

actualHourEpoch, found := s.App.EpochsKeeper.GetEpochInfo(s.Ctx, epochstypes.HOUR_EPOCH)
Expand Down
9 changes: 2 additions & 7 deletions proto/stride/stakeibc/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,8 @@ message Params {
uint64 delegate_interval = 6;
uint64 deposit_interval = 2;
uint64 redemption_rate_interval = 3;

uint64 stride_commission = 4;
// zone_com_address stores which addresses to
// send the Stride commission too, as well as what portion
// of the fee each address is entitled to
// TODO implement this
map<string, string> zone_com_address = 5;
uint64 reinvest_interval = 7;
uint64 validator_rebalancing_threshold = 8;
uint64 ica_timeout_nanos = 9;
uint64 buffer_size = 10;
uint64 ibc_timeout_blocks = 11;
Expand All @@ -34,4 +27,6 @@ message Params {
uint64 ibc_transfer_timeout_nanos = 16;
uint64 safety_num_validators = 17;
uint64 safety_max_slash_percent = 18;

reserved 8;
}
1 change: 0 additions & 1 deletion readme-docs/md/stakeibc_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ ReinvestInterval (default uint64 = 1)
RewardsInterval (default uint64 = 1)
RedemptionRateInterval (default uint64 = 1)
StrideCommission (default uint64 = 10)
ValidatorRebalancingThreshold (default uint64 = 100)
ICATimeoutNanos(default uint64 = 600000000000)
BufferSize (default uint64 = 5)
IbcTimeoutBlocks (default uint64 = 300)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import pandas as pd
import json

'''
This file provides an extremely lightweight tool to compare two state exports from a "localstride" test.
It will diff parts of state and will output any diffs that are not "expected"
To run, please modify "BEFORE_PATH" and "AFTER_PATH" and run `python3 compare_before_after_state.py`
'''

BEFORE_PATH = 'state_export_before_upgrade.json'
AFTER_PATH = 'state_export_after_upgrade.json'

EXPECTED_DIFFS = [
'/interchainquery/queries',
'/auth/accounts',
'/bank/balances',
'/bank/supply',
'/epochs/epochs',
'/staking/last_total_power',
'/staking/delegations',
'/staking/validators',
'/staking/last_validator_powers',
'/staking/unbonding_delegations',
'/gov/proposals',
'/gov/voting_params/voting_period',
'/gov/starting_proposal_id',
'/interchainaccounts/controller_genesis_state/ports',
'/slashing/missed_blocks',
'/slashing/signing_infos',
'/distribution/delegator_starting_infos',
'/distribution/previous_proposer',
]

def compare_app_state(before_state, after_state):
before = before_state['app_state']
after = after_state['app_state']
equal_paths, unequal_paths = _return_equal_unequal_paths_recursively(before, after, '')
print("THE FOLLOWING STORES ARE UNEXPECTEDLY DIFFERENT - MUST INVESTIGATE")
expected_diff = []
for p in unequal_paths:
if p in EXPECTED_DIFFS:
expected_diff.append(p)
continue
print(f"\t{p}")
print("\n\nTHE FOLLOWING STORES ARE DIFFERENT, AS EXPECTED - NO ACTION REQUIRED")
for p in expected_diff:
print(f"\t{p}")

def _clean_path(path_list):
return [c.replace(':/', ':') for c in path_list]

def _return_equal_unequal_paths_recursively(s1, s2, prefix):
if (type(s1) != dict) or (type(s2) != dict):
if s1 == s2:
return [prefix], []
else:
if (type(s1) == type(s2)) and (type(s1) == list) and (len(s1) == len(s2)) and (prefix not in EXPECTED_DIFFS):
zipped_list = zip(s1, s2)
equal_paths = set()
unequal_paths = set()
for zl in zipped_list:
sub_equal, sub_unequal = _return_equal_unequal_paths_recursively(zl[0], zl[1], prefix + ':')
equal_paths.update(sub_equal)
unequal_paths.update(sub_unequal)
return _clean_path(list(equal_paths)), _clean_path(list(unequal_paths))
return [], [prefix]
equal_paths = []
unequal_paths = []
s1_keys = set(s1.keys())
s2_keys = set(s2.keys())
inter_keys = s1_keys.intersection(s2_keys)
s1_unequal = s1_keys.difference(s2_keys)
s2_unequal = s2_keys.difference(s1_keys)
for joint_key in inter_keys:
sub_equal, sub_unequal = _return_equal_unequal_paths_recursively(s1[joint_key], s2[joint_key], prefix + f'/{joint_key}')
equal_paths.extend(sub_equal)
unequal_paths.extend(sub_unequal)
for s1_key in s1_unequal:
unequal_paths.append(prefix + f'/{s1_key} - MISSING')
for s2_key in s2_unequal:
unequal_paths.append(prefix + f'/{s2_key} - ADDED')

return equal_paths, unequal_paths

def main():
with open(BEFORE_PATH) as f:
before_state = json.load(f)
with open(AFTER_PATH) as f:
after_state = json.load(f)

compare_app_state(before_state, after_state)

if __name__ == '__main__':
main()
4 changes: 2 additions & 2 deletions testutil/localstride/state-export/scripts/submit_upgrade.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ STRIDE_MAIN_CMD="docker-compose -f ${SCRIPT_DIR}/../docker-compose.yml exec -it

printf "PROPOSAL\n"
$STRIDE_MAIN_CMD tx gov submit-legacy-proposal software-upgrade $upgrade_name \
--title $upgrade_name --description "upgrade" \
--title $upgrade_name --description "upgrade" --upgrade-info "test" --no-validate \
--upgrade-height $upgrade_height --from val -y | TRIM_TX

sleep 5
Expand All @@ -35,7 +35,7 @@ $STRIDE_MAIN_CMD query gov proposal $proposal_id

sleep 5
printf "\nDEPOSIT\n"
$STRIDE_MAIN_CMD tx gov deposit $proposal_id 10000001ustrd --from val -y | TRIM_TX
$STRIDE_MAIN_CMD tx gov deposit $proposal_id 20000000001ustrd --from val -y | TRIM_TX

sleep 5
printf "\nDEPOSIT CONFIRMATION\n"
Expand Down
1 change: 0 additions & 1 deletion x/stakeibc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ ReinvestInterval (default uint64 = 1)
RewardsInterval (default uint64 = 1)
RedemptionRateInterval (default uint64 = 1)
StrideCommission (default uint64 = 10)
ValidatorRebalancingThreshold (default uint64 = 100)
ICATimeoutNanos(default uint64 = 600000000000)
BufferSize (default uint64 = 5)
IbcTimeoutBlocks (default uint64 = 300)
Expand Down
2 changes: 0 additions & 2 deletions x/stakeibc/keeper/msg_server_rebalance_validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ func (k msgServer) RebalanceValidators(goCtx context.Context, msg *types.MsgReba
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "no validator delegations found for Host Zone %s, cannot rebalance 0 delegations!", hostZone.ChainId)
}

// TODO Remove ValidatorRebalancingThreshold from our params

var msgs []sdk.Msg
delegationIca := hostZone.GetDelegationAccount()
if delegationIca == nil || delegationIca.GetAddress() == "" {
Expand Down
4 changes: 2 additions & 2 deletions x/stakeibc/keeper/reward_allocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ func (k Keeper) LiquidStakeRewardCollectorBalance(ctx sdk.Context, msgSvr types.
// liquid stake all tokens
msg := types.NewMsgLiquidStake(rewardCollectorAddress.String(), token.Amount, hz.HostDenom)
if err := msg.ValidateBasic(); err != nil {
k.Logger(ctx).Error("Liquid stake from reward collector address failed validate basic: %s", err.Error())
k.Logger(ctx).Error(fmt.Sprintf("Liquid stake from reward collector address failed validate basic: %s", err.Error()))
continue
}
_, err = msgSvr.LiquidStake(ctx, msg)
if err != nil {
k.Logger(ctx).Error("Can't liquid stake %s for hostzone %s", token.String(), hz.ChainId)
k.Logger(ctx).Error(fmt.Sprintf("Failed to liquid stake %s for hostzone %s: %s", token.String(), hz.ChainId, err.Error()))
continue
}
k.Logger(ctx).Info(fmt.Sprintf("Liquid staked %s for hostzone %s's accrued rewards", token.String(), hz.ChainId))
Expand Down
46 changes: 11 additions & 35 deletions x/stakeibc/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,17 @@ var (
DefaultRewardsInterval uint64 = 1
DefaultRedemptionRateInterval uint64 = 1
// you apparently cannot safely encode floats, so we make commission / 100
DefaultStrideCommission uint64 = 10
DefaultValidatorRebalancingThreshold uint64 = 100 // divide by 10,000, so 100 = 1%
DefaultICATimeoutNanos uint64 = 600000000000
DefaultBufferSize uint64 = 5 // 1/5=20% of the epoch
DefaultIbcTimeoutBlocks uint64 = 300 // 300 blocks ~= 30 minutes
DefaultFeeTransferTimeoutNanos uint64 = 1800000000000 // 30 minutes
DefaultMinRedemptionRateThreshold uint64 = 90 // divide by 100, so 90 = 0.9
DefaultMaxRedemptionRateThreshold uint64 = 150 // divide by 100, so 150 = 1.5
DefaultMaxStakeICACallsPerEpoch uint64 = 100
DefaultIBCTransferTimeoutNanos uint64 = 1800000000000 // 30 minutes
DefaultSafetyNumValidators uint64 = 35
DefaultSafetyMaxSlashPercent uint64 = 10
DefaultStrideCommission uint64 = 10
DefaultICATimeoutNanos uint64 = 600000000000
DefaultBufferSize uint64 = 5 // 1/5=20% of the epoch
DefaultIbcTimeoutBlocks uint64 = 300 // 300 blocks ~= 30 minutes
DefaultFeeTransferTimeoutNanos uint64 = 1800000000000 // 30 minutes
DefaultMinRedemptionRateThreshold uint64 = 90 // divide by 100, so 90 = 0.9
DefaultMaxRedemptionRateThreshold uint64 = 150 // divide by 100, so 150 = 1.5
DefaultMaxStakeICACallsPerEpoch uint64 = 100
DefaultIBCTransferTimeoutNanos uint64 = 1800000000000 // 30 minutes
DefaultSafetyNumValidators uint64 = 35
DefaultSafetyMaxSlashPercent uint64 = 10

// KeyDepositInterval is store's key for the DepositInterval option
KeyDepositInterval = []byte("DepositInterval")
Expand All @@ -36,7 +35,6 @@ var (
KeyRewardsInterval = []byte("RewardsInterval")
KeyRedemptionRateInterval = []byte("RedemptionRateInterval")
KeyStrideCommission = []byte("StrideCommission")
KeyValidatorRebalancingThreshold = []byte("ValidatorRebalancingThreshold")
KeyICATimeoutNanos = []byte("ICATimeoutNanos")
KeyFeeTransferTimeoutNanos = []byte("FeeTransferTimeoutNanos")
KeyBufferSize = []byte("BufferSize")
Expand Down Expand Up @@ -66,7 +64,6 @@ func NewParams(
redemptionRateInterval uint64,
strideCommission uint64,
reinvestInterval uint64,
validatorRebalancingThreshold uint64,
icaTimeoutNanos uint64,
bufferSize uint64,
ibcTimeoutBlocks uint64,
Expand All @@ -85,7 +82,6 @@ func NewParams(
RedemptionRateInterval: redemptionRateInterval,
StrideCommission: strideCommission,
ReinvestInterval: reinvestInterval,
ValidatorRebalancingThreshold: validatorRebalancingThreshold,
IcaTimeoutNanos: icaTimeoutNanos,
BufferSize: bufferSize,
IbcTimeoutBlocks: ibcTimeoutBlocks,
Expand All @@ -108,7 +104,6 @@ func DefaultParams() Params {
DefaultRedemptionRateInterval,
DefaultStrideCommission,
DefaultReinvestInterval,
DefaultValidatorRebalancingThreshold,
DefaultICATimeoutNanos,
DefaultBufferSize,
DefaultIbcTimeoutBlocks,
Expand All @@ -131,7 +126,6 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
paramtypes.NewParamSetPair(KeyRedemptionRateInterval, &p.RedemptionRateInterval, isPositive),
paramtypes.NewParamSetPair(KeyStrideCommission, &p.StrideCommission, isCommission),
paramtypes.NewParamSetPair(KeyReinvestInterval, &p.ReinvestInterval, isPositive),
paramtypes.NewParamSetPair(KeyValidatorRebalancingThreshold, &p.ValidatorRebalancingThreshold, isThreshold),
paramtypes.NewParamSetPair(KeyICATimeoutNanos, &p.IcaTimeoutNanos, isPositive),
paramtypes.NewParamSetPair(KeyBufferSize, &p.BufferSize, isPositive),
paramtypes.NewParamSetPair(KeyIbcTimeoutBlocks, &p.IbcTimeoutBlocks, isPositive),
Expand All @@ -145,21 +139,6 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
}
}

func isThreshold(i interface{}) error {
ival, ok := i.(uint64)
if !ok {
return fmt.Errorf("parameter not accepted: %T", i)
}

if ival <= 0 {
return fmt.Errorf("parameter must be positive: %d", ival)
}
if ival > 10000 {
return fmt.Errorf("parameter must be less than 10,000: %d", ival)
}
return nil
}

func validTimeoutNanos(i interface{}) error {
ival, ok := i.(uint64)
if !ok {
Expand Down Expand Up @@ -264,9 +243,6 @@ func (p Params) Validate() error {
if err := isPositive(p.ReinvestInterval); err != nil {
return err
}
if err := isThreshold(p.ValidatorRebalancingThreshold); err != nil {
return err
}
if err := isPositive(p.IcaTimeoutNanos); err != nil {
return err
}
Expand Down
Loading

0 comments on commit ef4808d

Please sign in to comment.