github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/types/context.go (about) 1 package types 2 3 import ( 4 "context" 5 "sync" 6 "time" 7 8 "github.com/fibonacci-chain/fbc/libs/system/trace" 9 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 10 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 11 "github.com/gogo/protobuf/proto" 12 13 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/gaskv" 14 stypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types" 15 ) 16 17 /* 18 Context is an immutable object contains all information needed to 19 process a request. 20 21 It contains a context.Context object inside if you want to use that, 22 but please do not over-use it. We try to keep all data structured 23 and standard additions here would be better just to add to the Context struct 24 */ 25 type Context struct { 26 ctx context.Context 27 ms MultiStore 28 header *abci.Header 29 chainID string 30 from string 31 txBytes []byte 32 logger log.Logger 33 voteInfo []abci.VoteInfo 34 gasMeter GasMeter 35 blockGasMeter GasMeter 36 isDeliver bool 37 checkTx bool 38 recheckTx bool // if recheckTx == true, then checkTx must also be true 39 wrappedCheckTx bool // if wrappedCheckTx == true, then checkTx must also be true 40 traceTx bool // traceTx is set true for trace tx and its predesessors , traceTx was set in app.beginBlockForTrace() 41 traceTxLog bool // traceTxLog is used to create trace logger for evm , traceTxLog is set to true when only tracing target tx (its predesessors will set false), traceTxLog is set before runtx 42 traceTxConfigBytes []byte // traceTxConfigBytes is used to save traceTxConfig, passed from api to x/evm 43 minGasPrice DecCoins 44 consParams *abci.ConsensusParams 45 eventManager *EventManager 46 accountNonce uint64 47 cache *Cache 48 trc *trace.Tracer 49 accountCache *AccountCache 50 paraMsg *ParaMsg 51 // txCount uint32 52 overridesBytes []byte // overridesBytes is used to save overrides info, passed from ethCall to x/evm 53 watcher *TxWatcher 54 feesplitInfo *FeeSplitInfo 55 } 56 57 // Proposed rename, not done to avoid API breakage 58 type Request = Context 59 60 // Read-only accessors 61 func (c *Context) Context() context.Context { return c.ctx } 62 func (c *Context) MultiStore() MultiStore { return c.ms } 63 func (c *Context) BlockHeight() int64 { 64 if c.header == nil { 65 return 0 66 } 67 return c.header.Height 68 } 69 func (c *Context) BlockTime() time.Time { 70 if c.header == nil { 71 return time.Time{} 72 } 73 return c.header.Time 74 } 75 func (c *Context) ChainID() string { return c.chainID } 76 func (c *Context) From() string { return c.from } 77 func (c *Context) TxBytes() []byte { return c.txBytes } 78 func (c *Context) Logger() log.Logger { return c.logger } 79 func (c *Context) VoteInfos() []abci.VoteInfo { return c.voteInfo } 80 func (c *Context) GasMeter() GasMeter { return c.gasMeter } 81 func (c *Context) BlockGasMeter() GasMeter { return c.blockGasMeter } 82 83 func (c *Context) IsDeliver() bool { 84 return c.isDeliver 85 } 86 87 func (c *Context) UseParamCache() bool { 88 return c.isDeliver || (c.paraMsg != nil && !c.paraMsg.HaveCosmosTxInBlock) || c.checkTx 89 } 90 91 func (c *Context) IsCheckTx() bool { return c.checkTx } 92 func (c *Context) IsReCheckTx() bool { return c.recheckTx } 93 func (c *Context) IsTraceTx() bool { return c.traceTx } 94 func (c *Context) IsTraceTxLog() bool { return c.traceTxLog } 95 func (c *Context) TraceTxLogConfig() []byte { return c.traceTxConfigBytes } 96 func (c *Context) IsWrappedCheckTx() bool { return c.wrappedCheckTx } 97 func (c *Context) MinGasPrices() DecCoins { return c.minGasPrice } 98 func (c *Context) EventManager() *EventManager { return c.eventManager } 99 func (c *Context) AccountNonce() uint64 { return c.accountNonce } 100 func (c *Context) AnteTracer() *trace.Tracer { return c.trc } 101 func (c *Context) Cache() *Cache { 102 return c.cache 103 } 104 func (c Context) ParaMsg() *ParaMsg { 105 return c.paraMsg 106 } 107 108 func (c Context) GetFeeSplitInfo() *FeeSplitInfo { 109 if c.feesplitInfo == nil { 110 c.feesplitInfo = &FeeSplitInfo{} 111 } 112 return c.feesplitInfo 113 } 114 115 func (c *Context) EnableAccountCache() { c.accountCache = &AccountCache{} } 116 func (c *Context) DisableAccountCache() { c.accountCache = nil } 117 118 func (c *Context) GetFromAccountCacheData() interface{} { 119 if c.accountCache == nil { 120 return nil 121 } 122 return c.accountCache.FromAcc 123 } 124 125 func (c *Context) GetFromAccountCacheGas() Gas { 126 if c.accountCache == nil { 127 return 0 128 } 129 return c.accountCache.FromAccGotGas 130 } 131 132 func (c *Context) GetToAccountCacheData() interface{} { 133 if c.accountCache == nil { 134 return nil 135 } 136 return c.accountCache.ToAcc 137 } 138 139 func (c *Context) GetToAccountCacheGas() Gas { 140 if c.accountCache == nil { 141 return 0 142 } 143 return c.accountCache.ToAccGotGas 144 } 145 146 func (c *Context) OverrideBytes() []byte { 147 return c.overridesBytes 148 } 149 150 func (c *Context) UpdateFromAccountCache(fromAcc interface{}, fromAccGettedGas Gas) { 151 if c.accountCache != nil { 152 c.accountCache.FromAcc = fromAcc 153 c.accountCache.FromAccGotGas = fromAccGettedGas 154 } 155 } 156 157 func (c *Context) UpdateToAccountCache(toAcc interface{}, toAccGotGas Gas) { 158 if c.accountCache != nil { 159 c.accountCache.ToAcc = toAcc 160 c.accountCache.ToAccGotGas = toAccGotGas 161 } 162 } 163 164 func (c *Context) BlockProposerAddress() []byte { 165 if c.header == nil { 166 return nil 167 } 168 return c.header.ProposerAddress 169 } 170 171 // BlockHeader clone the header before returning 172 func (c *Context) BlockHeader() abci.Header { 173 if c.header == nil { 174 return abci.Header{} 175 } 176 var msg = proto.Clone(c.header).(*abci.Header) 177 return *msg 178 } 179 180 func (c *Context) ConsensusParams() *abci.ConsensusParams { 181 return proto.Clone(c.consParams).(*abci.ConsensusParams) 182 } 183 184 ////TxCount 185 //func (c *Context) TxCount() uint32 { 186 // return c.txCount 187 //} 188 189 // NewContext create a new context 190 func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, logger log.Logger) Context { 191 // https://github.com/gogo/protobuf/issues/519 192 header.Time = header.Time.UTC() 193 return Context{ 194 ctx: context.Background(), 195 ms: ms, 196 header: &header, 197 chainID: header.ChainID, 198 checkTx: isCheckTx, 199 logger: logger, 200 gasMeter: stypes.NewInfiniteGasMeter(), 201 minGasPrice: DecCoins{}, 202 eventManager: NewEventManager(), 203 watcher: &TxWatcher{EmptyWatcher{}}, 204 } 205 } 206 207 func (c *Context) SetDeliver() *Context { 208 c.isDeliver = true 209 return c 210 } 211 212 // TODO: remove??? 213 func (c *Context) IsZero() bool { 214 return c.ms == nil 215 } 216 217 func (c *Context) SetGasMeter(meter GasMeter) *Context { 218 c.gasMeter = meter 219 return c 220 } 221 222 func (c *Context) SetMultiStore(ms MultiStore) *Context { 223 c.ms = ms 224 return c 225 } 226 227 func (c *Context) SetEventManager(em *EventManager) *Context { 228 c.eventManager = em 229 return c 230 } 231 232 func (c *Context) SetAccountNonce(nonce uint64) *Context { 233 c.accountNonce = nonce 234 return c 235 } 236 237 func (c *Context) SetCache(cache *Cache) *Context { 238 c.cache = cache 239 return c 240 } 241 242 func (c *Context) SetFrom(from string) *Context { 243 c.from = from 244 return c 245 } 246 247 func (c *Context) SetAnteTracer(trc *trace.Tracer) *Context { 248 c.trc = trc 249 return c 250 } 251 252 func (c *Context) SetBlockGasMeter(meter GasMeter) *Context { 253 c.blockGasMeter = meter 254 return c 255 } 256 257 func (c *Context) SetBlockHeader(header abci.Header) *Context { 258 // https://github.com/gogo/protobuf/issues/519 259 header.Time = header.Time.UTC() 260 c.header = &header 261 return c 262 } 263 264 func (c *Context) SetBlockHeight(height int64) *Context { 265 newHeader := c.BlockHeader() 266 newHeader.Height = height 267 c.SetBlockHeader(newHeader) 268 return c 269 } 270 271 func (c *Context) SetBlockTime(newTime time.Time) *Context { 272 newHeader := c.BlockHeader() 273 // https://github.com/gogo/protobuf/issues/519 274 newHeader.Time = newTime.UTC() 275 c.SetBlockHeader(newHeader) 276 return c 277 } 278 279 func (c *Context) SetContext(ctx context.Context) *Context { 280 c.ctx = ctx 281 return c 282 } 283 284 func (c *Context) SetChainID(chainID string) *Context { 285 c.chainID = chainID 286 return c 287 } 288 289 func (c *Context) SetConsensusParams(params *abci.ConsensusParams) *Context { 290 c.consParams = params 291 return c 292 } 293 294 func (c *Context) SetMinGasPrices(gasPrices DecCoins) *Context { 295 c.minGasPrice = gasPrices 296 return c 297 } 298 299 func (c *Context) SetIsCheckTx(isCheckTx bool) *Context { 300 c.checkTx = isCheckTx 301 return c 302 } 303 304 func (c *Context) SetIsDeliverTx(isDeliverTx bool) *Context { 305 c.isDeliver = isDeliverTx 306 return c 307 } 308 309 // SetIsWrappedCheckTx called with true will also set true on checkTx in order to 310 // enforce the invariant that if recheckTx = true then checkTx = true as well. 311 func (c *Context) SetIsWrappedCheckTx(isWrappedCheckTx bool) *Context { 312 if isWrappedCheckTx { 313 c.checkTx = true 314 } 315 c.wrappedCheckTx = isWrappedCheckTx 316 return c 317 } 318 319 // SetIsReCheckTx called with true will also set true on checkTx in order to 320 // enforce the invariant that if recheckTx = true then checkTx = true as well. 321 func (c *Context) SetIsReCheckTx(isRecheckTx bool) *Context { 322 if isRecheckTx { 323 c.checkTx = true 324 } 325 c.recheckTx = isRecheckTx 326 return c 327 } 328 329 func (c *Context) SetIsTraceTxLog(isTraceTxLog bool) *Context { 330 if isTraceTxLog { 331 c.checkTx = true 332 } 333 c.traceTxLog = isTraceTxLog 334 return c 335 } 336 337 func (c *Context) SetIsTraceTx(isTraceTx bool) *Context { 338 if isTraceTx { 339 c.checkTx = true 340 } 341 c.traceTx = isTraceTx 342 return c 343 } 344 345 func (c *Context) SetProposer(addr ConsAddress) *Context { 346 newHeader := c.BlockHeader() 347 newHeader.ProposerAddress = addr.Bytes() 348 c.SetBlockHeader(newHeader) 349 return c 350 } 351 352 func (c *Context) SetTraceTxLogConfig(traceLogConfigBytes []byte) *Context { 353 c.traceTxConfigBytes = traceLogConfigBytes 354 return c 355 } 356 357 func (c *Context) SetTxBytes(txBytes []byte) *Context { 358 c.txBytes = txBytes 359 return c 360 } 361 362 func (c *Context) SetLogger(logger log.Logger) *Context { 363 c.logger = logger 364 return c 365 } 366 367 func (c *Context) SetParaMsg(m *ParaMsg) *Context { 368 c.paraMsg = m 369 return c 370 } 371 372 func (c *Context) SetFeeSplitInfo(f *FeeSplitInfo) *Context { 373 c.feesplitInfo = f 374 return c 375 } 376 377 func (c *Context) SetVoteInfos(voteInfo []abci.VoteInfo) *Context { 378 c.voteInfo = voteInfo 379 return c 380 } 381 382 func (c *Context) SetOverrideBytes(b []byte) *Context { 383 c.overridesBytes = b 384 return c 385 } 386 387 var emptyWatcher IWatcher = EmptyWatcher{} 388 389 func (c *Context) ResetWatcher() { 390 c.watcher = &TxWatcher{emptyWatcher} 391 } 392 393 func (c *Context) SetWatcher(w IWatcher) { 394 if c.watcher == nil { 395 c.watcher = &TxWatcher{EmptyWatcher{}} 396 return 397 } 398 c.watcher.IWatcher = w 399 } 400 401 func (c *Context) GetWatcher() IWatcher { 402 if c.watcher == nil { 403 return emptyWatcher 404 } 405 return c.watcher.IWatcher 406 } 407 408 //func (c *Context) SetTxCount(count uint32) *Context { 409 // c.txCount = count 410 // return c 411 //} 412 413 // ---------------------------------------------------------------------------- 414 // Store / Caching 415 // ---------------------------------------------------------------------------- 416 417 // KVStore fetches a KVStore from the MultiStore. 418 func (c *Context) KVStore(key StoreKey) KVStore { 419 return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.KVGasConfig()) 420 } 421 422 var gasKvPool = &sync.Pool{ 423 New: func() interface{} { 424 return &gaskv.Store{} 425 }, 426 } 427 428 // GetReusableKVStore fetches a KVStore from the MultiStore than can be reused. 429 // you must call ReturnKVStore() after you are done with the KVStore. 430 func (c *Context) GetReusableKVStore(key StoreKey) KVStore { 431 gaskvs := gasKvPool.Get().(*gaskv.Store) 432 return gaskv.ResetStore(gaskvs, c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.KVGasConfig()) 433 } 434 435 // ReturnKVStore returns a KVStore than from GetReusableKVStore. 436 func (_ *Context) ReturnKVStore(store KVStore) { 437 gasKvPool.Put(store) 438 } 439 440 // TransientStore fetches a TransientStore from the MultiStore. 441 func (c *Context) TransientStore(key StoreKey) KVStore { 442 return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.TransientGasConfig()) 443 } 444 445 // CacheContext returns a new Context with the multi-store cached and a new 446 // EventManager. The cached context is written to the context when writeCache 447 // is called. 448 func (c *Context) CacheContext() (cc Context, writeCache func()) { 449 cms := c.MultiStore().CacheMultiStore() 450 cc = *c 451 cc.SetMultiStore(cms) 452 cc.SetEventManager(NewEventManager()) 453 writeCache = cms.Write 454 return 455 } 456 457 func (c Context) WithBlockTime(newTime time.Time) Context { 458 newHeader := c.BlockHeader() 459 // https://github.com/gogo/protobuf/issues/519 460 newHeader.Time = newTime.UTC() 461 c.SetBlockHeader(newHeader) 462 return c 463 } 464 465 func (c Context) WithBlockHeight(height int64) Context { 466 newHeader := c.BlockHeader() 467 newHeader.Height = height 468 c.SetBlockHeader(newHeader) 469 return c 470 } 471 472 func (c Context) WithIsCheckTx(isCheckTx bool) Context { 473 c.checkTx = isCheckTx 474 return c 475 } 476 477 // WithIsReCheckTx called with true will also set true on checkTx in order to 478 // enforce the invariant that if recheckTx = true then checkTx = true as well. 479 func (c Context) WithIsReCheckTx(isRecheckTx bool) Context { 480 if isRecheckTx { 481 c.checkTx = true 482 } 483 c.recheckTx = isRecheckTx 484 return c 485 } 486 487 func (c Context) WithIsTraceTxLog(isTraceTxLog bool) Context { 488 if isTraceTxLog { 489 c.checkTx = true 490 } 491 c.traceTxLog = isTraceTxLog 492 return c 493 } 494 495 // WithValue is deprecated, provided for backwards compatibility 496 // Please use 497 // 498 // ctx = ctx.WithContext(context.WithValue(ctx.Context(), key, false)) 499 // 500 // instead of 501 // 502 // ctx = ctx.WithValue(key, false) 503 func (c Context) WithValue(key, value interface{}) Context { 504 c.ctx = context.WithValue(c.ctx, key, value) 505 return c 506 } 507 508 // Value is deprecated, provided for backwards compatibility 509 // Please use 510 // 511 // ctx.Context().Value(key) 512 // 513 // instead of 514 // 515 // ctx.Value(key) 516 func (c Context) Value(key interface{}) interface{} { 517 return c.ctx.Value(key) 518 } 519 520 type AccountCache struct { 521 FromAcc interface{} // must be auth.Account 522 ToAcc interface{} // must be auth.Account 523 FromAccGotGas Gas 524 ToAccGotGas Gas 525 } 526 527 // ContextKey defines a type alias for a stdlib Context key. 528 type ContextKey string 529 530 // SdkContextKey is the key in the context.Context which holds the sdk.Context. 531 const SdkContextKey ContextKey = "sdk-context" 532 533 // WrapSDKContext returns a stdlib context.Context with the provided sdk.Context's internal 534 // context as a value. It is useful for passing an sdk.Context through methods that take a 535 // stdlib context.Context parameter such as generated gRPC methods. To get the original 536 // sdk.Context back, call UnwrapSDKContext. 537 func WrapSDKContext(ctx Context) context.Context { 538 return context.WithValue(ctx.ctx, SdkContextKey, ctx) 539 } 540 541 // UnwrapSDKContext retrieves a Context from a context.Context instance 542 // attached with WrapSDKContext. It panics if a Context was not properly 543 // attached 544 func UnwrapSDKContext(ctx context.Context) Context { 545 return ctx.Value(SdkContextKey).(Context) 546 }