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  }