228 lines
6.4 KiB
Go
228 lines
6.4 KiB
Go
package types
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/gogo/protobuf/proto"
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
"github.com/tendermint/tendermint/libs/log"
|
|
|
|
"github.com/cosmos/cosmos-sdk/store/gaskv"
|
|
stypes "github.com/cosmos/cosmos-sdk/store/types"
|
|
)
|
|
|
|
/*
|
|
Context is an immutable object contains all information needed to
|
|
process a request.
|
|
|
|
It contains a context.Context object inside if you want to use that,
|
|
but please do not over-use it. We try to keep all data structured
|
|
and standard additions here would be better just to add to the Context struct
|
|
*/
|
|
type Context struct {
|
|
ctx context.Context
|
|
ms MultiStore
|
|
header abci.Header
|
|
chainID string
|
|
txBytes []byte
|
|
logger log.Logger
|
|
voteInfo []abci.VoteInfo
|
|
gasMeter GasMeter
|
|
blockGasMeter GasMeter
|
|
checkTx bool
|
|
recheckTx bool // if recheckTx == true, then checkTx must also be true
|
|
minGasPrice DecCoins
|
|
consParams *abci.ConsensusParams
|
|
eventManager *EventManager
|
|
}
|
|
|
|
// Proposed rename, not done to avoid API breakage
|
|
type Request = Context
|
|
|
|
// Read-only accessors
|
|
func (c Context) Context() context.Context { return c.ctx }
|
|
func (c Context) MultiStore() MultiStore { return c.ms }
|
|
func (c Context) BlockHeight() int64 { return c.header.Height }
|
|
func (c Context) BlockTime() time.Time { return c.header.Time }
|
|
func (c Context) ChainID() string { return c.chainID }
|
|
func (c Context) TxBytes() []byte { return c.txBytes }
|
|
func (c Context) Logger() log.Logger { return c.logger }
|
|
func (c Context) VoteInfos() []abci.VoteInfo { return c.voteInfo }
|
|
func (c Context) GasMeter() GasMeter { return c.gasMeter }
|
|
func (c Context) BlockGasMeter() GasMeter { return c.blockGasMeter }
|
|
func (c Context) IsCheckTx() bool { return c.checkTx }
|
|
func (c Context) IsReCheckTx() bool { return c.recheckTx }
|
|
func (c Context) MinGasPrices() DecCoins { return c.minGasPrice }
|
|
func (c Context) EventManager() *EventManager { return c.eventManager }
|
|
|
|
// clone the header before returning
|
|
func (c Context) BlockHeader() abci.Header {
|
|
var msg = proto.Clone(&c.header).(*abci.Header)
|
|
return *msg
|
|
}
|
|
|
|
func (c Context) ConsensusParams() *abci.ConsensusParams {
|
|
return proto.Clone(c.consParams).(*abci.ConsensusParams)
|
|
}
|
|
|
|
// create a new context
|
|
func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, logger log.Logger) Context {
|
|
// https://github.com/gogo/protobuf/issues/519
|
|
header.Time = header.Time.UTC()
|
|
return Context{
|
|
ctx: context.Background(),
|
|
ms: ms,
|
|
header: header,
|
|
chainID: header.ChainID,
|
|
checkTx: isCheckTx,
|
|
logger: logger,
|
|
gasMeter: stypes.NewInfiniteGasMeter(),
|
|
minGasPrice: DecCoins{},
|
|
eventManager: NewEventManager(),
|
|
}
|
|
}
|
|
|
|
func (c Context) WithContext(ctx context.Context) Context {
|
|
c.ctx = ctx
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithMultiStore(ms MultiStore) Context {
|
|
c.ms = ms
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithBlockHeader(header abci.Header) Context {
|
|
// https://github.com/gogo/protobuf/issues/519
|
|
header.Time = header.Time.UTC()
|
|
c.header = header
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithBlockTime(newTime time.Time) Context {
|
|
newHeader := c.BlockHeader()
|
|
// https://github.com/gogo/protobuf/issues/519
|
|
newHeader.Time = newTime.UTC()
|
|
return c.WithBlockHeader(newHeader)
|
|
}
|
|
|
|
func (c Context) WithProposer(addr ConsAddress) Context {
|
|
newHeader := c.BlockHeader()
|
|
newHeader.ProposerAddress = addr.Bytes()
|
|
return c.WithBlockHeader(newHeader)
|
|
}
|
|
|
|
func (c Context) WithBlockHeight(height int64) Context {
|
|
newHeader := c.BlockHeader()
|
|
newHeader.Height = height
|
|
return c.WithBlockHeader(newHeader)
|
|
}
|
|
|
|
func (c Context) WithChainID(chainID string) Context {
|
|
c.chainID = chainID
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithTxBytes(txBytes []byte) Context {
|
|
c.txBytes = txBytes
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithLogger(logger log.Logger) Context {
|
|
c.logger = logger
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithVoteInfos(voteInfo []abci.VoteInfo) Context {
|
|
c.voteInfo = voteInfo
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithGasMeter(meter GasMeter) Context {
|
|
c.gasMeter = meter
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithBlockGasMeter(meter GasMeter) Context {
|
|
c.blockGasMeter = meter
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithIsCheckTx(isCheckTx bool) Context {
|
|
c.checkTx = isCheckTx
|
|
return c
|
|
}
|
|
|
|
// WithIsRecheckTx called with true will also set true on checkTx in order to
|
|
// enforce the invariant that if recheckTx = true then checkTx = true as well.
|
|
func (c Context) WithIsReCheckTx(isRecheckTx bool) Context {
|
|
if isRecheckTx {
|
|
c.checkTx = true
|
|
}
|
|
c.recheckTx = isRecheckTx
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithMinGasPrices(gasPrices DecCoins) Context {
|
|
c.minGasPrice = gasPrices
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithConsensusParams(params *abci.ConsensusParams) Context {
|
|
c.consParams = params
|
|
return c
|
|
}
|
|
|
|
func (c Context) WithEventManager(em *EventManager) Context {
|
|
c.eventManager = em
|
|
return c
|
|
}
|
|
|
|
// TODO: remove???
|
|
func (c Context) IsZero() bool {
|
|
return c.ms == nil
|
|
}
|
|
|
|
// WithValue is deprecated, provided for backwards compatibility
|
|
// Please use
|
|
// ctx = ctx.WithContext(context.WithValue(ctx.Context(), key, false))
|
|
// instead of
|
|
// ctx = ctx.WithValue(key, false)
|
|
func (c Context) WithValue(key, value interface{}) Context {
|
|
c.ctx = context.WithValue(c.ctx, key, value)
|
|
return c
|
|
}
|
|
|
|
// Value is deprecated, provided for backwards compatibility
|
|
// Please use
|
|
// ctx.Context().Value(key)
|
|
// instead of
|
|
// ctx.Value(key)
|
|
func (c Context) Value(key interface{}) interface{} {
|
|
return c.ctx.Value(key)
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Store / Caching
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// KVStore fetches a KVStore from the MultiStore.
|
|
func (c Context) KVStore(key StoreKey) KVStore {
|
|
return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.KVGasConfig())
|
|
}
|
|
|
|
// TransientStore fetches a TransientStore from the MultiStore.
|
|
func (c Context) TransientStore(key StoreKey) KVStore {
|
|
return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.TransientGasConfig())
|
|
}
|
|
|
|
// CacheContext returns a new Context with the multi-store cached and a new
|
|
// EventManager. The cached context is written to the context when writeCache
|
|
// is called.
|
|
func (c Context) CacheContext() (cc Context, writeCache func()) {
|
|
cms := c.MultiStore().CacheMultiStore()
|
|
cc = c.WithMultiStore(cms).WithEventManager(NewEventManager())
|
|
return cc, cms.Write
|
|
}
|