-
Notifications
You must be signed in to change notification settings - Fork 2
[CP-341] Async CheckTx and Unified Mempool #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v1.x-inj
Are you sure you want to change the base?
Changes from 5 commits
28fb9b6
0ddf5ec
2dc0759
ee15275
8df4e19
2a6bcc9
799a71d
e1db388
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,6 +49,7 @@ const ( | |
| v2 = "v2" | ||
|
|
||
| MempoolTypeFlood = "flood" | ||
| MempoolTypeProxy = "proxy" | ||
| MempoolTypeNop = "nop" | ||
| ) | ||
|
Comment on lines
51
to
54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainAllow the new "proxy" mempool type in validation; otherwise node won't start You added MempoolTypeProxy, but ValidateBasic still rejects any type other than "flood" and "nop". This will prevent nodes from booting with type="proxy" despite having a reactor path wired in node/setup.go. Update MempoolConfig.ValidateBasic to accept the proxy type: // in func (cfg *MempoolConfig) ValidateBasic() error
switch cfg.Type {
case MempoolTypeFlood, MempoolTypeNop, MempoolTypeProxy:
case "": // allow empty string to be backwards compatible
default:
return fmt.Errorf("unknown mempool type: %q", cfg.Type)
}Also consider updating the config docs/toml template to mention "proxy" as a valid mempool type. Run this to find and update any config templates referencing mempool types: 🏁 Script executed: #!/bin/bash
rg -nP --type=go -C2 '(MempoolTypeFlood|MempoolTypeNop)' config | sed -n '1,200p'
rg -nP 'mempool.*type' -C2 config
rg -nP --glob '!**/vendor/**' -C2 'proxy' configLength of output: 6268 Allow “proxy” as a valid mempool type The • config/config.go • config/config_test.go • config/config.toml.tpl 🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Mark ReqRes as done, fix callback data race, and propagate the error message
Apply:
func (app *unsyncLocalClient) CheckTxAsync(ctx context.Context, req *types.CheckTxRequest) (*ReqRes, error) { - reqres := NewReqRes(types.ToCheckTxRequest(req)) + reqres := NewReqRes(types.ToCheckTxRequest(req)) - go func() { - res, err := app.Application.CheckTx(ctx, req) - if err != nil { - reqres.Response = types.ToExceptionResponse("") // optimistic recheck failed - } else { - reqres.Response = types.ToCheckTxResponse(res) - } - - if app.Callback != nil { - app.Callback(reqres.Request, reqres.Response) - } - reqres.InvokeCallback() - }() + go func() { + // Ensure any waiter on this ReqRes unblocks. + defer reqres.WaitGroup.Done() + + res, err := app.Application.CheckTx(ctx, req) + if err != nil { + reqres.Response = types.ToExceptionResponse(err.Error()) + } else { + reqres.Response = types.ToCheckTxResponse(res) + } + + // Read callback under lock to avoid races with SetResponseCallback. + app.mtx.Lock() + cb := app.Callback + app.mtx.Unlock() + if cb != nil { + cb(reqres.Request, reqres.Response) + } + // If a per-request callback is set on reqres, invoke it too. + reqres.InvokeCallback() + }() return reqres, nil }To double-check the correct way to mark a ReqRes as complete, inspect ReqRes methods:
🏁 Script executed:
Length of output: 363
I didn’t locate
NewReqRes,InvokeCallback, or aDonemethod forReqRes. Let’s find their definitions across the repo:🏁 Script executed:
Length of output: 110
Let’s locate all
ReqResusages and definitions to confirm howWaitGroupandInvokeCallbackbehave:🏁 Script executed:
Length of output: 38394
Let’s inspect
unsyncLocalClientto confirm its fields and callback handling:🏁 Script executed:
Length of output: 166
Let’s inspect the
unsyncLocalClienttype and its methods to verify callback and mutex usage:🏁 Script executed:
Length of output: 2277
Fix Request-Response synchronization and callback races in unsyncLocalClient.CheckTxAsync
File: abci/client/unsync_local_client.go
func (app *unsyncLocalClient) CheckTxAsync(ctx context.Context, req *types.CheckTxRequest) (*ReqRes, error) { - reqres := NewReqRes(types.ToCheckTxRequest(req)) + reqres := NewReqRes(types.ToCheckTxRequest(req)) - go func() { - res, err := app.Application.CheckTx(ctx, req) - if err != nil { - reqres.Response = types.ToExceptionResponse("") // optimistic recheck failed - } else { - reqres.Response = types.ToCheckTxResponse(res) - } - - if app.Callback != nil { - app.Callback(reqres.Request, reqres.Response) - } - reqres.InvokeCallback() - }() + go func() { + // Unblock any Wait() calls on this ReqRes. + defer reqres.Done() + + res, err := app.Application.CheckTx(ctx, req) + if err != nil { + reqres.Response = types.ToExceptionResponse(err.Error()) + } else { + reqres.Response = types.ToCheckTxResponse(res) + } + + // Safely grab the client‐level callback under lock. + app.mtx.Lock() + cb := app.Callback + app.mtx.Unlock() + if cb != nil { + cb(reqres.Request, reqres.Response) + } + // Invoke any per‐ReqRes callback. + reqres.InvokeCallback() + }() return reqres, nil }🤖 Prompt for AI Agents