Skip to content

fix: get the tx_id from the transaction body#823

Open
etorreborre wants to merge 3 commits into
mainfrom
etorreborre/fix/transaction-id
Open

fix: get the tx_id from the transaction body#823
etorreborre wants to merge 3 commits into
mainfrom
etorreborre/fix/transaction-id

Conversation

@etorreborre
Copy link
Copy Markdown
Contributor

@etorreborre etorreborre commented May 14, 2026

The main fix of this PR is the retrieval of the transaction id used in the mempool and tx submission protocol from the transaction body and not from the hashing of the full transaction CBOR.

Then, in order to make the access to the transaction id more consistent and encapsulated, I defined a tx_id() method on Transaction.

Notes:

Summary by CodeRabbit

  • Refactor
    • Unified transaction identifier handling by introducing a consolidated TransactionId type across consensus, mempool, and protocol layers.
    • Standardized transaction ID derivation through a new trait-based mechanism.
    • Removed unused dummy mempool implementation.

@etorreborre etorreborre self-assigned this May 14, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 14, 2026

Walkthrough

This PR centralizes transaction identifiers in the kernel by introducing TransactionId and a HasTransactionId trait, adds Transaction::tx_id(), and migrates mempool, protocol, consensus, ledger, and tests from the old local TxId/TxId::from(&tx) flow to deriving IDs via tx.tx_id(). It also removes the removed dummy mempool strategy and updates related types/signatures.

Changes

Kernel: TransactionId + HasTransactionId

Layer / File(s) Summary
TransactionId type + CBOR/display
crates/amaru-kernel/src/cardano/transaction_id.rs, crates/amaru-kernel/src/cardano/hash.rs
Adds TransactionId newtype wrapping TransactionIdHash, CBOR Encode/Decode, and Display. Renames prior alias to TransactionIdHash.
Transaction accessor
crates/amaru-kernel/src/cardano/transaction.rs
Adds pub fn tx_id(&self) -> TransactionId returning id from the transaction body.
Traits re-export & HasTransactionId
crates/amaru-kernel/src/traits/has_transaction_id.rs, crates/amaru-kernel/src/traits.rs, crates/amaru-kernel/src/lib.rs
Introduces HasTransactionId trait, implements it for Transaction, and re-exports TransactionId at crate root.

Mempool traits & values migration

Layer / File(s) Summary
Trait surface to TransactionId
crates/amaru-ouroboros-traits/src/mempool/mempool_traits.rs, crates/amaru-ouroboros-traits/src/mempool/values.rs
Removes local TxId wrapper; TxInsertResult, get_tx, contains, tx_ids_since, get_txs_for_ids and related APIs now use TransactionId directly. CBOR/Encode impls for the removed wrapper deleted.
Mempool message type update
crates/amaru-ouroboros/src/mempool.rs
MempoolInsertError.tx_id field and imports updated to use TransactionId.

Mempool implementations & strategies

Layer / File(s) Summary
In-memory mempool: API, storage, and bounds
crates/amaru-mempool/src/strategies/in_memory_mempool.rs
Indexes and MempoolEntry now store TransactionId; insert and retrieval methods derive IDs via tx.tx_id(); generic bounds tightened to Tx: HasTransactionId. Tests updated with HasTransactionId impl for test Tx.
Remove dummy mempool
crates/amaru-mempool/src/strategies/dummy.rs, crates/amaru-mempool/src/strategies/mod.rs
Deletes dummy.rs and its re-export; mod.rs now only exposes in_memory_mempool.

Protocols, tx-submission, and effects

Layer / File(s) Summary
Protocol IDs and messages
crates/amaru-protocols/src/tx_submission/messages.rs, crates/amaru-protocols/src/tx_submission/outcome.rs
Message, ProtocolError, and display/prop-test helpers now use TransactionId (e.g., RequestTxs, ReplyTxIds).
Initiator & Responder
crates/amaru-protocols/src/tx_submission/initiator.rs, crates/amaru-protocols/src/tx_submission/responder.rs
Sliding-window state, action/result enums, internal queues/sets, duplicate-detection, request/response plumbing, and tests switched to TransactionId and to deriving ids via tx.tx_id(). Mock/test mempool types adjusted accordingly.
Async/MemoryPool effects
crates/amaru-protocols/src/mempool_effects.rs
AsyncMempool and MemoryPool methods and external effect structs (GetTx, ContainsTx, TxIdsSince, GetTxsForIds) now accept/return TransactionId. ConstantMempool test impl derives ids via Transaction::tx_id().
Test helpers & configurations
crates/amaru-protocols/src/tests/configuration.rs, crates/amaru-protocols/src/tx_submission/tests/assertions.rs
Test helpers now return/use TransactionId derived with tx.tx_id().

