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 }