Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 35 additions & 13 deletions src/Ledger/Dijkstra/Specification/Ledger.lagda.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
source_branch: master
source_path: src/Ledger/Dijkstra/Specification/Ledger.lagda
source_path: src/Ledger/Dijkstra/Specification/Ledger.lagda.md
---

# Ledger {#sec:ledger}
Expand Down Expand Up @@ -46,7 +46,10 @@ record SubLedgerEnv : Type where
pparams : PParams
enactState : EnactState
treasury : Treasury
isValid : Bool
utxo₀ : UTxO
isTopLevelValid : Bool
globalScripts : ℙ Script
globalData : DataHash ⇀ Datum

record LedgerEnv : Type where
field
Expand Down Expand Up @@ -172,6 +175,7 @@ private variable
Γ : LedgerEnv
s s' s'' : LState
utxoState utxoState' : UTxOState
utxo₀ : UTxO
govState govState' : GovState
certState certState' : CertState
stx : SubLevelTx
Expand All @@ -181,34 +185,36 @@ private variable
enactState : EnactState
treasury : Treasury
isTopLevelValid : Bool
utxo₀ : UTxO
globalScripts : ℙ Script
globalData : DataHash ⇀ Datum
```
-->

```agda
data _⊢_⇀⦇_,SUBLEDGER⦈_ : SubLedgerEnv → LState → SubLevelTx → LState → Type where
SUBLEDGER-V :
let txb = stx .txBody
let txb = stx .txBody

```
<!--
```agda
open TxBody txb
open TxBody txb
```
-->
```agda
in
∙ isTopLevelValid ≡ true
∙ ⟦ slot , pp , treasury , utxo₀ ⟧ ⊢ utxoState ⇀⦇ stx ,SUBUTXOW⦈ utxoState'
∙ ⟦ slot , pp , treasury , utxo₀ , isTopLevelValid , globalScripts , globalData ⟧ ⊢ utxoState ⇀⦇ stx ,SUBUTXOW⦈ utxoState'
∙ ⟦ epoch slot , pp , txGovVotes , txWithdrawals , allColdCreds govState enactState ⟧ ⊢ certState ⇀⦇ txCerts ,CERTS⦈ certState'
∙ ⟦ txId , epoch slot , pp , ppolicy , enactState , certState' , dom (RewardsOf certState) ⟧ ⊢ {- rmOrphanDRepVotes certState' -} govState ⇀⦇ txgov txb ,GOVS⦈ govState'
────────────────────────────────
⟦ slot , ppolicy , pp , enactState , treasury , isTopLevelValid ⟧ ⊢ ⟦ utxoState , govState , certState ⟧ ⇀⦇ stx ,SUBLEDGER⦈ ⟦ utxoState' , govState' , certState' ⟧
⟦ slot , ppolicy , pp , enactState , treasury , utxo₀ , isTopLevelValid , globalScripts , globalData ⟧ ⊢ ⟦ utxoState , govState , certState ⟧ ⇀⦇ stx ,SUBLEDGER⦈ ⟦ utxoState' , govState' , certState' ⟧

SUBLEDGER-I :
∙ isTopLevelValid ≡ false
∙ ⟦ slot , pp , treasury , utxo₀ ⟧ ⊢ utxoState ⇀⦇ stx ,SUBUTXOW⦈ utxoState
∙ ⟦ slot , pp , treasury , utxo₀ , isTopLevelValid , globalScripts , globalData ⟧ ⊢ utxoState ⇀⦇ stx ,SUBUTXOW⦈ utxoState
────────────────────────────────
⟦ slot , ppolicy , pp , enactState , treasury , isTopLevelValid ⟧ ⊢ ⟦ utxoState , govState , certState ⟧ ⇀⦇ stx ,SUBLEDGER⦈ ⟦ utxoState , govState , certState ⟧
⟦ slot , ppolicy , pp , enactState , treasury , utxo₀ , isTopLevelValid , globalScripts , globalData ⟧ ⊢ ⟦ utxoState , govState , certState ⟧ ⇀⦇ stx ,SUBLEDGER⦈ ⟦ utxoState , govState , certState ⟧

_⊢_⇀⦇_,SUBLEDGERS⦈_ : SubLedgerEnv → LState → List SubLevelTx → LState → Type
_⊢_⇀⦇_,SUBLEDGERS⦈_ = ReflexiveTransitiveClosure {sts = _⊢_⇀⦇_,SUBLEDGER⦈_}
Expand All @@ -228,6 +234,14 @@ private variable
data _⊢_⇀⦇_,LEDGER⦈_ : LedgerEnv → LState → TopLevelTx → LState → Type where
LEDGER-V :
let txb = tx .txBody

