Skip to content

Commit

Permalink
Add Cardano.Api.Tx.Compatible
Browse files Browse the repository at this point in the history
This module exposes createCompatibleSignedTx which is intended to be
used in testing only. It allows creation of simple unbalanced
transactions that can submit protocol updates in any era.
  • Loading branch information
Jimbo4350 committed Oct 3, 2024
1 parent 17eb46f commit 03b8dd5
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 12 deletions.
2 changes: 2 additions & 0 deletions cardano-api/cardano-api.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ library internal
Cardano.Api.SpecialByron
Cardano.Api.StakePoolMetadata
Cardano.Api.Tx.Body
Cardano.Api.Tx.Compatible
Cardano.Api.Tx.Sign
Cardano.Api.TxIn
Cardano.Api.TxMetadata
Expand Down Expand Up @@ -236,6 +237,7 @@ library
Cardano.Api.Byron
Cardano.Api.ChainSync.Client
Cardano.Api.ChainSync.ClientPipelined
Cardano.Api.Compatible
Cardano.Api.Crypto.Ed25519Bip32
Cardano.Api.Experimental
Cardano.Api.Ledger
Expand Down
1 change: 1 addition & 0 deletions cardano-api/internal/Cardano/Api/Eon/ConwayEraOnwards.hs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ type ConwayEraOnwardsConstraints era =
, Consensus.ShelleyCompatible (ConsensusProtocol era) (ShelleyLedgerEra era)
, L.ADDRHASH (Consensus.PraosProtocolSupportsNodeCrypto (ConsensusProtocol era)) ~ Blake2b.Blake2b_224
, L.AlonzoEraTxOut (ShelleyLedgerEra era)
, L.AlonzoEraTxWits (ShelleyLedgerEra era)
, L.BabbageEraTxBody (ShelleyLedgerEra era)
, L.ConwayEraGov (ShelleyLedgerEra era)
, L.ConwayEraPParams (ShelleyLedgerEra era)
Expand Down
1 change: 1 addition & 0 deletions cardano-api/internal/Cardano/Api/Eon/ShelleyBasedEra.hs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ type ShelleyBasedEraConstraints era =
, L.EraTxBody (ShelleyLedgerEra era)
, L.EraTxOut (ShelleyLedgerEra era)
, L.EraUTxO (ShelleyLedgerEra era)
, L.EraTxWits (ShelleyLedgerEra era)
, L.HashAnnotated (L.TxBody (ShelleyLedgerEra era)) L.EraIndependentTxBody L.StandardCrypto
, L.ShelleyEraTxCert (ShelleyLedgerEra era)
, FromCBOR (Consensus.ChainDepState (ConsensusProtocol era))
Expand Down
9 changes: 9 additions & 0 deletions cardano-api/internal/Cardano/Api/Script.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ module Cardano.Api.Script
-- * Reference scripts
, ReferenceScript (..)
, refScriptToShelleyScript
, getScriptWitnessReferenceInput

-- * Use of a script in an era as a witness
, WitCtxTxIn
Expand Down Expand Up @@ -694,6 +695,14 @@ data SimpleScriptOrReferenceInput lang
| SReferenceScript TxIn (Maybe ScriptHash)
deriving (Eq, Show)

getScriptWitnessReferenceInput :: ScriptWitness witctx era -> Maybe TxIn
getScriptWitnessReferenceInput (SimpleScriptWitness _ (SReferenceScript txIn _)) =
Just txIn
getScriptWitnessReferenceInput (PlutusScriptWitness _ _ (PReferenceScript txIn _) _ _ _) =
Just txIn
getScriptWitnessReferenceInput (SimpleScriptWitness _ (SScript _)) = Nothing
getScriptWitnessReferenceInput (PlutusScriptWitness _ _ (PScript _) _ _ _) = Nothing

-- | A /use/ of a script within a transaction body to witness that something is
-- being used in an authorised manner. That can be
--
Expand Down
25 changes: 13 additions & 12 deletions cardano-api/internal/Cardano/Api/Tx/Body.hs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ module Cardano.Api.Tx.Body
, convWithdrawals
, getScriptIntegrityHash
, mkCommonTxBody
, scriptWitnessesProposing
, toAuxiliaryData
, toByronTxId
, toShelleyTxId
Expand Down Expand Up @@ -3367,18 +3368,18 @@ collectTxBodyScriptWitnesses
, witness <- maybeToList (Map.lookup voter witnesses)
]

