github.com/cosmos/cosmos-sdk@v0.50.10/types/context.go (about) 1 package types 2 3 import ( 4 "context" 5 "time" 6 7 abci "github.com/cometbft/cometbft/abci/types" 8 cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" 9 "github.com/cosmos/gogoproto/proto" 10 11 "cosmossdk.io/core/comet" 12 "cosmossdk.io/core/header" 13 "cosmossdk.io/log" 14 "cosmossdk.io/store/gaskv" 15 storetypes "cosmossdk.io/store/types" 16 ) 17 18 // ExecMode defines the execution mode which can be set on a Context. 19 type ExecMode uint8 20 21 // All possible execution modes. 22 const ( 23 ExecModeCheck ExecMode = iota 24 ExecModeReCheck 25 ExecModeSimulate 26 ExecModePrepareProposal 27 ExecModeProcessProposal 28 ExecModeVoteExtension 29 ExecModeVerifyVoteExtension 30 ExecModeFinalize 31 ) 32 33 /* 34 Context is an immutable object contains all information needed to 35 process a request. 36 37 It contains a context.Context object inside if you want to use that, 38 but please do not over-use it. We try to keep all data structured 39 and standard additions here would be better just to add to the Context struct 40 */ 41 type Context struct { 42 baseCtx context.Context 43 ms storetypes.MultiStore 44 // Deprecated: Use HeaderService for height, time, and chainID and CometService for the rest 45 header cmtproto.Header 46 // Deprecated: Use HeaderService for hash 47 headerHash []byte 48 // Deprecated: Use HeaderService for chainID and CometService for the rest 49 chainID string 50 txBytes []byte 51 logger log.Logger 52 voteInfo []abci.VoteInfo 53 gasMeter storetypes.GasMeter 54 blockGasMeter storetypes.GasMeter 55 checkTx bool 56 recheckTx bool // if recheckTx == true, then checkTx must also be true 57 sigverifyTx bool // when run simulation, because the private key corresponding to the account in the genesis.json randomly generated, we must skip the sigverify. 58 execMode ExecMode 59 minGasPrice DecCoins 60 consParams cmtproto.ConsensusParams 61 eventManager EventManagerI 62 priority int64 // The tx priority, only relevant in CheckTx 63 kvGasConfig storetypes.GasConfig 64 transientKVGasConfig storetypes.GasConfig 65 streamingManager storetypes.StreamingManager 66 cometInfo comet.BlockInfo 67 headerInfo header.Info 68 } 69 70 // Proposed rename, not done to avoid API breakage 71 type Request = Context 72 73 // Read-only accessors 74 func (c Context) Context() context.Context { return c.baseCtx } 75 func (c Context) MultiStore() storetypes.MultiStore { return c.ms } 76 func (c Context) BlockHeight() int64 { return c.header.Height } 77 func (c Context) BlockTime() time.Time { return c.header.Time } 78 func (c Context) ChainID() string { return c.chainID } 79 func (c Context) TxBytes() []byte { return c.txBytes } 80 func (c Context) Logger() log.Logger { return c.logger } 81 func (c Context) VoteInfos() []abci.VoteInfo { return c.voteInfo } 82 func (c Context) GasMeter() storetypes.GasMeter { return c.gasMeter } 83 func (c Context) BlockGasMeter() storetypes.GasMeter { return c.blockGasMeter } 84 func (c Context) IsCheckTx() bool { return c.checkTx } 85 func (c Context) IsReCheckTx() bool { return c.recheckTx } 86 func (c Context) IsSigverifyTx() bool { return c.sigverifyTx } 87 func (c Context) ExecMode() ExecMode { return c.execMode } 88 func (c Context) MinGasPrices() DecCoins { return c.minGasPrice } 89 func (c Context) EventManager() EventManagerI { return c.eventManager } 90 func (c Context) Priority() int64 { return c.priority } 91 func (c Context) KVGasConfig() storetypes.GasConfig { return c.kvGasConfig } 92 func (c Context) TransientKVGasConfig() storetypes.GasConfig { return c.transientKVGasConfig } 93 func (c Context) StreamingManager() storetypes.StreamingManager { return c.streamingManager } 94 func (c Context) CometInfo() comet.BlockInfo { return c.cometInfo } 95 func (c Context) HeaderInfo() header.Info { return c.headerInfo } 96 97 // clone the header before returning 98 func (c Context) BlockHeader() cmtproto.Header { 99 msg := proto.Clone(&c.header).(*cmtproto.Header) 100 return *msg 101 } 102 103 // HeaderHash returns a copy of the header hash obtained during abci.RequestBeginBlock 104 func (c Context) HeaderHash() []byte { 105 hash := make([]byte, len(c.headerHash)) 106 copy(hash, c.headerHash) 107 return hash 108 } 109 110 func (c Context) ConsensusParams() cmtproto.ConsensusParams { 111 return c.consParams 112 } 113 114 func (c Context) Deadline() (deadline time.Time, ok bool) { 115 return c.baseCtx.Deadline() 116 } 117 118 func (c Context) Done() <-chan struct{} { 119 return c.baseCtx.Done() 120 } 121 122 func (c Context) Err() error { 123 return c.baseCtx.Err() 124 } 125 126 // create a new context 127 func NewContext(ms storetypes.MultiStore, header cmtproto.Header, isCheckTx bool, logger log.Logger) Context { 128 // https://github.com/gogo/protobuf/issues/519 129 header.Time = header.Time.UTC() 130 return Context{ 131 baseCtx: context.Background(), 132 ms: ms, 133 header: header, 134 chainID: header.ChainID, 135 checkTx: isCheckTx, 136 sigverifyTx: true, 137 logger: logger, 138 gasMeter: storetypes.NewInfiniteGasMeter(), 139 minGasPrice: DecCoins{}, 140 eventManager: NewEventManager(), 141 kvGasConfig: storetypes.KVGasConfig(), 142 transientKVGasConfig: storetypes.TransientGasConfig(), 143 } 144 } 145 146 // WithContext returns a Context with an updated context.Context. 147 func (c Context) WithContext(ctx context.Context) Context { 148 c.baseCtx = ctx 149 return c 150 } 151 152 // WithMultiStore returns a Context with an updated MultiStore. 153 func (c Context) WithMultiStore(ms storetypes.MultiStore) Context { 154 c.ms = ms 155 return c 156 } 157 158 // WithBlockHeader returns a Context with an updated CometBFT block header in UTC time. 159 func (c Context) WithBlockHeader(header cmtproto.Header) Context { 160 // https://github.com/gogo/protobuf/issues/519 161 header.Time = header.Time.UTC() 162 c.header = header 163 return c 164 } 165 166 // WithHeaderHash returns a Context with an updated CometBFT block header hash. 167 func (c Context) WithHeaderHash(hash []byte) Context { 168 temp := make([]byte, len(hash)) 169 copy(temp, hash) 170 171 c.headerHash = temp 172 return c 173 } 174 175 // WithBlockTime returns a Context with an updated CometBFT block header time in UTC with no monotonic component. 176 // Stripping the monotonic component is for time equality. 177 func (c Context) WithBlockTime(newTime time.Time) Context { 178 newHeader := c.BlockHeader() 179 // https://github.com/gogo/protobuf/issues/519 180 newHeader.Time = newTime.Round(0).UTC() 181 return c.WithBlockHeader(newHeader) 182 } 183 184 // WithProposer returns a Context with an updated proposer consensus address. 185 func (c Context) WithProposer(addr ConsAddress) Context { 186 newHeader := c.BlockHeader() 187 newHeader.ProposerAddress = addr.Bytes() 188 return c.WithBlockHeader(newHeader) 189 } 190 191 // WithBlockHeight returns a Context with an updated block height. 192 func (c Context) WithBlockHeight(height int64) Context { 193 newHeader := c.BlockHeader() 194 newHeader.Height = height 195 return c.WithBlockHeader(newHeader) 196 } 197 198 // WithChainID returns a Context with an updated chain identifier. 199 func (c Context) WithChainID(chainID string) Context { 200 c.chainID = chainID 201 return c 202 } 203 204 // WithTxBytes returns a Context with an updated txBytes. 205 func (c Context) WithTxBytes(txBytes []byte) Context { 206 c.txBytes = txBytes 207 return c 208 } 209 210 // WithLogger returns a Context with an updated logger. 211 func (c Context) WithLogger(logger log.Logger) Context { 212 c.logger = logger 213 return c 214 } 215 216 // WithVoteInfos returns a Context with an updated consensus VoteInfo. 217 func (c Context) WithVoteInfos(voteInfo []abci.VoteInfo) Context { 218 c.voteInfo = voteInfo 219 return c 220 } 221 222 // WithGasMeter returns a Context with an updated transaction GasMeter. 223 func (c Context) WithGasMeter(meter storetypes.GasMeter) Context { 224 c.gasMeter = meter 225 return c 226 } 227 228 // WithBlockGasMeter returns a Context with an updated block GasMeter 229 func (c Context) WithBlockGasMeter(meter storetypes.GasMeter) Context { 230 c.blockGasMeter = meter 231 return c 232 } 233 234 // WithKVGasConfig returns a Context with an updated gas configuration for 235 // the KVStore 236 func (c Context) WithKVGasConfig(gasConfig storetypes.GasConfig) Context { 237 c.kvGasConfig = gasConfig 238 return c 239 } 240 241 // WithTransientKVGasConfig returns a Context with an updated gas configuration for 242 // the transient KVStore 243 func (c Context) WithTransientKVGasConfig(gasConfig storetypes.GasConfig) Context { 244 c.transientKVGasConfig = gasConfig 245 return c 246 } 247 248 // WithIsCheckTx enables or disables CheckTx value for verifying transactions and returns an updated Context 249 func (c Context) WithIsCheckTx(isCheckTx bool) Context { 250 c.checkTx = isCheckTx 251 c.execMode = ExecModeCheck 252 return c 253 } 254 255 // WithIsRecheckTx called with true will also set true on checkTx in order to 256 // enforce the invariant that if recheckTx = true then checkTx = true as well. 257 func (c Context) WithIsReCheckTx(isRecheckTx bool) Context { 258 if isRecheckTx { 259 c.checkTx = true 260 } 261 c.recheckTx = isRecheckTx 262 c.execMode = ExecModeReCheck 263 return c 264 } 265 266 // WithIsSigverifyTx called with true will sigverify in auth module 267 func (c Context) WithIsSigverifyTx(isSigverifyTx bool) Context { 268 c.sigverifyTx = isSigverifyTx 269 return c 270 } 271 272 // WithExecMode returns a Context with an updated ExecMode. 273 func (c Context) WithExecMode(m ExecMode) Context { 274 c.execMode = m 275 return c 276 } 277 278 // WithMinGasPrices returns a Context with an updated minimum gas price value 279 func (c Context) WithMinGasPrices(gasPrices DecCoins) Context { 280 c.minGasPrice = gasPrices 281 return c 282 } 283 284 // WithConsensusParams returns a Context with an updated consensus params 285 func (c Context) WithConsensusParams(params cmtproto.ConsensusParams) Context { 286 c.consParams = params 287 return c 288 } 289 290 // WithEventManager returns a Context with an updated event manager 291 func (c Context) WithEventManager(em EventManagerI) Context { 292 c.eventManager = em 293 return c 294 } 295 296 // WithPriority returns a Context with an updated tx priority 297 func (c Context) WithPriority(p int64) Context { 298 c.priority = p 299 return c 300 } 301 302 // WithStreamingManager returns a Context with an updated streaming manager 303 func (c Context) WithStreamingManager(sm storetypes.StreamingManager) Context { 304 c.streamingManager = sm 305 return c 306 } 307 308 // WithCometInfo returns a Context with an updated comet info 309 func (c Context) WithCometInfo(cometInfo comet.BlockInfo) Context { 310 c.cometInfo = cometInfo 311 return c 312 } 313 314 // WithHeaderInfo returns a Context with an updated header info 315 func (c Context) WithHeaderInfo(headerInfo header.Info) Context { 316 // Settime to UTC 317 headerInfo.Time = headerInfo.Time.UTC() 318 c.headerInfo = headerInfo 319 return c 320 } 321 322 // TODO: remove??? 323 func (c Context) IsZero() bool { 324 return c.ms == nil 325 } 326 327 func (c Context) WithValue(key, value interface{}) Context { 328 c.baseCtx = context.WithValue(c.baseCtx, key, value) 329 return c 330 } 331 332 func (c Context) Value(key interface{}) interface{} { 333 if key == SdkContextKey { 334 return c 335 } 336 337 return c.baseCtx.Value(key) 338 } 339 340 // ---------------------------------------------------------------------------- 341 // Store / Caching 342 // ---------------------------------------------------------------------------- 343 344 // KVStore fetches a KVStore from the MultiStore. 345 func (c Context) KVStore(key storetypes.StoreKey) storetypes.KVStore { 346 return gaskv.NewStore(c.ms.GetKVStore(key), c.gasMeter, c.kvGasConfig) 347 } 348 349 // TransientStore fetches a TransientStore from the MultiStore. 350 func (c Context) TransientStore(key storetypes.StoreKey) storetypes.KVStore { 351 return gaskv.NewStore(c.ms.GetKVStore(key), c.gasMeter, c.transientKVGasConfig) 352 } 353 354 // CacheContext returns a new Context with the multi-store cached and a new 355 // EventManager. The cached context is written to the context when writeCache 356 // is called. Note, events are automatically emitted on the parent context's 357 // EventManager when the caller executes the write. 358 func (c Context) CacheContext() (cc Context, writeCache func()) { 359 cms := c.ms.CacheMultiStore() 360 cc = c.WithMultiStore(cms).WithEventManager(NewEventManager()) 361 362 writeCache = func() { 363 c.EventManager().EmitEvents(cc.EventManager().Events()) 364 cms.Write() 365 } 366 367 return cc, writeCache 368 } 369 370 var ( 371 _ context.Context = Context{} 372 _ storetypes.Context = Context{} 373 ) 374 375 // ContextKey defines a type alias for a stdlib Context key. 376 type ContextKey string 377 378 // SdkContextKey is the key in the context.Context which holds the sdk.Context. 379 const SdkContextKey ContextKey = "sdk-context" 380 381 // WrapSDKContext returns a stdlib context.Context with the provided sdk.Context's internal 382 // context as a value. It is useful for passing an sdk.Context through methods that take a 383 // stdlib context.Context parameter such as generated gRPC methods. To get the original 384 // sdk.Context back, call UnwrapSDKContext. 385 // 386 // Deprecated: there is no need to wrap anymore as the Cosmos SDK context implements context.Context. 387 func WrapSDKContext(ctx Context) context.Context { 388 return ctx 389 } 390 391 // UnwrapSDKContext retrieves a Context from a context.Context instance 392 // attached with WrapSDKContext. It panics if a Context was not properly 393 // attached 394 func UnwrapSDKContext(ctx context.Context) Context { 395 if sdkCtx, ok := ctx.(Context); ok { 396 return sdkCtx 397 } 398 return ctx.Value(SdkContextKey).(Context) 399 }