Skip to content

Spec Review: Datum Lifecycle Management#686

Draft
buddhisthead wants to merge 1 commit intomainfrom
568-datum-lifecycle
Draft

Spec Review: Datum Lifecycle Management#686
buddhisthead wants to merge 1 commit intomainfrom
568-datum-lifecycle

Conversation

@buddhisthead
Copy link
Collaborator

Specification & Implementation Plan for Review

This PR contains the specification and implementation plan for datum lifecycle management — the next phase of Plutus Phase 2 validation (#568). No code changes are included; this is a request for review of the design artifacts before implementation begins.

Artifacts for Review

Document Description
spec.md Feature specification — 3 user stories, 10 functional requirements, 6 edge cases, 6 success criteria
plan.md Implementation plan — architecture decisions, project structure, constitution compliance
research.md Research findings — 7 technical decisions with rationale and alternatives
data-model.md Data model — 8 entities, relationships, state transitions, validation rules
contracts/resolved-utxo.md API contract — public interface for the shared plutus_validation crate
quickstart.md Developer quickstart — build, test, and architecture overview

Key Design Decisions

  1. Phase 2 moves to utxo_state — it needs resolved UTxO data (datums, values) which only utxo_state has access to
  2. Shared evaluation crate — extract the existing Phase 2 evaluator into acropolis_module_plutus_validation for reuse
  3. TxUTxODeltas extended — adds raw_tx: Option<Vec<u8>> so utxo_state can re-parse script witnesses and redeemers
  4. Version-specific ScriptContext — V1/V2 use 3-argument application; V3 uses single-argument model (CIP-0069)
  5. Two-path datum resolution — inline datums used directly; hash datums looked up in witness set with hash validation

Scope

This builds on the Phase 2 evaluator work merged in PR #669. It adds:

  • Datum resolution from UTxO store (inline + hash-based)
  • ScriptContext/TxInfo construction for PlutusV1, V2, and V3
  • Integration of Phase 2 validation into the utxo_state block validation loop
  • Alonzo-era UTxOW validation rules (currently stubs)

Reviewers — What to Look For

  • Are the architecture decisions sound? (especially AD-1: moving Phase 2 to utxo_state)
  • Is the ScriptContext V1/V2/V3 data model complete?
  • Are there missing edge cases or validation rules?
  • Does the API contract in contracts/resolved-utxo.md have the right surface area?

@buddhisthead buddhisthead changed the title Spec Review: Datum Lifecycle Management (#568) Spec Review: Datum Lifecycle Management Feb 12, 2026
@buddhisthead
Copy link
Collaborator Author

@golddydev Based on our conversation, I looked more into script evaluation and I think I missed an important point of updating the datums. The existing implementation just passes None as a context and thus many scripts will fail that require inputs. This PR is just the specification phase of adding datum input/output. Can you please review the main files "requirements.md" and "plan.md" to see if you agree with the problem being presented, it's proposed solution, and the plan? Thank you.


1. **Given** a transaction spending a UTxO whose output contains an inline datum, **When** Phase 2 validation runs the spending validator, **Then** the validator receives the inline datum bytes as its first argument and evaluates correctly.
2. **Given** a transaction spending a UTxO whose output references a datum hash, and the transaction witness set contains the corresponding datum bytes, **When** Phase 2 validation runs the spending validator, **Then** the validator receives the witness-set datum bytes as its first argument and evaluates correctly.
3. **Given** a transaction spending a UTxO whose output references a datum hash, but the transaction witness set does NOT contain the corresponding datum, **When** Phase 2 validation attempts datum resolution, **Then** validation fails with a clear error identifying the missing datum hash.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is actually Phase1 Validation. MissingRequiredDatums.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thank you. Do we already do that validation or is that something that is needed (new)?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh, currently, we don't have Redeemer/Datum Phase1 Validation merged.
That is on draft PR still.
#713

1. **Given** a transaction spending a UTxO whose output contains an inline datum, **When** Phase 2 validation runs the spending validator, **Then** the validator receives the inline datum bytes as its first argument and evaluates correctly.
2. **Given** a transaction spending a UTxO whose output references a datum hash, and the transaction witness set contains the corresponding datum bytes, **When** Phase 2 validation runs the spending validator, **Then** the validator receives the witness-set datum bytes as its first argument and evaluates correctly.
3. **Given** a transaction spending a UTxO whose output references a datum hash, but the transaction witness set does NOT contain the corresponding datum, **When** Phase 2 validation attempts datum resolution, **Then** validation fails with a clear error identifying the missing datum hash.
4. **Given** a transaction spending a UTxO that has no datum (non-script address or Plutus V3 with CIP-0069 no-datum spending), **When** Phase 2 validation runs, **Then** the validator is invoked without a datum argument as appropriate for its Plutus version.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am sure, but this is Phase1 Validation. UnspendableUTxONoDatumHash
Which checks that when spending UTxO which is locked at Plutus Script, there must be datum, unless the script is not Plutus V3.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do we already run the UnspendableUTxONoDatumHash validation?

Copy link
Collaborator

Choose a reason for hiding this comment

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

That is on draft PR still.
#713

Comment on lines +75 to +80
- What happens when a spending validator expects a datum but the consumed UTxO has no datum? The system MUST report a datum resolution error specific to the missing datum, distinguishing between "UTxO has no datum" and "datum hash not found in witness set."
- What happens when the datum bytes in the witness set do not hash to the expected datum hash? The system MUST reject the transaction with a datum hash mismatch error.
- How are datums handled for Plutus V3 scripts using CIP-0069 (spending scripts without datum arguments)? The system MUST allow spending without a datum for V3 scripts that opt into this pattern.
- What happens when a transaction has both regular inputs and reference inputs with datums? Regular inputs consume the UTxO and its datum, while reference inputs only read the UTxO — both must have their datums resolved for ScriptContext but only regular inputs are consumed.
- How does the system handle the transition between datum-hash outputs (Alonzo/Babbage) and inline-datum outputs (Babbage+)? Both formats MUST be supported simultaneously since the chain contains historical outputs of both types.
- What happens when multiple scripts in the same transaction need datum resolution? All datums MUST be resolved before any script evaluation begins, and per L008, scripts within the same transaction can run in parallel once inputs are resolved.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are these edge cases Phase1 Validation?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I am not sure myself. Where would we find the answer to your question?

Copy link
Collaborator

Choose a reason for hiding this comment

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

**Rationale**: Phase 2 needs Plutus script bytecodes from the transaction witness set. Currently `TxUTxODeltas` only carries `script_witnesses: Vec<(ScriptHash, ScriptLang)>` without the actual script bytes. Carrying raw tx bytes allows re-extraction of script bytes, witness-set datums, and redeemers in `utxo_state` without duplicating every field. The overhead is ~1-2KB per tx per block.

**Alternatives considered**:
- **Add separate `plutus_scripts: Vec<(ScriptHash, Vec<u8>)>` field**: More targeted but requires duplicating extraction logic and doesn't help with ScriptContext construction which needs many transaction fields.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Or is it better to extract Script raw bytes from tx_unpacker module and send it to utxo_state

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good question. What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it is good to unpack script bytes from tx_unpacker and pass this down to utxo_state.
Such that we don't need to re-decoded raw tx bytes in utxo_state and don't need to send full tx bytes down to utxo_state.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That sounds like a good strategy to me. Thank you.

Comment on lines +32 to +38
pub struct ResolvedInput {
pub utxo_ref: UTxOIdentifier,
pub address: Vec<u8>,
pub value: UTxOValue,
pub datum: Option<ResolvedDatum>,
pub reference_script: Option<ResolvedScript>,
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need this new ResolvedInput type?
Can we just use UTxOValue?

UTxOValue doesn't have reference script bytes though. (But I think we need to add reference script bytes either this type or new type which extends this.)

@buddhisthead
Copy link
Collaborator Author

@golddydev I'm assigning this to you so that you can make progress if you have time, while I'm out of the office. I can finish this when I return if you do not have time, but please go ahead if you run out of other work. Thank you!

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.

2 participants