Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
fe24824
refactor: unicast router
bryanchriswhite Jun 19, 2023
1277859
chore: cleanup TODOs
bryanchriswhite Jun 22, 2023
871af48
chore: add background message
bryanchriswhite Jun 16, 2023
013c433
chore: add `Router#Close()`
bryanchriswhite Jun 22, 2023
4f998ee
chore: separate raintree & bg protocol IDs
bryanchriswhite Jun 22, 2023
1c9c18c
chore: generate `PocketEnvelope` nonce in `PackMessage()`
bryanchriswhite Jun 22, 2023
f9a0c10
refactor: add `Handler` to router config validation
bryanchriswhite Jun 22, 2023
0bdffbd
refactor: raintree router
bryanchriswhite Jun 22, 2023
2b40776
refactor: background router
bryanchriswhite Jun 22, 2023
213f294
refactor: integrate bg router
bryanchriswhite Jun 22, 2023
437afc8
refactor: staked actor router peer discovery
bryanchriswhite Jun 22, 2023
43cf671
test: post-refactor updates
bryanchriswhite Jun 22, 2023
4b19d8f
Merge remote-tracking branch 'pokt/main' into refactor/unicast-router
bryanchriswhite Jun 22, 2023
cf886a7
Merge branch 'refactor/unicast-router' into feat/integrate-bg-router
bryanchriswhite Jun 22, 2023
048e306
fix: gofmt
bryanchriswhite Jun 23, 2023
d7278b8
Merge remote-tracking branch 'pokt/main' into refactor/unicast-router
bryanchriswhite Jun 23, 2023
acc1d59
Merge branch 'refactor/unicast-router' into feat/integrate-bg-router
bryanchriswhite Jun 23, 2023
9ab2a5d
chore: fix typo in comment
bryanchriswhite Jun 26, 2023
dce1bac
chore: add debug log
bryanchriswhite Jun 26, 2023
8dc2852
chore: fix field comment out of place
bryanchriswhite Jun 26, 2023
a6d4b52
fix: imports
bryanchriswhite Jun 26, 2023
87d1fa9
Merge branch 'refactor/unicast-router' into feat/integrate-bg-router
bryanchriswhite Jun 26, 2023
d24407b
chore: bootstrap refactor / TECHDEBT
bryanchriswhite Jun 26, 2023
70ca573
fix: imports
bryanchriswhite Jun 26, 2023
8467f3a
chore: remove unused field
bryanchriswhite Jun 26, 2023
c3bc4c7
chore: cleanup unused test utils
bryanchriswhite Jun 27, 2023
3fdada6
chore: comment cleanup
bryanchriswhite Jun 28, 2023
39a7877
chore: add submodule TECHDEBT comments
bryanchriswhite Jun 28, 2023
049cbf5
chore: add missing godoc comments
bryanchriswhite Jun 28, 2023
79a1c6e
chore: cleanup unused garbage
bryanchriswhite Jun 28, 2023
a7c4bf6
fix: return error
bryanchriswhite Jun 28, 2023
904f17b
Merge remote-tracking branch 'pokt/main' into refactor/unicast-router
bryanchriswhite Jun 28, 2023
70b020b
Merge branch 'refactor/unicast-router' into feat/integrate-bg-router
bryanchriswhite Jun 28, 2023
8a54f1a
chore: router logging improvements
bryanchriswhite Jun 28, 2023
6795c96
fix: interim background router bootstrapping
bryanchriswhite Jun 28, 2023
0a3fac1
fix: `p2pModule#Send()` routing logic
bryanchriswhite Jun 28, 2023
b8f9a1a
chore: improve variable naming
bryanchriswhite Jun 28, 2023
de63d6d
chore: improve comments
bryanchriswhite Jun 28, 2023
1282e1a
chore: improve debug logging
bryanchriswhite Jun 28, 2023
5793b7f
chore: return early
bryanchriswhite Jun 28, 2023
95a3948
chore: add TECHDEBT comment
bryanchriswhite Jun 29, 2023
7cdc9e7
Merge remote-tracking branch 'pokt/main' into HEAD
bryanchriswhite Jun 29, 2023
fe42ab3
test: fix raintree message target test
bryanchriswhite Jun 29, 2023
60cd2bd
docs: update P2P readme
bryanchriswhite Jun 29, 2023
8354d79
docs: update table of contents
bryanchriswhite Jun 29, 2023
f7b0202
docs: tweak P2P readme
bryanchriswhite Jun 29, 2023
d2f33a4
chore: add godoc comment
bryanchriswhite Jun 29, 2023
b527d91
chore: remove warning log
bryanchriswhite Jun 29, 2023
73da86c
chore: convert `DISCUSS_THIS_COMMIT` to `TECHDEBT`
bryanchriswhite Jun 29, 2023
bf96542
Merge remote-tracking branch 'pokt/main' into feat/integrate-bg-router
bryanchriswhite Jun 30, 2023
4602283
fix: typo
bryanchriswhite Jul 3, 2023
65a8c94
chore: review suggestion improvements
bryanchriswhite Jul 4, 2023
519db25
fix: gofmt
bryanchriswhite Jul 4, 2023
7e7e6e7
docs: README improvements (review feedback)
bryanchriswhite Jul 4, 2023
f3437cb
docs: add architecture design language section
bryanchriswhite Jul 4, 2023
4f87921
chore: background router comment and var name cleanup
bryanchriswhite Jul 4, 2023
c113a36
chore: review feedback improvements
bryanchriswhite Jul 6, 2023
3356f63
chore: add issue # to TECHDEBT comment
bryanchriswhite Jul 6, 2023
157ecb6
docs: update TOC
bryanchriswhite Jul 6, 2023
30cf145
chore: add TODO README
bryanchriswhite Jul 6, 2023
40628c4
docs: improve legend definitions
bryanchriswhite Jul 6, 2023
8c0b8c3
docs: clarify broadcast table
bryanchriswhite Jul 6, 2023
5a4cc80
docs: fix mistake in peer discovery section
bryanchriswhite Jul 7, 2023
3e997f5
test: improve background router validation test
bryanchriswhite Jul 7, 2023
abd4789
chore: add error log
bryanchriswhite Jul 7, 2023
8c6ac68
fix: unstaked actor bootstrapping FSM transition
bryanchriswhite Jul 7, 2023
b76efdf
fix: goimports
bryanchriswhite Jul 7, 2023
66afa18
Merge remote-tracking branch 'pokt/main' into feat/integrate-bg-router
bryanchriswhite Jul 7, 2023
5aa0a5c
docs: update unicast/broadcast table
bryanchriswhite Jul 11, 2023
6fde86f
Merge branch 'main' into feat/integrate-bg-router
bryanchriswhite Jul 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion p2p/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ Peer discovery involves pairing peer IDs to their network addresses (multiaddr).
This pairing always has an associated TTL (time-to-live), near the end of which it must
be refreshed.

