github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/sdk/context.go (about)

     1  package sdk
     2  
     3  import (
     4  	"context"
     5  	"log/slog"
     6  	"time"
     7  
     8  	"github.com/gnolang/gno/tm2/pkg/amino"
     9  	abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
    10  	"github.com/gnolang/gno/tm2/pkg/store"
    11  	"github.com/gnolang/gno/tm2/pkg/store/gas"
    12  )
    13  
    14  /*
    15  Context is a mostly immutable object contains all information needed to process
    16  a request.
    17  
    18  It contains a context.Context object inside if you want to use that, but please
    19  do not over-use it. We try to keep all data structured and standard additions
    20  here would be better just to add to the Context struct
    21  */
    22  type Context struct {
    23  	ctx           context.Context
    24  	mode          RunTxMode
    25  	ms            store.MultiStore
    26  	header        abci.Header
    27  	chainID       string
    28  	txBytes       []byte
    29  	logger        *slog.Logger
    30  	voteInfo      []abci.VoteInfo
    31  	gasMeter      store.GasMeter // XXX make passthroughGasMeter w/ blockGasMeter?
    32  	blockGasMeter store.GasMeter
    33  	minGasPrices  []GasPrice
    34  	consParams    *abci.ConsensusParams
    35  	eventLogger   *EventLogger
    36  }
    37  
    38  // Proposed rename, not done to avoid API breakage
    39  type Request = Context
    40  
    41  // Read-only accessors
    42  func (c Context) Context() context.Context      { return c.ctx }
    43  func (c Context) Mode() RunTxMode               { return c.mode }
    44  func (c Context) MultiStore() store.MultiStore  { return c.ms }
    45  func (c Context) BlockHeight() int64            { return c.header.GetHeight() }
    46  func (c Context) BlockTime() time.Time          { return c.header.GetTime() }
    47  func (c Context) ChainID() string               { return c.chainID }
    48  func (c Context) TxBytes() []byte               { return c.txBytes }
    49  func (c Context) Logger() *slog.Logger          { return c.logger }
    50  func (c Context) VoteInfos() []abci.VoteInfo    { return c.voteInfo }
    51  func (c Context) GasMeter() store.GasMeter      { return c.gasMeter }
    52  func (c Context) BlockGasMeter() store.GasMeter { return c.blockGasMeter }
    53  func (c Context) IsCheckTx() bool               { return c.mode == RunTxModeCheck }
    54  func (c Context) MinGasPrices() []GasPrice      { return c.minGasPrices }
    55  func (c Context) EventLogger() *EventLogger     { return c.eventLogger }
    56  
    57  // clone the header before returning
    58  func (c Context) BlockHeader() abci.Header {
    59  	msg := amino.DeepCopy(&c.header).(*abci.Header)
    60  	return *msg
    61  }
    62  
    63  func (c Context) ConsensusParams() *abci.ConsensusParams {
    64  	return amino.DeepCopy(c.consParams).(*abci.ConsensusParams)
    65  }
    66  
    67  // create a new context
    68  func NewContext(mode RunTxMode, ms store.MultiStore, header abci.Header, logger *slog.Logger) Context {
    69  	if header.GetChainID() == "" {
    70  		panic("header chain id cannot be empty")
    71  	}
    72  	return Context{
    73  		ctx:          context.Background(),
    74  		mode:         mode,
    75  		ms:           ms,
    76  		header:       header,
    77  		chainID:      header.GetChainID(),
    78  		logger:       logger,
    79  		gasMeter:     store.NewInfiniteGasMeter(),
    80  		minGasPrices: nil,
    81  		eventLogger:  NewEventLogger(),
    82  	}
    83  }
    84  
    85  func (c Context) WithContext(ctx context.Context) Context {
    86  	c.ctx = ctx
    87  	return c
    88  }
    89  
    90  func (c Context) WithMode(mode RunTxMode) Context {
    91  	c.mode = mode
    92  	return c
    93  }
    94  
    95  func (c Context) WithMultiStore(ms store.MultiStore) Context {
    96  	c.ms = ms
    97  	return c
    98  }
    99  
   100  func (c Context) WithBlockHeader(header abci.Header) Context {
   101  	c.header = header
   102  	return c
   103  }
   104  
   105  func (c Context) WithChainID(chainID string) Context {
   106  	c.chainID = chainID
   107  	return c
   108  }
   109  
   110  func (c Context) WithTxBytes(txBytes []byte) Context {
   111  	c.txBytes = txBytes
   112  	return c
   113  }
   114  
   115  func (c Context) WithLogger(logger *slog.Logger) Context {
   116  	c.logger = logger
   117  	return c
   118  }
   119  
   120  func (c Context) WithVoteInfos(voteInfo []abci.VoteInfo) Context {
   121  	c.voteInfo = voteInfo
   122  	return c
   123  }
   124  
   125  func (c Context) WithGasMeter(meter store.GasMeter) Context {
   126  	c.gasMeter = meter
   127  	return c
   128  }
   129  
   130  func (c Context) WithBlockGasMeter(meter store.GasMeter) Context {
   131  	c.blockGasMeter = meter
   132  	return c
   133  }
   134  
   135  func (c Context) WithMinGasPrices(gasPrices []GasPrice) Context {
   136  	c.minGasPrices = gasPrices
   137  	return c
   138  }
   139  
   140  func (c Context) WithConsensusParams(params *abci.ConsensusParams) Context {
   141  	c.consParams = params
   142  	return c
   143  }
   144  
   145  func (c Context) WithEventLogger(em *EventLogger) Context {
   146  	c.eventLogger = em
   147  	return c
   148  }
   149  
   150  // WithValue is deprecated, provided for backwards compatibility
   151  // Please use
   152  //
   153  //	ctx = ctx.WithContext(context.WithValue(ctx.Context(), key, false))
   154  //
   155  // instead of
   156  //
   157  //	ctx = ctx.WithValue(key, false)
   158  //
   159  // NOTE: why?
   160  func (c Context) WithValue(key, value interface{}) Context {
   161  	c.ctx = context.WithValue(c.ctx, key, value)
   162  	return c
   163  }
   164  
   165  // Value is deprecated, provided for backwards compatibility
   166  // Please use
   167  //
   168  //	ctx.Context().Value(key)
   169  //
   170  // instead of
   171  //
   172  //	ctx.Value(key)
   173  //
   174  // NOTE: why?
   175  func (c Context) Value(key interface{}) interface{} {
   176  	return c.ctx.Value(key)
   177  }
   178  
   179  // ----------------------------------------------------------------------------
   180  // Store / Caching
   181  // ----------------------------------------------------------------------------
   182  
   183  // Store fetches a Store from the MultiStore, but wrapped for gas calculation.
   184  func (c Context) Store(key store.StoreKey) store.Store {
   185  	return gas.New(c.MultiStore().GetStore(key), c.GasMeter(), store.DefaultGasConfig())
   186  }
   187  
   188  // CacheContext returns a new Context with the multi-store cached and a new
   189  // EventLogger . The cached context is written to the context when writeCache
   190  // is called.
   191  // XXX remove?
   192  func (c Context) CacheContext() (cc Context, writeCache func()) {
   193  	cms := c.MultiStore().MultiCacheWrap()
   194  	cc = c.WithMultiStore(cms).WithEventLogger(NewEventLogger())
   195  	return cc, cms.MultiWrite
   196  }
   197  
   198  func (c Context) IsZero() bool {
   199  	return c.ms == nil
   200  }