\section{Transactions}
\label{sec:transactions}
\begin{code}[hide]
{-# OPTIONS --safe #-}
module Ledger.Transaction where
import Data.Maybe.Base as M
open import Ledger.Prelude renaming (filterᵐ to filter)
open import Ledger.Crypto
open import Ledger.Types.Epoch
open import Ledger.Types.GovStructure
import Ledger.PParams
import Ledger.Script
import Ledger.GovernanceActions
import Ledger.Certs
import Ledger.TokenAlgebra
import Ledger.Address
open import Tactic.Derive.DecEq
open import MyDebugOptions
open import Relation.Nullary.Decidable using (⌊_⌋)
data Tag : Type where
Spend Mint Cert Rewrd Vote Propose : Tag
unquoteDecl DecEq-Tag = derive-DecEq ((quote Tag , DecEq-Tag) ∷ [])
record TransactionStructure : Type₁ where
field
\end{code}
Transactions are defined in Figure~\ref{fig:defs:transactions}. A
transaction is made up of a transaction body, a collection of
witnesses and some optional auxiliary data.
\begin{NoConway}
Some key ingredients in the transaction body are:
\begin{itemize}
\item A set \txins of transaction inputs, each of which identifies an output from a previous transaction.
A transaction input consists of a transaction id and an index to uniquely identify the output.
\item An indexed collection \txouts of transaction outputs.
The \TxOut type is an address paired with a coin value.
\item A transaction fee. This value will be added to the fee pot.
\item The size \txsize and the hash \txid of the serialized form of the transaction that was included in the block.
\end{itemize}
\end{NoConway}
\begin{Conway}
Ingredients of the transaction body introduced in the Conway era are the following:
\begin{itemize}
\item \txvote, the list of votes for goverance actions;
\item \txprop, the list of governance proposals;
\item \txdonation, the treasury donation amount;
\item \curTreasury, the current value of the treasury.
\item \txsize and \txid, the size and hash of the serialized form of the transaction that was included in the block.
\end{itemize}
\end{Conway}
\begin{figure*}[h]
\emph{Abstract types}
\begin{code}
Ix TxId AuxiliaryData : Type
\end{code}
\begin{code}[hide]
⦃ DecEq-Ix ⦄ : DecEq Ix
⦃ DecEq-TxId ⦄ : DecEq TxId
adHashingScheme : isHashableSet AuxiliaryData
open isHashableSet adHashingScheme renaming (THash to ADHash) public
field globalConstants : _
open GlobalConstants globalConstants public
field crypto : _
open Crypto crypto public
open Ledger.TokenAlgebra ScriptHash public
open Ledger.Address Network KeyHash ScriptHash ⦃ it ⦄ ⦃ it ⦄ ⦃ it ⦄ public
field epochStructure : _
open EpochStructure epochStructure public
open Ledger.Script crypto epochStructure public
field scriptStructure : _
open ScriptStructure scriptStructure public
open Ledger.PParams crypto epochStructure scriptStructure public
field govParams : _
open GovParams govParams public
field tokenAlgebra : TokenAlgebra
open TokenAlgebra tokenAlgebra public
field txidBytes : TxId → Ser
govStructure : GovStructure
govStructure = record
{ TxId = TxId; DocHash = ADHash
; crypto = crypto
; epochStructure = epochStructure
; scriptStructure = scriptStructure
; govParams = govParams
; globalConstants = globalConstants
}
module GovernanceActions = Ledger.GovernanceActions govStructure
open GovernanceActions hiding (Vote; yes; no; abstain) public
open import Ledger.Certs govStructure using (DCert)
\end{code}
\begin{NoConway}
\emph{Derived types}
\begin{code}
TxIn = TxId × Ix
TxOut = Addr × Value × Maybe (Datum ⊎ DataHash) × Maybe Script
UTxO = TxIn ⇀ TxOut
Wdrl = RwdAddr ⇀ Coin
RdmrPtr = Tag × Ix
ProposedPPUpdates = KeyHash ⇀ PParamsUpdate
Update = ProposedPPUpdates × Epoch
\end{code}
\end{NoConway}
\emph{Transaction types}
\begin{AgdaMultiCode}
\begin{code}
record TxBody : Type where
\end{code}
\begin{code}[hide]
field
\end{code}
\begin{code}
txins : ℙ TxIn
refInputs : ℙ TxIn
txouts : Ix ⇀ TxOut
txfee : Coin
mint : Value
txvldt : Maybe Slot × Maybe Slot
txcerts : List DCert
txwdrls : Wdrl
txvote : List GovVote
txprop : List GovProposal
txdonation : Coin
txup : Maybe Update
txADhash : Maybe ADHash
txNetworkId : Maybe Network
curTreasury : Maybe Coin
txsize : ℕ
txid : TxId
collateral : ℙ TxIn
reqSigHash : ℙ KeyHash
scriptIntHash : Maybe ScriptHash
\end{code}
\begin{NoConway}
\begin{code}
record TxWitnesses : Type where
\end{code}
\begin{code}[hide]
field
\end{code}
\begin{code}
vkSigs : VKey ⇀ Sig
scripts : ℙ Script
txdats : DataHash ⇀ Datum
txrdmrs : RdmrPtr ⇀ Redeemer × ExUnits
scriptsP1 : ℙ P1Script
scriptsP1 = mapPartial isInj₁ scripts
record Tx : Type where
\end{code}
\begin{code}[hide]
field
\end{code}
\begin{code}
body : TxBody
wits : TxWitnesses
isValid : Bool
txAD : Maybe AuxiliaryData
\end{code}
\end{NoConway}
\end{AgdaMultiCode}
\caption{Transactions and related types}
\label{fig:defs:transactions}
\end{figure*}
\begin{NoConway}
\begin{figure*}[h]
\begin{AgdaMultiCode}
\begin{code}
getValue : TxOut → Value
getValue (_ , v , _) = v
TxOutʰ = Addr × Value × Maybe (Datum ⊎ DataHash) × Maybe ScriptHash
txOutHash : TxOut → TxOutʰ
txOutHash (a , v , d , s) = a , (v , (d , M.map hash s))
getValueʰ : TxOutʰ → Value
getValueʰ (_ , v , _) = v
txinsVKey : ℙ TxIn → UTxO → ℙ TxIn
txinsVKey txins utxo = txins ∩ dom (utxo ∣^' (isVKeyAddr ∘ proj₁))
scriptOuts : UTxO → UTxO
scriptOuts utxo = filter (λ (_ , addr , _) → isScriptAddr addr) utxo
txinsScript : ℙ TxIn → UTxO → ℙ TxIn
txinsScript txins utxo = txins ∩ dom (proj₁ (scriptOuts utxo))
refScripts : Tx → UTxO → List Script
refScripts tx utxo =
mapMaybe (proj₂ ∘ proj₂ ∘ proj₂) $ setToList (range (utxo ∣ (txins ∪ refInputs)))
where open Tx; open TxBody (tx .body)
txscripts : Tx → UTxO → ℙ Script
txscripts tx utxo = scripts (tx .wits) ∪ fromList (refScripts tx utxo)
where open Tx; open TxWitnesses
lookupScriptHash : ScriptHash → Tx → UTxO → Maybe Script
lookupScriptHash sh tx utxo =
if sh ∈ mapˢ proj₁ (m ˢ) then
just (lookupᵐ m sh)
else
nothing
where m = setToHashMap (txscripts tx utxo)
\end{code}
\end{AgdaMultiCode}
\caption{Functions related to transactions}
\label{fig:defs:transaction-funs}
\end{figure*}
\end{NoConway}
\begin{code}[hide]
isP2Script : Script → Type
isP2Script = T ∘ is-just ∘ isInj₂
isP2Script? : ∀ {s} → isP2Script s ⁇
isP2Script? {inj₁ x} .dec = no λ ()
isP2Script? {inj₂ y} .dec = yes tt
instance
HasCoin-TxOut : HasCoin TxOut
HasCoin-TxOut .getCoin = coin ∘ proj₁ ∘ proj₂
\end{code}