Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[P2P] refactor: message handling #763

Merged
merged 14 commits into from
May 31, 2023
Merged

Conversation

bryanchriswhite
Copy link
Contributor

@bryanchriswhite bryanchriswhite commented May 17, 2023

Description

Before

The P2P module is responsible for handling incoming messages from the router's host. When it receives a message, it calls into the router to unpack the RainTreeMessage (and facilitate further broadcast propagation). The resulting PocketEnvelope is returned to the P2P module to be emitted over the application event bus.

classDiagram
    class RainTreeMessage {
        <<protobuf>>
        +Level uint32
        +Data []byte
        +Nonce uint64
    }
    
    class PocketEnvelope {
        <<protobuf>>
        +Content *anypb.Any   
    }

    RainTreeMessage --* PocketEnvelope : serialized as `Data`
    
      
    class P2PModule {
        -handleNetworkData([]byte) error
        -handleStream(stream libp2pNetwork.Stream)
        -readStream(stream libp2pNetwork.Stream)
    }

    class RainTreeRouter {
        +HandleNetworkData func([]byte) ([]byte, error)
    }

    RainTreeRouter --> P2PModule
    P2PModule --> RainTreeRouter
    RainTreeRouter --o RainTreeMessage
    P2PModule --o PocketEnvelope
Loading

After

The router encapsulates handling incoming RainTreeMessages, unpacking them and passing them along to the P2P module as serialized PocketEnvelopes. The P2P module then deserializes and emits them over the application event bus.

classDiagram
    class RainTreeMessage {
        <<protobuf>>
        +Level uint32
        +Data []byte
        +Nonce uint64
    }
    
    class PocketEnvelope {
        <<protobuf>>
        +Content *anypb.Any
    }

    RainTreeMessage --* PocketEnvelope : serialized as `Data`
    
    class P2PModule {
        -handlePocketEnvelope([]byte) error
    }

    class RainTreeRouter {
        -handler RouterHandler
        -handleRainTreeMsg([]byte) ([]byte, error)
        -handleStream(stream libp2pNetwork.Stream)
        -readStream(stream libp2pNetwork.Stream)
    }

    RainTreeRouter --> P2PModule : `handler` == `handlePocketEnvelope`
    RainTreeRouter --o RainTreeMessage

    P2PModule --o PocketEnvelope
Loading

Issue

Second deliverable in #762

Type of change

Please mark the relevant option(s):

  • New feature, functionality or library
  • Bug fix
  • Code health or cleanup
  • Major breaking change
  • Documentation
  • Other

List of changes

  • Added Handler field to RainTreeConfig & BackgroundConfig
  • Refactored rainTreeRouter logging methods
  • Renamed rainTreeRouter#HandleNetworkData() to #handleRainTreeMsg()
  • Renamed p2pModule#handleNetworkData() to #handleAppData()
  • Added -tags=test to all test make targets
  • Fixed mockdns usage in TestP2PModule_Insecure_Error test
  • Moved message handling from p2p module to router

Testing

  • make develop_test; if any code changes were made
  • make test_e2e on k8s LocalNet; if any code changes were made
  • e2e-devnet-test passes tests on DevNet; if any code was changed
  • Docker Compose LocalNet; if any major functionality was changed or introduced
  • k8s LocalNet; if any infrastructure or configuration changes were made

Required Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added, or updated, godoc format comments on touched members (see: tip.golang.org/doc/comment)
  • I have tested my changes using the available tooling
  • I have updated the corresponding CHANGELOG

