55{-# LANGUAGE GADTs #-}
66{-# LANGUAGE LambdaCase #-}
77{-# LANGUAGE MultiParamTypeClasses #-}
8+ {-# LANGUAGE NumericUnderscores #-}
89{-# LANGUAGE ScopedTypeVariables #-}
910{-# LANGUAGE TypeApplications #-}
1011{-# LANGUAGE TypeFamilies #-}
@@ -28,6 +29,7 @@ module Ouroboros.Consensus.Shelley.Eras (
2829 , StandardMary
2930 , StandardShelley
3031 -- * Shelley-based era
32+ , BabbageTxDict (.. )
3133 , ConwayEraGovDict (.. )
3234 , ShelleyBasedEra (.. )
3335 , WrapTx (.. )
@@ -45,6 +47,7 @@ import Cardano.Ledger.Alonzo (AlonzoEra)
4547import qualified Cardano.Ledger.Alonzo.Rules as Alonzo
4648import qualified Cardano.Ledger.Alonzo.Translation as Alonzo
4749import qualified Cardano.Ledger.Alonzo.Tx as Alonzo
50+ import qualified Cardano.Ledger.Api as SL
4851import qualified Cardano.Ledger.Api.Era as L
4952import Cardano.Ledger.Babbage (BabbageEra )
5053import qualified Cardano.Ledger.Babbage.Rules as Babbage
@@ -57,6 +60,8 @@ import qualified Cardano.Ledger.Conway.Rules as Conway
5760import qualified Cardano.Ledger.Conway.Rules as SL
5861 (ConwayLedgerPredFailure (.. ))
5962import qualified Cardano.Ledger.Conway.Translation as Conway
63+ import qualified Cardano.Ledger.Conway.Tx as SL
64+ import qualified Cardano.Ledger.Conway.UTxO as SL
6065import Cardano.Ledger.Core as Core
6166import Cardano.Ledger.Crypto (StandardCrypto )
6267import Cardano.Ledger.Keys (DSignable , Hash )
@@ -68,11 +73,13 @@ import Cardano.Ledger.Shelley.Core as Core
6873import qualified Cardano.Ledger.Shelley.LedgerState as SL
6974import qualified Cardano.Ledger.Shelley.Rules as SL
7075import qualified Cardano.Ledger.Shelley.Transition as SL
76+ import qualified Cardano.Ledger.Val as SL
7177import qualified Cardano.Protocol.TPraos.API as SL
7278import Control.Monad.Except
7379import Control.State.Transition (PredicateFailure )
7480import Data.Data (Proxy (Proxy ))
7581import Data.List.NonEmpty (NonEmpty ((:|) ))
82+ import Lens.Micro ((^.) )
7683import NoThunks.Class (NoThunks )
7784import Ouroboros.Consensus.Ledger.SupportsMempool
7885 (WhetherToIntervene (.. ))
@@ -162,6 +169,16 @@ class ( Core.EraSegWits era
162169 -- | Whether the era has an instance of 'CG.ConwayEraGov'
163170 getConwayEraGovDict :: proxy era -> Maybe (ConwayEraGovDict era )
164171
172+ getBabbageTxDict :: proxy era -> Maybe (BabbageTxDict era )
173+
174+ data BabbageTxDict era where
175+ BabbageTxDict ::
176+ SL. BabbageEraTxBody era
177+ => (Integer -> Integer -> SL. ApplyTxError era )
178+ -- ^ Construct an arbitrary ledger error with two integers as its
179+ -- payload.
180+ -> BabbageTxDict era
181+
165182data ConwayEraGovDict era where
166183 ConwayEraGovDict :: CG. ConwayEraGov era => ConwayEraGovDict era
167184
@@ -172,7 +189,7 @@ isBeforeConway _ =
172189-- | The default implementation of 'applyShelleyBasedTx', a thin wrapper around
173190-- 'SL.applyTx'
174191defaultApplyShelleyBasedTx ::
175- ShelleyBasedEra era
192+ forall era . ShelleyBasedEra era
176193 => SL. Globals
177194 -> SL. LedgerEnv era
178195 -> SL. LedgerState era
@@ -183,12 +200,51 @@ defaultApplyShelleyBasedTx ::
183200 ( SL. LedgerState era
184201 , SL. Validated (Core. Tx era )
185202 )
186- defaultApplyShelleyBasedTx globals ledgerEnv mempoolState _wti tx =
203+ defaultApplyShelleyBasedTx globals ledgerEnv mempoolState _wti tx = do
204+ refScriptPredicate
187205 SL. applyTx
188206 globals
189207 ledgerEnv
190208 mempoolState
191209 tx
210+ where
211+ refScriptPredicate = case getBabbageTxDict (Proxy @ era ) of
212+ Nothing -> pure ()
213+ Just (BabbageTxDict mkError)
214+ -- Reject it if it has more than 100 kibibytes of ref script.
215+ | refScriptsSize > totalRefScriptsSizeLimit
216+ -> throwError $ mkError
217+ -- As we are reusing an existing error message, we add a large
218+ -- number to make users running into this are productively irritated
219+ -- and post this error message somewhere where they can receive
220+ -- help/context.
221+ (toInteger refScriptsSize + 1_000_000_000 )
222+ (toInteger totalRefScriptsSizeLimit + 1_000_000_000 )
223+ -- Reject it if it has more than 50 kibibytes of ref script and does not
224+ -- satisfy an additional fee as calculated in the table below.
225+ | refScriptsSize > freeOfChargeRefScriptsBytes
226+ , actualFee < expectedFee
227+ -> throwError $ mkError
228+ -- See above for why we add a large constant.
229+ (SL. unCoin actualFee + 100_000_000 )
230+ (SL. unCoin expectedFee + 100_000_000 )
231+ | otherwise -> pure ()
232+ where
233+ totalRefScriptsSizeLimit :: Int
234+ totalRefScriptsSizeLimit = 100 * 1024
235+
236+ freeOfChargeRefScriptsBytes :: Int
237+ freeOfChargeRefScriptsBytes = 50 * 1024
238+
239+ actualFee = tx ^. SL. bodyTxL . SL. feeTxBodyL
240+ expectedFee = minFee SL. <+> refScriptsFee
241+ where
242+ minFee = SL. getMinFeeTx (SL. ledgerPp ledgerEnv) tx 0
243+ refScriptsFee = SL. tierRefScriptFee 1.2 25600 15 refScriptsSize
244+
245+ refScriptsSize = SL. txNonDistinctRefScriptsSize utxo tx
246+
247+ utxo = SL. utxosUtxo . SL. lsUTxOState $ mempoolState
192248
193249defaultGetConwayEraGovDict :: proxy era -> Maybe (ConwayEraGovDict era )
194250defaultGetConwayEraGovDict _ = Nothing
@@ -199,34 +255,52 @@ instance (SL.PraosCrypto c, DSignable c (Hash c EraIndependentTxBody))
199255
200256 getConwayEraGovDict = defaultGetConwayEraGovDict
201257
258+ getBabbageTxDict _ = Nothing
259+
202260instance (SL. PraosCrypto c , DSignable c (Hash c EraIndependentTxBody ))
203261 => ShelleyBasedEra (AllegraEra c ) where
204262 applyShelleyBasedTx = defaultApplyShelleyBasedTx
205263
206264 getConwayEraGovDict = defaultGetConwayEraGovDict
207265
266+ getBabbageTxDict _ = Nothing
267+
208268instance (SL. PraosCrypto c , DSignable c (Hash c EraIndependentTxBody ))
209269 => ShelleyBasedEra (MaryEra c ) where
210270 applyShelleyBasedTx = defaultApplyShelleyBasedTx
211271
212272 getConwayEraGovDict = defaultGetConwayEraGovDict
213273
274+ getBabbageTxDict _ = Nothing
275+
214276instance (SL. PraosCrypto c , DSignable c (Hash c EraIndependentTxBody ))
215277 => ShelleyBasedEra (AlonzoEra c ) where
216278 applyShelleyBasedTx = applyAlonzoBasedTx
217279
218280 getConwayEraGovDict = defaultGetConwayEraGovDict
219281
282+ getBabbageTxDict _ = Nothing
283+
220284instance (Praos. PraosCrypto c ) => ShelleyBasedEra (BabbageEra c ) where
221285 applyShelleyBasedTx = applyAlonzoBasedTx
222286
223287 getConwayEraGovDict = defaultGetConwayEraGovDict
224288
289+ getBabbageTxDict _ = Just $ BabbageTxDict $ \ a b ->
290+ SL. ApplyTxError
291+ $ pure
292+ $ SL. UtxowFailure
293+ $ Babbage. UtxoFailure
294+ $ Babbage. AlonzoInBabbageUtxoPredFailure
295+ $ Alonzo. MaxTxSizeUTxO a b
296+
225297instance (Praos. PraosCrypto c ) => ShelleyBasedEra (ConwayEra c ) where
226298 applyShelleyBasedTx = applyAlonzoBasedTx
227299
228300 getConwayEraGovDict _ = Just ConwayEraGovDict
229301
302+ getBabbageTxDict _ = Nothing
303+
230304applyAlonzoBasedTx :: forall era .
231305 ( ShelleyBasedEra era ,
232306 SupportsTwoPhaseValidation era ,
0 commit comments