Skip to content

Commit

Permalink
Release v9.1.0 (evmos#1011)
Browse files Browse the repository at this point in the history
* update cosmos sdk

* add v9.1.0 upgrade handler and test

* add changelog

Co-authored-by: Ramiro Carlucho <[email protected]>
  • Loading branch information
facs95 and ramacarlucho authored Oct 25, 2022
1 parent db076d7 commit 80c38f6
Show file tree
Hide file tree
Showing 8 changed files with 2,476 additions and 3 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ Ref: https://keepachangelog.com/en/1.0.0/

# Changelog

## [v9.1.0] - 2022-10-25

### Improvements

- (deps) [\#1011](https://github.com/evmos/evmos/pull/1011) Bump Cosmos SDK to [`v0.45.10`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.45.10)

## [v9.0.0] - 2022-10-21

### Bug Fixes
Expand Down
12 changes: 12 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ import (
v81 "github.com/evmos/evmos/v9/app/upgrades/v8_1"
v82 "github.com/evmos/evmos/v9/app/upgrades/v8_2"
v9 "github.com/evmos/evmos/v9/app/upgrades/v9"
v91 "github.com/evmos/evmos/v9/app/upgrades/v9_1"
"github.com/evmos/evmos/v9/x/claims"
claimskeeper "github.com/evmos/evmos/v9/x/claims/keeper"
claimstypes "github.com/evmos/evmos/v9/x/claims/types"
Expand Down Expand Up @@ -1120,6 +1121,15 @@ func (app *Evmos) setupUpgradeHandlers() {
),
)

// v9.1 upgrade handler
app.UpgradeKeeper.SetUpgradeHandler(
v91.UpgradeName,
v91.CreateUpgradeHandler(
app.mm, app.configurator,
app.DistrKeeper,
),
)

// When a planned update height is reached, the old binary will panic
// writing on disk the height and name of the update that triggered it
// This will read that value, and execute the preparations for the upgrade.
Expand Down Expand Up @@ -1162,6 +1172,8 @@ func (app *Evmos) setupUpgradeHandlers() {
}
case v9.UpgradeName:
// no store upgrade in v9
case v91.UpgradeName:
// no store upgrade in v9
}

if storeUpgrades != nil {
Expand Down
2,162 changes: 2,162 additions & 0 deletions app/upgrades/v9_1/accounts.go

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions app/upgrades/v9_1/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package v91

const (
// UpgradeName is the shared upgrade plan name for mainnet
UpgradeName = "v9.1.0"
// UpgradeInfo defines the binaries that will be used for the upgrade
UpgradeInfo = `'{"binaries":{"darwin/arm64":"https://github.com/evmos/evmos/releases/download/v9.1.0/evmos_9.1.0_Darwin_arm64.tar.gz","darwin/amd64":"https://github.com/evmos/evmos/releases/download/v9.1.0/evmos_9.1.0_Darwin_amd64.tar.gz","linux/arm64":"https://github.com/evmos/evmos/releases/download/v9.1.0/evmos_9.1.0_Linux_arm64.tar.gz","linux/amd64":"https://github.com/evmos/evmos/releases/download/v9.1.0/evmos_9.1.0_Linux_amd64.tar.gz","windows/x86_64":"https://github.com/evmos/evmos/releases/download/v9.1.0/evmos_9.1.0_Windows_x86_64.zip"}}'`
// MaxRecover is the maximum amount of coins to be redistributed in the upgrade
MaxRecover = "93590289356801768542679"
)
86 changes: 86 additions & 0 deletions app/upgrades/v9_1/upgrades.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package v91

import (
"fmt"

"github.com/tendermint/tendermint/libs/log"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
distrKeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
"github.com/evmos/evmos/v9/types"
)

// CreateUpgradeHandler creates an SDK upgrade handler for v9
func CreateUpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
dk distrKeeper.Keeper,
) upgradetypes.UpgradeHandler {
return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
logger := ctx.Logger().With("upgrade", UpgradeName)

if types.IsMainnet(ctx.ChainID()) {
logger.Debug("recovering lost funds from clawback...")
HandleMainnetUpgrade(ctx, dk, logger)
}

// Leave modules are as-is to avoid running InitGenesis.
logger.Debug("running module migrations ...")
return mm.RunMigrations(ctx, configurator, vm)
}
}

// HandleMainnetUpgrade handles the logic for Mainnet upgrade, it only commits to the db if successful
func HandleMainnetUpgrade(ctx sdk.Context, dk distrKeeper.Keeper, logger log.Logger) {
// use a cache context as a rollback mechanism in case
// the refund fails
cacheCtx, writeFn := ctx.CacheContext()
err := ReturnFundsFromCommunityPool(cacheCtx, dk)
if err != nil {
// log error instead of aborting the upgrade
logger.Error("failed to recover from community funds", "error", err.Error())
} else {
writeFn()
}
}

