@@ -86,14 +86,20 @@ import Cardano.Ledger.Val qualified as L
8686import Ouroboros.Consensus.HardFork.History qualified as Consensus
8787
8888import Control.Monad
89- import Data.Bifunctor (bimap , first , second )
89+ import Data.Bifunctor
90+ ( bimap
91+ , first
92+ , second
93+ )
9094import Data.ByteString.Short (ShortByteString )
9195import Data.Function ((&) )
96+ import Data.List (sortBy )
9297import Data.List qualified as List
9398import Data.Map.Strict (Map )
9499import Data.Map.Strict qualified as Map
95100import Data.Maybe
96101import Data.OSet.Strict qualified as OSet
102+ import Data.Ord (Down (Down ), comparing )
97103import Data.Ratio
98104import Data.Set (Set )
99105import Data.Set qualified as Set
@@ -464,7 +470,7 @@ estimateTransactionKeyWitnessCount
464470 , txUpdateProposal
465471 } =
466472 fromIntegral $
467- length [ () | (_txin, BuildTxWith KeyWitness {}) <- txIns]
473+ sum ( map estimateTxInWitnesses txIns)
468474 + case txInsCollateral of
469475 TxInsCollateral _ txins ->
470476 length txins
@@ -486,6 +492,27 @@ estimateTransactionKeyWitnessCount
486492 TxUpdateProposal _ (UpdateProposal updatePerGenesisKey _) ->
487493 Map. size updatePerGenesisKey
488494 _ -> 0
495+ where
496+ estimateTxInWitnesses :: (TxIn , BuildTxWith BuildTx (Witness WitCtxTxIn era )) -> Int
497+ estimateTxInWitnesses (_, BuildTxWith (KeyWitness _)) = 1
498+ estimateTxInWitnesses (_, BuildTxWith (ScriptWitness _ (SimpleScriptWitness _ (SScript simpleScript)))) = maxWitnessesInSimpleScript simpleScript
499+ estimateTxInWitnesses (_, BuildTxWith (ScriptWitness _ (SimpleScriptWitness _ (SReferenceScript _)))) = 0
500+ estimateTxInWitnesses (_, BuildTxWith (ScriptWitness _ (PlutusScriptWitness {}))) = 0
501+
502+ -- This is a rough conservative estimate of the maximum number of witnesses
503+ -- needed for a simple script to be satisfied. It is conservative because it
504+ -- assumes that each key hash only appears once, and it assumes the worst
505+ -- scenario. A more accurate estimate for the maximum could be computed by
506+ -- keeping track of the possible combinations of key hashes that have
507+ -- potentially already been counted, but that would increase complexity a lot,
508+ -- and it would still be a conservative estimate.
509+ maxWitnessesInSimpleScript :: SimpleScript -> Int
510+ maxWitnessesInSimpleScript (RequireSignature _) = 1
511+ maxWitnessesInSimpleScript (RequireTimeBefore _) = 0
512+ maxWitnessesInSimpleScript (RequireTimeAfter _) = 0
513+ maxWitnessesInSimpleScript (RequireAllOf simpleScripts) = sum $ map maxWitnessesInSimpleScript simpleScripts
514+ maxWitnessesInSimpleScript (RequireAnyOf simpleScripts) = maximum $ map maxWitnessesInSimpleScript simpleScripts
515+ maxWitnessesInSimpleScript (RequireMOf n simpleScripts) = sum $ take n $ sortBy (comparing Down ) (map maxWitnessesInSimpleScript simpleScripts)
489516
490517-- ----------------------------------------------------------------------------
491518-- Script execution units
@@ -841,6 +868,7 @@ data TxBodyErrorAutoBalance era
841868 -- input ada.
842869 TxBodyErrorAdaBalanceTooSmall
843870 -- \^ Offending TxOut
871+
844872 TxOutInAnyEra
845873 -- ^ Minimum UTxO
846874 L. Coin
@@ -857,6 +885,7 @@ data TxBodyErrorAutoBalance era
857885 | -- | The minimum spendable UTxO threshold has not been met.
858886 TxBodyErrorMinUTxONotMet
859887 -- \^ Offending TxOut
888+
860889 TxOutInAnyEra
861890 -- ^ Minimum UTxO
862891 L. Coin
0 commit comments