scriptWitnessesProposing
:: TxProposalProcedures BuildTx era
-> [(ScriptWitnessIndex, AnyScriptWitness era)]
scriptWitnessesProposing TxProposalProceduresNone = []
scriptWitnessesProposing (TxProposalProcedures proposalProcedures (BuildTxWith mScriptWitnesses))
| Map.null mScriptWitnesses = []
| otherwise =
[ (ScriptWitnessIndexProposing ix, AnyScriptWitness witness)
| let proposalsList = toList proposalProcedures
, (ix, proposal) <- zip [0 ..] proposalsList
, witness <- maybeToList (Map.lookup proposal mScriptWitnesses)
]
scriptWitnessesProposing
:: TxProposalProcedures BuildTx era
-> [(ScriptWitnessIndex, AnyScriptWitness era)]
scriptWitnessesProposing TxProposalProceduresNone = []
scriptWitnessesProposing (TxProposalProcedures proposalProcedures (BuildTxWith mScriptWitnesses))
| Map.null mScriptWitnesses = []
| otherwise =
[ (ScriptWitnessIndexProposing ix, AnyScriptWitness witness)
| let proposalsList = toList proposalProcedures
, (ix, proposal) <- zip [0 ..] proposalsList
, witness <- maybeToList (Map.lookup proposal mScriptWitnesses)
]

-- This relies on the TxId Ord instance being consistent with the
-- Ledger.TxId Ord instance via the toShelleyTxId conversion
Expand Down
155 changes: 155 additions & 0 deletions cardano-api/internal/Cardano/Api/Tx/Compatible.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}

-- | This module provides a way to construct a simple transaction over all eras.
-- It is exposed for testing purposes only.
module Cardano.Api.Tx.Compatible
( AnyProtocolUpdate (..)
, createCompatibleSignedTx
)
where

import Cardano.Api.Eon.ConwayEraOnwards
import Cardano.Api.Eon.ShelleyBasedEra
import Cardano.Api.Eon.ShelleyToBabbageEra
import Cardano.Api.ProtocolParameters
import Cardano.Api.Script
import Cardano.Api.Tx.Body
import Cardano.Api.Tx.Sign
import Cardano.Api.Value

import qualified Cardano.Ledger.Api as L

import Control.Error (catMaybes)
import qualified Data.Map.Strict as Map
import Data.Maybe.Strict
import qualified Data.Sequence.Strict as Seq
import Data.Set (fromList)
import Lens.Micro

data AnyProtocolUpdate era where
ShelleyToBabbageProtocolUpdate
:: ShelleyToBabbageEra era
-> UpdateProposal
-> AnyProtocolUpdate era
ConwayEraOnwardsProtocolUpdate
:: ConwayEraOnwards era
-> TxProposalProcedures BuildTx era
-> AnyProtocolUpdate era
NoPParamsUpdate
:: ShelleyBasedEra era
-> AnyProtocolUpdate era

createCompatibleSignedTx
:: forall era
. ShelleyBasedEra era
-> [TxIn]
-> [TxOut CtxTx era]
-> [KeyWitness era]
-> Lovelace
-- ^ Fee
-> AnyProtocolUpdate era
-> Either ProtocolParametersConversionError (Tx era)
createCompatibleSignedTx sbeF ins outs witnesses txFee' anyProtocolUpdate =
shelleyBasedEraConstraints sbeF $
case anyProtocolUpdate of
ShelleyToBabbageProtocolUpdate shelleyToBabbageEra updateProposal -> do
let sbe = shelleyToBabbageEraToShelleyBasedEra shelleyToBabbageEra

ledgerPParamsUpdate <- toLedgerUpdate sbe updateProposal

let txbody = createCommonTxBody sbe ins outs txFee'
bodyWithProtocolUpdate =
shelleyToBabbageEraConstraints shelleyToBabbageEra $
txbody & L.updateTxBodyL .~ SJust ledgerPParamsUpdate
finalTx =
L.mkBasicTx bodyWithProtocolUpdate
& L.witsTxL .~ shelleyToBabbageEraConstraints shelleyToBabbageEra allShelleyToBabbageWitnesses

