Skip to content

phase1: withdrawal redeemers rejected as UnneededRedeemer #750

Description

@mduthey

phase1: withdrawal redeemers rejected as UnneededRedeemer (Babbage + Conway)

Summary

pallas-validate's phase-1 validator builds the set of expected redeemer pointers by iterating only tx_body.inputs (for RedeemerTag::Spend) and tx_body.mint (for RedeemerTag::Mint). It never iterates tx_body.withdrawals, certificates, voting_procedures, or proposal_procedures, so no Reward/Cert/Vote/Propose pointers are ever emitted.

As a consequence, any structurally valid tx that includes a withdrawal-purpose redeemer (the "withdraw-zero trick" used by Pyth-style pull oracles, Indigo, etc.) is rejected with:

an unnecessary redeemer is present

…which surfaces over JSON-RPC as code -32004 (e.g. via dolos).

The same bug exists in both the Babbage and Conway phase-1 modules.

Affected versions

  • pallas-validate 1.0.0-alpha.4 — Babbage path
  • pallas-validate 1.0.0-alpha.5 — Conway path

Reproduced downstream via dolos 1.0.3, which links both. Cardano node (preview) accepts the same tx, confirming the bug is in pallas-validate, not in tx construction.

Where the bug lives

  • crates/pallas-validate/src/phase1/babbage.rs:947mk_plutus_script_redeemer_pointers
  • crates/pallas-validate/src/phase1/babbage.rs:1006redeemer_pointers_coincide
  • crates/pallas-validate/src/phase1/conway.rs:1150 — same defect, duplicated for Conway

mk_plutus_script_redeemer_pointers returns the list of expected pointers; redeemer_pointers_coincide compares the tx's actual redeemers against that list and raises UnneededRedeemer for anything missing. Because the expected list is incomplete, every withdrawal redeemer is flagged.

Steps

  1. Compile any always-true Plutus V3 validator and publish it as a reference UTxO at script_ref. Use its script hash as script_hash.
  2. Build and submit withdraw_zero(0) against a dolos devnet (which links pallas-validate).
  3. Submit the same tx against a real cardano-node (preview).

Result

  • Real cardano-node: phase-1 passes, phase-2 runs the validator, tx is accepted.

  • dolos (pallas-validate phase-1): rejected with

    an unnecessary redeemer is present
    

    surfaced over JSON-RPC as code -32004.

The tx body is identical in both cases — only the validator differs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions