github.com/Finschia/finschia-sdk@v0.48.1/types/context.go (about) 1 package types 2 3 import ( 4 "context" 5 "time" 6 7 "github.com/gogo/protobuf/proto" 8 abci "github.com/tendermint/tendermint/abci/types" 9 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 10 11 ocbytes "github.com/Finschia/ostracon/libs/bytes" 12 "github.com/Finschia/ostracon/libs/log" 13 14 "github.com/Finschia/finschia-sdk/store/gaskv" 15 stypes "github.com/Finschia/finschia-sdk/store/types" 16 ) 17 18 /* 19 Context is an immutable object contains all information needed to 20 process a request. 21 22 It contains a context.Context object inside if you want to use that, 23 but please do not over-use it. We try to keep all data structured 24 and standard additions here would be better just to add to the Context struct 25 */ 26 type Context struct { 27 ctx context.Context 28 ms MultiStore 29 header tmproto.Header 30 headerHash ocbytes.HexBytes 31 chainID string 32 txBytes []byte 33 logger log.Logger 34 voteInfo []abci.VoteInfo 35 gasMeter GasMeter 36 blockGasMeter GasMeter 37 checkTx bool 38 recheckTx bool // if recheckTx == true, then checkTx must also be true 39 minGasPrice DecCoins 40 consParams *abci.ConsensusParams 41 eventManager *EventManager 42 } 43 44 // Proposed rename, not done to avoid API breakage 45 type Request = Context 46 47 // Read-only accessors 48 func (c Context) Context() context.Context { return c.ctx } 49 func (c Context) MultiStore() MultiStore { return c.ms } 50 func (c Context) BlockHeight() int64 { return c.header.Height } 51 func (c Context) BlockTime() time.Time { return c.header.Time } 52 func (c Context) ChainID() string { return c.chainID } 53 func (c Context) TxBytes() []byte { return c.txBytes } 54 func (c Context) Logger() log.Logger { return c.logger } 55 func (c Context) VoteInfos() []abci.VoteInfo { return c.voteInfo } 56 func (c Context) GasMeter() GasMeter { return c.gasMeter } 57 func (c Context) BlockGasMeter() GasMeter { return c.blockGasMeter } 58 func (c Context) IsCheckTx() bool { return c.checkTx } 59 func (c Context) IsReCheckTx() bool { return c.recheckTx } 60 func (c Context) MinGasPrices() DecCoins { return c.minGasPrice } 61 func (c Context) EventManager() *EventManager { return c.eventManager } 62 63 // clone the header before returning 64 func (c Context) BlockHeader() tmproto.Header { 65 msg := proto.Clone(&c.header).(*tmproto.Header) 66 return *msg 67 } 68 69 // HeaderHash returns a copy of the header hash obtained during abci.RequestBeginBlock 70 func (c Context) HeaderHash() ocbytes.HexBytes { 71 hash := make([]byte, len(c.headerHash)) 72 copy(hash, c.headerHash) 73 return hash 74 } 75 76 func (c Context) ConsensusParams() *abci.ConsensusParams { 77 return proto.Clone(c.consParams).(*abci.ConsensusParams) 78 } 79 80 // create a new context 81 func NewContext(ms MultiStore, header tmproto.Header, isCheckTx bool, logger log.Logger) Context { 82 // https://github.com/gogo/protobuf/issues/519 83 header.Time = header.Time.UTC() 84 return Context{ 85 ctx: context.Background(), 86 ms: ms, 87 header: header, 88 chainID: header.ChainID, 89 checkTx: isCheckTx, 90 logger: logger, 91 gasMeter: stypes.NewInfiniteGasMeter(), 92 minGasPrice: DecCoins{}, 93 eventManager: NewEventManager(), 94 } 95 } 96 97 // WithContext returns a Context with an updated context.Context. 98 func (c Context) WithContext(ctx context.Context) Context { 99 c.ctx = ctx 100 return c 101 } 102 103 // WithMultiStore returns a Context with an updated MultiStore. 104 func (c Context) WithMultiStore(ms MultiStore) Context { 105 c.ms = ms 106 return c 107 } 108 109 // WithBlockHeader returns a Context with an updated tendermint block header in UTC time. 110 func (c Context) WithBlockHeader(header tmproto.Header) Context { 111 // https://github.com/gogo/protobuf/issues/519 112 header.Time = header.Time.UTC() 113 c.header = header 114 return c 115 } 116 117 // WithHeaderHash returns a Context with an updated tendermint block header hash. 118 func (c Context) WithHeaderHash(hash []byte) Context { 119 temp := make([]byte, len(hash)) 120 copy(temp, hash) 121 122 c.headerHash = temp 123 return c 124 } 125 126 // WithBlockTime returns a Context with an updated tendermint block header time in UTC time 127 func (c Context) WithBlockTime(newTime time.Time) Context { 128 newHeader := c.BlockHeader() 129 // https://github.com/gogo/protobuf/issues/519 130 newHeader.Time = newTime.UTC() 131 return c.WithBlockHeader(newHeader) 132 } 133 134 // WithProposer returns a Context with an updated proposer consensus address. 135 func (c Context) WithProposer(addr ConsAddress) Context { 136 newHeader := c.BlockHeader() 137 newHeader.ProposerAddress = addr.Bytes() 138 return c.WithBlockHeader(newHeader) 139 } 140 141 // WithBlockHeight returns a Context with an updated block height. 142 func (c Context) WithBlockHeight(height int64) Context { 143 newHeader := c.BlockHeader() 144 newHeader.Height = height 145 return c.WithBlockHeader(newHeader) 146 } 147 148 // WithChainID returns a Context with an updated chain identifier. 149 func (c Context) WithChainID(chainID string) Context { 150 c.chainID = chainID 151 return c 152 } 153 154 // WithTxBytes returns a Context with an updated txBytes. 155 func (c Context) WithTxBytes(txBytes []byte) Context { 156 c.txBytes = txBytes 157 return c 158 } 159 160 // WithLogger returns a Context with an updated logger. 161 func (c Context) WithLogger(logger log.Logger) Context { 162 c.logger = logger 163 return c 164 } 165 166 // WithVoteInfos returns a Context with an updated consensus VoteInfo. 167 func (c Context) WithVoteInfos(voteInfo []abci.VoteInfo) Context { 168 c.voteInfo = voteInfo 169 return c 170 } 171 172 // WithGasMeter returns a Context with an updated transaction GasMeter. 173 func (c Context) WithGasMeter(meter GasMeter) Context { 174 c.gasMeter = meter 175 return c 176 } 177 178 // WithBlockGasMeter returns a Context with an updated block GasMeter 179 func (c Context) WithBlockGasMeter(meter GasMeter) Context { 180 c.blockGasMeter = meter 181 return c 182 } 183 184 // WithIsCheckTx enables or disables CheckTx value for verifying transactions and returns an updated Context 185 func (c Context) WithIsCheckTx(isCheckTx bool) Context { 186 c.checkTx = isCheckTx 187 return c 188 } 189 190 // WithIsRecheckTx called with true will also set true on checkTx in order to 191 // enforce the invariant that if recheckTx = true then checkTx = true as well. 192 func (c Context) WithIsReCheckTx(isRecheckTx bool) Context { 193 if isRecheckTx { 194 c.checkTx = true 195 } 196 c.recheckTx = isRecheckTx 197 return c 198 } 199 200 // WithMinGasPrices returns a Context with an updated minimum gas price value 201 func (c Context) WithMinGasPrices(gasPrices DecCoins) Context { 202 c.minGasPrice = gasPrices 203 return c 204 } 205 206 // WithConsensusParams returns a Context with an updated consensus params 207 func (c Context) WithConsensusParams(params *abci.ConsensusParams) Context { 208 c.consParams = params 209 return c 210 } 211 212 // WithEventManager returns a Context with an updated event manager 213 func (c Context) WithEventManager(em *EventManager) Context { 214 c.eventManager = em 215 return c 216 } 217 218 // TODO: remove??? 219 func (c Context) IsZero() bool { 220 return c.ms == nil 221 } 222 223 // WithValue is deprecated, provided for backwards compatibility 224 // Please use 225 // 226 // ctx = ctx.WithContext(context.WithValue(ctx.Context(), key, false)) 227 // 228 // instead of 229 // 230 // ctx = ctx.WithValue(key, false) 231 func (c Context) WithValue(key, value interface{}) Context { 232 c.ctx = context.WithValue(c.ctx, key, value) 233 return c 234 } 235 236 // Value is deprecated, provided for backwards compatibility 237 // Please use 238 // 239 // ctx.Context().Value(key) 240 // 241 // instead of 242 // 243 // ctx.Value(key) 244 func (c Context) Value(key interface{}) interface{} { 245 return c.ctx.Value(key) 246 } 247 248 // ---------------------------------------------------------------------------- 249 // Store / Caching 250 // ---------------------------------------------------------------------------- 251 252 // KVStore fetches a KVStore from the MultiStore. 253 func (c Context) KVStore(key StoreKey) KVStore { 254 return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.KVGasConfig()) 255 } 256 257 // CacheContext returns a new Context with the multi-store cached and a new 258 // EventManager. The cached context is written to the context when writeCache 259 // is called. 260 func (c Context) CacheContext() (cc Context, writeCache func()) { 261 cms := c.MultiStore().CacheMultiStore() 262 cc = c.WithMultiStore(cms).WithEventManager(NewEventManager()) 263 return cc, cms.Write 264 } 265 266 // ContextKey defines a type alias for a stdlib Context key. 267 type ContextKey string 268 269 // SdkContextKey is the key in the context.Context which holds the sdk.Context. 270 const SdkContextKey ContextKey = "sdk-context" 271 272 // WrapSDKContext returns a stdlib context.Context with the provided sdk.Context's internal 273 // context as a value. It is useful for passing an sdk.Context through methods that take a 274 // stdlib context.Context parameter such as generated gRPC methods. To get the original 275 // sdk.Context back, call UnwrapSDKContext. 276 func WrapSDKContext(ctx Context) context.Context { 277 return context.WithValue(ctx.ctx, SdkContextKey, ctx) 278 } 279 280 // UnwrapSDKContext retrieves a Context from a context.Context instance 281 // attached with WrapSDKContext. It panics if a Context was not properly 282 // attached 283 func UnwrapSDKContext(ctx context.Context) Context { 284 return ctx.Value(SdkContextKey).(Context) 285 }