return $ ShelleyTx sbe finalTx
NoPParamsUpdate sbe -> do
let txbody = createCommonTxBody sbe ins outs txFee'
finalTx = L.mkBasicTx txbody & L.witsTxL .~ shelleyBasedEraConstraints sbe allShelleyToBabbageWitnesses

return $ ShelleyTx sbe finalTx
ConwayEraOnwardsProtocolUpdate conwayOnwards proposalProcedures -> do
let sbe = conwayEraOnwardsToShelleyBasedEra conwayOnwards
proposals = convProposalProcedures proposalProcedures
apiScriptWitnesses = scriptWitnessesProposing proposalProcedures
ledgerScripts = convScripts apiScriptWitnesses
referenceInputs =
map toShelleyTxIn $
catMaybes [getScriptWitnessReferenceInput sWit | (_, AnyScriptWitness sWit) <- apiScriptWitnesses]
sData = convScriptData sbe outs apiScriptWitnesses
txbody =
conwayEraOnwardsConstraints conwayOnwards $
createCommonTxBody sbe ins outs txFee'
& L.referenceInputsTxBodyL .~ fromList referenceInputs
& L.proposalProceduresTxBodyL
.~ proposals

finalTx =
L.mkBasicTx txbody
& L.witsTxL
.~ conwayEraOnwardsConstraints conwayOnwards (allConwayEraOnwardsWitnesses sData ledgerScripts)

return $ ShelleyTx sbe finalTx
where
shelleyKeywitnesses =
fromList [w | ShelleyKeyWitness _ w <- witnesses]

shelleyBootstrapWitnesses =
fromList [w | ShelleyBootstrapWitness _ w <- witnesses]

allConwayEraOnwardsWitnesses
:: L.AlonzoEraTxWits (ShelleyLedgerEra era)
=> L.EraCrypto (ShelleyLedgerEra era) ~ L.StandardCrypto
=> TxBodyScriptData era -> [L.Script (ShelleyLedgerEra era)] -> L.TxWits (ShelleyLedgerEra era)
allConwayEraOnwardsWitnesses sData ledgerScripts =
let (datums, redeemers) = case sData of
TxBodyScriptData _ ds rs -> (ds, rs)
TxBodyNoScriptData -> (mempty, L.Redeemers mempty)
in L.mkBasicTxWits
& L.addrTxWitsL
.~ shelleyKeywitnesses
& L.bootAddrTxWitsL
.~ shelleyBootstrapWitnesses
& L.datsTxWitsL .~ datums
& L.rdmrsTxWitsL .~ redeemers
& L.scriptTxWitsL
.~ Map.fromList
[ (L.hashScript sw, sw)
| sw <- ledgerScripts
]

allShelleyToBabbageWitnesses
:: L.EraTxWits (ShelleyLedgerEra era)
=> L.EraCrypto (ShelleyLedgerEra era) ~ L.StandardCrypto
=> L.TxWits (ShelleyLedgerEra era)
allShelleyToBabbageWitnesses =
L.mkBasicTxWits
& L.addrTxWitsL
.~ shelleyKeywitnesses
& L.bootAddrTxWitsL
.~ shelleyBootstrapWitnesses

createCommonTxBody
:: ShelleyBasedEra era
-> [TxIn]
-> [TxOut ctx era]
-> Lovelace
-> L.TxBody (ShelleyLedgerEra era)
createCommonTxBody era ins outs txFee' =
let txIns' = map toShelleyTxIn ins
txOuts' = map (toShelleyTxOutAny era) outs
in shelleyBasedEraConstraints era $
L.mkBasicTxBody
& L.inputsTxBodyL
.~ fromList txIns'
& L.outputsTxBodyL
.~ Seq.fromList txOuts'
& L.feeTxBodyL
.~ txFee'
6 changes: 6 additions & 0 deletions cardano-api/src/Cardano/Api/Compatible.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Cardano.Api.Compatible
( module Cardano.Api.Tx.Compatible
)
where

import Cardano.Api.Tx.Compatible

0 comments on commit 03b8dd5

Please sign in to comment.