From a08c28ee842f2cbec384ed6fc2a8f033fa74dba0 Mon Sep 17 00:00:00 2001 From: tkernell Date: Fri, 25 Oct 2024 11:50:02 -0500 Subject: [PATCH 1/8] handle bad rpc connections --- daemons/token_bridge_feed/client/client.go | 81 +++++++++++++++++++--- 1 file changed, 73 insertions(+), 8 deletions(-) diff --git a/daemons/token_bridge_feed/client/client.go b/daemons/token_bridge_feed/client/client.go index ab3c2238..df8bf92b 100644 --- a/daemons/token_bridge_feed/client/client.go +++ b/daemons/token_bridge_feed/client/client.go @@ -134,13 +134,26 @@ func (c *Client) QueryAPI(urlStr string) ([]byte, error) { } func (c *Client) InitializeDeposits() error { - ethRpcUrl, err := c.getEthRpcUrl() - if err != nil { - return fmt.Errorf("failed to get ETH RPC url: %w", err) + // Add retry logic for initial connection + var eclient *ethclient.Client + var err error + var ethRpcUrl string + for retries := 0; retries < 3; retries++ { + ethRpcUrl, err = c.getEthRpcUrl() + if err != nil { + return fmt.Errorf("failed to get ETH RPC url: %w", err) + } + + eclient, err = ethclient.Dial(ethRpcUrl) + if err != nil { + c.logger.Error("Failed to connect to Ethereum client, retrying...", "attempt", retries+1, "error", err) + time.Sleep(time.Second * 5) + continue + } + break } - eclient, err := ethclient.Dial(ethRpcUrl) if err != nil { - return fmt.Errorf("failed to connect to the Ethereum client: %w", err) + return fmt.Errorf("failed to connect to the Ethereum client after retries: %w", err) } c.ethClient = eclient @@ -168,9 +181,27 @@ func (c *Client) InitializeDeposits() error { } func (c *Client) QueryTokenBridgeContract() error { - latestDepositId, err := c.QueryCurrentDepositId() - if err != nil { - return fmt.Errorf("failed to query the latest deposit ID: %w", err) + // Add retry logic for queries + var latestDepositId *big.Int + var err error + + for retries := 0; retries < 3; retries++ { + latestDepositId, err = c.QueryCurrentDepositId() + if err != nil { + if retries < 2 { + c.logger.Error("Failed to query latest deposit ID, reconnecting...", "attempt", retries+1, "error", err) + // Attempt to reconnect + if err := c.reconnectEthClient(); err != nil { + c.logger.Error("Failed to reconnect", "error", err) + time.Sleep(time.Second * 5) + continue + } + } else { + return fmt.Errorf("failed to query the latest deposit ID: %w", err) + } + } else { + break + } } if c.lastReportedDepositId == nil { @@ -378,3 +409,37 @@ func (c *Client) getTokenBridgeContractAddress() (common.Address, error) { } return common.HexToAddress(tokenBridgeContractAddress), nil } + +// Add new helper function for reconnection +func (c *Client) reconnectEthClient() error { + ethRpcUrl, err := c.getEthRpcUrl() + if err != nil { + return fmt.Errorf("failed to get ETH RPC url: %w", err) + } + + eclient, err := ethclient.Dial(ethRpcUrl) + if err != nil { + return fmt.Errorf("failed to reconnect to the Ethereum client: %w", err) + } + + // Close existing client if it exists + if c.ethClient != nil { + c.ethClient.Close() + } + + c.ethClient = eclient + + // Reinstantiate the bridge contract with new client + contractAddress, err := c.getTokenBridgeContractAddress() + if err != nil { + return fmt.Errorf("failed to get token bridge contract address: %w", err) + } + + bridgeContract, err := tokenbridge.NewTokenBridge(contractAddress, c.ethClient) + if err != nil { + return fmt.Errorf("failed to reinstantiate TokenBridge contract: %w", err) + } + + c.bridgeContract = bridgeContract + return nil +} From 0efb85db3bd70d717d39881f691d635b6562a274 Mon Sep 17 00:00:00 2001 From: tkernell Date: Fri, 25 Oct 2024 15:16:31 -0500 Subject: [PATCH 2/8] use legacydec for division --- x/dispute/keeper/claim_reward.go | 20 +++-- x/dispute/keeper/dispute.go | 22 ++++-- x/dispute/keeper/execute.go | 25 +++++-- .../keeper/msg_server_withdraw_fee_refund.go | 9 ++- x/dispute/keeper/tally.go | 73 +++++++++++++------ x/reporter/keeper/distribution.go | 44 +++++++++-- x/reporter/keeper/msg_server.go | 4 +- x/reporter/keeper/withdraw.go | 38 ++++++++-- 8 files changed, 182 insertions(+), 53 deletions(-) diff --git a/x/dispute/keeper/claim_reward.go b/x/dispute/keeper/claim_reward.go index 5af8604b..6daf09ac 100644 --- a/x/dispute/keeper/claim_reward.go +++ b/x/dispute/keeper/claim_reward.go @@ -123,11 +123,21 @@ func (k Keeper) CalculateReward(ctx sdk.Context, addr sdk.AccAddress, id uint64) } // normalize powers - userPower := addrUserPower.Mul(layer.PowerReduction).Quo(globalUserPower) - reporterPower := addrReporterPower.Mul(layer.PowerReduction).Quo(globalReporterPower) - tokenholderPower := addrTokenholderPower.Mul(layer.PowerReduction).Quo(globalTokenholderPower) + powerReductionDec := math.LegacyNewDecFromInt(layer.PowerReduction) + addrUserPowerDec := math.LegacyNewDecFromInt(addrUserPower) + addrReporterPowerDec := math.LegacyNewDecFromInt(addrReporterPower) + addrTokenholderPowerDec := math.LegacyNewDecFromInt(addrTokenholderPower) + globalUserPowerDec := math.LegacyNewDecFromInt(globalUserPower) + globalReporterPowerDec := math.LegacyNewDecFromInt(globalReporterPower) + globalTokenholderPowerDec := math.LegacyNewDecFromInt(globalTokenholderPower) + totalGroupsDec := math.LegacyNewDecFromInt(math.NewInt(totalGroups)) + disputeVoterRewardDec := math.LegacyNewDecFromInt(dispute.VoterReward) + + userPower := addrUserPowerDec.Mul(powerReductionDec).Quo(globalUserPowerDec) + reporterPower := addrReporterPowerDec.Mul(powerReductionDec).Quo(globalReporterPowerDec) + tokenholderPower := addrTokenholderPowerDec.Mul(powerReductionDec).Quo(globalTokenholderPowerDec) totalAccPower := userPower.Add(reporterPower).Add(tokenholderPower) - rewardAcc := totalAccPower.Mul(dispute.VoterReward).Quo(math.NewInt(totalGroups).Mul(layer.PowerReduction)) + rewardAcc := totalAccPower.Mul(disputeVoterRewardDec).Quo(totalGroupsDec.Mul(powerReductionDec)) - return rewardAcc, nil + return rewardAcc.TruncateInt(), nil } diff --git a/x/dispute/keeper/dispute.go b/x/dispute/keeper/dispute.go index 16d53636..c5df163c 100644 --- a/x/dispute/keeper/dispute.go +++ b/x/dispute/keeper/dispute.go @@ -80,7 +80,9 @@ func (k Keeper) SetNewDispute(ctx sdk.Context, sender sdk.AccAddress, msg types. if msg.Fee.Amount.GT(disputeFee) { msg.Fee.Amount = disputeFee } - fivePercent := disputeFee.MulRaw(1).QuoRaw(20) + disputeFeeDec := math.LegacyNewDecFromInt(disputeFee) + fivePercentDec := disputeFeeDec.Mul(math.LegacyNewDec(1)).Quo(math.LegacyNewDec(20)) + fivePercent := fivePercentDec.TruncateInt() dispute := types.Dispute{ HashId: hashId[:], DisputeId: disputeId, @@ -159,7 +161,11 @@ func (k Keeper) SlashAndJailReporter(ctx sdk.Context, report oracletypes.MicroRe return err } reportPowerFixed6 := math.NewInt(int64(report.Power)).Mul(layertypes.PowerReduction) - slashAmountFixed6 := reportPowerFixed6.Mul(slashPercentageFixed6).Quo(layertypes.PowerReduction) + powerReductionDec := math.LegacyNewDecFromInt(layertypes.PowerReduction) + reportPowerFixed6Dec := math.LegacyNewDecFromInt(reportPowerFixed6) + slashPercentageFixed6Dec := math.LegacyNewDecFromInt(slashPercentageFixed6) + slashAmountFixed6Dec := reportPowerFixed6Dec.Mul(slashPercentageFixed6Dec).Quo(powerReductionDec) + slashAmountFixed6 := slashAmountFixed6Dec.TruncateInt() err = k.reporterKeeper.EscrowReporterStake(ctx, reporterAddr, report.Power, report.BlockNumber, slashAmountFixed6, hashId) if err != nil { return err @@ -195,10 +201,14 @@ func (k Keeper) GetDisputeFee(ctx sdk.Context, rep oracletypes.MicroReport, cate switch category { case types.Warning: // calculate 1 percent of bond - return stake.MulRaw(1).QuoRaw(100), nil + stakeDec := math.LegacyNewDecFromInt(stake) + feeDec := stakeDec.Mul(math.LegacyNewDec(1)).Quo(math.LegacyNewDec(100)) + return feeDec.TruncateInt(), nil case types.Minor: // calculate 5 percent of bond - return stake.MulRaw(5).QuoRaw(100), nil + stakeDec := math.LegacyNewDecFromInt(stake) + feeDec := stakeDec.Mul(math.LegacyNewDec(5)).Quo(math.LegacyNewDec(100)) + return feeDec.TruncateInt(), nil case types.Major: // calculate 100 percent of bond return stake, nil @@ -225,7 +235,9 @@ func (k Keeper) AddDisputeRound(ctx sdk.Context, sender sdk.AccAddress, dispute base := new(big.Int).Exp(big.NewInt(2), big.NewInt(round), nil) return fivePercent.Mul(math.NewIntFromBigInt(base)) } - fivePercent := dispute.SlashAmount.MulRaw(1).QuoRaw(20) + disputeSlashAmountDec := math.LegacyNewDecFromInt(dispute.SlashAmount) + fivePercentDec := disputeSlashAmountDec.Mul(math.LegacyNewDec(1)).Quo(math.LegacyNewDec(20)) + fivePercent := fivePercentDec.TruncateInt() roundFee := fee(fivePercent, int64(dispute.DisputeRound)) if roundFee.GT(dispute.SlashAmount) { roundFee = dispute.SlashAmount diff --git a/x/dispute/keeper/execute.go b/x/dispute/keeper/execute.go index 4815ab3c..2037e40c 100644 --- a/x/dispute/keeper/execute.go +++ b/x/dispute/keeper/execute.go @@ -49,7 +49,9 @@ func (k Keeper) ExecuteVote(ctx context.Context, id uint64) error { // amount of dispute fee to return to fee payers or give to reporter disputeFeeMinusBurn := dispute.SlashAmount.Sub(dispute.BurnAmount) // the burnAmount starts at %5 of disputeFee, half of which is burned and the other half is distributed to the voters - halfBurnAmount := dispute.BurnAmount.QuoRaw(2) + disputeBurnAmountDec := math.LegacyNewDecFromInt(dispute.BurnAmount) + halfBurnAmountDec := disputeBurnAmountDec.Quo(math.LegacyNewDec(2)) + halfBurnAmount := halfBurnAmountDec.TruncateInt() voterReward := halfBurnAmount totalVoterPower, err := k.GetSumOfAllGroupVotesAllRounds(ctx, id) if err != nil { @@ -126,8 +128,14 @@ func (k Keeper) ExecuteVote(ctx context.Context, id uint64) error { func (k Keeper) RefundDisputeFee(ctx context.Context, feePayer sdk.AccAddress, payerInfo types.PayerInfo, totalFeesPaid, feeMinusBurn math.Int, hashId []byte) (math.Int, error) { fee := payerInfo.Amount totalFees := totalFeesPaid - feeMinusBurnDec := feeMinusBurn - amtFixed12 := fee.Mul(feeMinusBurnDec).Mul(layertypes.PowerReduction).Quo(totalFees) + + feeDec := math.LegacyNewDecFromInt(fee) + feeMinusBurnDec := math.LegacyNewDecFromInt(feeMinusBurn) + powerReductionDec := math.LegacyNewDecFromInt(layertypes.PowerReduction) + totalFeesDec := math.LegacyNewDecFromInt(totalFees) + amtFixed12Dec := feeDec.Mul(feeMinusBurnDec).Mul(powerReductionDec).Quo(totalFeesDec) + + amtFixed12 := amtFixed12Dec.TruncateInt() remainder := amtFixed12.Mod(layertypes.PowerReduction) @@ -145,9 +153,16 @@ func (k Keeper) RewardReporterBondToFeePayers(ctx context.Context, feePayer sdk. totalFees := totalFeesPaid fee := payerInfo.Amount - amtFixed12 := fee.Mul(bond).Mul(layertypes.PowerReduction).Quo(totalFees) + feeDec := math.LegacyNewDecFromInt(fee) + bondDec := math.LegacyNewDecFromInt(bond) + totalFeesDec := math.LegacyNewDecFromInt(totalFees) + powerReductionDec := math.LegacyNewDecFromInt(layertypes.PowerReduction) + amtFixed12Dec := feeDec.Mul(bondDec).Mul(powerReductionDec).Quo(totalFeesDec) - amtFixed6 := amtFixed12.Quo(layertypes.PowerReduction) + amtFixed12 := amtFixed12Dec.TruncateInt() + + amtFixed6Dec := amtFixed12Dec.Quo(powerReductionDec) + amtFixed6 := amtFixed6Dec.TruncateInt() if err := k.reporterKeeper.AddAmountToStake(ctx, feePayer, amtFixed6); err != nil { return math.Int{}, err } diff --git a/x/dispute/keeper/msg_server_withdraw_fee_refund.go b/x/dispute/keeper/msg_server_withdraw_fee_refund.go index 84df091b..f7104285 100644 --- a/x/dispute/keeper/msg_server_withdraw_fee_refund.go +++ b/x/dispute/keeper/msg_server_withdraw_fee_refund.go @@ -32,7 +32,9 @@ func (k msgServer) WithdrawFeeRefund(ctx context.Context, msg *types.MsgWithdraw } // handle failed underfunded dispute if dispute.DisputeStatus == types.Failed { - feeMinusBurn := dispute.FeeTotal.Quo(math.NewInt(20)) + disputeFeeTotalDec := math.LegacyNewDecFromInt(dispute.FeeTotal) + feeMinusBurnDec := disputeFeeTotalDec.Quo(math.LegacyNewDec(20)) + feeMinusBurn := feeMinusBurnDec.TruncateInt() fraction, err := k.RefundDisputeFee(ctx, feePayer, payerInfo, dispute.FeeTotal, feeMinusBurn, dispute.HashId) if err != nil { return nil, err @@ -77,7 +79,10 @@ func (k msgServer) WithdrawFeeRefund(ctx context.Context, msg *types.MsgWithdraw } - burnDust := remainder.Quo(layertypes.PowerReduction) + remainderDec := math.LegacyNewDecFromInt(remainder) + powerReductionDec := math.LegacyNewDecFromInt(layertypes.PowerReduction) + burnDustDec := remainderDec.Quo(powerReductionDec) + burnDust := burnDustDec.TruncateInt() if !burnDust.IsZero() { if err := k.bankKeeper.BurnCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(layertypes.BondDenom, burnDust))); err != nil { diff --git a/x/dispute/keeper/tally.go b/x/dispute/keeper/tally.go index 0f55bfe5..6889587c 100644 --- a/x/dispute/keeper/tally.go +++ b/x/dispute/keeper/tally.go @@ -45,8 +45,12 @@ func Ratio(total, part math.Int) math.Int { return math.ZeroInt() } total = total.MulRaw(4) - ratio := part.Mul(layertypes.PowerReduction).Quo(total) - return ratio.MulRaw(100) + totalDec := math.LegacyNewDecFromInt(total) + partDec := math.LegacyNewDecFromInt(part) + powerReductionDec := math.LegacyNewDecFromInt(layertypes.PowerReduction) + ratioDec := partDec.Mul(powerReductionDec).Quo(totalDec).Mul(math.LegacyNewDec(100)) + + return ratioDec.TruncateInt() } // TallyVote determines whether the dispute vote has either reached quorum or the vote period has ended. @@ -56,6 +60,8 @@ func (k Keeper) TallyVote(ctx context.Context, id uint64) error { scaledSupport := math.ZeroInt() scaledAgainst := math.ZeroInt() scaledInvalid := math.ZeroInt() + powerReductionDec := math.LegacyNewDecFromInt(layertypes.PowerReduction) + vote, err := k.Votes.Get(ctx, id) if err != nil { return err @@ -125,12 +131,20 @@ func (k Keeper) TallyVote(ctx context.Context, id uint64) error { tallies.Invalid.Users = math.NewIntFromUint64(voteCounts.Users.Invalid) userVoteSum := tallies.ForVotes.Users.Add(tallies.AgainstVotes.Users).Add(tallies.Invalid.Users) + scaledSupportDec := math.LegacyNewDecFromInt(scaledSupport) + scaledAgainstDec := math.LegacyNewDecFromInt(scaledAgainst) + scaledInvalidDec := math.LegacyNewDecFromInt(scaledInvalid) if userVoteSum.GT(math.ZeroInt()) { totalRatio = totalRatio.Add(Ratio(info.TotalUserTips, userVoteSum)) + userVoteSumDec := math.LegacyNewDecFromInt(userVoteSum) - scaledSupport = scaledSupport.Add(tallies.ForVotes.Users.Mul(layertypes.PowerReduction).Quo(userVoteSum)) - scaledAgainst = scaledAgainst.Add(tallies.AgainstVotes.Users.Mul(layertypes.PowerReduction).Quo(userVoteSum)) - scaledInvalid = scaledInvalid.Add(tallies.Invalid.Users.Mul(layertypes.PowerReduction).Quo(userVoteSum)) + usersForVotesDec := math.LegacyNewDecFromInt(tallies.ForVotes.Users) + usersAgainstVotesDec := math.LegacyNewDecFromInt(tallies.AgainstVotes.Users) + usersInvalidVotesDec := math.LegacyNewDecFromInt(tallies.Invalid.Users) + + scaledSupportDec = scaledSupportDec.Add(usersForVotesDec.Mul(powerReductionDec).Quo(userVoteSumDec)) + scaledAgainstDec = scaledAgainstDec.Add(usersAgainstVotesDec.Mul(powerReductionDec).Quo(userVoteSumDec)) + scaledInvalidDec = scaledInvalidDec.Add(usersInvalidVotesDec.Mul(powerReductionDec).Quo(userVoteSumDec)) } // replace logic above with this @@ -142,18 +156,28 @@ func (k Keeper) TallyVote(ctx context.Context, id uint64) error { totalRatio = totalRatio.Add(reporterRatio) if reporterVoteSum.GT(math.ZeroInt()) { - forReporters := tallies.ForVotes.Reporters.Mul(layertypes.PowerReduction).Quo(reporterVoteSum) - againstReporters := tallies.AgainstVotes.Reporters.Mul(layertypes.PowerReduction).Quo(reporterVoteSum) - invalidReporters := tallies.Invalid.Reporters.Mul(layertypes.PowerReduction).Quo(reporterVoteSum) - scaledSupport = scaledSupport.Add(forReporters) - scaledAgainst = scaledAgainst.Add(againstReporters) - scaledInvalid = scaledInvalid.Add(invalidReporters) + reporterVoteSumDec := math.LegacyNewDecFromInt(reporterVoteSum) + reportersForVotesDec := math.LegacyNewDecFromInt(tallies.ForVotes.Reporters) + reportersAgainstVotesDec := math.LegacyNewDecFromInt(tallies.AgainstVotes.Reporters) + reportersInvalidVotesDec := math.LegacyNewDecFromInt(tallies.Invalid.Reporters) + + forReportersDec := reportersForVotesDec.Mul(powerReductionDec).Quo(reporterVoteSumDec) + againstReportersDec := reportersAgainstVotesDec.Mul(powerReductionDec).Quo(reporterVoteSumDec) + invalidReportersDec := reportersInvalidVotesDec.Mul(powerReductionDec).Quo(reporterVoteSumDec) + scaledSupportDec = scaledSupportDec.Add(forReportersDec) + scaledAgainstDec = scaledAgainstDec.Add(againstReportersDec) + scaledInvalidDec = scaledInvalidDec.Add(invalidReportersDec) } if totalRatio.GTE(math.NewInt(51).Mul(layertypes.PowerReduction)) { - scaledSupport = scaledSupport.Quo(numGroups) - scaledAgainst = scaledAgainst.Quo(numGroups) - scaledInvalid = scaledInvalid.Quo(numGroups) + numGroupsDec := math.LegacyNewDecFromInt(numGroups) + scaledSupportDec = scaledSupportDec.Quo(numGroupsDec) + scaledAgainstDec = scaledAgainstDec.Quo(numGroupsDec) + scaledInvalidDec = scaledInvalidDec.Quo(numGroupsDec) + + scaledSupport = scaledSupportDec.TruncateInt() + scaledAgainst = scaledAgainstDec.TruncateInt() + scaledInvalid = scaledInvalidDec.TruncateInt() dispute.DisputeStatus = types.Resolved dispute.Open = false dispute.PendingExecution = true @@ -170,18 +194,23 @@ func (k Keeper) TallyVote(ctx context.Context, id uint64) error { totalRatio = totalRatio.Add(Ratio(tokenSupply, tokenHolderVoteSum)) if !tokenHolderVoteSum.IsZero() { - forTokenHolders := tallies.ForVotes.TokenHolders.Mul(layertypes.PowerReduction).Quo(tokenHolderVoteSum) - againstTokenHolders := tallies.AgainstVotes.TokenHolders.Mul(layertypes.PowerReduction).Quo(tokenHolderVoteSum) - invalidTokenHolders := tallies.Invalid.TokenHolders.Mul(layertypes.PowerReduction).Quo(tokenHolderVoteSum) - scaledSupport = scaledSupport.Add(forTokenHolders).Quo(numGroups) - scaledAgainst = scaledAgainst.Add(againstTokenHolders).Quo(numGroups) - scaledInvalid = scaledInvalid.Add(invalidTokenHolders).Quo(numGroups) + tokenHolderVoteSumDec := math.LegacyNewDecFromInt(tokenHolderVoteSum) + tokenHoldersForVotesDec := math.LegacyNewDecFromInt(tallies.ForVotes.TokenHolders) + tokenHoldersAgainstVotesDec := math.LegacyNewDecFromInt(tallies.AgainstVotes.TokenHolders) + tokenHoldersInvalidVotesDec := math.LegacyNewDecFromInt(tallies.Invalid.TokenHolders) + + forTokenHoldersDec := tokenHoldersForVotesDec.Mul(powerReductionDec).Quo(tokenHolderVoteSumDec) + againstTokenHoldersDec := tokenHoldersAgainstVotesDec.Mul(powerReductionDec).Quo(tokenHolderVoteSumDec) + invalidTokenHoldersDec := tokenHoldersInvalidVotesDec.Mul(powerReductionDec).Quo(tokenHolderVoteSumDec) + scaledSupportDec = scaledSupportDec.Add(forTokenHoldersDec) + scaledAgainstDec = scaledAgainstDec.Add(againstTokenHoldersDec) + scaledInvalidDec = scaledInvalidDec.Add(invalidTokenHoldersDec) } if totalRatio.GTE(math.NewInt(51).Mul(layertypes.PowerReduction)) { dispute.DisputeStatus = types.Resolved dispute.Open = false dispute.PendingExecution = true - return k.UpdateDispute(ctx, id, dispute, vote, scaledSupport, scaledAgainst, scaledInvalid, true) + return k.UpdateDispute(ctx, id, dispute, vote, scaledSupportDec.TruncateInt(), scaledAgainstDec.TruncateInt(), scaledInvalidDec.TruncateInt(), true) } sdkctx := sdk.UnwrapSDKContext(ctx) // quorum not reached case @@ -205,7 +234,7 @@ func (k Keeper) TallyVote(ctx context.Context, id uint64) error { vote.VoteEnd = sdkctx.BlockTime() return k.Votes.Set(ctx, id, vote) } - return k.UpdateDispute(ctx, id, dispute, vote, scaledSupport, scaledAgainst, scaledInvalid, false) + return k.UpdateDispute(ctx, id, dispute, vote, scaledSupportDec.TruncateInt(), scaledAgainstDec.TruncateInt(), scaledInvalidDec.TruncateInt(), false) } else { return errors.New(types.ErrNoQuorumStillVoting.Error()) } diff --git a/x/reporter/keeper/distribution.go b/x/reporter/keeper/distribution.go index 15d9f9f5..9bd73489 100644 --- a/x/reporter/keeper/distribution.go +++ b/x/reporter/keeper/distribution.go @@ -21,8 +21,15 @@ func (k Keeper) DivvyingTips(ctx context.Context, reporterAddr sdk.AccAddress, r if err != nil { return err } - // Calculate commission - commission := reward.Value.Mul(reporter.CommissionRate).QuoUint64(1000000) + + // Convert arguments needed for calculations to legacy decimals + rewardDec := k.LegacyDecFromMathUint(reward.Value) + commissionRateDec := k.LegacyDecFromMathUint(reporter.CommissionRate) + + // Calculate commission: commission = reward * commissionRate + commissionDec := rewardDec.Mul(commissionRateDec).Quo(math.LegacyNewDec(1000000)) + + commission := k.TruncateUint(commissionDec) // Calculate net reward netReward := reward.Value.Sub(commission) @@ -33,7 +40,12 @@ func (k Keeper) DivvyingTips(ctx context.Context, reporterAddr sdk.AccAddress, r } for _, del := range delAddrs.TokenOrigins { - delegatorShare := netReward.Mul(math.NewUint(del.Amount.Uint64())).Quo(math.NewUint(delAddrs.Total.Uint64())) + // convert args needed for calculations to legacy decimals + netRewardDec := k.LegacyDecFromMathUint(netReward) + delAmountDec := math.LegacyNewDecFromInt(del.Amount) + delTotalDec := math.LegacyNewDecFromInt(delAddrs.Total) + delegatorShareDec := netRewardDec.Mul(delAmountDec).Quo(delTotalDec) + delegatorShare := k.TruncateUint(delegatorShareDec) if bytes.Equal(del.DelegatorAddress, reporterAddr.Bytes()) { delegatorShare = delegatorShare.Add(commission) } @@ -98,7 +110,12 @@ func (k Keeper) ReturnSlashedTokens(ctx context.Context, amt math.Int, hashId [] shareAmt := math.NewUint(source.Amount.Uint64()) if extra.IsPositive() { // add extra tokens based on the share of the delegator - shareAmt = math.NewUint(source.Amount.Uint64()).Mul(math.NewUint(amt.Uint64())).Quo(math.NewUint(snapshot.Total.Uint64())) + // convert args needed for calculations to legacy decimals + sourceAmountDec := math.LegacyNewDecFromInt(source.Amount) + amountDec := math.LegacyNewDecFromInt(amt) + snapshotTotalDec := math.LegacyNewDecFromInt(snapshot.Total) + shareAmtDec := sourceAmountDec.Mul(amountDec).Quo(snapshotTotalDec) + shareAmt = k.TruncateUint(shareAmtDec) } _, err = k.stakingKeeper.Delegate(ctx, delAddr, math.NewInt(int64(shareAmt.Uint64())), tokenSrc, val, false) if err != nil { @@ -134,8 +151,13 @@ func (k Keeper) FeeRefund(ctx context.Context, hashId []byte, amt math.Int) erro val = vals[0] } // since fee paid is returned minus the voter/burned amount, calculate by accordingly - shareAmt := math.LegacyNewDecFromInt(source.Amount).Quo(math.LegacyNewDecFromInt(trackedFees.Total)).Mul(math.LegacyNewDecFromInt(amt)) - _, err = k.stakingKeeper.Delegate(ctx, sdk.AccAddress(source.DelegatorAddress), shareAmt.TruncateInt(), stakingtypes.Bonded, val, false) + // convert args needed for calculations to legacy decimals + sourceAmountDec := math.LegacyNewDecFromInt(source.Amount) + trackedFeesTotalDec := math.LegacyNewDecFromInt(trackedFees.Total) + amtDec := math.LegacyNewDecFromInt(amt) + shareAmtDec := sourceAmountDec.Mul(amtDec).Quo(trackedFeesTotalDec) + shareAmt := shareAmtDec.TruncateInt() + _, err = k.stakingKeeper.Delegate(ctx, sdk.AccAddress(source.DelegatorAddress), shareAmt, stakingtypes.Bonded, val, false) if err != nil { return err } @@ -182,3 +204,13 @@ func (k Keeper) AddAmountToStake(ctx context.Context, acc sdk.AccAddress, amt ma } return nil } + +// Converts a math.Uint to a legacy decimal +func (k Keeper) LegacyDecFromMathUint(value math.Uint) math.LegacyDec { + return math.LegacyNewDecFromInt(math.NewIntFromUint64(value.Uint64())) +} + +// Truncates a legacy decimal to a math.Uint +func (k Keeper) TruncateUint(value math.LegacyDec) math.Uint { + return math.NewUint(value.TruncateInt().Uint64()) +} diff --git a/x/reporter/keeper/msg_server.go b/x/reporter/keeper/msg_server.go index 90b5ff4a..334172fb 100644 --- a/x/reporter/keeper/msg_server.go +++ b/x/reporter/keeper/msg_server.go @@ -303,7 +303,9 @@ func (k msgServer) WithdrawTip(goCtx context.Context, msg *types.MsgWithdrawTip) if !val.IsBonded() { return nil, errors.New("chosen validator must be bonded") } - amtToDelegate := shares.Value.QuoUint64(1e6) + sharesDec := k.LegacyDecFromMathUint(shares.Value) + amtToDelegateDec := sharesDec.Quo(math.LegacyNewDec(1e6)) + amtToDelegate := k.TruncateUint(amtToDelegateDec) if amtToDelegate.IsZero() { return nil, errors.New("no tips to withdraw") } diff --git a/x/reporter/keeper/withdraw.go b/x/reporter/keeper/withdraw.go index 52110194..03c288ad 100644 --- a/x/reporter/keeper/withdraw.go +++ b/x/reporter/keeper/withdraw.go @@ -161,7 +161,13 @@ func (k Keeper) EscrowReporterStake(ctx context.Context, reporterAddr sdk.AccAdd leftover := math.NewUint(amt.Uint64() * 1e6) for i, del := range report.TokenOrigins { truncDelAmount := math.NewUint(del.Amount.Uint64()).QuoUint64(layertypes.PowerReduction.Uint64()).MulUint64(layertypes.PowerReduction.Uint64()) - delegatorShare := truncDelAmount.MulUint64(amt.Uint64()).MulUint64(1e6).Quo(math.NewUint(totalTokens.Uint64())) + // convert args needed for calculations to legacy decimals + truncDelAmountDec := k.LegacyDecFromMathUint(truncDelAmount) + amtDec := math.LegacyNewDecFromInt(amt) + powerReductionDec := math.LegacyNewDecFromInt(layertypes.PowerReduction) + totalTokensDec := math.LegacyNewDecFromInt(totalTokens) + delegatorShareDec := truncDelAmountDec.Mul(amtDec).Mul(powerReductionDec).Quo(totalTokensDec) + delegatorShare := k.TruncateUint(delegatorShareDec) leftover = leftover.Sub(delegatorShare) if i == len(report.TokenOrigins)-1 { @@ -176,7 +182,9 @@ func (k Keeper) EscrowReporterStake(ctx context.Context, reporterAddr sdk.AccAdd return err } storedAmount := delegatorShare.Sub(math.NewUint(remaining.Uint64())) - storedAmountFixed6 := storedAmount.Quo(math.NewUint(1e6)) + storedAmountDec := k.LegacyDecFromMathUint(storedAmount) + storedAmountFixed6Dec := storedAmountDec.Quo(powerReductionDec) + storedAmountFixed6 := k.TruncateUint(storedAmountFixed6Dec) if !storedAmount.IsZero() { disputeTokens = append(disputeTokens, &types.TokenOriginInfo{ DelegatorAddress: del.DelegatorAddress, @@ -185,7 +193,9 @@ func (k Keeper) EscrowReporterStake(ctx context.Context, reporterAddr sdk.AccAdd }) } - remainingFixed6 := remaining.Quo(math.NewUint(1e6)) + remainingDec := k.LegacyDecFromMathUint(remaining) + remainingFixed6Dec := remainingDec.Quo(powerReductionDec) + remainingFixed6 := k.TruncateUint(remainingFixed6Dec) if !remaining.IsZero() { dstVAl, err := k.getDstValidator(ctx, delAddr, valAddr) if err != nil { @@ -243,8 +253,15 @@ func (k Keeper) deductUnbondingDelegation(ctx context.Context, delAddr sdk.AccAd removeAmt = removeAmt.Add(normalizedBalance) ubd.RemoveEntry(int64(i)) } else { - u.Balance = math.NewIntFromUint64(normalizedBalance.Sub(tokens).QuoUint64(1e6).Uint64()) - u.InitialBalance = u.InitialBalance.Sub(math.NewIntFromUint64(tokens.QuoUint64(1e6).Uint64())) + normalizedBalanceDec := k.LegacyDecFromMathUint(normalizedBalance) + tokensDec := k.LegacyDecFromMathUint(tokens) + powerReductionDec := math.LegacyNewDecFromInt(layertypes.PowerReduction) + uBalanceDec := normalizedBalanceDec.Sub(tokensDec).Quo(powerReductionDec) + u.Balance = uBalanceDec.TruncateInt() + + uInitialBalanceDec := math.LegacyNewDecFromInt(u.InitialBalance) + uInitialBalanceDec = uInitialBalanceDec.Sub(tokensDec).Quo(powerReductionDec) + u.InitialBalance = uInitialBalanceDec.TruncateInt() ubd.Entries[i] = u removeAmt = removeAmt.Add(tokens) tokens = math.ZeroUint() @@ -260,7 +277,11 @@ func (k Keeper) deductUnbondingDelegation(ctx context.Context, delAddr sdk.AccAd if err != nil { return math.Uint{}, err } - err = k.tokensToDispute(ctx, stakingtypes.NotBondedPoolName, (math.NewInt(int64(removeAmt.Uint64())).QuoRaw(1e6))) + removeAmtDec := k.LegacyDecFromMathUint(removeAmt) + powerReductionDec := math.LegacyNewDecFromInt(layertypes.PowerReduction) + disputeAmtDec := removeAmtDec.Quo(powerReductionDec) + disputeAmt := disputeAmtDec.TruncateInt() + err = k.tokensToDispute(ctx, stakingtypes.NotBondedPoolName, disputeAmt) if err != nil { return math.Uint{}, err } @@ -286,7 +307,10 @@ func (k Keeper) deductFromdelegation(ctx context.Context, delAddr sdk.AccAddress tokensFromShare := math.NewUint(currentTokens.BigInt().Uint64() * 1e6) // normalize to match with the normalized delTokens shares := del.Shares if tokensFromShare.GTE(delTokens) { - shares, err = validator.SharesFromTokens(math.Int(delTokens.QuoUint64(1e6))) + delTokensDec := k.LegacyDecFromMathUint(delTokens) + powerReductionDec := math.LegacyNewDecFromInt(layertypes.PowerReduction) + tokensAmtDec := delTokensDec.Quo(powerReductionDec) + shares, err = validator.SharesFromTokens(tokensAmtDec.TruncateInt()) if err != nil { return math.Uint{}, err } From 67a06cc0d1e162e6124bf97049da77d3fbee1897 Mon Sep 17 00:00:00 2001 From: danflo27 Date: Fri, 25 Oct 2024 16:24:35 -0400 Subject: [PATCH 3/8] unfinsihed tests --- tests/e2e/basic_dispute_test.go | 756 ++++++++++++++++++++++++++++++++ 1 file changed, 756 insertions(+) diff --git a/tests/e2e/basic_dispute_test.go b/tests/e2e/basic_dispute_test.go index 8ece7cec..ff4c5157 100644 --- a/tests/e2e/basic_dispute_test.go +++ b/tests/e2e/basic_dispute_test.go @@ -642,3 +642,759 @@ func (s *E2ETestSuite) TestDisputes() { // reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) // require.NoError(err) } + + +// Vicky the Validator just produces blocks, has 1000 trb staked +// Rob the Reporter has 100 trb staked with Vicky so he can select himself as the reporter +// Delwood the Delegator has 250 trb delegated to Rob +// Rob stakes 10 more trb through a different reporter account to vicky and makes Rob2 a reporter +// Rob creates a dispute for a good report from Rob2 +// The dispute settles to `No`, moving tokens from Delwood to Rob through proxy of Rob2 ? +func (s *E2ETestSuite) TestDisputeSettlesToNo() { + // Setup msgServers + require := s.Require() + msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) + require.NotNil(msgServerOracle) + msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) + require.NotNil(msgServerReporter) + msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) + require.NotNil(msgServerDispute) + msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) + require.NotNil(msgServerStaking) + + //--------------------------------------------------------------------------- + // Height 0 - vicky becomes a validator + //--------------------------------------------------------------------------- + _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + vickyAccAddr := simtestutil.CreateIncrementalAccounts(1) + vickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) // give vicky extra to act as free floating token voting group + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(vickyInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, vickyAccAddr[0], sdk.NewCoins(vickyInitCoins))) + s.Setup.Accountkeeper.NewAccountWithAddress(s.Setup.Ctx, vickyAccAddr[0]) + + pubKey := simtestutil.CreateTestPubKeys(1) + vickyValAddr := simtestutil.ConvertAddrsToValAddrs(vickyAccAddr) + msgCreateValidator, err := stakingtypes.NewMsgCreateValidator( + vickyValAddr[0].String(), + pubKey[0], + sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), + stakingtypes.Description{Moniker: "created validator"}, + stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(0, 0), math.LegacyNewDecWithPrec(3, 1), math.LegacyNewDecWithPrec(1, 1)), + math.OneInt(), + ) + require.NoError(err) + + _, err = msgServerStaking.CreateValidator(s.Setup.Ctx, msgCreateValidator) + require.NoError(err) + + require.NoError(s.Setup.Bridgekeeper.SetEVMAddressByOperator(s.Setup.Ctx, vickyValAddr[0].String(), []byte("vickyEvmAddr"))) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 1 - Rob delegates to Vicky and selects himself to become a reporter + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // verify vicky is a bonded validator + vickyValidatorInfo, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, vickyValAddr[0]) + require.NoError(err) + require.Equal(vickyValidatorInfo.Status, stakingtypes.Bonded) + require.Equal(vickyValidatorInfo.Tokens, math.NewInt(1000*1e6)) + + robPrivKey := secp256k1.GenPrivKey() + robAccAddr := sdk.AccAddress(robPrivKey.PubKey().Address()) + robInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(robInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, robAccAddr, sdk.NewCoins(robInitCoins))) + + // rob delegates to vicky + msgDelegate := stakingtypes.NewMsgDelegate( + robAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + // rob becomes a reporter + _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ + ReporterAddress: robAccAddr.String(), + CommissionRate: reportertypes.DefaultMinCommissionRate, + MinTokensRequired: math.NewInt(1 * 1e6), + }) + require.NoError(err) + robReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, robAccAddr) + require.NoError(err) + require.Equal(robReporterInfo.Jailed, false) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 2 - Delwood delegates 250 trb to Vicky + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(2) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + delwoodPrivKey := secp256k1.GenPrivKey() + delwoodAccAddr := sdk.AccAddress(delwoodPrivKey.PubKey().Address()) + delwoodInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(delwoodInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, delwoodAccAddr, sdk.NewCoins(delwoodInitCoins))) + + msgDelegate = stakingtypes.NewMsgDelegate( + delwoodAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 3 - Delwood selects 250 trb to Rob + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(3) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = msgServerReporter.SelectReporter(s.Setup.Ctx, &reportertypes.MsgSelectReporter{ + SelectorAddress: delwoodAccAddr.String(), + ReporterAddress: robAccAddr.String(), + }) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 4 - Rob creates a second reporter + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(4) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + rob2PrivKey := secp256k1.GenPrivKey() + rob2AccAddr := sdk.AccAddress(rob2PrivKey.PubKey().Address()) + rob2InitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(50*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(rob2InitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, rob2AccAddr, sdk.NewCoins(rob2InitCoins))) + + // rob delegates to vicky + msgDelegate = stakingtypes.NewMsgDelegate( + rob2AccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(50*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + // rob2 becomes a reporter + _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ + ReporterAddress: rob2AccAddr.String(), + CommissionRate: reportertypes.DefaultMinCommissionRate, + MinTokensRequired: math.NewInt(1 * 1e6), + }) + require.NoError(err) + rob2ReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, rob2AccAddr) + require.NoError(err) + require.Equal(rob2ReporterInfo.Jailed, false) + + // create third party ricky the reporter to vote from reporter group + rickyPrivKey := secp256k1.GenPrivKey() + rickyAccAddr := sdk.AccAddress(rickyPrivKey.PubKey().Address()) + rickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(rickyInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, rickyAccAddr, sdk.NewCoins(rickyInitCoins))) + + // ricky delegates to vicky + msgDelegate = stakingtypes.NewMsgDelegate( + rickyAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + // ricky becomes a reporter + _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ + ReporterAddress: rickyAccAddr.String(), + CommissionRate: reportertypes.DefaultMinCommissionRate, + MinTokensRequired: math.NewInt(1 * 1e6), + }) + require.NoError(err) + rickyReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, rickyAccAddr) + require.NoError(err) + require.Equal(rickyReporterInfo.Jailed, false) + + // ricky tips for more voting power + queryData, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) + require.NoError(err) + msgTip := oracletypes.MsgTip{ + Tipper: rickyAccAddr.String(), + QueryData: queryData, + Amount: sdk.NewCoin(s.Setup.Denom, math.NewInt(10*1e6)), + } + _, err = msgServerOracle.Tip(s.Setup.Ctx, &msgTip) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 5 - Rob2 makes a fine report + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(5) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // balances before reporting/disputing + robReporterStake, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, robAccAddr) + require.NoError(err) + require.Equal(robReporterStake, math.NewInt(350*1e6)) + + rob2ReporterStake, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rob2AccAddr) + require.NoError(err) + require.Equal(rob2ReporterStake, math.NewInt(50*1e6)) + + delwoodSelectionStake, err := s.Setup.Reporterkeeper.GetDelegatorTokensAtBlock(s.Setup.Ctx, delwoodAccAddr, 5) + require.NoError(err) + require.Equal(delwoodSelectionStake, math.NewInt(250*1e6)) + + vickyValidatorStakedTokens, err := s.Setup.Stakingkeeper.GetLastValidatorPower(s.Setup.Ctx, vickyValAddr[0]) + require.NoError(err) + require.Equal(vickyValidatorStakedTokens, int64(2400)) + + // rob2 makes a report + currentCycleList, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) + require.NoError(err) + queryId := utils.QueryIDFromData(currentCycleList) + msgSubmitValue := oracletypes.MsgSubmitValue{ + Creator: rob2AccAddr.String(), + QueryData: currentCycleList, + Value: testutil.EncodeValue(100_000), + } + _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &msgSubmitValue) + require.NoError(err) + + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(7 * time.Second)) + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + getAggReportRequest := oracletypes.QueryGetCurrentAggregateReportRequest{ + QueryId: hex.EncodeToString(queryId), + } + queryServer := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) + result, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest) + require.NoError(err) + require.Equal(int64(0), result.Aggregate.AggregateReportIndex) + require.Equal(testutil.EncodeValue(100_000), result.Aggregate.AggregateValue) + require.Equal(rob2AccAddr.String(), result.Aggregate.AggregateReporter) + require.Equal(queryId, result.Aggregate.QueryId) + require.Equal(int64(50), result.Aggregate.ReporterPower) + require.Equal(int64(5), result.Aggregate.Height) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 6 - Rob disputes Rob2s report (minor - 5%) + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(6) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // double check balances + robReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, robAccAddr) + require.NoError(err) + require.Equal(robReporterStake, math.NewInt(350*1e6)) + + rob2ReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rob2AccAddr) + require.NoError(err) + require.Equal(rob2ReporterStake, math.NewInt(50*1e6)) + + delwoodSelectionStake, err = s.Setup.Reporterkeeper.GetDelegatorTokensAtBlock(s.Setup.Ctx, delwoodAccAddr, 6) + require.NoError(err) + require.Equal(delwoodSelectionStake, math.NewInt(250*1e6)) + + vickyValidatorStakedTokens, err = s.Setup.Stakingkeeper.GetLastValidatorPower(s.Setup.Ctx, vickyValAddr[0]) + require.NoError(err) + require.Equal(vickyValidatorStakedTokens, int64(2400)) + + // rob proposes a minor dispute + report := oracletypes.MicroReport{ + Reporter: rob2AccAddr.String(), + Power: rob2ReporterStake.Quo(layertypes.PowerReduction).Int64(), + QueryId: queryId, + Value: testutil.EncodeValue(100_000), + Timestamp: s.Setup.Ctx.BlockTime(), + BlockNumber: int64(5), + } + + // create msg for propose dispute tx + msgProposeDispute := disputetypes.MsgProposeDispute{ + Creator: robAccAddr.String(), + Report: &report, + DisputeCategory: disputetypes.Minor, + Fee: sdk.NewCoin(s.Setup.Denom, math.NewInt(2.5*1e6)), + PayFromBond: true, + } + + _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) + require.NoError(err) + + disputes, err := s.Setup.Disputekeeper.GetOpenDisputes(s.Setup.Ctx) + require.NoError(err) + require.NotNil(disputes) + require.Equal(len(disputes), 1) + + burnAmount := msgProposeDispute.Fee.Amount.MulRaw(1).QuoRaw(20) + dispute, err := s.Setup.Disputekeeper.Disputes.Get(s.Setup.Ctx, 1) + require.NoError(err) + require.Equal(dispute.DisputeId, uint64(1)) + require.Equal(dispute.DisputeStatus, disputetypes.Voting) + require.Equal(dispute.DisputeCategory, disputetypes.Minor) + require.Equal(dispute.DisputeFee, msgProposeDispute.Fee.Amount.Sub(burnAmount)) + // require.Equal(dispute.BlockNumber, int64(5)) + require.Equal(dispute.DisputeStartBlock, int64(6)) + feepayer, err := s.Setup.Disputekeeper.DisputeFeePayer.Get(s.Setup.Ctx, collections.Join(uint64(1), robAccAddr.Bytes())) + require.NoError(err) + require.Equal(feepayer.Amount, msgProposeDispute.Fee.Amount) + require.Equal(feepayer.FromBond, true) + slashAmount := dispute.SlashAmount + fmt.Println("slashAmount", slashAmount) + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 7 - Everyone votes No on the dispute + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(7) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // rob2 unjails himself + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Hour)) + msgUnjailReporter := reportertypes.MsgUnjailReporter{ + ReporterAddress: rob2AccAddr.String(), + } + _, err = msgServerReporter.UnjailReporter(s.Setup.Ctx, &msgUnjailReporter) + require.NoError(err) + rob2ReporterInfo, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, rob2AccAddr) + require.NoError(err) + require.Equal(rob2ReporterInfo.Jailed, false) + + // check balances + vickyValidatorStakedTokens, err = s.Setup.Stakingkeeper.GetLastValidatorPower(s.Setup.Ctx, vickyValAddr[0]) + require.NoError(err) + require.Equal(vickyValidatorStakedTokens, int64(2395)) // 2.5 trb gone from Rob, 2.5 trb gone from Rob2 + + robReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, robAccAddr) + require.NoError(err) + require.Equal(robReporterStake, math.NewInt(347.5*1e6)) // Paid 5% of 50 trb to open dispute + + rob2ReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rob2AccAddr) + require.NoError(err) + require.Equal(rob2ReporterStake, math.NewInt(47.5*1e6)) // 5% slashed from 50 trb + + delwoodSelectionStake, err = s.Setup.Reporterkeeper.GetDelegatorTokensAtBlock(s.Setup.Ctx, delwoodAccAddr, 7) + require.NoError(err) + delwoodsFee := ((250 * 2.5) / 350) * 1e6 // ((250/350) * 2.5) trb = ~1.785 trb + fmt.Println("delwoodsFee", delwoodsFee) + require.Equal(delwoodSelectionStake, math.NewInt(250*1e6).Sub(math.NewInt(int64(delwoodsFee)))) // ~1.785 of delwoods trb used towards dispute + + // free floating token group votes no + fmt.Println("Vicky's Vote") + msgVoteVicky := disputetypes.MsgVote{ + Voter: vickyAccAddr[0].String(), + Id: dispute.DisputeId, + Vote: disputetypes.VoteEnum_VOTE_AGAINST, + } + voteResponse, err := msgServerDispute.Vote(s.Setup.Ctx, &msgVoteVicky) + require.NoError(err) + require.NotNil(voteResponse) + + // team votes no + fmt.Println("Team's Vote") + teamAddr, err := s.Setup.Disputekeeper.GetTeamAddress(s.Setup.Ctx) + require.NoError(err) + msgVoteTeam := disputetypes.MsgVote{ + Voter: teamAddr.String(), + Id: dispute.DisputeId, + Vote: disputetypes.VoteEnum_VOTE_AGAINST, + } + voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVoteTeam) + require.NoError(err) + require.NotNil(voteResponse) + + // // ricky votes no -- no voting power ? + fmt.Println("Ricky's Vote") + msgVoteRicky := disputetypes.MsgVote{ + Voter: rickyAccAddr.String(), + Id: dispute.DisputeId, + Vote: disputetypes.VoteEnum_VOTE_AGAINST, + } + voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVoteRicky) + require.NoError(err) + require.NotNil(voteResponse) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + // --------------------------------------------------------------------------- + // Height 8 - quorom reached, advance 3 days, tally votes + // --------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(8) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // check on dispute status + disputeByReporter, err := s.Setup.Disputekeeper.GetDisputeByReporter(s.Setup.Ctx, report, disputetypes.Minor) + require.NoError(err) + require.Equal(disputeByReporter.DisputeId, uint64(1)) + require.Equal(disputeByReporter.DisputeStatus, disputetypes.Voting) + require.Equal(disputeByReporter.DisputeCategory, disputetypes.Minor) + require.Equal(disputeByReporter.DisputeFee, msgProposeDispute.Fee.Amount.Sub(burnAmount)) + require.Equal(disputeByReporter.DisputeStartBlock, int64(6)) + + // fast forward 3 days + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(disputekeeper.THREE_DAYS)) + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + // tally votes + err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 1) + require.NoError(err) + + // execute vote + msgExecuteDispute := disputetypes.MsgExecuteDispute{ + CallerAddress: rob2AccAddr.String(), + DisputeId: 1, + } + _, err = msgServerDispute.ExecuteDispute(s.Setup.Ctx, &msgExecuteDispute) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + // --------------------------------------------------------------------------- + // Height 9 - rob2 unjails himself, check balances + // --------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(9) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // check on dispute status + disputeByReporter, err = s.Setup.Disputekeeper.GetDisputeByReporter(s.Setup.Ctx, report, disputetypes.Minor) + require.NoError(err) + require.Equal(disputeByReporter.DisputeId, uint64(1)) + require.Equal(disputeByReporter.DisputeStatus, disputetypes.Resolved) + + // robReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, robAccAddr) + // require.NoError(err) + // require.Equal(robReporterStake, math.NewInt(350*1e6)) + + // rob2ReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rob2AccAddr) + // require.NoError(err) + // require.Equal(rob2ReporterStake, math.NewInt(50*1e6)) + + // delwoodSelectionStake, err = s.Setup.Reporterkeeper.GetDelegatorTokensAtBlock(s.Setup.Ctx, delwoodAccAddr, 6) + // require.NoError(err) + // require.Equal(delwoodSelectionStake, math.NewInt(250*1e6)) + + // vickyValidatorStakedTokens, err = s.Setup.Stakingkeeper.GetLastValidatorPower(s.Setup.Ctx, vickyValAddr[0]) + // require.NoError(err) + // require.Equal(vickyValidatorStakedTokens, int64(2400)) + + // FINAL RESULTS: + vickyFreeFloating := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, vickyAccAddr[0], s.Setup.Denom) + vickyStaked, err := s.Setup.Stakingkeeper.GetLastValidatorPower(s.Setup.Ctx, vickyValAddr[0]) + require.NoError(err) + fmt.Println("\nvicky before the dispute: ", 2400) + fmt.Println("vickyStaked: ", vickyStaked) + fmt.Println("vickyFreeFloating: ", vickyFreeFloating.Amount) + fmt.Println("vicky total after dispute: ", vickyStaked+vickyFreeFloating.Amount.Int64()) + + robFreeFloating := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, robAccAddr, s.Setup.Denom) + robReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, robAccAddr) + require.NoError(err) + fmt.Println("\nrob before the dispute: ", 350) + fmt.Println("robReporterStake", robReporterStake) + fmt.Println("robFreeFloating: ", robFreeFloating.Amount) + fmt.Println("rob total after dispute: ", robReporterStake.Int64()+robFreeFloating.Amount.Int64()) + + rob2FreeFloating := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, rob2AccAddr, s.Setup.Denom) + rob2ReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rob2AccAddr) + require.NoError(err) + fmt.Println("\nrob2 before the dispute: ", 50) + fmt.Println("rob2ReporterStake", rob2ReporterStake) + fmt.Println("rob2FreeFloating: ", rob2FreeFloating.Amount) + fmt.Println("rob2 total after dispute: ", rob2ReporterStake.Int64()+rob2FreeFloating.Amount.Int64()) + + delwoodFreeFloating := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, delwoodAccAddr, s.Setup.Denom) + delwoodSelectionStake, err = s.Setup.Reporterkeeper.GetDelegatorTokensAtBlock(s.Setup.Ctx, delwoodAccAddr, 9) + require.NoError(err) + fmt.Println("\ndelwood before the dispute: ", 250) + fmt.Println("delwoodSelectionStake", delwoodSelectionStake) + fmt.Println("delwoodFreeFloating: ", delwoodFreeFloating.Amount) + fmt.Println("delwood total after dispute: ", delwoodSelectionStake.Int64()+delwoodFreeFloating.Amount.Int64()) + + rickyFreeFloating := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, rickyAccAddr, s.Setup.Denom) + rickyReporterStake, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rickyAccAddr) + require.NoError(err) + fmt.Println("\nricky before the dispute: ", 1999) + fmt.Println("rickyReporterStake", rickyReporterStake) + fmt.Println("rickyFreeFloating: ", rickyFreeFloating.Amount) + fmt.Println("ricky total after dispute: ", rickyReporterStake.Int64()+rickyFreeFloating.Amount.Int64()) +} + +// Vicky the Validator has 1000 trb staked +// Rob the Reporter has 100 trb staked with Vicky, selects himself as a reporter +// Ricky the Reporter has 100 trb staked with Vicky, selects himself as a reporter +// Delwood the Delegator has 250 trb delegated to Rob +// Delwood tries to dispute a report from Ricky to eliminate his competition +// fails +func (s *E2ETestSuite) TestDisputeFromDelegatorPayFromBond() { + // Setup msgServers + require := s.Require() + msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) + require.NotNil(msgServerOracle) + msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) + require.NotNil(msgServerReporter) + msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) + require.NotNil(msgServerDispute) + msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) + require.NotNil(msgServerStaking) + + //--------------------------------------------------------------------------- + // Height 0 - vicky becomes a validator + //--------------------------------------------------------------------------- + _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + vickyAccAddr := simtestutil.CreateIncrementalAccounts(1) + vickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) // give vicky extra to act as free floating token voting group + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(vickyInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, vickyAccAddr[0], sdk.NewCoins(vickyInitCoins))) + s.Setup.Accountkeeper.NewAccountWithAddress(s.Setup.Ctx, vickyAccAddr[0]) + + pubKey := simtestutil.CreateTestPubKeys(1) + vickyValAddr := simtestutil.ConvertAddrsToValAddrs(vickyAccAddr) + msgCreateValidator, err := stakingtypes.NewMsgCreateValidator( + vickyValAddr[0].String(), + pubKey[0], + sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), + stakingtypes.Description{Moniker: "created validator"}, + stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(0, 0), math.LegacyNewDecWithPrec(3, 1), math.LegacyNewDecWithPrec(1, 1)), + math.OneInt(), + ) + require.NoError(err) + + _, err = msgServerStaking.CreateValidator(s.Setup.Ctx, msgCreateValidator) + require.NoError(err) + + require.NoError(s.Setup.Bridgekeeper.SetEVMAddressByOperator(s.Setup.Ctx, vickyValAddr[0].String(), []byte("vickyEvmAddr"))) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 1 - Rob delegates to Vicky and selects himself to become a reporter + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // verify vicky is a bonded validator + vickyValidatorInfo, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, vickyValAddr[0]) + require.NoError(err) + require.Equal(vickyValidatorInfo.Status, stakingtypes.Bonded) + require.Equal(vickyValidatorInfo.Tokens, math.NewInt(1000*1e6)) + + robPrivKey := secp256k1.GenPrivKey() + robAccAddr := sdk.AccAddress(robPrivKey.PubKey().Address()) + robInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(robInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, robAccAddr, sdk.NewCoins(robInitCoins))) + + // rob delegates to vicky + msgDelegate := stakingtypes.NewMsgDelegate( + robAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + // rob becomes a reporter + _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ + ReporterAddress: robAccAddr.String(), + CommissionRate: reportertypes.DefaultMinCommissionRate, + MinTokensRequired: math.NewInt(1 * 1e6), + }) + require.NoError(err) + robReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, robAccAddr) + require.NoError(err) + require.Equal(robReporterInfo.Jailed, false) + + rickyPrivKey := secp256k1.GenPrivKey() + rickyAccAddr := sdk.AccAddress(rickyPrivKey.PubKey().Address()) + rickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(rickyInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, rickyAccAddr, sdk.NewCoins(rickyInitCoins))) + + // ricky delegates to vicky + msgDelegate = stakingtypes.NewMsgDelegate( + rickyAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + // ricky becomes a reporter + _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ + ReporterAddress: rickyAccAddr.String(), + CommissionRate: reportertypes.DefaultMinCommissionRate, + MinTokensRequired: math.NewInt(1 * 1e6), + }) + require.NoError(err) + rickyReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, rickyAccAddr) + require.NoError(err) + require.Equal(rickyReporterInfo.Jailed, false) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 2 - Delwood delegates 250 trb to Vicky + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(2) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + delwoodPrivKey := secp256k1.GenPrivKey() + delwoodAccAddr := sdk.AccAddress(delwoodPrivKey.PubKey().Address()) + delwoodInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(delwoodInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, delwoodAccAddr, sdk.NewCoins(delwoodInitCoins))) + + msgDelegate = stakingtypes.NewMsgDelegate( + delwoodAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 3 - Delwood selects 250 trb to Rob + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(3) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = msgServerReporter.SelectReporter(s.Setup.Ctx, &reportertypes.MsgSelectReporter{ + SelectorAddress: delwoodAccAddr.String(), + ReporterAddress: robAccAddr.String(), + }) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 4 - Ricky reports for the cycle list + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(4) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + currentCycleList, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) + require.NoError(err) + queryId := utils.QueryIDFromData(currentCycleList) + msgSubmitValue := oracletypes.MsgSubmitValue{ + Creator: rickyAccAddr.String(), + QueryData: currentCycleList, + Value: testutil.EncodeValue(100_000), + } + _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &msgSubmitValue) + require.NoError(err) + + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(7 * time.Second)) + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + getAggReportRequest := oracletypes.QueryGetCurrentAggregateReportRequest{ + QueryId: hex.EncodeToString(queryId), + } + queryServer := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) + result, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest) + require.NoError(err) + require.Equal(int64(0), result.Aggregate.AggregateReportIndex) + require.Equal(testutil.EncodeValue(100_000), result.Aggregate.AggregateValue) + require.Equal(rickyAccAddr.String(), result.Aggregate.AggregateReporter) + require.Equal(queryId, result.Aggregate.QueryId) + require.Equal(int64(1000), result.Aggregate.ReporterPower) + require.Equal(int64(4), result.Aggregate.Height) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 5 - Delwood proposes a dispute from bond + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(5) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + rickyReporterStake, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rickyAccAddr) + require.NoError(err) + + report := oracletypes.MicroReport{ + Reporter: rickyAccAddr.String(), + Power: rickyReporterStake.Quo(layertypes.PowerReduction).Int64(), + QueryId: queryId, + Value: testutil.EncodeValue(100_000), + Timestamp: s.Setup.Ctx.BlockTime(), + BlockNumber: int64(4), + } + + msgProposeDispute := disputetypes.MsgProposeDispute{ + Creator: delwoodAccAddr.String(), + Report: &report, + DisputeCategory: disputetypes.Warning, + Fee: sdk.NewCoin(s.Setup.Denom, math.NewInt(10*1e6)), + PayFromBond: true, + } + + _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) + require.Error(err) +} + +// test precision loss throughout tip/report/dispute/claim process + From 53a20dbd93b024bc2beedae8bfeb94654dc647e8 Mon Sep 17 00:00:00 2001 From: tkernell Date: Fri, 25 Oct 2024 15:44:05 -0500 Subject: [PATCH 4/8] fix --- x/reporter/keeper/withdraw.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/reporter/keeper/withdraw.go b/x/reporter/keeper/withdraw.go index 03c288ad..7855ac4d 100644 --- a/x/reporter/keeper/withdraw.go +++ b/x/reporter/keeper/withdraw.go @@ -260,7 +260,7 @@ func (k Keeper) deductUnbondingDelegation(ctx context.Context, delAddr sdk.AccAd u.Balance = uBalanceDec.TruncateInt() uInitialBalanceDec := math.LegacyNewDecFromInt(u.InitialBalance) - uInitialBalanceDec = uInitialBalanceDec.Sub(tokensDec).Quo(powerReductionDec) + uInitialBalanceDec = uInitialBalanceDec.Sub(tokensDec.Quo(powerReductionDec)) u.InitialBalance = uInitialBalanceDec.TruncateInt() ubd.Entries[i] = u removeAmt = removeAmt.Add(tokens) From c63bd7a0a2a45d6fe0a30aee54f0dca0611f4afb Mon Sep 17 00:00:00 2001 From: tkernell Date: Fri, 25 Oct 2024 15:47:24 -0500 Subject: [PATCH 5/8] testnet blobstream reset --- evm/contracts/bridge/BlobstreamO.sol | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/evm/contracts/bridge/BlobstreamO.sol b/evm/contracts/bridge/BlobstreamO.sol index e94555ca..3d1e2de3 100644 --- a/evm/contracts/bridge/BlobstreamO.sol +++ b/evm/contracts/bridge/BlobstreamO.sol @@ -45,6 +45,7 @@ contract BlobstreamO is ECDSA { uint256 public validatorTimestamp; /// Timestamp of the block where validator set is updated. address public deployer; /// Address that deployed the contract. bool public initialized; /// True if the contract is initialized. + bool public isTestnet = true; /// True if the contract is on testnet. /*Events*/ event ValidatorSetUpdated(uint256 _powerThreshold, uint256 _validatorTimestamp, bytes32 _validatorSetHash); @@ -58,6 +59,7 @@ contract BlobstreamO is ECDSA { error NotConsensusValue(); error NotDeployer(); error NotGuardian(); + error NotTestnet(); error StaleValidatorSet(); error SuppliedValidatorSetInvalid(); error ValidatorSetNotStale(); @@ -118,6 +120,34 @@ contract BlobstreamO is ECDSA { lastValidatorSetCheckpoint = _validatorSetCheckpoint; } + /// @notice This function is called by the guardian to reset the validator set + /// on testnet. Not to be used on mainnet. + /// @param _powerThreshold Amount of voting power needed to approve operations. + /// @param _validatorTimestamp The timestamp of the block where validator set is updated. + /// @param _validatorSetCheckpoint The hash of the validator set. + function guardianResetValidatorSetTestnet( + uint256 _powerThreshold, + uint256 _validatorTimestamp, + bytes32 _validatorSetCheckpoint + ) external { + if (msg.sender != guardian) { + revert NotGuardian(); + } + if (!isTestnet) { + revert NotTestnet(); + } + powerThreshold = _powerThreshold; + validatorTimestamp = _validatorTimestamp; + lastValidatorSetCheckpoint = _validatorSetCheckpoint; + } + + function guardianThrowAwayReset() external { + if (msg.sender != guardian) { + revert NotGuardian(); + } + isTestnet = false; + } + /// @notice This updates the validator set by checking that the validators /// in the current validator set have signed off on the new validator set. /// @param _newValidatorSetHash The hash of the new validator set. From 207582f4e723c70a28a2d2d87efb80578823db3e Mon Sep 17 00:00:00 2001 From: danflo27 Date: Wed, 30 Oct 2024 13:25:30 -0400 Subject: [PATCH 6/8] tests --- tests/e2e/basic_dispute_test.go | 1400 -------------------- tests/e2e/basic_reporting_test.go | 793 ----------- tests/e2e/e2e_test.go | 620 --------- tests/setup.go | 162 +++ x/oracle/abci.go | 23 +- x/oracle/keeper/msg_server_submit_value.go | 2 + x/oracle/keeper/submit_value.go | 3 + 7 files changed, 178 insertions(+), 2825 deletions(-) delete mode 100644 tests/e2e/basic_dispute_test.go delete mode 100644 tests/e2e/basic_reporting_test.go diff --git a/tests/e2e/basic_dispute_test.go b/tests/e2e/basic_dispute_test.go deleted file mode 100644 index ff4c5157..00000000 --- a/tests/e2e/basic_dispute_test.go +++ /dev/null @@ -1,1400 +0,0 @@ -package e2e_test - -import ( - "encoding/hex" - "fmt" - "time" - - "github.com/tellor-io/layer/testutil" - utils "github.com/tellor-io/layer/utils" - disputekeeper "github.com/tellor-io/layer/x/dispute/keeper" - disputetypes "github.com/tellor-io/layer/x/dispute/types" - oraclekeeper "github.com/tellor-io/layer/x/oracle/keeper" - oracletypes "github.com/tellor-io/layer/x/oracle/types" - reporterkeeper "github.com/tellor-io/layer/x/reporter/keeper" - reportertypes "github.com/tellor-io/layer/x/reporter/types" - - collections "cosmossdk.io/collections" - math "cosmossdk.io/math" - - secp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -func (s *E2ETestSuite) TestDisputes() { - require := s.Require() - msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) - require.NotNil(msgServerOracle) - msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) - require.NotNil(msgServerReporter) - msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) - require.NotNil(msgServerDispute) - msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) - require.NotNil(msgServerStaking) - - //--------------------------------------------------------------------------- - // Height 0 - create validator and 2 reporters - //--------------------------------------------------------------------------- - _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // create a validator - valAccount := simtestutil.CreateIncrementalAccounts(1) - // mint 5000*1e8 tokens for validator - initCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(5000*1e8)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, valAccount[0], sdk.NewCoins(initCoins))) - // get val address - valAccountValAddrs := simtestutil.ConvertAddrsToValAddrs(valAccount) - // create pub key for validator - pubKey := simtestutil.CreateTestPubKeys(1) - // tell keepers about the new validator - s.Setup.Accountkeeper.NewAccountWithAddress(s.Setup.Ctx, valAccount[0]) - msgCreateValidaotr, err := stakingtypes.NewMsgCreateValidator( - valAccountValAddrs[0].String(), - pubKey[0], - sdk.NewCoin(s.Setup.Denom, math.NewInt(4000*1e8)), - stakingtypes.Description{Moniker: "created validator"}, - stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(0, 0), math.LegacyNewDecWithPrec(3, 1), math.LegacyNewDecWithPrec(1, 1)), - math.OneInt(), - ) - require.NoError(err) - _, err = msgServerStaking.CreateValidator(s.Setup.Ctx, msgCreateValidaotr) - require.NoError(err) - for _, val := range valAccountValAddrs { - err := s.Setup.Bridgekeeper.SetEVMAddressByOperator(s.Setup.Ctx, val.String(), []byte("not real")) - s.NoError(err) - } - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - validator, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, valAccountValAddrs[0]) - require.NoError(err) - - type Delegator struct { - delegatorAddress sdk.AccAddress - validator stakingtypes.Validator - tokenAmount math.Int - } - pk := secp256k1.GenPrivKey() - reporterAccount := sdk.AccAddress(pk.PubKey().Address()) - // mint 5000*1e6 tokens for reporter - s.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) - s.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, reporterAccount, sdk.NewCoins(initCoins))) - // delegate 5k trb to validator so reporter can delegate to themselves - reporterDelToVal := Delegator{delegatorAddress: reporterAccount, validator: validator, tokenAmount: math.NewInt(4000 * 1e6)} - msgDelegate := stakingtypes.NewMsgDelegate( - reporterDelToVal.delegatorAddress.String(), - reporterDelToVal.validator.GetOperator(), sdk.NewCoin(s.Setup.Denom, reporterDelToVal.tokenAmount), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - // // check that reporter was created in Reporters collections - _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ReporterAddress: reporterAccount.String(), CommissionRate: reportertypes.DefaultMinCommissionRate, MinTokensRequired: math.NewInt(4000 * 1e6)}) - require.NoError(err) - reporter, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) - fmt.Println(reporterAccount.String()) - require.NoError(err) - require.Equal(reporter.Jailed, false) - // // check on reporter in Delegators collections - rkDelegation, err := s.Setup.Reporterkeeper.Selectors.Get(s.Setup.Ctx, reporterAccount) - require.NoError(err) - require.Equal(rkDelegation.Reporter, reporterAccount.Bytes()) - - // check on reporter/validator delegation - skDelegation, err := s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount, valAccountValAddrs[0]) - require.NoError(err) - require.Equal(skDelegation.GetDelegatorAddr(), reporterAccount.String()) - require.Equal(skDelegation.GetValidatorAddr(), validator.GetOperator()) - - //--------------------------------------------------------------------------- - // Height 1 - direct reveal for cycle list - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - // get new cycle list query data - cycleListQuery, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) - require.NoError(err) - // create reveal message - value := testutil.EncodeValue(100_000) - require.NoError(err) - reveal := oracletypes.MsgSubmitValue{ - Creator: reporterAccount.String(), - QueryData: cycleListQuery, - Value: value, - } - // send reveal message - revealResponse, err := msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) - revealBlock := s.Setup.Ctx.BlockHeight() - require.NoError(err) - require.NotNil(revealResponse) - // advance block height to expire the query and aggregate report - - //--------------------------------------------------------------------------- - // Height 2 - advance block to expire query - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - //--------------------------------------------------------------------------- - // Height 3 - advance block to expire query - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - //--------------------------------------------------------------------------- - // Height 4 - check on aggregate - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // get queryId for GetAggregatedReportRequest - queryId := utils.QueryIDFromData(cycleListQuery) - s.NoError(err) - // create get aggregated report query - getAggReportRequest := oracletypes.QueryGetCurrentAggregateReportRequest{ - QueryId: hex.EncodeToString(queryId), - } - // aggregated report is stored correctly - queryServer := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) - result, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest) - require.NoError(err) - require.Equal(uint64(0), result.Aggregate.AggregateReportIndex) - require.Equal(testutil.EncodeValue(100_000), result.Aggregate.AggregateValue) - require.Equal(reporterAccount.String(), result.Aggregate.AggregateReporter) - require.Equal(queryId, result.Aggregate.QueryId) - require.Equal(uint64(4000), result.Aggregate.ReporterPower) - require.Equal(uint64(3), result.Aggregate.Height) - - //--------------------------------------------------------------------------- - // Height 5 - create a dispute - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) - require.NoError(err) - require.Equal(reporter.Jailed, false) - freeFloatingBalanceBefore := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterAccount, s.Setup.Denom) - - balBeforeDispute, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, reporterAccount) - require.NoError(err) - onePercent := balBeforeDispute.Mul(math.NewInt(1)).Quo(math.NewInt(100)) - disputeFee := sdk.NewCoin(s.Setup.Denom, onePercent) // warning should be 1% of bonded tokens - - // todo: is there a getter for this ? - // get microreport for dispute - report := oracletypes.MicroReport{ - Reporter: reporterAccount.String(), - Power: balBeforeDispute.Quo(sdk.DefaultPowerReduction).Uint64(), - QueryId: queryId, - Value: value, - Timestamp: s.Setup.Ctx.BlockTime(), - BlockNumber: uint64(revealBlock), - } - - // create msg for propose dispute tx - msgProposeDispute := disputetypes.MsgProposeDispute{ - Creator: reporterAccount.String(), - Report: &report, - DisputeCategory: disputetypes.Warning, - Fee: disputeFee, - PayFromBond: false, - } - - // send propose dispute tx - _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) - require.NoError(err) - - burnAmount := disputeFee.Amount.MulRaw(1).QuoRaw(20) - disputes, err := s.Setup.Disputekeeper.GetOpenDisputes(s.Setup.Ctx) - require.NoError(err) - require.NotNil(disputes) - require.Equal(1, len(disputes)) - // dispute is created correctly - dispute, err := s.Setup.Disputekeeper.Disputes.Get(s.Setup.Ctx, 1) - require.NoError(err) - require.Equal(dispute.DisputeId, uint64(1)) - require.Equal(dispute.DisputeStatus, disputetypes.Voting) - require.Equal(dispute.DisputeCategory, disputetypes.Warning) - require.Equal(dispute.DisputeFee, disputeFee.Amount.Sub(burnAmount)) - feepayer, err := s.Setup.Disputekeeper.DisputeFeePayer.Get(s.Setup.Ctx, collections.Join(uint64(1), reporterAccount.Bytes())) - require.NoError(err) - require.Equal(feepayer.Amount, disputeFee.Amount) - require.Equal(feepayer.FromBond, false) - slashAmount := dispute.SlashAmount - firstDisputeVoteMsg := disputetypes.MsgVote{ - Voter: reporterAccount.String(), - Id: dispute.DisputeId, - Vote: disputetypes.VoteEnum_VOTE_SUPPORT, - } - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 6 - unjail reporter - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, dispute.DisputeId) - require.Error(err, "vote period not ended and quorum not reached") - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // reporter is in jail - reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) - require.NoError(err) - require.Equal(reporter.Jailed, true) - // reporter lost 1% of their free floating tokens - freeFloatingBalanceAfter := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterAccount, s.Setup.Denom) - require.Equal(freeFloatingBalanceAfter, freeFloatingBalanceBefore.Sub(disputeFee)) - - // create msgUnJailReporter - msgUnjailReporter := reportertypes.MsgUnjailReporter{ - ReporterAddress: reporterAccount.String(), - } - // send unjailreporter tx - _, err = msgServerReporter.UnjailReporter(s.Setup.Ctx, &msgUnjailReporter) - require.NoError(err) - - // reporter is now unjailed - reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) - require.NoError(err) - require.Equal(reporter.Jailed, false) - freeFloatingBalanceAfter = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterAccount, s.Setup.Denom) - require.Equal(freeFloatingBalanceAfter, freeFloatingBalanceBefore.Sub(disputeFee)) - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - // todo: more balance checks at each step - - //--------------------------------------------------------------------------- - // Height 7 - direct reveal for cycle list again - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 1) - require.Error(err, "vote period not ended and quorum not reached") - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // get new cycle list query data - cycleListQuery, err = s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) - require.NoError(err) - // create reveal message - value = testutil.EncodeValue(100_000) - require.NoError(err) - reveal = oracletypes.MsgSubmitValue{ - Creator: reporterAccount.String(), - QueryData: cycleListQuery, - Value: value, - } - secReportQueryId := utils.QueryIDFromData(cycleListQuery) - // send reveal message - revealResponse, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) - revealBlock = s.Setup.Ctx.BlockHeight() - require.NoError(err) - require.NotNil(revealResponse) - // advance block height to expire the query and aggregate report - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 8 - advance block to expire query - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - //--------------------------------------------------------------------------- - // Height 9 - advance block to expire query - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - // get queryId for GetAggregatedReportRequest - queryId = utils.QueryIDFromData(cycleListQuery) - s.NoError(err) - // create get aggregated report query - getAggReportRequest = oracletypes.QueryGetCurrentAggregateReportRequest{ - QueryId: hex.EncodeToString(queryId), - } - // aggregated report is stored correctly - result, err = queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest) - require.NoError(err) - require.Equal(uint64(0), result.Aggregate.AggregateReportIndex) - require.Equal(testutil.EncodeValue(100_000), result.Aggregate.AggregateValue) - require.Equal(reporterAccount.String(), result.Aggregate.AggregateReporter) - require.Equal(queryId, result.Aggregate.QueryId) - require.Equal(uint64(4000)-slashAmount.Quo(sdk.DefaultPowerReduction).Uint64(), result.Aggregate.ReporterPower) - require.Equal(uint64(7), result.Aggregate.Height) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 10 - open minor dispute - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - balBeforeDispute, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, reporterAccount) - fmt.Println("Balance before dispute: ", balBeforeDispute) - require.NoError(err) - fivePercent := balBeforeDispute.Mul(math.NewInt(5)).Quo(math.NewInt(100)) - disputeFee = sdk.NewCoin(s.Setup.Denom, fivePercent) - - report = oracletypes.MicroReport{ - Reporter: reporterAccount.String(), - Power: balBeforeDispute.Quo(sdk.DefaultPowerReduction).Uint64(), - QueryId: secReportQueryId, - Value: value, - Timestamp: s.Setup.Ctx.BlockTime(), - BlockNumber: uint64(revealBlock), - } - - fmt.Println("Report power: ", report.Power) - - // create msg for propose dispute tx - msgProposeDispute = disputetypes.MsgProposeDispute{ - Creator: reporterAccount.String(), - Report: &report, - DisputeCategory: disputetypes.Minor, - Fee: disputeFee, - PayFromBond: false, - } - - // send propose dispute tx - _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) - require.NoError(err) - disputeStartTime := s.Setup.Ctx.BlockTime() - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 11 - vote on minor dispute - // --------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 1) - require.Error(err, "vote period not ended and quorum not reached") - err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 2) - require.Error(err, "vote period not ended and quorum not reached") - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // reporter is in jail - reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) - require.NoError(err) - require.Equal(reporter.Jailed, true) - // dispute is created correctly - burnAmount = disputeFee.Amount.MulRaw(1).QuoRaw(20) - dispute, err = s.Setup.Disputekeeper.GetDisputeByReporter(s.Setup.Ctx, report, disputetypes.Minor) - fmt.Printf("Dispute: %v,\r Report: %v\r", dispute, report) - require.NoError(err) - require.Equal(dispute.DisputeCategory, disputetypes.Minor) - require.Equal(dispute.DisputeStatus, disputetypes.Voting) - require.Equal(dispute.DisputeFee, disputeFee.Amount.Sub(burnAmount)) - feepayer, err = s.Setup.Disputekeeper.DisputeFeePayer.Get(s.Setup.Ctx, collections.Join(dispute.DisputeId, reporterAccount.Bytes())) - require.NoError(err) - require.Equal(feepayer.Amount, disputeFee.Amount) - require.Equal(feepayer.FromBond, false) - - firstVoteReponse, err := msgServerDispute.Vote(s.Setup.Ctx, &firstDisputeVoteMsg) - require.NoError(err) - require.NotNil(firstVoteReponse) - - // create vote tx msg - msgVote := disputetypes.MsgVote{ - Voter: reporterAccount.String(), - Id: dispute.DisputeId, - Vote: disputetypes.VoteEnum_VOTE_SUPPORT, - } - // send vote tx for second dispute - voteResponse, err := msgServerDispute.Vote(s.Setup.Ctx, &msgVote) - require.NoError(err) - require.NotNil(voteResponse) - - // vote is properly stored - vote, err := s.Setup.Disputekeeper.Votes.Get(s.Setup.Ctx, dispute.DisputeId) - require.NoError(err) - require.NotNil(vote) - require.Equal(vote.Executed, false) - require.Equal(vote.Id, dispute.DisputeId) - require.Equal(vote.VoteStart, disputeStartTime) - require.Equal(vote.VoteEnd, disputeStartTime.Add(disputekeeper.TWO_DAYS)) - - // advance 2 days to expire vote - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(disputekeeper.THREE_DAYS)) - // call unjail function - msgUnjailReporter = reportertypes.MsgUnjailReporter{ - ReporterAddress: reporterAccount.String(), - } - _, err = msgServerReporter.UnjailReporter(s.Setup.Ctx, &msgUnjailReporter) - require.NoError(err) - - // reporter no longer in jail - reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) - require.NoError(err) - require.Equal(reporter.Jailed, false) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 12 - minor dispute ends and another direct reveal for cycle list - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - require.NoError(s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 1)) - require.NoError(s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 2)) - require.NoError(s.Setup.Disputekeeper.ExecuteVote(s.Setup.Ctx, 1)) - require.NoError(s.Setup.Disputekeeper.ExecuteVote(s.Setup.Ctx, 2)) - - // vote is executed - vote, err = s.Setup.Disputekeeper.Votes.Get(s.Setup.Ctx, dispute.DisputeId) - require.NoError(err) - require.NotNil(vote) - require.Equal(vote.Executed, true) - require.Equal(vote.Id, dispute.DisputeId) - // reporter no longer in jail - reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) - require.NoError(err) - require.Equal(reporter.Jailed, false) - - // get open disputes - disputes, err = s.Setup.Disputekeeper.GetOpenDisputes(s.Setup.Ctx) - require.NoError(err) - require.NotNil(disputes) - - cycleListQuery, err = s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) - require.NoError(err) - // create reveal message - value = testutil.EncodeValue(100_000) - require.NoError(err) - reveal = oracletypes.MsgSubmitValue{ - Creator: reporterAccount.String(), - QueryData: cycleListQuery, - Value: value, - } - // send reveal message - revealResponse, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) - revealBlock = s.Setup.Ctx.BlockHeight() - require.NoError(err) - require.NotNil(revealResponse) - // advance time and block height to expire the query and aggregate report - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(21 * time.Second)) - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - // get queryId for GetAggregatedReportRequest - queryId = utils.QueryIDFromData(cycleListQuery) - s.NoError(err) - // create get aggregated report query - getAggReportRequest = oracletypes.QueryGetCurrentAggregateReportRequest{ - QueryId: hex.EncodeToString(queryId), - } - // check that aggregated report is stored correctly - result, err = queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest) - require.NoError(err) - require.Equal(uint64(0), result.Aggregate.AggregateReportIndex) - require.Equal(testutil.EncodeValue(100_000), result.Aggregate.AggregateValue) - require.Equal(reporterAccount.String(), result.Aggregate.AggregateReporter) - require.Equal(queryId, result.Aggregate.QueryId) - require.Equal(uint64(7), result.Aggregate.Height) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 13 - open major dispute for report - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) - require.NoError(err) - require.Equal(reporter.Jailed, false) - - oneHundredPercent, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, reporterAccount) - require.NoError(err) - disputeFee = sdk.NewCoin(s.Setup.Denom, oneHundredPercent) - - report = oracletypes.MicroReport{ - Reporter: reporterAccount.String(), - Power: oneHundredPercent.Quo(sdk.DefaultPowerReduction).Uint64(), - QueryId: queryId, - Value: value, - Timestamp: s.Setup.Ctx.BlockTime(), - BlockNumber: uint64(revealBlock), - } - // create msg for propose dispute tx - - msgProposeDispute = disputetypes.MsgProposeDispute{ - Creator: reporterAccount.String(), - Report: &report, - DisputeCategory: disputetypes.Major, - Fee: disputeFee, - PayFromBond: false, - } - - // send propose dispute tx - _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) - require.NoError(err) - disputeStartTime = s.Setup.Ctx.BlockTime() - disputeStartHeight := uint64(s.Setup.Ctx.BlockHeight()) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 9 - vote on major dispute - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 3) - require.Error(err, "vote period not ended and quorum not reached") - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - fee, err := s.Setup.Disputekeeper.GetDisputeFee(s.Setup.Ctx, report, disputetypes.Major) - require.NoError(err) - require.GreaterOrEqual(msgProposeDispute.Fee.Amount.Uint64(), fee.Uint64()) - - // dispute is created and open for voting - dispute, err = s.Setup.Disputekeeper.GetDisputeByReporter(s.Setup.Ctx, report, disputetypes.Major) - require.NoError(err) - burnAmount = disputeFee.Amount.MulRaw(1).QuoRaw(20) - require.Equal(dispute.DisputeStatus, disputetypes.Voting) - require.Equal(dispute.DisputeStartTime, disputeStartTime) - require.Equal(dispute.DisputeEndTime, disputeStartTime.Add(disputekeeper.THREE_DAYS)) - require.Equal(dispute.DisputeFee, disputeFee.Amount.Sub(burnAmount)) - require.Equal(dispute.DisputeStartBlock, disputeStartHeight) - - // create vote tx msg - msgVote = disputetypes.MsgVote{ - Voter: reporterAccount.String(), - Id: dispute.DisputeId, - Vote: disputetypes.VoteEnum_VOTE_SUPPORT, - } - // send vote tx - voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVote) - require.NoError(err) - require.NotNil(voteResponse) - - // vote is properly stored - vote, err = s.Setup.Disputekeeper.Votes.Get(s.Setup.Ctx, dispute.DisputeId) - require.NoError(err) - require.NotNil(vote) - require.Equal(vote.Executed, false) - require.Equal(vote.Id, dispute.DisputeId) - require.Equal(vote.VoteStart, disputeStartTime) - require.Equal(vote.VoteEnd, disputeStartTime.Add(disputekeeper.TWO_DAYS)) - - // advance 3 days to expire vote - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(disputekeeper.THREE_DAYS)) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - // --------------------------------------------------------------------------- - // Height 10 - dispute is resolved, reporter no longer a reporter - // --------------------------------------------------------------------------- - // s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - // s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - // _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - // require.NoError(err) - - err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 3) - require.NoError(err) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - // reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) - // require.NoError(err) -} - - -// Vicky the Validator just produces blocks, has 1000 trb staked -// Rob the Reporter has 100 trb staked with Vicky so he can select himself as the reporter -// Delwood the Delegator has 250 trb delegated to Rob -// Rob stakes 10 more trb through a different reporter account to vicky and makes Rob2 a reporter -// Rob creates a dispute for a good report from Rob2 -// The dispute settles to `No`, moving tokens from Delwood to Rob through proxy of Rob2 ? -func (s *E2ETestSuite) TestDisputeSettlesToNo() { - // Setup msgServers - require := s.Require() - msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) - require.NotNil(msgServerOracle) - msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) - require.NotNil(msgServerReporter) - msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) - require.NotNil(msgServerDispute) - msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) - require.NotNil(msgServerStaking) - - //--------------------------------------------------------------------------- - // Height 0 - vicky becomes a validator - //--------------------------------------------------------------------------- - _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - vickyAccAddr := simtestutil.CreateIncrementalAccounts(1) - vickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) // give vicky extra to act as free floating token voting group - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(vickyInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, vickyAccAddr[0], sdk.NewCoins(vickyInitCoins))) - s.Setup.Accountkeeper.NewAccountWithAddress(s.Setup.Ctx, vickyAccAddr[0]) - - pubKey := simtestutil.CreateTestPubKeys(1) - vickyValAddr := simtestutil.ConvertAddrsToValAddrs(vickyAccAddr) - msgCreateValidator, err := stakingtypes.NewMsgCreateValidator( - vickyValAddr[0].String(), - pubKey[0], - sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), - stakingtypes.Description{Moniker: "created validator"}, - stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(0, 0), math.LegacyNewDecWithPrec(3, 1), math.LegacyNewDecWithPrec(1, 1)), - math.OneInt(), - ) - require.NoError(err) - - _, err = msgServerStaking.CreateValidator(s.Setup.Ctx, msgCreateValidator) - require.NoError(err) - - require.NoError(s.Setup.Bridgekeeper.SetEVMAddressByOperator(s.Setup.Ctx, vickyValAddr[0].String(), []byte("vickyEvmAddr"))) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 1 - Rob delegates to Vicky and selects himself to become a reporter - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // verify vicky is a bonded validator - vickyValidatorInfo, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, vickyValAddr[0]) - require.NoError(err) - require.Equal(vickyValidatorInfo.Status, stakingtypes.Bonded) - require.Equal(vickyValidatorInfo.Tokens, math.NewInt(1000*1e6)) - - robPrivKey := secp256k1.GenPrivKey() - robAccAddr := sdk.AccAddress(robPrivKey.PubKey().Address()) - robInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(robInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, robAccAddr, sdk.NewCoins(robInitCoins))) - - // rob delegates to vicky - msgDelegate := stakingtypes.NewMsgDelegate( - robAccAddr.String(), - vickyValAddr[0].String(), - sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - - // rob becomes a reporter - _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ - ReporterAddress: robAccAddr.String(), - CommissionRate: reportertypes.DefaultMinCommissionRate, - MinTokensRequired: math.NewInt(1 * 1e6), - }) - require.NoError(err) - robReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, robAccAddr) - require.NoError(err) - require.Equal(robReporterInfo.Jailed, false) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 2 - Delwood delegates 250 trb to Vicky - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(2) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - delwoodPrivKey := secp256k1.GenPrivKey() - delwoodAccAddr := sdk.AccAddress(delwoodPrivKey.PubKey().Address()) - delwoodInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(delwoodInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, delwoodAccAddr, sdk.NewCoins(delwoodInitCoins))) - - msgDelegate = stakingtypes.NewMsgDelegate( - delwoodAccAddr.String(), - vickyValAddr[0].String(), - sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 3 - Delwood selects 250 trb to Rob - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(3) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - _, err = msgServerReporter.SelectReporter(s.Setup.Ctx, &reportertypes.MsgSelectReporter{ - SelectorAddress: delwoodAccAddr.String(), - ReporterAddress: robAccAddr.String(), - }) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 4 - Rob creates a second reporter - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(4) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - rob2PrivKey := secp256k1.GenPrivKey() - rob2AccAddr := sdk.AccAddress(rob2PrivKey.PubKey().Address()) - rob2InitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(50*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(rob2InitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, rob2AccAddr, sdk.NewCoins(rob2InitCoins))) - - // rob delegates to vicky - msgDelegate = stakingtypes.NewMsgDelegate( - rob2AccAddr.String(), - vickyValAddr[0].String(), - sdk.NewCoin(s.Setup.Denom, math.NewInt(50*1e6)), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - - // rob2 becomes a reporter - _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ - ReporterAddress: rob2AccAddr.String(), - CommissionRate: reportertypes.DefaultMinCommissionRate, - MinTokensRequired: math.NewInt(1 * 1e6), - }) - require.NoError(err) - rob2ReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, rob2AccAddr) - require.NoError(err) - require.Equal(rob2ReporterInfo.Jailed, false) - - // create third party ricky the reporter to vote from reporter group - rickyPrivKey := secp256k1.GenPrivKey() - rickyAccAddr := sdk.AccAddress(rickyPrivKey.PubKey().Address()) - rickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(rickyInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, rickyAccAddr, sdk.NewCoins(rickyInitCoins))) - - // ricky delegates to vicky - msgDelegate = stakingtypes.NewMsgDelegate( - rickyAccAddr.String(), - vickyValAddr[0].String(), - sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - - // ricky becomes a reporter - _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ - ReporterAddress: rickyAccAddr.String(), - CommissionRate: reportertypes.DefaultMinCommissionRate, - MinTokensRequired: math.NewInt(1 * 1e6), - }) - require.NoError(err) - rickyReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, rickyAccAddr) - require.NoError(err) - require.Equal(rickyReporterInfo.Jailed, false) - - // ricky tips for more voting power - queryData, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) - require.NoError(err) - msgTip := oracletypes.MsgTip{ - Tipper: rickyAccAddr.String(), - QueryData: queryData, - Amount: sdk.NewCoin(s.Setup.Denom, math.NewInt(10*1e6)), - } - _, err = msgServerOracle.Tip(s.Setup.Ctx, &msgTip) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 5 - Rob2 makes a fine report - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(5) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // balances before reporting/disputing - robReporterStake, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, robAccAddr) - require.NoError(err) - require.Equal(robReporterStake, math.NewInt(350*1e6)) - - rob2ReporterStake, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rob2AccAddr) - require.NoError(err) - require.Equal(rob2ReporterStake, math.NewInt(50*1e6)) - - delwoodSelectionStake, err := s.Setup.Reporterkeeper.GetDelegatorTokensAtBlock(s.Setup.Ctx, delwoodAccAddr, 5) - require.NoError(err) - require.Equal(delwoodSelectionStake, math.NewInt(250*1e6)) - - vickyValidatorStakedTokens, err := s.Setup.Stakingkeeper.GetLastValidatorPower(s.Setup.Ctx, vickyValAddr[0]) - require.NoError(err) - require.Equal(vickyValidatorStakedTokens, int64(2400)) - - // rob2 makes a report - currentCycleList, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) - require.NoError(err) - queryId := utils.QueryIDFromData(currentCycleList) - msgSubmitValue := oracletypes.MsgSubmitValue{ - Creator: rob2AccAddr.String(), - QueryData: currentCycleList, - Value: testutil.EncodeValue(100_000), - } - _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &msgSubmitValue) - require.NoError(err) - - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(7 * time.Second)) - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - getAggReportRequest := oracletypes.QueryGetCurrentAggregateReportRequest{ - QueryId: hex.EncodeToString(queryId), - } - queryServer := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) - result, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest) - require.NoError(err) - require.Equal(int64(0), result.Aggregate.AggregateReportIndex) - require.Equal(testutil.EncodeValue(100_000), result.Aggregate.AggregateValue) - require.Equal(rob2AccAddr.String(), result.Aggregate.AggregateReporter) - require.Equal(queryId, result.Aggregate.QueryId) - require.Equal(int64(50), result.Aggregate.ReporterPower) - require.Equal(int64(5), result.Aggregate.Height) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 6 - Rob disputes Rob2s report (minor - 5%) - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(6) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // double check balances - robReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, robAccAddr) - require.NoError(err) - require.Equal(robReporterStake, math.NewInt(350*1e6)) - - rob2ReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rob2AccAddr) - require.NoError(err) - require.Equal(rob2ReporterStake, math.NewInt(50*1e6)) - - delwoodSelectionStake, err = s.Setup.Reporterkeeper.GetDelegatorTokensAtBlock(s.Setup.Ctx, delwoodAccAddr, 6) - require.NoError(err) - require.Equal(delwoodSelectionStake, math.NewInt(250*1e6)) - - vickyValidatorStakedTokens, err = s.Setup.Stakingkeeper.GetLastValidatorPower(s.Setup.Ctx, vickyValAddr[0]) - require.NoError(err) - require.Equal(vickyValidatorStakedTokens, int64(2400)) - - // rob proposes a minor dispute - report := oracletypes.MicroReport{ - Reporter: rob2AccAddr.String(), - Power: rob2ReporterStake.Quo(layertypes.PowerReduction).Int64(), - QueryId: queryId, - Value: testutil.EncodeValue(100_000), - Timestamp: s.Setup.Ctx.BlockTime(), - BlockNumber: int64(5), - } - - // create msg for propose dispute tx - msgProposeDispute := disputetypes.MsgProposeDispute{ - Creator: robAccAddr.String(), - Report: &report, - DisputeCategory: disputetypes.Minor, - Fee: sdk.NewCoin(s.Setup.Denom, math.NewInt(2.5*1e6)), - PayFromBond: true, - } - - _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) - require.NoError(err) - - disputes, err := s.Setup.Disputekeeper.GetOpenDisputes(s.Setup.Ctx) - require.NoError(err) - require.NotNil(disputes) - require.Equal(len(disputes), 1) - - burnAmount := msgProposeDispute.Fee.Amount.MulRaw(1).QuoRaw(20) - dispute, err := s.Setup.Disputekeeper.Disputes.Get(s.Setup.Ctx, 1) - require.NoError(err) - require.Equal(dispute.DisputeId, uint64(1)) - require.Equal(dispute.DisputeStatus, disputetypes.Voting) - require.Equal(dispute.DisputeCategory, disputetypes.Minor) - require.Equal(dispute.DisputeFee, msgProposeDispute.Fee.Amount.Sub(burnAmount)) - // require.Equal(dispute.BlockNumber, int64(5)) - require.Equal(dispute.DisputeStartBlock, int64(6)) - feepayer, err := s.Setup.Disputekeeper.DisputeFeePayer.Get(s.Setup.Ctx, collections.Join(uint64(1), robAccAddr.Bytes())) - require.NoError(err) - require.Equal(feepayer.Amount, msgProposeDispute.Fee.Amount) - require.Equal(feepayer.FromBond, true) - slashAmount := dispute.SlashAmount - fmt.Println("slashAmount", slashAmount) - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 7 - Everyone votes No on the dispute - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(7) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // rob2 unjails himself - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Hour)) - msgUnjailReporter := reportertypes.MsgUnjailReporter{ - ReporterAddress: rob2AccAddr.String(), - } - _, err = msgServerReporter.UnjailReporter(s.Setup.Ctx, &msgUnjailReporter) - require.NoError(err) - rob2ReporterInfo, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, rob2AccAddr) - require.NoError(err) - require.Equal(rob2ReporterInfo.Jailed, false) - - // check balances - vickyValidatorStakedTokens, err = s.Setup.Stakingkeeper.GetLastValidatorPower(s.Setup.Ctx, vickyValAddr[0]) - require.NoError(err) - require.Equal(vickyValidatorStakedTokens, int64(2395)) // 2.5 trb gone from Rob, 2.5 trb gone from Rob2 - - robReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, robAccAddr) - require.NoError(err) - require.Equal(robReporterStake, math.NewInt(347.5*1e6)) // Paid 5% of 50 trb to open dispute - - rob2ReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rob2AccAddr) - require.NoError(err) - require.Equal(rob2ReporterStake, math.NewInt(47.5*1e6)) // 5% slashed from 50 trb - - delwoodSelectionStake, err = s.Setup.Reporterkeeper.GetDelegatorTokensAtBlock(s.Setup.Ctx, delwoodAccAddr, 7) - require.NoError(err) - delwoodsFee := ((250 * 2.5) / 350) * 1e6 // ((250/350) * 2.5) trb = ~1.785 trb - fmt.Println("delwoodsFee", delwoodsFee) - require.Equal(delwoodSelectionStake, math.NewInt(250*1e6).Sub(math.NewInt(int64(delwoodsFee)))) // ~1.785 of delwoods trb used towards dispute - - // free floating token group votes no - fmt.Println("Vicky's Vote") - msgVoteVicky := disputetypes.MsgVote{ - Voter: vickyAccAddr[0].String(), - Id: dispute.DisputeId, - Vote: disputetypes.VoteEnum_VOTE_AGAINST, - } - voteResponse, err := msgServerDispute.Vote(s.Setup.Ctx, &msgVoteVicky) - require.NoError(err) - require.NotNil(voteResponse) - - // team votes no - fmt.Println("Team's Vote") - teamAddr, err := s.Setup.Disputekeeper.GetTeamAddress(s.Setup.Ctx) - require.NoError(err) - msgVoteTeam := disputetypes.MsgVote{ - Voter: teamAddr.String(), - Id: dispute.DisputeId, - Vote: disputetypes.VoteEnum_VOTE_AGAINST, - } - voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVoteTeam) - require.NoError(err) - require.NotNil(voteResponse) - - // // ricky votes no -- no voting power ? - fmt.Println("Ricky's Vote") - msgVoteRicky := disputetypes.MsgVote{ - Voter: rickyAccAddr.String(), - Id: dispute.DisputeId, - Vote: disputetypes.VoteEnum_VOTE_AGAINST, - } - voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVoteRicky) - require.NoError(err) - require.NotNil(voteResponse) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - // --------------------------------------------------------------------------- - // Height 8 - quorom reached, advance 3 days, tally votes - // --------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(8) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // check on dispute status - disputeByReporter, err := s.Setup.Disputekeeper.GetDisputeByReporter(s.Setup.Ctx, report, disputetypes.Minor) - require.NoError(err) - require.Equal(disputeByReporter.DisputeId, uint64(1)) - require.Equal(disputeByReporter.DisputeStatus, disputetypes.Voting) - require.Equal(disputeByReporter.DisputeCategory, disputetypes.Minor) - require.Equal(disputeByReporter.DisputeFee, msgProposeDispute.Fee.Amount.Sub(burnAmount)) - require.Equal(disputeByReporter.DisputeStartBlock, int64(6)) - - // fast forward 3 days - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(disputekeeper.THREE_DAYS)) - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - // tally votes - err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 1) - require.NoError(err) - - // execute vote - msgExecuteDispute := disputetypes.MsgExecuteDispute{ - CallerAddress: rob2AccAddr.String(), - DisputeId: 1, - } - _, err = msgServerDispute.ExecuteDispute(s.Setup.Ctx, &msgExecuteDispute) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - // --------------------------------------------------------------------------- - // Height 9 - rob2 unjails himself, check balances - // --------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(9) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // check on dispute status - disputeByReporter, err = s.Setup.Disputekeeper.GetDisputeByReporter(s.Setup.Ctx, report, disputetypes.Minor) - require.NoError(err) - require.Equal(disputeByReporter.DisputeId, uint64(1)) - require.Equal(disputeByReporter.DisputeStatus, disputetypes.Resolved) - - // robReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, robAccAddr) - // require.NoError(err) - // require.Equal(robReporterStake, math.NewInt(350*1e6)) - - // rob2ReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rob2AccAddr) - // require.NoError(err) - // require.Equal(rob2ReporterStake, math.NewInt(50*1e6)) - - // delwoodSelectionStake, err = s.Setup.Reporterkeeper.GetDelegatorTokensAtBlock(s.Setup.Ctx, delwoodAccAddr, 6) - // require.NoError(err) - // require.Equal(delwoodSelectionStake, math.NewInt(250*1e6)) - - // vickyValidatorStakedTokens, err = s.Setup.Stakingkeeper.GetLastValidatorPower(s.Setup.Ctx, vickyValAddr[0]) - // require.NoError(err) - // require.Equal(vickyValidatorStakedTokens, int64(2400)) - - // FINAL RESULTS: - vickyFreeFloating := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, vickyAccAddr[0], s.Setup.Denom) - vickyStaked, err := s.Setup.Stakingkeeper.GetLastValidatorPower(s.Setup.Ctx, vickyValAddr[0]) - require.NoError(err) - fmt.Println("\nvicky before the dispute: ", 2400) - fmt.Println("vickyStaked: ", vickyStaked) - fmt.Println("vickyFreeFloating: ", vickyFreeFloating.Amount) - fmt.Println("vicky total after dispute: ", vickyStaked+vickyFreeFloating.Amount.Int64()) - - robFreeFloating := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, robAccAddr, s.Setup.Denom) - robReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, robAccAddr) - require.NoError(err) - fmt.Println("\nrob before the dispute: ", 350) - fmt.Println("robReporterStake", robReporterStake) - fmt.Println("robFreeFloating: ", robFreeFloating.Amount) - fmt.Println("rob total after dispute: ", robReporterStake.Int64()+robFreeFloating.Amount.Int64()) - - rob2FreeFloating := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, rob2AccAddr, s.Setup.Denom) - rob2ReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rob2AccAddr) - require.NoError(err) - fmt.Println("\nrob2 before the dispute: ", 50) - fmt.Println("rob2ReporterStake", rob2ReporterStake) - fmt.Println("rob2FreeFloating: ", rob2FreeFloating.Amount) - fmt.Println("rob2 total after dispute: ", rob2ReporterStake.Int64()+rob2FreeFloating.Amount.Int64()) - - delwoodFreeFloating := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, delwoodAccAddr, s.Setup.Denom) - delwoodSelectionStake, err = s.Setup.Reporterkeeper.GetDelegatorTokensAtBlock(s.Setup.Ctx, delwoodAccAddr, 9) - require.NoError(err) - fmt.Println("\ndelwood before the dispute: ", 250) - fmt.Println("delwoodSelectionStake", delwoodSelectionStake) - fmt.Println("delwoodFreeFloating: ", delwoodFreeFloating.Amount) - fmt.Println("delwood total after dispute: ", delwoodSelectionStake.Int64()+delwoodFreeFloating.Amount.Int64()) - - rickyFreeFloating := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, rickyAccAddr, s.Setup.Denom) - rickyReporterStake, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rickyAccAddr) - require.NoError(err) - fmt.Println("\nricky before the dispute: ", 1999) - fmt.Println("rickyReporterStake", rickyReporterStake) - fmt.Println("rickyFreeFloating: ", rickyFreeFloating.Amount) - fmt.Println("ricky total after dispute: ", rickyReporterStake.Int64()+rickyFreeFloating.Amount.Int64()) -} - -// Vicky the Validator has 1000 trb staked -// Rob the Reporter has 100 trb staked with Vicky, selects himself as a reporter -// Ricky the Reporter has 100 trb staked with Vicky, selects himself as a reporter -// Delwood the Delegator has 250 trb delegated to Rob -// Delwood tries to dispute a report from Ricky to eliminate his competition -// fails -func (s *E2ETestSuite) TestDisputeFromDelegatorPayFromBond() { - // Setup msgServers - require := s.Require() - msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) - require.NotNil(msgServerOracle) - msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) - require.NotNil(msgServerReporter) - msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) - require.NotNil(msgServerDispute) - msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) - require.NotNil(msgServerStaking) - - //--------------------------------------------------------------------------- - // Height 0 - vicky becomes a validator - //--------------------------------------------------------------------------- - _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - vickyAccAddr := simtestutil.CreateIncrementalAccounts(1) - vickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) // give vicky extra to act as free floating token voting group - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(vickyInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, vickyAccAddr[0], sdk.NewCoins(vickyInitCoins))) - s.Setup.Accountkeeper.NewAccountWithAddress(s.Setup.Ctx, vickyAccAddr[0]) - - pubKey := simtestutil.CreateTestPubKeys(1) - vickyValAddr := simtestutil.ConvertAddrsToValAddrs(vickyAccAddr) - msgCreateValidator, err := stakingtypes.NewMsgCreateValidator( - vickyValAddr[0].String(), - pubKey[0], - sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), - stakingtypes.Description{Moniker: "created validator"}, - stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(0, 0), math.LegacyNewDecWithPrec(3, 1), math.LegacyNewDecWithPrec(1, 1)), - math.OneInt(), - ) - require.NoError(err) - - _, err = msgServerStaking.CreateValidator(s.Setup.Ctx, msgCreateValidator) - require.NoError(err) - - require.NoError(s.Setup.Bridgekeeper.SetEVMAddressByOperator(s.Setup.Ctx, vickyValAddr[0].String(), []byte("vickyEvmAddr"))) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 1 - Rob delegates to Vicky and selects himself to become a reporter - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // verify vicky is a bonded validator - vickyValidatorInfo, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, vickyValAddr[0]) - require.NoError(err) - require.Equal(vickyValidatorInfo.Status, stakingtypes.Bonded) - require.Equal(vickyValidatorInfo.Tokens, math.NewInt(1000*1e6)) - - robPrivKey := secp256k1.GenPrivKey() - robAccAddr := sdk.AccAddress(robPrivKey.PubKey().Address()) - robInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(robInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, robAccAddr, sdk.NewCoins(robInitCoins))) - - // rob delegates to vicky - msgDelegate := stakingtypes.NewMsgDelegate( - robAccAddr.String(), - vickyValAddr[0].String(), - sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - - // rob becomes a reporter - _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ - ReporterAddress: robAccAddr.String(), - CommissionRate: reportertypes.DefaultMinCommissionRate, - MinTokensRequired: math.NewInt(1 * 1e6), - }) - require.NoError(err) - robReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, robAccAddr) - require.NoError(err) - require.Equal(robReporterInfo.Jailed, false) - - rickyPrivKey := secp256k1.GenPrivKey() - rickyAccAddr := sdk.AccAddress(rickyPrivKey.PubKey().Address()) - rickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(rickyInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, rickyAccAddr, sdk.NewCoins(rickyInitCoins))) - - // ricky delegates to vicky - msgDelegate = stakingtypes.NewMsgDelegate( - rickyAccAddr.String(), - vickyValAddr[0].String(), - sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - - // ricky becomes a reporter - _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ - ReporterAddress: rickyAccAddr.String(), - CommissionRate: reportertypes.DefaultMinCommissionRate, - MinTokensRequired: math.NewInt(1 * 1e6), - }) - require.NoError(err) - rickyReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, rickyAccAddr) - require.NoError(err) - require.Equal(rickyReporterInfo.Jailed, false) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 2 - Delwood delegates 250 trb to Vicky - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(2) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - delwoodPrivKey := secp256k1.GenPrivKey() - delwoodAccAddr := sdk.AccAddress(delwoodPrivKey.PubKey().Address()) - delwoodInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(delwoodInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, delwoodAccAddr, sdk.NewCoins(delwoodInitCoins))) - - msgDelegate = stakingtypes.NewMsgDelegate( - delwoodAccAddr.String(), - vickyValAddr[0].String(), - sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 3 - Delwood selects 250 trb to Rob - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(3) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - _, err = msgServerReporter.SelectReporter(s.Setup.Ctx, &reportertypes.MsgSelectReporter{ - SelectorAddress: delwoodAccAddr.String(), - ReporterAddress: robAccAddr.String(), - }) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 4 - Ricky reports for the cycle list - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(4) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - currentCycleList, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) - require.NoError(err) - queryId := utils.QueryIDFromData(currentCycleList) - msgSubmitValue := oracletypes.MsgSubmitValue{ - Creator: rickyAccAddr.String(), - QueryData: currentCycleList, - Value: testutil.EncodeValue(100_000), - } - _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &msgSubmitValue) - require.NoError(err) - - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(7 * time.Second)) - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - getAggReportRequest := oracletypes.QueryGetCurrentAggregateReportRequest{ - QueryId: hex.EncodeToString(queryId), - } - queryServer := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) - result, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest) - require.NoError(err) - require.Equal(int64(0), result.Aggregate.AggregateReportIndex) - require.Equal(testutil.EncodeValue(100_000), result.Aggregate.AggregateValue) - require.Equal(rickyAccAddr.String(), result.Aggregate.AggregateReporter) - require.Equal(queryId, result.Aggregate.QueryId) - require.Equal(int64(1000), result.Aggregate.ReporterPower) - require.Equal(int64(4), result.Aggregate.Height) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 5 - Delwood proposes a dispute from bond - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(5) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - rickyReporterStake, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rickyAccAddr) - require.NoError(err) - - report := oracletypes.MicroReport{ - Reporter: rickyAccAddr.String(), - Power: rickyReporterStake.Quo(layertypes.PowerReduction).Int64(), - QueryId: queryId, - Value: testutil.EncodeValue(100_000), - Timestamp: s.Setup.Ctx.BlockTime(), - BlockNumber: int64(4), - } - - msgProposeDispute := disputetypes.MsgProposeDispute{ - Creator: delwoodAccAddr.String(), - Report: &report, - DisputeCategory: disputetypes.Warning, - Fee: sdk.NewCoin(s.Setup.Denom, math.NewInt(10*1e6)), - PayFromBond: true, - } - - _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) - require.Error(err) -} - -// test precision loss throughout tip/report/dispute/claim process - diff --git a/tests/e2e/basic_reporting_test.go b/tests/e2e/basic_reporting_test.go deleted file mode 100644 index 37e078ba..00000000 --- a/tests/e2e/basic_reporting_test.go +++ /dev/null @@ -1,793 +0,0 @@ -package e2e_test - -import ( - "encoding/hex" - "time" - - "github.com/tellor-io/layer/testutil" - utils "github.com/tellor-io/layer/utils" - disputekeeper "github.com/tellor-io/layer/x/dispute/keeper" - oraclekeeper "github.com/tellor-io/layer/x/oracle/keeper" - oracletypes "github.com/tellor-io/layer/x/oracle/types" - reporterkeeper "github.com/tellor-io/layer/x/reporter/keeper" - reportertypes "github.com/tellor-io/layer/x/reporter/types" - - collections "cosmossdk.io/collections" - "cosmossdk.io/math" - - secp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/query" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -// func (s *E2ETestSuite) TestBasicReporting() { -// require := s.Require() -// minter, err := s.Setup.Mintkeeper.Minter.Get(s.Setup.Ctx) -// require.NoError(err) -// minter.Initialized = true -// require.NoError(s.Setup.Mintkeeper.Minter.Set(s.Setup.Ctx, minter)) -// msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) - -// //--------------------------------------------------------------------------- -// // Height 0 -// //--------------------------------------------------------------------------- -// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) -// require.NoError(err) - -// // create a validator -// valAccount := simtestutil.CreateIncrementalAccounts(1) -// // mint 5000*1e8 tokens for validator -// initCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(5000*1e8)) -// require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) -// require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, valAccount[0], sdk.NewCoins(initCoins))) -// // get val address -// valAccountValAddrs := simtestutil.ConvertAddrsToValAddrs(valAccount) -// // create pub key for validator -// pubKey := simtestutil.CreateTestPubKeys(1) -// // tell keepers about the new validator -// s.Setup.Accountkeeper.NewAccountWithAddress(s.Setup.Ctx, valAccount[0]) -// msgCreateValidaotr, err := stakingtypes.NewMsgCreateValidator( -// valAccountValAddrs[0].String(), -// pubKey[0], -// sdk.NewCoin(s.Setup.Denom, math.NewInt(4000*1e8)), -// stakingtypes.Description{Moniker: "created validator"}, -// stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(0, 0), math.LegacyNewDecWithPrec(3, 1), math.LegacyNewDecWithPrec(1, 1)), -// math.OneInt(), -// ) -// require.NoError(err) -// _, err = msgServerStaking.CreateValidator(s.Setup.Ctx, msgCreateValidaotr) -// require.NoError(err) -// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) -// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) -// validator, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, valAccountValAddrs[0]) -// require.NoError(err) - -// _, err = s.Setup.Stakingkeeper.EndBlocker(s.Setup.Ctx) -// s.NoError(err) - -// type Delegator struct { -// delegatorAddress sdk.AccAddress -// validator stakingtypes.Validator -// tokenAmount math.Int -// } -// pk := ed25519.GenPrivKey() -// reporterAccount := sdk.AccAddress(pk.PubKey().Address()) -// // mint 5000*1e6 tokens for reporter -// s.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) -// s.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, reporterAccount, sdk.NewCoins(initCoins))) -// // delegate to validator so reporter can delegate to themselves -// reporterDelToVal := Delegator{delegatorAddress: reporterAccount, validator: validator, tokenAmount: math.NewInt(4000 * 1e6)} -// msgDelegate := stakingtypes.NewMsgDelegate(reporterAccount.String(), validator.OperatorAddress, sdk.NewCoin(s.Setup.Denom, math.NewInt(4000*1e6))) -// _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) -// require.NoError(err) -// // set up reporter module msgServer -// msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) -// require.NotNil(msgServerReporter) -// // define createReporterMsg params -// reporterAddress := reporterDelToVal.delegatorAddress.String() - -// createReporterMsg := reportertypes.MsgCreateReporter{ReporterAddress: reporterAddress, CommissionRate: reportertypes.DefaultMinCommissionRate, MinTokensRequired: reportertypes.DefaultMinTrb} -// // send createreporter msg -// _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &createReporterMsg) -// require.NoError(err) -// // check that reporter was created in Reporters collections -// reporter, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) -// require.NoError(err) -// s.NoError(s.Setup.Reporterkeeper.Reporters.Set(s.Setup.Ctx, reporterAccount, reportertypes.NewReporter(reportertypes.DefaultMinCommissionRate, math.OneInt()))) -// s.NoError(s.Setup.Reporterkeeper.Selectors.Set(s.Setup.Ctx, reporterAccount, reportertypes.NewSelection(reporterAccount, 1))) -// reporterTokens, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, reporterAccount) -// require.NoError(err) -// require.Equal(reporterTokens, math.NewInt(4000*1e6)) -// require.Equal(reporter.Jailed, false) -// // check on reporter in Delegators collections -// rkDelegation, err := s.Setup.Reporterkeeper.Selectors.Get(s.Setup.Ctx, reporterAccount) -// require.NoError(err) -// require.Equal(rkDelegation.Reporter, reporterAccount.Bytes()) -// // check on reporter/validator delegation -// valBz, err := s.Setup.Stakingkeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) -// require.NoError(err) -// skDelegation, err := s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount, valBz) -// require.NoError(err) -// require.Equal(skDelegation.GetDelegatorAddr(), reporterAccount.String()) -// require.Equal(skDelegation.GetValidatorAddr(), validator.GetOperator()) - -// // setup oracle msgServer -// msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) -// require.NotNil(msgServerOracle) - -// // case 1: commit/reveal for cycle list -// //--------------------------------------------------------------------------- -// // Height 1 -// //--------------------------------------------------------------------------- -// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) -// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) -// require.NoError(err) - -// // check that no time based rewards have been minted yet -// tbrModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(minttypes.TimeBasedRewards) -// tbrModuleAccountBalance := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) -// require.Equal(int64(0), tbrModuleAccountBalance.Amount.Int64()) - -// // begin report -// cycleListEth, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) -// require.NoError(err) -// // create hash for commit -// salt1, err := oracleutils.Salt(32) -// require.NoError(err) -// value1 := testutil.EncodeValue(4500) -// hash1 := oracleutils.CalculateCommitment(value1, salt1) -// // create commit1 msg -// commit1 := oracletypes.MsgCommitReport{ -// Creator: reporterAccount.String(), -// QueryData: cycleListEth, -// Hash: hash1, -// } -// // send commit tx -// commitResponse1, err := msgServerOracle.CommitReport(s.Setup.Ctx, &commit1) -// require.NoError(err) -// require.NotNil(commitResponse1) -// commitHeight := s.Setup.Ctx.BlockHeight() -// require.Equal(int64(1), commitHeight) - -// _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) -// require.NoError(err) -// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) - -// //--------------------------------------------------------------------------- -// // Height 2 -// //--------------------------------------------------------------------------- -// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(commitHeight + 1) -// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 14)) -// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) -// require.NoError(err) -// _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) -// require.NoError(err) - -// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(commitHeight + 2) -// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) -// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) -// require.NoError(err) - -// // check that 1 second worth of tbr has been minted -// // expected tbr = (daily mint rate * time elapsed) / (# of ms in a day) -// expectedBlockProvision := int64(146940000 * (15 * time.Second) / (24 * 60 * 60 * 1000)) -// expectedTbr := sdk.NewCoin(s.Setup.Denom, math.NewInt((expectedBlockProvision)).MulRaw(75).QuoRaw(100).Quo(sdk.DefaultPowerReduction)) -// tbrModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) -// require.GreaterOrEqual(tbrModuleAccountBalance.Amount.Int64(), expectedTbr.Amount.Int64()-1) -// require.LessOrEqual(tbrModuleAccountBalance.Amount.Int64(), expectedTbr.Amount.Int64()+1) -// // check that the cycle list has rotated -// cycleListBtc, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) -// require.NotEqual(cycleListEth, cycleListBtc) -// require.NoError(err) - -// // create reveal msg -// require.NoError(err) -// reveal1 := oracletypes.MsgSubmitValue{ -// Creator: reporterAccount.String(), -// QueryData: cycleListEth, -// Value: value1, -// Salt: salt1, -// } -// // send reveal tx -// revealResponse1, err := msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal1) -// require.NoError(err) -// require.NotNil(revealResponse1) -// // advance time and block height to expire the query and aggregate report -// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(21 * time.Second)) -// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) -// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) - -// // get queryId for GetAggregatedReportRequest -// queryIdEth := utils.QueryIDFromData(cycleListEth) - -// // check that aggregated report is stored -// getAggReportRequest1 := oracletypes.QueryGetCurrentAggregateReportRequest{ -// QueryId: hex.EncodeToString(queryIdEth), -// } -// queryServer := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) -// result1, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest1) -// require.NoError(err) -// require.Equal(result1.Aggregate.Height, uint64(2)) -// require.Equal(result1.Aggregate.AggregateReportIndex, uint64(0)) -// require.Equal(result1.Aggregate.AggregateValue, testutil.EncodeValue(4500)) -// require.Equal(result1.Aggregate.AggregateReporter, reporterAccount.String()) -// require.Equal(result1.Aggregate.QueryId, queryIdEth) -// require.Equal(uint64(4000), result1.Aggregate.ReporterPower) -// // check that tbr is no longer in timeBasedRewards module acct -// tbrModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) -// require.Equal(int64(0), tbrModuleAccountBalance.Amount.Int64()) -// // check that tbr was sent to reporter module account -// reporterModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(reportertypes.TipsEscrowPool) -// reporterModuleAccountBalance := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterModuleAccount, s.Setup.Denom) -// require.Equal(expectedTbr, reporterModuleAccountBalance) -// // check reporters outstaning rewards -// outstandingRewards, err := s.Setup.Reporterkeeper.SelectorTips.Get(s.Setup.Ctx, reporterAccount.Bytes()) -// require.NoError(err) -// require.Equal(outstandingRewards.TruncateInt(), expectedTbr.Amount) -// // withdraw tbr -// rewards, err := msgServerReporter.WithdrawTip(s.Setup.Ctx, &reportertypes.MsgWithdrawTip{SelectorAddress: reporterAddress, ValidatorAddress: validator.OperatorAddress}) -// require.NoError(err) -// tbrEarned := outstandingRewards -// // check that there is only one reward to claim -// require.NotNil(rewards) -// // check that reporter module account balance is now empty -// reporterModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterModuleAccount, s.Setup.Denom) -// require.Equal(int64(0), reporterModuleAccountBalance.Amount.Int64()) -// // check that reporter now has more bonded tokens - -// // case 2: direct reveal for cycle list -// //--------------------------------------------------------------------------- -// // Height 3 -// //--------------------------------------------------------------------------- -// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) -// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) -// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) -// require.NoError(err) - -// // check that 8 sec of tbr has been minted -// tbrModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) -// expectedBlockProvision = int64(146940000 * (22 * time.Second) / (24 * 60 * 60 * 1000)) -// expectedTbr = sdk.NewCoin(s.Setup.Denom, (math.NewInt((expectedBlockProvision)).MulRaw(75).QuoRaw(100).Quo(sdk.DefaultPowerReduction)).Add(math.NewInt(1))) - -// require.Equal(expectedTbr, tbrModuleAccountBalance) - -// // get new cycle list query data -// cycleListTrb, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) -// require.NoError(err) -// require.NotEqual(cycleListEth, cycleListTrb) -// require.NotEqual(cycleListBtc, cycleListTrb) -// // create reveal message -// value2 := testutil.EncodeValue(100_000) -// require.NoError(err) -// reveal2 := oracletypes.MsgSubmitValue{ -// Creator: reporterAccount.String(), -// QueryData: cycleListTrb, -// Value: value2, -// } -// // send reveal message -// revealResponse2, err := msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal2) -// require.NoError(err) -// require.NotNil(revealResponse2) -// // advance time and block height to expire the query and aggregate report -// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(21 * time.Second)) -// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) -// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) - -// // get queryId for GetAggregatedReportRequest -// queryIdTrb := utils.QueryIDFromData(cycleListTrb) - -// // create get aggregated report query -// getAggReportRequest2 := oracletypes.QueryGetCurrentAggregateReportRequest{ -// QueryId: hex.EncodeToString(queryIdTrb), -// } -// // check that aggregated report is stored correctly -// result2, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest2) -// require.NoError(err) -// require.Equal(uint64(0), result2.Aggregate.AggregateReportIndex) -// require.Equal(testutil.EncodeValue(100_000), result2.Aggregate.AggregateValue) -// require.Equal(reporterAccount.String(), result2.Aggregate.AggregateReporter) -// require.Equal(queryIdTrb, result2.Aggregate.QueryId) -// require.Equal(uint64(4000), result2.Aggregate.ReporterPower) -// require.Equal(uint64(3), result2.Aggregate.Height) -// // check that tbr is no longer in timeBasedRewards module acct -// tbrModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) -// require.Equal(int64(0), tbrModuleAccountBalance.Amount.Int64()) -// // check that tbr was sent to reporter module account -// reporterModuleAccount = s.Setup.Accountkeeper.GetModuleAddress(reportertypes.TipsEscrowPool) -// reporterModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterModuleAccount, s.Setup.Denom) -// require.Equal(expectedTbr, reporterModuleAccountBalance) - -// // check reporters outstaning rewards -// outstandingRewards, err = s.Setup.Reporterkeeper.SelectorTips.Get(s.Setup.Ctx, reporterAccount.Bytes()) -// require.NoError(err) -// require.Equal(outstandingRewards.TruncateInt(), expectedTbr.Amount) -// // withdraw tbr -// tbrEarned = tbrEarned.Add(outstandingRewards) -// rewards, err = msgServerReporter.WithdrawTip(s.Setup.Ctx, &reportertypes.MsgWithdrawTip{SelectorAddress: reporterAddress, ValidatorAddress: validator.OperatorAddress}) -// require.NoError(err) -// require.NotNil(rewards) -// // check that reporter module account balance is now empty -// reporterModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterModuleAccount, s.Setup.Denom) -// require.Equal(int64(0), reporterModuleAccountBalance.Amount.Int64()) - -// // case 3: commit/reveal for tipped query -// //--------------------------------------------------------------------------- -// // Height 4 -// //--------------------------------------------------------------------------- -// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) -// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) -// require.NoError(err) - -// // get reporters shares -// deleBeforeReport, err := s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount.Bytes(), valBz) -// require.NoError(err) -// require.Equal(deleBeforeReport.GetShares(), math.LegacyNewDec(4000*1e6).Add(tbrEarned)) - -// // create tip msg -// balanceBeforetip := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) -// tipAmount := sdk.NewCoin(s.Setup.Denom, math.NewInt(100)) -// msgTip := oracletypes.MsgTip{ -// Tipper: reporterAccount.String(), -// QueryData: cycleListEth, -// Amount: tipAmount, -// } -// // send tip tx -// tipRes, err := msgServerOracle.Tip(s.Setup.Ctx, &msgTip) -// require.NoError(err) -// require.NotNil(tipRes) - -// // check that tip is in oracle module account -// twoPercent := sdk.NewCoin(s.Setup.Denom, tipAmount.Amount.Mul(math.NewInt(2)).Quo(math.NewInt(100))) -// tipModuleAcct := s.Setup.Accountkeeper.GetModuleAddress(oracletypes.ModuleName) -// tipAcctBalance := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipModuleAcct, s.Setup.Denom) -// require.Equal(tipAcctBalance, tipAmount.Sub(twoPercent)) -// // create commit for tipped eth query -// salt1, err = oracleutils.Salt(32) -// require.NoError(err) -// value1 = testutil.EncodeValue(5000) -// hash1 = oracleutils.CalculateCommitment(value1, salt1) - -// queryId := utils.QueryIDFromData(cycleListEth) -// quertip, err := s.Setup.Oraclekeeper.GetQueryTip(s.Setup.Ctx, queryId) -// require.NoError(err) -// require.Equal(quertip, tipAmount.Amount.Sub(twoPercent.Amount)) - -// commit1 = oracletypes.MsgCommitReport{ -// Creator: reporterAccount.String(), -// QueryData: cycleListEth, -// Hash: hash1, -// } -// // send commit tx -// commitResponse1, err = msgServerOracle.CommitReport(s.Setup.Ctx, &commit1) -// require.NoError(err) -// require.NotNil(commitResponse1) -// commitHeight = s.Setup.Ctx.BlockHeight() -// require.Equal(int64(4), commitHeight) -// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) -// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) - -// //--------------------------------------------------------------------------- -// // Height 5 -// //--------------------------------------------------------------------------- -// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(commitHeight + 1) -// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) -// require.NoError(err) - -// // create reveal msg -// value1 = testutil.EncodeValue(5000) -// reveal1 = oracletypes.MsgSubmitValue{ -// Creator: reporterAccount.String(), -// QueryData: cycleListEth, -// Value: value1, -// Salt: salt1, -// } -// // send reveal tx -// revealResponse1, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal1) -// require.NoError(err) -// require.NotNil(revealResponse1) - -// // advance time and block height to expire the query and aggregate report -// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(21 * time.Second)) -// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) -// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) - -// // create get aggreagted report query -// getAggReportRequest1 = oracletypes.QueryGetCurrentAggregateReportRequest{ -// QueryId: hex.EncodeToString(queryIdEth), -// } -// // check that the aggregated report is stored correctly -// result1, err = queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest1) -// require.NoError(err) -// require.Equal(result1.Aggregate.AggregateReportIndex, uint64(0)) -// require.Equal(result1.Aggregate.AggregateValue, testutil.EncodeValue(5000)) -// require.Equal(result1.Aggregate.AggregateReporter, reporterAccount.String()) -// require.Equal(queryIdEth, result1.Aggregate.QueryId) -// require.Equal(uint64(4000), result1.Aggregate.ReporterPower) -// require.Equal(uint64(5), result1.Aggregate.Height) -// // check that the tip is in tip escrow -// tipEscrowAcct := s.Setup.Accountkeeper.GetModuleAddress(reportertypes.TipsEscrowPool) -// tipEscrowBalance := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipEscrowAcct, s.Setup.Denom) // 98 loya -// require.Equal(tipAmount.Amount.Sub(twoPercent.Amount), tipEscrowBalance.Amount.Sub(balanceBeforetip.Amount)) -// // withdraw tip -// msgWithdrawTip := reportertypes.MsgWithdrawTip{ -// SelectorAddress: reporterAddress, -// ValidatorAddress: validator.OperatorAddress, -// } -// _, err = msgServerReporter.WithdrawTip(s.Setup.Ctx, &msgWithdrawTip) -// require.NoError(err) - -// // check that tip is no longer in escrow pool -// tipEscrowBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipEscrowAcct, s.Setup.Denom) -// require.Equal(int64(0), tipEscrowBalance.Amount.Int64()) -// // check that reporter now has more bonded tokens -// deleAfter, err := s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount.Bytes(), valBz) -// require.NoError(err) -// tipPlusTbr := math.NewInt(98 + 26786) -// require.Equal(deleBeforeReport.GetShares().Add(math.LegacyNewDecFromInt(tipPlusTbr)), deleAfter.GetShares()) - -// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) -// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) - -// // case 4: submit without committing for tipped query -// //--------------------------------------------------------------------------- -// // Height 6 -// //--------------------------------------------------------------------------- -// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) -// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) -// require.NoError(err) - -// // check reporter starting shares -// deleBeforeReport2, err := s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount.Bytes(), valBz) -// require.NoError(err) - -// twoPercentTip := sdk.NewCoin(s.Setup.Denom, tipAmount.Amount.Mul(math.NewInt(2)).Quo(math.NewInt(100))) -// twoPercentTipPlusTbr := sdk.NewCoin(s.Setup.Denom, tipAmount.Amount.Mul(math.NewInt(2)).Quo(math.NewInt(tipPlusTbr.Int64()))) -// expectedShares := math.LegacyNewDecFromInt(deleBeforeReport.GetShares().TruncateInt().Add(tipPlusTbr)) // 8928 is the tbr that was earned -// require.Equal(deleBeforeReport2.GetShares(), expectedShares) - -// // create tip msg -// msgTip = oracletypes.MsgTip{ -// Tipper: reporterAccount.String(), -// QueryData: cycleListTrb, -// Amount: tipAmount, -// } -// // send tip tx -// tipRes, err = msgServerOracle.Tip(s.Setup.Ctx, &msgTip) -// require.NoError(err) -// require.NotNil(tipRes) -// // check that tip is in oracle module account -// tipModuleAcct = s.Setup.Accountkeeper.GetModuleAddress(oracletypes.ModuleName) -// tipAcctBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipModuleAcct, s.Setup.Denom) -// require.Equal(tipAcctBalance.Amount, tipAmount.Amount.Sub(twoPercentTip.Amount)) -// // create submit msg -// revealMsgTrb := oracletypes.MsgSubmitValue{ -// Creator: reporterAccount.String(), -// QueryData: cycleListTrb, -// Value: testutil.EncodeValue(1_000_000), -// } -// // send submit msg -// revealTrb, err := msgServerOracle.SubmitValue(s.Setup.Ctx, &revealMsgTrb) -// require.NoError(err) -// require.NotNil(revealTrb) -// // advance time and block height to expire the query and aggregate report -// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(21 * time.Second)) -// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) -// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) -// // create get aggregated report query -// getAggReportRequestTrb := oracletypes.QueryGetCurrentAggregateReportRequest{ -// QueryId: hex.EncodeToString(queryIdTrb), -// } -// // query aggregated report -// reportTrb, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequestTrb) -// require.NoError(err) -// require.Equal(reportTrb.Aggregate.AggregateReportIndex, uint64(0)) -// require.Equal(reportTrb.Aggregate.AggregateValue, testutil.EncodeValue(1_000_000)) -// require.Equal(reportTrb.Aggregate.AggregateReporter, reporterAccount.String()) -// require.Equal(queryIdTrb, reportTrb.Aggregate.QueryId) -// require.Equal(uint64(4000), reportTrb.Aggregate.ReporterPower) -// require.Equal(uint64(6), reportTrb.Aggregate.Height) -// // check that the tip is in tip escrow -// tipEscrowBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipEscrowAcct, s.Setup.Denom) // 98 loya -// require.Equal(tipPlusTbr.Sub(twoPercentTipPlusTbr.Amount), tipEscrowBalance.Amount) -// // withdraw tip -// _, err = msgServerReporter.WithdrawTip(s.Setup.Ctx, &msgWithdrawTip) -// require.NoError(err) -// // check that tip is no longer in escrow pool -// tipEscrowBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipEscrowAcct, s.Setup.Denom) -// require.Equal(int64(0), tipEscrowBalance.Amount.Int64()) -// // check that reporter now has more bonded tokens -// deleAfter, err = s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount.Bytes(), valBz) -// require.NoError(err) -// require.Equal(deleBeforeReport2.GetShares().Add(math.LegacyNewDecFromInt(tipPlusTbr)), deleAfter.GetShares()) -// } - -func (s *E2ETestSuite) TestAggregateOverMultipleBlocks() { - // Setup msgServers - require := s.Require() - msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) - require.NotNil(msgServerOracle) - msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) - require.NotNil(msgServerReporter) - msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) - require.NotNil(msgServerDispute) - msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) - require.NotNil(msgServerStaking) - - //--------------------------------------------------------------------------- - // Height 0 - vicky becomes a validator - //--------------------------------------------------------------------------- - _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - vickyAccAddr := simtestutil.CreateIncrementalAccounts(1) - vickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(vickyInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, vickyAccAddr[0], sdk.NewCoins(vickyInitCoins))) - s.Setup.Accountkeeper.NewAccountWithAddress(s.Setup.Ctx, vickyAccAddr[0]) - - pubKey := simtestutil.CreateTestPubKeys(1) - vickyValAddr := simtestutil.ConvertAddrsToValAddrs(vickyAccAddr) - msgCreateValidator, err := stakingtypes.NewMsgCreateValidator( - vickyValAddr[0].String(), - pubKey[0], - sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), - stakingtypes.Description{Moniker: "created validator"}, - stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(0, 0), math.LegacyNewDecWithPrec(3, 1), math.LegacyNewDecWithPrec(1, 1)), - math.OneInt(), - ) - require.NoError(err) - - _, err = msgServerStaking.CreateValidator(s.Setup.Ctx, msgCreateValidator) - require.NoError(err) - - require.NoError(s.Setup.Bridgekeeper.SetEVMAddressByOperator(s.Setup.Ctx, vickyValAddr[0].String(), []byte("vickyEvmAddr"))) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 1 - Rob delegates to Vicky and selects himself to become a reporter - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(1) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // verify vicky is a bonded validator - vickyValidatorInfo, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, vickyValAddr[0]) - require.NoError(err) - require.Equal(vickyValidatorInfo.Status, stakingtypes.Bonded) - require.Equal(vickyValidatorInfo.Tokens, math.NewInt(1000*1e6)) - - robPrivKey := secp256k1.GenPrivKey() - robAccAddr := sdk.AccAddress(robPrivKey.PubKey().Address()) - robInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(robInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, robAccAddr, sdk.NewCoins(robInitCoins))) - - // rob delegates to vicky - msgDelegate := stakingtypes.NewMsgDelegate( - robAccAddr.String(), - vickyValAddr[0].String(), - sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - - // rob becomes a reporter - _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ - ReporterAddress: robAccAddr.String(), - CommissionRate: reportertypes.DefaultMinCommissionRate, - MinTokensRequired: math.NewInt(1 * 1e6), - }) - require.NoError(err) - robReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, robAccAddr) - require.NoError(err) - require.Equal(robReporterInfo.Jailed, false) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 2 - Delwood delegates 250 trb to Vicky - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(2) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - delwoodPrivKey := secp256k1.GenPrivKey() - delwoodAccAddr := sdk.AccAddress(delwoodPrivKey.PubKey().Address()) - delwoodInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(delwoodInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, delwoodAccAddr, sdk.NewCoins(delwoodInitCoins))) - - msgDelegate = stakingtypes.NewMsgDelegate( - delwoodAccAddr.String(), - vickyValAddr[0].String(), - sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 3 - Delwood selects 250 trb to Rob - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(3) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - _, err = msgServerReporter.SelectReporter(s.Setup.Ctx, &reportertypes.MsgSelectReporter{ - SelectorAddress: delwoodAccAddr.String(), - ReporterAddress: robAccAddr.String(), - }) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 4 - Roman and Ricky become reporters - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(4) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - romanPrivKey := secp256k1.GenPrivKey() - romanAccAddr := sdk.AccAddress(romanPrivKey.PubKey().Address()) - romanInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(200*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(romanInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, romanAccAddr, sdk.NewCoins(romanInitCoins))) - - // roman delegates to vicky - msgDelegate = stakingtypes.NewMsgDelegate( - romanAccAddr.String(), - vickyValAddr[0].String(), - sdk.NewCoin(s.Setup.Denom, math.NewInt(200*1e6)), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - - _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ - ReporterAddress: romanAccAddr.String(), - CommissionRate: reportertypes.DefaultMinCommissionRate, - MinTokensRequired: math.NewInt(1 * 1e6), - }) - require.NoError(err) - romanReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, romanAccAddr) - require.NoError(err) - require.Equal(romanReporterInfo.Jailed, false) - - rickyPrivKey := secp256k1.GenPrivKey() - rickyAccAddr := sdk.AccAddress(rickyPrivKey.PubKey().Address()) - rickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(300*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(rickyInitCoins))) - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, rickyAccAddr, sdk.NewCoins(rickyInitCoins))) - - // ricky delegates to vicky - msgDelegate = stakingtypes.NewMsgDelegate( - rickyAccAddr.String(), - vickyValAddr[0].String(), - sdk.NewCoin(s.Setup.Denom, math.NewInt(300*1e6)), - ) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) - require.NoError(err) - - // ricky becomes a reporter - _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ - ReporterAddress: rickyAccAddr.String(), - CommissionRate: reportertypes.DefaultMinCommissionRate, - MinTokensRequired: math.NewInt(1 * 1e6), - }) - require.NoError(err) - rickyReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, rickyAccAddr) - require.NoError(err) - require.Equal(rickyReporterInfo.Jailed, false) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 5 - only one block left in this cycle list query, pretend empty block - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(5) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 6 - Rob direct reveals for cycle list at height 6 - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(6) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - // Rob direct reveals for cycle list - currentCycleList, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) - require.NoError(err) - queryId := utils.QueryIDFromData(currentCycleList) - msgSubmitValue := oracletypes.MsgSubmitValue{ - Creator: robAccAddr.String(), - QueryData: currentCycleList, - Value: testutil.EncodeValue(90_000), - } - _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &msgSubmitValue) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 7 - Roman and Ricky direct reveal for the same cycle list at height 7 - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(7) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - msgSubmitValue = oracletypes.MsgSubmitValue{ - Creator: romanAccAddr.String(), - QueryData: currentCycleList, - Value: testutil.EncodeValue(100_000), - } - _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &msgSubmitValue) - require.NoError(err) - - msgSubmitValue = oracletypes.MsgSubmitValue{ - Creator: rickyAccAddr.String(), - QueryData: currentCycleList, - Value: testutil.EncodeValue(110_000), - } - _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &msgSubmitValue) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 7 - Commit window expires, report gets aggregated in endblock - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(8) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - aggregate, time, err := s.Setup.Oraclekeeper.GetCurrentAggregateReport(s.Setup.Ctx, queryId) - require.NoError(err) - require.Equal(3, len(aggregate.Reporters)) - require.Equal(aggregate.AggregateReportIndex, uint64(1)) - require.Equal(aggregate.AggregateValue, testutil.EncodeValue(100_000)) - require.Equal(aggregate.AggregateReporter, romanAccAddr.String()) - require.Equal(aggregate.Height, uint64(7)) - require.Equal(aggregate.ReporterPower, uint64(850)) - require.Equal(aggregate.QueryId, queryId) - require.Equal(aggregate.MetaId, uint64(2)) - - agg, err := s.Setup.Oraclekeeper.Aggregates.Get(s.Setup.Ctx, collections.Join(queryId, uint64(time.UnixMilli()))) - require.NoError(err) - require.Equal(3, len(agg.Reporters)) - - oracleQuerier := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) - microreports, err := oracleQuerier.GetReportsByAggregate(s.Setup.Ctx, &oracletypes.QueryGetReportsByAggregateRequest{ - QueryId: hex.EncodeToString(queryId), - Timestamp: uint64(time.UnixMilli()), - Pagination: &query.PageRequest{Limit: 100, CountTotal: true}, - }) - require.NoError(err) - require.Equal(3, len(microreports.MicroReports)) -} diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 6d87def3..c5fdaeb2 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1,95 +1,24 @@ package e2e_test import ( - "fmt" "math/big" "math/rand" "strconv" "time" - "github.com/tellor-io/layer/testutil" - "github.com/tellor-io/layer/utils" - disputekeeper "github.com/tellor-io/layer/x/dispute/keeper" - disputetypes "github.com/tellor-io/layer/x/dispute/types" - minttypes "github.com/tellor-io/layer/x/mint/types" - oraclekeeper "github.com/tellor-io/layer/x/oracle/keeper" - oracletypes "github.com/tellor-io/layer/x/oracle/types" - registrytypes "github.com/tellor-io/layer/x/registry/types" reporterkeeper "github.com/tellor-io/layer/x/reporter/keeper" reportertypes "github.com/tellor-io/layer/x/reporter/types" - collections "cosmossdk.io/collections" "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) -// func (s *E2ETestSuite) TestTransferAfterMint() { -// require := s.Setup.Require() - -// mintToTeamAcc := s.Setup.Accountkeeper.GetModuleAddress(minttypes.MintToTeam) -// require.NotNil(mintToTeamAcc) -// balance := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, mintToTeamAcc, s.Setup.Denom) -// require.Equal(balance.Amount, math.NewInt(300*1e6)) - -// // create 5 accounts -// type Accounts struct { -// PrivateKey secp256k1.PrivKey -// Account sdk.AccAddress -// } -// accounts := make([]Accounts, 0, 5) -// for i := 0; i < 5; i++ { -// privKey := secp256k1.GenPrivKey() -// accountAddress := sdk.AccAddress(privKey.PubKey().Address()) -// account := authtypes.BaseAccount{ -// Address: accountAddress.String(), -// PubKey: codectypes.UnsafePackAny(privKey.PubKey()), -// AccountNumber: uint64(i + 1), -// } -// existingAccount := s.Setup.Accountkeeper.GetAccount(s.Setup.Ctx, accountAddress) -// if existingAccount == nil { -// s.Setup.Accountkeeper.SetAccount(s.Setup.Ctx, &account) -// accounts = append(accounts, Accounts{ -// PrivateKey: *privKey, -// Account: accountAddress, -// }) -// } -// } - -// // transfer 1000 tokens from team to all 5 accounts -// for _, acc := range accounts { -// startBalance := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, acc.Account, s.Setup.Denom).Amount -// err := s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, minttypes.MintToTeam, acc.Account, sdk.NewCoins(sdk.NewCoin(s.Setup.Denom, math.NewInt(1000)))) -// require.NoError(err) -// require.Equal(startBalance.Add(math.NewInt(1000)), s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, acc.Account, s.Setup.Denom).Amount) -// } -// expectedTeamBalance := math.NewInt(300*1e6 - 1000*5) -// require.Equal(expectedTeamBalance, s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, mintToTeamAcc, s.Setup.Denom).Amount) - -// // transfer from account 0 to account 1 -// s.Setup.Bankkeeper.SendCoins(s.Setup.Ctx, accounts[0].Account, accounts[1].Account, sdk.NewCoins(sdk.NewCoin(s.Setup.Denom, math.NewInt(1000)))) -// require.Equal(math.NewInt(0), s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, accounts[0].Account, s.Setup.Denom).Amount) -// require.Equal(math.NewInt(2000), s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, accounts[1].Account, s.Setup.Denom).Amount) - -// // transfer from account 2 to team -// s.Setup.Bankkeeper.SendCoinsFromAccountToModule(s.Setup.Ctx, accounts[2].Account, minttypes.MintToTeam, sdk.NewCoins(sdk.NewCoin(s.Setup.Denom, math.NewInt(1000)))) -// require.Equal(math.NewInt(0), s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, accounts[2].Account, s.Setup.Denom).Amount) -// require.Equal(expectedTeamBalance.Add(math.NewInt(1000)), s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, mintToTeamAcc, s.Setup.Denom).Amount) - -// // try to transfer more than balance from account 3 to 4 -// err := s.Setup.Bankkeeper.SendCoins(s.Setup.Ctx, accounts[3].Account, accounts[4].Account, sdk.NewCoins(sdk.NewCoin(s.Setup.Denom, math.NewInt(1001)))) -// require.Error(err) -// require.Equal(s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, accounts[3].Account, s.Setup.Denom).Amount, math.NewInt(1000)) -// require.Equal(s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, accounts[4].Account, s.Setup.Denom).Amount, math.NewInt(1000)) -// } - func (s *E2ETestSuite) TestSetUpValidatorAndReporter() { require := s.Require() @@ -278,552 +207,3 @@ func (s *E2ETestSuite) TestUnstaking() { require.NoError(err) require.Equal(val1.IsUnbonded(), true) } - -func (s *E2ETestSuite) TestDisputes2() { - require := s.Require() - msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) - require.NotNil(msgServerOracle) - msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) - require.NotNil(msgServerReporter) - msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) - require.NotNil(msgServerDispute) - msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) - require.NotNil(msgServerStaking) - - //--------------------------------------------------------------------------- - // Height 0 - create 3 validators and 3 reporters - //--------------------------------------------------------------------------- - _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - valsAcctAddrs, valsValAddrs, _ := s.Setup.CreateValidators(3) - require.NotNil(valsAcctAddrs) - repsAccs := valsAcctAddrs - for _, val := range valsValAddrs { - err := s.Setup.Bridgekeeper.SetEVMAddressByOperator(s.Setup.Ctx, val.String(), []byte("not real")) - s.NoError(err) - } - badReporter := repsAccs[0] - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - s.NoError(s.Setup.Reporterkeeper.Reporters.Set(s.Setup.Ctx, badReporter, reportertypes.NewReporter(reportertypes.DefaultMinCommissionRate, math.OneInt()))) - s.NoError(s.Setup.Reporterkeeper.Selectors.Set(s.Setup.Ctx, badReporter, reportertypes.NewSelection(badReporter, 1))) - s.NoError(s.Setup.Reporterkeeper.Reporters.Set(s.Setup.Ctx, repsAccs[1], reportertypes.NewReporter(reportertypes.DefaultMinCommissionRate, math.OneInt()))) - s.NoError(s.Setup.Reporterkeeper.Selectors.Set(s.Setup.Ctx, repsAccs[1], reportertypes.NewSelection(repsAccs[1], 1))) - s.NoError(s.Setup.Reporterkeeper.Reporters.Set(s.Setup.Ctx, repsAccs[2], reportertypes.NewReporter(reportertypes.DefaultMinCommissionRate, math.OneInt()))) - s.NoError(s.Setup.Reporterkeeper.Selectors.Set(s.Setup.Ctx, repsAccs[2], reportertypes.NewSelection(repsAccs[2], 1))) - // mapping to track reporter delegation balance - // reporterToBalanceMap := make(map[string]math.Int) - // for _, acc := range repsAccs { - // rkDelegation, err := s.Setup.Reporterkeeper.Delegators.Get(s.Setup.Ctx, acc) - // require.NoError(err) - // reporterToBalanceMap[acc.String()] = rkDelegation.Amount - // } - - //--------------------------------------------------------------------------- - // Height 1 - delegate 500 trb to validator 0 and bad reporter - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(1) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - pk := ed25519.GenPrivKey() - delAcc := s.Setup.ConvertToAccAddress([]ed25519.PrivKey{*pk}) - delAccAddr := delAcc[0] - initCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(500*1e6)) - s.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) - s.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, delAccAddr, sdk.NewCoins(initCoins))) - - // delegate to validator 0 - s.Setup.MintTokens(delAccAddr, math.NewInt(500*1e6)) - _, err = msgServerStaking.Delegate(s.Setup.Ctx, &stakingtypes.MsgDelegate{DelegatorAddress: delAccAddr.String(), ValidatorAddress: valsValAddrs[0].String(), Amount: sdk.NewCoin(s.Setup.Denom, math.NewInt(500*1e6))}) - require.NoError(err) - s.NoError(s.Setup.Reporterkeeper.Selectors.Set(s.Setup.Ctx, delAccAddr, reportertypes.NewSelection(badReporter, 1))) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - val, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, valsValAddrs[0]) - require.NoError(err) - repTokens, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, badReporter) - require.NoError(err) - require.Equal(repTokens, val.Tokens) - - //--------------------------------------------------------------------------- - // Height 2 - direct reveal for cycle list - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(2) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - _, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) - require.NoError(err) - - // get new cycle list query data - cycleListQuery, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) - require.NoError(err) - queryId := utils.QueryIDFromData(cycleListQuery) - // create reveal message - value := testutil.EncodeValue(10_000) - require.NoError(err) - reveal := oracletypes.MsgSubmitValue{ - Creator: repsAccs[0].String(), - QueryData: cycleListQuery, - Value: value, - } - reportBlock := s.Setup.Ctx.BlockHeight() - // send reveal message - revealResponse, err := msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) - require.NoError(err) - require.NotNil(revealResponse) - revealTime := s.Setup.Ctx.BlockTime() - // advance time and block height to expire the query and aggregate report - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(7 * time.Second)) - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 3 - open warning, pay from bond from reporter 1 - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(3) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - // todo: is there a getter for this ? - // get microreport for dispute - report := oracletypes.MicroReport{ - Reporter: repsAccs[0].String(), - Power: repTokens.Quo(sdk.DefaultPowerReduction).Uint64(), - QueryId: queryId, - Value: value, - Timestamp: revealTime, - BlockNumber: uint64(reportBlock), - } - - // disputedBal := disputedRep.TotalTokens - // onePercent := disputedBal.Mul(math.NewInt(1)).Quo(math.NewInt(100)) - fee, err := s.Setup.Disputekeeper.GetDisputeFee(s.Setup.Ctx, report, disputetypes.Warning) - require.NoError(err) - disputeFee := sdk.NewCoin(s.Setup.Denom, fee) // warning should be 1% of bonded tokens - - // create msg for propose dispute tx - msgProposeDispute := disputetypes.MsgProposeDispute{ - Creator: repsAccs[0].String(), - Report: &report, - DisputeCategory: disputetypes.Warning, - Fee: disputeFee, - PayFromBond: true, - } - - // send propose dispute tx - _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) - require.NoError(err) - - burnAmount := disputeFee.Amount.MulRaw(1).QuoRaw(20) - disputes, err := s.Setup.Disputekeeper.GetOpenDisputes(s.Setup.Ctx) - require.NoError(err) - require.NotNil(disputes) - // dispute is created correctly - dispute, err := s.Setup.Disputekeeper.Disputes.Get(s.Setup.Ctx, 1) - require.NoError(err) - require.Equal(dispute.DisputeId, uint64(1)) - require.Equal(dispute.DisputeStatus, disputetypes.Voting) - require.Equal(dispute.DisputeCategory, disputetypes.Warning) - require.Equal(dispute.DisputeFee, disputeFee.Amount.Sub(burnAmount)) - feepayer, err := s.Setup.Disputekeeper.DisputeFeePayer.Get(s.Setup.Ctx, collections.Join(uint64(1), repsAccs[0].Bytes())) - require.NoError(err) - require.Equal(feepayer.Amount, disputeFee.Amount) - require.Equal(feepayer.FromBond, true) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 4 - disputed reporter reports after calling unjail - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(4) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - - disputedRep, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) - require.NoError(err) - require.Equal(disputedRep.Jailed, true) - - // disputed reporter cant report yet - cycleListQuery, err = s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) - require.NoError(err) - value = testutil.EncodeValue(10_000) - require.NoError(err) - reveal = oracletypes.MsgSubmitValue{ - Creator: repsAccs[0].String(), - QueryData: cycleListQuery, - Value: value, - } - _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) - require.Error(err) - - // disputed reporter can report after calling unjail function - msgUnjail := reportertypes.MsgUnjailReporter{ - ReporterAddress: repsAccs[0].String(), - } - _, err = msgServerReporter.UnjailReporter(s.Setup.Ctx, &msgUnjail) - require.NoError(err) - disputedRep, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) - require.NoError(err) - require.Equal(disputedRep.Jailed, false) - // send reveal message - revealResponse, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) - require.NoError(err) - require.NotNil(revealResponse) - revealTime = s.Setup.Ctx.BlockTime() - revealBlock := s.Setup.Ctx.BlockHeight() - - // give disputer tokens to pay for next disputes not from bond - beforemint := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, repsAccs[1], s.Setup.Denom) - initCoins = sdk.NewCoin(s.Setup.Denom, math.NewInt(10_000*1e6)) - require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) - // send from module to account - require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, repsAccs[1], sdk.NewCoins(initCoins))) - require.Equal(beforemint.Add(initCoins), s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, repsAccs[1], s.Setup.Denom)) - - // advance time and block height to expire the query and aggregate report - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(7 * time.Second)) - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - // disputer, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[1]) - // require.NoError(err) - disputedRep, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 5 - open warning, pay from not bond from reporter 1 - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(5) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - report.Power = repTokens.Quo(sdk.DefaultPowerReduction).Uint64() - fee, err = s.Setup.Disputekeeper.GetDisputeFee(s.Setup.Ctx, report, disputetypes.Warning) - require.NoError(err) - disputeFee = sdk.NewCoin(s.Setup.Denom, fee) // warning should be 1% of bonded tokens - - // get microreport for dispute - report = oracletypes.MicroReport{ - Reporter: repsAccs[0].String(), - Power: repTokens.Quo(sdk.DefaultPowerReduction).Uint64(), - QueryId: queryId, - Value: value, - Timestamp: revealTime, - BlockNumber: uint64(revealBlock), - } - - // create msg for propose dispute tx - msgProposeDispute = disputetypes.MsgProposeDispute{ - Creator: repsAccs[1].String(), - Report: &report, - DisputeCategory: disputetypes.Warning, - Fee: disputeFee, - PayFromBond: false, - } - - // send propose dispute tx - _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) - require.NoError(err) - - burnAmount = disputeFee.Amount.MulRaw(1).QuoRaw(20) - disputes, err = s.Setup.Disputekeeper.GetOpenDisputes(s.Setup.Ctx) - require.NoError(err) - require.NotNil(disputes) - // dispute is created correctly - dispute, err = s.Setup.Disputekeeper.Disputes.Get(s.Setup.Ctx, 2) - require.NoError(err) - require.Equal(dispute.DisputeId, uint64(2)) - require.Equal(dispute.DisputeStatus, disputetypes.Voting) - require.Equal(dispute.DisputeCategory, disputetypes.Warning) - require.Equal(dispute.DisputeFee, disputeFee.Amount.Sub(burnAmount)) - feepayer, err = s.Setup.Disputekeeper.DisputeFeePayer.Get(s.Setup.Ctx, collections.Join(uint64(2), repsAccs[1].Bytes())) - require.NoError(err) - require.Equal(feepayer.Amount, disputeFee.Amount) - require.Equal(feepayer.FromBond, false) - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 6 - dispute is resolved, direct reveal again - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(6) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - disputedRep, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) - require.NoError(err) - require.Equal(disputedRep.Jailed, true) - - // disputed reporter cant report yet - cycleListQuery, err = s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) - require.NoError(err) - value = testutil.EncodeValue(10_000) - require.NoError(err) - queryId = utils.QueryIDFromData(cycleListQuery) - reveal = oracletypes.MsgSubmitValue{ - Creator: repsAccs[0].String(), - QueryData: cycleListQuery, - Value: value, - } - _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) - require.Error(err) - - // disputed reporter can report after calling unjail function - msgUnjail = reportertypes.MsgUnjailReporter{ - ReporterAddress: repsAccs[0].String(), - } - _, err = msgServerReporter.UnjailReporter(s.Setup.Ctx, &msgUnjail) - require.NoError(err) - disputedRep, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) - require.NoError(err) - require.Equal(disputedRep.Jailed, false) - // send reveal message - revealResponse, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) - require.NoError(err) - require.NotNil(revealResponse) - revealTime = s.Setup.Ctx.BlockTime() - revealBlock = s.Setup.Ctx.BlockHeight() - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 7 - open minor dispute, pay from bond from reporter 1 - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(7) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - balBeforeDispute := repTokens - fivePercent := balBeforeDispute.Mul(math.NewInt(5)).Quo(math.NewInt(100)) - disputeFee = sdk.NewCoin(s.Setup.Denom, fivePercent) - - report = oracletypes.MicroReport{ - Reporter: repsAccs[0].String(), - Power: repTokens.Quo(sdk.DefaultPowerReduction).Uint64(), - QueryId: queryId, - Value: value, - Timestamp: revealTime, - BlockNumber: uint64(revealBlock), - } - - // create msg for propose dispute tx - msgProposeDispute = disputetypes.MsgProposeDispute{ - Creator: repsAccs[1].String(), - Report: &report, - DisputeCategory: disputetypes.Minor, - Fee: disputeFee, - PayFromBond: true, - } - - // send propose dispute tx - _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) - require.NoError(err) - _ = s.Setup.Ctx.BlockTime() - - _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) - require.NoError(err) - - //--------------------------------------------------------------------------- - // Height 8 - vote on minor dispute -- reaches quorum - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(8) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - // vote from disputer - msgVote := disputetypes.MsgVote{ - Voter: repsAccs[0].String(), - Id: dispute.DisputeId, - Vote: disputetypes.VoteEnum_VOTE_SUPPORT, - } - fmt.Println("Dispute Id on rep[0] vote: ", dispute.DisputeId) - voteResponse, err := msgServerDispute.Vote(s.Setup.Ctx, &msgVote) - require.NoError(err) - require.NotNil(voteResponse) - - // vote from disputed reporter - msgVote = disputetypes.MsgVote{ - Voter: repsAccs[1].String(), - Id: dispute.DisputeId, - Vote: disputetypes.VoteEnum_VOTE_SUPPORT, - } - - voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVote) - require.NoError(err) - require.NotNil(voteResponse) - - // vote from third reporter - // thirdReporter, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[2]) - require.NoError(err) - msgVote = disputetypes.MsgVote{ - Voter: repsAccs[2].String(), - Id: dispute.DisputeId, - Vote: disputetypes.VoteEnum_VOTE_SUPPORT, - } - voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVote) - require.NoError(err) - require.NotNil(voteResponse) - - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) - - // vote from team - // fmt.Println(disputetypes.TeamAddress) - // msgVote = disputetypes.MsgVote{ - // Voter: sdk.MustAccAddressFromBech32(disputetypes.TeamAddress).String(), - // Id: dispute.DisputeId, - // Vote: disputetypes.VoteEnum_VOTE_SUPPORT, - // } - // voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVote) - // require.NoError(err) - // require.NotNil(voteResponse) - - totalTips, err := s.Setup.Disputekeeper.BlockInfo.Get(s.Setup.Ctx, dispute.HashId) - require.NoError(err) - fmt.Println("totalTips: ", totalTips) - - totalReporterPower, err := s.Setup.Reporterkeeper.TotalReporterPower(s.Setup.Ctx) - require.NoError(err) - fmt.Println("total reporter power: ", totalReporterPower.Quo(sdk.DefaultPowerReduction)) - - totalFreeFloatingTokens := s.Setup.Disputekeeper.GetTotalSupply(s.Setup.Ctx) - fmt.Println("total Free Floating Tokens: ", totalFreeFloatingTokens) - owners, err := s.Setup.Bankkeeper.DenomOwners(s.Setup.Ctx, &banktypes.QueryDenomOwnersRequest{Denom: s.Setup.Denom}) - require.NoError(err) - sumFromDenomOwners := math.ZeroInt() - for _, owner := range owners.DenomOwners { - fmt.Println("owner: ", owner) - sumFromDenomOwners = sumFromDenomOwners.Add(owner.Balance.Amount) - } - fmt.Println("sumFromDenomOwners: ", sumFromDenomOwners) - - // print all reporter sdk.AccAddr - for _, rep := range repsAccs { - fmt.Println("rep: ", rep.String()) - } - for _, val := range valsAcctAddrs { - fmt.Println("val: ", val.String()) - } - fmt.Println("delegator acc addr: ", delAccAddr.String()) - - // print tbr module account address - tbrModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(minttypes.TimeBasedRewards) // yes - fmt.Println("tbr module account: ", tbrModuleAccount.String()) - - disputeModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(disputetypes.ModuleName) // yes - fmt.Println("dispute module account: ", disputeModuleAccount.String()) - - authModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(authtypes.ModuleName) // - fmt.Println("auth module account: ", authModuleAccount.String()) - - reporterModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(reportertypes.ModuleName) // yes - fmt.Println("reporter module account: ", reporterModuleAccount.String()) - - registryModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(registrytypes.ModuleName) // no - fmt.Println("registry module account: ", registryModuleAccount.String()) - - reporterTipsEscrowAccount := s.Setup.Accountkeeper.GetModuleAddress(reportertypes.TipsEscrowPool) // no - fmt.Println("reporter tips escrow account: ", reporterTipsEscrowAccount.String()) - - oracleModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(oracletypes.ModuleName) // no - fmt.Println("oracle module account: ", oracleModuleAccount.String()) - - stakingModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(stakingtypes.ModuleName) // - fmt.Println("staking module account: ", stakingModuleAccount.String()) - - //--------------------------------------------------------------------------- - // Height 9 - resolve dispute, direct reveal again - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(9) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - //--------------------------------------------------------------------------- - // Height 10 - open minor dispute, pay from not bond from reporter 1 - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(10) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - //--------------------------------------------------------------------------- - // Height 11 - vote on minor dispute - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(11) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - //--------------------------------------------------------------------------- - // Height 12 - resolve dispute, direct reveal again - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(12) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - //--------------------------------------------------------------------------- - // Height 13 - open major dispute, pay from bond from reporter 1 - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(13) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - //--------------------------------------------------------------------------- - // Height 14 - vote on major dispute - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(14) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - //--------------------------------------------------------------------------- - // Height 15 - resolve dispute, direct reveal again - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(15) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - //--------------------------------------------------------------------------- - // Height 16 - open major dispute, pay from not bond from reporter 1 - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(16) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - //--------------------------------------------------------------------------- - // Height 17 - vote on major dispute - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(17) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) - - //--------------------------------------------------------------------------- - // Height 18 - resolve dispute, direct reveal again - //--------------------------------------------------------------------------- - s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(18) - _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) - require.NoError(err) - s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) -} diff --git a/tests/setup.go b/tests/setup.go index 17c2762e..e1550b06 100644 --- a/tests/setup.go +++ b/tests/setup.go @@ -1,6 +1,7 @@ package setup import ( + "fmt" "strconv" "testing" "time" @@ -25,10 +26,14 @@ import ( mintkeeper "github.com/tellor-io/layer/x/mint/keeper" _ "github.com/tellor-io/layer/x/oracle" oraclekeeper "github.com/tellor-io/layer/x/oracle/keeper" + oracletypes "github.com/tellor-io/layer/x/oracle/types" registrykeeper "github.com/tellor-io/layer/x/registry/keeper" _ "github.com/tellor-io/layer/x/registry/module" + registrytypes "github.com/tellor-io/layer/x/registry/types" reporterkeeper "github.com/tellor-io/layer/x/reporter/keeper" _ "github.com/tellor-io/layer/x/reporter/module" + reportertypes "github.com/tellor-io/layer/x/reporter/types" + "golang.org/x/exp/rand" appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1" authmodulev1 "cosmossdk.io/api/cosmos/auth/module/v1" @@ -309,6 +314,65 @@ func (s *SharedSetup) CreateValidators(numValidators int) ([]sdk.AccAddress, []s return accountsAddrs, validatorsAddrs, validators } +func (s *SharedSetup) CreateValidatorsRandomStake(numValidators int) ([]sdk.AccAddress, []sdk.ValAddress, []stakingtypes.Validator, []int64) { + require := s.require + + // create account that will become a validator + accountsAddrs := simtestutil.CreateIncrementalAccounts(numValidators) + // mint 250k trb for each validator + maxTrb := int64(250_000) + initCoins := sdk.NewCoin(s.Denom, math.NewInt(maxTrb*1e6)) + for _, acc := range accountsAddrs { + // mint to module + require.NoError(s.Bankkeeper.MintCoins(s.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) + // send from module to account + require.NoError(s.Bankkeeper.SendCoinsFromModuleToAccount(s.Ctx, authtypes.Minter, acc, sdk.NewCoins(initCoins))) + require.Equal(initCoins, s.Bankkeeper.GetBalance(s.Ctx, acc, s.Denom)) + } + + // get val address for each account + validatorsAddrs := simtestutil.ConvertAddrsToValAddrs(accountsAddrs) + // create pub keys for validators + pubKeys := simtestutil.CreateTestPubKeys(numValidators) + validators := make([]stakingtypes.Validator, numValidators) + stakingServer := stakingkeeper.NewMsgServerImpl(s.Stakingkeeper) + // set each account with proper keepers + stakes := make([]int64, numValidators) + for i, pubKey := range pubKeys { + s.Accountkeeper.NewAccountWithAddress(s.Ctx, accountsAddrs[i]) + // pick random amount of trb between 1 and 200,000 to stake + rand := rand.New(rand.NewSource(uint64(time.Now().UnixNano()))) + randAmt := (rand.Int63n(200_000 * 1e6)) + stakes[i] = randAmt + randCoins := sdk.NewCoin(s.Denom, math.NewInt(randAmt)) + // create msg for validator creation + valMsg, err := stakingtypes.NewMsgCreateValidator( + validatorsAddrs[i].String(), + pubKey, + randCoins, + stakingtypes.Description{Moniker: strconv.Itoa(i)}, + stakingtypes.CommissionRates{ + Rate: math.LegacyNewDecWithPrec(5, 1), + MaxRate: math.LegacyNewDecWithPrec(5, 1), + MaxChangeRate: math.LegacyNewDec(0), + }, + math.OneInt()) + require.NoError(err) + // create validator + _, err = stakingServer.CreateValidator(s.Ctx, valMsg) + require.NoError(err) + } + _, err := s.Stakingkeeper.EndBlocker(s.Ctx) + require.NoError(err) + + for _, val := range validatorsAddrs { + err := s.Bridgekeeper.SetEVMAddressByOperator(s.Ctx, val.String(), []byte("evmAddr")) + require.NoError(err) + } + + return accountsAddrs, validatorsAddrs, validators, stakes +} + func (s *SharedSetup) MintTokens(addr sdk.AccAddress, amount math.Int) { require := s.require Ctx := s.Ctx @@ -324,3 +388,101 @@ func (s *SharedSetup) ConvertToAccAddress(priv []ed25519.PrivKey) []sdk.AccAddre } return testAddrs } + +func (s *SharedSetup) CreateReporter(ctx sdk.Context, accAddr sdk.AccAddress, commissionRate math.Uint, minTokensRequired math.Int) (reportertypes.OracleReporter, error) { + msgCreateReporter := reportertypes.MsgCreateReporter{ + ReporterAddress: accAddr.String(), + CommissionRate: commissionRate, + MinTokensRequired: minTokensRequired, + } + msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Reporterkeeper) + _, err := msgServerReporter.CreateReporter(ctx, &msgCreateReporter) + if err != nil { + fmt.Println("create reporter fail") + panic(err) + } + + reporter, err := s.Reporterkeeper.Reporter(ctx, accAddr) + if err != nil { + fmt.Println("get reporter fail") + panic(err) + } + return reporter, nil +} + +func (s *SharedSetup) DelegateAndSelect(msgServerStaking stakingtypes.MsgServer, + msgServerReporter reportertypes.MsgServer, + numLoya math.Int, + delegatorAccAddr sdk.AccAddress, + valAddr sdk.ValAddress, + reporterAccAddr sdk.AccAddress) { + + msgDelegate := stakingtypes.MsgDelegate{ + DelegatorAddress: delegatorAccAddr.String(), + ValidatorAddress: valAddr.String(), + Amount: sdk.NewCoin(s.Denom, numLoya), + } + _, err := msgServerStaking.Delegate(s.Ctx, &msgDelegate) + if err != nil { + fmt.Println("delegate fail") + panic(err) + } + + msgSelectReporter := reportertypes.MsgSelectReporter{ + SelectorAddress: delegatorAccAddr.String(), + ReporterAddress: reporterAccAddr.String(), + } + _, err = msgServerReporter.SelectReporter(s.Ctx, &msgSelectReporter) + if err != nil { + fmt.Println("select reporter fail") + panic(err) + } +} + +func (s *SharedSetup) CreateFundedAccount(numTrb int64) (sdk.AccAddress, error) { + priv := secp256k1.GenPrivKey() + addr := sdk.AccAddress(priv.PubKey().Address()) + s.MintTokens(addr, math.NewInt(numTrb*1e6)) + return addr, nil +} + +func (s *SharedSetup) CreateSpotPriceTip(ctx sdk.Context, tipperAccAddr sdk.AccAddress, parameters string, amountLoya math.Int) *[]byte { + + req := ®istrytypes.QueryGenerateQuerydataRequest{ + Querytype: "SpotPrice", + Parameters: parameters, + } + res, err := s.Registrykeeper.GenerateQuerydata(ctx, req) + if err != nil { + panic(err) + } + + msgTip := oracletypes.MsgTip{ + Tipper: tipperAccAddr.String(), + QueryData: res.QueryData, + Amount: sdk.NewCoin(s.Denom, amountLoya), + } + oracleMsgServer := oraclekeeper.NewMsgServerImpl(s.Oraclekeeper) + _, err = oracleMsgServer.Tip(ctx, &msgTip) + if err != nil { + panic(err) + } + + return &res.QueryData +} + +func (s *SharedSetup) Report(ctx sdk.Context, reporterAccAddr sdk.AccAddress, queryData []byte, reportValue string) { + + msgSubmitValue := oracletypes.MsgSubmitValue{ + Creator: reporterAccAddr.String(), + QueryData: queryData, + Value: reportValue, + } + + oracleMsgServer := oraclekeeper.NewMsgServerImpl(s.Oraclekeeper) + _, err := oracleMsgServer.SubmitValue(ctx, &msgSubmitValue) + if err != nil { + fmt.Println("submit value fail") + panic(err) + } +} diff --git a/x/oracle/abci.go b/x/oracle/abci.go index 1f2eb0ab..4f2fc3ac 100644 --- a/x/oracle/abci.go +++ b/x/oracle/abci.go @@ -2,23 +2,22 @@ package oracle import ( "context" - "fmt" + // "fmt" - "github.com/tellor-io/layer/utils" + // "github.com/tellor-io/layer/utils" "github.com/tellor-io/layer/x/oracle/keeper" - - sdk "github.com/cosmos/cosmos-sdk/types" + // sdk "github.com/cosmos/cosmos-sdk/types" ) func EndBlocker(ctx context.Context, k keeper.Keeper) error { - currentHeight := sdk.UnwrapSDKContext(ctx).BlockHeight() - currentCycleListQuery, err := k.GetCurrentQueryInCycleList(ctx) - if err != nil { - return err - } - queryId := utils.QueryIDFromData(currentCycleListQuery) - fmt.Println("\ncurrentHeight:", currentHeight) - fmt.Println("queryId:", queryId) + // currentHeight := sdk.UnwrapSDKContext(ctx).BlockHeight() + // currentCycleListQuery, err := k.GetCurrentQueryInCycleList(ctx) + // if err != nil { + // return err + // } + // queryId := utils.QueryIDFromData(currentCycleListQuery) + // fmt.Println("\ncurrentHeight:", currentHeight) + // fmt.Println("queryId:", queryId) // Rotate through the cycle list and set the current query index if err := k.SetAggregatedReport(ctx); err != nil { return err diff --git a/x/oracle/keeper/msg_server_submit_value.go b/x/oracle/keeper/msg_server_submit_value.go index 69314f41..08d9116e 100644 --- a/x/oracle/keeper/msg_server_submit_value.go +++ b/x/oracle/keeper/msg_server_submit_value.go @@ -3,6 +3,7 @@ package keeper import ( "context" "errors" + "fmt" "strings" layertypes "github.com/tellor-io/layer/types" @@ -46,6 +47,7 @@ func (k msgServer) SubmitValue(ctx context.Context, msg *types.MsgSubmitValue) ( queryId := utils.QueryIDFromData(msg.QueryData) query, err := k.keeper.CurrentQuery(ctx, queryId) + fmt.Println("query.QueryType from SubmitValue: ", query.QueryType) if err != nil { if !errors.Is(err, collections.ErrNotFound) { return nil, err diff --git a/x/oracle/keeper/submit_value.go b/x/oracle/keeper/submit_value.go index 1a372d63..b73ff209 100644 --- a/x/oracle/keeper/submit_value.go +++ b/x/oracle/keeper/submit_value.go @@ -19,6 +19,7 @@ import ( func (k Keeper) SetValue(ctx context.Context, reporter sdk.AccAddress, query types.QueryMeta, val string, queryData []byte, power uint64, incycle bool) error { // decode query data hex to get query type, returns interface array queryType, _, err := regTypes.DecodeQueryType(queryData) + fmt.Println("queryType from SetValue: ", queryType) if err != nil { return status.Error(codes.InvalidArgument, fmt.Sprintf("failed to decode query type: %v", err)) } @@ -46,7 +47,9 @@ func (k Keeper) SetValue(ctx context.Context, reporter sdk.AccAddress, query typ BlockNumber: uint64(sdkCtx.BlockHeight()), } + fmt.Println("report.QueryType from SetValue: ", report.QueryType) query.HasRevealedReports = true + fmt.Println("query.QueryType from SetValue: ", query.QueryType) err = k.Query.Set(ctx, collections.Join(queryId, query.Id), query) if err != nil { return err From add5353da677d634a72f810a76aaec50a053689c Mon Sep 17 00:00:00 2001 From: danflo27 Date: Thu, 31 Oct 2024 10:16:28 -0400 Subject: [PATCH 7/8] rounding check test for tip/report/opening dispute, e2e cleanup --- heighliner | 1 + tests/e2e/dispute_test.go | 1652 ++++++++++++++++++++ tests/e2e/reporting_test.go | 793 ++++++++++ tests/setup.go | 28 +- x/dispute/keeper/dispute.go | 2 +- x/oracle/abci.go | 2 - x/oracle/keeper/msg_server_submit_value.go | 2 - x/oracle/keeper/msg_server_tip.go | 1 - x/oracle/keeper/submit_value.go | 3 - 9 files changed, 2469 insertions(+), 15 deletions(-) create mode 160000 heighliner create mode 100644 tests/e2e/dispute_test.go create mode 100644 tests/e2e/reporting_test.go diff --git a/heighliner b/heighliner new file mode 160000 index 00000000..b675b55c --- /dev/null +++ b/heighliner @@ -0,0 +1 @@ +Subproject commit b675b55c3c252681dde0c1449035e5c625907915 diff --git a/tests/e2e/dispute_test.go b/tests/e2e/dispute_test.go new file mode 100644 index 00000000..a94cc3f1 --- /dev/null +++ b/tests/e2e/dispute_test.go @@ -0,0 +1,1652 @@ +package e2e_test + +import ( + "encoding/hex" + "fmt" + "math/rand" + "time" + + "github.com/tellor-io/layer/testutil" + layertypes "github.com/tellor-io/layer/types" + utils "github.com/tellor-io/layer/utils" + disputekeeper "github.com/tellor-io/layer/x/dispute/keeper" + disputetypes "github.com/tellor-io/layer/x/dispute/types" + minttypes "github.com/tellor-io/layer/x/mint/types" + oraclekeeper "github.com/tellor-io/layer/x/oracle/keeper" + oracletypes "github.com/tellor-io/layer/x/oracle/types" + registrytypes "github.com/tellor-io/layer/x/registry/types" + reporterkeeper "github.com/tellor-io/layer/x/reporter/keeper" + reportertypes "github.com/tellor-io/layer/x/reporter/types" + + collections "cosmossdk.io/collections" + math "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + secp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +func (s *E2ETestSuite) TestDisputes() { + require := s.Require() + msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) + require.NotNil(msgServerOracle) + msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) + require.NotNil(msgServerReporter) + msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) + require.NotNil(msgServerDispute) + msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) + require.NotNil(msgServerStaking) + + //--------------------------------------------------------------------------- + // Height 0 - create validator and 2 reporters + //--------------------------------------------------------------------------- + _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // create a validator + valAccount := simtestutil.CreateIncrementalAccounts(1) + // mint 5000*1e8 tokens for validator + initCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(5000*1e8)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, valAccount[0], sdk.NewCoins(initCoins))) + // get val address + valAccountValAddrs := simtestutil.ConvertAddrsToValAddrs(valAccount) + // create pub key for validator + pubKey := simtestutil.CreateTestPubKeys(1) + // tell keepers about the new validator + s.Setup.Accountkeeper.NewAccountWithAddress(s.Setup.Ctx, valAccount[0]) + msgCreateValidaotr, err := stakingtypes.NewMsgCreateValidator( + valAccountValAddrs[0].String(), + pubKey[0], + sdk.NewCoin(s.Setup.Denom, math.NewInt(4000*1e8)), + stakingtypes.Description{Moniker: "created validator"}, + stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(0, 0), math.LegacyNewDecWithPrec(3, 1), math.LegacyNewDecWithPrec(1, 1)), + math.OneInt(), + ) + require.NoError(err) + _, err = msgServerStaking.CreateValidator(s.Setup.Ctx, msgCreateValidaotr) + require.NoError(err) + for _, val := range valAccountValAddrs { + err := s.Setup.Bridgekeeper.SetEVMAddressByOperator(s.Setup.Ctx, val.String(), []byte("not real")) + s.NoError(err) + } + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + validator, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, valAccountValAddrs[0]) + require.NoError(err) + + type Delegator struct { + delegatorAddress sdk.AccAddress + validator stakingtypes.Validator + tokenAmount math.Int + } + pk := secp256k1.GenPrivKey() + reporterAccount := sdk.AccAddress(pk.PubKey().Address()) + // mint 5000*1e6 tokens for reporter + s.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) + s.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, reporterAccount, sdk.NewCoins(initCoins))) + // delegate 5k trb to validator so reporter can delegate to themselves + reporterDelToVal := Delegator{delegatorAddress: reporterAccount, validator: validator, tokenAmount: math.NewInt(4000 * 1e6)} + msgDelegate := stakingtypes.NewMsgDelegate( + reporterDelToVal.delegatorAddress.String(), + reporterDelToVal.validator.GetOperator(), sdk.NewCoin(s.Setup.Denom, reporterDelToVal.tokenAmount), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + // // check that reporter was created in Reporters collections + _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ReporterAddress: reporterAccount.String(), CommissionRate: reportertypes.DefaultMinCommissionRate, MinTokensRequired: math.NewInt(4000 * 1e6)}) + require.NoError(err) + reporter, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) + fmt.Println(reporterAccount.String()) + require.NoError(err) + require.Equal(reporter.Jailed, false) + // // check on reporter in Delegators collections + rkDelegation, err := s.Setup.Reporterkeeper.Selectors.Get(s.Setup.Ctx, reporterAccount) + require.NoError(err) + require.Equal(rkDelegation.Reporter, reporterAccount.Bytes()) + + // check on reporter/validator delegation + skDelegation, err := s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount, valAccountValAddrs[0]) + require.NoError(err) + require.Equal(skDelegation.GetDelegatorAddr(), reporterAccount.String()) + require.Equal(skDelegation.GetValidatorAddr(), validator.GetOperator()) + + //--------------------------------------------------------------------------- + // Height 1 - direct reveal for cycle list + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + // get new cycle list query data + cycleListQuery, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) + require.NoError(err) + // create reveal message + value := testutil.EncodeValue(100_000) + require.NoError(err) + reveal := oracletypes.MsgSubmitValue{ + Creator: reporterAccount.String(), + QueryData: cycleListQuery, + Value: value, + } + // send reveal message + revealResponse, err := msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) + revealBlock := s.Setup.Ctx.BlockHeight() + require.NoError(err) + require.NotNil(revealResponse) + // advance block height to expire the query and aggregate report + + //--------------------------------------------------------------------------- + // Height 2 - advance block to expire query + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + //--------------------------------------------------------------------------- + // Height 3 - advance block to expire query + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + //--------------------------------------------------------------------------- + // Height 4 - check on aggregate + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // get queryId for GetAggregatedReportRequest + queryId := utils.QueryIDFromData(cycleListQuery) + s.NoError(err) + // create get aggregated report query + getAggReportRequest := oracletypes.QueryGetCurrentAggregateReportRequest{ + QueryId: hex.EncodeToString(queryId), + } + // aggregated report is stored correctly + queryServer := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) + result, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest) + require.NoError(err) + require.Equal(uint64(0), result.Aggregate.AggregateReportIndex) + require.Equal(testutil.EncodeValue(100_000), result.Aggregate.AggregateValue) + require.Equal(reporterAccount.String(), result.Aggregate.AggregateReporter) + require.Equal(queryId, result.Aggregate.QueryId) + require.Equal(uint64(4000), result.Aggregate.ReporterPower) + require.Equal(uint64(3), result.Aggregate.Height) + + //--------------------------------------------------------------------------- + // Height 5 - create a dispute + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) + require.NoError(err) + require.Equal(reporter.Jailed, false) + freeFloatingBalanceBefore := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterAccount, s.Setup.Denom) + + balBeforeDispute, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, reporterAccount) + require.NoError(err) + onePercent := balBeforeDispute.Mul(math.NewInt(1)).Quo(math.NewInt(100)) + disputeFee := sdk.NewCoin(s.Setup.Denom, onePercent) // warning should be 1% of bonded tokens + + // todo: is there a getter for this ? + // get microreport for dispute + report := oracletypes.MicroReport{ + Reporter: reporterAccount.String(), + Power: balBeforeDispute.Quo(sdk.DefaultPowerReduction).Uint64(), + QueryId: queryId, + Value: value, + Timestamp: s.Setup.Ctx.BlockTime(), + BlockNumber: uint64(revealBlock), + } + + // create msg for propose dispute tx + msgProposeDispute := disputetypes.MsgProposeDispute{ + Creator: reporterAccount.String(), + Report: &report, + DisputeCategory: disputetypes.Warning, + Fee: disputeFee, + PayFromBond: false, + } + + // send propose dispute tx + _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) + require.NoError(err) + + burnAmount := disputeFee.Amount.MulRaw(1).QuoRaw(20) + disputes, err := s.Setup.Disputekeeper.GetOpenDisputes(s.Setup.Ctx) + require.NoError(err) + require.NotNil(disputes) + require.Equal(1, len(disputes)) + // dispute is created correctly + dispute, err := s.Setup.Disputekeeper.Disputes.Get(s.Setup.Ctx, 1) + require.NoError(err) + require.Equal(dispute.DisputeId, uint64(1)) + require.Equal(dispute.DisputeStatus, disputetypes.Voting) + require.Equal(dispute.DisputeCategory, disputetypes.Warning) + require.Equal(dispute.DisputeFee, disputeFee.Amount.Sub(burnAmount)) + feepayer, err := s.Setup.Disputekeeper.DisputeFeePayer.Get(s.Setup.Ctx, collections.Join(uint64(1), reporterAccount.Bytes())) + require.NoError(err) + require.Equal(feepayer.Amount, disputeFee.Amount) + require.Equal(feepayer.FromBond, false) + slashAmount := dispute.SlashAmount + firstDisputeVoteMsg := disputetypes.MsgVote{ + Voter: reporterAccount.String(), + Id: dispute.DisputeId, + Vote: disputetypes.VoteEnum_VOTE_SUPPORT, + } + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 6 - unjail reporter + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, dispute.DisputeId) + require.Error(err, "vote period not ended and quorum not reached") + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // reporter is in jail + reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) + require.NoError(err) + require.Equal(reporter.Jailed, true) + // reporter lost 1% of their free floating tokens + freeFloatingBalanceAfter := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterAccount, s.Setup.Denom) + require.Equal(freeFloatingBalanceAfter, freeFloatingBalanceBefore.Sub(disputeFee)) + + // create msgUnJailReporter + msgUnjailReporter := reportertypes.MsgUnjailReporter{ + ReporterAddress: reporterAccount.String(), + } + // send unjailreporter tx + _, err = msgServerReporter.UnjailReporter(s.Setup.Ctx, &msgUnjailReporter) + require.NoError(err) + + // reporter is now unjailed + reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) + require.NoError(err) + require.Equal(reporter.Jailed, false) + freeFloatingBalanceAfter = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterAccount, s.Setup.Denom) + require.Equal(freeFloatingBalanceAfter, freeFloatingBalanceBefore.Sub(disputeFee)) + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + // todo: more balance checks at each step + + //--------------------------------------------------------------------------- + // Height 7 - direct reveal for cycle list again + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 1) + require.Error(err, "vote period not ended and quorum not reached") + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // get new cycle list query data + cycleListQuery, err = s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) + require.NoError(err) + // create reveal message + value = testutil.EncodeValue(100_000) + require.NoError(err) + reveal = oracletypes.MsgSubmitValue{ + Creator: reporterAccount.String(), + QueryData: cycleListQuery, + Value: value, + } + secReportQueryId := utils.QueryIDFromData(cycleListQuery) + // send reveal message + revealResponse, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) + revealBlock = s.Setup.Ctx.BlockHeight() + require.NoError(err) + require.NotNil(revealResponse) + // advance block height to expire the query and aggregate report + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 8 - advance block to expire query + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + //--------------------------------------------------------------------------- + // Height 9 - advance block to expire query + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + // get queryId for GetAggregatedReportRequest + queryId = utils.QueryIDFromData(cycleListQuery) + s.NoError(err) + // create get aggregated report query + getAggReportRequest = oracletypes.QueryGetCurrentAggregateReportRequest{ + QueryId: hex.EncodeToString(queryId), + } + // aggregated report is stored correctly + result, err = queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest) + require.NoError(err) + require.Equal(uint64(0), result.Aggregate.AggregateReportIndex) + require.Equal(testutil.EncodeValue(100_000), result.Aggregate.AggregateValue) + require.Equal(reporterAccount.String(), result.Aggregate.AggregateReporter) + require.Equal(queryId, result.Aggregate.QueryId) + require.Equal(uint64(4000)-slashAmount.Quo(sdk.DefaultPowerReduction).Uint64(), result.Aggregate.ReporterPower) + require.Equal(uint64(7), result.Aggregate.Height) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 10 - open minor dispute + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + balBeforeDispute, err = s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, reporterAccount) + fmt.Println("Balance before dispute: ", balBeforeDispute) + require.NoError(err) + fivePercent := balBeforeDispute.Mul(math.NewInt(5)).Quo(math.NewInt(100)) + disputeFee = sdk.NewCoin(s.Setup.Denom, fivePercent) + + report = oracletypes.MicroReport{ + Reporter: reporterAccount.String(), + Power: balBeforeDispute.Quo(sdk.DefaultPowerReduction).Uint64(), + QueryId: secReportQueryId, + Value: value, + Timestamp: s.Setup.Ctx.BlockTime(), + BlockNumber: uint64(revealBlock), + } + + fmt.Println("Report power: ", report.Power) + + // create msg for propose dispute tx + msgProposeDispute = disputetypes.MsgProposeDispute{ + Creator: reporterAccount.String(), + Report: &report, + DisputeCategory: disputetypes.Minor, + Fee: disputeFee, + PayFromBond: false, + } + + // send propose dispute tx + _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) + require.NoError(err) + disputeStartTime := s.Setup.Ctx.BlockTime() + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 11 - vote on minor dispute + // --------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 1) + require.Error(err, "vote period not ended and quorum not reached") + err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 2) + require.Error(err, "vote period not ended and quorum not reached") + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // reporter is in jail + reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) + require.NoError(err) + require.Equal(reporter.Jailed, true) + // dispute is created correctly + burnAmount = disputeFee.Amount.MulRaw(1).QuoRaw(20) + dispute, err = s.Setup.Disputekeeper.GetDisputeByReporter(s.Setup.Ctx, report, disputetypes.Minor) + fmt.Printf("Dispute: %v,\r Report: %v\r", dispute, report) + require.NoError(err) + require.Equal(dispute.DisputeCategory, disputetypes.Minor) + require.Equal(dispute.DisputeStatus, disputetypes.Voting) + require.Equal(dispute.DisputeFee, disputeFee.Amount.Sub(burnAmount)) + feepayer, err = s.Setup.Disputekeeper.DisputeFeePayer.Get(s.Setup.Ctx, collections.Join(dispute.DisputeId, reporterAccount.Bytes())) + require.NoError(err) + require.Equal(feepayer.Amount, disputeFee.Amount) + require.Equal(feepayer.FromBond, false) + + firstVoteReponse, err := msgServerDispute.Vote(s.Setup.Ctx, &firstDisputeVoteMsg) + require.NoError(err) + require.NotNil(firstVoteReponse) + + // create vote tx msg + msgVote := disputetypes.MsgVote{ + Voter: reporterAccount.String(), + Id: dispute.DisputeId, + Vote: disputetypes.VoteEnum_VOTE_SUPPORT, + } + // send vote tx for second dispute + voteResponse, err := msgServerDispute.Vote(s.Setup.Ctx, &msgVote) + require.NoError(err) + require.NotNil(voteResponse) + + // vote is properly stored + vote, err := s.Setup.Disputekeeper.Votes.Get(s.Setup.Ctx, dispute.DisputeId) + require.NoError(err) + require.NotNil(vote) + require.Equal(vote.Executed, false) + require.Equal(vote.Id, dispute.DisputeId) + require.Equal(vote.VoteStart, disputeStartTime) + require.Equal(vote.VoteEnd, disputeStartTime.Add(disputekeeper.TWO_DAYS)) + + // advance 2 days to expire vote + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(disputekeeper.THREE_DAYS)) + // call unjail function + msgUnjailReporter = reportertypes.MsgUnjailReporter{ + ReporterAddress: reporterAccount.String(), + } + _, err = msgServerReporter.UnjailReporter(s.Setup.Ctx, &msgUnjailReporter) + require.NoError(err) + + // reporter no longer in jail + reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) + require.NoError(err) + require.Equal(reporter.Jailed, false) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 12 - minor dispute ends and another direct reveal for cycle list + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + require.NoError(s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 1)) + require.NoError(s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 2)) + require.NoError(s.Setup.Disputekeeper.ExecuteVote(s.Setup.Ctx, 1)) + require.NoError(s.Setup.Disputekeeper.ExecuteVote(s.Setup.Ctx, 2)) + + // vote is executed + vote, err = s.Setup.Disputekeeper.Votes.Get(s.Setup.Ctx, dispute.DisputeId) + require.NoError(err) + require.NotNil(vote) + require.Equal(vote.Executed, true) + require.Equal(vote.Id, dispute.DisputeId) + // reporter no longer in jail + reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) + require.NoError(err) + require.Equal(reporter.Jailed, false) + + // get open disputes + disputes, err = s.Setup.Disputekeeper.GetOpenDisputes(s.Setup.Ctx) + require.NoError(err) + require.NotNil(disputes) + + cycleListQuery, err = s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) + require.NoError(err) + // create reveal message + value = testutil.EncodeValue(100_000) + require.NoError(err) + reveal = oracletypes.MsgSubmitValue{ + Creator: reporterAccount.String(), + QueryData: cycleListQuery, + Value: value, + } + // send reveal message + revealResponse, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) + revealBlock = s.Setup.Ctx.BlockHeight() + require.NoError(err) + require.NotNil(revealResponse) + // advance time and block height to expire the query and aggregate report + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(21 * time.Second)) + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + // get queryId for GetAggregatedReportRequest + queryId = utils.QueryIDFromData(cycleListQuery) + s.NoError(err) + // create get aggregated report query + getAggReportRequest = oracletypes.QueryGetCurrentAggregateReportRequest{ + QueryId: hex.EncodeToString(queryId), + } + // check that aggregated report is stored correctly + result, err = queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest) + require.NoError(err) + require.Equal(uint64(0), result.Aggregate.AggregateReportIndex) + require.Equal(testutil.EncodeValue(100_000), result.Aggregate.AggregateValue) + require.Equal(reporterAccount.String(), result.Aggregate.AggregateReporter) + require.Equal(queryId, result.Aggregate.QueryId) + require.Equal(uint64(7), result.Aggregate.Height) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 13 - open major dispute for report + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) + require.NoError(err) + require.Equal(reporter.Jailed, false) + + oneHundredPercent, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, reporterAccount) + require.NoError(err) + disputeFee = sdk.NewCoin(s.Setup.Denom, oneHundredPercent) + + report = oracletypes.MicroReport{ + Reporter: reporterAccount.String(), + Power: oneHundredPercent.Quo(sdk.DefaultPowerReduction).Uint64(), + QueryId: queryId, + Value: value, + Timestamp: s.Setup.Ctx.BlockTime(), + BlockNumber: uint64(revealBlock), + } + // create msg for propose dispute tx + + msgProposeDispute = disputetypes.MsgProposeDispute{ + Creator: reporterAccount.String(), + Report: &report, + DisputeCategory: disputetypes.Major, + Fee: disputeFee, + PayFromBond: false, + } + + // send propose dispute tx + _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) + require.NoError(err) + disputeStartTime = s.Setup.Ctx.BlockTime() + disputeStartHeight := uint64(s.Setup.Ctx.BlockHeight()) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 9 - vote on major dispute + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 3) + require.Error(err, "vote period not ended and quorum not reached") + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + fee, err := s.Setup.Disputekeeper.GetDisputeFee(s.Setup.Ctx, report, disputetypes.Major) + require.NoError(err) + require.GreaterOrEqual(msgProposeDispute.Fee.Amount.Uint64(), fee.Uint64()) + + // dispute is created and open for voting + dispute, err = s.Setup.Disputekeeper.GetDisputeByReporter(s.Setup.Ctx, report, disputetypes.Major) + require.NoError(err) + burnAmount = disputeFee.Amount.MulRaw(1).QuoRaw(20) + require.Equal(dispute.DisputeStatus, disputetypes.Voting) + require.Equal(dispute.DisputeStartTime, disputeStartTime) + require.Equal(dispute.DisputeEndTime, disputeStartTime.Add(disputekeeper.THREE_DAYS)) + require.Equal(dispute.DisputeFee, disputeFee.Amount.Sub(burnAmount)) + require.Equal(dispute.DisputeStartBlock, disputeStartHeight) + + // create vote tx msg + msgVote = disputetypes.MsgVote{ + Voter: reporterAccount.String(), + Id: dispute.DisputeId, + Vote: disputetypes.VoteEnum_VOTE_SUPPORT, + } + // send vote tx + voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVote) + require.NoError(err) + require.NotNil(voteResponse) + + // vote is properly stored + vote, err = s.Setup.Disputekeeper.Votes.Get(s.Setup.Ctx, dispute.DisputeId) + require.NoError(err) + require.NotNil(vote) + require.Equal(vote.Executed, false) + require.Equal(vote.Id, dispute.DisputeId) + require.Equal(vote.VoteStart, disputeStartTime) + require.Equal(vote.VoteEnd, disputeStartTime.Add(disputekeeper.TWO_DAYS)) + + // advance 3 days to expire vote + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(disputekeeper.THREE_DAYS)) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + // --------------------------------------------------------------------------- + // Height 10 - dispute is resolved, reporter no longer a reporter + // --------------------------------------------------------------------------- + // s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + // s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + // _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + // require.NoError(err) + + err = s.Setup.Disputekeeper.TallyVote(s.Setup.Ctx, 3) + require.NoError(err) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + // reporter, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) + // require.NoError(err) +} + +// Vicky the Validator has 1000 trb staked +// Rob the Reporter has 100 trb staked with Vicky, selects himself as a reporter +// Ricky the Reporter has 100 trb staked with Vicky, selects himself as a reporter +// Delwood the Delegator has 250 trb selected to Rob +// Delwood tries to dispute Rickys report +// fails +func (s *E2ETestSuite) TestDisputeFromDelegatorPayFromBond() { + // Setup msgServers + require := s.Require() + msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) + require.NotNil(msgServerOracle) + msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) + require.NotNil(msgServerReporter) + msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) + require.NotNil(msgServerDispute) + msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) + require.NotNil(msgServerStaking) + + //--------------------------------------------------------------------------- + // Height 0 - vicky becomes a validator + //--------------------------------------------------------------------------- + _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + vickyAccAddr := simtestutil.CreateIncrementalAccounts(1) + vickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) // give vicky extra to act as free floating token voting group + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(vickyInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, vickyAccAddr[0], sdk.NewCoins(vickyInitCoins))) + s.Setup.Accountkeeper.NewAccountWithAddress(s.Setup.Ctx, vickyAccAddr[0]) + + pubKey := simtestutil.CreateTestPubKeys(1) + vickyValAddr := simtestutil.ConvertAddrsToValAddrs(vickyAccAddr) + msgCreateValidator, err := stakingtypes.NewMsgCreateValidator( + vickyValAddr[0].String(), + pubKey[0], + sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), + stakingtypes.Description{Moniker: "created validator"}, + stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(0, 0), math.LegacyNewDecWithPrec(3, 1), math.LegacyNewDecWithPrec(1, 1)), + math.OneInt(), + ) + require.NoError(err) + + _, err = msgServerStaking.CreateValidator(s.Setup.Ctx, msgCreateValidator) + require.NoError(err) + + require.NoError(s.Setup.Bridgekeeper.SetEVMAddressByOperator(s.Setup.Ctx, vickyValAddr[0].String(), []byte("vickyEvmAddr"))) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 1 - Rob delegates to Vicky and selects himself to become a reporter + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // verify vicky is a bonded validator + vickyValidatorInfo, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, vickyValAddr[0]) + require.NoError(err) + require.Equal(vickyValidatorInfo.Status, stakingtypes.Bonded) + require.Equal(vickyValidatorInfo.Tokens, math.NewInt(1000*1e6)) + + robPrivKey := secp256k1.GenPrivKey() + robAccAddr := sdk.AccAddress(robPrivKey.PubKey().Address()) + robInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(robInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, robAccAddr, sdk.NewCoins(robInitCoins))) + + // rob delegates to vicky + msgDelegate := stakingtypes.NewMsgDelegate( + robAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + // rob becomes a reporter + _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ + ReporterAddress: robAccAddr.String(), + CommissionRate: reportertypes.DefaultMinCommissionRate, + MinTokensRequired: math.NewInt(1 * 1e6), + }) + require.NoError(err) + robReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, robAccAddr) + require.NoError(err) + require.Equal(robReporterInfo.Jailed, false) + + rickyPrivKey := secp256k1.GenPrivKey() + rickyAccAddr := sdk.AccAddress(rickyPrivKey.PubKey().Address()) + rickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(rickyInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, rickyAccAddr, sdk.NewCoins(rickyInitCoins))) + + // ricky delegates to vicky + msgDelegate = stakingtypes.NewMsgDelegate( + rickyAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + // ricky becomes a reporter + _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ + ReporterAddress: rickyAccAddr.String(), + CommissionRate: reportertypes.DefaultMinCommissionRate, + MinTokensRequired: math.NewInt(1 * 1e6), + }) + require.NoError(err) + rickyReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, rickyAccAddr) + require.NoError(err) + require.Equal(rickyReporterInfo.Jailed, false) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 2 - Delwood delegates 250 trb to Vicky + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(2) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + delwoodPrivKey := secp256k1.GenPrivKey() + delwoodAccAddr := sdk.AccAddress(delwoodPrivKey.PubKey().Address()) + delwoodInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(delwoodInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, delwoodAccAddr, sdk.NewCoins(delwoodInitCoins))) + + msgDelegate = stakingtypes.NewMsgDelegate( + delwoodAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 3 - Delwood selects 250 trb to Rob + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(3) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = msgServerReporter.SelectReporter(s.Setup.Ctx, &reportertypes.MsgSelectReporter{ + SelectorAddress: delwoodAccAddr.String(), + ReporterAddress: robAccAddr.String(), + }) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 4 - Ricky reports for the cycle list + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(4) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + currentCycleList, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) + require.NoError(err) + queryId := utils.QueryIDFromData(currentCycleList) + msgSubmitValue := oracletypes.MsgSubmitValue{ + Creator: rickyAccAddr.String(), + QueryData: currentCycleList, + Value: testutil.EncodeValue(100_000), + } + _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &msgSubmitValue) + require.NoError(err) + + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 2) // advance to 6, call 6 endblocker + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + getAggReportRequest := oracletypes.QueryGetCurrentAggregateReportRequest{ + QueryId: hex.EncodeToString(queryId), + } + queryServer := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) + result, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest) + require.NoError(err) + require.Equal(uint64(0), result.Aggregate.AggregateReportIndex) + require.Equal(testutil.EncodeValue(100_000), result.Aggregate.AggregateValue) + require.Equal(rickyAccAddr.String(), result.Aggregate.AggregateReporter) + require.Equal(queryId, result.Aggregate.QueryId) + require.Equal(uint64(1000), result.Aggregate.ReporterPower) + require.Equal(uint64(6), result.Aggregate.Height) + + //--------------------------------------------------------------------------- + // Height 5 - Delwood proposes a dispute from bond + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(7) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + rickyReporterStake, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, rickyAccAddr) + require.NoError(err) + + report := oracletypes.MicroReport{ + Reporter: rickyAccAddr.String(), + Power: rickyReporterStake.Quo(layertypes.PowerReduction).Uint64(), + QueryId: queryId, + Value: testutil.EncodeValue(100_000), + Timestamp: s.Setup.Ctx.BlockTime(), + BlockNumber: uint64(4), + } + + msgProposeDispute := disputetypes.MsgProposeDispute{ + Creator: delwoodAccAddr.String(), + Report: &report, + DisputeCategory: disputetypes.Warning, + Fee: sdk.NewCoin(s.Setup.Denom, math.NewInt(10*1e6)), + PayFromBond: true, + } + + _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) + require.Error(err) +} + +// test precision loss throughout tip/report/dispute/claim process +// 2 validators anna and bob become reporters +// chris delegates and selects to anna +// chris tips between 1 loya and 1 trb to get matic/usd spot price +// bob reports matic/usd price inaccurately +// anna disputes bob's report +func (s *E2ETestSuite) TestOpenDisputePrecision() { + require := s.Require() + + // setup msgServers + msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) + require.NotNil(msgServerOracle) + msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) + require.NotNil(msgServerReporter) + msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) + require.NotNil(msgServerDispute) + msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) + require.NotNil(msgServerStaking) + + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(time.Now()) + _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + ctx := s.Setup.Ctx + + // create 2 validators with random stakes 1 trb to 200,001 trb + valAccAddrs, valAddrs, _, stakes := s.Setup.CreateValidatorsRandomStake(2) + annaAccAddr := valAccAddrs[0] + bobAccAddr := valAccAddrs[1] + annaValAddr := valAddrs[0] + // bobValAddr := valAddrs[1] + annaInitialStake := stakes[0] + bobInitialStake := stakes[1] + + _, err = s.Setup.App.EndBlocker(ctx) + require.NoError(err) + + // ________________________________________________________________________ + // Block 2 - anna and bob become reporters + // ________________________________________________________________________ + ctx = ctx.WithBlockHeight(2) + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(ctx) + require.NoError(err) + + // anna becomes a reporter + _, err = s.Setup.CreateReporter(ctx, annaAccAddr, reportertypes.DefaultMinCommissionRate, math.NewInt(1*1e6)) + require.NoError(err) + // verify anna's reporter power + annaReporterStake, err := s.Setup.Reporterkeeper.ReporterStake(ctx, annaAccAddr) + require.NoError(err) + require.Equal(math.NewInt(annaInitialStake).String(), annaReporterStake.String()) + + // bob becomes a reporter + _, err = s.Setup.CreateReporter(ctx, bobAccAddr, reportertypes.DefaultMinCommissionRate, math.NewInt(1*1e6)) + require.NoError(err) + // verify bobs reporter power + bobReporterStake, err := s.Setup.Reporterkeeper.ReporterStake(ctx, bobAccAddr) + require.NoError(err) + require.Equal(math.NewInt(bobInitialStake).String(), bobReporterStake.String()) + + _, err = s.Setup.App.EndBlocker(ctx) + require.NoError(err) + + // ________________________________________________________________________ + // Block 3 - chris delegates to anna and selects annas reporter + // ________________________________________________________________________ + ctx = ctx.WithBlockHeight(3) + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(ctx) + require.NoError(err) + + // chris has 250k trb + chrisAccAddr, err := s.Setup.CreateFundedAccount(250_000) + require.NoError(err) + + // chris delegates a random amount of trb to annas validator, selects the same amount to annas reporter + // amount is between 1 trb and 200k trb + randomAmountLoya := rand.Int63n(200_000*1e6) + 1*1e6 + s.Setup.DelegateAndSelect(msgServerStaking, msgServerReporter, math.NewInt(randomAmountLoya), chrisAccAddr, annaValAddr, annaAccAddr) + + _, err = s.Setup.App.EndBlocker(ctx) + require.NoError(err) + + // ________________________________________________________________________ + // Block 4 - chris tips small amount of trb to get matic/usd spot price + // ________________________________________________________________________ + ctx = ctx.WithBlockHeight(4) + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(ctx) + require.NoError(err) + + // check on delegation from chris to anna validator + chrisDelegation, err := s.Setup.Stakingkeeper.Delegation(ctx, chrisAccAddr, annaValAddr) + require.NoError(err) + require.Equal(randomAmountLoya, chrisDelegation.GetShares().TruncateInt64()) + // check on selection from chris to anna reporter + annaReporterStake, err = s.Setup.Reporterkeeper.ReporterStake(ctx, annaAccAddr) + require.NoError(err) + expectedAnnaPower := math.NewInt(randomAmountLoya).Add(math.NewInt(annaInitialStake)) + require.Equal(expectedAnnaPower.String(), annaReporterStake.String()) + + // chris tips random fraction of trb to get matic/usd spot price + // tip is between 1 loya and 1 trb + randomTipAmount := math.NewInt(rand.Int63n(1*1e6) + 1) + maticQueryData := s.Setup.CreateSpotPriceTip(ctx, chrisAccAddr, `["matic","usd"]`, randomTipAmount) + + _, err = s.Setup.App.EndBlocker(ctx) + require.NoError(err) + + // ________________________________________________________________________ + // Block 5 - bob reports a bad matic/usd price + // ________________________________________________________________________ + ctx = ctx.WithBlockHeight(5) + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(ctx) + require.NoError(err) + + // check on tip + maticQueryId := utils.QueryIDFromData(maticQueryData) + maticTip, err := s.Setup.Oraclekeeper.GetQueryTip(ctx, maticQueryId) + require.NoError(err) + // 2% of tip is burned + burn := randomTipAmount.Mul(math.NewInt(2)).Quo(math.NewInt(100)) + expectedTip := randomTipAmount.Sub(burn) + require.Equal(expectedTip.String(), maticTip.String()) + + // bob reports 100 as matic/usd spot price + bobReportValue := testutil.EncodeValue(100) + s.Setup.Report(ctx, bobAccAddr, maticQueryData, bobReportValue) + + _, err = s.Setup.App.EndBlocker(ctx) + require.NoError(err) + + // ________________________________________________________________________ + // Block 6 - last block to report matic/usd, check on query in collections + // ________________________________________________________________________ + ctx = ctx.WithBlockHeight(6) + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(ctx) + require.NoError(err) + + // check on matic/usd query + query, err := s.Setup.Oraclekeeper.CurrentQuery(ctx, maticQueryId) + require.NoError(err) + require.Equal(query.QueryData, maticQueryData) + require.Equal(query.Amount, expectedTip) + require.Equal(query.HasRevealedReports, true) + require.Equal(query.CycleList, false) + require.Equal(query.RegistrySpecBlockWindow, uint64(2)) + require.Equal(query.Expiration, uint64(6)) + + _, err = s.Setup.App.EndBlocker(ctx) + require.NoError(err) + + // ________________________________________________________________________ + // Block 7 - report gets aggregated, anna opens dispute + // ________________________________________________________________________ + ctx = ctx.WithBlockHeight(7) + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(ctx) + require.NoError(err) + + // query should no longer be in query collections because it got aggregated + query, err = s.Setup.Oraclekeeper.Query.Get(ctx, collections.Join(maticQueryId, uint64(2))) + require.ErrorContains(err, "not found") + + // get microreport to submit in dispute + oracleQuerier := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) + report, err := oracleQuerier.GetReportsbyQid(ctx, &oracletypes.QueryGetReportsbyQidRequest{ + QueryId: hex.EncodeToString(maticQueryId), + }) + require.NoError(err) + + // for a warning dispute, 1% of the report's power is the dispute fee (or 1 trb if 1% is less than 1 trb) + fmt.Println("report power: ", report.MicroReports[0].Power) + stake := layertypes.PowerReduction.MulRaw(int64(report.MicroReports[0].Power)) + disputeFeeTotal := stake.Mul(math.NewInt(1)).Quo(math.NewInt(100)) + if disputeFeeTotal.LT(layertypes.OnePercent) { + disputeFeeTotal = layertypes.OnePercent + } + fmt.Println("dispute fee total: ", disputeFeeTotal) + // anna opens dispute + disputeStartTime := ctx.BlockTime() + s.Setup.OpenDispute(ctx, annaAccAddr, report.MicroReports[0], disputetypes.Warning, disputeFeeTotal, true) + + _, err = s.Setup.App.EndBlocker(ctx) + require.NoError(err) + + // ________________________________________________________________________ + // Block 8 - check on dispute, everybody votes + // _________________________________________________________________________ + ctx = ctx.WithBlockHeight(8) + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(ctx) + require.NoError(err) + + // check on dispute + disputes, err := s.Setup.Disputekeeper.GetOpenDisputes(ctx) + require.NoError(err) + require.Equal(len(disputes), 1) + dispute, err := s.Setup.Disputekeeper.Disputes.Get(ctx, disputes[0]) + require.NoError(err) + require.Equal(dispute.DisputeId, disputes[0]) + fmt.Println("dispute status: ", dispute.DisputeStatus) + require.Equal(dispute.DisputeStatus, disputetypes.Voting) + require.Equal(dispute.DisputeCategory, disputetypes.Warning) + require.Equal(dispute.FeeTotal, disputeFeeTotal) + // disputeFee should be 95% of fee total, 5% is burned + disputeFee := disputeFeeTotal.Mul(math.NewInt(95)).Quo(math.NewInt(100)) + require.Equal(dispute.DisputeFee, disputeFee) + disputeFeeBurn := disputeFeeTotal.Sub(disputeFee) + require.Equal(dispute.BurnAmount, disputeFeeBurn) + require.Equal(dispute.BlockNumber, uint64(7)) + // dispute ends in 3 days if fully paid + require.Equal(dispute.DisputeEndTime, disputeStartTime.Add(3*time.Hour*24)) + require.Equal(dispute.DisputeStartTime, disputeStartTime) + require.Equal(dispute.DisputeRound, uint64(1)) + require.Equal(dispute.SlashAmount, disputeFeeTotal) + require.Equal(dispute.InitialEvidence, report.MicroReports[0]) + + _, err = s.Setup.App.EndBlocker(ctx) + require.NoError(err) +} + +func (s *E2ETestSuite) TestDisputes2() { + require := s.Require() + msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) + require.NotNil(msgServerOracle) + msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) + require.NotNil(msgServerReporter) + msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) + require.NotNil(msgServerDispute) + msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) + require.NotNil(msgServerStaking) + + //--------------------------------------------------------------------------- + // Height 0 - create 3 validators and 3 reporters + //--------------------------------------------------------------------------- + _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + valsAcctAddrs, valsValAddrs, _ := s.Setup.CreateValidators(3) + require.NotNil(valsAcctAddrs) + repsAccs := valsAcctAddrs + for _, val := range valsValAddrs { + err := s.Setup.Bridgekeeper.SetEVMAddressByOperator(s.Setup.Ctx, val.String(), []byte("not real")) + s.NoError(err) + } + badReporter := repsAccs[0] + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + s.NoError(s.Setup.Reporterkeeper.Reporters.Set(s.Setup.Ctx, badReporter, reportertypes.NewReporter(reportertypes.DefaultMinCommissionRate, math.OneInt()))) + s.NoError(s.Setup.Reporterkeeper.Selectors.Set(s.Setup.Ctx, badReporter, reportertypes.NewSelection(badReporter, 1))) + s.NoError(s.Setup.Reporterkeeper.Reporters.Set(s.Setup.Ctx, repsAccs[1], reportertypes.NewReporter(reportertypes.DefaultMinCommissionRate, math.OneInt()))) + s.NoError(s.Setup.Reporterkeeper.Selectors.Set(s.Setup.Ctx, repsAccs[1], reportertypes.NewSelection(repsAccs[1], 1))) + s.NoError(s.Setup.Reporterkeeper.Reporters.Set(s.Setup.Ctx, repsAccs[2], reportertypes.NewReporter(reportertypes.DefaultMinCommissionRate, math.OneInt()))) + s.NoError(s.Setup.Reporterkeeper.Selectors.Set(s.Setup.Ctx, repsAccs[2], reportertypes.NewSelection(repsAccs[2], 1))) + // mapping to track reporter delegation balance + // reporterToBalanceMap := make(map[string]math.Int) + // for _, acc := range repsAccs { + // rkDelegation, err := s.Setup.Reporterkeeper.Delegators.Get(s.Setup.Ctx, acc) + // require.NoError(err) + // reporterToBalanceMap[acc.String()] = rkDelegation.Amount + // } + + //--------------------------------------------------------------------------- + // Height 1 - delegate 500 trb to validator 0 and bad reporter + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(1) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + pk := ed25519.GenPrivKey() + delAcc := s.Setup.ConvertToAccAddress([]ed25519.PrivKey{*pk}) + delAccAddr := delAcc[0] + initCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(500*1e6)) + s.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) + s.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, delAccAddr, sdk.NewCoins(initCoins))) + + // delegate to validator 0 + s.Setup.MintTokens(delAccAddr, math.NewInt(500*1e6)) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, &stakingtypes.MsgDelegate{DelegatorAddress: delAccAddr.String(), ValidatorAddress: valsValAddrs[0].String(), Amount: sdk.NewCoin(s.Setup.Denom, math.NewInt(500*1e6))}) + require.NoError(err) + s.NoError(s.Setup.Reporterkeeper.Selectors.Set(s.Setup.Ctx, delAccAddr, reportertypes.NewSelection(badReporter, 1))) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + val, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, valsValAddrs[0]) + require.NoError(err) + repTokens, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, badReporter) + require.NoError(err) + require.Equal(repTokens, val.Tokens) + + //--------------------------------------------------------------------------- + // Height 2 - direct reveal for cycle list + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(2) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) + require.NoError(err) + + // get new cycle list query data + cycleListQuery, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) + require.NoError(err) + queryId := utils.QueryIDFromData(cycleListQuery) + // create reveal message + value := testutil.EncodeValue(10_000) + require.NoError(err) + reveal := oracletypes.MsgSubmitValue{ + Creator: repsAccs[0].String(), + QueryData: cycleListQuery, + Value: value, + } + reportBlock := s.Setup.Ctx.BlockHeight() + // send reveal message + revealResponse, err := msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) + require.NoError(err) + require.NotNil(revealResponse) + revealTime := s.Setup.Ctx.BlockTime() + // advance time and block height to expire the query and aggregate report + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(7 * time.Second)) + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 3 - open warning, pay from bond from reporter 1 + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(3) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + // todo: is there a getter for this ? + // get microreport for dispute + report := oracletypes.MicroReport{ + Reporter: repsAccs[0].String(), + Power: repTokens.Quo(sdk.DefaultPowerReduction).Uint64(), + QueryId: queryId, + Value: value, + Timestamp: revealTime, + BlockNumber: uint64(reportBlock), + } + + // disputedBal := disputedRep.TotalTokens + // onePercent := disputedBal.Mul(math.NewInt(1)).Quo(math.NewInt(100)) + fee, err := s.Setup.Disputekeeper.GetDisputeFee(s.Setup.Ctx, report, disputetypes.Warning) + require.NoError(err) + disputeFee := sdk.NewCoin(s.Setup.Denom, fee) // warning should be 1% of bonded tokens + + // create msg for propose dispute tx + msgProposeDispute := disputetypes.MsgProposeDispute{ + Creator: repsAccs[0].String(), + Report: &report, + DisputeCategory: disputetypes.Warning, + Fee: disputeFee, + PayFromBond: true, + } + + // send propose dispute tx + _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) + require.NoError(err) + + burnAmount := disputeFee.Amount.MulRaw(1).QuoRaw(20) + disputes, err := s.Setup.Disputekeeper.GetOpenDisputes(s.Setup.Ctx) + require.NoError(err) + require.NotNil(disputes) + // dispute is created correctly + dispute, err := s.Setup.Disputekeeper.Disputes.Get(s.Setup.Ctx, 1) + require.NoError(err) + require.Equal(dispute.DisputeId, uint64(1)) + require.Equal(dispute.DisputeStatus, disputetypes.Voting) + require.Equal(dispute.DisputeCategory, disputetypes.Warning) + require.Equal(dispute.DisputeFee, disputeFee.Amount.Sub(burnAmount)) + feepayer, err := s.Setup.Disputekeeper.DisputeFeePayer.Get(s.Setup.Ctx, collections.Join(uint64(1), repsAccs[0].Bytes())) + require.NoError(err) + require.Equal(feepayer.Amount, disputeFee.Amount) + require.Equal(feepayer.FromBond, true) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 4 - disputed reporter reports after calling unjail + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(4) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + disputedRep, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) + require.NoError(err) + require.Equal(disputedRep.Jailed, true) + + // disputed reporter cant report yet + cycleListQuery, err = s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) + require.NoError(err) + value = testutil.EncodeValue(10_000) + require.NoError(err) + reveal = oracletypes.MsgSubmitValue{ + Creator: repsAccs[0].String(), + QueryData: cycleListQuery, + Value: value, + } + _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) + require.Error(err) + + // disputed reporter can report after calling unjail function + msgUnjail := reportertypes.MsgUnjailReporter{ + ReporterAddress: repsAccs[0].String(), + } + _, err = msgServerReporter.UnjailReporter(s.Setup.Ctx, &msgUnjail) + require.NoError(err) + disputedRep, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) + require.NoError(err) + require.Equal(disputedRep.Jailed, false) + // send reveal message + revealResponse, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) + require.NoError(err) + require.NotNil(revealResponse) + revealTime = s.Setup.Ctx.BlockTime() + revealBlock := s.Setup.Ctx.BlockHeight() + + // give disputer tokens to pay for next disputes not from bond + beforemint := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, repsAccs[1], s.Setup.Denom) + initCoins = sdk.NewCoin(s.Setup.Denom, math.NewInt(10_000*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) + // send from module to account + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, repsAccs[1], sdk.NewCoins(initCoins))) + require.Equal(beforemint.Add(initCoins), s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, repsAccs[1], s.Setup.Denom)) + + // advance time and block height to expire the query and aggregate report + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(7 * time.Second)) + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + // disputer, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[1]) + // require.NoError(err) + disputedRep, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 5 - open warning, pay from not bond from reporter 1 + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(5) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + report.Power = repTokens.Quo(sdk.DefaultPowerReduction).Uint64() + fee, err = s.Setup.Disputekeeper.GetDisputeFee(s.Setup.Ctx, report, disputetypes.Warning) + require.NoError(err) + disputeFee = sdk.NewCoin(s.Setup.Denom, fee) // warning should be 1% of bonded tokens + + // get microreport for dispute + report = oracletypes.MicroReport{ + Reporter: repsAccs[0].String(), + Power: repTokens.Quo(sdk.DefaultPowerReduction).Uint64(), + QueryId: queryId, + Value: value, + Timestamp: revealTime, + BlockNumber: uint64(revealBlock), + } + + // create msg for propose dispute tx + msgProposeDispute = disputetypes.MsgProposeDispute{ + Creator: repsAccs[1].String(), + Report: &report, + DisputeCategory: disputetypes.Warning, + Fee: disputeFee, + PayFromBond: false, + } + + // send propose dispute tx + _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) + require.NoError(err) + + burnAmount = disputeFee.Amount.MulRaw(1).QuoRaw(20) + disputes, err = s.Setup.Disputekeeper.GetOpenDisputes(s.Setup.Ctx) + require.NoError(err) + require.NotNil(disputes) + // dispute is created correctly + dispute, err = s.Setup.Disputekeeper.Disputes.Get(s.Setup.Ctx, 2) + require.NoError(err) + require.Equal(dispute.DisputeId, uint64(2)) + require.Equal(dispute.DisputeStatus, disputetypes.Voting) + require.Equal(dispute.DisputeCategory, disputetypes.Warning) + require.Equal(dispute.DisputeFee, disputeFee.Amount.Sub(burnAmount)) + feepayer, err = s.Setup.Disputekeeper.DisputeFeePayer.Get(s.Setup.Ctx, collections.Join(uint64(2), repsAccs[1].Bytes())) + require.NoError(err) + require.Equal(feepayer.Amount, disputeFee.Amount) + require.Equal(feepayer.FromBond, false) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 6 - dispute is resolved, direct reveal again + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(6) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + disputedRep, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) + require.NoError(err) + require.Equal(disputedRep.Jailed, true) + + // disputed reporter cant report yet + cycleListQuery, err = s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) + require.NoError(err) + value = testutil.EncodeValue(10_000) + require.NoError(err) + queryId = utils.QueryIDFromData(cycleListQuery) + reveal = oracletypes.MsgSubmitValue{ + Creator: repsAccs[0].String(), + QueryData: cycleListQuery, + Value: value, + } + _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) + require.Error(err) + + // disputed reporter can report after calling unjail function + msgUnjail = reportertypes.MsgUnjailReporter{ + ReporterAddress: repsAccs[0].String(), + } + _, err = msgServerReporter.UnjailReporter(s.Setup.Ctx, &msgUnjail) + require.NoError(err) + disputedRep, err = s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[0]) + require.NoError(err) + require.Equal(disputedRep.Jailed, false) + // send reveal message + revealResponse, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal) + require.NoError(err) + require.NotNil(revealResponse) + revealTime = s.Setup.Ctx.BlockTime() + revealBlock = s.Setup.Ctx.BlockHeight() + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 7 - open minor dispute, pay from bond from reporter 1 + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(7) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + balBeforeDispute := repTokens + fivePercent := balBeforeDispute.Mul(math.NewInt(5)).Quo(math.NewInt(100)) + disputeFee = sdk.NewCoin(s.Setup.Denom, fivePercent) + + report = oracletypes.MicroReport{ + Reporter: repsAccs[0].String(), + Power: repTokens.Quo(sdk.DefaultPowerReduction).Uint64(), + QueryId: queryId, + Value: value, + Timestamp: revealTime, + BlockNumber: uint64(revealBlock), + } + + // create msg for propose dispute tx + msgProposeDispute = disputetypes.MsgProposeDispute{ + Creator: repsAccs[1].String(), + Report: &report, + DisputeCategory: disputetypes.Minor, + Fee: disputeFee, + PayFromBond: true, + } + + // send propose dispute tx + _, err = msgServerDispute.ProposeDispute(s.Setup.Ctx, &msgProposeDispute) + require.NoError(err) + _ = s.Setup.Ctx.BlockTime() + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 8 - vote on minor dispute -- reaches quorum + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(8) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + // vote from disputer + msgVote := disputetypes.MsgVote{ + Voter: repsAccs[0].String(), + Id: dispute.DisputeId, + Vote: disputetypes.VoteEnum_VOTE_SUPPORT, + } + fmt.Println("Dispute Id on rep[0] vote: ", dispute.DisputeId) + voteResponse, err := msgServerDispute.Vote(s.Setup.Ctx, &msgVote) + require.NoError(err) + require.NotNil(voteResponse) + + // vote from disputed reporter + msgVote = disputetypes.MsgVote{ + Voter: repsAccs[1].String(), + Id: dispute.DisputeId, + Vote: disputetypes.VoteEnum_VOTE_SUPPORT, + } + + voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVote) + require.NoError(err) + require.NotNil(voteResponse) + + // vote from third reporter + // thirdReporter, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, repsAccs[2]) + require.NoError(err) + msgVote = disputetypes.MsgVote{ + Voter: repsAccs[2].String(), + Id: dispute.DisputeId, + Vote: disputetypes.VoteEnum_VOTE_SUPPORT, + } + voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVote) + require.NoError(err) + require.NotNil(voteResponse) + + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) + + // vote from team + // fmt.Println(disputetypes.TeamAddress) + // msgVote = disputetypes.MsgVote{ + // Voter: sdk.MustAccAddressFromBech32(disputetypes.TeamAddress).String(), + // Id: dispute.DisputeId, + // Vote: disputetypes.VoteEnum_VOTE_SUPPORT, + // } + // voteResponse, err = msgServerDispute.Vote(s.Setup.Ctx, &msgVote) + // require.NoError(err) + // require.NotNil(voteResponse) + + totalTips, err := s.Setup.Disputekeeper.BlockInfo.Get(s.Setup.Ctx, dispute.HashId) + require.NoError(err) + fmt.Println("totalTips: ", totalTips) + + totalReporterPower, err := s.Setup.Reporterkeeper.TotalReporterPower(s.Setup.Ctx) + require.NoError(err) + fmt.Println("total reporter power: ", totalReporterPower.Quo(sdk.DefaultPowerReduction)) + + totalFreeFloatingTokens := s.Setup.Disputekeeper.GetTotalSupply(s.Setup.Ctx) + fmt.Println("total Free Floating Tokens: ", totalFreeFloatingTokens) + owners, err := s.Setup.Bankkeeper.DenomOwners(s.Setup.Ctx, &banktypes.QueryDenomOwnersRequest{Denom: s.Setup.Denom}) + require.NoError(err) + sumFromDenomOwners := math.ZeroInt() + for _, owner := range owners.DenomOwners { + fmt.Println("owner: ", owner) + sumFromDenomOwners = sumFromDenomOwners.Add(owner.Balance.Amount) + } + fmt.Println("sumFromDenomOwners: ", sumFromDenomOwners) + + // print all reporter sdk.AccAddr + for _, rep := range repsAccs { + fmt.Println("rep: ", rep.String()) + } + for _, val := range valsAcctAddrs { + fmt.Println("val: ", val.String()) + } + fmt.Println("delegator acc addr: ", delAccAddr.String()) + + // print tbr module account address + tbrModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(minttypes.TimeBasedRewards) // yes + fmt.Println("tbr module account: ", tbrModuleAccount.String()) + + disputeModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(disputetypes.ModuleName) // yes + fmt.Println("dispute module account: ", disputeModuleAccount.String()) + + authModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(authtypes.ModuleName) // + fmt.Println("auth module account: ", authModuleAccount.String()) + + reporterModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(reportertypes.ModuleName) // yes + fmt.Println("reporter module account: ", reporterModuleAccount.String()) + + registryModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(registrytypes.ModuleName) // no + fmt.Println("registry module account: ", registryModuleAccount.String()) + + reporterTipsEscrowAccount := s.Setup.Accountkeeper.GetModuleAddress(reportertypes.TipsEscrowPool) // no + fmt.Println("reporter tips escrow account: ", reporterTipsEscrowAccount.String()) + + oracleModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(oracletypes.ModuleName) // no + fmt.Println("oracle module account: ", oracleModuleAccount.String()) + + stakingModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(stakingtypes.ModuleName) // + fmt.Println("staking module account: ", stakingModuleAccount.String()) + + //--------------------------------------------------------------------------- + // Height 9 - resolve dispute, direct reveal again + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(9) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + //--------------------------------------------------------------------------- + // Height 10 - open minor dispute, pay from not bond from reporter 1 + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(10) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + //--------------------------------------------------------------------------- + // Height 11 - vote on minor dispute + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(11) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + //--------------------------------------------------------------------------- + // Height 12 - resolve dispute, direct reveal again + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(12) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + //--------------------------------------------------------------------------- + // Height 13 - open major dispute, pay from bond from reporter 1 + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(13) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + //--------------------------------------------------------------------------- + // Height 14 - vote on major dispute + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(14) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + //--------------------------------------------------------------------------- + // Height 15 - resolve dispute, direct reveal again + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(15) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + //--------------------------------------------------------------------------- + // Height 16 - open major dispute, pay from not bond from reporter 1 + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(16) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + //--------------------------------------------------------------------------- + // Height 17 - vote on major dispute + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(17) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) + + //--------------------------------------------------------------------------- + // Height 18 - resolve dispute, direct reveal again + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(18) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) +} diff --git a/tests/e2e/reporting_test.go b/tests/e2e/reporting_test.go new file mode 100644 index 00000000..37e078ba --- /dev/null +++ b/tests/e2e/reporting_test.go @@ -0,0 +1,793 @@ +package e2e_test + +import ( + "encoding/hex" + "time" + + "github.com/tellor-io/layer/testutil" + utils "github.com/tellor-io/layer/utils" + disputekeeper "github.com/tellor-io/layer/x/dispute/keeper" + oraclekeeper "github.com/tellor-io/layer/x/oracle/keeper" + oracletypes "github.com/tellor-io/layer/x/oracle/types" + reporterkeeper "github.com/tellor-io/layer/x/reporter/keeper" + reportertypes "github.com/tellor-io/layer/x/reporter/types" + + collections "cosmossdk.io/collections" + "cosmossdk.io/math" + + secp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +// func (s *E2ETestSuite) TestBasicReporting() { +// require := s.Require() +// minter, err := s.Setup.Mintkeeper.Minter.Get(s.Setup.Ctx) +// require.NoError(err) +// minter.Initialized = true +// require.NoError(s.Setup.Mintkeeper.Minter.Set(s.Setup.Ctx, minter)) +// msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) + +// //--------------------------------------------------------------------------- +// // Height 0 +// //--------------------------------------------------------------------------- +// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) +// require.NoError(err) + +// // create a validator +// valAccount := simtestutil.CreateIncrementalAccounts(1) +// // mint 5000*1e8 tokens for validator +// initCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(5000*1e8)) +// require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) +// require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, valAccount[0], sdk.NewCoins(initCoins))) +// // get val address +// valAccountValAddrs := simtestutil.ConvertAddrsToValAddrs(valAccount) +// // create pub key for validator +// pubKey := simtestutil.CreateTestPubKeys(1) +// // tell keepers about the new validator +// s.Setup.Accountkeeper.NewAccountWithAddress(s.Setup.Ctx, valAccount[0]) +// msgCreateValidaotr, err := stakingtypes.NewMsgCreateValidator( +// valAccountValAddrs[0].String(), +// pubKey[0], +// sdk.NewCoin(s.Setup.Denom, math.NewInt(4000*1e8)), +// stakingtypes.Description{Moniker: "created validator"}, +// stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(0, 0), math.LegacyNewDecWithPrec(3, 1), math.LegacyNewDecWithPrec(1, 1)), +// math.OneInt(), +// ) +// require.NoError(err) +// _, err = msgServerStaking.CreateValidator(s.Setup.Ctx, msgCreateValidaotr) +// require.NoError(err) +// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) +// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) +// validator, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, valAccountValAddrs[0]) +// require.NoError(err) + +// _, err = s.Setup.Stakingkeeper.EndBlocker(s.Setup.Ctx) +// s.NoError(err) + +// type Delegator struct { +// delegatorAddress sdk.AccAddress +// validator stakingtypes.Validator +// tokenAmount math.Int +// } +// pk := ed25519.GenPrivKey() +// reporterAccount := sdk.AccAddress(pk.PubKey().Address()) +// // mint 5000*1e6 tokens for reporter +// s.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(initCoins))) +// s.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, reporterAccount, sdk.NewCoins(initCoins))) +// // delegate to validator so reporter can delegate to themselves +// reporterDelToVal := Delegator{delegatorAddress: reporterAccount, validator: validator, tokenAmount: math.NewInt(4000 * 1e6)} +// msgDelegate := stakingtypes.NewMsgDelegate(reporterAccount.String(), validator.OperatorAddress, sdk.NewCoin(s.Setup.Denom, math.NewInt(4000*1e6))) +// _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) +// require.NoError(err) +// // set up reporter module msgServer +// msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) +// require.NotNil(msgServerReporter) +// // define createReporterMsg params +// reporterAddress := reporterDelToVal.delegatorAddress.String() + +// createReporterMsg := reportertypes.MsgCreateReporter{ReporterAddress: reporterAddress, CommissionRate: reportertypes.DefaultMinCommissionRate, MinTokensRequired: reportertypes.DefaultMinTrb} +// // send createreporter msg +// _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &createReporterMsg) +// require.NoError(err) +// // check that reporter was created in Reporters collections +// reporter, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, reporterAccount) +// require.NoError(err) +// s.NoError(s.Setup.Reporterkeeper.Reporters.Set(s.Setup.Ctx, reporterAccount, reportertypes.NewReporter(reportertypes.DefaultMinCommissionRate, math.OneInt()))) +// s.NoError(s.Setup.Reporterkeeper.Selectors.Set(s.Setup.Ctx, reporterAccount, reportertypes.NewSelection(reporterAccount, 1))) +// reporterTokens, err := s.Setup.Reporterkeeper.ReporterStake(s.Setup.Ctx, reporterAccount) +// require.NoError(err) +// require.Equal(reporterTokens, math.NewInt(4000*1e6)) +// require.Equal(reporter.Jailed, false) +// // check on reporter in Delegators collections +// rkDelegation, err := s.Setup.Reporterkeeper.Selectors.Get(s.Setup.Ctx, reporterAccount) +// require.NoError(err) +// require.Equal(rkDelegation.Reporter, reporterAccount.Bytes()) +// // check on reporter/validator delegation +// valBz, err := s.Setup.Stakingkeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) +// require.NoError(err) +// skDelegation, err := s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount, valBz) +// require.NoError(err) +// require.Equal(skDelegation.GetDelegatorAddr(), reporterAccount.String()) +// require.Equal(skDelegation.GetValidatorAddr(), validator.GetOperator()) + +// // setup oracle msgServer +// msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) +// require.NotNil(msgServerOracle) + +// // case 1: commit/reveal for cycle list +// //--------------------------------------------------------------------------- +// // Height 1 +// //--------------------------------------------------------------------------- +// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) +// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) +// require.NoError(err) + +// // check that no time based rewards have been minted yet +// tbrModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(minttypes.TimeBasedRewards) +// tbrModuleAccountBalance := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) +// require.Equal(int64(0), tbrModuleAccountBalance.Amount.Int64()) + +// // begin report +// cycleListEth, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) +// require.NoError(err) +// // create hash for commit +// salt1, err := oracleutils.Salt(32) +// require.NoError(err) +// value1 := testutil.EncodeValue(4500) +// hash1 := oracleutils.CalculateCommitment(value1, salt1) +// // create commit1 msg +// commit1 := oracletypes.MsgCommitReport{ +// Creator: reporterAccount.String(), +// QueryData: cycleListEth, +// Hash: hash1, +// } +// // send commit tx +// commitResponse1, err := msgServerOracle.CommitReport(s.Setup.Ctx, &commit1) +// require.NoError(err) +// require.NotNil(commitResponse1) +// commitHeight := s.Setup.Ctx.BlockHeight() +// require.Equal(int64(1), commitHeight) + +// _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) +// require.NoError(err) +// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) + +// //--------------------------------------------------------------------------- +// // Height 2 +// //--------------------------------------------------------------------------- +// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(commitHeight + 1) +// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 14)) +// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) +// require.NoError(err) +// _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) +// require.NoError(err) + +// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(commitHeight + 2) +// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) +// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) +// require.NoError(err) + +// // check that 1 second worth of tbr has been minted +// // expected tbr = (daily mint rate * time elapsed) / (# of ms in a day) +// expectedBlockProvision := int64(146940000 * (15 * time.Second) / (24 * 60 * 60 * 1000)) +// expectedTbr := sdk.NewCoin(s.Setup.Denom, math.NewInt((expectedBlockProvision)).MulRaw(75).QuoRaw(100).Quo(sdk.DefaultPowerReduction)) +// tbrModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) +// require.GreaterOrEqual(tbrModuleAccountBalance.Amount.Int64(), expectedTbr.Amount.Int64()-1) +// require.LessOrEqual(tbrModuleAccountBalance.Amount.Int64(), expectedTbr.Amount.Int64()+1) +// // check that the cycle list has rotated +// cycleListBtc, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) +// require.NotEqual(cycleListEth, cycleListBtc) +// require.NoError(err) + +// // create reveal msg +// require.NoError(err) +// reveal1 := oracletypes.MsgSubmitValue{ +// Creator: reporterAccount.String(), +// QueryData: cycleListEth, +// Value: value1, +// Salt: salt1, +// } +// // send reveal tx +// revealResponse1, err := msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal1) +// require.NoError(err) +// require.NotNil(revealResponse1) +// // advance time and block height to expire the query and aggregate report +// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(21 * time.Second)) +// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) +// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) + +// // get queryId for GetAggregatedReportRequest +// queryIdEth := utils.QueryIDFromData(cycleListEth) + +// // check that aggregated report is stored +// getAggReportRequest1 := oracletypes.QueryGetCurrentAggregateReportRequest{ +// QueryId: hex.EncodeToString(queryIdEth), +// } +// queryServer := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) +// result1, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest1) +// require.NoError(err) +// require.Equal(result1.Aggregate.Height, uint64(2)) +// require.Equal(result1.Aggregate.AggregateReportIndex, uint64(0)) +// require.Equal(result1.Aggregate.AggregateValue, testutil.EncodeValue(4500)) +// require.Equal(result1.Aggregate.AggregateReporter, reporterAccount.String()) +// require.Equal(result1.Aggregate.QueryId, queryIdEth) +// require.Equal(uint64(4000), result1.Aggregate.ReporterPower) +// // check that tbr is no longer in timeBasedRewards module acct +// tbrModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) +// require.Equal(int64(0), tbrModuleAccountBalance.Amount.Int64()) +// // check that tbr was sent to reporter module account +// reporterModuleAccount := s.Setup.Accountkeeper.GetModuleAddress(reportertypes.TipsEscrowPool) +// reporterModuleAccountBalance := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterModuleAccount, s.Setup.Denom) +// require.Equal(expectedTbr, reporterModuleAccountBalance) +// // check reporters outstaning rewards +// outstandingRewards, err := s.Setup.Reporterkeeper.SelectorTips.Get(s.Setup.Ctx, reporterAccount.Bytes()) +// require.NoError(err) +// require.Equal(outstandingRewards.TruncateInt(), expectedTbr.Amount) +// // withdraw tbr +// rewards, err := msgServerReporter.WithdrawTip(s.Setup.Ctx, &reportertypes.MsgWithdrawTip{SelectorAddress: reporterAddress, ValidatorAddress: validator.OperatorAddress}) +// require.NoError(err) +// tbrEarned := outstandingRewards +// // check that there is only one reward to claim +// require.NotNil(rewards) +// // check that reporter module account balance is now empty +// reporterModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterModuleAccount, s.Setup.Denom) +// require.Equal(int64(0), reporterModuleAccountBalance.Amount.Int64()) +// // check that reporter now has more bonded tokens + +// // case 2: direct reveal for cycle list +// //--------------------------------------------------------------------------- +// // Height 3 +// //--------------------------------------------------------------------------- +// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) +// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second)) +// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) +// require.NoError(err) + +// // check that 8 sec of tbr has been minted +// tbrModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) +// expectedBlockProvision = int64(146940000 * (22 * time.Second) / (24 * 60 * 60 * 1000)) +// expectedTbr = sdk.NewCoin(s.Setup.Denom, (math.NewInt((expectedBlockProvision)).MulRaw(75).QuoRaw(100).Quo(sdk.DefaultPowerReduction)).Add(math.NewInt(1))) + +// require.Equal(expectedTbr, tbrModuleAccountBalance) + +// // get new cycle list query data +// cycleListTrb, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) +// require.NoError(err) +// require.NotEqual(cycleListEth, cycleListTrb) +// require.NotEqual(cycleListBtc, cycleListTrb) +// // create reveal message +// value2 := testutil.EncodeValue(100_000) +// require.NoError(err) +// reveal2 := oracletypes.MsgSubmitValue{ +// Creator: reporterAccount.String(), +// QueryData: cycleListTrb, +// Value: value2, +// } +// // send reveal message +// revealResponse2, err := msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal2) +// require.NoError(err) +// require.NotNil(revealResponse2) +// // advance time and block height to expire the query and aggregate report +// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(21 * time.Second)) +// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) +// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) + +// // get queryId for GetAggregatedReportRequest +// queryIdTrb := utils.QueryIDFromData(cycleListTrb) + +// // create get aggregated report query +// getAggReportRequest2 := oracletypes.QueryGetCurrentAggregateReportRequest{ +// QueryId: hex.EncodeToString(queryIdTrb), +// } +// // check that aggregated report is stored correctly +// result2, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest2) +// require.NoError(err) +// require.Equal(uint64(0), result2.Aggregate.AggregateReportIndex) +// require.Equal(testutil.EncodeValue(100_000), result2.Aggregate.AggregateValue) +// require.Equal(reporterAccount.String(), result2.Aggregate.AggregateReporter) +// require.Equal(queryIdTrb, result2.Aggregate.QueryId) +// require.Equal(uint64(4000), result2.Aggregate.ReporterPower) +// require.Equal(uint64(3), result2.Aggregate.Height) +// // check that tbr is no longer in timeBasedRewards module acct +// tbrModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) +// require.Equal(int64(0), tbrModuleAccountBalance.Amount.Int64()) +// // check that tbr was sent to reporter module account +// reporterModuleAccount = s.Setup.Accountkeeper.GetModuleAddress(reportertypes.TipsEscrowPool) +// reporterModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterModuleAccount, s.Setup.Denom) +// require.Equal(expectedTbr, reporterModuleAccountBalance) + +// // check reporters outstaning rewards +// outstandingRewards, err = s.Setup.Reporterkeeper.SelectorTips.Get(s.Setup.Ctx, reporterAccount.Bytes()) +// require.NoError(err) +// require.Equal(outstandingRewards.TruncateInt(), expectedTbr.Amount) +// // withdraw tbr +// tbrEarned = tbrEarned.Add(outstandingRewards) +// rewards, err = msgServerReporter.WithdrawTip(s.Setup.Ctx, &reportertypes.MsgWithdrawTip{SelectorAddress: reporterAddress, ValidatorAddress: validator.OperatorAddress}) +// require.NoError(err) +// require.NotNil(rewards) +// // check that reporter module account balance is now empty +// reporterModuleAccountBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, reporterModuleAccount, s.Setup.Denom) +// require.Equal(int64(0), reporterModuleAccountBalance.Amount.Int64()) + +// // case 3: commit/reveal for tipped query +// //--------------------------------------------------------------------------- +// // Height 4 +// //--------------------------------------------------------------------------- +// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) +// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) +// require.NoError(err) + +// // get reporters shares +// deleBeforeReport, err := s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount.Bytes(), valBz) +// require.NoError(err) +// require.Equal(deleBeforeReport.GetShares(), math.LegacyNewDec(4000*1e6).Add(tbrEarned)) + +// // create tip msg +// balanceBeforetip := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tbrModuleAccount, s.Setup.Denom) +// tipAmount := sdk.NewCoin(s.Setup.Denom, math.NewInt(100)) +// msgTip := oracletypes.MsgTip{ +// Tipper: reporterAccount.String(), +// QueryData: cycleListEth, +// Amount: tipAmount, +// } +// // send tip tx +// tipRes, err := msgServerOracle.Tip(s.Setup.Ctx, &msgTip) +// require.NoError(err) +// require.NotNil(tipRes) + +// // check that tip is in oracle module account +// twoPercent := sdk.NewCoin(s.Setup.Denom, tipAmount.Amount.Mul(math.NewInt(2)).Quo(math.NewInt(100))) +// tipModuleAcct := s.Setup.Accountkeeper.GetModuleAddress(oracletypes.ModuleName) +// tipAcctBalance := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipModuleAcct, s.Setup.Denom) +// require.Equal(tipAcctBalance, tipAmount.Sub(twoPercent)) +// // create commit for tipped eth query +// salt1, err = oracleutils.Salt(32) +// require.NoError(err) +// value1 = testutil.EncodeValue(5000) +// hash1 = oracleutils.CalculateCommitment(value1, salt1) + +// queryId := utils.QueryIDFromData(cycleListEth) +// quertip, err := s.Setup.Oraclekeeper.GetQueryTip(s.Setup.Ctx, queryId) +// require.NoError(err) +// require.Equal(quertip, tipAmount.Amount.Sub(twoPercent.Amount)) + +// commit1 = oracletypes.MsgCommitReport{ +// Creator: reporterAccount.String(), +// QueryData: cycleListEth, +// Hash: hash1, +// } +// // send commit tx +// commitResponse1, err = msgServerOracle.CommitReport(s.Setup.Ctx, &commit1) +// require.NoError(err) +// require.NotNil(commitResponse1) +// commitHeight = s.Setup.Ctx.BlockHeight() +// require.Equal(int64(4), commitHeight) +// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) +// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) + +// //--------------------------------------------------------------------------- +// // Height 5 +// //--------------------------------------------------------------------------- +// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(commitHeight + 1) +// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) +// require.NoError(err) + +// // create reveal msg +// value1 = testutil.EncodeValue(5000) +// reveal1 = oracletypes.MsgSubmitValue{ +// Creator: reporterAccount.String(), +// QueryData: cycleListEth, +// Value: value1, +// Salt: salt1, +// } +// // send reveal tx +// revealResponse1, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &reveal1) +// require.NoError(err) +// require.NotNil(revealResponse1) + +// // advance time and block height to expire the query and aggregate report +// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(21 * time.Second)) +// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) +// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) + +// // create get aggreagted report query +// getAggReportRequest1 = oracletypes.QueryGetCurrentAggregateReportRequest{ +// QueryId: hex.EncodeToString(queryIdEth), +// } +// // check that the aggregated report is stored correctly +// result1, err = queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequest1) +// require.NoError(err) +// require.Equal(result1.Aggregate.AggregateReportIndex, uint64(0)) +// require.Equal(result1.Aggregate.AggregateValue, testutil.EncodeValue(5000)) +// require.Equal(result1.Aggregate.AggregateReporter, reporterAccount.String()) +// require.Equal(queryIdEth, result1.Aggregate.QueryId) +// require.Equal(uint64(4000), result1.Aggregate.ReporterPower) +// require.Equal(uint64(5), result1.Aggregate.Height) +// // check that the tip is in tip escrow +// tipEscrowAcct := s.Setup.Accountkeeper.GetModuleAddress(reportertypes.TipsEscrowPool) +// tipEscrowBalance := s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipEscrowAcct, s.Setup.Denom) // 98 loya +// require.Equal(tipAmount.Amount.Sub(twoPercent.Amount), tipEscrowBalance.Amount.Sub(balanceBeforetip.Amount)) +// // withdraw tip +// msgWithdrawTip := reportertypes.MsgWithdrawTip{ +// SelectorAddress: reporterAddress, +// ValidatorAddress: validator.OperatorAddress, +// } +// _, err = msgServerReporter.WithdrawTip(s.Setup.Ctx, &msgWithdrawTip) +// require.NoError(err) + +// // check that tip is no longer in escrow pool +// tipEscrowBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipEscrowAcct, s.Setup.Denom) +// require.Equal(int64(0), tipEscrowBalance.Amount.Int64()) +// // check that reporter now has more bonded tokens +// deleAfter, err := s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount.Bytes(), valBz) +// require.NoError(err) +// tipPlusTbr := math.NewInt(98 + 26786) +// require.Equal(deleBeforeReport.GetShares().Add(math.LegacyNewDecFromInt(tipPlusTbr)), deleAfter.GetShares()) + +// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) +// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) + +// // case 4: submit without committing for tipped query +// //--------------------------------------------------------------------------- +// // Height 6 +// //--------------------------------------------------------------------------- +// s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(s.Setup.Ctx.BlockHeight() + 1) +// _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) +// require.NoError(err) + +// // check reporter starting shares +// deleBeforeReport2, err := s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount.Bytes(), valBz) +// require.NoError(err) + +// twoPercentTip := sdk.NewCoin(s.Setup.Denom, tipAmount.Amount.Mul(math.NewInt(2)).Quo(math.NewInt(100))) +// twoPercentTipPlusTbr := sdk.NewCoin(s.Setup.Denom, tipAmount.Amount.Mul(math.NewInt(2)).Quo(math.NewInt(tipPlusTbr.Int64()))) +// expectedShares := math.LegacyNewDecFromInt(deleBeforeReport.GetShares().TruncateInt().Add(tipPlusTbr)) // 8928 is the tbr that was earned +// require.Equal(deleBeforeReport2.GetShares(), expectedShares) + +// // create tip msg +// msgTip = oracletypes.MsgTip{ +// Tipper: reporterAccount.String(), +// QueryData: cycleListTrb, +// Amount: tipAmount, +// } +// // send tip tx +// tipRes, err = msgServerOracle.Tip(s.Setup.Ctx, &msgTip) +// require.NoError(err) +// require.NotNil(tipRes) +// // check that tip is in oracle module account +// tipModuleAcct = s.Setup.Accountkeeper.GetModuleAddress(oracletypes.ModuleName) +// tipAcctBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipModuleAcct, s.Setup.Denom) +// require.Equal(tipAcctBalance.Amount, tipAmount.Amount.Sub(twoPercentTip.Amount)) +// // create submit msg +// revealMsgTrb := oracletypes.MsgSubmitValue{ +// Creator: reporterAccount.String(), +// QueryData: cycleListTrb, +// Value: testutil.EncodeValue(1_000_000), +// } +// // send submit msg +// revealTrb, err := msgServerOracle.SubmitValue(s.Setup.Ctx, &revealMsgTrb) +// require.NoError(err) +// require.NotNil(revealTrb) +// // advance time and block height to expire the query and aggregate report +// s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(21 * time.Second)) +// _, _ = s.Setup.App.EndBlocker(s.Setup.Ctx) +// s.NoError(s.Setup.Oraclekeeper.SetAggregatedReport(s.Setup.Ctx)) +// // create get aggregated report query +// getAggReportRequestTrb := oracletypes.QueryGetCurrentAggregateReportRequest{ +// QueryId: hex.EncodeToString(queryIdTrb), +// } +// // query aggregated report +// reportTrb, err := queryServer.GetCurrentAggregateReport(s.Setup.Ctx, &getAggReportRequestTrb) +// require.NoError(err) +// require.Equal(reportTrb.Aggregate.AggregateReportIndex, uint64(0)) +// require.Equal(reportTrb.Aggregate.AggregateValue, testutil.EncodeValue(1_000_000)) +// require.Equal(reportTrb.Aggregate.AggregateReporter, reporterAccount.String()) +// require.Equal(queryIdTrb, reportTrb.Aggregate.QueryId) +// require.Equal(uint64(4000), reportTrb.Aggregate.ReporterPower) +// require.Equal(uint64(6), reportTrb.Aggregate.Height) +// // check that the tip is in tip escrow +// tipEscrowBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipEscrowAcct, s.Setup.Denom) // 98 loya +// require.Equal(tipPlusTbr.Sub(twoPercentTipPlusTbr.Amount), tipEscrowBalance.Amount) +// // withdraw tip +// _, err = msgServerReporter.WithdrawTip(s.Setup.Ctx, &msgWithdrawTip) +// require.NoError(err) +// // check that tip is no longer in escrow pool +// tipEscrowBalance = s.Setup.Bankkeeper.GetBalance(s.Setup.Ctx, tipEscrowAcct, s.Setup.Denom) +// require.Equal(int64(0), tipEscrowBalance.Amount.Int64()) +// // check that reporter now has more bonded tokens +// deleAfter, err = s.Setup.Stakingkeeper.Delegation(s.Setup.Ctx, reporterAccount.Bytes(), valBz) +// require.NoError(err) +// require.Equal(deleBeforeReport2.GetShares().Add(math.LegacyNewDecFromInt(tipPlusTbr)), deleAfter.GetShares()) +// } + +func (s *E2ETestSuite) TestAggregateOverMultipleBlocks() { + // Setup msgServers + require := s.Require() + msgServerOracle := oraclekeeper.NewMsgServerImpl(s.Setup.Oraclekeeper) + require.NotNil(msgServerOracle) + msgServerReporter := reporterkeeper.NewMsgServerImpl(s.Setup.Reporterkeeper) + require.NotNil(msgServerReporter) + msgServerDispute := disputekeeper.NewMsgServerImpl(s.Setup.Disputekeeper) + require.NotNil(msgServerDispute) + msgServerStaking := stakingkeeper.NewMsgServerImpl(s.Setup.Stakingkeeper) + require.NotNil(msgServerStaking) + + //--------------------------------------------------------------------------- + // Height 0 - vicky becomes a validator + //--------------------------------------------------------------------------- + _, err := s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + vickyAccAddr := simtestutil.CreateIncrementalAccounts(1) + vickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(2000*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(vickyInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, vickyAccAddr[0], sdk.NewCoins(vickyInitCoins))) + s.Setup.Accountkeeper.NewAccountWithAddress(s.Setup.Ctx, vickyAccAddr[0]) + + pubKey := simtestutil.CreateTestPubKeys(1) + vickyValAddr := simtestutil.ConvertAddrsToValAddrs(vickyAccAddr) + msgCreateValidator, err := stakingtypes.NewMsgCreateValidator( + vickyValAddr[0].String(), + pubKey[0], + sdk.NewCoin(s.Setup.Denom, math.NewInt(1000*1e6)), + stakingtypes.Description{Moniker: "created validator"}, + stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(0, 0), math.LegacyNewDecWithPrec(3, 1), math.LegacyNewDecWithPrec(1, 1)), + math.OneInt(), + ) + require.NoError(err) + + _, err = msgServerStaking.CreateValidator(s.Setup.Ctx, msgCreateValidator) + require.NoError(err) + + require.NoError(s.Setup.Bridgekeeper.SetEVMAddressByOperator(s.Setup.Ctx, vickyValAddr[0].String(), []byte("vickyEvmAddr"))) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 1 - Rob delegates to Vicky and selects himself to become a reporter + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(1) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // verify vicky is a bonded validator + vickyValidatorInfo, err := s.Setup.Stakingkeeper.GetValidator(s.Setup.Ctx, vickyValAddr[0]) + require.NoError(err) + require.Equal(vickyValidatorInfo.Status, stakingtypes.Bonded) + require.Equal(vickyValidatorInfo.Tokens, math.NewInt(1000*1e6)) + + robPrivKey := secp256k1.GenPrivKey() + robAccAddr := sdk.AccAddress(robPrivKey.PubKey().Address()) + robInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(robInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, robAccAddr, sdk.NewCoins(robInitCoins))) + + // rob delegates to vicky + msgDelegate := stakingtypes.NewMsgDelegate( + robAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(100*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + // rob becomes a reporter + _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ + ReporterAddress: robAccAddr.String(), + CommissionRate: reportertypes.DefaultMinCommissionRate, + MinTokensRequired: math.NewInt(1 * 1e6), + }) + require.NoError(err) + robReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, robAccAddr) + require.NoError(err) + require.Equal(robReporterInfo.Jailed, false) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 2 - Delwood delegates 250 trb to Vicky + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(2) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + delwoodPrivKey := secp256k1.GenPrivKey() + delwoodAccAddr := sdk.AccAddress(delwoodPrivKey.PubKey().Address()) + delwoodInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(delwoodInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, delwoodAccAddr, sdk.NewCoins(delwoodInitCoins))) + + msgDelegate = stakingtypes.NewMsgDelegate( + delwoodAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(250*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 3 - Delwood selects 250 trb to Rob + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(3) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = msgServerReporter.SelectReporter(s.Setup.Ctx, &reportertypes.MsgSelectReporter{ + SelectorAddress: delwoodAccAddr.String(), + ReporterAddress: robAccAddr.String(), + }) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 4 - Roman and Ricky become reporters + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(4) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + romanPrivKey := secp256k1.GenPrivKey() + romanAccAddr := sdk.AccAddress(romanPrivKey.PubKey().Address()) + romanInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(200*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(romanInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, romanAccAddr, sdk.NewCoins(romanInitCoins))) + + // roman delegates to vicky + msgDelegate = stakingtypes.NewMsgDelegate( + romanAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(200*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ + ReporterAddress: romanAccAddr.String(), + CommissionRate: reportertypes.DefaultMinCommissionRate, + MinTokensRequired: math.NewInt(1 * 1e6), + }) + require.NoError(err) + romanReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, romanAccAddr) + require.NoError(err) + require.Equal(romanReporterInfo.Jailed, false) + + rickyPrivKey := secp256k1.GenPrivKey() + rickyAccAddr := sdk.AccAddress(rickyPrivKey.PubKey().Address()) + rickyInitCoins := sdk.NewCoin(s.Setup.Denom, math.NewInt(300*1e6)) + require.NoError(s.Setup.Bankkeeper.MintCoins(s.Setup.Ctx, authtypes.Minter, sdk.NewCoins(rickyInitCoins))) + require.NoError(s.Setup.Bankkeeper.SendCoinsFromModuleToAccount(s.Setup.Ctx, authtypes.Minter, rickyAccAddr, sdk.NewCoins(rickyInitCoins))) + + // ricky delegates to vicky + msgDelegate = stakingtypes.NewMsgDelegate( + rickyAccAddr.String(), + vickyValAddr[0].String(), + sdk.NewCoin(s.Setup.Denom, math.NewInt(300*1e6)), + ) + _, err = msgServerStaking.Delegate(s.Setup.Ctx, msgDelegate) + require.NoError(err) + + // ricky becomes a reporter + _, err = msgServerReporter.CreateReporter(s.Setup.Ctx, &reportertypes.MsgCreateReporter{ + ReporterAddress: rickyAccAddr.String(), + CommissionRate: reportertypes.DefaultMinCommissionRate, + MinTokensRequired: math.NewInt(1 * 1e6), + }) + require.NoError(err) + rickyReporterInfo, err := s.Setup.Reporterkeeper.Reporters.Get(s.Setup.Ctx, rickyAccAddr) + require.NoError(err) + require.Equal(rickyReporterInfo.Jailed, false) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 5 - only one block left in this cycle list query, pretend empty block + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(5) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 6 - Rob direct reveals for cycle list at height 6 + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(6) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + // Rob direct reveals for cycle list + currentCycleList, err := s.Setup.Oraclekeeper.GetCurrentQueryInCycleList(s.Setup.Ctx) + require.NoError(err) + queryId := utils.QueryIDFromData(currentCycleList) + msgSubmitValue := oracletypes.MsgSubmitValue{ + Creator: robAccAddr.String(), + QueryData: currentCycleList, + Value: testutil.EncodeValue(90_000), + } + _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &msgSubmitValue) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 7 - Roman and Ricky direct reveal for the same cycle list at height 7 + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(7) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + msgSubmitValue = oracletypes.MsgSubmitValue{ + Creator: romanAccAddr.String(), + QueryData: currentCycleList, + Value: testutil.EncodeValue(100_000), + } + _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &msgSubmitValue) + require.NoError(err) + + msgSubmitValue = oracletypes.MsgSubmitValue{ + Creator: rickyAccAddr.String(), + QueryData: currentCycleList, + Value: testutil.EncodeValue(110_000), + } + _, err = msgServerOracle.SubmitValue(s.Setup.Ctx, &msgSubmitValue) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + //--------------------------------------------------------------------------- + // Height 7 - Commit window expires, report gets aggregated in endblock + //--------------------------------------------------------------------------- + s.Setup.Ctx = s.Setup.Ctx.WithBlockHeight(8) + s.Setup.Ctx = s.Setup.Ctx.WithBlockTime(s.Setup.Ctx.BlockTime().Add(time.Second * 2)) + _, err = s.Setup.App.BeginBlocker(s.Setup.Ctx) + require.NoError(err) + + _, err = s.Setup.App.EndBlocker(s.Setup.Ctx) + require.NoError(err) + + aggregate, time, err := s.Setup.Oraclekeeper.GetCurrentAggregateReport(s.Setup.Ctx, queryId) + require.NoError(err) + require.Equal(3, len(aggregate.Reporters)) + require.Equal(aggregate.AggregateReportIndex, uint64(1)) + require.Equal(aggregate.AggregateValue, testutil.EncodeValue(100_000)) + require.Equal(aggregate.AggregateReporter, romanAccAddr.String()) + require.Equal(aggregate.Height, uint64(7)) + require.Equal(aggregate.ReporterPower, uint64(850)) + require.Equal(aggregate.QueryId, queryId) + require.Equal(aggregate.MetaId, uint64(2)) + + agg, err := s.Setup.Oraclekeeper.Aggregates.Get(s.Setup.Ctx, collections.Join(queryId, uint64(time.UnixMilli()))) + require.NoError(err) + require.Equal(3, len(agg.Reporters)) + + oracleQuerier := oraclekeeper.NewQuerier(s.Setup.Oraclekeeper) + microreports, err := oracleQuerier.GetReportsByAggregate(s.Setup.Ctx, &oracletypes.QueryGetReportsByAggregateRequest{ + QueryId: hex.EncodeToString(queryId), + Timestamp: uint64(time.UnixMilli()), + Pagination: &query.PageRequest{Limit: 100, CountTotal: true}, + }) + require.NoError(err) + require.Equal(3, len(microreports.MicroReports)) +} diff --git a/tests/setup.go b/tests/setup.go index e1550b06..90bd62a5 100644 --- a/tests/setup.go +++ b/tests/setup.go @@ -22,6 +22,7 @@ import ( bridgekeeper "github.com/tellor-io/layer/x/bridge/keeper" _ "github.com/tellor-io/layer/x/dispute" disputekeeper "github.com/tellor-io/layer/x/dispute/keeper" + disputetypes "github.com/tellor-io/layer/x/dispute/types" _ "github.com/tellor-io/layer/x/mint" mintkeeper "github.com/tellor-io/layer/x/mint/keeper" _ "github.com/tellor-io/layer/x/oracle" @@ -415,8 +416,8 @@ func (s *SharedSetup) DelegateAndSelect(msgServerStaking stakingtypes.MsgServer, numLoya math.Int, delegatorAccAddr sdk.AccAddress, valAddr sdk.ValAddress, - reporterAccAddr sdk.AccAddress) { - + reporterAccAddr sdk.AccAddress, +) { msgDelegate := stakingtypes.MsgDelegate{ DelegatorAddress: delegatorAccAddr.String(), ValidatorAddress: valAddr.String(), @@ -446,8 +447,7 @@ func (s *SharedSetup) CreateFundedAccount(numTrb int64) (sdk.AccAddress, error) return addr, nil } -func (s *SharedSetup) CreateSpotPriceTip(ctx sdk.Context, tipperAccAddr sdk.AccAddress, parameters string, amountLoya math.Int) *[]byte { - +func (s *SharedSetup) CreateSpotPriceTip(ctx sdk.Context, tipperAccAddr sdk.AccAddress, parameters string, amountLoya math.Int) []byte { req := ®istrytypes.QueryGenerateQuerydataRequest{ Querytype: "SpotPrice", Parameters: parameters, @@ -468,11 +468,10 @@ func (s *SharedSetup) CreateSpotPriceTip(ctx sdk.Context, tipperAccAddr sdk.AccA panic(err) } - return &res.QueryData + return res.QueryData } func (s *SharedSetup) Report(ctx sdk.Context, reporterAccAddr sdk.AccAddress, queryData []byte, reportValue string) { - msgSubmitValue := oracletypes.MsgSubmitValue{ Creator: reporterAccAddr.String(), QueryData: queryData, @@ -486,3 +485,20 @@ func (s *SharedSetup) Report(ctx sdk.Context, reporterAccAddr sdk.AccAddress, qu panic(err) } } + +func (s *SharedSetup) OpenDispute(ctx sdk.Context, disputerAccAddr sdk.AccAddress, report oracletypes.MicroReport, category disputetypes.DisputeCategory, fee math.Int, payFromBond bool) { + msgProposeDispute := disputetypes.MsgProposeDispute{ + Creator: disputerAccAddr.String(), + Report: &report, + DisputeCategory: disputetypes.Warning, + Fee: sdk.NewCoin(s.Denom, fee), + PayFromBond: payFromBond, + } + + msgServerDispute := disputekeeper.NewMsgServerImpl(s.Disputekeeper) + _, err := msgServerDispute.ProposeDispute(ctx, &msgProposeDispute) + if err != nil { + fmt.Println("propose dispute fail") + panic(err) + } +} diff --git a/x/dispute/keeper/dispute.go b/x/dispute/keeper/dispute.go index c5df163c..325f31a7 100644 --- a/x/dispute/keeper/dispute.go +++ b/x/dispute/keeper/dispute.go @@ -76,7 +76,6 @@ func (k Keeper) SetNewDispute(ctx sdk.Context, sender sdk.AccAddress, msg types. if err != nil { return err } - if msg.Fee.Amount.GT(disputeFee) { msg.Fee.Amount = disputeFee } @@ -112,6 +111,7 @@ func (k Keeper) SetNewDispute(ctx sdk.Context, sender sdk.AccAddress, msg types. if err := k.PayDisputeFee(ctx, sender, msg.Fee, msg.PayFromBond, dispute.HashId); err != nil { return err } + // if the paid fee is equal to the slash amount, then slash validator and jail if dispute.FeeTotal.Equal(dispute.SlashAmount) { if err := k.SlashAndJailReporter(ctx, dispute.InitialEvidence, dispute.DisputeCategory, dispute.HashId); err != nil { diff --git a/x/oracle/abci.go b/x/oracle/abci.go index 4f2fc3ac..0e7023d3 100644 --- a/x/oracle/abci.go +++ b/x/oracle/abci.go @@ -2,11 +2,9 @@ package oracle import ( "context" - // "fmt" // "github.com/tellor-io/layer/utils" "github.com/tellor-io/layer/x/oracle/keeper" - // sdk "github.com/cosmos/cosmos-sdk/types" ) func EndBlocker(ctx context.Context, k keeper.Keeper) error { diff --git a/x/oracle/keeper/msg_server_submit_value.go b/x/oracle/keeper/msg_server_submit_value.go index 08d9116e..69314f41 100644 --- a/x/oracle/keeper/msg_server_submit_value.go +++ b/x/oracle/keeper/msg_server_submit_value.go @@ -3,7 +3,6 @@ package keeper import ( "context" "errors" - "fmt" "strings" layertypes "github.com/tellor-io/layer/types" @@ -47,7 +46,6 @@ func (k msgServer) SubmitValue(ctx context.Context, msg *types.MsgSubmitValue) ( queryId := utils.QueryIDFromData(msg.QueryData) query, err := k.keeper.CurrentQuery(ctx, queryId) - fmt.Println("query.QueryType from SubmitValue: ", query.QueryType) if err != nil { if !errors.Is(err, collections.ErrNotFound) { return nil, err diff --git a/x/oracle/keeper/msg_server_tip.go b/x/oracle/keeper/msg_server_tip.go index 643fa2fd..e48501e0 100644 --- a/x/oracle/keeper/msg_server_tip.go +++ b/x/oracle/keeper/msg_server_tip.go @@ -103,6 +103,5 @@ func (k msgServer) Tip(goCtx context.Context, msg *types.MsgTip) (*types.MsgTipR sdk.NewAttribute("amount", tip.Amount.String()), ), }) - fmt.Println("tip added") return &types.MsgTipResponse{}, nil } diff --git a/x/oracle/keeper/submit_value.go b/x/oracle/keeper/submit_value.go index b73ff209..1a372d63 100644 --- a/x/oracle/keeper/submit_value.go +++ b/x/oracle/keeper/submit_value.go @@ -19,7 +19,6 @@ import ( func (k Keeper) SetValue(ctx context.Context, reporter sdk.AccAddress, query types.QueryMeta, val string, queryData []byte, power uint64, incycle bool) error { // decode query data hex to get query type, returns interface array queryType, _, err := regTypes.DecodeQueryType(queryData) - fmt.Println("queryType from SetValue: ", queryType) if err != nil { return status.Error(codes.InvalidArgument, fmt.Sprintf("failed to decode query type: %v", err)) } @@ -47,9 +46,7 @@ func (k Keeper) SetValue(ctx context.Context, reporter sdk.AccAddress, query typ BlockNumber: uint64(sdkCtx.BlockHeight()), } - fmt.Println("report.QueryType from SetValue: ", report.QueryType) query.HasRevealedReports = true - fmt.Println("query.QueryType from SetValue: ", query.QueryType) err = k.Query.Set(ctx, collections.Join(queryId, query.Id), query) if err != nil { return err From 276c168f0552f1c40720f840213a241b156fc4cf Mon Sep 17 00:00:00 2001 From: danflo27 Date: Thu, 31 Oct 2024 10:25:06 -0400 Subject: [PATCH 8/8] remove heighliner submodule --- heighliner | 1 - 1 file changed, 1 deletion(-) delete mode 160000 heighliner diff --git a/heighliner b/heighliner deleted file mode 160000 index b675b55c..00000000 --- a/heighliner +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b675b55c3c252681dde0c1449035e5c625907915