Consensus, mempool stage, and other consumers

Layer / File(s) Summary
Consensus mempool stage
crates/amaru-consensus/src/stages/mempool/stage.rs, crates/amaru-consensus/src/stages/mempool/tests.rs
Single and batch insert paths use tx.tx_id() for building error payloads; validate_and_insert maps ledger validation failures into TxInsertResult::rejected with TxRejectReason::Invalid(tx.tx_id(), ...). Tests updated to expect tx.tx_id().
Submit API and repo tests
crates/amaru/src/submit_api.rs, crates/amaru/src/tests/configuration.rs
Test modules and helper get_tx_ids() switched to derive TransactionId via tx.tx_id(); FailOnceMempool test mempool adjusted to return TxInsertResult::accepted(tx.tx_id(), ...).
Ledger & Plutus adjustments
crates/amaru-ledger/src/rules/*, crates/amaru-plutus/src/script_context/mod.rs
Where callers required raw hash identifiers, code now uses TransactionIdHash for block/transaction validation and TxInfo storage; function signatures updated accordingly.

Sequence Diagram

sequenceDiagram
    autonumber
    participant Client as Client
    participant Tx as Transaction
    participant Kernel as Kernel (TransactionId)
    participant Mempool as Mempool
    participant Protocol as TxSubmission
    participant Ledger as Ledger

    Client->>Tx: create tx
    Tx->>Kernel: tx.tx_id() (compute TransactionId) 
    Note right of Kernel: TransactionId is opaque wrapper\naround TransactionIdHash (first 6 bytes shown in display)
    Tx->>Mempool: submit tx (+TransactionId via tx.tx_id())
    Mempool->>Protocol: advertise/request using TransactionId
    Protocol->>Ledger: validation may return Invalid(transaction_hash)
    Ledger-->>Mempool: validation result (mapped to TxInsertResult::rejected with tx.tx_id())
    Mempool-->>Client: insertion result (Accepted/Rejected with TransactionId)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • pragma-org/amaru#745: Overlaps mempool stage insert/validation wiring and identifier propagation patterns.
  • pragma-org/amaru#485: Related to ScriptContext changes affecting TxInfo and transaction-id handling.

Suggested reviewers

  • rkuhn
  • KtorZ
  • jeluard

"A tiny ID rebellion, all neat and centralized—
Transactions get named at source, no more duct-tape IDs.
Kernel holds the key, mempool sings along,
Tests updated, dummy gone — commit feels like a victory song." 🎮✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely summarizes the main change: retrieving transaction IDs from the transaction body rather than hashing full CBOR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch etorreborre/fix/transaction-id

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
crates/amaru-kernel/src/cardano/transaction.rs (1)

50-51: ⚡ Quick win

Add #[repr(transparent)] on TxId newtype.

Small but useful ABI/layout guarantee for this domain newtype, mate.

Proposed tweak
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
+#[repr(transparent)]
 pub struct TxId(TransactionId);

As per coding guidelines, “Implement newtypes with: #[derive(...)] #[repr(transparent)] pub struct Name(Type); with private field...”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/amaru-kernel/src/cardano/transaction.rs` around lines 50 - 51, Add the
#[repr(transparent)] attribute to the TxId newtype declaration to provide a
stable ABI/layout guarantee for this domain newtype; update the declaration that
currently reads "pub struct TxId(TransactionId);" (the TxId newtype around
TransactionId) by prepending #[repr(transparent)] while keeping the existing
derives and the inner field private.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/amaru-kernel/src/cardano/transaction.rs`:
- Around line 50-51: Add the #[repr(transparent)] attribute to the TxId newtype
declaration to provide a stable ABI/layout guarantee for this domain newtype;
update the declaration that currently reads "pub struct TxId(TransactionId);"
(the TxId newtype around TransactionId) by prepending #[repr(transparent)] while
keeping the existing derives and the inner field private.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: de148785-9279-41dc-9ebe-4174738bffc1

📥 Commits

Reviewing files that changed from the base of the PR and between b97d5cd and dd5476a.

📒 Files selected for processing (19)
  • crates/amaru-consensus/src/stages/mempool/stage.rs
  • crates/amaru-consensus/src/stages/mempool/tests.rs
  • crates/amaru-kernel/src/cardano/transaction.rs
  • crates/amaru-kernel/src/lib.rs
  • crates/amaru-mempool/src/strategies/dummy.rs
  • crates/amaru-mempool/src/strategies/in_memory_mempool.rs
  • crates/amaru-mempool/src/strategies/mod.rs
  • crates/amaru-ouroboros-traits/src/mempool/mempool_traits.rs
  • crates/amaru-ouroboros-traits/src/mempool/values.rs
  • crates/amaru-ouroboros/src/mempool.rs
  • crates/amaru-protocols/src/mempool_effects.rs
  • crates/amaru-protocols/src/tests/configuration.rs
  • crates/amaru-protocols/src/tx_submission/initiator.rs
  • crates/amaru-protocols/src/tx_submission/messages.rs
  • crates/amaru-protocols/src/tx_submission/outcome.rs
  • crates/amaru-protocols/src/tx_submission/responder.rs
  • crates/amaru-protocols/src/tx_submission/tests/assertions.rs
  • crates/amaru/src/submit_api.rs
  • crates/amaru/src/tests/configuration.rs
💤 Files with no reviewable changes (2)
  • crates/amaru-mempool/src/strategies/mod.rs
  • crates/amaru-mempool/src/strategies/dummy.rs

@etorreborre etorreborre force-pushed the etorreborre/fix/transaction-id branch from dd5476a to a7226ed Compare May 14, 2026 08:18
@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

❌ Patch coverage is 80.70175% with 22 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/amaru-protocols/src/mempool_effects.rs 64.28% 10 Missing ⚠️
...tes/amaru-protocols/src/tx_submission/responder.rs 65.21% 8 Missing ⚠️
crates/amaru/src/submit_api.rs 57.14% 3 Missing ⚠️
...ates/amaru-protocols/src/tx_submission/messages.rs 0.00% 1 Missing ⚠️
Files with missing lines Coverage Δ
crates/amaru-consensus/src/stages/mempool/stage.rs 75.75% <100.00%> (ø)
crates/amaru-kernel/src/cardano/hash.rs 100.00% <ø> (ø)
crates/amaru-kernel/src/cardano/transaction.rs 75.00% <100.00%> (+75.00%) ⬆️
crates/amaru-kernel/src/cardano/transaction_id.rs 100.00% <100.00%> (ø)
...ates/amaru-kernel/src/traits/has_transaction_id.rs 100.00% <100.00%> (ø)
crates/amaru-ledger/src/rules/block.rs 55.55% <ø> (ø)
...edger/src/rules/transaction/phase_one/proposals.rs 97.19% <100.00%> (ø)
...er/src/rules/transaction/phase_one/vkey_witness.rs 100.00% <100.00%> (ø)
.../amaru-mempool/src/strategies/in_memory_mempool.rs 75.60% <100.00%> (+0.60%) ⬆️
...aru-ouroboros-traits/src/mempool/mempool_traits.rs 100.00% <100.00%> (ø)
... and 8 more

... and 5 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.

@etorreborre etorreborre requested review from KtorZ and rkuhn May 14, 2026 09:31
/// It encapsulates the TransactionId to be completely opaque to the structure of the
/// transaction identifier.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
pub struct TxId(TransactionId);
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.

Please make a new kernel module 🙏, one module per type.

Also, let's try to avoid acronyms and short names as much as we can; 👉 TransactionId

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There's already a TransactionId used as a type alias for the hash. Should I remove that type alias then?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@KtorZ ☝️

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I pushed a new commit doing that renaming and then renaming the original TransactionId to TransactionIdHash. However it's not consistent with PoolId which is also a hash. Are you ok to rename it to PoolIdHash or do you have another naming scheme that you'd prefer?

Copy link
Copy Markdown
Contributor

@KtorZ KtorZ May 14, 2026

Choose a reason for hiding this comment

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

TransactionIdHash

😬 ... transaction id is already a hash. So; yeah, we should NOT use a type-alias if we think this deserves to be a proper type with its own set of methods.

It doesn't make sense to me to have TransactionId and TransactionIdHash (same for pool).

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.

Looking at the code here though; I don't really see what's specific to TransactionId though; everything could be generally handled by the Hash (though we don't yet control this type, so can't really extend it).


impl Display for TxId {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(self.0.as_slice()))
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.

Might want to limit to the first 10-12 chars.

Comment thread crates/amaru-kernel/src/cardano/transaction.rs Outdated
Copy link
Copy Markdown
Contributor

@rkuhn rkuhn left a comment

Choose a reason for hiding this comment

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

It looks like shuffling around rather similarly named types in some places, but I fail to see an actual change of computational rules. I’m a bit confused by the intended difference between TxId and TransactionId, which sounds like they should be the same thing to begin with.

@etorreborre
Copy link
Copy Markdown
Contributor Author

@rkuhn sorry I should have pointed it. The fix is here.

@etorreborre etorreborre force-pushed the etorreborre/fix/transaction-id branch 2 times, most recently from 8759ca9 to 3ed400f Compare May 14, 2026 13:32
and TransactionId to TransactionIdHash

Signed-off-by: Eric Torreborre <[email protected]>
@etorreborre etorreborre force-pushed the etorreborre/fix/transaction-id branch from 3ed400f to 31fa2b7 Compare May 14, 2026 14:00
@etorreborre etorreborre force-pushed the etorreborre/fix/transaction-id branch from 31fa2b7 to e5b1e11 Compare May 14, 2026 14:18
Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/amaru-kernel/src/cardano/transaction_id.rs`:
- Around line 27-28: The TransactionId newtype is missing the
#[repr(transparent)] attribute; add #[repr(transparent)] immediately above the
TransactionId declaration so the struct (pub struct
TransactionId(TransactionIdHash);) is represented transparently over its single
private field, keeping the existing derives intact (Debug, Copy, Clone,
PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize) to
comply with the repo newtype guideline.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b50769b8-be96-416b-89dd-f9237c1ae535

📥 Commits

Reviewing files that changed from the base of the PR and between dd5476a and e5b1e11.

📒 Files selected for processing (28)
  • crates/amaru-consensus/src/stages/mempool/stage.rs
  • crates/amaru-consensus/src/stages/mempool/tests.rs
  • crates/amaru-kernel/src/cardano.rs
  • crates/amaru-kernel/src/cardano/hash.rs
  • crates/amaru-kernel/src/cardano/transaction.rs
  • crates/amaru-kernel/src/cardano/transaction_id.rs
  • crates/amaru-kernel/src/lib.rs
  • crates/amaru-kernel/src/traits.rs
  • crates/amaru-kernel/src/traits/has_transaction_id.rs
  • crates/amaru-ledger/src/rules/block.rs
  • crates/amaru-ledger/src/rules/transaction/phase_one/proposals.rs
  • crates/amaru-ledger/src/rules/transaction/phase_one/vkey_witness.rs
  • crates/amaru-mempool/src/strategies/dummy.rs
  • crates/amaru-mempool/src/strategies/in_memory_mempool.rs
  • crates/amaru-mempool/src/strategies/mod.rs
  • crates/amaru-ouroboros-traits/src/mempool/mempool_traits.rs
  • crates/amaru-ouroboros-traits/src/mempool/values.rs
  • crates/amaru-ouroboros/src/mempool.rs
  • crates/amaru-plutus/src/script_context/mod.rs
  • crates/amaru-protocols/src/mempool_effects.rs
  • crates/amaru-protocols/src/tests/configuration.rs
  • crates/amaru-protocols/src/tx_submission/initiator.rs
  • crates/amaru-protocols/src/tx_submission/messages.rs
  • crates/amaru-protocols/src/tx_submission/outcome.rs
  • crates/amaru-protocols/src/tx_submission/responder.rs
  • crates/amaru-protocols/src/tx_submission/tests/assertions.rs
  • crates/amaru/src/submit_api.rs
  • crates/amaru/src/tests/configuration.rs
💤 Files with no reviewable changes (2)
  • crates/amaru-mempool/src/strategies/mod.rs
  • crates/amaru-mempool/src/strategies/dummy.rs
✅ Files skipped from review due to trivial changes (2)
  • crates/amaru-kernel/src/traits/has_transaction_id.rs
  • crates/amaru-protocols/src/tx_submission/tests/assertions.rs
🚧 Files skipped from review as they are similar to previous changes (4)
  • crates/amaru-protocols/src/tests/configuration.rs
  • crates/amaru/src/submit_api.rs
  • crates/amaru-consensus/src/stages/mempool/tests.rs
  • crates/amaru-consensus/src/stages/mempool/stage.rs

Comment on lines +27 to +28
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
pub struct TransactionId(TransactionIdHash);
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.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add #[repr(transparent)] on TransactionId for newtype compliance.

Quick win, mate: Line 28 defines a domain newtype, but it misses #[repr(transparent)], which this repo asks for on newtypes.

Proposed patch
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
+#[repr(transparent)]
 pub struct TransactionId(TransactionIdHash);

As per coding guidelines: "Implement newtypes with: #[derive(...)] #[repr(transparent)] pub struct Name(Type); with private field, and derive Debug, Clone, Copy (if applicable), PartialEq/Eq/Ord, Display, Serialize/Deserialize, CBOR Encode/Decode".

📝 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
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
pub struct TransactionId(TransactionIdHash);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
#[repr(transparent)]
pub struct TransactionId(TransactionIdHash);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/amaru-kernel/src/cardano/transaction_id.rs` around lines 27 - 28, The
TransactionId newtype is missing the #[repr(transparent)] attribute; add
#[repr(transparent)] immediately above the TransactionId declaration so the
struct (pub struct TransactionId(TransactionIdHash);) is represented
transparently over its single private field, keeping the existing derives intact
(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize,
serde::Deserialize) to comply with the repo newtype guideline.

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