diff --git a/app/app.go b/app/app.go index 50b65482e..72d3e5c80 100644 --- a/app/app.go +++ b/app/app.go @@ -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) diff --git a/types/alias.go b/types/alias.go index 5b86c9e62..3c855ebe2 100644 --- a/types/alias.go +++ b/types/alias.go @@ -39,7 +39,9 @@ const ( var ( // functions aliases - IsPeriodLastBlock = util.IsPeriodLastBlock + IsPeriodLastBlock = util.IsPeriodLastBlock + IsWaitingForSoftfork = util.IsWaitingForSoftfork + IsSoftforkHeight = util.IsSoftforkHeight ) type ( diff --git a/types/util/softfork.go b/types/util/softfork.go new file mode 100644 index 000000000..4d393511a --- /dev/null +++ b/types/util/softfork.go @@ -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) +} diff --git a/x/market/internal/keeper/swap.go b/x/market/internal/keeper/swap.go index 6dd259791..3e5d996c8 100644 --- a/x/market/internal/keeper/swap.go +++ b/x/market/internal/keeper/swap.go @@ -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) } diff --git a/x/market/internal/types/errors.go b/x/market/internal/types/errors.go index cddbb3046..2fae37830 100644 --- a/x/market/internal/types/errors.go +++ b/x/market/internal/types/errors.go @@ -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") ) diff --git a/x/oracle/abci_test.go b/x/oracle/abci_test.go index 0c15b9dbc..85e4bd832 100644 --- a/x/oracle/abci_test.go +++ b/x/oracle/abci_test.go @@ -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) diff --git a/x/oracle/alias.go b/x/oracle/alias.go index 504c2e872..2231982d1 100644 --- a/x/oracle/alias.go +++ b/x/oracle/alias.go @@ -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 diff --git a/x/oracle/handler.go b/x/oracle/handler.go index c4d2d8ef2..5ca69b506 100644 --- a/x/oracle/handler.go +++ b/x/oracle/handler.go @@ -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" ) @@ -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) { @@ -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) } } diff --git a/x/oracle/internal/keeper/keeper.go b/x/oracle/internal/keeper/keeper.go index 05ae81357..638069f24 100644 --- a/x/oracle/internal/keeper/keeper.go +++ b/x/oracle/internal/keeper/keeper.go @@ -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 diff --git a/x/oracle/internal/keeper/querier.go b/x/oracle/internal/keeper/querier.go index 9c34dc6b8..66924eda3 100644 --- a/x/oracle/internal/keeper/querier.go +++ b/x/oracle/internal/keeper/querier.go @@ -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" ) @@ -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) diff --git a/x/oracle/internal/types/errors.go b/x/oracle/internal/types/errors.go index 23896804c..295a81dda 100644 --- a/x/oracle/internal/types/errors.go +++ b/x/oracle/internal/types/errors.go @@ -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") @@ -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") ) diff --git a/x/oracle/internal/types/msgs.go b/x/oracle/internal/types/msgs.go index 6fd26a31d..1d495ca49 100644 --- a/x/oracle/internal/types/msgs.go +++ b/x/oracle/internal/types/msgs.go @@ -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"` @@ -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() { @@ -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"` @@ -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() { diff --git a/x/oracle/test_utils.go b/x/oracle/test_utils.go index f66b866a0..62558d2f4 100644 --- a/x/oracle/test_utils.go +++ b/x/oracle/test_utils.go @@ -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 diff --git a/x/treasury/alias.go b/x/treasury/alias.go index 68ead9ff8..b54ab26a0 100644 --- a/x/treasury/alias.go +++ b/x/treasury/alias.go @@ -29,7 +29,6 @@ const ( var ( // functions aliases RegisterCodec = types.RegisterCodec - ErrInvalidEpoch = types.ErrInvalidEpoch NewGenesisState = types.NewGenesisState DefaultGenesisState = types.DefaultGenesisState ValidateGenesis = types.ValidateGenesis diff --git a/x/treasury/internal/types/errors.go b/x/treasury/internal/types/errors.go deleted file mode 100644 index 75ba37d6f..000000000 --- a/x/treasury/internal/types/errors.go +++ /dev/null @@ -1,11 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// x/treasury module sentinel errors -// -var ( - ErrInvalidEpoch = sdkerrors.Register(ModuleName, 1, "The query epoch should be between [0, current epoch]") -) diff --git a/x/wasm/abci.go b/x/wasm/abci.go new file mode 100644 index 000000000..661f0419c --- /dev/null +++ b/x/wasm/abci.go @@ -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) + } +} diff --git a/x/wasm/internal/keeper/contract.go b/x/wasm/internal/keeper/contract.go index 09b28f38b..40819e5bf 100644 --- a/x/wasm/internal/keeper/contract.go +++ b/x/wasm/internal/keeper/contract.go @@ -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()) } @@ -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()) } @@ -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) diff --git a/x/wasm/internal/types/errors.go b/x/wasm/internal/types/errors.go index 322d24270..03f381af3 100644 --- a/x/wasm/internal/types/errors.go +++ b/x/wasm/internal/types/errors.go @@ -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") @@ -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") ) diff --git a/x/wasm/internal/types/query_binding.go b/x/wasm/internal/types/query_binding.go index 9a198c3cd..6244427c7 100644 --- a/x/wasm/internal/types/query_binding.go +++ b/x/wasm/internal/types/query_binding.go @@ -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 @@ -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) @@ -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{} diff --git a/x/wasm/module.go b/x/wasm/module.go index 994108b76..c690fc0d9 100644 --- a/x/wasm/module.go +++ b/x/wasm/module.go @@ -137,7 +137,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage { } // BeginBlock returns the begin blocker for the wasm module. -func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} +func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { + BeginBlocker(ctx, am.keeper) +} // EndBlock returns the end blocker for the wasm module. It returns no validator // updates.