// ReturnFundsFromCommunityPool handles the return of funds from the community pool to accounts affected during the claims clawback
func ReturnFundsFromCommunityPool(ctx sdk.Context, dk distrKeeper.Keeper) error {
availableCoins, ok := sdk.NewIntFromString(MaxRecover)
if !ok || availableCoins.IsNegative() {
return fmt.Errorf("failed to read maximum amount to recover from community funds")
}
for i := range Accounts {
address := Accounts[i][0]
amt := Accounts[i][1]

refund, _ := sdk.NewIntFromString(amt)
if availableCoins.LT(refund) {
return fmt.Errorf(
"refund to address %s exceeds the total available coins: %s > %s",
address, amt, availableCoins,
)
}
if err := ReturnFundsFromCommunityPoolToAccount(ctx, dk, address, refund); err != nil {
return err
}
availableCoins = availableCoins.Sub(refund)
}
return nil
}

// ReturnFundsFromCommunityPoolToAccount sends specified amount from the community pool to the affected account
func ReturnFundsFromCommunityPoolToAccount(ctx sdk.Context, dk distrKeeper.Keeper, account string, amount sdk.Int) error {
to := sdk.MustAccAddressFromBech32(account)
balance := sdk.Coin{
Denom: "aevmos",
Amount: amount,
}

if err := dk.DistributeFromFeePool(ctx, sdk.Coins{balance}, to); err != nil {
return err
}
return nil
}
197 changes: 197 additions & 0 deletions app/upgrades/v9_1/upgrades_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package v91_test

import (
"fmt"
"testing"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/suite"

"github.com/tendermint/tendermint/crypto/tmhash"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
"github.com/tendermint/tendermint/version"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/evmos/ethermint/crypto/ethsecp256k1"
feemarkettypes "github.com/evmos/ethermint/x/feemarket/types"

"github.com/evmos/evmos/v9/app"
v9 "github.com/evmos/evmos/v9/app/upgrades/v9_1"
evmostypes "github.com/evmos/evmos/v9/types"
"github.com/evmos/evmos/v9/x/erc20/types"
)

type UpgradeTestSuite struct {
suite.Suite

ctx sdk.Context
app *app.Evmos
consAddress sdk.ConsAddress
}

func (suite *UpgradeTestSuite) SetupTest(chainID string) {
checkTx := false

// consensus key
priv, err := ethsecp256k1.GenerateKey()
suite.Require().NoError(err)
suite.consAddress = sdk.ConsAddress(priv.PubKey().Address())

// NOTE: this is the new binary, not the old one.
suite.app = app.Setup(checkTx, feemarkettypes.DefaultGenesisState())
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{
Height: 1,
ChainID: chainID,
Time: time.Date(2022, 5, 9, 8, 0, 0, 0, time.UTC),
ProposerAddress: suite.consAddress.Bytes(),

Version: tmversion.Consensus{
Block: version.BlockProtocol,
},
LastBlockId: tmproto.BlockID{
Hash: tmhash.Sum([]byte("block_id")),
PartSetHeader: tmproto.PartSetHeader{
Total: 11,
Hash: tmhash.Sum([]byte("partset_header")),
},
},
AppHash: tmhash.Sum([]byte("app")),
DataHash: tmhash.Sum([]byte("data")),
EvidenceHash: tmhash.Sum([]byte("evidence")),
ValidatorsHash: tmhash.Sum([]byte("validators")),
NextValidatorsHash: tmhash.Sum([]byte("next_validators")),
ConsensusHash: tmhash.Sum([]byte("consensus")),
LastResultsHash: tmhash.Sum([]byte("last_result")),
})

cp := suite.app.BaseApp.GetConsensusParams(suite.ctx)
suite.ctx = suite.ctx.WithConsensusParams(cp)
}

func TestUpgradeTestSuite(t *testing.T) {
s := new(UpgradeTestSuite)
suite.Run(t, s)
}

