github.com/line/ostracon@v1.0.10-0.20230328032236-7f20145f065d/abci/client/local_client.go (about) 1 package abcicli 2 3 import ( 4 "github.com/tendermint/tendermint/abci/types" 5 6 ocabci "github.com/line/ostracon/abci/types" 7 "github.com/line/ostracon/libs/service" 8 tmsync "github.com/line/ostracon/libs/sync" 9 ) 10 11 var _ Client = (*localClient)(nil) 12 13 // NOTE: use defer to unlock mutex because Application might panic (e.g., in 14 // case of malicious tx or query). It only makes sense for publicly exposed 15 // methods like CheckTx (/broadcast_tx_* RPC endpoint) or Query (/abci_query 16 // RPC endpoint), but defers are used everywhere for the sake of consistency. 17 type localClient struct { 18 service.BaseService 19 20 // TODO: remove `mtx` to increase concurrency. We could remove it because the app should protect itself. 21 mtx *tmsync.Mutex 22 // CONTRACT: The application should protect itself from concurrency as an abci server. 23 ocabci.Application 24 25 globalCbMtx tmsync.Mutex 26 globalCb GlobalCallback 27 } 28 29 var _ Client = (*localClient)(nil) 30 31 // NewLocalClient creates a local client, which will be directly calling the 32 // methods of the given app. 33 // 34 // Both Async and Sync methods ignore the given context.Context parameter. 35 func NewLocalClient(mtx *tmsync.Mutex, app ocabci.Application) Client { 36 if mtx == nil { 37 mtx = new(tmsync.Mutex) 38 } 39 cli := &localClient{ 40 mtx: mtx, 41 Application: app, 42 } 43 cli.BaseService = *service.NewBaseService(nil, "localClient", cli) 44 return cli 45 } 46 47 func (app *localClient) SetGlobalCallback(globalCb GlobalCallback) { 48 app.globalCbMtx.Lock() 49 defer app.globalCbMtx.Unlock() 50 app.globalCb = globalCb 51 } 52 53 func (app *localClient) GetGlobalCallback() (cb GlobalCallback) { 54 app.globalCbMtx.Lock() 55 defer app.globalCbMtx.Unlock() 56 cb = app.globalCb 57 return cb 58 } 59 60 // TODO: change abci.Application to include Error()? 61 func (app *localClient) Error() error { 62 return nil 63 } 64 65 func (app *localClient) FlushAsync(cb ResponseCallback) *ReqRes { 66 // Do nothing 67 reqRes := NewReqRes(ocabci.ToRequestFlush(), cb) 68 return app.done(reqRes, ocabci.ToResponseFlush()) 69 } 70 71 func (app *localClient) EchoAsync(msg string, cb ResponseCallback) *ReqRes { 72 // NOTE: commented out for performance. delete all after commenting out all `app.mtx` 73 // app.mtx.Lock() 74 // defer app.mtx.Unlock() 75 76 reqRes := NewReqRes(ocabci.ToRequestEcho(msg), cb) 77 return app.done(reqRes, ocabci.ToResponseEcho(msg)) 78 } 79 80 func (app *localClient) InfoAsync(req types.RequestInfo, cb ResponseCallback) *ReqRes { 81 app.mtx.Lock() 82 defer app.mtx.Unlock() 83 84 reqRes := NewReqRes(ocabci.ToRequestInfo(req), cb) 85 res := app.Application.Info(req) 86 return app.done(reqRes, ocabci.ToResponseInfo(res)) 87 } 88 89 func (app *localClient) SetOptionAsync(req types.RequestSetOption, cb ResponseCallback) *ReqRes { 90 app.mtx.Lock() 91 defer app.mtx.Unlock() 92 93 reqRes := NewReqRes(ocabci.ToRequestSetOption(req), cb) 94 res := app.Application.SetOption(req) 95 return app.done(reqRes, ocabci.ToResponseSetOption(res)) 96 } 97 98 func (app *localClient) DeliverTxAsync(req types.RequestDeliverTx, cb ResponseCallback) *ReqRes { 99 app.mtx.Lock() 100 defer app.mtx.Unlock() 101 102 reqRes := NewReqRes(ocabci.ToRequestDeliverTx(req), cb) 103 res := app.Application.DeliverTx(req) 104 return app.done(reqRes, ocabci.ToResponseDeliverTx(res)) 105 } 106 107 func (app *localClient) CheckTxAsync(req types.RequestCheckTx, cb ResponseCallback) *ReqRes { 108 // NOTE: commented out for performance. delete all after commenting out all `app.mtx` 109 // app.mtx.Lock() 110 // defer app.mtx.Unlock() 111 112 reqRes := NewReqRes(ocabci.ToRequestCheckTx(req), cb) 113 114 app.Application.CheckTxAsync(req, func(r ocabci.ResponseCheckTx) { 115 res := ocabci.ToResponseCheckTx(r) 116 app.done(reqRes, res) 117 }) 118 119 return reqRes 120 } 121 122 func (app *localClient) QueryAsync(req types.RequestQuery, cb ResponseCallback) *ReqRes { 123 app.mtx.Lock() 124 defer app.mtx.Unlock() 125 126 reqRes := NewReqRes(ocabci.ToRequestQuery(req), cb) 127 res := app.Application.Query(req) 128 return app.done(reqRes, ocabci.ToResponseQuery(res)) 129 } 130 131 func (app *localClient) CommitAsync(cb ResponseCallback) *ReqRes { 132 app.mtx.Lock() 133 defer app.mtx.Unlock() 134 135 reqRes := NewReqRes(ocabci.ToRequestCommit(), cb) 136 res := app.Application.Commit() 137 return app.done(reqRes, ocabci.ToResponseCommit(res)) 138 } 139 140 func (app *localClient) InitChainAsync(req types.RequestInitChain, cb ResponseCallback) *ReqRes { 141 app.mtx.Lock() 142 defer app.mtx.Unlock() 143 144 reqRes := NewReqRes(ocabci.ToRequestInitChain(req), cb) 145 res := app.Application.InitChain(req) 146 return app.done(reqRes, ocabci.ToResponseInitChain(res)) 147 } 148 149 func (app *localClient) BeginBlockAsync(req ocabci.RequestBeginBlock, cb ResponseCallback) *ReqRes { 150 app.mtx.Lock() 151 defer app.mtx.Unlock() 152 153 reqRes := NewReqRes(ocabci.ToRequestBeginBlock(req), cb) 154 res := app.Application.BeginBlock(req) 155 return app.done(reqRes, ocabci.ToResponseBeginBlock(res)) 156 } 157 158 func (app *localClient) EndBlockAsync(req types.RequestEndBlock, cb ResponseCallback) *ReqRes { 159 app.mtx.Lock() 160 defer app.mtx.Unlock() 161 162 reqRes := NewReqRes(ocabci.ToRequestEndBlock(req), cb) 163 res := app.Application.EndBlock(req) 164 return app.done(reqRes, ocabci.ToResponseEndBlock(res)) 165 } 166 167 func (app *localClient) BeginRecheckTxAsync(req ocabci.RequestBeginRecheckTx, cb ResponseCallback) *ReqRes { 168 // NOTE: commented out for performance. delete all after commenting out all `app.mtx` 169 // app.mtx.Lock() 170 // defer app.mtx.Unlock() 171 172 reqRes := NewReqRes(ocabci.ToRequestBeginRecheckTx(req), cb) 173 res := app.Application.BeginRecheckTx(req) 174 return app.done(reqRes, ocabci.ToResponseBeginRecheckTx(res)) 175 } 176 177 func (app *localClient) EndRecheckTxAsync(req ocabci.RequestEndRecheckTx, cb ResponseCallback) *ReqRes { 178 // NOTE: commented out for performance. delete all after commenting out all `app.mtx` 179 // app.mtx.Lock() 180 // defer app.mtx.Unlock() 181 182 reqRes := NewReqRes(ocabci.ToRequestEndRecheckTx(req), cb) 183 res := app.Application.EndRecheckTx(req) 184 return app.done(reqRes, ocabci.ToResponseEndRecheckTx(res)) 185 } 186 187 func (app *localClient) ListSnapshotsAsync(req types.RequestListSnapshots, cb ResponseCallback) *ReqRes { 188 app.mtx.Lock() 189 defer app.mtx.Unlock() 190 191 reqRes := NewReqRes(ocabci.ToRequestListSnapshots(req), cb) 192 res := app.Application.ListSnapshots(req) 193 return app.done(reqRes, ocabci.ToResponseListSnapshots(res)) 194 } 195 196 func (app *localClient) OfferSnapshotAsync(req types.RequestOfferSnapshot, cb ResponseCallback) *ReqRes { 197 app.mtx.Lock() 198 defer app.mtx.Unlock() 199 200 reqRes := NewReqRes(ocabci.ToRequestOfferSnapshot(req), cb) 201 res := app.Application.OfferSnapshot(req) 202 return app.done(reqRes, ocabci.ToResponseOfferSnapshot(res)) 203 } 204 205 func (app *localClient) LoadSnapshotChunkAsync(req types.RequestLoadSnapshotChunk, cb ResponseCallback) *ReqRes { 206 app.mtx.Lock() 207 defer app.mtx.Unlock() 208 209 reqRes := NewReqRes(ocabci.ToRequestLoadSnapshotChunk(req), cb) 210 res := app.Application.LoadSnapshotChunk(req) 211 return app.done(reqRes, ocabci.ToResponseLoadSnapshotChunk(res)) 212 } 213 214 func (app *localClient) ApplySnapshotChunkAsync(req types.RequestApplySnapshotChunk, cb ResponseCallback) *ReqRes { 215 app.mtx.Lock() 216 defer app.mtx.Unlock() 217 218 reqRes := NewReqRes(ocabci.ToRequestApplySnapshotChunk(req), cb) 219 res := app.Application.ApplySnapshotChunk(req) 220 return app.done(reqRes, ocabci.ToResponseApplySnapshotChunk(res)) 221 } 222 223 // ------------------------------------------------------- 224 func (app *localClient) FlushSync() (*types.ResponseFlush, error) { 225 return &types.ResponseFlush{}, nil 226 } 227 228 func (app *localClient) EchoSync(msg string) (*types.ResponseEcho, error) { 229 // NOTE: commented out for performance. delete all after commenting out all `app.mtx` 230 // app.mtx.Lock() 231 // defer app.mtx.Unlock() 232 233 return &types.ResponseEcho{Message: msg}, nil 234 } 235 236 func (app *localClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, error) { 237 app.mtx.Lock() 238 defer app.mtx.Unlock() 239 240 res := app.Application.Info(req) 241 return &res, nil 242 } 243 244 func (app *localClient) SetOptionSync(req types.RequestSetOption) (*types.ResponseSetOption, error) { 245 app.mtx.Lock() 246 defer app.mtx.Unlock() 247 248 res := app.Application.SetOption(req) 249 return &res, nil 250 } 251 252 func (app *localClient) DeliverTxSync(req types.RequestDeliverTx) (*types.ResponseDeliverTx, error) { 253 app.mtx.Lock() 254 defer app.mtx.Unlock() 255 256 res := app.Application.DeliverTx(req) 257 return &res, nil 258 } 259 260 func (app *localClient) CheckTxSync(req types.RequestCheckTx) (*ocabci.ResponseCheckTx, error) { 261 // NOTE: commented out for performance. delete all after commenting out all `app.mtx` 262 // app.mtx.Lock() 263 // defer app.mtx.Unlock() 264 265 res := app.Application.CheckTxSync(req) 266 return &res, nil 267 } 268 269 func (app *localClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { 270 app.mtx.Lock() 271 defer app.mtx.Unlock() 272 273 res := app.Application.Query(req) 274 return &res, nil 275 } 276 277 func (app *localClient) CommitSync() (*types.ResponseCommit, error) { 278 app.mtx.Lock() 279 defer app.mtx.Unlock() 280 281 res := app.Application.Commit() 282 return &res, nil 283 } 284 285 func (app *localClient) InitChainSync(req types.RequestInitChain) (*types.ResponseInitChain, error) { 286 app.mtx.Lock() 287 defer app.mtx.Unlock() 288 289 res := app.Application.InitChain(req) 290 return &res, nil 291 } 292 293 func (app *localClient) BeginBlockSync(req ocabci.RequestBeginBlock) (*types.ResponseBeginBlock, error) { 294 app.mtx.Lock() 295 defer app.mtx.Unlock() 296 297 res := app.Application.BeginBlock(req) 298 return &res, nil 299 } 300 301 func (app *localClient) EndBlockSync(req types.RequestEndBlock) (*types.ResponseEndBlock, error) { 302 app.mtx.Lock() 303 defer app.mtx.Unlock() 304 305 res := app.Application.EndBlock(req) 306 return &res, nil 307 } 308 309 func (app *localClient) BeginRecheckTxSync(req ocabci.RequestBeginRecheckTx) (*ocabci.ResponseBeginRecheckTx, error) { 310 // NOTE: commented out for performance. delete all after commenting out all `app.mtx` 311 // app.mtx.Lock() 312 // defer app.mtx.Unlock() 313 314 res := app.Application.BeginRecheckTx(req) 315 return &res, nil 316 } 317 318 func (app *localClient) EndRecheckTxSync(req ocabci.RequestEndRecheckTx) (*ocabci.ResponseEndRecheckTx, error) { 319 // NOTE: commented out for performance. delete all after commenting out all `app.mtx` 320 // app.mtx.Lock() 321 // defer app.mtx.Unlock() 322 323 res := app.Application.EndRecheckTx(req) 324 return &res, nil 325 } 326 327 func (app *localClient) ListSnapshotsSync(req types.RequestListSnapshots) (*types.ResponseListSnapshots, error) { 328 app.mtx.Lock() 329 defer app.mtx.Unlock() 330 331 res := app.Application.ListSnapshots(req) 332 return &res, nil 333 } 334 335 func (app *localClient) OfferSnapshotSync(req types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) { 336 app.mtx.Lock() 337 defer app.mtx.Unlock() 338 339 res := app.Application.OfferSnapshot(req) 340 return &res, nil 341 } 342 343 func (app *localClient) LoadSnapshotChunkSync( 344 req types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) { 345 app.mtx.Lock() 346 defer app.mtx.Unlock() 347 348 res := app.Application.LoadSnapshotChunk(req) 349 return &res, nil 350 } 351 352 func (app *localClient) ApplySnapshotChunkSync( 353 req types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) { 354 app.mtx.Lock() 355 defer app.mtx.Unlock() 356 357 res := app.Application.ApplySnapshotChunk(req) 358 return &res, nil 359 } 360 361 //------------------------------------------------------- 362 363 func (app *localClient) done(reqRes *ReqRes, res *ocabci.Response) *ReqRes { 364 set := reqRes.SetDone(res) 365 if set { 366 if globalCb := app.GetGlobalCallback(); globalCb != nil { 367 globalCb(reqRes.Request, res) 368 } 369 } 370 return reqRes 371 }