Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Cardano.Api.Tx.Compatible #644

Merged
merged 2 commits into from
Oct 3, 2024
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
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
Comment on lines +7 to +9
Copy link
Contributor

@carbolymer carbolymer Sep 30, 2024

Choose a reason for hiding this comment

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

The module name and the description is not quite clear for me. Is it supposed to be a module for support of transaction building for older eras once we remove them from API?

Maybe we should add Internal to the module name e.g. Cardano.Api.Tx.Internal.Compatible, to mark that it's not meant to be directly used?

I'm not sure about the name as well. Maybe we should name it something like Old or Legacy to put emphasis that it's meant just for backwards compatibility for tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's meant to be directly used. It's supposed to house all functions that are expected to be backwards compatible across all shelley based eras. I'm not opposed to a rename but I'm not blocking the PR on this.

( 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 (BuildTxWith TxSupplementalDataNone)
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' =
palas marked this conversation as resolved.
Show resolved Hide resolved
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'
2 changes: 1 addition & 1 deletion cardano-api/internal/Cardano/Api/TxMetadata.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
-- | Metadata embedded in transactions
module Cardano.Api.TxMetadata
( -- * Types
TxMetadata (TxMetadata)
TxMetadata (..)

-- * Class
, AsTxMetadata (..)
Expand Down
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
Loading