func (suite *UpgradeTestSuite) TestMigrateFaucetBalance() {

firstAccountAmount := v9.Accounts[0][1]
thousandAccountAmount := v9.Accounts[1000][1]

testCases := []struct {
name string
chainID string
malleate func()
expectedSuccess bool
}{
{
"Mainnet - sucess",
evmostypes.MainnetChainID + "-4",
func() {
// send funds to the community pool
priv, err := ethsecp256k1.GenerateKey()
suite.Require().NoError(err)
address := common.BytesToAddress(priv.PubKey().Address().Bytes())
sender := sdk.AccAddress(address.Bytes())
res, _ := sdk.NewIntFromString(v9.MaxRecover)
coins := sdk.NewCoins(sdk.NewCoin("aevmos", res))
suite.app.BankKeeper.MintCoins(suite.ctx, types.ModuleName, coins)
suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleName, sender, coins)
err = suite.app.DistrKeeper.FundCommunityPool(suite.ctx, coins, sender)
suite.Require().NoError(err)

balanceBefore := suite.app.DistrKeeper.GetFeePoolCommunityCoins(suite.ctx)
suite.Require().Equal(balanceBefore.AmountOf("aevmos"), sdk.NewDecFromInt(res))
},
true,
},
{
"Mainnet - first account > MaxRecover",
evmostypes.MainnetChainID + "-4",
func() {
// send funds to the community pool
priv, err := ethsecp256k1.GenerateKey()
suite.Require().NoError(err)
address := common.BytesToAddress(priv.PubKey().Address().Bytes())
sender := sdk.AccAddress(address.Bytes())
res, _ := sdk.NewIntFromString(v9.MaxRecover)
coins := sdk.NewCoins(sdk.NewCoin("aevmos", res))
suite.app.BankKeeper.MintCoins(suite.ctx, types.ModuleName, coins)
suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleName, sender, coins)
err = suite.app.DistrKeeper.FundCommunityPool(suite.ctx, coins, sender)
suite.Require().NoError(err)

balanceBefore := suite.app.DistrKeeper.GetFeePoolCommunityCoins(suite.ctx)
suite.Require().Equal(balanceBefore.AmountOf("aevmos"), sdk.NewDecFromInt(res))

v9.Accounts[0][1] = v9.MaxRecover
},
false,
},
{
"Mainnet - middle account > MaxRecover",
evmostypes.MainnetChainID + "-4",
func() {
// send funds to the community pool
priv, err := ethsecp256k1.GenerateKey()
suite.Require().NoError(err)
address := common.BytesToAddress(priv.PubKey().Address().Bytes())
sender := sdk.AccAddress(address.Bytes())
res, _ := sdk.NewIntFromString(v9.MaxRecover)
coins := sdk.NewCoins(sdk.NewCoin("aevmos", res))
suite.app.BankKeeper.MintCoins(suite.ctx, types.ModuleName, coins)
suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleName, sender, coins)
err = suite.app.DistrKeeper.FundCommunityPool(suite.ctx, coins, sender)
suite.Require().NoError(err)

balanceBefore := suite.app.DistrKeeper.GetFeePoolCommunityCoins(suite.ctx)
suite.Require().Equal(balanceBefore.AmountOf("aevmos"), sdk.NewDecFromInt(res))

v9.Accounts[1000][1] = v9.MaxRecover
},
false,
},
{
"Mainnet - fail communityFund is empty",
evmostypes.MainnetChainID + "-4",
func() {
},
false,
},
}

for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest(tc.chainID)

tc.malleate()

logger := suite.ctx.Logger().With("upgrade", "Test v9 Upgrade")
v9.HandleMainnetUpgrade(suite.ctx, suite.app.DistrKeeper, logger)

// check balance of affected accounts
if tc.expectedSuccess {
for i := range v9.Accounts {
addr := sdk.MustAccAddressFromBech32(v9.Accounts[i][0])
res, _ := sdk.NewIntFromString(v9.Accounts[i][1])
balance := suite.app.BankKeeper.GetBalance(suite.ctx, addr, "aevmos")
suite.Require().Equal(balance.Amount, res)
}

balanceAfter := suite.app.DistrKeeper.GetFeePoolCommunityCoins(suite.ctx)
suite.Require().True(balanceAfter.IsZero())
} else {
for i := range v9.Accounts {
addr := sdk.MustAccAddressFromBech32(v9.Accounts[i][0])
balance := suite.app.BankKeeper.GetBalance(suite.ctx, addr, "aevmos")
suite.Require().Equal(balance.Amount, sdk.NewInt(0))
}
}
v9.Accounts[0][1] = firstAccountAmount
v9.Accounts[1000][1] = thousandAccountAmount
})
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.18

require (
github.com/armon/go-metrics v0.4.0
github.com/cosmos/cosmos-sdk v0.45.9
github.com/cosmos/cosmos-sdk v0.45.10
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/ibc-go/v3 v3.2.0
github.com/ethereum/go-ethereum v1.10.19
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44=
github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU=
github.com/cosmos/cosmos-sdk v0.45.9 h1:Z4s1EZL/mfM8uSSZr8WmyEbWp4hqbWVI5sAIFR432KY=
github.com/cosmos/cosmos-sdk v0.45.9/go.mod h1:Z5M4TX7PsHNHlF/1XanI2DIpORQ+Q/st7oaeufEjnvU=
github.com/cosmos/cosmos-sdk v0.45.10 h1:YRf1N6C7OFCc8FJ5wuhcnDDySJNDn5DxSscVgbeXgz4=
github.com/cosmos/cosmos-sdk v0.45.10/go.mod h1:CbfWNs4PuxxsvRD/snQuSBDwIhtsD7rIDTVQyYMKTa0=
github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 h1:iKclrn3YEOwk4jQHT2ulgzuXyxmzmPczUalMwW4XH9k=
github.com/cosmos/cosmos-sdk/ics23/go v0.8.0/go.mod h1:2a4dBq88TUoqoWAU5eu0lGvpFP3wWDPgdHPargtyw30=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
Expand Down

0 comments on commit 80c38f6

Please sign in to comment.