ITADN

Bug: STMRunner passes nil transaction bytes to deliverTx when estimate is false

#25879Openrandy-cro 创建于 2026-02-09
R
randy-crocommented
### Summary In `blockstm/txnrunner.go`, `STMRunner.Run` fails to pass the raw transaction bytes to `deliverTx` when the `estimate` flag is `false`. This results in `deliverTx` being called with `nil` tx bytes, which will result in the transaction not executing in `BaseApp.RunTx`. ### Affected Code https://github.com/cosmos/cosmos-sdk/blob/main/blockstm/txnrunner.go#L66-L96 ``` var ( estimates []MultiLocations memTxs [][]byte ) if e.estimate { memTxs, estimates = preEstimates(txs, e.workers, authStore, bankStore, e.coinDenom(ms), e.txDecoder) } // ...inside ExecuteBlockWithEstimates callback: var memTx []byte if memTxs != nil { memTx = memTxs[txn] } results[txn] = deliverTx(memTx, msWrapper{ms}, int(txn), cache) ``` When `estimate` is `false`: 1. `memTxs` remains its zero value (`nil`) 2. `if memTxs != nil` check is `false`, so `memTx` stays `nil` 3. `deliverTx(nil, ...)` is called — the original `txs[txn]` bytes are never passed ### Comparison with DefaultRunner `DefaultRunner` correctly passes the raw transaction bytes: https://github.com/cosmos/cosmos-sdk/blob/main/baseapp/txnrunner/default.go#L34 ``` response = deliverTx(rawTx, nil, i, nil) ``` ### Suggested Fix Fall back to the original `txs[txn]` when `memTxs` is nil or when the entry is nil: ``` var memTx []byte if memTxs != nil && memTxs[txn] != nil { memTx = memTxs[txn] } else { memTx = txs[txn] } ``` This ensures raw transaction bytes are always passed to `deliverTx`, consistent with `DefaultRunner` behavior. It also handles the edge case where `preEstimates` skips a malformed transaction.
2 条评论