Skip to content

Commit b109aee

Browse files
MSeveyGanesha Upadhyaya
authored andcommitted
chore: make sure all blocking chan calls are also watching for shutdown signals (#1328)
In the spirit of shutdown handling, I did a quick audit of the codebase for places where we had blocking channel calls and put them into select statements so that we can also watch for a shutdown signal. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> - **New Features** - Introduced a new "DA Included" status for blocks, indicating a higher level of finality. - Added support for out-of-order rollup blocks on DA and a termination condition related to sequencer double-signing. - Implemented a new `BlockSyncService` with functions to start syncing and handle block storage and broadcasting. - Created a `NewPendingBlocks` function to manage blocks that need to be published to the DA layer. - **Improvements** - Improved error handling by checking for context completion before sending data to channels, ensuring more informative error messages. - Enhanced the block confirmation process and block retrieval mechanism with updated terminology and functionality. - **Refactor** - Renamed various functions and methods to better reflect their purpose, such as `store.GetState`, `Manager.IsDAIncluded`, and `Manager.BlockStoreRetrieveLoop`. - Removed unused functions like `Manager.saveValidatorsToStore` and `Manager.getLastStateValidators`. - **Bug Fixes** - Fixed potential goroutine leaks by handling context cancellation in `newTxValidator`, `BroadcastTxCommit`, and `BroadcastTxSync` functions. - **Tests** - Updated test assertions from `assert` to `require` to ensure immediate failure upon encountering errors during testing. - **Documentation** - Updated documentation to reflect changes in block confirmation terminology and the introduction of the "DA Included" concept. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 30b0a58 commit b109aee

5 files changed

Lines changed: 51 additions & 14 deletions

File tree

block/manager.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/cometbft/cometbft/proxy"
1717
cmtypes "github.com/cometbft/cometbft/types"
1818
"github.com/libp2p/go-libp2p/core/crypto"
19+
"github.com/pkg/errors"
1920
"go.uber.org/multierr"
2021

2122
"github.com/rollkit/rollkit/config"
@@ -426,6 +427,17 @@ func (m *Manager) BlockStoreRetrieveLoop(ctx context.Context) {
426427
}
427428
daHeight := atomic.LoadUint64(&m.daHeight)
428429
for _, block := range blocks {
430+
// Check for shut down event prior to logging
431+
// and sending block to blockInCh. The reason
432+
// for checking for the shutdown event
433+
// separately is due to the inconsistent nature
434+
// of the select statement when multiple cases
435+
// are satisfied.
436+
select {
437+
case <-ctx.Done():
438+
return
439+
default:
440+
}
429441
m.logger.Debug("block retrieved from p2p block sync", "blockHeight", block.Height(), "daHeight", daHeight)
430442
m.blockInCh <- newBlockEvent{block, daHeight}
431443
}
@@ -501,6 +513,17 @@ func (m *Manager) processNextDABlock(ctx context.Context) error {
501513
m.blockCache.setDAIncluded(blockHash)
502514
m.logger.Info("block marked as DA included", "blockHeight", block.Height(), "blockHash", blockHash)
503515
if !m.blockCache.isSeen(blockHash) {
516+
// Check for shut down event prior to logging
517+
// and sending block to blockInCh. The reason
518+
// for checking for the shutdown event
519+
// separately is due to the inconsistent nature
520+
// of the select statement when multiple cases
521+
// are satisfied.
522+
select {
523+
case <-ctx.Done():
524+
return errors.WithMessage(ctx.Err(), "unable to send block to blockInCh, context done")
525+
default:
526+
}
504527
m.blockInCh <- newBlockEvent{block, daHeight}
505528
}
506529
}
@@ -689,11 +712,13 @@ func (m *Manager) publishBlock(ctx context.Context) error {
689712
if err != nil {
690713
return err
691714
}
692-
693-
// Check if the node has shutdown prior to publishing to channels
715+
// Check for shut down event prior to sending the header and block to
716+
// their respective channels. The reason for checking for the shutdown
717+
// event separately is due to the inconsistent nature of the select
718+
// statement when multiple cases are satisfied.
694719
select {
695720
case <-ctx.Done():
696-
return nil
721+
return errors.WithMessage(ctx.Err(), "unable to send header and block, context done")
697722
default:
698723
}
699724

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ require (
2121
github.com/libp2p/go-libp2p-kad-dht v0.23.0
2222
github.com/libp2p/go-libp2p-pubsub v0.9.3
2323
github.com/multiformats/go-multiaddr v0.12.0
24+
github.com/pkg/errors v0.9.1
2425
github.com/prometheus/client_golang v1.17.0
2526
github.com/rollkit/go-da v0.0.0-20231117151938-ee3b613d7a3a
2627
github.com/rs/cors v1.10.1
@@ -132,7 +133,6 @@ require (
132133
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
133134
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
134135
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect
135-
github.com/pkg/errors v0.9.1 // indirect
136136
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
137137
github.com/polydawn/refmt v0.89.0 // indirect
138138
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect

node/full.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,11 @@ func (n *FullNode) newTxValidator() p2p.GossipValidator {
400400
n.Logger.Debug("transaction received", "bytes", len(m.Data))
401401
checkTxResCh := make(chan *abci.ResponseCheckTx, 1)
402402
err := n.Mempool.CheckTx(m.Data, func(resp *abci.ResponseCheckTx) {
403-
checkTxResCh <- resp
403+
select {
404+
case <-n.ctx.Done():
405+
return
406+
case checkTxResCh <- resp:
407+
}
404408
}, mempool.TxInfo{
405409
SenderID: n.mempoolIDs.GetForPeer(m.From),
406410
SenderP2PID: corep2p.ID(m.From),

node/full_client.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,11 @@ func (c *FullClient) BroadcastTxCommit(ctx context.Context, tx cmtypes.Tx) (*cty
120120
// add to mempool and wait for CheckTx result
121121
checkTxResCh := make(chan *abci.ResponseCheckTx, 1)
122122
err = c.node.Mempool.CheckTx(tx, func(res *abci.ResponseCheckTx) {
123-
checkTxResCh <- res
123+
select {
124+
case <-ctx.Done():
125+
return
126+
case checkTxResCh <- res:
127+
}
124128
}, mempool.TxInfo{})
125129
if err != nil {
126130
c.Logger.Error("Error on broadcastTxCommit", "err", err)
@@ -198,7 +202,11 @@ func (c *FullClient) BroadcastTxAsync(ctx context.Context, tx cmtypes.Tx) (*ctyp
198202
func (c *FullClient) BroadcastTxSync(ctx context.Context, tx cmtypes.Tx) (*ctypes.ResultBroadcastTx, error) {
199203
resCh := make(chan *abci.ResponseCheckTx, 1)
200204
err := c.node.Mempool.CheckTx(tx, func(res *abci.ResponseCheckTx) {
201-
resCh <- res
205+
select {
206+
case <-ctx.Done():
207+
return
208+
case resCh <- res:
209+
}
202210
}, mempool.TxInfo{})
203211
if err != nil {
204212
return nil, err

rpc/json/ws_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,25 +47,25 @@ func TestWebSockets(t *testing.T) {
4747
}
4848
}
4949
`))
50-
assert.NoError(err)
50+
require.NoError(err)
5151

5252
err = conn.SetReadDeadline(time.Now().Add(1 * time.Second))
53-
assert.NoError(err)
53+
require.NoError(err)
5454
typ, msg, err := conn.ReadMessage()
55-
assert.NoError(err)
55+
require.NoError(err)
5656
assert.Equal(websocket.TextMessage, typ)
5757
assert.NotEmpty(msg)
5858

5959
// wait for new block event
6060
err = conn.SetReadDeadline(time.Now().Add(3 * time.Second))
61-
assert.NoError(err)
61+
require.NoError(err)
6262
typ, msg, err = conn.ReadMessage()
63-
assert.NoError(err)
63+
require.NoError(err)
6464
assert.Equal(websocket.TextMessage, typ)
6565
assert.NotEmpty(msg)
6666
var payload cmtypes.EventDataNewBlock
6767
err = json.Unmarshal(msg, &payload)
68-
assert.NoError(err)
68+
require.NoError(err)
6969
assert.NotNil(payload.ResultFinalizeBlock)
7070
assert.NotNil(payload.Block)
7171
assert.GreaterOrEqual(payload.Block.Height, int64(1))
@@ -79,6 +79,6 @@ func TestWebSockets(t *testing.T) {
7979
handler.ServeHTTP(rsp, req)
8080
assert.Equal(http.StatusOK, rsp.Code)
8181
jsonResp := response{}
82-
assert.NoError(json.Unmarshal(rsp.Body.Bytes(), &jsonResp))
82+
require.NoError(json.Unmarshal(rsp.Body.Bytes(), &jsonResp))
8383
assert.Nil(jsonResp.Error)
8484
}

0 commit comments

Comments
 (0)