utxo₀ = UTxOOf utxoState

globalScripts : ℙ Script
globalScripts = ∅ -- TODO

globalData : DataHash ⇀ Datum
globalData = ∅ -- TODO
Comment on lines +240 to +244
Copy link
Member

Choose a reason for hiding this comment

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

It's probably a good idea to document globalScripts and globalData above where they're first introduced, since they're central to the new Dijkstra semantics. Could you add something like the following above this code block?

  • globalScripts : ℙ Script denotes the batch-wide script pool, available for resolving script hashes (witness scripts + reference scripts reachable via reference inputs, possibly including outputs created earlier in the batch).
  • globalData : DataHash ⇀ Datum denotes the batch-wide datum pool, available for resolving datum hashes (witness datums + datums reachable via reference inputs and/or other transactions in the batch).

Of course you should revise the prose if you have a better or different understanding of the roles played by these objects.

Copy link
Collaborator Author

@carlostome carlostome Jan 13, 2026

Choose a reason for hiding this comment

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

I'll leave this to the corresponding issue.

```
<!--
```agda
Expand All @@ -237,15 +251,23 @@ data _⊢_⇀⦇_,LEDGER⦈_ : LedgerEnv → LState → TopLevelTx → LState
```agda
in
∙ isValid tx ≡ true
∙ ⟦ slot , ppolicy , pp , enactState , treasury , isValid tx ⟧ ⊢ ⟦ utxoState , govState , certState ⟧ ⇀⦇ txSubTransactions ,SUBLEDGERS⦈ ⟦ utxoState' , govState' , certState' ⟧
∙ ⟦ slot , pp , treasury , utxo₀ ⟧ ⊢ utxoState' ⇀⦇ tx ,UTXOW⦈ utxoState''
∙ ⟦ slot , ppolicy , pp , enactState , treasury , utxo₀ , isValid tx , globalScripts , globalData ⟧ ⊢ ⟦ utxoState , govState , certState ⟧ ⇀⦇ txSubTransactions ,SUBLEDGERS⦈ ⟦ utxoState' , govState' , certState' ⟧
∙ ⟦ slot , pp , treasury , utxo₀ , isValid tx , globalScripts , globalData ⟧ ⊢ utxoState' ⇀⦇ tx ,UTXOW⦈ utxoState''
∙ ⟦ epoch slot , pp , txGovVotes , txWithdrawals , allColdCreds govState enactState ⟧ ⊢ certState' ⇀⦇ txCerts ,CERTS⦈ certState''
∙ ⟦ txId , epoch slot , pp , ppolicy , enactState , certState' , dom (RewardsOf certState) ⟧ ⊢ {- rmOrphanDRepVotes certState' -} govState ⇀⦇ txgov txb ,GOVS⦈ govState'
────────────────────────────────
⟦ slot , ppolicy , pp , enactState , treasury ⟧ ⊢ ⟦ utxoState , govState , certState ⟧ ⇀⦇ tx ,LEDGER⦈ ⟦ utxoState'' , govState'' , certState'' ⟧

LEDGER-I :
let txb = tx .txBody

utxo₀ = UTxOOf utxoState

globalScripts : ℙ Script
globalScripts = ∅ -- TODO

globalData : DataHash ⇀ Datum
globalData = ∅ -- TODO
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
globalData = -- TODO
globalData = DatumMapOf tx -- TODO

I think we should put something other than ∅ here for now, since otherwise the neededDataHashes ⊆ dom (Γ .globalData) fails for all nonempty neededDataHashes.

The suggestion above (DatumMapOf tx) should work if you put the following in Dijkstra/Specification/Transaction.lagda.md:

  record HasDatumMap {a} (A : Type a) : Type a where
    field DatumMapOf : A  DataHash ⇀ Datum
  open HasDatumMap ⦃...⦄ public

  instance
    HasDatumMap-TxWitnesses : HasDatumMap (TxWitnesses txLevel)
    HasDatumMap-TxWitnesses .DatumMapOf = TxWitnesses.txData

    HasDatumMap-Tx : HasDatumMap (Tx txLevel)
    HasDatumMap-Tx .DatumMapOf = DatumMapOf ∘ TxWitnessesOf

Similarly, we should probably put a non-empty placeholder in globalScripts. (Maybe something like witness scripts ∪ ref-input scripts?)

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 suggest we leave this to the corresponding issue.

```
<!--
```agda
Expand All @@ -255,8 +277,8 @@ data _⊢_⇀⦇_,LEDGER⦈_ : LedgerEnv → LState → TopLevelTx → LState
```agda
in
∙ isValid tx ≡ false
∙ ⟦ slot , ppolicy , pp , enactState , treasury , isValid tx ⟧ ⊢ ⟦ utxoState , govState , certState ⟧ ⇀⦇ txSubTransactions ,SUBLEDGERS⦈ ⟦ utxoState , govState , certState ⟧
∙ ⟦ slot , pp , treasury , utxo₀ ⟧ ⊢ utxoState ⇀⦇ tx ,UTXOW⦈ utxoState'
∙ ⟦ slot , ppolicy , pp , enactState , treasury , utxo₀ , isValid tx , globalScripts , globalData ⟧ ⊢ ⟦ utxoState , govState , certState ⟧ ⇀⦇ txSubTransactions ,SUBLEDGERS⦈ ⟦ utxoState , govState , certState ⟧
∙ ⟦ slot , pp , treasury , utxo₀ , isValid tx , globalScripts , globalData ⟧ ⊢ utxoState ⇀⦇ tx ,UTXOW⦈ utxoState'
────────────────────────────────
⟦ slot , ppolicy , pp , enactState , treasury ⟧ ⊢ ⟦ utxoState , govState , certState ⟧ ⇀⦇ tx ,LEDGER⦈ ⟦ utxoState' , govState , certState ⟧
```
Expand Down
6 changes: 3 additions & 3 deletions src/Ledger/Dijkstra/Specification/Script/Validation.lagda.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,12 @@ credsNeededMinusCollateral txb =
∪ mapPartial (λ p → if PolicyOf p then (λ {sh} → just (Propose p , ScriptObj sh)) else nothing)
(fromList (GovProposalsOf txb))

credsNeeded : (ℓ : TxLevel) → UTxO → (TxBody ℓ) → ℙ (ScriptPurpose × Credential)
credsNeeded TxLevelTop utxo txb = credsNeededMinusCollateral txb
credsNeeded : {ℓ : TxLevel} → UTxO → (TxBody ℓ) → ℙ (ScriptPurpose × Credential)
credsNeeded {TxLevelTop} utxo txb = credsNeededMinusCollateral txb
∪ mapˢ (λ (i , o) → (Spend i , payCred (proj₁ o))) ((utxo ∣ (txIns ∪ collateralInputs)) ˢ)
where open TxBody txb

credsNeeded TxLevelSub utxo txb = credsNeededMinusCollateral txb
credsNeeded {TxLevelSub} utxo txb = credsNeededMinusCollateral txb
∪ mapˢ (λ (i , o) → (Spend i , payCred (proj₁ o))) ((utxo ∣ txIns) ˢ)
where open TxBody txb

Expand Down
7 changes: 4 additions & 3 deletions src/Ledger/Dijkstra/Specification/Transaction.lagda.md
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,9 @@ on the present module; thus, we cannot bind the UTxO arguments to a particular
UTxO environment and state at this point.)

```agda
txOutToScript : TxOut → Maybe Script
txOutToScript (_ , _ , _ , s) = s

refScripts : Tx txLevel → UTxO → UTxO → List Script
refScripts tx utxo₀ utxoRef =
mapMaybe (proj₂ ∘ proj₂ ∘ proj₂)
Expand All @@ -536,9 +539,7 @@ UTxO environment and state at this point.)
txscripts tx utxo₀ utxoRef = ScriptsOf tx ∪ fromList (refScripts tx utxo₀ utxoRef)

lookupScriptHash : ScriptHash → Tx txLevel → UTxO → UTxO → Maybe Script
lookupScriptHash sh tx utxo₀ utxoRef =
if sh ∈ mapˢ proj₁ (m ˢ) then just (lookupᵐ m sh) else nothing
where m = setToMap (mapˢ < hash , id > (txscripts tx utxo₀ utxoRef))
lookupScriptHash sh tx utxoSpend₀ utxoRefView = lookupHash sh (txscripts tx utxoSpend₀ utxoRefView)

getSubTxScripts : SubLevelTx → ℙ (TxId × ScriptHash)
getSubTxScripts subtx = mapˢ (λ hash → (TxIdOf subtx , hash)) (ScriptHashes subtx)
Expand Down
10 changes: 9 additions & 1 deletion src/Ledger/Dijkstra/Specification/Utxo.lagda.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ record UTxOEnv : Type where
pparams : PParams
treasury : Treasury
utxo₀ : UTxO
slot : Slot
pparams : PParams
treasury : Treasury
utxo₀ : UTxO
isTopLevelValid : Bool
globalScripts : ℙ Script
globalData : DataHash ⇀ Datum
```

The `utxo₀`{.AgdaField} field of `UTxOEnv`{.AgdaRecord} is introduced in the Dijkstra
Expand All @@ -65,7 +72,8 @@ instance
HasUTxO-UTxOState .UTxOOf = UTxOState.utxo

unquoteDecl HasCast-UTxOEnv HasCast-UTxOState = derive-HasCast
((quote UTxOEnv , HasCast-UTxOEnv ) ∷ (quote UTxOState , HasCast-UTxOState) ∷ [])
( (quote UTxOEnv , HasCast-UTxOEnv ) ∷
[ (quote UTxOState , HasCast-UTxOState) ])
```
-->

Expand Down
118 changes: 108 additions & 10 deletions src/Ledger/Dijkstra/Specification/Utxow.lagda.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@ source_branch: master
source_path: src/Ledger/Dijkstra/Specification/Utxow.lagda.md
---

# UTxOW (Dijkstra skeleton)

This is a **minimal skeleton** of the Dijkstra-era witnessing layer.

It currently acts as a wrapper around `UTXO`, mirroring Conway's shape, but without
committing to full witnessing checks yet.
# UTxOW

<!--
```agda
Expand All @@ -24,30 +19,133 @@ module Ledger.Dijkstra.Specification.Utxow
where

open import Ledger.Dijkstra.Specification.Utxo txs abs
open import Ledger.Dijkstra.Specification.Script.Validation txs abs

private variable
ℓ : TxLevel
Γ : UTxOEnv
s s' : UTxOState
tx : TopLevelTx
stx : SubLevelTx
```
-->

```agda
languages : Tx ℓ → UTxO → ℙ Language
languages tx utxo = ∅ -- TODO

allowedLanguages : Tx ℓ → UTxO → ℙ Language
allowedLanguages tx utxo = ∅ -- TODO
```

```agda
data _⊢_⇀⦇_,SUBUTXOW⦈_ : UTxOEnv → UTxOState → SubLevelTx → UTxOState → Type where

SUBUTXOW :
let
open Tx tx
open TxBody txBody
open TxWitnesses txWitnesses
open UTxOEnv

utxo₀ = Γ .utxo₀
utxo = s .UTxOState.utxo

witsKeyHashes : ℙ KeyHash
witsKeyHashes = mapˢ hash (dom vKeySigs)

allScripts : ℙ Script
allScripts =
( scripts -- (1) scripts from witnesses
∪ mapPartial txOutToScript
( range (utxo₀ ∣ txIns) -- (2) scripts from transaction inputs
Copy link
Member

Choose a reason for hiding this comment

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

I think we should document asap the important semantic choice of using utxo₀ in both UTXOW and SUBUTXOW to compute scripts/data needed from spending inputs:

range (utxo₀ ∣ txIns)

which encodes the policy spending inputs are always resolved from the initial snapshot (utxo₀). (The "mempool-safety" / "no subtransaction spends newly created outputs" semantics.)

For now maybe just add one sentence above the relevant code blocks, something like,

"In SUBUTXOW, needed scripts/data for txIns are looked up in utxo₀ rather than the current s.utxo since subtransactions cannot spend outputs created earlier in the batch."

By the way, in my PR, I'll rename utxoSpend₀utxo₀ (pre-batch snapshot used for spending-input inspection + realizedInputs) and keep utxoRefView (ref-input lookup view, potentially evolving to include earlier-prefix outputs), and I'll add something like the following above where they're introduced:

"utxo₀{.AgdaField} is the pre-batch snapshot used for spending-input inspection and TxInfo.realizedInputs{.AgdaField}; utxoRefView{.AgdaField} is the reference-lookup view (which may include earlier-prefix outputs)."

∪ range (utxo ∣ refInputs) -- (3) scripts from reference inputs
)
∪ Γ .globalScripts -- (4) scripts from the nested transaction
)

p1Scripts : ℙ P1Script
p1Scripts = mapPartial toP1Script allScripts

p2Scripts : ℙ P2Script
p2Scripts = mapPartial toP2Script allScripts

neededScriptHashes : ℙ ScriptHash
neededScriptHashes = mapPartial (isScriptObj ∘ proj₂) (credsNeeded utxo₀ txBody)

neededVKeyHashes : ℙ KeyHash
neededVKeyHashes = mapPartial (isKeyHashObj ∘ proj₂) (credsNeeded utxo₀ txBody)

neededDataHashes : ℙ DataHash
neededDataHashes = mapPartial (λ txOut@(a , _ , d , _) → do sh ← isScriptObj (payCred a)
_ ← lookupHash sh p2Scripts
d >>= isInj₂)
(range (utxo₀ ∣ txIns))

in
∙ ∀[ (vk , σ) ∈ vKeySigs ] isSigned vk (txidBytes txId) σ
∙ ∀[ s ∈ p1Scripts ] (hash s ∈ neededScriptHashes → validP1Script witsKeyHashes txVldt s)
∙ neededVKeyHashes ⊆ witsKeyHashes
∙ neededScriptHashes ⊆ mapˢ hash allScripts
∙ neededDataHashes ⊆ dom (Γ .globalData)
∙ languages tx utxo ⊆ allowedLanguages tx utxo
∙ txADhash ≡ map hash txAuxData
∙ Γ ⊢ s ⇀⦇ stx ,SUBUTXO⦈ s'
────────────────────────────────
Γ ⊢ s ⇀⦇ stx ,SUBUTXOW⦈ s'

data _⊢_⇀⦇_,UTXOW⦈_ : UTxOEnv → UTxOState → TopLevelTx → UTxOState → Type where

UTXOW :
∙ Γ ⊢ s ⇀⦇ tx ,UTXO⦈ s'
let
open Tx tx
open TxBody txBody
open TxWitnesses txWitnesses
open UTxOEnv

utxo₀ = Γ .utxo₀
utxo = s .UTxOState.utxo

witsKeyHashes : ℙ KeyHash
witsKeyHashes = mapˢ hash (dom vKeySigs)

allScripts : ℙ Script
allScripts =
( scripts -- (1) scripts from witnesses
∪ mapPartial txOutToScript
( range (utxo₀ ∣ txIns) -- (2) scripts from transaction inputs
∪ range (utxo ∣ refInputs) -- (3) scripts from reference inputs
)
∪ Γ .globalScripts -- (4) scripts from the nested transaction
)

p1Scripts : ℙ P1Script
p1Scripts = mapPartial toP1Script allScripts

p2Scripts : ℙ P2Script
p2Scripts = mapPartial toP2Script allScripts

neededScriptHashes : ℙ ScriptHash
neededScriptHashes = mapPartial (isScriptObj ∘ proj₂) (credsNeeded utxo₀ txBody)

neededVKeyHashes : ℙ KeyHash
neededVKeyHashes = mapPartial (isKeyHashObj ∘ proj₂) (credsNeeded utxo₀ txBody)

neededDataHashes : ℙ DataHash
neededDataHashes = mapPartial (λ txOut@(a , _ , d , _) → do sh ← isScriptObj (payCred a)
_ ← lookupHash sh p2Scripts
d >>= isInj₂)
(range (utxo₀ ∣ txIns))

in
∙ ∀[ (vk , σ) ∈ vKeySigs ] isSigned vk (txidBytes txId) σ
∙ ∀[ s ∈ p1Scripts ] (hash s ∈ neededScriptHashes → validP1Script witsKeyHashes txVldt s)
∙ neededVKeyHashes ⊆ witsKeyHashes
∙ neededScriptHashes ⊆ mapˢ hash allScripts
∙ neededDataHashes ⊆ dom (Γ .globalData)
∙ languages tx utxo ⊆ allowedLanguages tx utxo
∙ txADhash ≡ map hash txAuxData
∙ Γ ⊢ s ⇀⦇ tx ,UTXO⦈ s'
────────────────────────────────
Γ ⊢ s ⇀⦇ tx ,UTXOW⦈ s'
```

This file intentionally contains **no** additional premises yet. As Dijkstra witnessing
evolves, this is where signature / script / datum / language constraints can be added.
4 changes: 4 additions & 0 deletions src/Ledger/Prelude.lagda.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,8 @@ module Filter where
filter : ∀ {a} {p} {A : Type a} → (P : Pred A p) → ⦃ P ⁇¹ ⦄ → List A → List A
filter P = Data.List.filter ¿ P ¿¹

lookupHash : ∀ {T H : Type} ⦃ _ : DecEq H ⦄ ⦃ _ : Hashable T H ⦄ → H → ℙ T → Maybe T
lookupHash h s =
if h ∈ mapˢ proj₁ (m ˢ) then just (lookupᵐ m h) else nothing
where m = setToMap (mapˢ < hash , id > s)
```
Loading