@@ -60,7 +60,7 @@ can include required top-level guards (the `txRequiredTopLevelGuards`{.AgdaField
6060
6161To that end, we define two auxiliary functions that will aid in
6262specifying which record fields of a transaction body are present at
63- each ` TxLevel ` {.agdatype }:
63+ each ` TxLevel ` {.AgdaDatatype }:
6464
6565``` agda
6666InTopLevel : TxLevel → Type → Type
@@ -73,7 +73,7 @@ InSubLevel TxLevelTop _ = ⊤
7373```
7474
7575These functions discriminate on an argument of type
76- ` TxLevel ` {.agdatype } and either act as the identity function on types
76+ ` TxLevel ` {.AgdaDatatype } and either act as the identity function on types
7777or as the constant function that returns the unit type.
7878
7979<!--
@@ -291,6 +291,14 @@ could be either of them.
291291 field TxIdOf : A → TxId
292292 open HasTxId ⦃...⦄ public
293293
294+ record HasSpendInputs {a} (A : Type a) : Type a where
295+ field SpendInputsOf : A → ℙ TxIn
296+ open HasSpendInputs ⦃...⦄ public
297+
298+ record HasReferenceInputs {a} (A : Type a) : Type a where
299+ field ReferenceInputsOf : A → ℙ TxIn
300+ open HasReferenceInputs ⦃...⦄ public
301+
294302 record HasFees? {a} (A : Type a) : Type a where
295303 field FeesOf? : A → Maybe Fees
296304 open HasFees? ⦃...⦄ public
@@ -339,6 +347,18 @@ could be either of them.
339347 HasWithdrawals-Tx : HasWithdrawals (Tx txLevel)
340348 HasWithdrawals-Tx .WithdrawalsOf = WithdrawalsOf ∘ TxBodyOf
341349
350+ HasSpendInputs-TxBody : HasSpendInputs (TxBody txLevel)
351+ HasSpendInputs-TxBody .SpendInputsOf = TxBody.txIns
352+
353+ HasSpendInputs-Tx : HasSpendInputs (Tx txLevel)
354+ HasSpendInputs-Tx .SpendInputsOf = SpendInputsOf ∘ TxBodyOf
355+
356+ HasReferenceInputs-TxBody : HasReferenceInputs (TxBody txLevel)
357+ HasReferenceInputs-TxBody .ReferenceInputsOf = TxBody.refInputs
358+
359+ HasReferenceInputs-Tx : HasReferenceInputs (Tx txLevel)
360+ HasReferenceInputs-Tx .ReferenceInputsOf = ReferenceInputsOf ∘ TxBodyOf
361+
342362 HasValue-TxBody : HasValue (TxBody txLevel)
343363 HasValue-TxBody .ValueOf = TxBody.mint
344364
@@ -403,23 +423,36 @@ This section collects some unimportant but useful helper and accessor functions.
403423
404424 txinsScript : ℙ TxIn → UTxO → ℙ TxIn
405425 txinsScript txins utxo = txins ∩ dom (proj₁ (scriptOuts utxo))
426+ ```
427+
428+ In the Dijkstra era, * spending* inputs must exist in the initial UTxO snapshot, while
429+ * reference* inputs may see earlier outputs, so we need two UTxO views:
406430
407- refScripts : Tx txLevel → UTxO → List Script
408- refScripts tx utxo =
409- mapMaybe (proj₂ ∘ proj₂ ∘ proj₂) $ setToList (range (utxo ∣ (txIns ∪ refInputs)))
410- where open Tx; open TxBody (TxBodyOf tx)
431+ + ` utxoSpend₀ ` {.AgdaBound}, the initial snapshot, used for ` txIns ` {.AgdaField},
432+ + ` utxoRefView ` {.AgdaBound}, the evolving view, used for ` refInputs ` {.AgdaField}.
411433
412- txscripts : Tx txLevel → UTxO → ℙ Script
413- txscripts tx utxo = scripts (tx .txWitnesses) ∪ fromList (refScripts tx utxo)
434+ Thus functions like ` refScripts ` {.AgdaFunction}, ` txscripts ` {.AgdaFunction},
435+ and ` lookupScriptHash ` {.AgdaFunction} (defined below) will take * two* UTxO arguments.
436+
437+ ``` agda
438+ refScripts : Tx txLevel → UTxO → UTxO → List Script
439+ refScripts tx utxoSpend₀ utxoRefView =
440+ mapMaybe (proj₂ ∘ proj₂ ∘ proj₂) ( setToList (range (utxoSpend₀ ∣ txIns))
441+ ++ setToList (range (utxoRefView ∣ refInputs))
442+ )
443+ where open Tx tx; open TxBody (TxBodyOf tx)
444+
445+ txscripts : Tx txLevel → UTxO → UTxO → ℙ Script
446+ txscripts tx utxoSpend₀ utxoRefView =
447+ scripts (tx .txWitnesses) ∪ fromList (refScripts tx utxoSpend₀ utxoRefView)
414448 where open Tx; open TxWitnesses
415449
416- lookupScriptHash : ScriptHash → Tx txLevel → UTxO → Maybe Script
417- lookupScriptHash sh tx utxo =
418- if sh ∈ mapˢ proj₁ (m ˢ) then
419- just (lookupᵐ m sh)
420- else
421- nothing
422- where m = setToMap (mapˢ < hash , id > (txscripts tx utxo))
450+ lookupScriptHash : ScriptHash → Tx txLevel → UTxO → UTxO → Maybe Script
451+ lookupScriptHash sh tx utxoSpend₀ utxoRefView =
452+ if sh ∈ mapˢ proj₁ (m ˢ) then just (lookupᵐ m sh) else nothing
453+ where m = setToMap (mapˢ < hash , id > (txscripts tx utxoSpend₀ utxoRefView))
454+
455+ -- TODO: implement the actual evolving `utxoRefView` (issue #1006)
423456
424457 getSubTxScripts : SubLevelTx → ℙ (TxId × ScriptHash)
425458 getSubTxScripts subtx = mapˢ (λ hash → (TxIdOf subtx , hash)) (ScriptHashes subtx)
@@ -520,6 +553,14 @@ The Dijkstra era introduces *nested transactions* (a single top-level transactio
520553that contains a list of sub-transactions) and * guards* (CIP-0112 / CIP-0118). As a
521554result, several checks that were "per-transaction" in Conway become * batch-aware* .
522555
556+ ** Design Note** (CIP-0118: spending inputs vs reference inputs).
557+ For Dijkstra batches, we distinguish * spending inputs* from * reference inputs* .
558+ All spending inputs across the whole batch must exist in the initial UTxO snapshot
559+ (mempool safety). Reference inputs may additionally point to outputs of ** preceding
560+ subtransactions in the batch order** . Therefore reference-script/datum lookup is
561+ performed against an * evolving, tentative UTxO view* (prefix-applied), used only for
562+ lookup/validation, while * ledger state is committed only if the full batch succeeds* .
563+
523564### Key points
524565
5255661 . ** No further nesting**
@@ -537,17 +578,17 @@ result, several checks that were "per-transaction" in Conway become *batch-aware
537578
5385793 . ** Batch-wide phase-2 evaluation**
539580
540- Phase-2 (Plutus) validation is performed ** once**
541- for the whole batch (mempool safety), even though script inputs/contexts are
542- constructed from both sub- and top-level components.
581+ Phase-2 (Plutus) validation is performed * once* for the whole batch (mempool
582+ safety), even though script inputs/contexts are constructed from both sub- and
583+ top-level components.
543584
5445854 . ** Guards are credentials**
545586
546587 A transaction body may specify * guards* as a set of * credentials* (key or
547588 script). This is distinct from the legacy "required signer" key hashes used for
548589 phase-1 key-witness checking and native/timelock scripts.
549590
550- 5 . ** Required top-level guards are requests (list-like) **
591+ 5 . ** Required top-level guards are requests**
551592
552593 Sub-transaction bodies may include a list of "required top-level guard" requests
553594 (credential plus optional datum). Ledger phase-1 checks must ensure that the
@@ -581,28 +622,6 @@ result, several checks that were "per-transaction" in Conway become *batch-aware
581622 referenced are defined by the UTxO rules.)
582623
583624
584- <!--
585- The following text previously appeared in item 4.
586-
587- > All scripts are shared across all transactions within a single batch, so
588- > attaching one script to either a sub- or a top-level-transaction allows other
589- > transactions to run it without also including it in its own scripts. This
590- > includes reference scripts that are sourced from the outputs to which reference
591- > inputs point in the UTxO. These referenced UTxO entries could be outputs of
592- > preceding transactions in the batch.
593-
594- > Datums (from reference inputs and from other transactions) are also shared in
595- > this way. As before, only the datums fixed by the executing transaction are
596- > included in the `TxInfo`{.AgdaRecord} constructed for its scripts, however, now
597- > they don't necessarily have to be attached to that transaction.
598-
599- I've removed these two paragraphs for now because I'm not sure they're accurate.
600- I've replaced them with an explanation that removes the contradiction between "ref
601- inputs may refer to earlier tx outputs in the batch" vs "all inputs must exist before
602- applying any tx in the batch," and punts the exact constraint to the UTxO rules
603- (where I think it belongs).
604- -->
605-
606625[ ^ 1 ] : See CIP 0118; once finalized and merged, CIP 0118 will appear in the
607626 main branch of [ the CIP repository] [ CIPs ] ; until then, it can be found
608627 at < https://github.com/polinavino/CIPs/tree/polina/CIP0118/CIP-0118 > .
0 commit comments