Skip to content

Commit

Permalink
Merge pull request #808 from HaoyangLiu/develop
Browse files Browse the repository at this point in the history
R4R: Merge PRs from cosmos
  • Loading branch information
wukongcheng authored Dec 12, 2018
2 parents 499da01 + 51f1d52 commit 5aea8de
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 65 deletions.
98 changes: 63 additions & 35 deletions app/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/tmhash"
cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"

Expand Down Expand Up @@ -65,6 +64,10 @@ type BaseApp struct {
deliverState *state // for DeliverTx
voteInfos []abci.VoteInfo // absent validators from begin block

// consensus params
// TODO move this in the future to baseapp param store on main store.
consensusParams *abci.ConsensusParams

// minimum fees for spam prevention
minimumFees sdk.Coins

Expand Down Expand Up @@ -208,6 +211,10 @@ func (st *state) CacheMultiStore() sdk.CacheMultiStore {
return st.ms.CacheMultiStore()
}

func (st *state) Context() sdk.Context {
return st.ctx
}

func (app *BaseApp) setCheckState(header abci.Header) {
ms := app.cms.CacheMultiStore()
app.checkState = &state{
Expand Down Expand Up @@ -392,6 +399,7 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res
return sdk.ErrUnknownRequest(fmt.Sprintf("no custom querier found for route %s", path[1])).QueryResult()
}

// Cache wrap the commit-multistore for safety.
ctx := sdk.NewContext(app.cms.CacheMultiStore(), app.checkState.ctx.BlockHeader(), true, app.Logger).
WithMinimumFees(app.minimumFees)
// Passes the rest of the path as an argument to the querier.
Expand Down Expand Up @@ -539,13 +547,14 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error {
return nil
}

// retrieve the context for the ante handler and store the tx bytes; store
// the vote infos if the tx runs within the deliverTx() state.
func (app *BaseApp) getContextForAnte(mode RunTxMode, txBytes []byte) (ctx sdk.Context) {
// Get the context
ctx = getState(app, mode).ctx.WithTxBytes(txBytes)
if mode == RunTxModeDeliver {
ctx = ctx.WithVoteInfos(app.voteInfos)
// retrieve the context for the tx w/ txBytes and other memoized values.
func (app *BaseApp) getContextForTx(mode RunTxMode, txBytes []byte) (ctx sdk.Context) {
ctx = app.getState(mode).ctx.
WithTxBytes(txBytes).
WithVoteInfos(app.voteInfos).
WithConsensusParams(app.consensusParams)
if mode == RunTxModeSimulate {
ctx, _ = ctx.CacheContext()
}
return
}
Expand Down Expand Up @@ -612,19 +621,31 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode RunTxMode) (re

// Returns the applicantion's deliverState if app is in runTxModeDeliver,
// otherwise it returns the application's checkstate.
func getState(app *BaseApp, mode RunTxMode) *state {
func (app *BaseApp) getState(mode RunTxMode) *state {
if mode == RunTxModeCheck || mode == RunTxModeSimulate {
return app.checkState
}

return app.deliverState
}

func (app *BaseApp) initializeContext(ctx sdk.Context, mode RunTxMode) sdk.Context {
if mode == RunTxModeSimulate {
ctx = ctx.WithMultiStore(getState(app, RunTxModeSimulate).CacheMultiStore())
// cacheTxContext returns a new context based off of the provided context with
// a cache wrapped multi-store.
func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) (
sdk.Context, sdk.CacheMultiStore) {
ms := ctx.MultiStore()
// TODO: https://github.com/cosmos/cosmos-sdk/issues/2824
msCache := ms.CacheMultiStore()
if msCache.TracingEnabled() {
msCache = msCache.WithTracingContext(
sdk.TraceContext(
map[string]interface{}{
"txHash": fmt.Sprintf("%X", tmhash.Sum(txBytes)),
},
),
).(sdk.CacheMultiStore)
}
return ctx
return ctx.WithMultiStore(msCache), msCache
}

// runTx processes a transaction. The transactions is proccessed via an
Expand All @@ -636,9 +657,8 @@ func (app *BaseApp) runTx(mode RunTxMode, txBytes []byte, tx sdk.Tx) (result sdk
// meter so we initialize upfront.
var gasWanted uint64
var msCache sdk.CacheMultiStore
ctx := app.getContextForAnte(mode, txBytes)
ctx = app.initializeContext(ctx, mode)
ctxWithNoCache := ctx
ctx := app.getContextForTx(mode, txBytes)
ms := ctx.MultiStore()

defer func() {
if r := recover(); r != nil {
Expand All @@ -658,7 +678,7 @@ func (app *BaseApp) runTx(mode RunTxMode, txBytes []byte, tx sdk.Tx) (result sdk
feeRefundHandler := app.Engine.GetCurrent().GetFeeRefundHandler()
// Refund unspent fee
if mode != RunTxModeCheck && feeRefundHandler != nil {
_, err := feeRefundHandler(ctxWithNoCache, tx, result)
_, err := feeRefundHandler(ctx, tx, result)
if err != nil {
result = sdk.ErrInternal(err.Error()).Result()
result.GasWanted = gasWanted
Expand All @@ -685,37 +705,45 @@ func (app *BaseApp) runTx(mode RunTxMode, txBytes []byte, tx sdk.Tx) (result sdk
anteHandler := app.Engine.GetCurrent().GetAnteHandler()
// run the ante handler
if anteHandler != nil {
newCtx, result, abort := anteHandler(ctx, tx, (mode == RunTxModeSimulate))
var anteCtx sdk.Context
var msCache sdk.CacheMultiStore
// Cache wrap context before anteHandler call in case it aborts.
// This is required for both CheckTx and DeliverTx.
// https://github.com/cosmos/cosmos-sdk/issues/2772
// NOTE: Alternatively, we could require that anteHandler ensures that
// writes do not happen if aborted/failed. This may have some
// performance benefits, but it'll be more difficult to get right.
anteCtx, msCache = app.cacheTxContext(ctx, txBytes)

newCtx, result, abort := anteHandler(anteCtx, tx, (mode == RunTxModeSimulate))
if abort {
return result
}
if !newCtx.IsZero() {
ctx = newCtx
ctxWithNoCache = newCtx
// At this point, newCtx.MultiStore() is cache wrapped,
// or something else replaced by anteHandler.
// We want the original ms, not one which was cache-wrapped
// for the ante handler.
ctx = newCtx.WithMultiStore(ms)
}

msCache.Write()
gasWanted = result.GasWanted
}

if mode == RunTxModeSimulate {
result = app.runMsgs(ctx, msgs, mode)
result.GasWanted = gasWanted
if mode == RunTxModeCheck {
return
}

// Keep the state in a transient CacheWrap in case processing the messages
// fails.
msCache = getState(app, mode).CacheMultiStore()
if msCache.TracingEnabled() {
msCache = msCache.WithTracingContext(sdk.TraceContext(
map[string]interface{}{"txHash": cmn.HexBytes(tmhash.Sum(txBytes)).String()},
)).(sdk.CacheMultiStore)
}

ctx = ctx.WithMultiStore(msCache)
result = app.runMsgs(ctx, msgs, mode)
// Create a new context based off of the existing context with a cache wrapped
// multi-store in case message processing fails.
runMsgCtx, msCache := app.cacheTxContext(ctx, txBytes)
result = app.runMsgs(runMsgCtx, msgs, mode)
result.GasWanted = gasWanted

if mode == RunTxModeSimulate {
return
}

// only update state if all messages pass
if result.IsOK() {
msCache.Write()
Expand Down
9 changes: 8 additions & 1 deletion modules/distribution/keeper/allocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ func (k Keeper) AllocateTokens(ctx sdk.Context, percentVotes sdk.Dec, proposer s
feesCollected := k.feeCollectionKeeper.GetCollectedFees(ctx)
feesCollectedDec := types.NewDecCoins(feesCollected)

feePool := k.GetFeePool(ctx)
if k.stakeKeeper.GetLastTotalPower(ctx).IsZero() {
feePool.CommunityPool = feePool.CommunityPool.Plus(feesCollectedDec)
k.SetFeePool(ctx, feePool)
k.feeCollectionKeeper.ClearCollectedFees(ctx)
return
}

// allocated rewards to proposer
baseProposerReward := k.GetBaseProposerReward(ctx)
bonusProposerReward := k.GetBonusProposerReward(ctx)
Expand All @@ -33,7 +41,6 @@ func (k Keeper) AllocateTokens(ctx sdk.Context, percentVotes sdk.Dec, proposer s
// allocate community funding
communityTax := k.GetCommunityTax(ctx)
communityFunding := feesCollectedDec.MulDec(communityTax)
feePool := k.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Plus(communityFunding)

// set the global pool within the distribution module
Expand Down
9 changes: 9 additions & 0 deletions modules/stake/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"github.com/irisnet/irishub/modules/stake/tags"
"github.com/irisnet/irishub/modules/stake/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/common"
tmtypes "github.com/tendermint/tendermint/types"
)

func NewHandler(k keeper.Keeper) sdk.Handler {
Expand Down Expand Up @@ -103,6 +105,13 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
return ErrBadDenom(k.Codespace()).Result()
}

if ctx.ConsensusParams() != nil {
tmPubKey := tmtypes.TM2PB.PubKey(msg.PubKey)
if !common.StringInSlice(tmPubKey.Type, ctx.ConsensusParams().Validator.PubKeyTypes) {
return ErrValidatorPubKeyTypeUnsupported(k.Codespace(), tmPubKey.Type, ctx.ConsensusParams().Validator.PubKeyTypes).Result()
}
}

validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description)
commission := NewCommissionWithTime(
msg.Commission.Rate, msg.Commission.MaxRate,
Expand Down
18 changes: 18 additions & 0 deletions modules/stake/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import (
sdk "github.com/irisnet/irishub/types"
keep "github.com/irisnet/irishub/modules/stake/keeper"
"github.com/irisnet/irishub/modules/stake/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/secp256k1"
tmtypes "github.com/tendermint/tendermint/types"
)

//______________________________________________________________________
Expand Down Expand Up @@ -157,6 +160,21 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
assert.Equal(t, Description{}, validator.Description)
}

func TestInvalidPubKeyTypeMsgCreateValidator(t *testing.T) {
ctx, _, keeper := keep.CreateTestInput(t, false, sdk.NewIntWithDecimal(1000,18))
addr := sdk.ValAddress(keep.Addrs[0])
invalidPk := secp256k1.GenPrivKey().PubKey()
// invalid pukKey type should not be allowed
msgCreateValidator := NewTestMsgCreateValidator(addr, invalidPk, sdk.NewIntWithDecimal(10,18))
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
require.False(t, got.IsOK(), "%v", got)
ctx = ctx.WithConsensusParams(&abci.ConsensusParams{
Validator: &abci.ValidatorParams{PubKeyTypes: []string{tmtypes.ABCIPubKeyTypeSecp256k1}},
})
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
require.True(t, got.IsOK(), "%v", got)
}

func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) {
ctx, _, keeper := keep.CreateTestInput(t, false, sdk.NewIntWithDecimal(1000, 18))

Expand Down
18 changes: 9 additions & 9 deletions modules/stake/keeper/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@ import (
"strconv"
"testing"

"github.com/irisnet/irishub/codec"
"github.com/irisnet/irishub/modules/auth"
"github.com/irisnet/irishub/modules/bank"
"github.com/irisnet/irishub/modules/params"
"github.com/irisnet/irishub/modules/stake/types"
"github.com/irisnet/irishub/store"
sdk "github.com/irisnet/irishub/types"
"github.com/stretchr/testify/require"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"

"github.com/irisnet/irishub/codec"
"github.com/irisnet/irishub/store"
sdk "github.com/irisnet/irishub/types"
"github.com/irisnet/irishub/modules/auth"
"github.com/irisnet/irishub/modules/bank"
"github.com/irisnet/irishub/modules/params"
"github.com/irisnet/irishub/modules/stake/types"
tmtypes "github.com/tendermint/tendermint/types"
)

// dummy addresses used for testing
Expand Down Expand Up @@ -94,6 +93,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins sdk.Int) (sdk.Conte
require.Nil(t, err)

ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, log.NewNopLogger())
ctx = ctx.WithConsensusParams(&abci.ConsensusParams{Validator: &abci.ValidatorParams{PubKeyTypes: []string{tmtypes.ABCIPubKeyTypeEd25519}}})
cdc := MakeTestCodec()
accountKeeper := auth.NewAccountKeeper(
cdc, // amino codec
Expand Down
19 changes: 10 additions & 9 deletions modules/stake/stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,16 @@ const (
)

var (
ErrNilValidatorAddr = types.ErrNilValidatorAddr
ErrNoValidatorFound = types.ErrNoValidatorFound
ErrValidatorOwnerExists = types.ErrValidatorOwnerExists
ErrValidatorPubKeyExists = types.ErrValidatorPubKeyExists
ErrValidatorJailed = types.ErrValidatorJailed
ErrBadRemoveValidator = types.ErrBadRemoveValidator
ErrDescriptionLength = types.ErrDescriptionLength
ErrCommissionNegative = types.ErrCommissionNegative
ErrCommissionHuge = types.ErrCommissionHuge
ErrNilValidatorAddr = types.ErrNilValidatorAddr
ErrNoValidatorFound = types.ErrNoValidatorFound
ErrValidatorOwnerExists = types.ErrValidatorOwnerExists
ErrValidatorPubKeyExists = types.ErrValidatorPubKeyExists
ErrValidatorPubKeyTypeUnsupported = types.ErrValidatorPubKeyTypeNotSupported
ErrValidatorJailed = types.ErrValidatorJailed
ErrBadRemoveValidator = types.ErrBadRemoveValidator
ErrDescriptionLength = types.ErrDescriptionLength
ErrCommissionNegative = types.ErrCommissionNegative
ErrCommissionHuge = types.ErrCommissionHuge

ErrNilDelegatorAddr = types.ErrNilDelegatorAddr
ErrBadDenom = types.ErrBadDenom
Expand Down
6 changes: 6 additions & 0 deletions modules/stake/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

sdk "github.com/irisnet/irishub/types"
"strings"
)

type CodeType = sdk.CodeType
Expand Down Expand Up @@ -44,6 +45,11 @@ func ErrValidatorPubKeyExists(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidValidator, "validator already exist for this pubkey, must use new validator pubkey")
}

func ErrValidatorPubKeyTypeNotSupported(codespace sdk.CodespaceType, keyType string, supportedTypes []string) sdk.Error {
msg := fmt.Sprintf("validator pubkey type %s is not supported, must use %s", keyType, strings.Join(supportedTypes, ","))
return sdk.NewError(codespace, CodeInvalidValidator, msg)
}

func ErrValidatorJailed(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidValidator, "validator for this address is currently jailed")
}
Expand Down
Loading

0 comments on commit 5aea8de

Please sign in to comment.