-
Notifications
You must be signed in to change notification settings - Fork 974
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
245 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package header | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/tendermint/tendermint/types" | ||
) | ||
|
||
// CoreListener TODO @renaynay: document | ||
type CoreListener struct { | ||
ex *CoreExchange | ||
p2pSub *P2PSubscriber | ||
|
||
blockSub <-chan *types.Block | ||
|
||
ctx context.Context | ||
cancel context.CancelFunc | ||
} | ||
|
||
func NewCoreListener(ex *CoreExchange, p2pSub *P2PSubscriber) *CoreListener { | ||
return &CoreListener{ | ||
ex: ex, | ||
p2pSub: p2pSub, | ||
} | ||
} | ||
|
||
// Start kicks off the CoreListener listener loop. | ||
func (cl *CoreListener) Start(ctx context.Context) error { | ||
cl.ctx, cl.cancel = context.WithCancel(context.Background()) | ||
|
||
go cl.listen(ctx) | ||
return nil | ||
} | ||
|
||
// Stop stops the CoreListener listener loop. | ||
func (cl *CoreListener) Stop(context.Context) error { | ||
cl.cancel() | ||
return nil | ||
} | ||
|
||
// listen kicks off a loop, listening for new block events from Core, | ||
// generating ExtendedHeaders and broadcasting them to the header-sub | ||
// gossipsub network. | ||
func (cl *CoreListener) listen(ctx context.Context) { | ||
// start subscription to core node new block events | ||
err := cl.startBlockSubscription(ctx) | ||
if err != nil { | ||
log.Errorw("core-listener: starting subscription to core client", "err", err) | ||
return | ||
} | ||
|
||
for { | ||
select { | ||
case <-cl.ctx.Done(): | ||
if err := cl.cancelBlockSubscription(context.Background()); err != nil { | ||
log.Errorw("core-listener: canceling subscription to core", "err", err) | ||
} | ||
return | ||
default: | ||
// get next header from core | ||
next, err := cl.nextHeader(cl.ctx) | ||
if err != nil { | ||
log.Errorw("core-listener: getting next header", "err", err) | ||
return | ||
} | ||
if next == nil { | ||
log.Debugw("core-listener: no subsequent header, exiting listening service") | ||
return | ||
} | ||
// broadcast new ExtendedHeader | ||
err = cl.p2pSub.Broadcast(cl.ctx, next) | ||
if err != nil { | ||
log.Errorw("core-listener: broadcasting next header", "height", next.Height, | ||
"err", err) | ||
return | ||
} | ||
} | ||
} | ||
} | ||
|
||
// startBlockSubscription starts the CoreListener's subscription to new block events | ||
// from Core. | ||
func (cl *CoreListener) startBlockSubscription(ctx context.Context) error { | ||
if cl.blockSub != nil { | ||
return fmt.Errorf("subscription already started") | ||
} | ||
|
||
var err error | ||
cl.blockSub, err = cl.ex.fetcher.SubscribeNewBlockEvent(ctx) | ||
|
||
return err | ||
} | ||
|
||
// cancelBlockSubscription stops the CoreListener's subscription to new block events | ||
// from Core. | ||
func (cl *CoreListener) cancelBlockSubscription(ctx context.Context) error { | ||
return cl.ex.fetcher.UnsubscribeNewBlockEvent(ctx) | ||
} | ||
|
||
// nextHeader returns the next latest header from Core. | ||
func (cl *CoreListener) nextHeader(ctx context.Context) (*ExtendedHeader, error) { | ||
select { | ||
case <-ctx.Done(): | ||
return nil, nil | ||
case newBlock, ok := <-cl.blockSub: | ||
if !ok { | ||
return nil, fmt.Errorf("subscription closed") | ||
} | ||
return cl.ex.generateExtendedHeaderFromBlock(newBlock) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package header | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
mdutils "github.com/ipfs/go-merkledag/test" | ||
pubsub "github.com/libp2p/go-libp2p-pubsub" | ||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/celestiaorg/celestia-node/core" | ||
) | ||
|
||
// TestCoreListener tests the lifecycle of the core listener. | ||
func TestCoreListener(t *testing.T) { | ||
// create mocknet with two pubsub endpoints | ||
ps1, ps2 := createMocknetWithTwoPubsubEndpoints(t) | ||
// create second subscription endpoint to listen for CoreListener's pubsub messages | ||
topic2, err := ps2.Join(PubSubTopic) | ||
require.NoError(t, err) | ||
sub, err := topic2.Subscribe() | ||
require.NoError(t, err) | ||
|
||
// create one block to store as Head in local store and then unsubscribe from block events | ||
fetcher := createCoreFetcher(t) | ||
|
||
// create CoreListener and start listening | ||
cl := createCoreListener(t, fetcher, ps1) | ||
|
||
ctx, cancel := context.WithCancel(context.Background()) | ||
t.Cleanup(cancel) | ||
|
||
err = cl.Start(ctx) | ||
require.NoError(t, err) | ||
|
||
// ensure headers are getting broadcasted to the gossipsub topic | ||
msg, err := sub.Next(context.Background()) | ||
require.NoError(t, err) | ||
|
||
var resp ExtendedHeader | ||
err = resp.UnmarshalBinary(msg.Data) | ||
require.NoError(t, err) | ||
require.Equal(t, 1, int(resp.Height)) | ||
|
||
require.NoError(t, cl.cancelBlockSubscription(context.Background())) | ||
} | ||
|
||
func createMocknetWithTwoPubsubEndpoints(t *testing.T) (*pubsub.PubSub, *pubsub.PubSub) { | ||
host1, host2 := createMocknet(context.Background(), t) | ||
// create pubsub for host | ||
ps1, err := pubsub.NewGossipSub(context.Background(), host1, | ||
pubsub.WithMessageSignaturePolicy(pubsub.StrictNoSign)) | ||
require.NoError(t, err) | ||
// create pubsub for peer-side (to test broadcast comes through network) | ||
ps2, err := pubsub.NewGossipSub(context.Background(), host2, | ||
pubsub.WithMessageSignaturePolicy(pubsub.StrictNoSign)) | ||
require.NoError(t, err) | ||
return ps1, ps2 | ||
} | ||
|
||
func createCoreListener( | ||
t *testing.T, | ||
fetcher *core.BlockFetcher, | ||
ps *pubsub.PubSub, | ||
) *CoreListener { | ||
// create all sub-services necessary for CoreListener | ||
ex := NewCoreExchange(fetcher, mdutils.Mock()) | ||
|
||
p2pSub := NewP2PSubscriber(ps, nil) | ||
err := p2pSub.Start(context.Background()) | ||
require.NoError(t, err) | ||
t.Cleanup(func() { | ||
p2pSub.Stop(context.Background()) //nolint:errcheck | ||
}) | ||
|
||
return NewCoreListener(ex, p2pSub) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters