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  }