Skip to content

Commit 049308a

Browse files
authored
fix: pending state access PendingBlockNotFound (#2985)
* always provide pending state * add test for pendig data wrapper
1 parent dd04178 commit 049308a

10 files changed

+283
-49
lines changed

rpc/v6/pending_data_wrapper.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func (h *Handler) PendingData() (*core.PendingData, error) {
1919
return pending, nil
2020
}
2121

22-
// If pre_confirmed, network is polling pre_confirmed block and running on >= 0.14.0
22+
// If pending data variant is not `Pending` or err is `sync.ErrPendingBlockNotFound`
2323
latestHeader, err := h.bcReader.HeadsHeader()
2424
if err != nil {
2525
return nil, err
@@ -37,6 +37,30 @@ func (h *Handler) PendingBlock() *core.Block {
3737
return pending.GetBlock()
3838
}
3939

40+
func (h *Handler) PendingState() (core.StateReader, func() error, error) {
41+
pending, err := h.syncReader.PendingData()
42+
if err != nil {
43+
if errors.Is(err, sync.ErrPendingBlockNotFound) {
44+
return h.bcReader.HeadState()
45+
}
46+
return nil, nil, err
47+
}
48+
49+
if pending.Variant() == core.PendingBlockVariant {
50+
state, closer, err := h.syncReader.PendingState()
51+
if err != nil {
52+
if !errors.Is(err, sync.ErrPendingBlockNotFound) {
53+
return h.bcReader.HeadState()
54+
}
55+
return nil, nil, err
56+
}
57+
58+
return state, closer, nil
59+
}
60+
61+
return h.bcReader.HeadState()
62+
}
63+
4064
func emptyPendingForParent(parentHeader *core.Header) sync.Pending {
4165
receipts := make([]*core.TransactionReceipt, 0)
4266
pendingBlock := &core.Block{
@@ -75,16 +99,3 @@ func emptyPendingForParent(parentHeader *core.Header) sync.Pending {
7599
NewClasses: make(map[felt.Felt]core.Class, 0),
76100
}
77101
}
78-
79-
func (h *Handler) PendingState() (core.StateReader, func() error, error) {
80-
pending, err := h.PendingData()
81-
if err != nil {
82-
return nil, nil, err
83-
}
84-
85-
if pending.Variant() == core.PendingBlockVariant {
86-
return h.syncReader.PendingState()
87-
} else {
88-
return h.bcReader.HeadState()
89-
}
90-
}

rpc/v6/pending_data_wrapper_test.go

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
"go.uber.org/mock/gomock"
1717
)
1818

19-
func TestPendingDataWrapper(t *testing.T) {
19+
func TestPendingDataWrapper_PendingData(t *testing.T) {
2020
mockCtrl := gomock.NewController(t)
2121
t.Cleanup(mockCtrl.Finish)
2222
mockSyncReader := mocks.NewMockSyncReader(mockCtrl)
@@ -101,3 +101,55 @@ func TestPendingDataWrapper(t *testing.T) {
101101
))
102102
})
103103
}
104+
105+
func TestPendingDataWrapper_PendingState(t *testing.T) {
106+
mockCtrl := gomock.NewController(t)
107+
t.Cleanup(mockCtrl.Finish)
108+
mockSyncReader := mocks.NewMockSyncReader(mockCtrl)
109+
mockReader := mocks.NewMockReader(mockCtrl)
110+
handler := rpc.New(mockReader, mockSyncReader, nil, "", &utils.Sepolia, nil)
111+
112+
mockState := mocks.NewMockStateHistoryReader(mockCtrl)
113+
t.Run("Returns pending state when starknet version < 0.14.0", func(t *testing.T) {
114+
pending := sync.Pending{}
115+
pendingData := pending.AsPendingData()
116+
mockSyncReader.EXPECT().PendingData().Return(
117+
&pendingData,
118+
nil,
119+
)
120+
mockSyncReader.EXPECT().PendingState().Return(mockState, nopCloser, nil)
121+
pendingState, closer, err := handler.PendingState()
122+
123+
require.NoError(t, err)
124+
require.NotNil(t, pendingState)
125+
require.NotNil(t, closer)
126+
})
127+
128+
t.Run("Returns latest state starknet version >= 0.14.0", func(t *testing.T) {
129+
preConfirmed := core.PreConfirmed{}
130+
pendingData := preConfirmed.AsPendingData()
131+
mockSyncReader.EXPECT().PendingData().Return(
132+
&pendingData,
133+
nil,
134+
)
135+
mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil)
136+
pending, closer, err := handler.PendingState()
137+
138+
require.NoError(t, err)
139+
require.NotNil(t, pending)
140+
require.NotNil(t, closer)
141+
})
142+
143+
t.Run("Returns latest state when pending data is nil", func(t *testing.T) {
144+
mockSyncReader.EXPECT().PendingData().Return(
145+
nil,
146+
sync.ErrPendingBlockNotFound,
147+
)
148+
mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil)
149+
pending, closer, err := handler.PendingState()
150+
151+
require.NoError(t, err)
152+
require.NotNil(t, pending)
153+
require.NotNil(t, closer)
154+
})
155+
}

rpc/v7/pending_data_wrapper.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func (h *Handler) PendingData() (*core.PendingData, error) {
1919
return pending, nil
2020
}
2121

22-
// If pre_confirmed, network is polling pre_confirmed block and running on >= 0.14.0
22+
// If pending data variant is not `Pending` or err is `sync.ErrPendingBlockNotFound`
2323
latestHeader, err := h.bcReader.HeadsHeader()
2424
if err != nil {
2525
return nil, err
@@ -37,6 +37,30 @@ func (h *Handler) PendingBlock() *core.Block {
3737
return pending.GetBlock()
3838
}
3939

40+
func (h *Handler) PendingState() (core.StateReader, func() error, error) {
41+
pending, err := h.syncReader.PendingData()
42+
if err != nil {
43+
if errors.Is(err, sync.ErrPendingBlockNotFound) {
44+
return h.bcReader.HeadState()
45+
}
46+
return nil, nil, err
47+
}
48+
49+
if pending.Variant() == core.PendingBlockVariant {
50+
state, closer, err := h.syncReader.PendingState()
51+
if err != nil {
52+
if !errors.Is(err, sync.ErrPendingBlockNotFound) {
53+
return h.bcReader.HeadState()
54+
}
55+
return nil, nil, err
56+
}
57+
58+
return state, closer, nil
59+
}
60+
61+
return h.bcReader.HeadState()
62+
}
63+
4064
func emptyPendingForParent(parentHeader *core.Header) sync.Pending {
4165
receipts := make([]*core.TransactionReceipt, 0)
4266
pendingBlock := &core.Block{
@@ -75,16 +99,3 @@ func emptyPendingForParent(parentHeader *core.Header) sync.Pending {
7599
NewClasses: make(map[felt.Felt]core.Class, 0),
76100
}
77101
}
78-
79-
func (h *Handler) PendingState() (core.StateReader, func() error, error) {
80-
pending, err := h.PendingData()
81-
if err != nil {
82-
return nil, nil, err
83-
}
84-
85-
if pending.Variant() == core.PendingBlockVariant {
86-
return h.syncReader.PendingState()
87-
} else {
88-
return h.bcReader.HeadState()
89-
}
90-
}

rpc/v7/pending_data_wrapper_test.go

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,22 @@ import (
88
"github.com/NethermindEth/juno/core"
99
"github.com/NethermindEth/juno/core/felt"
1010
"github.com/NethermindEth/juno/mocks"
11-
rpc "github.com/NethermindEth/juno/rpc/v8"
11+
rpc "github.com/NethermindEth/juno/rpc/v7"
1212
adaptfeeder "github.com/NethermindEth/juno/starknetdata/feeder"
1313
"github.com/NethermindEth/juno/sync"
1414
"github.com/NethermindEth/juno/utils"
1515
"github.com/stretchr/testify/require"
1616
"go.uber.org/mock/gomock"
1717
)
1818

19-
func TestPendingDataWrapper(t *testing.T) {
19+
func TestPendingDataWrapper_PebndingData(t *testing.T) {
2020
mockCtrl := gomock.NewController(t)
2121
t.Cleanup(mockCtrl.Finish)
2222
mockSyncReader := mocks.NewMockSyncReader(mockCtrl)
2323
n := utils.HeapPtr(utils.Sepolia)
2424
mockReader := mocks.NewMockReader(mockCtrl)
2525
log := utils.NewNopZapLogger()
26-
handler := rpc.New(mockReader, mockSyncReader, nil, "", log)
26+
handler := rpc.New(mockReader, mockSyncReader, nil, "", &utils.Sepolia, log)
2727

2828
client := feeder.NewTestClient(t, n)
2929
gw := adaptfeeder.New(client)
@@ -102,3 +102,55 @@ func TestPendingDataWrapper(t *testing.T) {
102102
))
103103
})
104104
}
105+
106+
func TestPendingDataWrapper_PendingState(t *testing.T) {
107+
mockCtrl := gomock.NewController(t)
108+
t.Cleanup(mockCtrl.Finish)
109+
mockSyncReader := mocks.NewMockSyncReader(mockCtrl)
110+
mockReader := mocks.NewMockReader(mockCtrl)
111+
handler := rpc.New(mockReader, mockSyncReader, nil, "", &utils.Sepolia, nil)
112+
113+
mockState := mocks.NewMockStateHistoryReader(mockCtrl)
114+
t.Run("Returns pending state when starknet version < 0.14.0", func(t *testing.T) {
115+
pending := sync.Pending{}
116+
pendingData := pending.AsPendingData()
117+
mockSyncReader.EXPECT().PendingData().Return(
118+
&pendingData,
119+
nil,
120+
)
121+
mockSyncReader.EXPECT().PendingState().Return(mockState, nopCloser, nil)
122+
pendingState, closer, err := handler.PendingState()
123+
124+
require.NoError(t, err)
125+
require.NotNil(t, pendingState)
126+
require.NotNil(t, closer)
127+
})
128+
129+
t.Run("Returns latest state starknet version >= 0.14.0", func(t *testing.T) {
130+
preConfirmed := core.PreConfirmed{}
131+
pendingData := preConfirmed.AsPendingData()
132+
mockSyncReader.EXPECT().PendingData().Return(
133+
&pendingData,
134+
nil,
135+
)
136+
mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil)
137+
pending, closer, err := handler.PendingState()
138+
139+
require.NoError(t, err)
140+
require.NotNil(t, pending)
141+
require.NotNil(t, closer)
142+
})
143+
144+
t.Run("Returns latest state when pending data is nil", func(t *testing.T) {
145+
mockSyncReader.EXPECT().PendingData().Return(
146+
nil,
147+
sync.ErrPendingBlockNotFound,
148+
)
149+
mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil)
150+
pending, closer, err := handler.PendingState()
151+
152+
require.NoError(t, err)
153+
require.NotNil(t, pending)
154+
require.NotNil(t, closer)
155+
})
156+
}

rpc/v8/pending_data_wrapper.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func (h *Handler) PendingData() (*core.PendingData, error) {
1919
return pending, nil
2020
}
2121

22-
// If pre_confirmed, network is polling pre_confirmed block and running on >= 0.14.0
22+
// If pending data variant is not `Pending` or err is `sync.ErrPendingBlockNotFound`
2323
latestHeader, err := h.bcReader.HeadsHeader()
2424
if err != nil {
2525
return nil, err
@@ -37,6 +37,30 @@ func (h *Handler) PendingBlock() *core.Block {
3737
return pending.GetBlock()
3838
}
3939

40+
func (h *Handler) PendingState() (core.StateReader, func() error, error) {
41+
pending, err := h.syncReader.PendingData()
42+
if err != nil {
43+
if errors.Is(err, sync.ErrPendingBlockNotFound) {
44+
return h.bcReader.HeadState()
45+
}
46+
return nil, nil, err
47+
}
48+
49+
if pending.Variant() == core.PendingBlockVariant {
50+
state, closer, err := h.syncReader.PendingState()
51+
if err != nil {
52+
if !errors.Is(err, sync.ErrPendingBlockNotFound) {
53+
return h.bcReader.HeadState()
54+
}
55+
return nil, nil, err
56+
}
57+
58+
return state, closer, nil
59+
}
60+
61+
return h.bcReader.HeadState()
62+
}
63+
4064
func emptyPendingForParent(parentHeader *core.Header) sync.Pending {
4165
receipts := make([]*core.TransactionReceipt, 0)
4266
pendingBlock := &core.Block{
@@ -75,16 +99,3 @@ func emptyPendingForParent(parentHeader *core.Header) sync.Pending {
7599
NewClasses: make(map[felt.Felt]core.Class, 0),
76100
}
77101
}
78-
79-
func (h *Handler) PendingState() (core.StateReader, func() error, error) {
80-
pending, err := h.PendingData()
81-
if err != nil {
82-
return nil, nil, err
83-
}
84-
85-
if pending.Variant() == core.PendingBlockVariant {
86-
return h.syncReader.PendingState()
87-
} else {
88-
return h.bcReader.HeadState()
89-
}
90-
}

rpc/v8/pending_data_wrapper_test.go

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
"go.uber.org/mock/gomock"
1717
)
1818

19-
func TestPendingDataWrapper(t *testing.T) {
19+
func TestPendingDataWrapper_PendingData(t *testing.T) {
2020
mockCtrl := gomock.NewController(t)
2121
t.Cleanup(mockCtrl.Finish)
2222
mockSyncReader := mocks.NewMockSyncReader(mockCtrl)
@@ -102,3 +102,55 @@ func TestPendingDataWrapper(t *testing.T) {
102102
))
103103
})
104104
}
105+
106+
func TestPendingDataWrapper_PendingState(t *testing.T) {
107+
mockCtrl := gomock.NewController(t)
108+
t.Cleanup(mockCtrl.Finish)
109+
mockSyncReader := mocks.NewMockSyncReader(mockCtrl)
110+
mockReader := mocks.NewMockReader(mockCtrl)
111+
handler := rpc.New(mockReader, mockSyncReader, nil, "", nil)
112+
113+
mockState := mocks.NewMockStateHistoryReader(mockCtrl)
114+
t.Run("Returns pending state when starknet version < 0.14.0", func(t *testing.T) {
115+
pending := sync.Pending{}
116+
pendingData := pending.AsPendingData()
117+
mockSyncReader.EXPECT().PendingData().Return(
118+
&pendingData,
119+
nil,
120+
)
121+
mockSyncReader.EXPECT().PendingState().Return(mockState, nopCloser, nil)
122+
pendingState, closer, err := handler.PendingState()
123+
124+
require.NoError(t, err)
125+
require.NotNil(t, pendingState)
126+
require.NotNil(t, closer)
127+
})
128+
129+
t.Run("Returns latest state starknet version >= 0.14.0", func(t *testing.T) {
130+
preConfirmed := core.PreConfirmed{}
131+
pendingData := preConfirmed.AsPendingData()
132+
mockSyncReader.EXPECT().PendingData().Return(
133+
&pendingData,
134+
nil,
135+
)
136+
mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil)
137+
pending, closer, err := handler.PendingState()
138+
139+
require.NoError(t, err)
140+
require.NotNil(t, pending)
141+
require.NotNil(t, closer)
142+
})
143+
144+
t.Run("Returns latest state when pending data is nil", func(t *testing.T) {
145+
mockSyncReader.EXPECT().PendingData().Return(
146+
nil,
147+
sync.ErrPendingBlockNotFound,
148+
)
149+
mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil)
150+
pending, closer, err := handler.PendingState()
151+
152+
require.NoError(t, err)
153+
require.NotNil(t, pending)
154+
require.NotNil(t, closer)
155+
})
156+
}

rpc/v9/helpers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func (h *Handler) stateByBlockID(blockID *BlockID) (core.StateReader, blockchain
143143
var err error
144144
switch blockID.Type() {
145145
case preConfirmed:
146-
reader, closer, err = h.syncReader.PendingState()
146+
reader, closer, err = h.PendingState()
147147
case latest:
148148
reader, closer, err = h.bcReader.HeadState()
149149
case hash:

0 commit comments

Comments
 (0)