Skip to content
This repository has been archived by the owner on Dec 2, 2024. It is now read-only.

Commit

Permalink
Drop Tx and EmulatorTx types (#973)
Browse files Browse the repository at this point in the history
* Drop EmulatorTx

* Make CardanoTx newtype

* Remove Tx type

* Drop unnecessary CardanoTx newtype layer
  • Loading branch information
Evgenii Akentev authored Mar 3, 2023
1 parent f54eca8 commit b80116b
Show file tree
Hide file tree
Showing 52 changed files with 591 additions and 1,324 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Removed

- Remove `estimateTransactionFee`, `signTx`, `fromPlutusTx`, `fromPlutusTxSigned`, `fromPlutusTxSigned'` as the `Tx` was removed from `plutus-ledger`.
19 changes: 4 additions & 15 deletions cardano-node-emulator/src/Cardano/Node/Emulator/Fee.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
{-# LANGUAGE TypeFamilies #-}
-- | Calculating transaction fees in the emulator.
module Cardano.Node.Emulator.Fee(
estimateTransactionFee,
estimateCardanoBuildTxFee,
makeAutoBalancedTransaction,
makeAutoBalancedTransactionWithUtxoProvider,
Expand All @@ -23,7 +22,7 @@ import Cardano.Api.Shelley qualified as C.Api
import Cardano.Ledger.BaseTypes (Globals (systemStart))
import Cardano.Ledger.Core qualified as C.Ledger (Tx)
import Cardano.Ledger.Shelley.API qualified as C.Ledger hiding (Tx)
import Cardano.Node.Emulator.Params (EmulatorEra, PParams, Params (emulatorPParams, pNetworkId), emulatorEraHistory,
import Cardano.Node.Emulator.Params (EmulatorEra, PParams, Params (emulatorPParams), emulatorEraHistory,
emulatorGlobals, pProtocolParams)
import Cardano.Node.Emulator.Validation (CardanoLedgerError, UTxO (..), makeTransactionBody)
import Control.Arrow ((&&&))
Expand All @@ -36,26 +35,16 @@ import Data.Map qualified as Map
import Data.Maybe (isNothing, listToMaybe)
import Data.Ord (Down (Down))
import GHC.Generics (Generic)
import Ledger.Address (CardanoAddress, PaymentPubKeyHash)
import Ledger.Address (CardanoAddress)
import Ledger.Index (UtxoIndex (UtxoIndex), ValidationError (..), ValidationPhase (Phase1), adjustCardanoTxOut,
minAdaTxOutEstimated)
import Ledger.Tx (ToCardanoError (TxBodyError), Tx, TxOut, TxOutRef)
import Ledger.Tx (ToCardanoError (TxBodyError), TxOut, TxOutRef)
import Ledger.Tx qualified as Tx
import Ledger.Tx.CardanoAPI (CardanoBuildTx (..), fromPlutusIndex, getCardanoBuildTx, toCardanoFee,
toCardanoReturnCollateral, toCardanoTotalCollateral, toCardanoTxBodyContent)
toCardanoReturnCollateral, toCardanoTotalCollateral)
import Ledger.Tx.CardanoAPI qualified as CardanoAPI
import Ledger.Value.CardanoAPI (isZero, lovelaceToValue, split, valueGeq)

estimateTransactionFee
:: Params
-> UTxO EmulatorEra
-> [PaymentPubKeyHash]
-> Tx
-> Either CardanoLedgerError C.Lovelace
estimateTransactionFee params utxo requiredSigners tx = do
txBodyContent <- first Right $ toCardanoTxBodyContent (pNetworkId params) (emulatorPParams params) requiredSigners tx
estimateCardanoBuildTxFee params utxo txBodyContent

estimateCardanoBuildTxFee
:: Params
-> UTxO EmulatorEra
Expand Down
95 changes: 37 additions & 58 deletions cardano-node-emulator/src/Cardano/Node/Emulator/Generators.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ module Cardano.Node.Emulator.Generators(
splitVal,
validateMockchain,
signAll,
signTx,
CW.knownAddresses,
CW.knownPaymentPublicKeys,
CW.knownPaymentPrivateKeys,
CW.knownPaymentKeys,
knownXPrvs,
alwaysSucceedPolicy,
alwaysSucceedPolicyId,
someTokenValue
someTokenValue,
emptyTxBodyContent
) where

import Control.Monad (guard, replicateM)
Expand Down Expand Up @@ -86,15 +86,14 @@ import Cardano.Crypto.Wallet qualified as Crypto
import Cardano.Node.Emulator.Params (Params (pSlotConfig))
import Cardano.Node.Emulator.TimeSlot (SlotConfig)
import Cardano.Node.Emulator.TimeSlot qualified as TimeSlot
import Cardano.Node.Emulator.Validation (fromPlutusTxSigned, validateCardanoTx)
import Cardano.Node.Emulator.Validation (validateCardanoTx)
import Control.Lens.Lens ((<&>))
import Data.Functor (($>))
import Data.String (fromString)
import Gen.Cardano.Api.Typed (genTxIn)
import Ledger (CardanoTx (CardanoApiTx), Interval, MintingPolicy (getMintingPolicy),
import Ledger (CardanoTx (CardanoEmulatorEraTx), Interval, MintingPolicy (getMintingPolicy),
POSIXTime (POSIXTime, getPOSIXTime), POSIXTimeRange, Passphrase (Passphrase),
PaymentPrivateKey (unPaymentPrivateKey), PaymentPubKey, Slot (Slot), SlotRange,
SomeCardanoApiTx (CardanoApiEmulatorEraTx),
TxInType (ConsumePublicKeyAddress, ConsumeSimpleScriptAddress, ScriptAddress), TxInput, TxInputType,
TxOut, TxOutRef (TxOutRef), ValidationErrorInPhase, addCardanoTxSignature, maxFee, minAdaTxOutEstimated,
minLovelaceTxOutEstimated, pubKeyTxOut, txOutValue, validatorHash)
Expand Down Expand Up @@ -163,11 +162,10 @@ genMockchain' gm = do
slotCfg <- genSlotConfig
(txn, ot) <- genInitialTransaction gm
let params = def { pSlotConfig = slotCfg }
signedTx = signTx params mempty txn
-- There is a problem that txId of emulator tx and tx of cardano tx are different.
-- We convert the emulator tx to cardano tx here to get the correct transaction id
-- because later we anyway will use the converted cardano tx so the utxo should match it.
tid = Tx.getCardanoTxId signedTx
tid = Tx.getCardanoTxId txn
pure Mockchain {
mockchainInitialTxPool = [txn],
mockchainUtxo = Map.fromList $ first (TxOutRef tid) <$> zip [0..] ot,
Expand All @@ -188,6 +186,27 @@ genInitialTransaction g = do
(body, o) <- initialTxBody g
(,o) <$> makeTx body

emptyTxBodyContent :: C.TxBodyContent C.BuildTx C.BabbageEra
emptyTxBodyContent = C.TxBodyContent
{ txIns = []
, txInsCollateral = C.TxInsCollateralNone
, txMintValue = C.TxMintNone
, txFee = C.toCardanoFee 0
, txOuts = []
, txProtocolParams = C.BuildTxWith $ Just $ C.fromLedgerPParams C.ShelleyBasedEraBabbage def
, txInsReference = C.TxInsReferenceNone
, txTotalCollateral = C.TxTotalCollateralNone
, txReturnCollateral = C.TxReturnCollateralNone
, txValidityRange = ( C.TxValidityNoLowerBound
, C.TxValidityNoUpperBound C.ValidityNoUpperBoundInBabbageEra)
, txScriptValidity = C.TxScriptValidityNone
, txExtraKeyWits = C.TxExtraKeyWitnessesNone
, txMetadata = C.TxMetadataNone
, txAuxScripts = C.TxAuxScriptsNone
, txWithdrawals = C.TxWithdrawalsNone
, txCertificates = C.TxCertificatesNone
, txUpdateProposal = C.TxUpdateProposalNone
}

initialTxBody ::
GeneratorModel
Expand All @@ -198,27 +217,9 @@ initialTxBody GeneratorModel{..} = do
-- we use a generated tx in input it's unbalanced but it's "fine" as we don't validate this tx
txIns <- map (, C.BuildTxWith (C.KeyWitness C.KeyWitnessForSpending))
<$> Gen.list (Range.constant 1 10) genTxIn
pure (C.TxBodyContent
{ txIns
, txInsCollateral = C.TxInsCollateralNone
, txMintValue = C.TxMintNone
, txFee = C.toCardanoFee 0
, txOuts = Tx.getTxOut <$> o
-- unused:
, txProtocolParams = C.BuildTxWith $ Just $ C.fromLedgerPParams C.ShelleyBasedEraBabbage def
, txInsReference = C.TxInsReferenceNone
, txTotalCollateral = C.TxTotalCollateralNone
, txReturnCollateral = C.TxReturnCollateralNone
, txValidityRange = ( C.TxValidityNoLowerBound
, C.TxValidityNoUpperBound C.ValidityNoUpperBoundInBabbageEra)
, txScriptValidity = C.TxScriptValidityNone
, txExtraKeyWits = C.TxExtraKeyWitnessesNone
, txMetadata = C.TxMetadataNone
, txAuxScripts = C.TxAuxScriptsNone
, txWithdrawals = C.TxWithdrawalsNone

, txCertificates = C.TxCertificatesNone
, txUpdateProposal = C.TxUpdateProposalNone
pure (emptyTxBodyContent
{ C.txIns
, C.txOuts = Tx.getTxOut <$> o
}, o)

-- | Generate a valid transaction, using the unspent outputs provided.
Expand Down Expand Up @@ -269,7 +270,7 @@ makeTx
-> m CardanoTx
makeTx bodyContent = do
txBody <- either (fail . ("Can't create TxBody" <>) . show) pure $ C.makeTransactionBody bodyContent
pure $ signAll $ CardanoApiTx $ CardanoApiEmulatorEraTx $ C.Tx txBody []
pure $ signAll $ CardanoEmulatorEraTx $ C.Tx txBody []

-- | Generate a valid transaction, using the unspent outputs provided.
-- Fails if the there are no unspent outputs, or if the total value
Expand Down Expand Up @@ -333,27 +334,12 @@ genValidTransactionBodySpending' g ins totalVal = do
(fail "Cannot gen collateral")
(failOnCardanoError . (C.toCardanoTxInsCollateral . map toTxInput . flip take ins . fromIntegral))
(gmMaxCollateralInputs g)
pure $ C.TxBodyContent
{ txIns
, txInsCollateral
, txMintValue
, txFee = C.toCardanoFee fee'
, txOuts = Tx.getTxOut <$> txOutputs
-- unused:
, txProtocolParams = C.BuildTxWith $ Just $ C.fromLedgerPParams C.ShelleyBasedEraBabbage def
, txInsReference = C.TxInsReferenceNone
, txTotalCollateral = C.TxTotalCollateralNone
, txReturnCollateral = C.TxReturnCollateralNone
, txValidityRange = ( C.TxValidityNoLowerBound
, C.TxValidityNoUpperBound C.ValidityNoUpperBoundInBabbageEra)
, txScriptValidity = C.TxScriptValidityNone
, txExtraKeyWits = C.TxExtraKeyWitnessesNone
, txMetadata = C.TxMetadataNone
, txAuxScripts = C.TxAuxScriptsNone
, txWithdrawals = C.TxWithdrawalsNone

, txCertificates = C.TxCertificatesNone
, txUpdateProposal = C.TxUpdateProposalNone
pure $ emptyTxBodyContent
{ C.txIns
, C.txInsCollateral
, C.txMintValue
, C.txFee = C.toCardanoFee fee'
, C.txOuts = Tx.getTxOut <$> txOutputs
}
where
-- | Translate TxIn to TxInput taking out data witnesses if present.
Expand All @@ -379,18 +365,11 @@ genValidTransactionBodySpending' g ins totalVal = do
toTxInType Tx.ConsumePublicKeyAddress = Tx.TxConsumePublicKeyAddress
toTxInType (Tx.ScriptAddress valOrRef rd dat) = Tx.TxScriptAddress rd (first validatorHash valOrRef) $ fmap datumHash dat

signTx :: Params -> Map TxOutRef TxOut -> CardanoTx -> CardanoTx
signTx params utxo = let
cUtxoIndex = either (error . show) id $ fromPlutusIndex (Index.UtxoIndex utxo)
in Tx.onCardanoTx
(\t -> fromPlutusTxSigned params cUtxoIndex t CW.knownPaymentKeys)
Tx.CardanoApiTx

-- | Validate a transaction in a mockchain.
validateMockchain :: Mockchain -> CardanoTx -> Maybe Ledger.ValidationErrorInPhase
validateMockchain (Mockchain _ utxo params) tx = result where
cUtxoIndex = either (error . show) id $ fromPlutusIndex (Index.UtxoIndex utxo)
result = leftToMaybe $ validateCardanoTx params 1 cUtxoIndex (signTx params utxo tx)
result = leftToMaybe $ validateCardanoTx params 1 cUtxoIndex tx

-- | Generate an 'Interval where the lower bound if less or equal than the
-- upper bound.
Expand Down
63 changes: 7 additions & 56 deletions cardano-node-emulator/src/Cardano/Node/Emulator/Validation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ViewPatterns #-}

{-| Transaction validation using 'cardano-ledger-specs'
-}
module Cardano.Node.Emulator.Validation(
Expand All @@ -19,9 +21,6 @@ module Cardano.Node.Emulator.Validation(
hasValidationErrors,
makeTransactionBody,
validateCardanoTx,
fromPlutusTx,
fromPlutusTxSigned,
fromPlutusTxSigned',
-- * Modifying the state
makeBlock,
setSlot,
Expand All @@ -37,7 +36,6 @@ module Cardano.Node.Emulator.Validation(
emulatorGlobals,
) where

import Cardano.Api qualified as C
import Cardano.Api.Shelley qualified as C.Api
import Cardano.Ledger.Alonzo.PlutusScriptApi (collectTwoPhaseScriptInputs, evalScripts)
import Cardano.Ledger.Alonzo.Rules.Utxos (UtxosPredicateFailure (CollectErrors))
Expand All @@ -58,29 +56,22 @@ import Cardano.Ledger.Shelley.LedgerState (LedgerState (..), UTxOState (..), sma
import Cardano.Ledger.Shelley.Rules.Utxo (UtxoEnv (..))
import Cardano.Ledger.Shelley.TxBody (DCert, Wdrl)
import Cardano.Ledger.ShelleyMA.Timelocks (ValidityInterval)
import Cardano.Node.Emulator.Params (EmulatorEra, Params (emulatorPParams, pNetworkId), emulatorGlobals,
emulatorPParams)
import Cardano.Node.Emulator.Params (EmulatorEra, Params (emulatorPParams), emulatorGlobals, emulatorPParams)
import Cardano.Slotting.Slot (SlotNo (..))
import Control.Lens (makeLenses, over, (&), (.~), (^.))
import Control.Monad.Except (MonadError (throwError))
import Data.Array (array)
import Data.Bifunctor (Bifunctor (..))
import Data.Default (def)
import Data.Foldable (foldl')
import Data.Map qualified as Map
import Data.Maybe (mapMaybe)
import Data.Sequence.Strict (StrictSeq)
import Data.Set (Set)
import Data.Text qualified as Text
import GHC.Records (HasField (..))
import Ledger.Address qualified as P
import Ledger.Crypto qualified as Crypto
import Ledger.Index.Internal qualified as P
import Ledger.Slot (Slot)
import Ledger.Tx (CardanoTx (CardanoApiTx), SomeCardanoApiTx (CardanoApiEmulatorEraTx, SomeTx), addCardanoTxSignature,
onCardanoTx)
import Ledger.Tx (CardanoTx (CardanoEmulatorEraTx))
import Ledger.Tx.CardanoAPI qualified as P
import Ledger.Tx.Internal qualified as P
import Plutus.V1.Ledger.Api qualified as V1 hiding (TxOut (..))
import Plutus.V1.Ledger.Scripts qualified as P

Expand Down Expand Up @@ -261,11 +252,9 @@ validateCardanoTx
-> UTxO EmulatorEra
-> CardanoTx
-> Either P.ValidationErrorInPhase P.ValidationSuccess
validateCardanoTx params slot utxo@(UTxO utxoMap) =
onCardanoTx
(\_ -> error "validateCardanoTx: EmulatorTx is not supported")
(\(CardanoApiEmulatorEraTx tx) -> if Map.null utxoMap then Right Map.empty else
hasValidationErrors params (fromIntegral slot) utxo tx)
validateCardanoTx params slot utxo@(UTxO utxoMap) (CardanoEmulatorEraTx tx) =
if Map.null utxoMap then Right Map.empty else
hasValidationErrors params (fromIntegral slot) utxo tx

getTxExUnitsWithLogs :: Params -> UTxO EmulatorEra -> C.Api.Tx C.Api.BabbageEra -> Either P.ValidationErrorInPhase P.ValidationSuccess
getTxExUnitsWithLogs params utxo (C.Api.ShelleyTx _ tx) =
Expand All @@ -292,41 +281,3 @@ makeTransactionBody params utxo txBodyContent = do
txTmp <- bimap Right (C.Api.makeSignedTransaction []) $ P.makeTransactionBody (Just $ emulatorPParams params) mempty txBodyContent
exUnits <- bimap Left (Map.map snd) $ getTxExUnitsWithLogs params utxo txTmp
first Right $ P.makeTransactionBody (Just $ emulatorPParams params) exUnits txBodyContent

fromPlutusTx
:: Params
-> UTxO EmulatorEra
-> [P.PaymentPubKeyHash]
-> P.Tx
-> Either CardanoLedgerError (C.Tx C.BabbageEra)
fromPlutusTx params utxo requiredSigners tx = do
txBodyContent <- first Right $ P.toCardanoTxBodyContent (pNetworkId params) (emulatorPParams params) requiredSigners tx
C.Api.makeSignedTransaction [] <$> makeTransactionBody params utxo txBodyContent

fromPlutusTxSigned
:: Params
-> UTxO EmulatorEra
-> P.Tx
-> Map.Map P.PaymentPubKey P.PaymentPrivateKey
-> CardanoTx
fromPlutusTxSigned params utxo tx knownPaymentKeys = case fromPlutusTxSigned' params utxo tx knownPaymentKeys of
Left e -> error ("fromPlutusTxSigned: failed to convert " ++ show e)
Right t -> t

fromPlutusTxSigned'
:: Params
-> UTxO EmulatorEra
-> P.Tx
-> Map.Map P.PaymentPubKey P.PaymentPrivateKey
-> Either CardanoLedgerError CardanoTx
fromPlutusTxSigned' params utxo tx knownPaymentKeys =
let
getPrivateKey = fmap P.unPaymentPrivateKey . flip Map.lookup knownPaymentKeys . P.PaymentPubKey
getPublicKeys = Map.keys . P.txSignatures
privateKeys = mapMaybe getPrivateKey $ getPublicKeys tx
signTx txn = foldl' (flip addCardanoTxSignature) txn privateKeys
convertTx t =
flip SomeTx C.BabbageEraInCardanoMode
<$> fromPlutusTx params utxo (P.PaymentPubKeyHash . Crypto.pubKeyHash <$> getPublicKeys t) t
in
signTx . CardanoApiTx <$> convertTx tx
2 changes: 1 addition & 1 deletion cardano-streaming/examples/Example2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ main = do
flip map txs $ \tx@(Cardano.Api.Tx txBody _) ->
let scriptData = Ledger.Tx.CardanoAPI.scriptDataFromCardanoTxBody txBody
txId = Ledger.Tx.CardanoAPI.fromCardanoTxId $ Cardano.Api.getTxId txBody
txOutRefs = Ledger.Tx.CardanoAPI.txOutRefs (workaround (Ledger.Tx.CardanoAPI.SomeTx tx) eim)
txOutRefs = Ledger.Tx.CardanoAPI.txOutRefs (workaround (Ledger.Tx.CardanoAPI.CardanoTx tx) eim)
in Aeson.object
[ "txId" .= txId,
"txOutRefs" .= txOutRefs,
Expand Down
Loading

0 comments on commit b80116b

Please sign in to comment.