Skip to content

Problem(backport) : block-stm, object store etc #1605

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

Draft
wants to merge 37 commits into
base: release/v0.53.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
cc6c67b
Support object store (#206)
Mar 25, 2024
17043e4
cleanup
mmsqe Mar 27, 2025
78e3a48
Merge remote-tracking branch 'origin/release/v0.53.x' into release/v0…
mmsqe Mar 28, 2025
f44f06b
fix test
mmsqe Mar 28, 2025
e1ee61f
lint
mmsqe Mar 28, 2025
b75bb98
Merge remote-tracking branch 'origin/main' into release/v0.53.x_obj_s…
mmsqe Apr 9, 2025
e64ccc0
resolve
mmsqe Apr 9, 2025
d2c1c3b
fix test
mmsqe Apr 9, 2025
8892029
fix test
mmsqe Apr 9, 2025
83f4859
Problem: store key type assertion is incorrect (#244)
mmsqe Apr 9, 2025
d97d3d1
Merge remote-tracking branch 'origin/main' into release/v0.53.x_obj_s…
mmsqe Apr 11, 2025
2475f01
Problem: MultiStore interface is bloated (#240)
Mar 29, 2024
af3a9f6
Problem: nested cache store not efficient (#241)
Mar 29, 2024
ed5c416
Problem: many memory allocs in cache store wrapping (#242)
Apr 1, 2024
cc2f1f8
Problem: parallel tx execution is not supported (#205)
Mar 22, 2024
fc94a55
Problem: fee collection not compatible with parallel execution (#237)
Mar 28, 2024
34d33dc
Problem: no API to use the new CoW branch store (#243)
Apr 1, 2024
fb9fc8a
Problem: store key type assertion is incorrect (#244)
Apr 1, 2024
f90fc95
Problem: Restore don't work snapshot revert usage (#245)
Apr 2, 2024
c675f52
feat: save some memory allocations on un-used cache store (#248)
Apr 3, 2024
13dca67
Problem: block gas used not set in context (#252)
Apr 3, 2024
d3485c7
Problem: invalid tx returns negative gas wanted (#253)
Apr 3, 2024
ee6aa36
Problem: no api to create cachemulti store from external cache store …
Apr 5, 2024
a08c72e
small optimisations (#261)
Apr 8, 2024
48da57e
Problem: mempool don't respect gas wanted returned by ante handler (#…
Jun 26, 2024
524d2c1
Problem: mempool.GasTx interface is not reused (#536)
mmsqe Jul 2, 2024
393b4e6
Problem: signature verification result not cache between incarnations…
Jul 15, 2024
5cbbe12
Problem: tx executor can't do dependency analysis (#744)
Sep 11, 2024
8f9c18b
mod tidy
mmsqe Apr 11, 2025
fb805e3
cleanup
mmsqe Apr 11, 2025
df7ea7b
feat(x/tx): support bytes field as signer (#21850)
Sep 26, 2024
9b09181
Merge remote-tracking branch 'origin/main' into obj_main
mmsqe Apr 12, 2025
79e09b2
Revert "fix (sims): state written in sims loop (#20936)"
mmsqe Apr 15, 2025
4187a9d
Merge remote-tracking branch 'origin/main' into obj_main
mmsqe Apr 15, 2025
67d990b
Problem: tx is decoded in PrepareProposal when using NopMempool (#884)
Nov 1, 2024
9ee27ce
Problem: versiondb/memiavl don't compatible with upstream sdk (#588)
Jul 22, 2024
4d2040f
Merge branch 'obj_main' into release/v0.53.x
mmsqe May 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/workflows/dependabot-update-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ jobs:
if: ${{ github.actor == 'dependabot[bot]' }}
steps:
- name: Generate Token
<<<<<<< HEAD
uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v1
=======
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v1
>>>>>>> acb39aa52 (build(deps): Bump actions/create-github-app-token from 2.0.3 to 2.0.6 (#24673))
id: app-token
with:
app-id: "${{ secrets.APP_ID }}"
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (genutil) [#24018](https://github.com/cosmos/cosmos-sdk/pull/24018) Allow manually setting the consensus key type in genesis
* (client) [#18557](https://github.com/cosmos/cosmos-sdk/pull/18557) Add `--qrcode` flag to `keys show` command to support displaying keys address QR code.
* (x/auth) [#24030](https://github.com/cosmos/cosmos-sdk/pull/24030) Allow usage of ed25519 keys for transaction signing.
* (baseapp) [#24159](https://github.com/cosmos/cosmos-sdk/pull/24159) Support mount object store in baseapp, add `ObjectStore` api in context.
* (baseapp) [#24163](https://github.com/cosmos/cosmos-sdk/pull/24163) Add `StreamingManager` to baseapp to extend the abci listeners.
* (x/protocolpool) [#23933](https://github.com/cosmos/cosmos-sdk/pull/23933) Add x/protocolpool module.
* x/distribution can now utilize an externally managed community pool. NOTE: this will make the message handlers for FundCommunityPool and CommunityPoolSpend error, as well as the query handler for CommunityPool.
Expand Down
99 changes: 68 additions & 31 deletions baseapp/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -791,48 +791,47 @@ func (app *BaseApp) internalFinalizeBlock(ctx context.Context, req *abci.Request

// Reset the gas meter so that the AnteHandlers aren't required to
gasMeter = app.getBlockGasMeter(app.finalizeBlockState.Context())
app.finalizeBlockState.SetContext(app.finalizeBlockState.Context().WithBlockGasMeter(gasMeter))
app.finalizeBlockState.SetContext(
app.finalizeBlockState.Context().
WithBlockGasMeter(gasMeter).
WithTxCount(len(req.Txs)),
)

// Iterate over all raw transactions in the proposal and attempt to execute
// them, gathering the execution results.
//
// NOTE: Not all raw transactions may adhere to the sdk.Tx interface, e.g.
// vote extensions, so skip those.
txResults := make([]*abci.ExecTxResult, 0, len(req.Txs))
for _, rawTx := range req.Txs {
var response *abci.ExecTxResult

if _, err := app.txDecoder(rawTx); err == nil {
response = app.deliverTx(rawTx)
} else {
// In the case where a transaction included in a block proposal is malformed,
// we still want to return a default response to comet. This is because comet
// expects a response for each transaction included in a block proposal.
response = sdkerrors.ResponseExecTxResultWithEvents(
sdkerrors.ErrTxDecode,
0,
0,
nil,
false,
)
}

// check after every tx if we should abort
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
// continue
}

txResults = append(txResults, response)
txResults, err := app.executeTxs(ctx, req.Txs)
if err != nil {
// usually due to canceled
return nil, err
}

if app.finalizeBlockState.ms.TracingEnabled() {
app.finalizeBlockState.ms = app.finalizeBlockState.ms.SetTracingContext(nil).(storetypes.CacheMultiStore)
}

endBlock, err := app.endBlock(app.finalizeBlockState.Context())
var (
blockGasUsed uint64
blockGasWanted uint64
)
for _, res := range txResults {
// GasUsed should not be -1 but just in case
if res.GasUsed > 0 {
blockGasUsed += uint64(res.GasUsed)
}
// GasWanted could be -1 if the tx is invalid
if res.GasWanted > 0 {
blockGasWanted += uint64(res.GasWanted)
}
}
app.finalizeBlockState.SetContext(
app.finalizeBlockState.Context().
WithBlockGasUsed(blockGasUsed).
WithBlockGasWanted(blockGasWanted),
)
endBlock, err := app.endBlock(ctx)
if err != nil {
return nil, err
}
Expand All @@ -856,6 +855,44 @@ func (app *BaseApp) internalFinalizeBlock(ctx context.Context, req *abci.Request
}, nil
}

func (app *BaseApp) executeTxs(ctx context.Context, txs [][]byte) ([]*abci.ExecTxResult, error) {
if app.txExecutor != nil {
return app.txExecutor(ctx, txs, app.finalizeBlockState.ms, func(i int, memTx sdk.Tx, ms storetypes.MultiStore, incarnationCache map[string]any) *abci.ExecTxResult {
return app.deliverTxWithMultiStore(txs[i], memTx, i, ms, incarnationCache)
})
}

txResults := make([]*abci.ExecTxResult, 0, len(txs))
for i, rawTx := range txs {
var response *abci.ExecTxResult

if memTx, err := app.txDecoder(rawTx); err == nil {
response = app.deliverTx(rawTx, memTx, i)
} else {
// In the case where a transaction included in a block proposal is malformed,
// we still want to return a default response to comet. This is because comet
// expects a response for each transaction included in a block proposal.
response = sdkerrors.ResponseExecTxResultWithEvents(
sdkerrors.ErrTxDecode,
0,
0,
nil,
false,
)
}
// check after every tx if we should abort
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
// continue
}

txResults = append(txResults, response)
}
return txResults, nil
}

// FinalizeBlock will execute the block proposal provided by RequestFinalizeBlock.
// Specifically, it will execute an application's BeginBlock (if defined), followed
// by the transactions in the proposal, finally followed by the application's
Expand Down Expand Up @@ -1213,7 +1250,7 @@ func (app *BaseApp) CreateQueryContextWithCheckHeader(height int64, prove, check
// use custom query multi-store if provided
qms := app.qms
if qms == nil {
qms = app.cms.(storetypes.MultiStore)
qms = storetypes.RootMultiStore(app.cms)
}

lastBlockHeight := qms.LatestVersion()
Expand Down
70 changes: 44 additions & 26 deletions baseapp/abci_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@
// to verify a transaction.
ProposalTxVerifier interface {
PrepareProposalVerifyTx(tx sdk.Tx) ([]byte, error)
ProcessProposalVerifyTx(txBz []byte) (sdk.Tx, error)
ProcessProposalVerifyTx(txBz []byte) (sdk.Tx, uint64, error)
TxDecode(txBz []byte) (sdk.Tx, error)
TxEncode(tx sdk.Tx) ([]byte, error)
}
Expand All @@ -213,6 +213,9 @@
txVerifier ProposalTxVerifier
txSelector TxSelector
signerExtAdapter mempool.SignerExtractionAdapter

// fastPrepareProposal together with NoOpMempool will bypass tx selector
fastPrepareProposal bool
}
)

Expand All @@ -225,6 +228,12 @@
}
}

func NewDefaultProposalHandlerFast(mp mempool.Mempool, txVerifier ProposalTxVerifier) *DefaultProposalHandler {
h := NewDefaultProposalHandler(mp, txVerifier)
h.fastPrepareProposal = true
return h
}

// SetTxSelector sets the TxSelector function on the DefaultProposalHandler.
func (h *DefaultProposalHandler) SetTxSelector(ts TxSelector) {
h.txSelector = ts
Expand Down Expand Up @@ -265,13 +274,23 @@
// Note, we still need to ensure the transactions returned respect req.MaxTxBytes.
_, isNoOp := h.mempool.(mempool.NoOpMempool)
if h.mempool == nil || isNoOp {
if h.fastPrepareProposal {
txs := h.txSelector.SelectTxForProposalFast(ctx, req.Txs)
return &abci.ResponsePrepareProposal{Txs: txs}, nil
}

for _, txBz := range req.Txs {
tx, err := h.txVerifier.TxDecode(txBz)
if err != nil {
return nil, err
}

stop := h.txSelector.SelectTxForProposal(ctx, uint64(req.MaxTxBytes), maxBlockGas, tx, txBz)
var txGasLimit uint64
if gasTx, ok := tx.(mempool.GasTx); ok {
txGasLimit = gasTx.GetGas()
}

stop := h.txSelector.SelectTxForProposal(ctx, uint64(req.MaxTxBytes), maxBlockGas, tx, txBz, txGasLimit)
if stop {
break
}
Expand All @@ -286,14 +305,14 @@
selectedTxsNums int
invalidTxs []sdk.Tx // invalid txs to be removed out of the loop to avoid dead lock
)
mempool.SelectBy(ctx, h.mempool, req.Txs, func(memTx sdk.Tx) bool {
unorderedTx, ok := memTx.(sdk.TxWithUnordered)
mempool.SelectBy(ctx, h.mempool, req.Txs, func(memTx mempool.Tx) bool {
unorderedTx, ok := memTx.Tx.(sdk.TxWithUnordered)
isUnordered := ok && unorderedTx.GetUnordered()
txSignersSeqs := make(map[string]uint64)

// if the tx is unordered, we don't need to check the sequence, we just add it
if !isUnordered {
signerData, err := h.signerExtAdapter.GetSigners(memTx)
signerData, err := h.signerExtAdapter.GetSigners(memTx.Tx)
if err != nil {
// propagate the error to the caller
resError = err
Expand All @@ -318,7 +337,7 @@
break
}
txSignersSeqs[signer.Signer.String()] = signer.Sequence
}
if !shouldAdd {
return true
}
Expand All @@ -328,11 +347,11 @@
// which calls mempool.Insert, in theory everything in the pool should be
// valid. But some mempool implementations may insert invalid txs, so we
// check again.
txBz, err := h.txVerifier.PrepareProposalVerifyTx(memTx)
txBz, err := h.txVerifier.PrepareProposalVerifyTx(memTx.Tx)
if err != nil {
invalidTxs = append(invalidTxs, memTx)
invalidTxs = append(invalidTxs, memTx.Tx)
} else {
stop := h.txSelector.SelectTxForProposal(ctx, uint64(req.MaxTxBytes), maxBlockGas, memTx, txBz)
stop := h.txSelector.SelectTxForProposal(ctx, uint64(req.MaxTxBytes), maxBlockGas, memTx.Tx, txBz, memTx.GasWanted)
if stop {
return false
}
Expand Down Expand Up @@ -404,17 +423,13 @@
}

for _, txBytes := range req.Txs {
tx, err := h.txVerifier.ProcessProposalVerifyTx(txBytes)
_, gasWanted, err := h.txVerifier.ProcessProposalVerifyTx(txBytes)
if err != nil {
return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil
}

if maxBlockGas > 0 {
gasTx, ok := tx.(GasTx)
if ok {
totalTxGas += gasTx.GetGas()
}

totalTxGas += gasWanted
if totalTxGas > uint64(maxBlockGas) {
return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil
}
Expand Down Expand Up @@ -472,7 +487,13 @@
// a proposal based on inclusion criteria defined by the TxSelector. It must
// return <true> if the caller should halt the transaction selection loop
// (typically over a mempool) or <false> otherwise.
SelectTxForProposal(ctx context.Context, maxTxBytes, maxBlockGas uint64, memTx sdk.Tx, txBz []byte) bool
SelectTxForProposal(ctx context.Context, maxTxBytes, maxBlockGas uint64, memTx sdk.Tx, txBz []byte, gasWanted uint64) bool

// SelectTxForProposalFast is called in the case of NoOpMempool,
// where cometbft already checked the block gas/size limit,
// so the tx selector should simply accept them all to the proposal.
// But extra validations on the tx are still possible though.
SelectTxForProposalFast(ctx context.Context, txs [][]byte) [][]byte
}

type defaultTxSelector struct {
Expand All @@ -494,26 +515,19 @@
func (ts *defaultTxSelector) Clear() {
ts.totalTxBytes = 0
ts.totalTxGas = 0
ts.selectedTxs = nil
ts.selectedTxs = ts.selectedTxs[:0] // keep the allocated memory
}

func (ts *defaultTxSelector) SelectTxForProposal(_ context.Context, maxTxBytes, maxBlockGas uint64, memTx sdk.Tx, txBz []byte) bool {
func (ts *defaultTxSelector) SelectTxForProposal(_ context.Context, maxTxBytes, maxBlockGas uint64, memTx sdk.Tx, txBz []byte, gasWanted uint64) bool {
txSize := uint64(cmttypes.ComputeProtoSizeForTxs([]cmttypes.Tx{txBz}))

var txGasLimit uint64
if memTx != nil {
if gasTx, ok := memTx.(GasTx); ok {
txGasLimit = gasTx.GetGas()
}
}

// only add the transaction to the proposal if we have enough capacity
if (txSize + ts.totalTxBytes) <= maxTxBytes {
// If there is a max block gas limit, add the tx only if the limit has
// not been met.
if maxBlockGas > 0 {
if (txGasLimit + ts.totalTxGas) <= maxBlockGas {
ts.totalTxGas += txGasLimit
if (gasWanted + ts.totalTxGas) <= maxBlockGas {
ts.totalTxGas += gasWanted
ts.totalTxBytes += txSize
ts.selectedTxs = append(ts.selectedTxs, txBz)
}
Expand All @@ -526,3 +540,7 @@
// check if we've reached capacity; if so, we cannot select any more transactions
return ts.totalTxBytes >= maxTxBytes || (maxBlockGas > 0 && (ts.totalTxGas >= maxBlockGas))
}

func (ts *defaultTxSelector) SelectTxForProposalFast(ctx context.Context, txs [][]byte) [][]byte {
return txs
}
Loading
Loading