In the background gossip overlay network (`backgroundRouter`), peers will re-advertise themselves 7/8th through their TTL.
In the background gossip overlay network (`backgroundRouter`), peers will re-advertise themselves every 3 hours through their TTL (see: [`RoutingDiscovery#Advertise()`](https://github.com/libp2p/go-libp2p/blob/87c2561238cb0340ddb182c61be8dbbc7a12a780/p2p/discovery/routing/routing.go#L34) and [`ProviderManager#AddProvider()`](https://github.com/libp2p/go-libp2p-kad-dht/blob/v0.24.2/providers/providers_manager.go#L255)).
This refreshes the libp2p peerstore automatically.

In the raintree gossip overlay network (`raintreeRouter`), the libp2p peerstore is **NOT** currently refreshed _(TODO: [#859](https://github.com/pokt-network/network/isues/859))_.
Expand Down
1 change: 1 addition & 0 deletions p2p/background/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ func (rtr *backgroundRouter) bootstrap(ctx context.Context) error {
func (rtr *backgroundRouter) topicValidator(_ context.Context, _ libp2pPeer.ID, msg *pubsub.Message) bool {
var backgroundMsg typesP2P.BackgroundMessage
if err := proto.Unmarshal(msg.Data, &backgroundMsg); err != nil {
rtr.logger.Error().Err(err).Msg("unmarshalling Background message")
return false
}

Expand Down
180 changes: 126 additions & 54 deletions p2p/background/router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ import (
)

// https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2
const testIP6ServiceURL = "[2a00:1450:4005:802::2004]:8080"
const (
testIP6ServiceURL = "[2a00:1450:4005:802::2004]:8080"
invalidReceiveTimeout = time.Millisecond * 500
)

// TECHDEBT(#609): move & de-dup.
var (
Expand All @@ -42,7 +45,7 @@ var (
)

func TestBackgroundRouter_AddPeer(t *testing.T) {
testRouter := newTestRouter(t, nil, noopHandler)
testRouter := newTestRouter(t, nil, nil)
libp2pPStore := testRouter.host.Peerstore()

// NB: assert initial state
Expand Down Expand Up @@ -90,7 +93,7 @@ func TestBackgroundRouter_AddPeer(t *testing.T) {
}

func TestBackgroundRouter_RemovePeer(t *testing.T) {
testRouter := newTestRouter(t, nil, noopHandler)
testRouter := newTestRouter(t, nil, nil)
peerstore := testRouter.host.Peerstore()

// NB: assert initial state
Expand Down Expand Up @@ -124,69 +127,112 @@ func TestBackgroundRouter_RemovePeer(t *testing.T) {
}

func TestBackgroundRouter_Validation(t *testing.T) {
ctx := context.Background()
libp2pMockNet := mocknet.New()

invalidWireFormatData := []byte("test message")
invalidPocketEnvelope := &anypb.Any{
TypeUrl: "/test",
Value: invalidWireFormatData,
invalidProtoMessage := anypb.Any{
TypeUrl: "/notADefinedProtobufType",
Value: []byte("not a serialized protobuf"),
}
invalidPocketEnvelopeBz, err := proto.Marshal(invalidPocketEnvelope)
require.NoError(t, err)

invalidMessages := [][]byte{
invalidWireFormatData,
invalidPocketEnvelopeBz,
testCases := []struct {
name string
msgBz []byte
}{
{
name: "invalid BackgroundMessage",
// NB: `msgBz` would normally be a serialized `BackgroundMessage`.
msgBz: mustMarshal(t, &invalidProtoMessage),
},
{
name: "empty PocketEnvelope",
msgBz: mustMarshal(t, &typesP2P.BackgroundMessage{
// NB: `Data` is normally a serialized `PocketEnvelope`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appreciate the comments 🙌

Data: nil,
}),
},
{
name: "invalid PoketEnvelope",
msgBz: mustMarshal(t, &typesP2P.BackgroundMessage{
// NB: `Data` is normally a serialized `PocketEnvelope`.
Data: mustMarshal(t, &invalidProtoMessage),
}),
},
}

receivedChan := make(chan struct{})
// Set up test router as the receiver.
ctx := context.Background()
libp2pMockNet := mocknet.New()

receivedChan := make(chan []byte, 1)
receiverPrivKey, receiverPeer := newTestPeer(t)
receiverHost := newTestHost(t, libp2pMockNet, receiverPrivKey)
receiverRouter := newRouterWithSelfPeerAndHost(t, receiverPeer, receiverHost, func(data []byte) error {
receivedChan <- struct{}{}
return nil
})
receiverRouter := newRouterWithSelfPeerAndHost(
t, receiverPeer,
receiverHost,
func(data []byte) error {
receivedChan <- data
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice change

return nil
},
)

t.Cleanup(func() {
err := receiverRouter.Close()
require.NoError(t, err)
})

senderPrivKey, _ := newTestPeer(t)
senderHost := newTestHost(t, libp2pMockNet, senderPrivKey)
gossipPubsub, err := pubsub.NewGossipSub(ctx, senderHost)
// Wrap `receiverRouter#topicValidator` to make assertions by.
// Existing topic validator must be unregistered first.
err := receiverRouter.gossipSub.UnregisterTopicValidator(protocol.BackgroundTopicStr)
require.NoError(t, err)

err = libp2pMockNet.LinkAll()
require.NoError(t, err)
// Register topic validator wrapper.
err = receiverRouter.gossipSub.RegisterTopicValidator(
protocol.BackgroundTopicStr,
func(ctx context.Context, peerID libp2pPeer.ID, msg *pubsub.Message) bool {
msgIsValid := receiverRouter.topicValidator(ctx, peerID, msg)
require.Falsef(t, msgIsValid, "expected message to be invalid")

receiverAddrInfo, err := utils.Libp2pAddrInfoFromPeer(receiverPeer)
require.NoError(t, err)

err = senderHost.Connect(ctx, receiverAddrInfo)
require.NoError(t, err)

topic, err := gossipPubsub.Join(protocol.BackgroundTopicStr)
return msgIsValid
},
)
require.NoError(t, err)

for _, invalidMessageBz := range invalidMessages {
err = topic.Publish(ctx, invalidMessageBz)
require.NoError(t, err)
}

select {
case <-time.After(time.Second * 2):
// TECHDEBT: find a better way to prove that pre-propagation validation
// works as expected. Ideally, we should be able to distinguish which
// invalid message was received in the event of failure.
//
// CONSIDERATION: we could use the telemetry module mock to set expectations
// for validation failure telemetry calls, which would probably be useful in
// their own right.
case <-receivedChan:
t.Fatal("expected message to not be received")
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
senderPrivKey, _ := newTestPeer(t)
senderHost := newTestHost(t, libp2pMockNet, senderPrivKey)
gossipPubsub, err := pubsub.NewGossipSub(ctx, senderHost)
require.NoError(t, err)

err = libp2pMockNet.LinkAll()
require.NoError(t, err)

receiverAddrInfo, err := utils.Libp2pAddrInfoFromPeer(receiverPeer)
require.NoError(t, err)

err = senderHost.Connect(ctx, receiverAddrInfo)
require.NoError(t, err)

topic, err := gossipPubsub.Join(protocol.BackgroundTopicStr)
require.NoError(t, err)

err = topic.Publish(ctx, testCase.msgBz)
require.NoError(t, err)

// Destroy previous topic and sender instances to start with new ones
// for each test case.
t.Cleanup(func() {
_ = topic.Close()
_ = senderHost.Close()
})

// Ensure no messages were handled at the end of each test case for
// async errors.
select {
case <-receivedChan:
t.Fatal("no messages should have been handled by receiver router")
case <-time.After(invalidReceiveTimeout):
// no error, continue
}
})
}
}

Expand Down Expand Up @@ -234,9 +280,9 @@ func TestBackgroundRouter_Broadcast(t *testing.T) {
expectedPeerIDs[i] = host.ID().String()
newRouterWithSelfPeerAndHost(t, peer, host, func(data []byte) error {
seenMessagesMutext.Lock()
broadcastWaitgroup.Done()
defer seenMessagesMutext.Unlock()
seenMessages[host.ID().String()] = struct{}{}
seenMessagesMutext.Unlock()
broadcastWaitgroup.Done()
return nil
})
}
Expand All @@ -246,7 +292,7 @@ func TestBackgroundRouter_Broadcast(t *testing.T) {

// set up a test backgroundRouter
testRouterHost := newTestHost(t, libp2pMockNet, privKey)
testRouter := newRouterWithSelfPeerAndHost(t, selfPeer, testRouterHost, noopHandler)
testRouter := newRouterWithSelfPeerAndHost(t, selfPeer, testRouterHost, nil)
testHosts = append(testHosts, testRouterHost)

// simulate network links between each to every other
Expand Down Expand Up @@ -331,7 +377,11 @@ func bootstrap(t *testing.T, ctx context.Context, testHosts []libp2pHost.Host) {
}

// TECHDEBT(#609): move & de-duplicate
func newTestRouter(t *testing.T, libp2pMockNet mocknet.Mocknet, handler typesP2P.MessageHandler) *backgroundRouter {
func newTestRouter(
t *testing.T,
libp2pMockNet mocknet.Mocknet,
handler typesP2P.MessageHandler,
) *backgroundRouter {
t.Helper()

privKey, selfPeer := newTestPeer(t)
Expand All @@ -349,7 +399,12 @@ func newTestRouter(t *testing.T, libp2pMockNet mocknet.Mocknet, handler typesP2P
return newRouterWithSelfPeerAndHost(t, selfPeer, host, handler)
}

func newRouterWithSelfPeerAndHost(t *testing.T, selfPeer typesP2P.Peer, host libp2pHost.Host, handler typesP2P.MessageHandler) *backgroundRouter {
func newRouterWithSelfPeerAndHost(
t *testing.T,
selfPeer typesP2P.Peer,
host libp2pHost.Host,
handler typesP2P.MessageHandler,
) *backgroundRouter {
t.Helper()

ctrl := gomock.NewController(t)
Expand All @@ -374,6 +429,10 @@ func newRouterWithSelfPeerAndHost(t *testing.T, selfPeer typesP2P.Peer, host lib
err := pstore.AddPeer(selfPeer)
require.NoError(t, err)

if handler == nil {
handler = noopHandler
}

router, err := Create(busMock, &config.BackgroundConfig{
Addr: selfPeer.GetAddress(),
PeerstoreProvider: pstoreProviderMock,
Expand Down Expand Up @@ -423,7 +482,11 @@ func newMockNetHostFromPeer(
return host
}

func newTestHost(t *testing.T, mockNet mocknet.Mocknet, privKey cryptoPocket.PrivateKey) libp2pHost.Host {
func newTestHost(
t *testing.T,
mockNet mocknet.Mocknet,
privKey cryptoPocket.PrivateKey,
) libp2pHost.Host {
t.Helper()

// listen on random port on loopback interface
Expand All @@ -436,3 +499,12 @@ func newTestHost(t *testing.T, mockNet mocknet.Mocknet, privKey cryptoPocket.Pri
// construct mock host
return newMockNetHostFromPeer(t, mockNet, privKey, peer)
}

func mustMarshal(t *testing.T, msg proto.Message) []byte {
t.Helper()

msgBz, err := proto.Marshal(msg)
require.NoError(t, err)

return msgBz
}
20 changes: 16 additions & 4 deletions p2p/event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,25 @@ func (m *p2pModule) HandleEvent(event *anypb.Any) error {
m.logger.Debug().Fields(messaging.TransitionEventToMap(stateMachineTransitionEvent)).Msg("Received state machine transition event")

if stateMachineTransitionEvent.NewState == string(coreTypes.StateMachineState_P2P_Bootstrapping) {
if m.stakedActorRouter.GetPeerstore().Size() == 0 {
m.logger.Warn().Msg("No peers in addrbook, bootstrapping")
staked, err := m.isStakedActor()
if err != nil {
return err
}
if staked {
// TECHDEBT(#859): this will never happen as the peerstore is
// seeded from consensus during P2P module construction.
if m.stakedActorRouter.GetPeerstore().Size() == 0 {
m.logger.Warn().Msg("No peers in peerstore, bootstrapping")

if err := m.bootstrap(); err != nil {
return err
if err := m.bootstrap(); err != nil {
return err
}
}
}

// TECHDEBT(#859): for unstaked actors, unstaked actor (background)
// router bootstrapping SHOULD complete before the event below is sent.

m.logger.Info().Bool("TODO", true).Msg("Advertise self to network")
if err := m.GetBus().GetStateMachineModule().SendEvent(coreTypes.StateMachineEvent_P2P_IsBootstrapped); err != nil {
return err
Expand Down