Skip to content

Commit

Permalink
Add certs support in compatible Tx building
Browse files Browse the repository at this point in the history
  • Loading branch information
carbolymer committed Nov 29, 2024
1 parent c084a4e commit df09cd9
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 72 deletions.
5 changes: 5 additions & 0 deletions cardano-api/internal/Cardano/Api/Eon/BabbageEraOnwards.hs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ instance Inject (BabbageEraOnwards era) (MaryEraOnwards era) where
BabbageEraOnwardsBabbage -> MaryEraOnwardsBabbage
BabbageEraOnwardsConway -> MaryEraOnwardsConway

instance Inject (BabbageEraOnwards era) (AlonzoEraOnwards era) where
inject = \case
BabbageEraOnwardsBabbage -> AlonzoEraOnwardsBabbage
BabbageEraOnwardsConway -> AlonzoEraOnwardsConway

type BabbageEraOnwardsConstraints era =
( C.HashAlgorithm (L.HASH (L.EraCrypto (ShelleyLedgerEra era)))
, C.Signable (L.VRF (L.EraCrypto (ShelleyLedgerEra era))) L.Seed
Expand Down
5 changes: 5 additions & 0 deletions cardano-api/internal/Cardano/Api/Eon/ConwayEraOnwards.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module Cardano.Api.Eon.ConwayEraOnwards
)
where

import Cardano.Api.Eon.AllegraEraOnwards (AllegraEraOnwards (..))
import Cardano.Api.Eon.BabbageEraOnwards
import Cardano.Api.Eon.ShelleyBasedEra
import Cardano.Api.Eras.Core
Expand Down Expand Up @@ -74,6 +75,10 @@ instance Inject (ConwayEraOnwards era) (ShelleyBasedEra era) where
inject = \case
ConwayEraOnwardsConway -> ShelleyBasedEraConway

instance Inject (ConwayEraOnwards era) (AllegraEraOnwards era) where
inject = \case
ConwayEraOnwardsConway -> AllegraEraOnwardsConway

instance Inject (ConwayEraOnwards era) (BabbageEraOnwards era) where
inject = \case
ConwayEraOnwardsConway -> BabbageEraOnwardsConway
Expand Down
1 change: 0 additions & 1 deletion cardano-api/internal/Cardano/Api/Fees.hs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ import Control.Monad
import Data.Bifunctor (bimap, first, second)
import Data.ByteString.Short (ShortByteString)
import Data.Function ((&))
import Data.Functor
import qualified Data.List as List
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
Expand Down
17 changes: 8 additions & 9 deletions cardano-api/internal/Cardano/Api/Tx/Body.hs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ module Cardano.Api.Tx.Body
, convWithdrawals
, getScriptIntegrityHash
, mkCommonTxBody
, scriptWitnessesProposing
, toAuxiliaryData
, toByronTxId
, toShelleyTxId
Expand Down Expand Up @@ -3427,14 +3426,14 @@ collectTxBodyScriptWitnesses
| (ix, _, witness) <- txVotingProceduresToIndexed txv
]

scriptWitnessesProposing
:: TxProposalProcedures BuildTx era
-> [(ScriptWitnessIndex, AnyScriptWitness era)]
scriptWitnessesProposing TxProposalProceduresNone = []
scriptWitnessesProposing txp =
[ (ix, AnyScriptWitness witness)
| (ix, _, witness) <- txProposalProceduresToIndexed txp
]
scriptWitnessesProposing
:: TxProposalProcedures BuildTx era
-> [(ScriptWitnessIndex, AnyScriptWitness era)]
scriptWitnessesProposing TxProposalProceduresNone = []
scriptWitnessesProposing txp =
[ (ix, AnyScriptWitness witness)
| (ix, _, witness) <- txProposalProceduresToIndexed txp
]

-- TODO: Investigate if we need
toShelleyWithdrawal :: [(StakeAddress, L.Coin, a)] -> L.Withdrawals StandardCrypto
Expand Down
188 changes: 126 additions & 62 deletions cardano-api/internal/Cardano/Api/Tx/Compatible.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}

-- | This module provides a way to construct a simple transaction over all eras.
Expand All @@ -17,6 +19,7 @@ import Cardano.Api.Eon.ConwayEraOnwards
import Cardano.Api.Eon.ShelleyBasedEra
import Cardano.Api.Eon.ShelleyToBabbageEra
import Cardano.Api.Eras
import Cardano.Api.Eras.Case
import Cardano.Api.ProtocolParameters
import Cardano.Api.Script
import Cardano.Api.Tx.Body
Expand All @@ -25,12 +28,13 @@ 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
import Data.Maybe.Strict
import qualified Data.Sequence.Strict as Seq
import Data.Set (fromList)
import Lens.Micro
import Data.Set (Set)
import GHC.Exts (IsList (..))
import Lens.Micro hiding (ix)

data AnyProtocolUpdate era where
ProtocolUpdate
Expand Down Expand Up @@ -62,62 +66,109 @@ createCompatibleSignedTx
-- ^ Fee
-> AnyProtocolUpdate era
-> AnyVote era
-> TxCertificates BuildTx era
-> Either ProtocolParametersConversionError (Tx era)
createCompatibleSignedTx sbeF ins outs witnesses txFee' anyProtocolUpdate anyVote =
shelleyBasedEraConstraints sbeF $ do
tx <- case anyProtocolUpdate of
createCompatibleSignedTx sbe ins outs witnesses txFee' anyProtocolUpdate anyVote txCertificates' =
shelleyBasedEraConstraints sbe $ do
let txbody =
createCommonTxBody sbe ins outs txFee'
& setCerts
& setRefInputs

fTx <- case anyProtocolUpdate of
ProtocolUpdate shelleyToBabbageEra updateProposal -> do
let sbe = inject shelleyToBabbageEra

ledgerPParamsUpdate <- toLedgerUpdate sbe updateProposal

let txbody = createCommonTxBody sbe ins outs txFee'
bodyWithProtocolUpdate =
let apiScriptWitnesses =
[ (ix, AnyScriptWitness witness)
| (ix, _, _, ScriptWitness _ witness) <- txCertificatesToIndexed txCertificates'
]
ledgerScripts = convScripts apiScriptWitnesses
sData = convScriptData sbe outs apiScriptWitnesses
let 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
pure $
L.mkBasicTx bodyWithProtocolUpdate
& L.witsTxL .~ allWitnesses sData ledgerScripts allShelleyToBabbageWitnesses
NoPParamsUpdate _ -> do
let apiScriptWitnesses =
[ (ix, AnyScriptWitness witness)
| (ix, _, _, ScriptWitness _ witness) <- txCertificatesToIndexed txCertificates'
]
ledgerScripts = convScripts apiScriptWitnesses
referenceInputs =
[ toShelleyTxIn txIn
| (_, AnyScriptWitness sWit) <- apiScriptWitnesses
, txIn <- maybeToList $ getScriptWitnessReferenceInput sWit
]
sData = convScriptData sbe outs apiScriptWitnesses
updatedBody =
txbody
& caseShelleyToAlonzoOrBabbageEraOnwards
(const id)
(const $ L.referenceInputsTxBodyL %~ (<> fromList referenceInputs))
sbe
pure $
L.mkBasicTx updatedBody
& L.witsTxL .~ allWitnesses sData ledgerScripts allShelleyToBabbageWitnesses
ProposalProcedures conwayOnwards proposalProcedures -> do
let sbe = inject conwayOnwards
proposals = convProposalProcedures proposalProcedures
apiScriptWitnesses = scriptWitnessesProposing proposalProcedures
let proposals = convProposalProcedures proposalProcedures
apiScriptWitnesses =
[ (ix, AnyScriptWitness witness)
| (ix, _, witness) <- txProposalProceduresToIndexed proposalProcedures
]
<> [ (ix, AnyScriptWitness witness)
| (ix, _, _, ScriptWitness _ witness) <- txCertificatesToIndexed txCertificates'
]
ledgerScripts = convScripts apiScriptWitnesses
referenceInputs =
map toShelleyTxIn $
catMaybes [getScriptWitnessReferenceInput sWit | (_, AnyScriptWitness sWit) <- apiScriptWitnesses]
[ toShelleyTxIn txIn
| (_, AnyScriptWitness sWit) <- apiScriptWitnesses
, txIn <- maybeToList $ getScriptWitnessReferenceInput sWit
]
sData = convScriptData sbe outs apiScriptWitnesses
txbody =
updatedTxBody =
conwayEraOnwardsConstraints conwayOnwards $
createCommonTxBody sbe ins outs txFee'
& L.referenceInputsTxBodyL .~ fromList referenceInputs
& L.proposalProceduresTxBodyL
.~ proposals
txbody
& L.referenceInputsTxBodyL %~ (<> fromList referenceInputs)
& L.proposalProceduresTxBodyL .~ proposals

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

return $ ShelleyTx sbe finalTx
pure $
L.mkBasicTx updatedTxBody
& L.witsTxL
.~ allWitnesses sData ledgerScripts allShelleyToBabbageWitnesses

case anyVote of
NoVotes -> return tx
NoVotes -> return $ ShelleyTx sbe fTx
VotingProcedures conwayOnwards procedures -> do
let ledgerVotingProcedures = convVotingProcedures procedures
ShelleyTx sbe' fTx = tx
updatedTx =
conwayEraOnwardsConstraints conwayOnwards $
overwriteVotingProcedures fTx ledgerVotingProcedures
return $ ShelleyTx sbe' updatedTx
return $ ShelleyTx sbe updatedTx
where
setCerts :: L.TxBody (ShelleyLedgerEra era) -> L.TxBody (ShelleyLedgerEra era)
setCerts =
shelleyBasedEraConstraints sbe $
caseShelleyToMaryOrAlonzoEraOnwards
(const id)
(const $ L.certsTxBodyL .~ convCertificates sbe txCertificates')
sbe

setRefInputs :: L.TxBody (ShelleyLedgerEra era) -> L.TxBody (ShelleyLedgerEra era)
setRefInputs = do
let refInputs =
[ toShelleyTxIn refInput
| (_, _, _, ScriptWitness _ wit) <- txCertificatesToIndexed txCertificates'
, refInput <- maybeToList $ getScriptWitnessReferenceInput wit
]

caseShelleyToAlonzoOrBabbageEraOnwards
(const id)
(const $ L.referenceInputsTxBodyL .~ fromList refInputs)
sbe

overwriteVotingProcedures
:: L.ConwayEraTxBody ledgerera
=> L.EraTx ledgerera
Expand All @@ -126,31 +177,42 @@ createCompatibleSignedTx sbeF ins outs witnesses txFee' anyProtocolUpdate anyVot
lTx & (L.bodyTxL . L.votingProceduresTxBodyL) .~ vProcedures

shelleyKeywitnesses =
fromList [w | ShelleyKeyWitness _ w <- witnesses]
fromList @(Set _) [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
]
fromList @(Set _) [w | ShelleyBootstrapWitness _ w <- witnesses]

allWitnesses
:: TxBodyScriptData era
-> [L.Script (ShelleyLedgerEra era)]
-> L.TxWits (ShelleyLedgerEra era)
-> L.TxWits (ShelleyLedgerEra era)
allWitnesses sData ledgerScripts txw = shelleyBasedEraConstraints sbe $ do
let txw1 =
caseShelleyToMaryOrAlonzoEraOnwards
(const txw)
( const $ do
let (datums, redeemers) = case sData of
TxBodyScriptData _ ds rs -> (ds, rs)
TxBodyNoScriptData -> (mempty, L.Redeemers mempty)
txw
& L.datsTxWitsL .~ datums
& L.rdmrsTxWitsL %~ (<> redeemers)
)
sbe
txw2 =
caseShelleyEraOnlyOrAllegraEraOnwards
(const txw1)
( const $
txw1
& L.scriptTxWitsL
.~ Map.fromList
[ (L.hashScript sw, sw)
| sw <- ledgerScripts
]
)
sbe
txw2

allShelleyToBabbageWitnesses
:: L.EraTxWits (ShelleyLedgerEra era)
Expand All @@ -163,6 +225,8 @@ createCompatibleSignedTx sbeF ins outs witnesses txFee' anyProtocolUpdate anyVot
& L.bootAddrTxWitsL
.~ shelleyBootstrapWitnesses

-- allWitnessesToIndexed ::

createCommonTxBody
:: ShelleyBasedEra era
-> [TxIn]
Expand Down

0 comments on commit df09cd9

Please sign in to comment.