Skip to content

Commit

Permalink
[Upgrade] Softfork for WASM Updates (#433)
Browse files Browse the repository at this point in the history
* add softfork condition to staking wasm querier

* formatting

* update error codes bigger than 1

* handle prev error to internal error

* handle prev error to internal error

* fix wrong error type

* add wasm execute msg size limit update

* remove unstable staking begin blocker
  • Loading branch information
yys authored Nov 23, 2020
1 parent df11740 commit ee1cd6e
Show file tree
Hide file tree
Showing 20 changed files with 131 additions and 40 deletions.
3 changes: 2 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,8 @@ func NewTerraApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest
// During begin block slashing happens after distr.BeginBlocker so that
// there is nothing left over in the validator fee pool, so as to keep the
// CanWithdrawInvariant invariant.
app.mm.SetOrderBeginBlockers(upgrade.ModuleName, mint.ModuleName, distr.ModuleName, slashing.ModuleName, evidence.ModuleName)
app.mm.SetOrderBeginBlockers(upgrade.ModuleName, mint.ModuleName, distr.ModuleName, slashing.ModuleName,
evidence.ModuleName, wasm.ModuleName)
app.mm.SetOrderEndBlockers(crisis.ModuleName, oracle.ModuleName, gov.ModuleName, market.ModuleName,
treasury.ModuleName, msgauth.ModuleName, staking.ModuleName)

Expand Down
4 changes: 3 additions & 1 deletion types/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ const (

var (
// functions aliases
IsPeriodLastBlock = util.IsPeriodLastBlock
IsPeriodLastBlock = util.IsPeriodLastBlock
IsWaitingForSoftfork = util.IsWaitingForSoftfork
IsSoftforkHeight = util.IsSoftforkHeight
)

type (
Expand Down
28 changes: 28 additions & 0 deletions types/util/softfork.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package util

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

// IsWaitingForSoftfork returns whether current block
// height is bigger than reserved softfork block height
func IsWaitingForSoftfork(ctx sdk.Context, _version uint8) bool {
// Expected time:
// MAINNET
// Fri Jan 01 2021 18:00:00 GMT+0900 (KST)
// Fri Jan 01 2021 09:00:00 GMT+0000 (UTC)
// Fri Jan 01 2021 01:00:00 GMT-0800 (PST)
//
// TEQUILA
// Fri Nov 27 2020 12:00:00 GMT+0900 (KST)
// Fri Nov 27 2020 03:00:00 GMT+0000 (UTC)
// Fri Nov 26 2020 19:00:00 GMT-0800 (KST)

return (ctx.ChainID() == "columbus-4" && ctx.BlockHeight() < 1200000) ||
(ctx.ChainID() == "tequila-0004" && ctx.BlockHeight() < 1350000)
}

// IsSoftforkHeight return whether current block
// height is the targeted softfork height
func IsSoftforkHeight(ctx sdk.Context, _version uint8) bool {
return (ctx.ChainID() == "columbus-4" && ctx.BlockHeight() == 1200000) ||
(ctx.ChainID() == "tequila-0004" && ctx.BlockHeight() == 1350000)
}
8 changes: 8 additions & 0 deletions x/market/internal/keeper/swap.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,19 @@ func (k Keeper) ComputeInternalSwap(ctx sdk.Context, offerCoin sdk.DecCoin, askD

offerRate, err := k.oracleKeeper.GetLunaExchangeRate(ctx, offerCoin.Denom)
if err != nil {
if core.IsWaitingForSoftfork(ctx, 1) {
return sdk.DecCoin{}, sdkerrors.Wrap(types.ErrInternal, "no effective price")
}

return sdk.DecCoin{}, sdkerrors.Wrap(types.ErrNoEffectivePrice, offerCoin.Denom)
}

askRate, err := k.oracleKeeper.GetLunaExchangeRate(ctx, askDenom)
if err != nil {
if core.IsWaitingForSoftfork(ctx, 1) {
return sdk.DecCoin{}, sdkerrors.Wrap(types.ErrInternal, "no effective price")
}

return sdk.DecCoin{}, sdkerrors.Wrap(types.ErrNoEffectivePrice, askDenom)
}

Expand Down
3 changes: 2 additions & 1 deletion x/market/internal/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import (

// Market errors
var (
ErrNoEffectivePrice = sdkerrors.Register(ModuleName, 1, "no price registered with oracle")
ErrInternal = sdkerrors.Register(ModuleName, 1, "internal error")
ErrInvalidOfferCoin = sdkerrors.Register(ModuleName, 2, "invalid offer coin")
ErrRecursiveSwap = sdkerrors.Register(ModuleName, 3, "recursive swap")
ErrNoEffectivePrice = sdkerrors.Register(ModuleName, 4, "no price registered with oracle")
)
2 changes: 1 addition & 1 deletion x/oracle/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ func TestVoteTargets(t *testing.T) {
}

func TestAbstainWithSmallStakingPower(t *testing.T) {
input, h := setup_with_small_voting_power(t)
input, h := setupWithSmallVotingPower(t)

// clear tobin tax to reset vote targets
input.OracleKeeper.ClearTobinTaxes(input.Ctx)
Expand Down
3 changes: 2 additions & 1 deletion x/oracle/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ var (

// variable aliases
ModuleCdc = types.ModuleCdc
ErrUnknowDenom = types.ErrUnknowDenom
ErrInternal = types.ErrInternal
ErrUnknownDenom = types.ErrUnknownDenom
ErrInvalidExchangeRate = types.ErrInvalidExchangeRate
ErrNoPrevote = types.ErrNoPrevote
ErrNoVote = types.ErrNoVote
Expand Down
16 changes: 12 additions & 4 deletions x/oracle/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package oracle
import (
"fmt"

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

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/staking"

core "github.com/terra-project/core/types"
"github.com/terra-project/core/x/oracle/internal/types"
)

Expand Down Expand Up @@ -39,7 +39,11 @@ func handleMsgExchangeRatePrevote(ctx sdk.Context, keeper Keeper, msg MsgExchang

// check the denom is in the vote target
if !keeper.IsVoteTarget(ctx, msg.Denom) {
return nil, sdkerrors.Wrap(ErrUnknowDenom, msg.Denom)
if core.IsWaitingForSoftfork(ctx, 1) {
return nil, sdkerrors.Wrap(ErrInternal, "unknown denom")
}

return nil, sdkerrors.Wrap(ErrUnknownDenom, msg.Denom)
}

if !msg.Feeder.Equals(msg.Validator) {
Expand Down Expand Up @@ -226,7 +230,11 @@ func handleMsgAggregateExchangeRateVote(ctx sdk.Context, keeper Keeper, msg MsgA
// check all denoms are in the vote target
for _, tuple := range exchangeRateTuples {
if !keeper.IsVoteTarget(ctx, tuple.Denom) {
return nil, sdkerrors.Wrap(ErrUnknowDenom, tuple.Denom)
if core.IsWaitingForSoftfork(ctx, 1) {
return nil, sdkerrors.Wrap(ErrInternal, "unknown denom")
}

return nil, sdkerrors.Wrap(ErrUnknownDenom, tuple.Denom)
}
}

Expand Down
6 changes: 5 additions & 1 deletion x/oracle/internal/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,11 @@ func (k Keeper) GetLunaExchangeRate(ctx sdk.Context, denom string) (exchangeRate
store := ctx.KVStore(k.storeKey)
b := store.Get(types.GetExchangeRateKey(denom))
if b == nil {
return sdk.ZeroDec(), sdkerrors.Wrap(types.ErrUnknowDenom, denom)
if core.IsWaitingForSoftfork(ctx, 1) {
return sdk.ZeroDec(), sdkerrors.Wrap(types.ErrInternal, "unknown denom")
}

return sdk.ZeroDec(), sdkerrors.Wrap(types.ErrUnknownDenom, denom)
}
k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &exchangeRate)
return
Expand Down
7 changes: 6 additions & 1 deletion x/oracle/internal/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

abci "github.com/tendermint/tendermint/abci/types"

core "github.com/terra-project/core/types"
"github.com/terra-project/core/x/oracle/internal/types"
)

Expand Down Expand Up @@ -56,7 +57,11 @@ func queryExchangeRate(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([

rate, err := keeper.GetLunaExchangeRate(ctx, params.Denom)
if err != nil {
return nil, sdkerrors.Wrap(types.ErrUnknowDenom, params.Denom)
if core.IsWaitingForSoftfork(ctx, 1) {
return nil, sdkerrors.Wrap(types.ErrInternal, "unknown denom")
}

return nil, sdkerrors.Wrap(types.ErrUnknownDenom, params.Denom)
}

bz, err2 := codec.MarshalJSONIndent(keeper.cdc, rate)
Expand Down
3 changes: 2 additions & 1 deletion x/oracle/internal/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

// Oracle Errors
var (
ErrUnknowDenom = sdkerrors.Register(ModuleName, 1, "unknown denom")
ErrInternal = sdkerrors.Register(ModuleName, 1, "internal error")
ErrInvalidExchangeRate = sdkerrors.Register(ModuleName, 2, "invalid exchange rate")
ErrNoPrevote = sdkerrors.Register(ModuleName, 3, "no prevote")
ErrNoVote = sdkerrors.Register(ModuleName, 4, "no vote")
Expand All @@ -22,4 +22,5 @@ var (
ErrNoAggregatePrevote = sdkerrors.Register(ModuleName, 11, "no aggregate prevote")
ErrNoAggregateVote = sdkerrors.Register(ModuleName, 12, "no aggregate vote")
ErrNoTobinTax = sdkerrors.Register(ModuleName, 13, "no tobin tax")
ErrUnknownDenom = sdkerrors.Register(ModuleName, 14, "unknown denom")
)
8 changes: 4 additions & 4 deletions x/oracle/internal/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ var (
//-------------------------------------------------
//-------------------------------------------------

// Deprecated: normal prevote and vote will be deprecated after columbus-4
// MsgExchangeRatePrevote - struct for prevoting on the ExchangeRateVote.
// The purpose of prevote is to hide vote exchange rate with hash
// which is formatted as hex string in SHA256("{salt}:{exchange_rate}:{denom}:{voter}")
// Deprecated: normal prevote and vote will be deprecated after columbus-4
type MsgExchangeRatePrevote struct {
Hash VoteHash `json:"hash" yaml:"hash"`
Denom string `json:"denom" yaml:"denom"`
Expand Down Expand Up @@ -67,7 +67,7 @@ func (msg MsgExchangeRatePrevote) ValidateBasic() error {
}

if len(msg.Denom) == 0 {
return ErrUnknowDenom
return sdkerrors.Wrap(ErrInternal, "invalid denom length")
}

if msg.Feeder.Empty() {
Expand All @@ -91,10 +91,10 @@ func (msg MsgExchangeRatePrevote) String() string {
msg.Hash, msg.Feeder, msg.Validator, msg.Denom)
}

// Deprecated: normal prevote and vote will be deprecated after columbus-4
// MsgExchangeRateVote - struct for voting on the exchange rate of Luna denominated in various Terra assets.
// For example, if the validator believes that the effective exchange rate of Luna in USD is 10.39, that's
// what the exchange rate field would be, and if 1213.34 for KRW, same.
// Deprecated: normal prevote and vote will be deprecated after columbus-4
type MsgExchangeRateVote struct {
ExchangeRate sdk.Dec `json:"exchange_rate" yaml:"exchange_rate"` // the effective rate of Luna in {Denom}
Salt string `json:"salt" yaml:"salt"`
Expand Down Expand Up @@ -134,7 +134,7 @@ func (msg MsgExchangeRateVote) GetSigners() []sdk.AccAddress {
func (msg MsgExchangeRateVote) ValidateBasic() error {

if len(msg.Denom) == 0 {
return ErrUnknowDenom
return sdkerrors.Wrap(ErrInternal, "invalid denom length")
}

if msg.Feeder.Empty() {
Expand Down
2 changes: 1 addition & 1 deletion x/oracle/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var (
anotherRandomExchangeRate = sdk.NewDecWithPrec(4882, 2) // swap rate
)

func setup_with_small_voting_power(t *testing.T) (keeper.TestInput, sdk.Handler) {
func setupWithSmallVotingPower(t *testing.T) (keeper.TestInput, sdk.Handler) {
input := keeper.CreateTestInput(t)
params := input.OracleKeeper.GetParams(input.Ctx)
params.VotePeriod = 1
Expand Down
1 change: 0 additions & 1 deletion x/treasury/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ const (
var (
// functions aliases
RegisterCodec = types.RegisterCodec
ErrInvalidEpoch = types.ErrInvalidEpoch
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
ValidateGenesis = types.ValidateGenesis
Expand Down
11 changes: 0 additions & 11 deletions x/treasury/internal/types/errors.go

This file was deleted.

17 changes: 17 additions & 0 deletions x/wasm/abci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package wasm

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

core "github.com/terra-project/core/types"
"github.com/terra-project/core/x/wasm/internal/keeper"
)

// BeginBlocker handles softfork over param changes
func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
if core.IsSoftforkHeight(ctx, 1) {
params := k.GetParams(ctx)
params.MaxContractMsgSize = 4096
k.SetParams(ctx, params)
}
}
19 changes: 18 additions & 1 deletion x/wasm/internal/keeper/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,26 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/tendermint/tendermint/crypto"
core "github.com/terra-project/core/types"
"github.com/terra-project/core/x/wasm/internal/types"
)

// CompileCode uncompress the wasm code bytes and store the code to local file system
func (k Keeper) CompileCode(ctx sdk.Context, wasmCode []byte) (codeHash []byte, err error) {
if uint64(len(wasmCode)) > k.MaxContractSize(ctx) {
if core.IsWaitingForSoftfork(ctx, 1) {
return nil, sdkerrors.Wrap(types.ErrInternal, "contract size is too huge")
}

return nil, sdkerrors.Wrap(types.ErrStoreCodeFailed, "contract size is too huge")
}

wasmCode, err = k.uncompress(ctx, wasmCode)
if err != nil {
if core.IsWaitingForSoftfork(ctx, 1) {
return nil, sdkerrors.Wrap(types.ErrInternal, err.Error())
}

return nil, sdkerrors.Wrap(types.ErrStoreCodeFailed, err.Error())
}

Expand All @@ -26,6 +35,10 @@ func (k Keeper) CompileCode(ctx sdk.Context, wasmCode []byte) (codeHash []byte,

codeHash, err = k.wasmer.Create(wasmCode)
if err != nil {
if core.IsWaitingForSoftfork(ctx, 1) {
return nil, sdkerrors.Wrap(types.ErrInternal, err.Error())
}

return nil, sdkerrors.Wrap(types.ErrStoreCodeFailed, err.Error())
}

Expand Down Expand Up @@ -167,7 +180,11 @@ func (k Keeper) ExecuteContract(ctx sdk.Context, contractAddress sdk.AccAddress,
ctx.GasMeter().ConsumeGas(types.InstanceCost, "Loading CosmWasm module: execute")

if uint64(len(exeMsg)) > k.MaxContractMsgSize(ctx) {
return nil, sdkerrors.Wrap(types.ErrInstantiateFailed, "execute msg size is too huge")
if core.IsWaitingForSoftfork(ctx, 1) {
return nil, sdkerrors.Wrap(types.ErrInstantiateFailed, "execute msg size is too huge")
}

return nil, sdkerrors.Wrap(types.ErrExecuteFailed, "execute msg size is too huge")
}

codeInfo, storePrefix, err := k.getContractDetails(ctx, contractAddress)
Expand Down
3 changes: 2 additions & 1 deletion x/wasm/internal/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (

// Wasm Errors
var (
ErrStoreCodeFailed = sdkerrors.Register(ModuleName, 1, "store wasm contract failed")
ErrInternal = sdkerrors.Register(ModuleName, 1, "internal error")
ErrAccountExists = sdkerrors.Register(ModuleName, 2, "contract account already exists")
ErrInstantiateFailed = sdkerrors.Register(ModuleName, 3, "instantiate wasm contract failed")
ErrExecuteFailed = sdkerrors.Register(ModuleName, 4, "execute wasm contract failed")
Expand All @@ -18,4 +18,5 @@ var (
ErrNoRegisteredParser = sdkerrors.Register(ModuleName, 10, "failed to find parser for route")
ErrMigrationFailed = sdkerrors.Register(ModuleName, 11, "migrate wasm contract failed")
ErrNotMigratable = sdkerrors.Register(ModuleName, 12, "the contract is not migratable ")
ErrStoreCodeFailed = sdkerrors.Register(ModuleName, 13, "store wasm contract failed")
)
23 changes: 15 additions & 8 deletions x/wasm/internal/types/query_binding.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (

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

core "github.com/terra-project/core/types"
)

// WasmQuerierInterface - query registration interface for other modules
Expand Down Expand Up @@ -74,9 +76,9 @@ func (q Querier) Query(request wasmTypes.QueryRequest, gasLimit uint64) ([]byte,
case request.Bank != nil:
if querier, ok := q.Queriers[WasmQueryRouteBank]; ok {
return querier.Query(ctx, request)
} else {
return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, WasmQueryRouteBank)
}

return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, WasmQueryRouteBank)
case request.Custom != nil:
var customQuery WasmCustomQuery
err := json.Unmarshal(request.Custom, &customQuery)
Expand All @@ -86,21 +88,26 @@ func (q Querier) Query(request wasmTypes.QueryRequest, gasLimit uint64) ([]byte,

if querier, ok := q.Queriers[customQuery.Route]; ok {
return querier.QueryCustom(ctx, customQuery.QueryData)
} else {
return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, customQuery.Route)
}

return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, customQuery.Route)
case request.Staking != nil:
if querier, ok := q.Queriers[WasmQueryRouteStaking]; ok {
if core.IsWaitingForSoftfork(ctx, 1) {
panic("NOT SUPPORTED UNTIL SOFTFORK TIME")
}

return querier.Query(ctx, request)
} else {
return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, WasmQueryRouteStaking)
}

return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, WasmQueryRouteStaking)

case request.Wasm != nil:
if querier, ok := q.Queriers[WasmQueryRouteWasm]; ok {
return querier.Query(ctx, request)
} else {
return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, WasmQueryRouteWasm)
}

return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, WasmQueryRouteWasm)
}

return nil, wasmTypes.Unknown{}
Expand Down
Loading

0 comments on commit ee1cd6e

Please sign in to comment.