Skip to content

Commit 758b6b2

Browse files
mergify[bot]rootulpevan-forbes
authored
fix: panic due to nil limit (backport #2215) (#2217)
Part of celestiaorg/celestia-app#5279 #1949 contained a regression because a nil limitPerPage causes UnconfirmedTxs to panic. Before that PR, the [validatePerPage](https://github.com/rootulp/celestia-core/blob/041b5177919562c111cad22c6aabac8a62de5a3a/rpc/core/env.go#L120-L123) would handle a nil limitPerPage by falling back to the default so that's what I did in this PR. Added unit tests to cover it too.<hr>This is an automatic backport of pull request #2215 done by [Mergify](https://mergify.com). --------- Co-authored-by: Rootul P <[email protected]> Co-authored-by: evan-forbes <[email protected]>
1 parent 92b3a75 commit 758b6b2

File tree

4 files changed

+77
-5
lines changed

4 files changed

+77
-5
lines changed

rpc/core/env.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,24 @@ func (env *Environment) validatePerPage(perPagePtr *int) int {
131131
return perPage
132132
}
133133

134+
func (env *Environment) validateUnconfirmedTxsPerPage(perPagePtr *int) int {
135+
if perPagePtr == nil { // no per_page parameter
136+
return defaultPerPage
137+
}
138+
139+
perPage := *perPagePtr
140+
if perPage < -1 {
141+
return defaultPerPage
142+
}
143+
if perPage == 0 {
144+
return defaultPerPage
145+
}
146+
if perPage > maxPerPage {
147+
return maxPerPage
148+
}
149+
return perPage
150+
}
151+
134152
// InitGenesisChunks configures the environment and should be called on service
135153
// startup.
136154
func (env *Environment) InitGenesisChunks() error {

rpc/core/env_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,36 @@ func TestPaginationPerPage(t *testing.T) {
8080
p := env.validatePerPage(nil)
8181
assert.Equal(t, defaultPerPage, p)
8282
}
83+
84+
func TestValidateUnconfirmedTxsPerPage(t *testing.T) {
85+
env := &Environment{}
86+
87+
t.Run("should return default if input is nil", func(t *testing.T) {
88+
got := env.validateUnconfirmedTxsPerPage(nil)
89+
assert.Equal(t, defaultPerPage, got)
90+
})
91+
92+
type testCase struct {
93+
input int
94+
want int
95+
}
96+
97+
cases := []testCase{
98+
{-2, defaultPerPage},
99+
{-1, -1}, // -1 is now a valid input and means query all unconfirmed txs
100+
{0, defaultPerPage},
101+
{1, 1},
102+
{10, 10},
103+
{30, 30},
104+
{defaultPerPage, defaultPerPage},
105+
{maxPerPage - 1, maxPerPage - 1},
106+
{maxPerPage, maxPerPage},
107+
{maxPerPage + 1, maxPerPage},
108+
}
109+
for _, c := range cases {
110+
t.Run(fmt.Sprintf("should return %d if input is %d", c.want, c.input), func(t *testing.T) {
111+
got := env.validateUnconfirmedTxsPerPage(&c.input)
112+
assert.Equal(t, c.want, got)
113+
})
114+
}
115+
}

rpc/core/mempool.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,7 @@ func (env *Environment) BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (*
148148
// More: https://docs.cometbft.com/v0.38.x/rpc/#/Info/unconfirmed_txs
149149
// If limitPtr == -1, it will return all the unconfirmed transactions in the mempool.
150150
func (env *Environment) UnconfirmedTxs(_ *rpctypes.Context, limitPtr *int) (*ctypes.ResultUnconfirmedTxs, error) {
151-
limit := *limitPtr
152-
if limit != -1 {
153-
// reuse per_page validator
154-
limit = env.validatePerPage(limitPtr)
155-
}
151+
limit := env.validateUnconfirmedTxsPerPage(limitPtr)
156152

157153
txs := env.Mempool.ReapMaxTxs(limit)
158154
return &ctypes.ResultUnconfirmedTxs{

rpc/core/mempool_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package core
2+
3+
import (
4+
"testing"
5+
6+
mempoolmocks "github.com/cometbft/cometbft/mempool/mocks"
7+
rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types"
8+
"github.com/cometbft/cometbft/types"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestUnconfirmedTxs(t *testing.T) {
13+
mempool := &mempoolmocks.Mempool{}
14+
mempool.On("ReapMaxTxs", 30).Return(types.Txs{})
15+
mempool.On("Size").Return(0)
16+
mempool.On("SizeBytes").Return(int64(0))
17+
env := &Environment{
18+
Mempool: mempool,
19+
}
20+
21+
t.Run("should not panic with nil limit", func(t *testing.T) {
22+
_, err := env.UnconfirmedTxs(&rpctypes.Context{}, nil)
23+
require.NoError(t, err)
24+
})
25+
}

0 commit comments

Comments
 (0)