If Applicable Checklist

  • I have updated the corresponding README(s); local and/or global
  • I have added tests that prove my fix is effective or that my feature works
  • I have added, or updated, mermaid.js diagrams in the corresponding README(s)
  • I have added, or updated, documentation and mermaid.js diagrams in shared/docs/* if I updated shared/*README(s)

@bryanchriswhite bryanchriswhite added the p2p P2P specific changes label May 17, 2023
@bryanchriswhite bryanchriswhite self-assigned this May 17, 2023
@reviewpad reviewpad bot added the medium label May 17, 2023
@Olshansk Olshansk removed the medium label May 17, 2023
@reviewpad reviewpad bot added the medium Pull request is medium label May 17, 2023
@bryanchriswhite bryanchriswhite force-pushed the refactor/message-handling branch from 461d794 to d37d14a Compare May 19, 2023 09:15
@reviewpad reviewpad bot added large Pull request is large and removed medium Pull request is medium labels May 19, 2023
@bryanchriswhite bryanchriswhite force-pushed the refactor/message-handling branch from d37d14a to 90d9311 Compare May 19, 2023 09:38
@bryanchriswhite bryanchriswhite added the gpt review Triggers a code review from https://github.com/anc95/ChatGPT-CodeReview label May 19, 2023
@bryanchriswhite bryanchriswhite force-pushed the refactor/message-handling branch from 65ca42d to a87e5cd Compare May 19, 2023 10:45
@bryanchriswhite bryanchriswhite marked this pull request as ready for review May 19, 2023 11:04
Copy link
Member

@Olshansk Olshansk left a comment

Choose a reason for hiding this comment

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

Wdyt about adding the mermaid diagram in the github description to the README for p2p?

p2p/CHANGELOG.md Show resolved Hide resolved
p2p/module.go Outdated Show resolved Hide resolved
p2p/module.go Outdated Show resolved Hide resolved
@@ -1,3 +1,5 @@
//go:build test
Copy link
Member

Choose a reason for hiding this comment

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

Should we add a linter for this? Dima recently added a custom one in build/linters/tests.go and it looks like we have access to the File.Name via the dsl matcher, but I don't know if there's any easy way to check for the first line.

Can be done in a separate commit, not a blocker.

type File struct {
	// Name is a file base name.
	Name String

	// PkgPath is a file package path.
	// Examples: "io/ioutil", "strings", "github.com/quasilyte/go-ruleguard/dsl".
	PkgPath String
}

Copy link
Contributor Author

@bryanchriswhite bryanchriswhite May 23, 2023

Choose a reason for hiding this comment

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

It's only necessary to add the test build tag to:

  1. non-test files in a non-internal package which exports a private member for testing purposes.
  2. test files which depend on something exported by a file which uses the build tag (assumes at least one instance of case 1).

Are you suggesting a linter which enforces the test build tag on all test files or something?

I don't suppose there would really be a prohibitive downside to adding the test tag in places where it's not strictly necessary. I can imagine an argument for either but am leaning towards "ubiquitous build tags" at the moment (unexpectedly):

  • ubiquitous build tags
    • pros
      • consistent
      • simpler
      • better justifies updates to the makefile (e.g. -tags test; necessary in either case)
    • cons
      • slightly unconventional
      • requires running tests via make targets OR adding tags manually (e.g. IDE run/test configs)
    • UX
      • go test runs no tests
  • only necessary build tags
    • pros
      • minimal impact on the codebase
    • cons
      • more mental overhead
      • less obvious when test(s) didn't run because of a missing tag
    • UX
      • go test runs some but not all tests


remotePeer, err := utils.PeerFromLibp2pStream(stream)
if err != nil {
rtr.logger.Debug().Err(err).Msg("getting remote remotePeer")
Copy link
Member

Choose a reason for hiding this comment

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

Why did you go with Debug instead of Error here?

Ditto below

Copy link
Contributor Author

@bryanchriswhite bryanchriswhite May 23, 2023

Choose a reason for hiding this comment

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

(see below)

In this case, my thinking was that this error only happens in the context of this logging helper function which is not a critical function. I didn't imagine that this logging helper producing an error would be useful to the end user (i.e. not actionable nor a useful signal). Perhaps I assume too much.


import libp2pNetwork "github.com/libp2p/go-libp2p/core/network"

// RainTreeRouter exports `rainTreeRouter` for testing purposes.
Copy link
Member

Choose a reason for hiding this comment

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

I like this design 💯

if err := stream.SetReadDeadline(newReadStreamDeadline()); err != nil {
// NB: tests using libp2p's `mocknet` rely on this not returning an error.
// `SetReadDeadline` not supported by `mocknet` streams.
rtr.logger.Debug().Err(err).Msg("setting stream read deadline")
Copy link
Member

Choose a reason for hiding this comment

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

Ditto. Noticed you're using Debug instead of Err for a lot of these. Why is that?

Copy link
Contributor Author

@bryanchriswhite bryanchriswhite May 23, 2023

Choose a reason for hiding this comment

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

Thank you for scrutinizing this, please continue to do so! 🙌

I was trying to be conservative with what we log to non-debug loggers. In this particular case, my thinking was that being unable to set the read deadline isn't actionable and isn't really useful as a signal for end-users.

p2p/raintree/router.go Outdated Show resolved Hide resolved
p2p/raintree/router.go Show resolved Hide resolved
p2p/raintree/router.go Outdated Show resolved Hide resolved
@bryanchriswhite
Copy link
Contributor Author

bryanchriswhite commented May 23, 2023

Wdyt about adding the mermaid diagram in the github description to the README for p2p?

@Olshansk I was planning on incorporating the diagrams from #505, which represents the composition of this and #769, into #732. My thinking was that the diagrams in this and #769 are trimmed down versions which only show what's relevant for understanding the change, whereas what I expect we want to keep in the repo is the representation of the desired state with sufficient context.

Do you imagine a step in between?

@bryanchriswhite bryanchriswhite mentioned this pull request May 23, 2023
20 tasks
* pokt/main:
  [Helm] Add ServiceMonitor to the helm chart (#767)
  Update PULL_REQUEST_TEMPLATE.md (#772)
  [CI/Infra] E2E tests on Argo Workflows (#737)
p2p/CHANGELOG.md Outdated
- Added -tags=test to all test make targets
- Fixed mockdns usage in `TestP2PModule_Insecure_Error` test
- Moved message handling from p2p module to router

## [0.0.0.50] - 2023-05-08

- Removed unused `Transport` interface

This comment was marked as outdated.

@bryanchriswhite bryanchriswhite force-pushed the refactor/message-handling branch from 66a0baa to 77d91f1 Compare May 23, 2023 13:08
p2p/CHANGELOG.md Outdated
- Added -tags=test to all test make targets
- Fixed mockdns usage in `TestP2PModule_Insecure_Error` test
- Moved message handling from p2p module to router

## [0.0.0.50] - 2023-05-08

- Removed unused `Transport` interface

This comment was marked as outdated.

Makefile Outdated Show resolved Hide resolved
Makefile Outdated Show resolved Hide resolved
* pokt/main:
  Update client to p1 in makefile
  change gitsha of private-keys.yaml (#787)
  Fix places where we request a password and don't check the nonInterac… (#788)
  [Testing] [Tooling] chore: replace `gocuke` & `go-mockdns` in go.mod (#782)
  [k8s] Rename `client` to `p1` in k8s localnet (#764)
  [Persistence] Refactors BlockStore Interface (#774)
  [BUG] Int casting issue when sending tx (#783)
  add public keys to private-keys.yaml (#779)
- Added -tags=test to all test make targets
- Fixed mockdns usage in `TestP2PModule_Insecure_Error` test
- Moved message handling from p2p module to router

## [0.0.0.51] - 2023-05-23

- Use the shared codec module when marshaling the data sent over the wire

Choose a reason for hiding this comment

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

Here's a brief review of the code patch:

  1. A new version (0.0.0.52) is being added with today's date.
  2. The RainTreeConfig and BackgroundConfig structs are updated to include a new field, Handler.
  3. Logging methods in the rainTreeRouter have been refactored.
  4. Methods rainTreeRouter#HandleNetworkData() and p2pModule#handleNetworkData() are renamed to #handleRainTreeMsg() and #handlePocketEnvelope(), respectively, for better consistency.
  5. The build flags now include -tags=test to all test make targets.
  6. An issue with mockdnswas fixed in the TestP2PModule_Insecure_Error test.
  7. Message handling is moved from the p2p module to the router.

Overall, the changes seem reasonably-safe and no significant risks or bugs stand out. One possible improvement suggestion is to ensure that unit tests are updated accordingly to reflect method name changes such as #handleRainTreeMsg() and #handlePocketEnvelope(). Additionally, it may be helpful to review the impact of refactored logging methods on overall system performance or log readability.

@codecov
Copy link

codecov bot commented May 26, 2023

Codecov Report

Patch and project coverage have no change.

Comparison is base (95cf73d) 0.00% compared to head (65ca42d) 0.00%.

❗ Current head 65ca42d differs from pull request most recent head 33b5b58. Consider uploading reports for the commit 33b5b58 to get more accurate results

Additional details and impacted files
@@     Coverage Diff     @@
##   main   #763   +/-   ##
===========================
===========================

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@@ -272,7 +276,7 @@ func testRainTreeCalls(t *testing.T, origNode string, networkSimulationConfig Te
mod := *p2pMod
p2pMod.host.SetStreamHandler(protocol.PoktProtocolID, func(stream libp2pNetwork.Stream) {
log.Printf("[valID: %s] Read\n", sURL)
(&mod).handleStream(stream)
(&mod).router.(*raintree.RainTreeRouter).HandleStream(stream)
wg.Done()
})
}

Choose a reason for hiding this comment

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

The code patch provided seems reasonable, but I have a few minor suggestions for improvement. Please consider the following:

  1. In line 19, add a comment to explain the purpose of moving the import statement and why it has been separated from the other import statements.

  2. Although not incorrect, you might want to change lines 272-276 to avoid using the pointer to 'mod'. Instead, directly use 'p2pMod'. This increases readability and reduces complexity:

    mod := p2pMod
    ...
    mod.router.(*raintree.RainTreeRouter).HandleStream(stream)
  3. Make sure that there are unit tests (or create new unit tests) that cover the changes introduced in this patch. The current tests should pass, and any new edge cases should also be considered when testing.

  4. Ensure that you follow the rest of the project's style and coding conventions when contributing your patch.

Overall, the code patch is generally fine, but addressing these points would lead to better quality code review.

p2p/raintree/router.go Show resolved Hide resolved
@bryanchriswhite bryanchriswhite merged commit fba11c3 into main May 31, 2023
bryanchriswhite added a commit that referenced this pull request May 31, 2023
* pokt/main:
  [P2P] refactor: message handling (#763)
  Remove coverage prep stage as this corrupts the coverage report (#792)
  [Utility] E2E Feature Path Template (#734)
@bryanchriswhite bryanchriswhite deleted the refactor/message-handling branch May 31, 2023 10:25
Olshansk pushed a commit that referenced this pull request Jun 1, 2023
## Description

### Before

The P2P module is responsible for handling incoming messages from the
router's host. When it receives a message, it calls into the router to
unpack the `RainTreeMessage` (and facilitate further broadcast
propagation). The resulting `PocketEnvelope` is returned to the P2P
module to be emitted over the application event bus.

```mermaid
classDiagram
    class RainTreeMessage {
        <<protobuf>>
        +Level uint32
        +Data []byte
        +Nonce uint64
    }
    
    class PocketEnvelope {
        <<protobuf>>
        +Content *anypb.Any   
    }

    RainTreeMessage --* PocketEnvelope : serialized as `Data`
    
      
    class P2PModule {
        -handleNetworkData([]byte) error
        -handleStream(stream libp2pNetwork.Stream)
        -readStream(stream libp2pNetwork.Stream)
    }

    class RainTreeRouter {
        +HandleNetworkData func([]byte) ([]byte, error)
    }

    RainTreeRouter --> P2PModule
    P2PModule --> RainTreeRouter
    RainTreeRouter --o RainTreeMessage
    P2PModule --o PocketEnvelope
```

### After

The router encapsulates handling incoming `RainTreeMessage`s, unpacking
them and passing them along to the P2P module as serialized
`PocketEnvelope`s. The P2P module then deserializes and emits them over
the application event bus.

```mermaid
classDiagram
    class RainTreeMessage {
        <<protobuf>>
        +Level uint32
        +Data []byte
        +Nonce uint64
    }
    
    class PocketEnvelope {
        <<protobuf>>
        +Content *anypb.Any
    }

    RainTreeMessage --* PocketEnvelope : serialized as `Data`
    
    class P2PModule {
        -handlePocketEnvelope([]byte) error
    }

    class RainTreeRouter {
        -handler RouterHandler
        -handleRainTreeMsg([]byte) ([]byte, error)
        -handleStream(stream libp2pNetwork.Stream)
        -readStream(stream libp2pNetwork.Stream)
    }

    RainTreeRouter --> P2PModule : `handler` == `handlePocketEnvelope`
    RainTreeRouter --o RainTreeMessage

    P2PModule --o PocketEnvelope
```

## Issue

Second deliverable in #762 

## Type of change

Please mark the relevant option(s):

- [ ] New feature, functionality or library
- [ ] Bug fix
- [x] Code health or cleanup
- [ ] Major breaking change
- [ ] Documentation
- [ ] Other <!-- add details here if it a different type of change -->

## List of changes

- Added `Handler` field to `RainTreeConfig` & `BackgroundConfig`
- Refactored `rainTreeRouter` logging methods
- Renamed `rainTreeRouter#HandleNetworkData()` to `#handleRainTreeMsg()`
- Renamed `p2pModule#handleNetworkData()` to `#handleAppData()`
- Added -tags=test to all test make targets
- Fixed mockdns usage in `TestP2PModule_Insecure_Error` test
- Moved message handling from p2p module to router

## Testing

- [ ] `make develop_test`; if any code changes were made
- [ ] `make test_e2e` on [k8s
LocalNet](https://github.com/pokt-network/pocket/blob/main/build/localnet/README.md);
if any code changes were made
- [ ] `e2e-devnet-test` passes tests on
[DevNet](https://pocketnetwork.notion.site/How-to-DevNet-ff1598f27efe44c09f34e2aa0051f0dd);
if any code was changed
- [x] [Docker Compose
LocalNet](https://github.com/pokt-network/pocket/blob/main/docs/development/README.md);
if any major functionality was changed or introduced
- [x] [k8s
LocalNet](https://github.com/pokt-network/pocket/blob/main/build/localnet/README.md);
if any infrastructure or configuration changes were made

## Required Checklist

- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have added, or updated, [`godoc` format
comments](https://go.dev/blog/godoc) on touched members (see:
[tip.golang.org/doc/comment](https://tip.golang.org/doc/comment))
- [ ] I have tested my changes using the available tooling
- [ ] I have updated the corresponding CHANGELOG

### If Applicable Checklist

- [ ] I have updated the corresponding README(s); local and/or global
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] I have added, or updated,
[mermaid.js](https://mermaid-js.github.io) diagrams in the corresponding
README(s)
- [ ] I have added, or updated, documentation and
[mermaid.js](https://mermaid-js.github.io) diagrams in `shared/docs/*`
if I updated `shared/*`README(s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gpt review Triggers a code review from https://github.com/anc95/ChatGPT-CodeReview large Pull request is large p2p P2P specific changes waiting-for-review
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants