Skip to content

Allow using Amaru as an upstream Cardano node#251

Merged
abailly merged 23 commits into
mainfrom
abailly/connect-2-nodes
Jun 17, 2025
Merged

Allow using Amaru as an upstream Cardano node#251
abailly merged 23 commits into
mainfrom
abailly/connect-2-nodes

Conversation

@abailly

@abailly abailly commented Jun 11, 2025

Copy link
Copy Markdown
Contributor

This PR adds a minimal ability to let other Cardano nodes connect to an Amaru upstream node and start syncing the chain from them:

  • fix the block type which was wrongly set to 1
  • actually implement minimal block-fetch server to serve blocks to downstream peers.

This PR has only been tested with 2 Amaru nodes and usage documents are not updated because this new feature can be used simply by running an Amaru node and setting its --peer-address argument to the --listen-address of the other Amaru node. We would want to check what happens if a cardano-node connects to the Amaru node and sync from them.

Also, there's no automated tests which is annoying: I don't have a good mental model of how to write tests for these low-level network features.

Summary by CodeRabbit

  • New Features

    • Implemented a minimal block fetch server that serves single-block requests and returns a specific error for unsupported range requests.
  • Bug Fixes

    • Improved error handling and logging in header reception, validation, block fetching, and chain selection for better troubleshooting.
  • Documentation

    • Removed outdated information about protocol implementation status.
  • Chores

    • Updated CI workflow to use a newer runner environment and ensure required system packages are installed.
  • Refactor

    • Introduced macros to simplify message sending and scheduling across multiple components, reducing boilerplate and enhancing error logging.
    • Enhanced logging for chain selection and protocol operations to aid in debugging and monitoring.
    • Added structured tracing instrumentation and improved span context propagation across stages.
    • Refactored event handling to adopt tracing spans from events, improving observability.
    • Added display formatting for peer entities to improve logging clarity.

@coderabbitai

coderabbitai Bot commented Jun 11, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Alright mate, here's the skinny: This update tweaks the CI workflow for the aarch64-unknown-linux-musl target, spruces up error logging and tracing in consensus stages, introduces handy macros for async message handling, and gives the block fetch protocol a proper minimal implementation. There's also a bit of tidying up in the docs and some extra trace logging sprinkled about for good measure.

Changes

File(s) Summary
.github/workflows/CI.yml Changed runner for aarch64-unknown-linux-musl to ubuntu-24.04; added pkg-config and libssl-dev install in setup step.
crates/amaru-consensus/src/consensus/select_chain.rs Added Span parameter propagation; added trace log before switch_to_fork; enhanced error logging and tracing macros.
crates/amaru-consensus/src/consensus/validate_header.rs Added Span parameter to handle_roll_forward; propagate span from event; improved error logging.
crates/amaru-consensus/src/peer.rs Added Display trait implementation for Peer struct.
crates/amaru/src/stages/consensus/forward_chain/README.md Removed line about protocol implementation status.
crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs Implemented block fetch for single-block requests; added CannotServeRange error; updated header variant; import tweaks.
crates/amaru/src/stages/consensus/receive_header.rs Added error logging for chain sync handling failures; refactored send and schedule with macros.
crates/amaru/src/stages/consensus/validate_header.rs Added error logging for consensus and message receive failures; improved error handling in schedule and handle_event.
crates/amaru/src/point.rs Changed from_network_point argument to take reference instead of value.
crates/amaru/src/stages/pull.rs Changed from_network_point argument to reference; refactored event sending with macros; updated tracing spans.
crates/amaru/src/stages/common.rs Added macros send! and schedule! for async message send/receive with error logging; added HasSpan trait and span adoption function.
crates/amaru/src/stages/consensus/fetch_block.rs Added error logging and proper error propagation in block fetch event handling; used scheduling macro; tracing added.
crates/amaru/src/stages/consensus/forward_chain.rs Refactored worker to handle validation results in dedicated method; added tracing instrumentation and logs.
crates/amaru/src/stages/consensus/select_chain.rs Added error logging and macro usage for send and schedule; replaced panics with error propagation; tracing added.
crates/amaru/src/stages/consensus/store_block.rs Replaced explicit send/receive calls with macros for cleaner code; added tracing instrumentation.
crates/amaru/src/stages/consensus/store_header.rs Added error logging on event handling failure; replaced send/receive calls with macros; tracing added.
crates/amaru/src/stages/ledger.rs Replaced manual send/receive with macros for scheduling and sending messages; adopted tracing spans from units.
crates/amaru/src/stages/mod.rs Added new public submodule common for shared macros and traits.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Server
    participant ChainStore

    Client->>Server: BlockFetch(BlockRequest { lower, upper })
    alt lower == upper
        Server->>ChainStore: Load block at point
        ChainStore-->>Server: Block
        Server->>Client: Batch with single block
    else lower != upper
        Server->>Client: Error: CannotServeRange(lower, upper)
    end
    Client-->>Server: Terminate (optional)
Loading

Possibly related PRs

Suggested reviewers

  • jeluard
  • KtorZ

Poem

🍀 G’day coder, here’s a tale to spin,
Logs now shout loud, no errors thin.
Block fetch got sharp, no more just a tease,
Ubuntu 24.04 with packages to please.
Raise your flat white, or a stout so great,
For code that sings and builds first-rate! ☕🎮

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • 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 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 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@jeluard jeluard force-pushed the abailly/bootstrap-command branch from 096ab06 to 5ed19de Compare June 11, 2025 14:03
@abailly abailly force-pushed the abailly/connect-2-nodes branch from fc2da64 to 6acd9be Compare June 11, 2025 17:01
@jeluard

jeluard commented Jun 13, 2025

Copy link
Copy Markdown
Contributor

Still a draft? Also, does it have to be based on branch abailly/bootstrap-command ?

@abailly

abailly commented Jun 13, 2025

Copy link
Copy Markdown
Contributor Author

I can rebase it to main I think, let me try.

@abailly

abailly commented Jun 13, 2025

Copy link
Copy Markdown
Contributor Author

Actually, I wanted to have some proper e2e test in place before undrafting it

@abailly abailly force-pushed the abailly/connect-2-nodes branch from 6acd9be to 58741b1 Compare June 13, 2025 07:29
Base automatically changed from abailly/bootstrap-command to main June 13, 2025 10:30
@abailly abailly marked this pull request as ready for review June 13, 2025 14:55
@codecov

codecov Bot commented Jun 13, 2025

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 32.19512% with 139 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/amaru/src/stages/common.rs 35.00% 26 Missing ⚠️
crates/amaru/src/stages/consensus/fetch_block.rs 4.16% 23 Missing ⚠️
crates/amaru/src/stages/ledger.rs 5.88% 16 Missing ⚠️
.../stages/consensus/forward_chain/client_protocol.rs 18.75% 13 Missing ⚠️
crates/amaru/src/stages/consensus/forward_chain.rs 79.24% 11 Missing ⚠️
...ates/amaru-consensus/src/consensus/select_chain.rs 0.00% 9 Missing ⚠️
crates/amaru/src/stages/pull.rs 0.00% 9 Missing ⚠️
...rates/amaru/src/stages/consensus/receive_header.rs 14.28% 6 Missing ⚠️
crates/amaru/src/stages/consensus/select_chain.rs 14.28% 6 Missing ⚠️
crates/amaru/src/stages/consensus/store_header.rs 14.28% 6 Missing ⚠️
... and 5 more
Files with missing lines Coverage Δ
crates/amaru/src/stages/mod.rs 84.27% <ø> (ø)
crates/amaru/src/point.rs 0.00% <0.00%> (ø)
...s/amaru-consensus/src/consensus/validate_header.rs 74.41% <0.00%> (+0.77%) ⬆️
crates/amaru/src/stages/consensus/store_block.rs 56.00% <33.33%> (+2.15%) ⬆️
crates/amaru-consensus/src/peer.rs 62.50% <0.00%> (-37.50%) ⬇️
...rates/amaru/src/stages/consensus/receive_header.rs 38.88% <14.28%> (-4.87%) ⬇️
crates/amaru/src/stages/consensus/select_chain.rs 45.16% <14.28%> (-4.84%) ⬇️
crates/amaru/src/stages/consensus/store_header.rs 56.00% <14.28%> (+4.14%) ⬆️
...ates/amaru/src/stages/consensus/validate_header.rs 50.00% <14.28%> (+1.61%) ⬆️
...ates/amaru-consensus/src/consensus/select_chain.rs 3.26% <0.00%> (ø)
... and 6 more

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
crates/amaru/src/stages/consensus/validate_header.rs (1)

46-55: Same wrapping remark as in receive_header

Swapping the source error for WorkerError::Recv drops valuable context.
A thin wrapper keeps logs happy while allowing callers to inspect the root cause. Same diff pattern applies here.

🧹 Nitpick comments (3)
crates/amaru-consensus/src/consensus/select_chain.rs (1)

90-93: Nice trace hook, but include the peer for richer breadcrumbs

Love the extra log, mate – helps when spelunking through forks like Nathan Drake.
Tiny nit: emit the peer ID so we know who twisted our arm.

-trace!(target: EVENT_TARGET, rollback = %rollback_point, "switching to fork");
+trace!(target: EVENT_TARGET, rollback = %rollback_point, peer = %peer, "switching to fork");
crates/amaru/src/stages/consensus/receive_header.rs (1)

35-38: Preserve the original error to ease post-mortems

We log the error but then map it to a generic WorkerError::Recv, losing the juicy stack for upstream handlers.
Consider wrapping instead of replacing so the caller can still pattern-match or bubble it up later.

-    .map_err(|e| {
-        error!("fail to handle chain sync {}", e);
-        WorkerError::Recv
-    })?;
+    .map_err(|e| {
+        error!("fail to handle chain sync: {e}");
+        WorkerError::RecvWithCause(Box::new(e))
+    })?;

(Assumes you add RecvWithCause or similar to WorkerError.)
It’s the difference between a VHS and 4K when debugging.

crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs (1)

242-247: Helper converts slot/hash nicely – promote to amaru_kernel::Point::from?

from_pallas_point is handy. Consider moving it to a shared util module and implementing From<Point> for amaru_kernel::Point so the conversion becomes ergonomic throughout the codebase.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02649fd and 58741b1.

⛔ Files ignored due to path filters (1)
  • examples/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • .github/workflows/CI.yml (1 hunks)
  • crates/amaru-consensus/src/consensus/select_chain.rs (1 hunks)
  • crates/amaru/src/stages/consensus/forward_chain/README.md (0 hunks)
  • crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs (4 hunks)
  • crates/amaru/src/stages/consensus/receive_header.rs (2 hunks)
  • crates/amaru/src/stages/consensus/validate_header.rs (3 hunks)
💤 Files with no reviewable changes (1)
  • crates/amaru/src/stages/consensus/forward_chain/README.md
🧰 Additional context used
🧬 Code Graph Analysis (1)
crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs (1)
crates/amaru/src/stages/consensus/forward_chain/test_infra.rs (1)
  • hash (136-138)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: Build on windows-latest with target x86_64-pc-windows-msvc
  • GitHub Check: Build on macos-latest with target aarch64-apple-darwin
  • GitHub Check: Build on ubuntu-latest with target x86_64-unknown-linux-gnu
  • GitHub Check: Build on ubuntu-latest with target riscv32im-risc0-zkvm-elf
  • GitHub Check: Build on ubuntu-24.04 with target aarch64-unknown-linux-musl
  • GitHub Check: Coverage
  • GitHub Check: Snapshots (preprod, 10.1.4)
🔇 Additional comments (2)
crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs (2)

31-33: Good UX: explicit error for unsupported ranges

The new CannotServeRange variant is a solid shout. 👍
No action needed, just tipping the hat.


208-212: Hard-coding variant: 6 – confirm protocol version drift

The variant jumped from 1 to 6. Make sure the downstream Cardano nodes you plan to charm actually expect 6, or you’ll be speaking Klingon while they listen for Elvish.

Comment thread .github/workflows/CI.yml
Comment on lines +70 to 74
- runner: ubuntu-24.04
target: aarch64-unknown-linux-musl
command: test
setup: rustup target add aarch64-unknown-linux-musl
setup: rustup target add aarch64-unknown-linux-musl && sudo apt-get install -y pkg-config libssl-dev
cross-compile: true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Add an apt-get update before installing packages

The new inline setup command installs pkg-config and libssl-dev, but skips an apt-get update.
Fresh runners occasionally have stale package indices which blows up with the classic “Unable to locate package” error and tanks the matrix job faster than a go-kart hitting a blue shell.

-setup: rustup target add aarch64-unknown-linux-musl && sudo apt-get install -y pkg-config libssl-dev
+setup: |
+  rustup target add aarch64-unknown-linux-musl
+  sudo apt-get update -y
+  sudo apt-get install -y pkg-config libssl-dev

Add sudo apt-get update to the CI setup step

Hey team, on fresh Ubuntu 24.04 runners the apt cache can be a wee bit dusty—think of it like trying to pick up loot from a sandbox without refreshing the map in an RPG. Let’s stave off the classic “Unable to locate package” boss fight by updating before we install.

Locations to tweak:

  • .github/workflows/CI.yml, lines ~70–74

Suggested change:

- setup: rustup target add aarch64-unknown-linux-musl && sudo apt-get install -y pkg-config libssl-dev
+ setup: |
+   rustup target add aarch64-unknown-linux-musl
+   sudo apt-get update -y
+   sudo apt-get install -y pkg-config libssl-dev
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- runner: ubuntu-24.04
target: aarch64-unknown-linux-musl
command: test
setup: rustup target add aarch64-unknown-linux-musl
setup: rustup target add aarch64-unknown-linux-musl && sudo apt-get install -y pkg-config libssl-dev
cross-compile: true
- runner: ubuntu-24.04
target: aarch64-unknown-linux-musl
command: test
setup: |
rustup target add aarch64-unknown-linux-musl
sudo apt-get update -y
sudo apt-get install -y pkg-config libssl-dev
cross-compile: true
🤖 Prompt for AI Agents
In .github/workflows/CI.yml around lines 70 to 74, the setup command installs
packages without running 'apt-get update' first, which can cause package not
found errors on fresh runners. Fix this by prepending 'sudo apt-get update &&'
to the setup command so the package index is refreshed before installing
pkg-config and libssl-dev.

Comment thread crates/amaru/src/stages/consensus/validate_header.rs Outdated
Comment thread crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs
Comment thread crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs
Comment thread crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (2)
crates/amaru/src/point.rs (1)

18-22: Avoid the full clone – match on the borrowed value instead

Solid move switching to a borrowed arg, mate, but the clone() inside drags a full Vec<u8> copy each time we traverse this function. We can sidestep that overhead by pattern-matching on the reference and only cloning the hash when needed:

-pub(crate) fn from_network_point(point: &pallas_network::miniprotocols::Point) -> Point {
-    match point.clone() {
-        pallas_network::miniprotocols::Point::Origin => Point::Origin,
-        pallas_network::miniprotocols::Point::Specific(slot, hash) => Point::Specific(slot, hash),
-    }
+pub(crate) fn from_network_point(point: &pallas_network::miniprotocols::Point) -> Point {
+    match point {
+        pallas_network::miniprotocols::Point::Origin => Point::Origin,
+        pallas_network::miniprotocols::Point::Specific(slot, hash) => {
+            Point::Specific(*slot, hash.clone())
+        }
+    }
 }

Same semantics, leaner byte-shuffling. Unless we’re in “who cares, it’s once per epoch” land, this keeps things tidy.

crates/amaru/src/stages/pull.rs (1)

205-207: Borrowing looks grand, but watch the double-clone cost

Passing &point aligns nicely with the new signature – cheers. Just flagging that from_network_point still clones internally, so we’re paying for the copy even though we still own point here. If you tweak from_network_point per the earlier suggestion, this call site stays the same and we dodge the surplus clone.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58741b1 and 3a2bfea.

📒 Files selected for processing (3)
  • crates/amaru/src/point.rs (1 hunks)
  • crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs (4 hunks)
  • crates/amaru/src/stages/pull.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: Build on windows-latest with target x86_64-pc-windows-msvc
  • GitHub Check: Build on ubuntu-24.04 with target aarch64-unknown-linux-musl
  • GitHub Check: Build on ubuntu-latest with target riscv32im-risc0-zkvm-elf
  • GitHub Check: Coverage
  • GitHub Check: Sanity
  • GitHub Check: Snapshots (preprod, 10.1.4)
  • GitHub Check: Build on macos-latest with target aarch64-apple-darwin

@abailly abailly force-pushed the abailly/connect-2-nodes branch from 3a2bfea to 17bbff7 Compare June 16, 2025 07:53

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
crates/amaru/src/stages/consensus/select_chain.rs (1)

47-55: 🛠️ Refactor suggestion

Misleading error kind on chain-selection failure

WorkerError::Recv suggests an I/O glitch, yet the failure comes from business logic inside select_chain.handle_chain_sync. Consider mapping to WorkerError::Panic or a dedicated WorkerError::Stage to avoid masking real bugs behind “recv” noise.

🧹 Nitpick comments (7)
crates/amaru/src/stages/common.rs (1)

19-27: 💌 send! macro: ergonomics are ace, but consider a tiny polish

The macro already does the heavy lifting, yet every call site must remember to tack on ? to bubble-up the Result.
An alternative is to return () and handle the error conversion inside the macro, sparing callers from the extra sigil and keeping their intent crystal-clear:

-$port.send($msg.into()).await.map_err(|e| {
-    tracing::error!(error=%e, "failed to send event");
-    gasket::framework::WorkerError::Send
-})
+if let Err(e) = $port.send($msg.into()).await {
+    tracing::error!(error = %e, "failed to send event");
+    return Err(gasket::framework::WorkerError::Send);
+}
+Ok(())

No functional bug here, just a UX upgrade for future devs.

crates/amaru/src/stages/consensus/forward_chain.rs (1)

342-343: Nit: stick to structured logging fields

Everywhere else you’re using error!(error=%e, ...). Here we switched to a free-text message. For log-query tooling it’s handier to keep the error=%e field.

-error!(target: EVENT_TARGET, "Unit::Peer was empty in execute");
+error!(target: EVENT_TARGET, reason = "empty Unit::Peer");
crates/amaru/src/stages/consensus/select_chain.rs (1)

19-22: Unnecessary macro import clutters namespace

send! and schedule! are in the crate root thanks to #[macro_export], so use crate::{schedule, send}; isn’t required and trips unused_imports when macro_use linting is tightened.

-use crate::{schedule, send};
+// macros are in scope by default
crates/amaru/src/stages/consensus/store_header.rs (2)

15-19: Same import quirk as above

Macros don’t need the use crate::{schedule, send}; import; drop it to dodge lints.


44-51: Structured error logging for the win

The new error message is free-text ("fail to store header {}"). For grep-less observability stick with structured fields, e.g.:

-error!("fail to store header {}", e);
+error!(error = %e, "fail to store header");
crates/amaru/src/stages/consensus/fetch_block.rs (2)

63-70: Now that send! exists let’s use it for symmetry

You manually map the send error instead of going through send!; keeps two codepaths alive for the same job.

- self.downstream
-     .send(ValidateBlockEvent::Validated { point, block, span }.into())
-     .await
-     .map_err(|e| {
-         error!(error=%e, "failed to send event");
-         WorkerError::Send
-     })?
+ send!(&mut self.downstream,
+     ValidateBlockEvent::Validated { point, block, span }.into()
+ )?;

94-114: Potential DOS: single peer fetch path

fetch_block fails the whole stage if the chosen peer doesn’t have the block.
Given the comment // FIXME: you’re already aware, but flagging: a malicious or lagging peer can now stall sync. Consider falling back to any peer claiming height ≥ slot.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a2bfea and 17bbff7.

📒 Files selected for processing (16)
  • .github/workflows/CI.yml (1 hunks)
  • crates/amaru-consensus/src/consensus/select_chain.rs (1 hunks)
  • crates/amaru/src/point.rs (1 hunks)
  • crates/amaru/src/stages/common.rs (1 hunks)
  • crates/amaru/src/stages/consensus/fetch_block.rs (3 hunks)
  • crates/amaru/src/stages/consensus/forward_chain.rs (2 hunks)
  • crates/amaru/src/stages/consensus/forward_chain/README.md (0 hunks)
  • crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs (4 hunks)
  • crates/amaru/src/stages/consensus/receive_header.rs (3 hunks)
  • crates/amaru/src/stages/consensus/select_chain.rs (3 hunks)
  • crates/amaru/src/stages/consensus/store_block.rs (3 hunks)
  • crates/amaru/src/stages/consensus/store_header.rs (3 hunks)
  • crates/amaru/src/stages/consensus/validate_header.rs (3 hunks)
  • crates/amaru/src/stages/ledger.rs (3 hunks)
  • crates/amaru/src/stages/mod.rs (1 hunks)
  • crates/amaru/src/stages/pull.rs (3 hunks)
💤 Files with no reviewable changes (1)
  • crates/amaru/src/stages/consensus/forward_chain/README.md
✅ Files skipped from review due to trivial changes (3)
  • crates/amaru/src/stages/mod.rs
  • crates/amaru/src/stages/ledger.rs
  • crates/amaru/src/stages/consensus/store_block.rs
🚧 Files skipped from review as they are similar to previous changes (7)
  • crates/amaru-consensus/src/consensus/select_chain.rs
  • crates/amaru/src/stages/pull.rs
  • crates/amaru/src/point.rs
  • crates/amaru/src/stages/consensus/validate_header.rs
  • .github/workflows/CI.yml
  • crates/amaru/src/stages/consensus/receive_header.rs
  • crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs
🧰 Additional context used
🧬 Code Graph Analysis (3)
crates/amaru/src/stages/common.rs (7)
crates/amaru/src/stages/consensus/receive_header.rs (1)
  • schedule (54-59)
crates/amaru/src/stages/consensus/select_chain.rs (1)
  • schedule (73-78)
crates/amaru/src/stages/consensus/store_block.rs (1)
  • schedule (63-68)
crates/amaru/src/stages/consensus/fetch_block.rs (1)
  • schedule (125-130)
crates/amaru/src/stages/consensus/store_header.rs (1)
  • schedule (62-67)
crates/amaru/src/stages/consensus/validate_header.rs (1)
  • schedule (70-75)
crates/amaru/src/stages/ledger.rs (1)
  • schedule (158-163)
crates/amaru/src/stages/consensus/select_chain.rs (8)
crates/amaru/src/stages/consensus/receive_header.rs (1)
  • schedule (54-59)
crates/amaru/src/stages/consensus/store_block.rs (1)
  • schedule (63-68)
crates/amaru/src/stages/consensus/fetch_block.rs (1)
  • schedule (125-130)
crates/amaru/src/stages/consensus/store_header.rs (1)
  • schedule (62-67)
crates/amaru/src/stages/consensus/validate_header.rs (1)
  • schedule (70-75)
crates/amaru/src/stages/ledger.rs (1)
  • schedule (158-163)
crates/amaru/src/stages/consensus/forward_chain.rs (1)
  • schedule (232-245)
crates/amaru/src/stages/pull.rs (1)
  • schedule (160-171)
crates/amaru/src/stages/consensus/fetch_block.rs (7)
crates/amaru/src/stages/consensus/receive_header.rs (1)
  • schedule (54-59)
crates/amaru/src/stages/consensus/select_chain.rs (1)
  • schedule (73-78)
crates/amaru/src/stages/consensus/store_block.rs (1)
  • schedule (63-68)
crates/amaru/src/stages/consensus/store_header.rs (1)
  • schedule (62-67)
crates/amaru/src/stages/consensus/validate_header.rs (1)
  • schedule (70-75)
crates/amaru/src/stages/ledger.rs (1)
  • schedule (158-163)
crates/amaru/src/stages/pull.rs (1)
  • schedule (160-171)
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Build on ubuntu-24.04 with target aarch64-unknown-linux-musl
  • GitHub Check: Build on windows-latest with target x86_64-pc-windows-msvc
  • GitHub Check: Build on ubuntu-latest with target riscv32im-risc0-zkvm-elf
  • GitHub Check: Coverage
  • GitHub Check: Build on macos-latest with target aarch64-apple-darwin
  • GitHub Check: Snapshots (preprod, 10.1.4)
🔇 Additional comments (4)
crates/amaru/src/stages/common.rs (1)

34-44: 🤔 schedule! macro may leak envelopes when recv yields an error

InputPort::recv() only errors on channel closure; otherwise it returns an envelope.
Mapping the envelope straight to unit.payload means any Envelope::Ack/control message would be silently ignored instead of being acked, potentially causing upstream back-pressure to stall.

Double-check the semantics of Envelope; if non-data variants exist, we need to handle/ack them explicitly before turning them into WorkSchedule::Unit.

crates/amaru/src/stages/consensus/forward_chain.rs (1)

279-285: 🍻 Great visibility! Tiny trace tweak

Love the new "tip_changed" log – makes following chain growth a breeze.
You’re forwarding the original span (from the peer) as parent; if you meant to keep the internal _span you just opened a few lines above, swap parent: span for parent: &_span. Otherwise all good.

crates/amaru/src/stages/consensus/select_chain.rs (1)

57-59: Consistency: leverage your own send! macro

Great that you brought the macro in – but the loop still uses the explicit call.

-        for event in events {
-            send!(&mut self.downstream, event)?;
-        }
+        for event in events {
+            send!(&mut self.downstream, event)?;
+        }

(If you keep the loop minimalist, a .try_for_each could shave a line, but that’s just bikeshedding.)

crates/amaru/src/stages/consensus/fetch_block.rs (1)

56-63: Goodbye panics, hello logs – love it!

Replacing the or_panic() with proper error bubbling keeps the node alive in face of flaky peers. Nicely played 👌

Comment on lines 17 to 23
use crate::schedule;
use crate::stages::PeerSession;
use amaru_consensus::{consensus::ValidateHeaderEvent, peer::Peer, ConsensusError};
use amaru_kernel::{block::ValidateBlockEvent, Point};
use gasket::framework::*;
use tracing::{instrument, Span};
use tracing::{error, instrument, Span};
use tracing_opentelemetry::OpenTelemetrySpanExt;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Importing PeerSession but never using it

use crate::stages::PeerSession; vanished from the diff’s body – looks like deadwood sneaked in.

-use crate::stages::PeerSession;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
use crate::schedule;
use crate::stages::PeerSession;
use amaru_consensus::{consensus::ValidateHeaderEvent, peer::Peer, ConsensusError};
use amaru_kernel::{block::ValidateBlockEvent, Point};
use gasket::framework::*;
use tracing::{instrument, Span};
use tracing::{error, instrument, Span};
use tracing_opentelemetry::OpenTelemetrySpanExt;
use crate::schedule;
use amaru_consensus::{consensus::ValidateHeaderEvent, peer::Peer, ConsensusError};
use amaru_kernel::{block::ValidateBlockEvent, Point};
use gasket::framework::*;
use tracing::{error, instrument, Span};
use tracing_opentelemetry::OpenTelemetrySpanExt;
🤖 Prompt for AI Agents
In crates/amaru/src/stages/consensus/fetch_block.rs between lines 17 and 23, the
import statement for PeerSession is present but not used anywhere in the code.
Remove the line `use crate::stages::PeerSession;` to clean up unused imports and
avoid dead code.

jeluard and others added 15 commits June 16, 2025 19:39
Signed-off-by: jeluard <jeluard@users.noreply.github.com>
Signed-off-by: jeluard <jeluard@users.noreply.github.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
This does the minimum to be able to serve blocks to a downstream Amaru
node.

Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
while I think the node  selecting a new tip should be an 'info' and
not a 'trace', this makes the CI timeout because of the amount of log
entries it generates which are captured by GHA.

Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
abailly added 8 commits June 17, 2025 08:42
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
@abailly abailly force-pushed the abailly/connect-2-nodes branch from d2560a1 to fa4621f Compare June 17, 2025 09:11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (2)
crates/amaru-consensus/src/consensus/validate_header.rs (2)

146-154: Parameter bloat – consider folding span into the event, not the API

handle_roll_forward now asks callers for an explicit Span.
The method does nothing with it except shuttle it back inside the result.
Every caller already has the span (it was extracted from the incoming
DecodedChainSyncEvent). Passing it back-and-forth through every layer
just mushrooms the surface of the API and forces ripple edits across the
codebase.

You could slim things down by:

-        span: Span,
+        // no span parameter

and inside the Ok(...) block simply reuse Span::current() (or attach
span fetched from the incoming event, if that’s the desired parent).

That keeps the public signature lean and avoids a param that carries no
new information.


229-236: Two nearly-identical code paths → maintenance gremlin

handle_chain_sync calls the “classic” handle_roll_forward, while
validate_header routes to handle_roll_forward_new. Both functions
perform the same checks but diverge on how evolve_nonce is executed
(one holds the mutex directly, the other wraps it in an ExternalEffect
for pure-stage).

Duplicated validation logic will inevitably drift (the old “Left 4
Dead vs. Left 4 Dead 2” patch dilemma). Extract the common bits into a
private helper, and let each public function focus only on where the
nonce data comes from.

Something like:

async fn process_roll_forward(
    &self,
    point: &Point,
    header: &Header,
    epoch_nonce: &Nonce,
    global_parameters: &GlobalParameters,
) -> Result<(), ConsensusError> { ... }

Both callers can then fetch epoch_nonce their preferred way and dunk
it into this helper.

🧹 Nitpick comments (1)
crates/amaru-consensus/src/consensus/validate_header.rs (1)

172-177: Redundant data shuffling – span is already inside the event

Here the span is piped straight from the parameter into the output
struct unmodified. The code tells us nothing is done with the span in
between, so schlepping it through the function doesn’t add value and
just invites ordering mistakes down the road.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2560a1 and fa4621f.

📒 Files selected for processing (18)
  • .github/workflows/CI.yml (1 hunks)
  • crates/amaru-consensus/src/consensus/select_chain.rs (4 hunks)
  • crates/amaru-consensus/src/consensus/validate_header.rs (3 hunks)
  • crates/amaru-consensus/src/peer.rs (1 hunks)
  • crates/amaru/src/point.rs (1 hunks)
  • crates/amaru/src/stages/common.rs (1 hunks)
  • crates/amaru/src/stages/consensus/fetch_block.rs (3 hunks)
  • crates/amaru/src/stages/consensus/forward_chain.rs (5 hunks)
  • crates/amaru/src/stages/consensus/forward_chain/README.md (0 hunks)
  • crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs (4 hunks)
  • crates/amaru/src/stages/consensus/receive_header.rs (4 hunks)
  • crates/amaru/src/stages/consensus/select_chain.rs (3 hunks)
  • crates/amaru/src/stages/consensus/store_block.rs (3 hunks)
  • crates/amaru/src/stages/consensus/store_header.rs (3 hunks)
  • crates/amaru/src/stages/consensus/validate_header.rs (3 hunks)
  • crates/amaru/src/stages/ledger.rs (4 hunks)
  • crates/amaru/src/stages/mod.rs (1 hunks)
  • crates/amaru/src/stages/pull.rs (4 hunks)
💤 Files with no reviewable changes (1)
  • crates/amaru/src/stages/consensus/forward_chain/README.md
✅ Files skipped from review due to trivial changes (1)
  • crates/amaru-consensus/src/peer.rs
🚧 Files skipped from review as they are similar to previous changes (15)
  • crates/amaru/src/stages/mod.rs
  • .github/workflows/CI.yml
  • crates/amaru/src/point.rs
  • crates/amaru/src/stages/consensus/store_header.rs
  • crates/amaru/src/stages/consensus/select_chain.rs
  • crates/amaru/src/stages/pull.rs
  • crates/amaru/src/stages/consensus/validate_header.rs
  • crates/amaru/src/stages/consensus/fetch_block.rs
  • crates/amaru/src/stages/consensus/receive_header.rs
  • crates/amaru/src/stages/consensus/forward_chain/client_protocol.rs
  • crates/amaru-consensus/src/consensus/select_chain.rs
  • crates/amaru/src/stages/common.rs
  • crates/amaru/src/stages/consensus/forward_chain.rs
  • crates/amaru/src/stages/consensus/store_block.rs
  • crates/amaru/src/stages/ledger.rs
🧰 Additional context used
🧠 Learnings (1)
crates/amaru-consensus/src/consensus/validate_header.rs (1)
Learnt from: abailly
PR: pragma-org/amaru#195
File: simulation/amaru-sim/src/simulator/mod.rs:167-182
Timestamp: 2025-04-22T09:18:19.893Z
Learning: In the Amaru consensus pipeline refactor, ValidateHeader::handle_roll_forward returns a Result<PullEvent, ConsensusError>, not ValidateHeaderEvent as might be expected from the older code structure.
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Snapshots (preprod, 1, 10.1.4)
  • GitHub Check: Build on ubuntu-24.04 with target aarch64-unknown-linux-musl
  • GitHub Check: Build on windows-latest with target x86_64-pc-windows-msvc
  • GitHub Check: Build on ubuntu-latest with target riscv32im-risc0-zkvm-elf
  • GitHub Check: Coverage
  • GitHub Check: Build on macos-latest with target aarch64-apple-darwin

@abailly abailly merged commit 1aea292 into main Jun 17, 2025
12 of 13 checks passed
@abailly abailly deleted the abailly/connect-2-nodes branch June 17, 2025 12:19
abailly added a commit that referenced this pull request Jun 17, 2025
This reverts commit 1aea292, reversing
changes made to 60393cb.

Signed-off-by: Arnaud Bailly <arnaud@pankzsoft.com>
@coderabbitai coderabbitai Bot mentioned this pull request Dec 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants