-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
refactor(server/v2): Update prepare & process proposal #21237
Changes from 6 commits
faf5335
f6b5f43
532edc8
96171df
c734809
53fafa8
9d725d4
5841d3b
5262b84
6856241
1075d9d
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 |
---|---|---|
|
@@ -6,13 +6,12 @@ import ( | |
"fmt" | ||
|
||
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" | ||
"github.com/cosmos/gogoproto/proto" | ||
|
||
consensusv1 "cosmossdk.io/api/cosmos/consensus/v1" | ||
appmanager "cosmossdk.io/core/app" | ||
"cosmossdk.io/core/store" | ||
"cosmossdk.io/core/transaction" | ||
"cosmossdk.io/server/v2/cometbft/mempool" | ||
consensustypes "cosmossdk.io/x/consensus/types" | ||
) | ||
|
||
type AppManager[T transaction.Tx] interface { | ||
|
@@ -33,28 +32,25 @@ func NewDefaultProposalHandler[T transaction.Tx](mp mempool.Mempool[T]) *Default | |
} | ||
|
||
func (h *DefaultProposalHandler[T]) PrepareHandler() PrepareHandler[T] { | ||
return func(ctx context.Context, app AppManager[T], txs []T, req proto.Message) ([]T, error) { | ||
abciReq, ok := req.(*abci.PrepareProposalRequest) | ||
if !ok { | ||
return nil, fmt.Errorf("expected abci.PrepareProposalRequest, invalid request type: %T,", req) | ||
} | ||
|
||
return func(ctx context.Context, app AppManager[T], codec transaction.Codec[T], req *abci.PrepareProposalRequest) ([]T, error) { | ||
var maxBlockGas uint64 | ||
|
||
res, err := app.Query(ctx, 0, &consensusv1.QueryParamsRequest{}) | ||
res, err := app.Query(ctx, 0, &consensustypes.QueryParamsRequest{}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
paramsResp, ok := res.(*consensusv1.QueryParamsResponse) | ||
paramsResp, ok := res.(*consensustypes.QueryParamsResponse) | ||
if !ok { | ||
return nil, fmt.Errorf("unexpected consensus params response type; expected: %T, got: %T", &consensusv1.QueryParamsResponse{}, res) | ||
return nil, fmt.Errorf("unexpected consensus params response type; expected: %T, got: %T", &consensustypes.QueryParamsResponse{}, res) | ||
} | ||
|
||
if b := paramsResp.GetParams().Block; b != nil { | ||
maxBlockGas = uint64(b.MaxGas) | ||
} | ||
|
||
txs := decodeTxs(codec, req.Txs) | ||
|
||
defer h.txSelector.Clear() | ||
|
||
// If the mempool is nil or NoOp we simply return the transactions | ||
|
@@ -64,7 +60,7 @@ func (h *DefaultProposalHandler[T]) PrepareHandler() PrepareHandler[T] { | |
_, isNoOp := h.mempool.(mempool.NoOpMempool[T]) | ||
if h.mempool == nil || isNoOp { | ||
for _, tx := range txs { | ||
stop := h.txSelector.SelectTxForProposal(ctx, uint64(abciReq.MaxTxBytes), maxBlockGas, tx) | ||
stop := h.txSelector.SelectTxForProposal(ctx, uint64(req.MaxTxBytes), maxBlockGas, tx) | ||
if stop { | ||
break | ||
} | ||
|
@@ -88,7 +84,7 @@ func (h *DefaultProposalHandler[T]) PrepareHandler() PrepareHandler[T] { | |
return nil, err | ||
} | ||
} else { | ||
stop := h.txSelector.SelectTxForProposal(ctx, uint64(abciReq.MaxTxBytes), maxBlockGas, memTx) | ||
stop := h.txSelector.SelectTxForProposal(ctx, uint64(req.MaxTxBytes), maxBlockGas, memTx) | ||
if stop { | ||
break | ||
} | ||
|
@@ -102,34 +98,31 @@ func (h *DefaultProposalHandler[T]) PrepareHandler() PrepareHandler[T] { | |
} | ||
|
||
func (h *DefaultProposalHandler[T]) ProcessHandler() ProcessHandler[T] { | ||
return func(ctx context.Context, app AppManager[T], txs []T, req proto.Message) error { | ||
return func(ctx context.Context, app AppManager[T], codec transaction.Codec[T], req *abci.ProcessProposalRequest) error { | ||
// If the mempool is nil we simply return ACCEPT, | ||
// because PrepareProposal may have included txs that could fail verification. | ||
_, isNoOp := h.mempool.(mempool.NoOpMempool[T]) | ||
if h.mempool == nil || isNoOp { | ||
return nil | ||
} | ||
|
||
_, ok := req.(*abci.PrepareProposalRequest) | ||
if !ok { | ||
return fmt.Errorf("invalid request type: %T", req) | ||
} | ||
|
||
res, err := app.Query(ctx, 0, &consensusv1.QueryParamsRequest{}) | ||
res, err := app.Query(ctx, 0, &consensustypes.QueryParamsRequest{}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
paramsResp, ok := res.(*consensusv1.QueryParamsResponse) | ||
paramsResp, ok := res.(*consensustypes.QueryParamsResponse) | ||
if !ok { | ||
return fmt.Errorf("unexpected consensus params response type; expected: %T, got: %T", &consensusv1.QueryParamsResponse{}, res) | ||
return fmt.Errorf("unexpected consensus params response type; expected: %T, got: %T", &consensustypes.QueryParamsResponse{}, res) | ||
} | ||
|
||
var maxBlockGas uint64 | ||
if b := paramsResp.GetParams().Block; b != nil { | ||
maxBlockGas = uint64(b.MaxGas) | ||
} | ||
|
||
txs := decodeTxs(codec, req.Txs) | ||
|
||
var totalTxGas uint64 | ||
for _, tx := range txs { | ||
_, err := app.ValidateTx(ctx, tx) | ||
|
@@ -153,18 +146,33 @@ func (h *DefaultProposalHandler[T]) ProcessHandler() ProcessHandler[T] { | |
} | ||
} | ||
|
||
func decodeTxs[T transaction.Tx](codec transaction.Codec[T], txsBz [][]byte) []T { | ||
var txs []T | ||
for _, tx := range txsBz { | ||
decTx, err := codec.Decode(tx) | ||
if err != nil { | ||
// TODO: vote extension meta data as a custom type to avoid possibly accepting invalid txs | ||
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. i think it's important to understand what to do here, is it fine to continue with txs if they fail decoding? 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. yes agree, I think we should decide about it. Like v1 we reject all if have a tx decoded fail. |
||
// continue even if tx decoding fails | ||
continue | ||
} | ||
|
||
txs = append(txs, decTx) | ||
} | ||
return txs | ||
} | ||
|
||
// NoOpPrepareProposal defines a no-op PrepareProposal handler. It will always | ||
// return the transactions sent by the client's request. | ||
func NoOpPrepareProposal[T transaction.Tx]() PrepareHandler[T] { | ||
return func(ctx context.Context, app AppManager[T], txs []T, req proto.Message) ([]T, error) { | ||
return txs, nil | ||
return func(ctx context.Context, app AppManager[T], codec transaction.Codec[T], req *abci.PrepareProposalRequest) ([]T, error) { | ||
return decodeTxs(codec, req.Txs), nil | ||
} | ||
} | ||
|
||
// NoOpProcessProposal defines a no-op ProcessProposal Handler. It will always | ||
// return ACCEPT. | ||
func NoOpProcessProposal[T transaction.Tx]() ProcessHandler[T] { | ||
return func(context.Context, AppManager[T], []T, proto.Message) error { | ||
return func(context.Context, AppManager[T], transaction.Codec[T], *abci.ProcessProposalRequest) error { | ||
return nil | ||
} | ||
} | ||
|
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.
shouldn't this fail at app build time?
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.
if you don't pass anything to the comet server, we use the default options (no op handlers).
so to get this you would have to purposely pass nil. as we don't want to make those mandatory, making it fail at compile time isn't best.