Skip to content

Conversation

Teebor-Choka
Copy link
Contributor

@Teebor-Choka Teebor-Choka commented Jun 19, 2025

This pull request introduces several changes across multiple modules, focusing on dependency updates, feature enhancements, and database schema modifications. The most significant updates include upgrading the libp2p dependencies, adding conditional compilation for Tokio runtime support, deprecating and replacing fields in the PeerStatus struct, and introducing a new database migration to handle these schema changes.

Dependency Updates:

  • Upgraded libp2p to version 0.56.0, libp2p-identity to 0.2.12, and libp2p-stream to 0.4.0-alpha in Cargo.toml. These updates ensure compatibility with the latest features and bug fixes.

Feature Enhancements:

  • Added conditional compilation for the Tokio runtime by introducing the runtime-tokio feature in chain/rpc/src/lib.rs and chain/rpc/src/transport.rs. This includes the use of ReqwestClient and additional tracing capabilities. [1] [2] [3]

Database Schema Changes:

  • Replaced the is_public, ignored, and peer_version fields in the PeerStatus struct with a new ignored_until field to better represent peer ignore periods. Updated related logic and tests accordingly. [1] [2] [3]
  • Added a new migration (m20250701_000028_peers_deprecate_fields) to handle schema changes for both SQLite and Postgres. This includes dropping deprecated fields and adding the new ignored_until field. [1] [2] [3]

Codebase Improvements:

  • Implemented a custom Debug trait for the OutgoingPacket struct to improve debugging output.

Additional Dependency Additions:

  • Added hopr-platform and hopr-async-runtime dependencies to support new runtime features and time utilities. [1] [2]

Closes #7288
Clsoes #7253

@Teebor-Choka Teebor-Choka self-assigned this Jun 19, 2025
Copy link
Contributor

coderabbitai bot commented Jun 19, 2025

Warning

Rate limit exceeded

@ausias-armesto has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 3 minutes and 55 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between e07f9e0 and 13a517e.

📒 Files selected for processing (1)
  • .github/workflows/build-docker.yaml (4 hunks)
📝 Walkthrough
## Walkthrough

This update removes the peer version and public status fields from the peer data model, database schema, and all related logic, including REST API endpoints and peer selection strategies. It also updates several dependencies, enhances tracing instrumentation, adjusts probe configuration defaults, and improves logging consistency across multiple modules. Additionally, it introduces packet capture support with pcap and UDP output, adds a Wireshark Lua dissector for HOPR protocols, refactors serialization of probe messages to manual byte-level encoding, and replaces the `spawn_as_abortable` function with a macro variant for async task management.

## Changes

| Files / Paths                                                                 | Change Summary                                                                                               |
|-------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|
| db/api/src/peers.rs, db/sql/src/peers.rs, hoprd/rest-api/src/node.rs, hoprd/rest-api/src/peers.rs, logic/strategy/src/promiscuous.rs | Removed all logic and struct fields related to peer version and public status; updated constructors and APIs |
| db/migration/src/m20250701_000028_peers_deprecate_fields.rs, db/migration/src/lib.rs | Added migration to remove `Public` and `Version` columns from `NetworkPeer` table for SQLite and Postgres   |
| db/sql/src/db.rs                                                             | Updated tests to remove references to deprecated peer fields                                                |
| Cargo.toml, logic/strategy/Cargo.toml                                         | Updated dependencies: `libp2p`, `libp2p-identity`, `libp2p-stream`; removed `semver` from strategy crate    |
| transport/network/src/network.rs, transport/api/src/network_notifier.rs       | Removed peer version from network update logic; simplified method signatures; improved tracing              |
| transport/p2p/src/behavior/discovery.rs, transport/p2p/src/swarm.rs           | Improved logging and tracing; renamed internal variables; enhanced error context                            |
| transport/protocol/src/codec.rs, transport/protocol/src/processor.rs, transport/protocol/src/lib.rs, transport/protocol/src/stream.rs | Enhanced tracing instrumentation and logging; minor refactors for clarity                                   |
| transport/probe/src/probe.rs, transport/probe/src/db_proxy.rs, transport/probe/src/config.rs | Improved probe emission delay, logging, and made probe interval public; updated default timeouts            |
| hoprd/hoprd/example_cfg.yaml, sdk/barebone.cfg.yaml, sdk/barebone-lower-win-prob.cfg.yaml, sdk/default.cfg.yaml | Adjusted probe timeout and interval defaults in configuration files                                         |
| db/api/src/protocol.rs                                                        | Added custom `Debug` implementation for `OutgoingPacket`                                                    |
| db/sql/src/protocol.rs                                                        | Added tracing instrumentation to async database methods                                                     |
| transport/api/src/lib.rs                                                      | Added event-driven network update mechanism from discovery events                                           |
| transport/network/Cargo.toml                                                  | Added `hopr-crypto-random` dependency                                                                        |
| db/sql/Cargo.toml                                                             | Added `hopr-async-runtime` with Tokio feature to dev dependencies                                           |
| chain/rpc/src/lib.rs, chain/rpc/src/transport.rs                             | Added conditional compilation for `ReqwestClient` based on `runtime-tokio` feature                          |
| misc/platform/src/time.rs                                                     | Added public re-export of `current_time` function                                                           |
| transport/network/src/config.rs                                               | Added constant for dial failure penalty duration                                                            |
| transport/p2p/src/lib.rs                                                      | Added public re-export of discovery event type                                                              |
| transport/probe/src/content.rs                                                | Replaced serialization with manual byte-level encoding/decoding for probe messages and telemetry           |
| transport/protocol/src/capture.rs                                             | Added packet capture module with pcap and UDP output support                                                |
| transport/protocol/src/lib.rs                                                 | Added packet capture integration and enhanced logging for message protocol                                  |
| transport/protocol/hopr.lua                                                   | Added Wireshark Lua dissector for HOPR protocol stack                                                       |
| common/async-runtime/src/lib.rs                                               | Replaced `spawn_as_abortable` function with macro version                                                  |
| Multiple files (hoprd/hoprd/src/main.rs, hoprd/rest-api/src/session.rs, transport/session/src/manager.rs, hopr/hopr-lib/src/lib.rs, hopr/hopr-lib/tests/chain_integration_tests.rs, chain/api/src/lib.rs, chain/indexer/src/block.rs, transport/api/src/lib.rs) | Changed calls from `spawn_as_abortable` function to macro invocation `spawn_as_abortable!`                    |
| .github/workflows/build-docker.yaml, flake.nix                               | Added profile build support with capture feature enabled in CI/CD and Nix packaging                         |
| transport/probe/Cargo.toml, transport/protocol/Cargo.toml, hopr/hopr-lib/Cargo.toml, hoprd/hoprd/Cargo.toml, transport/api/Cargo.toml, transport/network/Cargo.toml, db/api/Cargo.toml, db/sql/Cargo.toml, chain/rpc/src/lib.rs, chain/rpc/src/transport.rs | Added new optional features and dependencies for packet capture and async runtime                            |
| transport/mixer/src/channel.rs                                                | Added `Clone` trait to `SenderError` enum                                                                    |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Client
    participant REST_API
    participant DB
    participant Network

    Client->>REST_API: GET /peers
    REST_API->>DB: Query PeerStatus (no version/public fields)
    DB-->>REST_API: PeerStatus list (without version/public)
    REST_API-->>Client: PeerInfo list (without reported_version)

    Client->>REST_API: POST /peers/ping
    REST_API->>Network: Ping peer
    Network-->>REST_API: Ping result (no version)
    REST_API-->>Client: PingResponse (latency only)

Assessment against linked issues

Objective Addressed Explanation
Fix decoding failures due to missing reply openers in message processing (#7288) The PR includes enhancements in message decoding and probe processing, but explicit fix for missing reply openers is unclear from the summary.

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Addition of packet capture support and Wireshark dissector (transport/protocol/src/capture.rs, transport/protocol/hopr.lua) These changes are unrelated to the decoding issue and focus on diagnostics and capture features.
Refactor of spawn_as_abortable from function to macro and related async task spawning changes These are general improvements in async task management and unrelated to the decoding issue.
Removal of peer version and public status fields and related database schema migration These changes are orthogonal to the decoding issue and relate to peer metadata simplification.

Possibly related PRs

Suggested labels

bug, crate:core-network, crate:core-p2p

Suggested reviewers

  • NumberFour8
  • Teebor-Choka

</details>

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=hoprnet/hoprnet&utm_content=7255):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@Teebor-Choka Teebor-Choka force-pushed the kauki/v3/logs/improve-logging-and-code-quality branch from ca5852d to 7350fbf Compare June 19, 2025 18:39
@Teebor-Choka Teebor-Choka marked this pull request as ready for review June 19, 2025 18:39
@Copilot Copilot AI review requested due to automatic review settings June 19, 2025 18:39
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR addresses issues with sending messages in the hopr-lib by fixing the error handling in data conversion and improving logging.

  • Update error handling logic when converting data to a Message
  • Enhance error details by including the original error explanation in the log message
Comments suppressed due to low confidence (1)

transport/probe/src/probe.rs:232

  • [nitpick] Using .context() can automatically preserve the original error chain and may simplify error handling. Consider reverting to .context() if maintaining the error chain provenance is desired.
                        let message: anyhow::Result<Message> = data.try_into().map_err(|e| anyhow::anyhow!("failed to convert data into message: {e}"));

@Teebor-Choka Teebor-Choka force-pushed the kauki/v3/logs/improve-logging-and-code-quality branch from 7350fbf to 7359405 Compare June 19, 2025 18:41
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
transport/probe/src/probe.rs (1)

232-232: The error handling change looks correct, but check for unused imports.

The explicit error mapping approach is functionally equivalent to using .context() and properly includes the original error details in the formatted message.

Consider checking if the anyhow::Context import on line 3 is now unused since you're no longer using the .context() method:

-use anyhow::Context;

If it's still used elsewhere in the file, this change isn't needed.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea300b2 and 7350fbf.

📒 Files selected for processing (1)
  • transport/probe/src/probe.rs (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: hoprd / docker
  • GitHub Check: hopli / docker
  • GitHub Check: Docs / Rust docs
  • GitHub Check: zizmor
  • GitHub Check: Linter
  • GitHub Check: Build Candidate Binaries (hoprd)
  • GitHub Check: Build Candidate Binaries (hopli)
  • GitHub Check: tests-smart-contracts
  • GitHub Check: tests-unit
  • GitHub Check: tests-unit-nightly
  • GitHub Check: Cargo Audit
🔇 Additional comments (1)
transport/probe/src/probe.rs (1)

232-232: Verify consistency with project's error handling patterns.

The change from .context() to explicit .map_err() with formatted messages might indicate a broader refactoring effort to standardize error handling approaches across the codebase.

#!/bin/bash
# Description: Check for consistency in error handling patterns across the codebase
# Expected: Find usage patterns of .context() vs .map_err() with anyhow::anyhow!

echo "=== Checking usage of .context() method ===" 
rg "\.context\(" --type rust -A 2 -B 2

echo -e "\n=== Checking usage of .map_err with anyhow::anyhow! ===" 
rg "\.map_err.*anyhow::anyhow!" --type rust -A 2 -B 2

echo -e "\n=== Checking anyhow::Context imports ===" 
rg "use.*anyhow::Context" --type rust

@NumberFour8 NumberFour8 changed the title fix(hopr-lib): fix issues with sending messages fix(hopr-lib): improve logging for issues with sending messages Jun 19, 2025
@Teebor-Choka Teebor-Choka force-pushed the kauki/v3/logs/improve-logging-and-code-quality branch 2 times, most recently from c6a52c2 to 727b6a7 Compare June 23, 2025 12:48
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🔭 Outside diff range comments (1)
hopr/hopr-lib/src/lib.rs (1)

720-726: Fix variable name inconsistency.

The code references indexer_peer_update_tx_2 on line 723, but the variable declared above is indexer_peer_update_tx. This will cause a compilation error.

Apply this fix:

         spawn(async move {
             indexer_event_pipeline
                 .map(Ok)
-                .forward(indexer_peer_update_tx_2)
+                .forward(indexer_peer_update_tx)
                 .await
                 .expect("The index to transport event chain failed");
         });
🧹 Nitpick comments (1)
hopr/hopr-lib/src/lib.rs (1)

684-719: Consider alignment with PR objectives.

While this synchronization timing improvement is beneficial, the PR is titled "improve logging for issues with sending messages" but this change doesn't appear to add any logging improvements. Consider whether additional logging should be added to this synchronization process to help diagnose message sending issues.

For example, you could add logging like:

             info!("Syncing peer announcements and network registry updates from previous runs");
             let accounts = self.db.get_accounts(None, true).await?;
+            debug!(account_count = accounts.len(), "Retrieved accounts for synchronization");
             for account in accounts.into_iter() {
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 727b6a7 and b302a45.

📒 Files selected for processing (2)
  • hopr/hopr-lib/src/lib.rs (1 hunks)
  • transport/p2p/src/behavior/discovery.rs (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: hoprd / docker
  • GitHub Check: hopli / docker
  • GitHub Check: Docs / Rust docs
  • GitHub Check: Linter
  • GitHub Check: tests-unit-nightly
  • GitHub Check: Build Candidate Binaries (hoprd)
  • GitHub Check: tests-smart-contracts
  • GitHub Check: tests-unit
  • GitHub Check: Build Candidate Binaries (hopli)
  • GitHub Check: zizmor
🔇 Additional comments (2)
transport/p2p/src/behavior/discovery.rs (1)

208-213: LGTM! Good security improvement.

The conditional check restricts dialing to only allowed peers, which enhances security by preventing connections to unauthorized nodes. The early dialing logic is well-documented and helps ensure heartbeat mechanisms work effectively.

hopr/hopr-lib/src/lib.rs (1)

684-719: LGTM! Excellent timing improvement.

Moving the peer synchronization earlier ensures that pre-existing peer data is properly populated into the transport mechanism before event processing begins. This should prevent race conditions and improve the reliability of peer discovery and network registry state management.

@Teebor-Choka Teebor-Choka force-pushed the kauki/v3/logs/improve-logging-and-code-quality branch from b302a45 to fa63ba5 Compare June 23, 2025 13:34
@Teebor-Choka Teebor-Choka changed the title fix(hopr-lib): improve logging for issues with sending messages fix(hopr-lib): Connectability issues in the local cluster and production Jun 23, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
transport/protocol/src/codec.rs (1)

28-32: Consider removing redundant manual trace call.

With the comprehensive instrumentation now in place on line 20, this manual trace call might be redundant. The instrumentation already captures method entry, parameters, return values, and errors. However, this specific trace provides context about why decoding was skipped, which might be valuable to retain.

If you want to keep the specific context, consider this approach:

-            tracing::trace!(
-                available_bytes = len,
-                protocol = "msg",
-                "Skipping decoding operation, insufficient bytes available"
-            );
+            tracing::trace!("Insufficient bytes for decoding: need {SIZE}, have {len}");
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a224032 and ac25279.

📒 Files selected for processing (4)
  • db/api/src/protocol.rs (1 hunks)
  • transport/probe/src/probe.rs (2 hunks)
  • transport/protocol/src/codec.rs (2 hunks)
  • transport/protocol/src/processor.rs (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • db/api/src/protocol.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • transport/probe/src/probe.rs
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: tests-unit-nightly
  • GitHub Check: Build Candidate Binaries (hopli)
  • GitHub Check: Build Candidate Binaries (hoprd)
  • GitHub Check: tests-unit
  • GitHub Check: hoprd / docker
  • GitHub Check: hopli / docker
  • GitHub Check: Docs / Rust docs
  • GitHub Check: Linter
  • GitHub Check: zizmor
  • GitHub Check: Cargo Audit
🔇 Additional comments (3)
transport/protocol/src/processor.rs (1)

53-53: Excellent tracing enhancement for improved observability.

The addition of ret(Debug) and err parameters to the existing tracing instrumentation will provide valuable debugging information for connectability issues without impacting the method's core functionality.

transport/protocol/src/codec.rs (2)

9-9: Comprehensive tracing instrumentation enhances debugging capabilities.

The detailed instrumentation with custom span naming, field recording, and automatic return/error logging will significantly improve observability for codec operations.


20-20: Well-structured tracing instrumentation for decode operations.

The instrumentation provides excellent context with size and protocol fields, plus automatic return value and error logging.

@Teebor-Choka
Copy link
Contributor Author

🍺 🍺 🍺 well deserved. Kudos my friend!

@NumberFour8 NumberFour8 enabled auto-merge (squash) July 14, 2025 08:42
@NumberFour8 NumberFour8 disabled auto-merge July 14, 2025 08:43
@NumberFour8 NumberFour8 added this to the 3.0.0 milestone Jul 14, 2025
@tolbrino tolbrino removed the deploy_nodes Deploy Hoprd nodes in Kubernetes label Jul 14, 2025
@ausias-armesto ausias-armesto added the deploy_nodes Deploy Hoprd nodes in Kubernetes label Jul 14, 2025
@ausias-armesto ausias-armesto removed the deploy_nodes Deploy Hoprd nodes in Kubernetes label Jul 14, 2025
@NumberFour8 NumberFour8 merged commit f3ff9f8 into master Jul 14, 2025
31 checks passed
@NumberFour8 NumberFour8 deleted the kauki/v3/logs/improve-logging-and-code-quality branch July 14, 2025 15:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment