Skip to content

Conversation

Teebor-Choka
Copy link
Contributor

@Teebor-Choka Teebor-Choka commented Apr 16, 2025

The protocols have so far lived as separate protocols on the libp2p level. In order to improve privacy, they can be joined inside a single payload structure to externally appear only as sending messages.

This pull request includes several changes to the Cargo.toml, crypto/packet/src/packet.rs, db/api/src/protocol.rs, and db/sql/src/protocol.rs files, focusing on improving the handling of acknowledgments, restructuring data models, and adding metrics for better observability. The most significant changes include replacing the no_ack field with an Option<HalfKey> for ack_key, refactoring acknowledgment handling, and introducing new Prometheus metrics.

Changes to acknowledgment handling:

  • Replaced the no_ack boolean field in HoprIncomingPacket with an Option<HalfKey> for ack_key, allowing None when no acknowledgment is required. Updated the logic in HoprPacket to derive ack_key only when necessary. (crypto/packet/src/packet.rs, [1] [2]
  • Removed the no_ack field from the TransportPacketWithChainData enum and replaced it with the new OutgoingPacket struct, simplifying the outgoing packet model. (db/api/src/protocol.rs, [1] [2]
  • Updated tests to reflect the new Option<HalfKey> logic for ack_key and removed assertions related to no_ack. (crypto/packet/src/packet.rs, [1] [2] [3] [4] [5] [6]

Refactoring acknowledgment processing:

  • Simplified the handle_acknowledgement method in HoprDbProtocolOperations by removing the AckResult enum and using Result<()> instead. This change makes the acknowledgment handling pipeline more streamlined. (db/api/src/protocol.rs, [1] [2]
  • Adjusted the acknowledgment handling implementation in db/sql/src/protocol.rs to align with the updated interface and added Prometheus metrics for received acknowledgments. (db/sql/src/protocol.rs, [1] [2] [3]

Metrics and observability:

  • Introduced new Prometheus metrics, including METRIC_RECEIVED_ACKS, METRIC_SENT_ACKS, and METRIC_TICKETS_COUNT, to track acknowledgment and ticket-related events. (db/sql/src/protocol.rs, [1] [2]
  • Incremented the relevant metrics in acknowledgment and packet processing methods to improve observability. (db/sql/src/protocol.rs, [1] [2]

Dependency and workspace updates:

  • Added new workspace members transport/packet and transport/ticket-aggregation to Cargo.toml, and included their dependencies. (Cargo.toml, [1] [2]

Notes

Relates to #5662

@Teebor-Choka Teebor-Choka self-assigned this Apr 16, 2025
Copy link
Contributor

coderabbitai bot commented Apr 16, 2025

📝 Walkthrough
## Walkthrough

This change set removes the ticket aggregation protocol and its related infrastructure from the transport layer, P2P network behavior, and protocol configuration. It introduces two new workspace crates: `hopr-transport-packet` and `hopr-transport-ticket-aggregation`, the latter being a placeholder for future reimplementation. The packet processing flow is refactored to unify message and acknowledgment handling, removing separate acknowledgment protocols and codecs. Packet and protocol abstractions are simplified, with explicit replay detection handled via a Bloom filter. Several public APIs, trait signatures, and error types are updated to reflect these changes. Integration and unit tests are updated or skipped to accommodate the absence of session-based ticket aggregation.

## Changes

| File(s) / Path(s)                                                                                      | Change Summary |
|--------------------------------------------------------------------------------------------------------|---------------|
| Cargo.toml, logic/strategy/Cargo.toml, transport/api/Cargo.toml, transport/protocol/Cargo.toml         | Added new workspace members and dependencies: `hopr-transport-packet` and `hopr-transport-ticket-aggregation`. Updated feature groups and dev-dependencies accordingly. |
| transport/packet/.gitignore, transport/packet/Cargo.toml, transport/packet/src/lib.rs                  | Added new crate `hopr-transport-packet` with packet primitives, fixed-size payload enforcement, and basic packet structures. |
| transport/ticket-aggregation/.gitignore, transport/ticket-aggregation/Cargo.toml, transport/ticket-aggregation/src/lib.rs | Added new crate `hopr-transport-ticket-aggregation` as a placeholder. Introduced new error type `TicketAggregationError`. |
| hoprd/hoprd/example_cfg.yaml, transport/protocol/src/config.rs                                         | Removed ticket aggregation protocol configuration from protocol config and example config. |
| transport/protocol/src/ticket_aggregation/config.rs, transport/protocol/src/ticket_aggregation/mod.rs  | Deleted ticket aggregation protocol config and module re-exports. |
| transport/protocol/src/ack/codec.rs, transport/protocol/src/ack/mod.rs, transport/protocol/src/ack/processor.rs | Deleted acknowledgment protocol codec, module, and processor. |
| transport/protocol/src/msg/codec.rs, transport/protocol/src/msg/mod.rs, transport/protocol/src/msg/packet.rs | Deleted message protocol codec, module, and packet abstractions. |
| transport/protocol/src/processor.rs, transport/protocol/src/codec.rs                                   | Refactored packet processor: simplified interfaces, removed explicit replay detection, introduced `FixedLengthCodec`. |
| transport/protocol/src/lib.rs, transport/protocol/benches/protocol_throughput_emulated.rs, transport/protocol/tests/common/mod.rs | Refactored protocol entrypoint: unified message and acknowledgment handling, removed explicit ack protocol, updated test and bench setup accordingly. |
| transport/api/src/errors.rs, transport/api/src/lib.rs, transport/api/src/proxy.rs, transport/api/src/helpers.rs | Updated error handling for ticket aggregation, refactored proxy and aggregator traits to return new error types, removed session-based ticket aggregation logic. |
| db/api/src/protocol.rs, db/sql/src/protocol.rs                                                         | Refactored packet and acknowledgment handling: removed `AckResult`, unified packet representations, updated trait signatures, improved metrics. |
| transport/p2p/src/behavior/mod.rs, transport/p2p/src/behavior/ticket_aggregation.rs, transport/p2p/src/constants.rs, transport/p2p/src/lib.rs, transport/p2p/src/swarm.rs | Removed ticket aggregation behavior, protocol constants, and all related event handling from the P2P network stack. |
| transport/protocol/src/bloom.rs                                                                        | Added async `is_tag_replay` method to Bloom filter wrapper for replay detection. |
| crypto/packet/src/packet.rs                                                                            | Changed `ack_key` in `HoprIncomingPacket` to `Option<HalfKey>`, removed `no_ack` field, updated logic and tests accordingly. |
| tests/test_integration.py, tests/test_redeeming.py, tests/test_win_prob.py                             | Skipped tests related to ticket aggregation, as it is not implemented as a session protocol. |
| logic/strategy/src/aggregating.rs, logic/strategy/src/strategy.rs                                      | Updated import paths for ticket aggregation trait/types to new crate. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant App as Application
    participant Protocol as Protocol Layer
    participant DB as Database
    participant P2P as P2P Network

    App->>Protocol: Send application data
    Protocol->>DB: Packet wrapping (send)
    DB-->>Protocol: OutgoingPacket
    Protocol->>P2P: Send packet (wire)
    P2P-->>Protocol: Receive packet (wire)
    Protocol->>DB: Packet unwrapping (recv)
    DB-->>Protocol: Option<IncomingPacket>
    alt Final packet
        Protocol->>P2P: Send acknowledgment (wire)
    end
    Protocol-->>App: Deliver application data (if final)

Possibly related PRs

  • Improve logging for debugging purposes #6863: The main PR removes and disables the ticket aggregation protocol and related code, including its processor and behavior, while the retrieved PR improves logging within the ticket aggregation processor; thus, the main PR’s changes effectively disable the code that the retrieved PR modifies, making them related but with opposite focus (removal vs. enhancement) on the same ticket aggregation processor code.

  • Add support for libp2p_stream into the swarm object #6928: The main PR adds two new workspace members for transport packet and ticket aggregation crates and refactors transport protocol and p2p layers by removing ticket aggregation and acknowledgment protocol handling, simplifying packet processing, and disabling ticket aggregation as a session protocol; the retrieved PR introduces libp2p_stream support into the swarm object and restructures message and acknowledgment handling to use native libp2p streams, including removal of previous message and ack behaviors and protocols. Both PRs modify the transport/p2p swarm and protocol layers, specifically removing old ack and ticket aggregation protocol handling and replacing message and ack processing with stream-based handling, indicating a direct and strong connection at the code level in how transport packets and acknowledgments are processed and integrated into the swarm.

Suggested labels

crate:hopr-lib, crate:core-protocol

Suggested reviewers

  • NumberFour8

</details>

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


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

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_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=7073):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `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 generate unit testing code for this file.`
  -	`@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 generate unit testing code.`
  - `@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 -->

@tolbrino tolbrino added this to the 3.0.0 milestone Apr 29, 2025
@Teebor-Choka Teebor-Choka force-pushed the kauki/protocol/unify-the-msg-ack-protocol branch from 32274ca to 6296371 Compare April 30, 2025 11:49
@Teebor-Choka Teebor-Choka marked this pull request as ready for review April 30, 2025 13:15
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: 2

🔭 Outside diff range comments (3)
transport/p2p/src/lib.rs (1)

154-156: ⚠️ Potential issue

Left-over TicketAggregation event is now unreachable and will rot.

The ticket-aggregation behaviour was removed from HoprNetworkBehavior, yet the event variant and the From<…> conversion are still present.
With no sub-behaviour producing this event, the code is:

  • Dead / unreachable (may trigger dead-code warnings).
  • Misleading to future maintainers (suggests the feature is still available).
  • A potential compile-error magnet if the referenced types are ever deleted or renamed.
-    TicketAggregation(
-        libp2p::request_response::Event<Vec<TransferableWinningTicket>, std::result::Result<Ticket, String>>,
-    ),
+    // (ticket aggregation removed – variant intentionally deleted)

and drop the matching impl From … { … }.

If the plan is to re-add ticket aggregation later, keep the git history instead of zombie code.

Also applies to: 191-199

transport/protocol/src/processor.rs (1)

150-155: ⚠️ Potential issue

Missing definition of DEFAULT_OUTGOING_TICKET_WIN_PROB.

determine_actual_outgoing_win_prob references DEFAULT_OUTGOING_TICKET_WIN_PROB, but the constant is not declared in this module nor imported. This will not compile.

Either import the constant from its new home:

use hopr_internal_types::constants::DEFAULT_OUTGOING_TICKET_WIN_PROB;

or re-define it locally (same pattern as DEFAULT_PRICE_PER_PACKET).

transport/p2p/src/swarm.rs (1)

75-87: ⚠️ Potential issue

Builder fails to compile due to superfluous map_err on a non-Result value

swarm is a SwarmBuilder, not a Result.
The extra .map_err(..)? therefore makes the whole function fail to compile.

-    Ok(swarm
-        .map_err(|e| crate::errors::P2PError::Libp2p(e.to_string()))?
-        .with_behaviour(|_key| {
+    Ok(swarm
+        .with_behaviour(|_key| {
             HoprNetworkBehavior::new(
                 me_peerid,
                 network_update_input,
                 indexer_update_input,
                 heartbeat_requests,
                 protocol_cfg.heartbeat.timeout,
             )
         })

(The later .map_err(..)? after with_behaviour is still needed because that method does return a Result).
Without this fix the crate will not build.

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

4-4: Missing tracing::trace import

The code uses the trace level in the tracing::instrument attribute, but the trace import is missing from the tracing imports.

-use tracing::{debug, error, info};
+use tracing::{debug, error, info, trace};
crypto/packet/src/packet.rs (1)

385-390: Simplified acknowledgment handling logic.

The code now explicitly calculates should_acknowledge from !no_ack and then uses Rust's then_some() method to conditionally set the ack_key field. This improves readability and follows Rust idioms.

Consider making the intent even clearer by using this more direct approach:

-    let should_acknowledge = !no_ack;
-    Ok(Self::Final(
-        HoprIncomingPacket {
-            packet_tag,
-            ack_key: (should_acknowledge).then_some(derive_ack_key_share(&derived_secret)),
+    Ok(Self::Final(
+        HoprIncomingPacket {
+            packet_tag,
+            ack_key: (!no_ack).then_some(derive_ack_key_share(&derived_secret)),
transport/protocol/src/codec.rs (1)

3-38: Clean, generic fixed-length codec implementation.

The FixedLengthCodec implementation is well-designed with the generic const parameter for size, making it reusable for different packet sizes. The tracing is appropriate for debugging.

However, the error message "Payload too small" on line 29 could be misleading when the payload is actually too large.

-                "Payload too small",
+                format!("Payload size mismatch: expected {}, got {}", HoprPacket::PAYLOAD_SIZE, data.len()),
transport/api/src/proxy.rs (1)

40-62: Clear communication of unimplemented functionality.

The implementation now properly returns an error with a clear message that ticket aggregation is not yet supported. This is better than silently failing or providing partial functionality.

Consider removing the commented-out code in a future cleanup PR, as it adds noise to the current implementation. If it's meant as a reference for future implementation, consider moving it to documentation or a design document.

transport/packet/src/lib.rs (1)

94-95: Address TODO comment.

There's a TODO comment about possibly removing the SIZE constant. Since this PR introduces significant changes to the packet structure, it would be better to make a decision about this constant now rather than leaving it as a TODO.

Make a decision about whether to keep or remove this constant based on its current usage in the codebase.

transport/ticket-aggregation/Cargo.toml (1)

1-17: Mark placeholder crate as non-publishable.

Because this crate is “inert” and contains no functional code yet, publishing it to crates.io could confuse external users.

[package]
 name = "hopr-transport-ticket-aggregation"
 version = "0.1.0"
+# Prevent accidental publishing of an empty crate
+publish = false

Adding publish = false (and optionally a short README explaining the placeholder status) makes the intent explicit.

transport/protocol/src/processor.rs (1)

6-8: Duplicate import & shadowing of PacketError.

PacketError is imported twice: once as the type and once inside the grouped import that also pulls in the TransportError variant. The first import becomes unused and will trigger dead_code/unused_import warnings.

-use hopr_crypto_packet::errors::PacketError;
-use hopr_crypto_packet::errors::{PacketError::TransportError, Result};
+use hopr_crypto_packet::errors::{PacketError, PacketError::TransportError, Result};

This keeps a single, coherent import line.

transport/p2p/src/swarm.rs (1)

408-430: Dead code: old Inputs enum and ticket-aggregation aliases can be deleted

These definitions are no longer referenced after the ACK/ticket-aggregation removal. Keeping them:

  • increases compile time (dead-code lint),
  • confuses readers about the current design,
  • risks accidental re-use of soon-to-be-removed types.
-/// Composition of all inputs allowing to produce a single stream of
-/// input events passed into the swarm processing logic.
-#[derive(Debug)]
-pub enum Inputs {
-    Message((PeerId, Box<[u8]>)),
-    Acknowledgement((PeerId, Acknowledgement)),
-}
-
-impl From<(PeerId, Acknowledgement)> for Inputs { … }
-impl From<(PeerId, Box<[u8]>)> for Inputs { … }
-
-pub type TicketAggregationRequestType  = OutboundRequestId;
-pub type TicketAggregationResponseType = ResponseChannel<std::result::Result<Ticket, String>>;

If you still need the type aliases elsewhere, move them to a dedicated (and clearly named) module instead.

transport/api/src/lib.rs (2)

607-613: Hard-coded 15 s aggregation timeout makes the value un-tuneable

ticket_aggregator() bakes the timeout into the code:

std::time::Duration::from_secs(15)

Please expose this through HoprTransportConfig (e.g. cfg.protocol.ticket_agg_timeout_secs) so operators can adjust it for different network conditions or unit tests.

-            std::time::Duration::from_secs(15),
+            std::time::Duration::from_secs(self.cfg.protocol.ticket_agg_timeout_secs),

737-749: Stray commented code & unconditional error — clarify intent

The block is now:

// old implementation …
/// …
Err(TicketAggregationError::TransportError(
    "Ticket aggregation not supported as a session protocol yet".to_string(),
).into())
  1. The large commented section clutters the file – please remove it or open an issue that references the historic code.
  2. If ticket aggregation is temporarily disabled, gate the call behind a feature flag or TODO so downstream callers can feature-detect instead of always failing at runtime.
transport/protocol/tests/common/mod.rs (1)

230-268: Potential indefinite await in relay emulation

Inside emulate_channel_communication each relayer awaits:

components[i].1.next().await

If fewer than count packets arrive (e.g. due to earlier test failure) the test hangs forever.
Add a timeout to fail fast and surface the real issue:

-let (dest, payload) = components[i].1.next().await
+let (dest, payload) = components[i]
+    .1
+    .next()
+    .timeout(std::time::Duration::from_secs(5))
+    .await
+    .expect("channel stalled")

This prevents CI timeouts and gives clearer feedback.

transport/protocol/src/lib.rs (3)

7-11: Remove ack from the public-facing docs

The introductory comment still advertises an ack protocol, yet acknowledgements are now embedded in the unified “mix” flow. Leaving this line in misleads integrators and future maintainers.

-//! - `ack`

132-139: Rename the API — it no longer runs an “ack” protocol

run_msg_ack_protocol suggests two distinct protocols are spun up. After the merge, only the mix payload is transported. Renaming avoids confusion and aligns with the de-duped design.

-pub async fn run_msg_ack_protocol<Db>(
+pub async fn run_mix_protocol<Db>(

(remember to update call-sites & exports).


160-166: Dead metric initialisation code can be removed

The commented-out METRIC_*ACKS initialisers were left behind. Keeping them increases noise and hints at half-finished work.

-        // lazy_static::initialize(&METRIC_RECEIVED_ACKS);
-        // lazy_static::initialize(&METRIC_SENT_ACKS);
-        // lazy_static::initialize(&METRIC_TICKETS_COUNT);
db/api/src/protocol.rs (2)

50-68: Consider marking the large enums/structs as #[non_exhaustive]

IncomingPacket and OutgoingPacket are public API guarantees. Given the protocol is still evolving (e.g. ticket aggregation resurrection), adding a #[non_exhaustive] attribute future-proofs against breaking changes.


69-74: ack_challenge should be optional for “no-ack” packets

to_send_no_ack always fabricates an OutgoingPacket carrying an ack_challenge, even though the transport layer will never await it. Making the field Option<HalfKeyChallenge> clarifies intent and avoids misleading downstream metrics that count “sent acks”.

db/sql/src/protocol.rs (3)

252-254: Metric label loses information

Every valid acknowledgement increments METRIC_RECEIVED_ACKS with the label "true".
Distinguishing "win" | "loss" | "sender" (or similar) would give operators better insight without extra counters.


565-566: Typo in log field name

erorr will appear in logs and makes searching harder.

-warn!(?rejected_ticket, %rejected_value, erorr = ?error, "failure to validate during forwarding");
+warn!(?rejected_ticket, %rejected_value, error = ?error, "failure to validate during forwarding");

273-279: Underscore prefix hides a used binding

The binding _channel is later referenced, defeating the intent of a leading underscore.
Using channel_id (without underscore) silences the “unused variable” lint cleanly.

-ResolvedAcknowledgement::RelayingLoss(_channel) => {
+ResolvedAcknowledgement::RelayingLoss(channel_id) => {
...
-    crate::tickets::METRIC_HOPR_TICKETS_INCOMING_STATISTICS
-        .increment(&[&_channel.to_string(), "losing_count"], 1.0f64);
+    crate::tickets::METRIC_HOPR_TICKETS_INCOMING_STATISTICS
+        .increment(&[&channel_id.to_string(), "losing_count"], 1.0f64);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 48caa94 and 6326b71.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (44)
  • Cargo.toml (2 hunks)
  • crypto/packet/src/packet.rs (8 hunks)
  • db/api/src/protocol.rs (5 hunks)
  • db/sql/src/protocol.rs (13 hunks)
  • hoprd/hoprd/example_cfg.yaml (0 hunks)
  • logic/strategy/Cargo.toml (2 hunks)
  • logic/strategy/src/aggregating.rs (2 hunks)
  • logic/strategy/src/strategy.rs (1 hunks)
  • tests/test_integration.py (2 hunks)
  • tests/test_redeeming.py (1 hunks)
  • tests/test_win_prob.py (1 hunks)
  • transport/api/Cargo.toml (5 hunks)
  • transport/api/src/errors.rs (1 hunks)
  • transport/api/src/helpers.rs (1 hunks)
  • transport/api/src/lib.rs (5 hunks)
  • transport/api/src/proxy.rs (2 hunks)
  • transport/p2p/src/behavior/mod.rs (0 hunks)
  • transport/p2p/src/behavior/ticket_aggregation.rs (0 hunks)
  • transport/p2p/src/constants.rs (0 hunks)
  • transport/p2p/src/lib.rs (2 hunks)
  • transport/p2p/src/swarm.rs (6 hunks)
  • transport/p2p/tests/p2p_transport_test.rs (3 hunks)
  • transport/packet/.gitignore (1 hunks)
  • transport/packet/Cargo.toml (1 hunks)
  • transport/packet/src/lib.rs (1 hunks)
  • transport/protocol/Cargo.toml (1 hunks)
  • transport/protocol/benches/protocol_throughput_emulated.rs (2 hunks)
  • transport/protocol/src/ack/codec.rs (0 hunks)
  • transport/protocol/src/ack/mod.rs (0 hunks)
  • transport/protocol/src/ack/processor.rs (0 hunks)
  • transport/protocol/src/bloom.rs (2 hunks)
  • transport/protocol/src/codec.rs (1 hunks)
  • transport/protocol/src/config.rs (0 hunks)
  • transport/protocol/src/lib.rs (9 hunks)
  • transport/protocol/src/msg/codec.rs (0 hunks)
  • transport/protocol/src/msg/mod.rs (0 hunks)
  • transport/protocol/src/msg/packet.rs (0 hunks)
  • transport/protocol/src/processor.rs (9 hunks)
  • transport/protocol/src/ticket_aggregation/config.rs (0 hunks)
  • transport/protocol/src/ticket_aggregation/mod.rs (0 hunks)
  • transport/protocol/tests/common/mod.rs (4 hunks)
  • transport/ticket-aggregation/.gitignore (1 hunks)
  • transport/ticket-aggregation/Cargo.toml (1 hunks)
  • transport/ticket-aggregation/src/lib.rs (4 hunks)
💤 Files with no reviewable changes (13)
  • transport/protocol/src/config.rs
  • hoprd/hoprd/example_cfg.yaml
  • transport/p2p/src/constants.rs
  • transport/p2p/src/behavior/mod.rs
  • transport/protocol/src/ticket_aggregation/config.rs
  • transport/protocol/src/ack/mod.rs
  • transport/protocol/src/ack/processor.rs
  • transport/protocol/src/msg/codec.rs
  • transport/protocol/src/msg/mod.rs
  • transport/protocol/src/ticket_aggregation/mod.rs
  • transport/protocol/src/msg/packet.rs
  • transport/protocol/src/ack/codec.rs
  • transport/p2p/src/behavior/ticket_aggregation.rs
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: Teebor-Choka
PR: hoprnet/hoprnet#6765
File: transport/api/src/lib.rs:602-605
Timestamp: 2025-01-15T14:52:38.363Z
Learning: In the HOPR transport layer, the `TicketAggregatorProxy` is intentionally kept separate from the main transport interface to allow for potential extraction to upper interfaces in the future. This design decision facilitates architectural flexibility and should be maintained.
transport/protocol/Cargo.toml (1)
Learnt from: tolbrino
PR: hoprnet/hoprnet#6399
File: common/primitive-types/Cargo.toml:24-24
Timestamp: 2024-11-01T09:32:55.651Z
Learning: In the hoprnet project, dependency versions are defined in the workspace Cargo.toml, so it's not necessary to specify them in individual package Cargo.toml files.
logic/strategy/Cargo.toml (1)
Learnt from: Teebor-Choka
PR: hoprnet/hoprnet#6345
File: hopr-socks/hopr-socks-server/Cargo.toml:20-20
Timestamp: 2024-06-21T20:51:35.871Z
Learning: All code and packages in the `hoprnet` project should use the workspace level dependency of `reqwest`.
transport/api/Cargo.toml (1)
Learnt from: Teebor-Choka
PR: hoprnet/hoprnet#6345
File: hopr-socks/hopr-socks-server/Cargo.toml:20-20
Timestamp: 2024-06-21T20:51:35.871Z
Learning: All code and packages in the `hoprnet` project should use the workspace level dependency of `reqwest`.
transport/api/src/proxy.rs (1)
Learnt from: Teebor-Choka
PR: hoprnet/hoprnet#6765
File: transport/api/src/lib.rs:602-605
Timestamp: 2025-01-15T14:52:38.363Z
Learning: In the HOPR transport layer, the `TicketAggregatorProxy` is intentionally kept separate from the main transport interface to allow for potential extraction to upper interfaces in the future. This design decision facilitates architectural flexibility and should be maintained.
transport/api/src/lib.rs (1)
Learnt from: Teebor-Choka
PR: hoprnet/hoprnet#6765
File: transport/api/src/lib.rs:602-605
Timestamp: 2025-01-15T14:52:38.363Z
Learning: In the HOPR transport layer, the `TicketAggregatorProxy` is intentionally kept separate from the main transport interface to allow for potential extraction to upper interfaces in the future. This design decision facilitates architectural flexibility and should be maintained.
🧬 Code Graph Analysis (4)
crypto/packet/src/packet.rs (1)
crypto/packet/src/por.rs (1)
  • derive_ack_key_share (21-23)
db/sql/src/protocol.rs (4)
common/internal-types/src/protocol.rs (1)
  • new (68-75)
hopr/hopr-lib/src/lib.rs (2)
  • new (331-333)
  • new (371-522)
db/api/src/protocol.rs (2)
  • handle_acknowledgement (18-18)
  • to_send_no_ack (27-27)
db/sql/src/tickets.rs (7)
  • tickets (2417-2420)
  • tickets (2477-2480)
  • tickets (2502-2505)
  • tickets (2543-2546)
  • tickets (2698-2701)
  • tickets (2757-2760)
  • tickets (2799-2802)
db/api/src/protocol.rs (1)
db/sql/src/protocol.rs (4)
  • handle_acknowledgement (243-288)
  • get_network_winning_probability (290-295)
  • get_network_ticket_price (297-302)
  • to_send_no_ack (305-355)
transport/protocol/src/lib.rs (4)
transport/protocol/src/codec.rs (3)
  • FixedLengthCodec (49-49)
  • FixedLengthCodec (68-68)
  • FixedLengthCodec (89-89)
transport/protocol/src/bloom.rs (1)
  • new (20-37)
transport/protocol/src/processor.rs (2)
  • new (122-124)
  • new (224-226)
common/internal-types/src/protocol.rs (2)
  • random (78-80)
  • from_bytes (297-310)
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: hoprd / docker
  • GitHub Check: hopli / docker
  • GitHub Check: Docs / Rust docs
  • GitHub Check: zizmor
  • GitHub Check: tests-smoke-websocket
  • GitHub Check: tests-smart-contracts
  • GitHub Check: tests-unit-nightly
  • GitHub Check: tests-unit
  • GitHub Check: Linter
🔇 Additional comments (47)
transport/api/src/helpers.rs (1)

17-17: Update import path to unified processor module
The import of MsgSender and SendMsgInput has been updated to reflect the new unified processor module in hopr_transport_protocol. This aligns with the refactoring that merges the msg and ack protocols. No further changes to usage or behavior are required here.

logic/strategy/src/strategy.rs (1)

31-31: Switch TicketAggregatorTrait to the new aggregation crate
The import path for TicketAggregatorTrait now points to hopr_transport_ticket_aggregation. This correctly modularizes ticket aggregation into its own workspace crate. All trait usages in MultiStrategy::new will now reference the extracted crate.

logic/strategy/src/aggregating.rs (2)

41-41: Import TicketAggregatorTrait from the dedicated aggregation crate
The aggregating strategy now depends on hopr_transport_ticket_aggregation::TicketAggregatorTrait instead of the old protocol crate. This keeps the logic intact while honoring the new crate boundary.


314-316: Update test imports to use new aggregation crate
Tests now reference AwaitingAggregator, TicketAggregationInteraction, and TicketAggregationProcessed from hopr_transport_ticket_aggregation, matching the refactored module layout. Test functionality is preserved.

transport/protocol/Cargo.toml (1)

52-52: Add workspace dependency for the packet crate
Introducing hopr-transport-packet = { workspace = true } brings the new transport-packet workspace member into this crate. Dependency versions are managed at the workspace level, so no version specifier is needed here.

transport/packet/.gitignore (1)

1-6: Ignore generated and backup artifacts for the new packet crate
This .gitignore prevents committing build artifacts (/target), editor backups (*.rs.bk), lock files, and temporary logs within transport/packet. It’s a standard setup for a new workspace member.

transport/ticket-aggregation/.gitignore (1)

1-6: LGTM - Standard Rust project gitignore patterns.

The gitignore file includes common patterns for Rust projects, properly excluding build artifacts, backup files, package files, and log files.

transport/api/src/errors.rs (1)

39-41: Appropriate error integration for the new ticket aggregation crate.

This addition correctly follows the established error handling pattern in the project, using the #[from] attribute for automatic error conversion and providing a clear error message format.

logic/strategy/Cargo.toml (4)

20-20: LGTM - Consistent feature flag integration.

The ticket-aggregation dependency is properly added to the runtime-async-std feature group.


26-27: LGTM - Consistent feature flag integration.

The ticket-aggregation dependency is properly added to the runtime-tokio feature group.


35-35: LGTM - Consistent feature flag integration.

The ticket-aggregation dependency is properly added to the prometheus feature group.


64-64: LGTM - Proper workspace dependency addition.

The hopr-transport-ticket-aggregation is correctly added as a workspace dependency, following the project's dependency management pattern.

tests/test_win_prob.py (1)

64-64: Appropriate test skipping during refactoring.

The test is correctly marked to be skipped with a clear reason: "ticket aggregation is not implemented as a session protocol yet." This aligns with the PR's objective of unifying the message and acknowledgment protocols.

transport/packet/Cargo.toml (1)

1-22: Looks good - appropriate package configuration for new module

The new Cargo.toml file is well-structured with proper metadata, dependencies, and configuration for the new hopr-transport-packet crate. This addition aligns with the PR's goal of unifying message and acknowledgment protocols.

tests/test_redeeming.py (1)

121-123: Appropriate test skip with clear reason

Skipping this test is consistent with the PR objective of unifying message and acknowledgment protocols. The skip reason clearly documents that ticket aggregation functionality is not currently implemented as a session protocol.

transport/protocol/src/bloom.rs (1)

39-46: Well-documented replay detection method

The new is_tag_replay method is a good addition that properly encapsulates the replay detection logic. The documentation clearly communicates the false positive rate limitation of using a Bloom filter.

transport/protocol/benches/protocol_throughput_emulated.rs (4)

13-13: Updated import path aligns with protocol unification

The import path change reflects the consolidation of message and acknowledgment processing into a unified processor module, which is consistent with the PR objectives.


63-68: PacketInteractionConfig simplified by removing chain_keypair

The configuration no longer includes the chain_keypair field, which aligns with the refactoring of the packet interaction configuration to support the unified protocol structure.


69-76: Protocol initialization simplified

The call to run_msg_ack_protocol has been simplified by removing the acknowledgement channels tuple argument, which is consistent with the unification of message and acknowledgment handling.


80-80: Updated path construction for mock path resolution

The code now correctly passes clones of public keys directly, rather than using .into() conversions, which is consistent with updated key handling elsewhere in the codebase.

transport/api/Cargo.toml (5)

22-22: Added new dependency to runtime-async-std feature.

Adding hopr-transport-ticket-aggregation to the runtime feature sets is consistent with how other transport components are organized in this project.


32-32: Added new dependency to runtime-tokio feature.

The parallel addition to tokio runtime features maintains consistency with the async-std version.


45-45: Added new dependency to prometheus feature.

Adding the prometheus feature for the new ticket-aggregation module keeps instrumentation consistent across all transport components.


86-86: Added new workspace dependency.

The direct dependency on hopr-transport-ticket-aggregation is properly declared as a workspace dependency.


95-97: Added dev dependency with appropriate features.

The dev dependency includes runtime-async-std for testing, which aligns with the project's testing approach.

Cargo.toml (4)

42-43: Added new workspace member for transport packet module.

Adding transport/packet as a workspace member is appropriate for the unification of message and acknowledgment protocols.


46-47: Added placeholder workspace member for ticket aggregation.

Adding transport/ticket-aggregation as a workspace member sets up the structure for future implementation.


242-243: Added workspace dependency for transport packet.

The workspace dependency declaration for hopr-transport-packet is correctly set up.


245-246: Added placeholder dependency with clear documentation.

The workspace dependency for ticket-aggregation includes a helpful comment explaining its current status as a "dead package waiting for reimplementation as a session protocol," which provides valuable context for developers.

crypto/packet/src/packet.rs (2)

174-177: Improved design by making ack_key optional instead of using a separate flag.

Replacing the no_ack: bool field with an optional ack_key: Option<HalfKey> is a cleaner approach. This change centralizes the acknowledgment presence logic into a single field, making the code more maintainable and reducing potential inconsistencies.


618-619: Updated test assertions for ack_key presence.

All test assertions have been correctly updated to check for the presence of ack_key instead of the absence of the no_ack flag, maintaining consistency with the implementation changes.

Also applies to: 656-657, 796-797, 842-843

tests/test_integration.py (2)

251-252: Skipped test for ticket aggregation functionality.

The test test_hoprd_should_fail_sending_a_message_when_the_channel_is_out_of_funding is correctly marked to be skipped as ticket aggregation is not implemented as a session protocol yet. The skip reason is clear and appropriate.


348-349: Skipped test for automatic ticket aggregation and redeeming.

The test test_hoprd_default_strategy_automatic_ticket_aggregation_and_redeeming is correctly marked to be skipped for the same reason. This is consistent with the PR's objective of deferring ticket aggregation functionality.

transport/ticket-aggregation/src/lib.rs (4)

23-39: Well-structured error handling approach.

The new TicketAggregationError enum with thiserror is a good choice for domain-specific error handling, providing clear error messages and proper error categorization. The separation from the previous protocol errors aligns well with separating ticket aggregation into its own crate.


167-170: Appropriate error mapping in consume_and_wait.

The transition from previous error types to the new TicketAggregationError is handled correctly here, maintaining the same error semantics while using the new type system.


253-260: Good error handling in process method.

The error mapping in the process method correctly uses the new error types while preserving the original error conditions and messages.


356-356: Minor variable name improvement.

Changing from _ to _dest improves code readability by providing context for what this variable represents, while still indicating it's unused with the leading underscore.

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

40-106: Comprehensive test coverage.

The tests thoroughly cover the key codec behaviors:

  1. Happy path (encode/decode roundtrip)
  2. Handling insufficient bytes
  3. Handling excess bytes

This ensures the codec will work reliably in all expected scenarios.

transport/api/src/proxy.rs (2)

6-6: Appropriate import update.

Correctly updated the import to use the new dedicated ticket aggregation crate, following the architectural change to separate these concerns.


13-18: Reasonable use of #[allow(dead_code)].

Adding these attributes is appropriate since these fields are temporarily unused while ticket aggregation is disabled as a session protocol. This preserves the structure for future implementation while avoiding compiler warnings.

transport/packet/src/lib.rs (4)

10-47: Robust DataBytes implementation with proper validation.

The DataBytes struct correctly enforces the fixed payload size requirement through its TryFrom implementations. This ensures that invalid data is caught early with appropriate error messages.


49-96: Well-designed Payload enum with appropriate trait implementations.

The Payload enum properly represents both message and acknowledgment payloads. The trait implementations (Debug, AsRef, From/TryFrom) are comprehensive and make the type easy to use throughout the codebase.


98-105: Simple and appropriate packet structure.

The Header and Packet structures are straightforward and provide a clear separation of concerns between routing information (header) and payload data.


107-129: Good test coverage for DataBytes validation.

The tests properly verify the three key scenarios for DataBytes:

  1. Rejecting too short payloads
  2. Rejecting too long payloads
  3. Accepting correctly sized payloads

This ensures the fundamental size validation works correctly.

transport/p2p/tests/p2p_transport_test.rs (1)

72-74: Verify protocol constant & codec after unification.

The test still uses the pre-refactor constant CURRENT_HOPR_MSG_PROTOCOL.
After merging msg and ack into a single packet protocol, the constant may have been renamed or removed. A stale constant will fail to compile once CI turns strict on unused items.

let msg_proto_control =
    swarm.build_protocol_control(hopr_transport_protocol::CURRENT_HOPR_MSG_PROTOCOL);
let msg_codec = hopr_transport_protocol::HoprBinaryCodec {};

Please confirm the constant exists and represents the new unified protocol, or switch to the updated name (e.g. CURRENT_HOPR_PACKET_PROTOCOL).

transport/protocol/tests/common/mod.rs (1)

143-146: Channel alias now omits ACK stream – check remaining call-sites

WireChannels was reduced to two elements, but several helper functions (e.g. peer_setup_for) still construct/expect ACK-related logic. Ensure all usages were updated; otherwise tests may silently discard ACK traffic.

transport/protocol/src/lib.rs (1)

286-295: Bloom-filter look-up may race without recording fresh tags

is_tag_replay returns a boolean but it’s not obvious whether it ALSO inserts unseen tags.
If insertion is not atomic inside that method, the filter must be updated here to prevent re-processing on concurrent tasks.

Please confirm (or amend) that is_tag_replay() stores the tag when it returns false.

Copy link
Contributor

@NumberFour8 NumberFour8 left a comment

Choose a reason for hiding this comment

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

Version bumps needed.

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

♻️ Duplicate comments (1)
transport/protocol/src/lib.rs (1)

255-258: ⚠️ Potential issue

Fix potential panic in peer conversion

The code uses unwrap() when converting a PeerId to OffchainPublicKey, which could cause the application to crash if the conversion fails.

Replace the unwrap with proper error handling:

-let peer: OffchainPublicKey = peer.try_into().unwrap(); // TODO: should not unwrap !!!
+let peer: OffchainPublicKey = match peer.try_into() {
+    Ok(p) => p,
+    Err(e) => {
+        tracing::warn!(%peer, %e, "Dropping packet – cannot convert peer id");
+        return None;
+    }
+};
🧹 Nitpick comments (2)
transport/protocol/src/lib.rs (2)

7-10: Update documentation to reflect protocol unification

The documentation lists protocols that appear inconsistent with the unification changes. Line 7 has been updated to only include "mix" protocol, but lines 8-10 still list "ack", "heartbeat", and "ticket_aggregation" as separate protocols.

Update the documentation to accurately reflect the current protocol structure after unification:

-//! - `mix`
-//! - `ack`
-//! - `heartbeat`
-//! - `ticket_aggregation`
+//! - `mix` (unified protocol handling both messages and acknowledgments)
+//! - `heartbeat`

316-319: Optimize acknowledgment creation

There are multiple instances of creating acknowledgments with unnecessary copying.

Consider optimizing the acknowledgment data copying:

-db.to_send_no_ack(Box::from_iter(ack.as_ref().iter().copied()), previous_hop) // TODO: Optimize this copy
+db.to_send_no_ack(Box::from(ack.as_ref()), previous_hop)

This creates the Box directly from the acknowledgment reference, avoiding the need to iterate and copy each byte individually.

Also applies to: 352-354

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6326b71 and 5d47cdd.

📒 Files selected for processing (1)
  • transport/protocol/src/lib.rs (9 hunks)
🔇 Additional comments (8)
transport/protocol/src/lib.rs (8)

47-48: LGTM - New unified protocol structure looks good

The refactored code introduces a new processor module and simplified codec structure, which aligns well with the PR objective of unifying the message and acknowledgment protocols.

Also applies to: 59-60, 81-87


163-165: LGTM - Appropriate metric adjustments

Commenting out the acknowledgment and ticket metrics is consistent with the protocol unification approach.


192-193: LGTM - Simplified packet processor initialization

The packet processor initialization no longer requires a bloom filter parameter, which aligns with the unified approach to packet processing.


258-273: LGTM - Sending fallback acknowledgment on packet processing failure

The implementation sends a random signed acknowledgment back to the sender when packet processing fails, which provides useful feedback.


280-299: LGTM - Effective replay detection with bloom filter

The code properly handles replay detection using the bloom filter, incrementing metrics and dropping replayed packets.


309-334: LGTM - Clear handling of final packets

The code for processing final packets correctly extracts the plaintext and sends an acknowledgment back to the previous hop.


335-368: LGTM - Efficient packet forwarding logic

The forwarding logic handles both packet forwarding and acknowledgment sending appropriately.


371-377: LGTM - Proper application data decoding

The code correctly filters and decodes application data, with appropriate error logging.

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/lib.rs (1)

163-165: Commented out metric initializations

These metrics initializations are commented out but not removed. Consider either removing them completely if they're no longer needed or properly reinitializing them if they'll be used in the future.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5d47cdd and 9900de3.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • crypto/packet/Cargo.toml (1 hunks)
  • db/api/Cargo.toml (1 hunks)
  • db/sql/Cargo.toml (1 hunks)
  • db/sql/src/protocol.rs (13 hunks)
  • logic/strategy/Cargo.toml (3 hunks)
  • transport/api/Cargo.toml (6 hunks)
  • transport/p2p/Cargo.toml (1 hunks)
  • transport/protocol/Cargo.toml (2 hunks)
  • transport/protocol/src/lib.rs (9 hunks)
✅ Files skipped from review due to trivial changes (4)
  • db/sql/Cargo.toml
  • crypto/packet/Cargo.toml
  • transport/p2p/Cargo.toml
  • db/api/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (4)
  • transport/protocol/Cargo.toml
  • logic/strategy/Cargo.toml
  • transport/api/Cargo.toml
  • db/sql/src/protocol.rs
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: Teebor-Choka
PR: hoprnet/hoprnet#6765
File: transport/api/src/lib.rs:602-605
Timestamp: 2025-01-15T14:52:38.363Z
Learning: In the HOPR transport layer, the `TicketAggregatorProxy` is intentionally kept separate from the main transport interface to allow for potential extraction to upper interfaces in the future. This design decision facilitates architectural flexibility and should be maintained.
⏰ 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: tests-unit-nightly
  • GitHub Check: tests-unit
  • GitHub Check: tests-smoke-websocket
  • GitHub Check: Linter
  • GitHub Check: tests-smart-contracts
  • GitHub Check: zizmor
  • GitHub Check: Cargo Audit
🔇 Additional comments (10)
transport/protocol/src/lib.rs (10)

7-7: Documentation updated to reflect protocol unification

The protocol name change from "msg" to "mix" in the documentation correctly reflects the unification of message and acknowledgment protocols into a single payload structure as described in the PR objectives.


59-60: Module restructuring aligns with protocol unification

The change from separate message and acknowledgment modules to a unified "processor" module aligns well with the PR objective of unifying these protocols at the libp2p level.


84-87: Well-defined packet size constants and codec types

The addition of constants for packet size and defining a fixed-length codec type alias improves code clarity and maintainability. The protocol name constant also helps with protocol versioning.


254-260: Improved error handling for PeerId conversion

This change properly handles the error case when converting PeerId to OffchainPublicKey instead of using unwrap(), which could cause panics. This is a good improvement that addresses a previous review comment.


262-280: Enhanced error feedback with random signed acknowledgement

Sending a random signed acknowledgement when packet processing fails provides valuable feedback to the sender, improving the protocol's robustness. The error handling is comprehensive with appropriate logging.


286-308: Explicit replay detection with bloom filter

The implementation now includes explicit replay detection using the bloom filter, which helps prevent replay attacks. The metrics for replayed packets are appropriately incremented when replays are detected.


317-341: Unified packet handling for final packets

The handling of final packets now includes proper acknowledgment creation and sending, with comprehensive error handling. This implementation aligns with the goal of unifying message and acknowledgment protocols.


342-377: Comprehensive forwarded packet handling

The forwarding logic includes both sending the packet to the next hop and sending an acknowledgment back to the previous hop, with robust error handling throughout. This implementation supports the unified protocol approach well.


378-384: Improved application data decoding with error handling

The application data decoding process now includes proper error handling with detailed logging, which will make debugging issues easier.


192-193:

✅ Verification successful

Packet processor instantiation without bloom filter

The packet processor is now instantiated without the bloom filter argument, which suggests the bloom filter handling has been moved internally. Ensure this aligns with the implementation in the processor module.


🏁 Script executed:

#!/bin/bash
# Check if the packet processor implementation handles bloom filter internally
grep -A 20 "struct PacketProcessor" transport/protocol/src/processor.rs || echo "PacketProcessor struct not found"

Length of output: 698


🏁 Script executed:

#!/bin/bash
# Search for PacketProcessor::new signature
grep -R "impl<Db> PacketProcessor" -n transport/protocol/src/processor.rs -A 20

# Specifically locate the constructor
rg "fn new" -n transport/protocol/src/processor.rs

# Search for bloom usage in the transport protocol module
rg "bloom" -n transport/protocol/src

# Locate PacketInteractionConfig definition
rg "struct PacketInteractionConfig" -n transport/protocol/src

Length of output: 2314


🏁 Script executed:

#!/bin/bash
# Print PacketInteractionConfig definition and its fields
sed -n '250,300p' transport/protocol/src/processor.rs

# Locate where packet_cfg is constructed in the main library
grep -R -n "packet_cfg" transport/protocol/src/lib.rs -A 20

Length of output: 4653


Bloom filter integration confirmed in lib.rs; no changes needed

The PacketProcessor::new(db, cfg) constructor correctly only takes the database and PacketInteractionConfig. Bloom filter setup and persistence are handled upstream in transport/protocol/src/lib.rs via the WrappedTagBloomFilter, so no bloom-filter argument is required in the processor module.

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: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9900de3 and 8cfa712.

📒 Files selected for processing (2)
  • db/sql/src/db.rs (1 hunks)
  • db/sql/src/protocol.rs (13 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • db/sql/src/protocol.rs
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: Teebor-Choka
PR: hoprnet/hoprnet#6765
File: transport/api/src/lib.rs:602-605
Timestamp: 2025-01-15T14:52:38.363Z
Learning: In the HOPR transport layer, the `TicketAggregatorProxy` is intentionally kept separate from the main transport interface to allow for potential extraction to upper interfaces in the future. This design decision facilitates architectural flexibility and should be maintained.
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: tests-smoke-websocket
  • GitHub Check: tests-unit
  • GitHub Check: tests-smart-contracts
  • GitHub Check: tests-unit-nightly
  • GitHub Check: hoprd / docker
  • GitHub Check: hopli / docker
  • GitHub Check: Docs / Rust docs
  • GitHub Check: Linter
  • GitHub Check: zizmor
  • GitHub Check: Cargo Audit

@Teebor-Choka
Copy link
Contributor Author

The github runner for the unit tests has disk I/O errors, tested locally for unit tests - all passing.

@Teebor-Choka Teebor-Choka merged commit 507c5a0 into master May 3, 2025
29 of 32 checks passed
@Teebor-Choka Teebor-Choka deleted the kauki/protocol/unify-the-msg-ack-protocol branch May 3, 2025 09:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants