diff --git a/doc/cost-models/keeppolicies/index.html b/doc/cost-models/keeppolicies/index.html new file mode 100644 index 00000000000..a228d967b20 --- /dev/null +++ b/doc/cost-models/keeppolicies/index.html @@ -0,0 +1,120 @@ + + +
+ + +
+ Interactive 3D visualization of benchmark data and the fitted cost model for the
+ KeepPolicies builtin. The x-axis is the length of the policy list, the y-axis the total size
+ of the Value, and the z-axis execution time. Every benchmark point appears twice at the
+ same place on the floor: as a blue dot for what it measured, and as a red cross for what the model
+ charges for it. Where a cross sits above its dot the model overcharges that input; for a few of
+ the largest inputs the fitted plane sits below the measurement. The sizes are on log
+ axes because they are sampled log-uniformly, which leaves out the few points at p = 0 or n = 0.
+
${name}: not available
`; + const c = model.coefficients; + const ratios = []; + let undercharged = 0; + let worstShortfall = 0; + let worstRatio = 1; + for (const d of points) { + const predicted = modelCharge(model, d.args, overhead); + if (predicted === null) return `${name}: not evaluable (${model.modelType})
`; + ratios.push(predicted / d.time); + if (predicted < d.time) { + undercharged += 1; + worstShortfall = Math.max(worstShortfall, d.time - predicted); + worstRatio = Math.min(worstRatio, predicted / d.time); + } + } + const fmt = v => v.toLocaleString('en-US', { maximumFractionDigits: 0 }); + return ` +${name}
+Value; linear in the number ' +
'of policies. (2D visualization: Policy Count vs Time)'],
+ ['keeppolicies', 'KeepPolicies',
+ 'Retains only the listed currencies of a Plutus Value. ' +
+ '(3D visualization: List Length \u00d7 Value Size \u00d7 Time)'],
['listtoarray', 'ListToArray',
'Converts a Plutus list to an array representation. ' +
'(2D visualization: List Size vs Time)'],
diff --git a/plutus-core/changelog.d/20260828_144508_yuriy.lazaryev_issue_2310_keep_policies_costing.md b/plutus-core/changelog.d/20260828_144508_yuriy.lazaryev_issue_2310_keep_policies_costing.md
new file mode 100644
index 00000000000..04249bee422
--- /dev/null
+++ b/plutus-core/changelog.d/20260828_144508_yuriy.lazaryev_issue_2310_keep_policies_costing.md
@@ -0,0 +1,3 @@
+### Added
+
+- A cost model for the `keepPolicies` builtin ([CIP-0168](https://cips.cardano.org/cip/CIP-0168)), with five new cost model parameters. Linear in the length of the policy list and in the total size of the `Value`.
diff --git a/plutus-core/cost-model/budgeting-bench/Benchmarks/Values.hs b/plutus-core/cost-model/budgeting-bench/Benchmarks/Values.hs
index 9c574ba6cc3..756a7f0fec4 100644
--- a/plutus-core/cost-model/budgeting-bench/Benchmarks/Values.hs
+++ b/plutus-core/cost-model/budgeting-bench/Benchmarks/Values.hs
@@ -24,6 +24,7 @@ import PlutusCore
( DefaultFun
( AssetCount
, InsertCoin
+ , KeepPolicies
, LookupCoin
, Policies
, ScaleValue
@@ -70,6 +71,7 @@ makeBenchmarks gen =
, scaleValueBenchmark gen
, assetCountBenchmark gen
, policiesBenchmark gen
+ , keepPoliciesBenchmark gen
]
----------------------------------------------------------------------------------------------------
@@ -414,17 +416,11 @@ policiesBenchmark :: StdGen -> Benchmark
policiesBenchmark gen =
createOneTermBuiltinBenchWithWrapper_NF ValueOuterSize Policies [] (runBenchGen gen policiesArgs)
where
- -- 40k pairs: safely above the largest `Value` a script can build within the
- -- CPU budget (roughly 14k `insertCoin` applications).
- maxTotalSize :: Int
- maxTotalSize = Value.valueDataMaxSize
-
policiesArgs :: StatefulGen g m => g -> m [Value]
policiesArgs g = do
randoms <- replicateM 100 do
- u <- uniformRM (0 :: Double, log (fromIntegral maxTotalSize)) g
- let numPolicies = min maxTotalSize (max 1 (round (exp u)))
- numTokens <- uniformRM (1, maxTotalSize `div` numPolicies) g
+ numPolicies <- logUniform g maxValueTotalSize
+ numTokens <- uniformRM (1, maxValueTotalSize `div` numPolicies) g
generate g numPolicies numTokens
stacks <-
sequence
@@ -435,14 +431,122 @@ policiesBenchmark gen =
pure $ Value.empty : randoms <> stacks
generate :: StatefulGen g m => g -> Int -> Int -> m Value
- generate g numPolicies numTokens = do
- policyIds <- replicateM numPolicies (generateKey g)
- tokenNames <- replicateM numTokens (generateKey g)
- pure $ buildValue policyIds tokenNames (mkQuantity 1)
+ generate g numPolicies numTokens = snd <$> generateValueWithPolicyIds g numPolicies numTokens
+
+-- KeepPolicies ------------------------------------------------------------------------------------
+
+{- Note [Benchmarking keepPolicies]
+`keepPolicies` pays for three things: building a `Set` from the list, walking the outer
+map to drop what the list did not name, and recomputing the caches the `Value` carries
+over what is left. Only the first is proportional to the list length, and the last is
+proportional to the size of the result, which the cost model never sees. It sees the list
+length and the total size of the argument.
+
+Every point of `randomSizes`, the hundred with both sizes drawn independently on a log
+scale, is built to make those two agree: the list names every policy the `Value` has, so
+nothing is dropped and the result is the whole argument. The pairs are packed into as few
+policies as the list can cover, and the rest of the list is ids the `Value` does not have.
+On an input where half the policies get dropped the same two sizes would buy half the
+work, and a fit trained on those would undercharge a script that names them all. The log
+scale is what puts the sizes that occur on chain in the sample and not only the large ones.
+
+`shapeSweep` and `hitSweep` hold both sizes fixed and vary what the model cannot see: how
+many policies hold the pairs, and how much of the list hits. They therefore look like
+repeated measurements of one point, and a model that cannot tell those inputs apart shows
+it as vertical spread there. For `keepPolicies` that spread is widest at short lists and
+narrows as the list grows, because building the `Set` comes to dominate and the shape of
+the `Value` barely enters.
+
+`listOnly` hands the builtin an empty `Value`, which it returns from before it looks at
+the list. Those points are the control on the rig: had criterion floated the list work out
+of the measured loop, a list against an empty `Value` would cost what it costs against a
+full one. It costs a small fraction of that, so the list work is inside the loop where the
+measurement can see it. `models.R` drops these points from the fit, since nothing there is
+proportional to either size.
+-}
+
+keepPoliciesBenchmark :: StdGen -> Benchmark
+keepPoliciesBenchmark gen =
+ createTwoTermBuiltinBenchElementwise KeepPolicies [] (runBenchGen gen keepPoliciesArgs)
+
+-- | See Note [Benchmarking keepPolicies]
+keepPoliciesArgs :: forall g m. StatefulGen g m => g -> m [([ByteString], Value)]
+keepPoliciesArgs g = do
+ -- Both sizes drawn independently on a log scale, each point the costliest of its sizes.
+ randomSizes <- replicateM 100 do
+ totalSize <- logUniform g maxValueTotalSize
+ listLen <- logUniform g maxValueTotalSize
+ worstCase totalSize listLen
+ -- One `Value`, growing list.
+ listSweep <- traverse (worstCase 1000) [1000, 3000, 10_000, maxValueTotalSize]
+ -- One total size, policy counts from one to one per pair. Run against a short list as
+ -- well as a long one, because a long list swamps the `Value` term.
+ shapeSweep <-
+ sequence
+ [ reaching numPolicies (10_000 `div` numPolicies) listLen
+ | listLen <- [100, 10_000]
+ , numPolicies <- [1, 10, 100, 1000, 10_000]
+ ]
+ -- One pair of sizes, list hits from none to all.
+ hitSweep <- traverse (hitting 10_000) [0, 2500, 5000, 7500, 10_000]
+ -- The list on its own, including the empty list.
+ listOnly <-
+ traverse
+ (\listLen -> (,Value.empty) <$> paddedList [] listLen)
+ [0, 10, 100, 1000, 10_000, maxValueTotalSize]
+ -- Lovelace: the empty bytestring is a valid policy id, and `policySet` keeps it.
+ lovelace <- do
+ tokenName <- generateKey g
+ pure ([BS.empty], buildValue [emptyKey] [tokenName] (mkQuantity 1))
+ pure $ randomSizes <> listSweep <> shapeSweep <> hitSweep <> listOnly <> [lovelace]
+ where
+ -- The costliest input of its sizes: the pairs packed into as few policies as the list
+ -- covers, so that the list names every one of them.
+ worstCase :: Int -> Int -> m ([ByteString], Value)
+ worstCase totalSize listLen =
+ let numPolicies = max 1 (min listLen totalSize)
+ in reaching numPolicies (max 1 (totalSize `div` numPolicies)) listLen
+
+ -- A `Value` of the given shape, and a list of the given length that names as much of
+ -- it as it can.
+ reaching :: Int -> Int -> Int -> m ([ByteString], Value)
+ reaching numPolicies numTokens listLen = do
+ (policyIds, value) <- generateValueWithPolicyIds g numPolicies numTokens
+ ps <- paddedList policyIds listLen
+ pure (ps, value)
+
+ -- Every policy id the list has room for, padded to the given length with ids that are
+ -- absent from the `Value`.
+ paddedList :: [K] -> Int -> m [ByteString]
+ paddedList policyIds listLen = do
+ let hits = take listLen policyIds
+ misses <- replicateM (listLen - length hits) (generateKey g)
+ pure $ Value.unK <$> (hits <> misses)
+
+ -- A flat `Value` of @totalSize@ pairs, and a list of the same length hitting @numHits@
+ -- of its policies.
+ hitting :: Int -> Int -> m ([ByteString], Value)
+ hitting totalSize numHits = do
+ (policyIds, value) <- generateValueWithPolicyIds g totalSize 1
+ ps <- paddedList (take numHits policyIds) totalSize
+ pure (ps, value)
----------------------------------------------------------------------------------------------------
-- Value Generators --------------------------------------------------------------------------------
+{-| 40k pairs: safely above the largest `Value` a script can build within the CPU budget
+(roughly 14k `insertCoin` applications). -}
+maxValueTotalSize :: Int
+maxValueTotalSize = Value.valueDataMaxSize
+
+{-| A `Value` of @numPolicies@ policies holding @numTokens@ tokens each, together with its
+policy ids. -}
+generateValueWithPolicyIds :: StatefulGen g m => g -> Int -> Int -> m ([K], Value)
+generateValueWithPolicyIds g numPolicies numTokens = do
+ policyIds <- replicateM numPolicies (generateKey g)
+ tokenNames <- replicateM numTokens (generateKey g)
+ pure (policyIds, buildValue policyIds tokenNames (mkQuantity 1))
+
{-| Build Value from given policy IDs, token names and and a single quantity
for each (policy ID, token name) pair.
Uses 'unsafeFromList' because 'generateKey' may generate duplicate keys, although
@@ -545,6 +649,20 @@ generateConstrainedValue numPolicies tokensPerPolicy g = do
----------------------------------------------------------------------------------------------------
-- Other Generators --------------------------------------------------------------------------------
+{-| Sample @[1, hi]@ uniformly on a log scale, so that every decade gets a similar number of
+points. Sampling the count itself would put almost every point above 1000, leaving the sizes
+that occur on chain unmeasured. -}
+logUniform :: StatefulGen g m => g -> Int -> m Int
+logUniform g hi = do
+ u <- uniformRM (0 :: Double, log (fromIntegral hi)) g
+ pure $ min hi (max 1 (round (exp u)))
+
+-- | The policy id of lovelace.
+emptyKey :: K
+emptyKey = case Value.k BS.empty of
+ Just key -> key
+ Nothing -> error "Internal error: the empty bytestring should always be a valid key"
+
{-| Generate a worst-case key for benchmarking ByteString comparisons.
ByteString comparison is lexicographic and short-circuits on the first differing byte.
diff --git a/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs b/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs
index eac826dd397..47bf0a80e7e 100644
--- a/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs
+++ b/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs
@@ -387,6 +387,11 @@ builtinMemoryModels =
-- `Value`, so only the list spine is new, at three words per cons cell (as for
-- `multiIndexArray`). The size measure is the number of policies (`ValueOuterSize`).
paramPolicies = Id $ ModelOneArgumentLinearInX $ OneVariableLinearFunction 4 3
+ , -- The result shares the inner maps of the `Value` wholesale and its policy ids by
+ -- pointer, so the only new structure is the outer map spine, at six words per `Bin`
+ -- node, of which the result holds at most one per pair. The intercept covers the
+ -- `Value` closure, the `IntMap` of inner sizes and the two `Tip`s.
+ paramKeepPolicies = Id $ ModelTwoArgumentsLinearInY $ OneVariableLinearFunction 32 6
}
where
identityFunction = OneVariableLinearFunction 0 1
diff --git a/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs b/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs
index fe1a5ef834f..40cc7ea4315 100644
--- a/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs
+++ b/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs
@@ -156,6 +156,7 @@ builtinCostModelNames =
, paramMultiIndexArray = "multiIndexArrayModel"
, paramAssetCount = "assetCountModel"
, paramPolicies = "policiesModel"
+ , paramKeepPolicies = "keepPoliciesModel"
}
{-| Loads the models from R.
@@ -314,6 +315,7 @@ createBuiltinCostModel bmfile rfile = do
paramMultiIndexArray <- getParams readCF2 paramMultiIndexArray
paramAssetCount <- getParams readCF1 paramAssetCount
paramPolicies <- getParams readCF1 paramPolicies
+ paramKeepPolicies <- getParams readCF2 paramKeepPolicies
pure $ BuiltinCostModelBase {..}
diff --git a/plutus-core/cost-model/data/benching-conway.csv b/plutus-core/cost-model/data/benching-conway.csv
index 1a614e5ffbe..a241e03ea96 100644
--- a/plutus-core/cost-model/data/benching-conway.csv
+++ b/plutus-core/cost-model/data/benching-conway.csv
@@ -14993,3 +14993,129 @@ Policies/5000,7.189463631358013e-5,7.156936535249899e-5,7.233595900980706e-5,1.2
Policies/5000,6.977548091312812e-5,6.943112384678736e-5,7.019367856507662e-5,1.2159543852228183e-6,9.90682373757167e-7,1.5841499768829372e-6
Policies/5000,7.12030144189684e-5,7.071833317524066e-5,7.162200396101847e-5,1.484040635252136e-6,1.1899313792295193e-6,1.8877811906884912e-6
Policies/5000,6.948013194114908e-5,6.91854455461997e-5,6.976571016174288e-5,9.917311481076059e-7,8.296841366362688e-7,1.2065254642363083e-6
+KeepPolicies/12/2016,8.34452423230735e-6,8.311440108636333e-6,8.356198257094977e-6,6.549637851043791e-8,2.6154538666287462e-8,1.2803004743756804e-7
+KeepPolicies/1682/2,4.3460923809998664e-4,4.344533293464378e-4,4.348154106649132e-4,6.062042986473072e-7,4.882792391789208e-7,7.578226879388894e-7
+KeepPolicies/2248/7,6.03307042691011e-4,6.031638429801315e-4,6.035007885207912e-4,5.450170373800897e-7,4.035813703515201e-7,7.80100900717365e-7
+KeepPolicies/13319/1341,5.349670033707519e-3,5.346318671606141e-3,5.355008837304453e-3,1.2931311073034712e-5,8.401181398989266e-6,1.9960012941799645e-5
+KeepPolicies/91/16,1.3549082747626022e-5,1.3544294501465235e-5,1.3555384031830399e-5,1.8622673558593624e-8,1.3784628796940805e-8,2.9287389896924162e-8
+KeepPolicies/22/8778,3.0599488095687494e-5,3.045422916551157e-5,3.073888584488617e-5,5.107799301593917e-7,4.183006848062761e-7,6.398071711792458e-7
+KeepPolicies/198/1,3.135437274559374e-5,3.134344302090515e-5,3.136542946183127e-5,3.712915283679371e-8,3.089700833448893e-8,4.710389050393016e-8
+KeepPolicies/226/1582,4.719424582600942e-5,4.717677448045436e-5,4.721545321868843e-5,6.744330939190366e-8,4.978294796660503e-8,9.949096584140667e-8
+KeepPolicies/5/35,1.6083128141315506e-6,1.6068920900866857e-6,1.6100745484145253e-6,5.1983876510946296e-9,4.01962713057327e-9,6.9003540623143065e-9
+KeepPolicies/1089/2,2.5895907565909104e-4,2.5885339299062786e-4,2.591849293620828e-4,5.084194452143421e-7,1.9266889356460098e-7,8.487663998886138e-7
+KeepPolicies/17207/15,7.6261801596576645e-3,7.6227043401021185e-3,7.629446202225316e-3,9.608265798458434e-6,7.981396596525845e-6,1.2709167487182126e-5
+KeepPolicies/12382/174,4.828524239513516e-3,4.824503611444812e-3,4.831963235796406e-3,1.1705936721710128e-5,8.786799732217193e-6,1.5720433441823495e-5
+KeepPolicies/5/5,1.4814424992788024e-6,1.4801861248136993e-6,1.4827478643296807e-6,4.212291499480468e-9,3.40842639086626e-9,5.354398305902664e-9
+KeepPolicies/342/1710,7.754375206124261e-5,7.712681195643798e-5,7.792581155626945e-5,1.3084890009696134e-6,1.2391276350370044e-6,1.3638010380689058e-6
+KeepPolicies/25194/4243,1.1893887263605159e-2,1.1816906087855301e-2,1.2193877306084126e-2,3.7933756508274025e-4,1.5224176236337361e-5,7.776886740126747e-4
+KeepPolicies/40/80,6.0682133891193e-6,6.037981272718933e-6,6.104360579988268e-6,1.0888208707387058e-7,9.095349336514853e-8,1.1914467320952174e-7
+KeepPolicies/228/36024,1.493275500890498e-4,1.4920048474337768e-4,1.4946932397854606e-4,4.4866928481012307e-7,2.743154883620133e-7,7.499080708399551e-7
+KeepPolicies/3244/10,9.749434345112689e-4,9.743183790244611e-4,9.758747052880327e-4,2.5169451312134653e-6,1.811057031525325e-6,3.629924565802736e-6
+KeepPolicies/954/44,2.225418198841045e-4,2.2248641160858788e-4,2.226176873189782e-4,2.1541038112498643e-7,1.6704560337523392e-7,3.22334874785056e-7
+KeepPolicies/16851/118,7.552255522092183e-3,7.54726140861873e-3,7.558495619832893e-3,1.6554027466884027e-5,1.3168567096557539e-5,2.0485290350898528e-5
+KeepPolicies/8137/1,2.840765676083742e-3,2.8392230557021136e-3,2.8428362679642637e-3,5.972319408854604e-6,5.146035636159394e-6,7.342870562231395e-6
+KeepPolicies/24/4,3.2287089420462223e-6,3.2092020993419694e-6,3.2550879156058364e-6,7.399863577922531e-8,6.06212130400683e-8,8.271421438349691e-8
+KeepPolicies/39/2418,1.3456235722918716e-5,1.3443213165890612e-5,1.3470453759723634e-5,4.4499403860609125e-8,3.45433701815779e-8,5.887217787107002e-8
+KeepPolicies/33926/2512,1.8749763261834248e-2,1.8249655181692453e-2,1.913648148808545e-2,1.058843735995058e-3,7.65458667428421e-4,1.4175748395950987e-3
+KeepPolicies/201/1005,4.08762344784375e-5,4.0848755521905284e-5,4.0908472301222595e-5,9.888074242171163e-8,7.682849980365556e-8,1.3769696710747835e-7
+KeepPolicies/254/1270,5.298297426539896e-5,5.291498488204394e-5,5.3038642914978236e-5,2.0252596858665239e-7,1.7894618434569426e-7,2.3443087163969852e-7
+KeepPolicies/150/3,2.3093215968825676e-5,2.3056483266773117e-5,2.313391441396461e-5,1.3183024016149674e-7,1.1392369925837756e-7,1.4237343010393732e-7
+KeepPolicies/1007/283,2.480355901411246e-4,2.474984651497883e-4,2.485236581249494e-4,1.7487833078669998e-6,1.495126026223553e-6,2.009371891343252e-6
+KeepPolicies/3787/30296,1.3327879256018714e-3,1.3317224760689653e-3,1.335532460506836e-3,5.333146236836567e-6,2.3269201489781214e-6,9.054168445142165e-6
+KeepPolicies/685/24,1.4568773193484062e-4,1.4563792606226905e-4,1.458379195318242e-4,2.6154266573904533e-7,1.347541696445606e-7,5.161416677052253e-7
+KeepPolicies/62/2046,1.65177886803625e-5,1.6510056313300373e-5,1.6527541995192453e-5,2.837542611517423e-8,2.3774367656319283e-8,3.370534818779589e-8
+KeepPolicies/60/13260,4.742279163706607e-5,4.7275425386212756e-5,4.757895432500401e-5,5.472618647048666e-7,4.640317013857647e-7,6.543415903536758e-7
+KeepPolicies/18208/2407,8.240005647875021e-3,8.220167148545891e-3,8.259836800033428e-3,5.5436999064845e-5,4.814107941776064e-5,6.482519529254937e-5
+KeepPolicies/594/4,1.2076255012278089e-4,1.2070813097959217e-4,1.2092488891192438e-4,3.318365038287857e-7,6.326773064622122e-8,6.323482648712004e-7
+KeepPolicies/1308/133,3.209523707470092e-4,3.208064547057704e-4,3.2145682923059946e-4,7.709104173280084e-7,2.982470237736029e-7,1.6477993999810816e-6
+KeepPolicies/918/33966,3.674375003910061e-4,3.6718019238516237e-4,3.678659169820835e-4,1.0936497308072537e-6,7.608940294095604e-7,1.8237333328947571e-6
+KeepPolicies/37598/8987,2.14741729368081e-2,2.10485496893098e-2,2.2184953598807695e-2,1.250158516500455e-3,9.896701666401008e-4,1.7500943543296487e-3
+KeepPolicies/31224/2101,1.603668796278421e-2,1.5924305496024756e-2,1.6220284627692802e-2,3.426979003116951e-4,2.1806543330899768e-4,6.206122563591985e-4
+KeepPolicies/5449/13,1.879184674901998e-3,1.8783087808791684e-3,1.880180585085764e-3,3.0821860736487477e-6,2.692673228025177e-6,3.6974287820076093e-6
+KeepPolicies/8/1,1.6684795750137093e-6,1.6668205171984368e-6,1.6700007296863363e-6,5.384711454409226e-9,4.770628281340246e-9,6.1350624520992e-9
+KeepPolicies/14/14,2.4077531312995663e-6,2.4065393425197495e-6,2.409538370001584e-6,4.898762810928834e-9,3.8062470257763976e-9,6.5259853102246764e-9
+KeepPolicies/10204/43,3.796431786675184e-3,3.794113411475345e-3,3.80230169649601e-3,1.1782664048061357e-5,6.307620186084471e-6,2.1787841074821108e-5
+KeepPolicies/10/8350,2.720832211115342e-5,2.7080120929591304e-5,2.7320294781648828e-5,4.061418190670462e-7,3.3784222193882784e-7,5.997681984069162e-7
+KeepPolicies/9547/25,3.6433034862251353e-3,3.6393423378762073e-3,3.6483522240930793e-3,1.5122074545705697e-5,1.1257678382938116e-5,2.3067473797104728e-5
+KeepPolicies/1261/970,3.328532996386912e-4,3.327787015758768e-4,3.329390542909821e-4,2.633574993789877e-7,2.112223441762704e-7,3.3073232220425766e-7
+KeepPolicies/16694/3,7.070018751369125e-3,7.064337007047928e-3,7.082346661701785e-3,2.3147900541281882e-5,1.2255080231103777e-5,4.2369789138755996e-5
+KeepPolicies/1/8096,3.816788998343174e-5,3.809106663981347e-5,3.819641097310257e-5,1.4894058320375643e-7,7.376851538650934e-8,2.809590425892531e-7
+KeepPolicies/20209/7929,9.323766820062638e-3,9.315545633940301e-3,9.339464139439922e-3,3.0889406699882534e-5,1.593501747822226e-5,5.8323906566951693e-5
+KeepPolicies/85/2,1.1393419519714661e-5,1.138179584727921e-5,1.1403681888623612e-5,3.567225875919743e-8,3.168936310776552e-8,4.0198475534360737e-8
+KeepPolicies/21/63,3.436028919500751e-6,3.4322947276478504e-6,3.45040124173042e-6,2.0937619092906914e-8,6.677860636330805e-9,4.25282011375531e-8
+KeepPolicies/300/28800,1.5393304417138373e-4,1.5366931727800722e-4,1.5408319996627263e-4,6.455124707910082e-7,4.467214821878464e-7,9.426471452736311e-7
+KeepPolicies/30314/3631,1.6137060650064754e-2,1.5739029607137186e-2,1.6433450089596246e-2,8.601764460514637e-4,6.392026750795067e-4,1.0234706031415648e-3
+KeepPolicies/7343/5,2.6963895509172844e-3,2.6940533502990533e-3,2.6986101793825554e-3,7.836068522893435e-6,6.635310793673531e-6,9.553417264391918e-6
+KeepPolicies/447/3576,1.1182142254986294e-4,1.1168868484110851e-4,1.1207228088358934e-4,5.930200299433338e-7,2.876951473435506e-7,1.0911966422111278e-6
+KeepPolicies/43/42,6.2789573031022125e-6,6.274135535297077e-6,6.284923910582627e-6,1.8025558672194792e-8,1.4389162310047203e-8,2.3268117899523858e-8
+KeepPolicies/3/1,1.295222120085136e-6,1.2937941092438029e-6,1.2990342833254465e-6,7.462677871152894e-9,3.2788836137941475e-9,1.4551415597298707e-8
+KeepPolicies/2915/5,8.57045319070747e-4,8.5682134510172e-4,8.572738101652811e-4,7.595043332144929e-7,5.661698802330357e-7,1.1888057242804937e-6
+KeepPolicies/1754/751,4.8387279707086357e-4,4.8351113855941616e-4,4.8418887123222144e-4,1.151677839070935e-6,1.0533977187271131e-6,1.2725161107534052e-6
+KeepPolicies/2/26,1.3800409012093964e-6,1.3776640941696782e-6,1.3822158270848647e-6,7.680344736308382e-9,6.451868004244626e-9,9.054696406083068e-9
+KeepPolicies/407/13,7.625968832315485e-5,7.624256401947775e-5,7.628125707030219e-5,6.131428515529124e-8,4.6899128185226845e-8,8.17607529742969e-8
+KeepPolicies/764/10,1.6362538174420976e-4,1.6359338679520298e-4,1.636802770977125e-4,1.4747556269903103e-7,7.245030249466167e-8,2.3418973513324133e-7
+KeepPolicies/107/17869,7.395673250001695e-5,7.362432195690697e-5,7.419048969159555e-5,9.074654559546643e-7,7.323055542420074e-7,1.1167576360199357e-6
+KeepPolicies/12/24,2.2660843672914076e-6,2.264423294488468e-6,2.2679267741367724e-6,5.713068761943689e-9,5.083785465046485e-9,6.70420702600026e-9
+KeepPolicies/34291/3345,1.892731130587675e-2,1.8460394159001015e-2,1.9216963852787275e-2,8.832799386535062e-4,5.757165474732595e-4,1.1108195509366094e-3
+KeepPolicies/34/14824,4.8220014134668305e-5,4.789960624648113e-5,4.847622648200584e-5,9.084725350113807e-7,7.207341655231266e-7,1.0820812410926212e-6
+KeepPolicies/100/1,1.3727362382073472e-5,1.372051637534225e-5,1.3732169260510325e-5,1.8879902951859488e-8,1.4483273776884123e-8,2.776399289921702e-8
+KeepPolicies/1/253,1.933586503648855e-6,1.92790529950271e-6,1.937104986268359e-6,1.562729047245983e-8,1.2230442594134778e-8,2.0413997704732056e-8
+KeepPolicies/12/48,2.4171906834509693e-6,2.4163424467173552e-6,2.417966593151045e-6,2.8395926294118742e-9,2.32607923322153e-9,3.490253796410157e-9
+KeepPolicies/148/33,2.3218790254523786e-5,2.320951307344857e-5,2.322904694211889e-5,3.36224531639932e-8,2.5522214449161475e-8,4.967625480313176e-8
+KeepPolicies/764/143,1.7287190807959156e-4,1.7282671096446344e-4,1.7295439802467565e-4,2.0397524412620376e-7,1.296202653723472e-7,3.0927686473574836e-7
+KeepPolicies/1116/401,2.803458882209666e-4,2.8025141825983163e-4,2.805256660682557e-4,4.4210508439252226e-7,2.7177474735421845e-7,8.110433858992414e-7
+KeepPolicies/20/39140,1.4148865002280042e-4,1.408923524582039e-4,1.4168548625306926e-4,1.0250755520104568e-6,3.9557183308713393e-7,2.029879075051348e-6
+KeepPolicies/24222/224,1.0991287627212722e-2,1.0881171006694097e-2,1.1173235809470635e-2,3.732323478626389e-4,2.3549076156835768e-4,5.046867165004387e-4
+KeepPolicies/1250/64,3.028713475918936e-4,3.02820332331106e-4,3.0304836736706135e-4,2.788273276777325e-7,1.1071393629043304e-7,5.449072846527146e-7
+KeepPolicies/9/18,1.9109063719357526e-6,1.9100537863486604e-6,1.9121522407752012e-6,3.4830759265214323e-9,2.572776609233702e-9,5.708804746347951e-9
+KeepPolicies/5897/5416,2.097356809162859e-3,2.0960584324797985e-3,2.098753527555635e-3,4.374563588081874e-6,3.7216507768224796e-6,5.546523126314264e-6
+KeepPolicies/16/16,2.6837475415626287e-6,2.6817725028042306e-6,2.6861097229433507e-6,7.553362928978441e-9,5.998320795402098e-9,1.0317196051539616e-8
+KeepPolicies/46/10,6.148323019525302e-6,6.145124929528357e-6,6.15189569657857e-6,1.1001418611254766e-8,8.871691831431291e-9,1.6092877293770975e-8
+KeepPolicies/3/702,3.4156407101739755e-6,3.4108774685282634e-6,3.418451686243187e-6,1.165392996136369e-8,7.966234296553319e-9,1.9206382256794915e-8
+KeepPolicies/15032/4,6.44029652884813e-3,6.4382694024888755e-3,6.442557481418943e-3,6.498476059127708e-6,5.0305999753738085e-6,9.043704955889573e-6
+KeepPolicies/46/15364,5.2753369338903524e-5,5.239140713277697e-5,5.3063190941810516e-5,1.160579235449775e-6,9.612799220066187e-7,1.3642891624814108e-6
+KeepPolicies/125/6625,4.025454156212467e-5,4.024428009438962e-5,4.026532253075534e-5,3.6481957558418235e-8,3.0875512107137294e-8,4.6776376771933447e-8
+KeepPolicies/713/18,1.5322734834960386e-4,1.5318363316626794e-4,1.5336228664035198e-4,2.3219828459948976e-7,8.496833251361321e-8,4.982174468186235e-7
+KeepPolicies/5/40,1.6538601010695255e-6,1.6534428248489994e-6,1.6544097440079172e-6,1.622045126929525e-9,1.3128410182944956e-9,1.9972520148162566e-9
+KeepPolicies/1458/2,3.62666561984307e-4,3.6259618227821967e-4,3.6283418940507716e-4,3.289577210945002e-7,1.494932360941445e-7,6.332680130905202e-7
+KeepPolicies/17/85,3.00195105179893e-6,2.9999628707607485e-6,3.004416776892495e-6,7.395694231882257e-9,6.230582025279794e-9,9.222045246872217e-9
+KeepPolicies/3296/228,1.0026246463957823e-3,1.0023594696187234e-3,1.0030981415372617e-3,1.1127079953837005e-6,7.543012949220954e-7,1.8030113009855697e-6
+KeepPolicies/1/7,1.1889323299595621e-6,1.1861631396665084e-6,1.191485759305703e-6,9.167940707271487e-9,8.243536968263997e-9,1.0142075911186093e-8
+KeepPolicies/7427/117,2.6729138479061445e-3,2.6720676134498475e-3,2.674603738859107e-3,4.025890265049097e-6,2.5002318383440227e-6,7.011526982741162e-6
+KeepPolicies/14470/14470,6.2551145288556416e-3,6.248502762100676e-3,6.260815018586763e-3,1.8451254362006166e-5,1.5584894139071383e-5,2.1474370059552556e-5
+KeepPolicies/47/4,5.948260751733513e-6,5.923252787873301e-6,5.983304914231822e-6,1.0253612368172906e-7,6.696098835649568e-8,1.3375092290968562e-7
+KeepPolicies/27868/10478,1.375325311342286e-2,1.3678246115339755e-2,1.3893790075057713e-2,2.5506958819605335e-4,9.276987617544492e-5,4.0172814797437517e-4
+KeepPolicies/253/16951,1.0324732411979808e-4,1.0319666693936085e-4,1.033034560258703e-4,1.8374753179158072e-7,1.519774778649462e-7,2.400354594957357e-7
+KeepPolicies/110/5280,3.5823133855277284e-5,3.580507164895569e-5,3.584228319800851e-5,6.380343475962144e-8,4.966104617350527e-8,8.334220482381078e-8
+KeepPolicies/33/7,4.317323334841175e-6,4.313828164091268e-6,4.322670714444863e-6,1.4220148157927285e-8,1.0642772369434257e-8,1.730812102035045e-8
+KeepPolicies/20/7300,2.450410381029135e-5,2.449281200330174e-5,2.451362686943817e-5,3.474613717649599e-8,2.433888624266182e-8,4.955052489821649e-8
+KeepPolicies/364/1456,8.227019097436708e-5,8.192189469903249e-5,8.265381988482585e-5,1.2239411306208391e-6,1.1461759918348695e-6,1.289090829485932e-6
+KeepPolicies/1/96,1.4384826355940793e-6,1.4372804848127812e-6,1.4397743377030947e-6,4.305693025226102e-9,3.4528337164647744e-9,5.462904237693843e-9
+KeepPolicies/13442/2,5.779208654796054e-3,5.774170174922734e-3,5.783930996559928e-3,1.4663562184802957e-5,1.1005247599562239e-5,1.963245614825446e-5
+KeepPolicies/38564/87,2.236053737614652e-2,2.2069067206934273e-2,2.2708130105225426e-2,7.440391338481491e-4,6.137250472261507e-4,8.965628088422877e-4
+KeepPolicies/1000/1000,2.553029959878976e-4,2.552251320626936e-4,2.5540443386668014e-4,3.0452585249925687e-7,2.304100985269306e-7,4.116608176773928e-7
+KeepPolicies/3000/1000,9.0367049538478e-4,9.034813211342243e-4,9.039311449551064e-4,7.542536977771421e-7,5.196580463024318e-7,1.2480832933705278e-6
+KeepPolicies/10000/1000,3.9024764149771206e-3,3.901216522272979e-3,3.904983119459712e-3,5.407179447347465e-6,3.3836763859305933e-6,9.280822404745052e-6
+KeepPolicies/40000/1000,2.094799994752802e-2,2.082851205415138e-2,2.1184481589028758e-2,3.8345065329451595e-4,2.519247085318177e-4,5.808567861256287e-4
+KeepPolicies/100/10000,6.275697660168382e-5,6.267237900968753e-5,6.28231968605292e-5,2.466684226775891e-7,1.7470727129322545e-7,3.461140517641356e-7
+KeepPolicies/100/10000,4.7136562836383576e-5,4.687981496332207e-5,4.7335529160231854e-5,7.219714054148111e-7,5.386897527020627e-7,9.264082187484521e-7
+KeepPolicies/100/10000,4.706836316465256e-5,4.6948753777016064e-5,4.714989861597643e-5,3.186101339901925e-7,2.4106774139374934e-7,4.186859386880225e-7
+KeepPolicies/100/10000,2.4366520524943095e-5,2.4356038572157324e-5,2.4376513427602884e-5,3.425734107796843e-8,2.9681810141377015e-8,4.0798986200565076e-8
+KeepPolicies/100/10000,2.4960406357643733e-5,2.4940154067506225e-5,2.4983763974045722e-5,7.26331602568211e-8,6.123237332184721e-8,9.306549219821148e-8
+KeepPolicies/10000/10000,3.7589672878095095e-3,3.752659628271018e-3,3.765889455991348e-3,2.0294196509839806e-5,1.763047493692375e-5,2.3526755664552882e-5
+KeepPolicies/10000/10000,3.952454708517962e-3,3.948343483136616e-3,3.956585998673329e-3,1.2450591234147912e-5,1.0026677563836277e-5,1.572602699024895e-5
+KeepPolicies/10000/10000,3.8055816263683016e-3,3.7996755818863856e-3,3.811260999032312e-3,1.8815155961851637e-5,1.5473217849711637e-5,2.2725388358058714e-5
+KeepPolicies/10000/10000,3.8943541158001694e-3,3.8925824677040997e-3,3.897409458176648e-3,7.192795077119276e-6,4.821580875529609e-6,1.248418321601707e-5
+KeepPolicies/10000/10000,3.9870165001568945e-3,3.9856397876158025e-3,3.98920637607986e-3,5.193699686296274e-6,3.679798808145113e-6,8.592078052785928e-6
+KeepPolicies/10000/10000,4.635939157388207e-3,4.634366902334829e-3,4.639050791850601e-3,6.706824100457602e-6,4.17116466552532e-6,1.140013540085088e-5
+KeepPolicies/10000/10000,4.6324196557905595e-3,4.605888111956143e-3,4.6639684195667564e-3,9.187297051305469e-5,7.0390432912444e-5,1.3773510859273734e-4
+KeepPolicies/10000/10000,4.501773276808983e-3,4.47725714795292e-3,4.532870509625553e-3,8.997032818871563e-5,7.628713832014608e-5,1.0791847223438296e-4
+KeepPolicies/10000/10000,4.39389814672427e-3,4.369305690650765e-3,4.426179014073755e-3,9.129698929545358e-5,7.669248818713926e-5,1.1717219090289631e-4
+KeepPolicies/10000/10000,3.943501645373088e-3,3.941648576673032e-3,3.948502890385087e-3,8.956823589353712e-6,4.183917874463928e-6,1.7169716521178647e-5
+KeepPolicies/0/0,1.073777144078427e-6,1.0727133674196693e-6,1.0748087914400964e-6,3.589401178238296e-9,2.9674908464591197e-9,4.843991955564007e-9
+KeepPolicies/10/0,1.092581161224314e-6,1.0913558098556756e-6,1.0940731762838627e-6,4.6370575865682716e-9,3.891345834913469e-9,5.817993329050029e-9
+KeepPolicies/100/0,1.3235472015597536e-6,1.32290109860828e-6,1.3241294492774318e-6,2.1176482484183325e-9,1.7337840523418974e-9,2.684241178187931e-9
+KeepPolicies/1000/0,4.18300348834241e-6,4.181991868700537e-6,4.1840835040184515e-6,3.6533520549819114e-9,2.9489096732123943e-9,4.548093354483196e-9
+KeepPolicies/10000/0,4.440282330963081e-5,4.4398360261952016e-5,4.4409153285901145e-5,1.712155553493034e-8,1.179838863495409e-8,2.5074861334381542e-8
+KeepPolicies/40000/0,9.144561287579648e-5,9.13924072766682e-5,9.162202535203485e-5,2.899958382807669e-7,4.372217409053752e-8,5.978640247657308e-7
+KeepPolicies/1/1,1.1596820731990927e-6,1.158974430744399e-6,1.1604112830032068e-6,2.340799687346653e-9,1.9930271054282425e-9,2.767822960598697e-9
diff --git a/plutus-core/cost-model/data/builtinCostModelA.json b/plutus-core/cost-model/data/builtinCostModelA.json
index c5a59edee46..1ad82986593 100644
--- a/plutus-core/cost-model/data/builtinCostModelA.json
+++ b/plutus-core/cost-model/data/builtinCostModelA.json
@@ -1364,5 +1364,22 @@
},
"type": "linear_in_x"
}
+ },
+ "keepPolicies": {
+ "cpu": {
+ "arguments": {
+ "intercept": 1000,
+ "slope1": 517590,
+ "slope2": 3833
+ },
+ "type": "linear_in_x_and_y"
+ },
+ "memory": {
+ "arguments": {
+ "intercept": 32,
+ "slope": 6
+ },
+ "type": "linear_in_y"
+ }
}
}
diff --git a/plutus-core/cost-model/data/builtinCostModelB.json b/plutus-core/cost-model/data/builtinCostModelB.json
index 9eeb61bee16..e6447a53df1 100644
--- a/plutus-core/cost-model/data/builtinCostModelB.json
+++ b/plutus-core/cost-model/data/builtinCostModelB.json
@@ -1364,5 +1364,22 @@
},
"type": "linear_in_x"
}
+ },
+ "keepPolicies": {
+ "cpu": {
+ "arguments": {
+ "intercept": 1000,
+ "slope1": 517590,
+ "slope2": 3833
+ },
+ "type": "linear_in_x_and_y"
+ },
+ "memory": {
+ "arguments": {
+ "intercept": 32,
+ "slope": 6
+ },
+ "type": "linear_in_y"
+ }
}
}
diff --git a/plutus-core/cost-model/data/builtinCostModelC.json b/plutus-core/cost-model/data/builtinCostModelC.json
index 66e34d7f2c8..874b3d987c1 100644
--- a/plutus-core/cost-model/data/builtinCostModelC.json
+++ b/plutus-core/cost-model/data/builtinCostModelC.json
@@ -1382,5 +1382,22 @@
},
"type": "linear_in_x"
}
+ },
+ "keepPolicies": {
+ "cpu": {
+ "arguments": {
+ "intercept": 1000,
+ "slope1": 517590,
+ "slope2": 3833
+ },
+ "type": "linear_in_x_and_y"
+ },
+ "memory": {
+ "arguments": {
+ "intercept": 32,
+ "slope": 6
+ },
+ "type": "linear_in_y"
+ }
}
}
diff --git a/plutus-core/cost-model/data/builtinCostModelD.json b/plutus-core/cost-model/data/builtinCostModelD.json
index 9978dd0ca0b..ed975d2ed95 100644
--- a/plutus-core/cost-model/data/builtinCostModelD.json
+++ b/plutus-core/cost-model/data/builtinCostModelD.json
@@ -1364,5 +1364,22 @@
},
"type": "linear_in_x"
}
+ },
+ "keepPolicies": {
+ "cpu": {
+ "arguments": {
+ "intercept": 1000,
+ "slope1": 517590,
+ "slope2": 3833
+ },
+ "type": "linear_in_x_and_y"
+ },
+ "memory": {
+ "arguments": {
+ "intercept": 32,
+ "slope": 6
+ },
+ "type": "linear_in_y"
+ }
}
}
diff --git a/plutus-core/cost-model/data/builtinCostModelE.json b/plutus-core/cost-model/data/builtinCostModelE.json
index 2a2cbddc5a7..ca529ca741e 100644
--- a/plutus-core/cost-model/data/builtinCostModelE.json
+++ b/plutus-core/cost-model/data/builtinCostModelE.json
@@ -1382,5 +1382,22 @@
},
"type": "linear_in_x"
}
+ },
+ "keepPolicies": {
+ "cpu": {
+ "arguments": {
+ "intercept": 1000,
+ "slope1": 517590,
+ "slope2": 3833
+ },
+ "type": "linear_in_x_and_y"
+ },
+ "memory": {
+ "arguments": {
+ "intercept": 32,
+ "slope": 6
+ },
+ "type": "linear_in_y"
+ }
}
}
diff --git a/plutus-core/cost-model/data/models.R b/plutus-core/cost-model/data/models.R
index d3d18bfae64..d507ef34e49 100644
--- a/plutus-core/cost-model/data/models.R
+++ b/plutus-core/cost-model/data/models.R
@@ -162,6 +162,7 @@ arity <- function(name) {
"MultiIndexArray" = 2,
"AssetCount" = 1,
"Policies" = 1,
+ "KeepPolicies" = 2,
-1 ## Default for missing values
)
}
@@ -447,6 +448,19 @@ modelFun <- function(path) {
return (mk.result(m, "linear_in_u"))
}
+ ## Two-variable linear model on the points with y_mem > 0. Used by the `Value`
+ ## policy-filter builtins, which return before they look at the list when the `Value` is
+ ## empty, so the y = 0 points cost the machine sizing the list rather than the builtin
+ ## doing its work, and one slope cannot price both.
+ linearInXAndYNonzeroY <- function (fname) {
+ filtered <- data %>%
+ filter.and.check.nonempty(fname) %>%
+ filter(y_mem > 0) %>%
+ discard.overhead ()
+ m <- lm(t ~ x_mem + y_mem, filtered)
+ return (mk.result(m, "linear_in_x_and_y"))
+ }
+
linearOnDiagonal <- function (fname) {
filtered <- filter(data, name == fname)
data.on.diagonal <- filter(filtered, x_mem == y_mem)
@@ -856,6 +870,11 @@ modelFun <- function(path) {
## X wrapped with `ValueOuterSize`
policiesModel <- linearInX ("Policies")
+ ## X is the length of the policy list, Y is `Value.totalSize`. The builtin skips the part
+ ## of the outer map the list cannot reach, so what costs anything is the pairs the list
+ ## names. See Note [Benchmarking keepPolicies] in Benchmarks.Values.
+ keepPoliciesModel <- linearInXAndYNonzeroY ("KeepPolicies")
+
## Values
# Z wrapped with `Logarithmic . ValueOuterOrMaxInner`
@@ -1014,7 +1033,8 @@ modelFun <- function(path) {
scaleValueModel = scaleValueModel,
multiIndexArrayModel = multiIndexArrayModel,
assetCountModel = assetCountModel,
- policiesModel = policiesModel
+ policiesModel = policiesModel,
+ keepPoliciesModel = keepPoliciesModel
)
## The integer division functions have a complex costing behaviour that requires some negative
diff --git a/plutus-core/cost-model/test/TestCostModels.hs b/plutus-core/cost-model/test/TestCostModels.hs
index 5aa26720334..e38d0170801 100644
--- a/plutus-core/cost-model/test/TestCostModels.hs
+++ b/plutus-core/cost-model/test/TestCostModels.hs
@@ -559,4 +559,5 @@ main =
-- , $(genTest 1 "unValueData")
$(genTest 2 "scaleValue") Everywhere
, $(genTest 1 "assetCount")
+ , $(genTest 2 "keepPolicies") Everywhere
]
diff --git a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs
index 9978daa6a98..b8d27fa85b3 100644
--- a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs
+++ b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs
@@ -2516,7 +2516,7 @@ instance uni ~ DefaultUni => ToBuiltinMeaning uni DefaultFun where
{-# INLINE keepPoliciesDenotation #-}
in makeBuiltinMeaning
keepPoliciesDenotation
- (runCostingFunTwoArguments . unimplementedCostingFun)
+ (runCostingFunTwoArguments . paramKeepPolicies)
toBuiltinMeaning _semvar DropPolicies =
let dropPoliciesDenotation :: [ByteString] -> Value -> Value
dropPoliciesDenotation = Value.dropPolicies
diff --git a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs
index 4705cb2c3a5..9fa5f372364 100644
--- a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs
+++ b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs
@@ -201,6 +201,7 @@ data BuiltinCostModelBase f
paramMultiIndexArray :: f ModelTwoArguments
, paramAssetCount :: f ModelOneArgument
, paramPolicies :: f ModelOneArgument
+ , paramKeepPolicies :: f ModelTwoArguments
}
deriving stock (Generic)
deriving anyclass (FunctorB, TraversableB, ConstraintsB)
diff --git a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs
index b38a304056b..667af631d96 100644
--- a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs
+++ b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs
@@ -431,6 +431,7 @@ unitCostBuiltinCostModel =
paramMultiIndexArray = unitCostTwoArguments
, paramAssetCount = unitCostOneArgument
, paramPolicies = unitCostOneArgument
+ , paramKeepPolicies = unitCostTwoArguments
}
unitCekParameters
diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V1/ParamName.hs b/plutus-ledger-api/src/PlutusLedgerApi/V1/ParamName.hs
index 09239bbe622..72e31495237 100644
--- a/plutus-ledger-api/src/PlutusLedgerApi/V1/ParamName.hs
+++ b/plutus-ledger-api/src/PlutusLedgerApi/V1/ParamName.hs
@@ -361,5 +361,10 @@ data ParamName
| Policies'cpu'arguments'slope
| Policies'memory'arguments'intercept
| Policies'memory'arguments'slope
+ | KeepPolicies'cpu'arguments'intercept
+ | KeepPolicies'cpu'arguments'slope1
+ | KeepPolicies'cpu'arguments'slope2
+ | KeepPolicies'memory'arguments'intercept
+ | KeepPolicies'memory'arguments'slope
deriving stock (Eq, Ord, Enum, Ix, Bounded, Generic)
deriving (IsParamName) via (GenericParamName ParamName)
diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V2/ParamName.hs b/plutus-ledger-api/src/PlutusLedgerApi/V2/ParamName.hs
index 41092f16d7d..edc6711ea76 100644
--- a/plutus-ledger-api/src/PlutusLedgerApi/V2/ParamName.hs
+++ b/plutus-ledger-api/src/PlutusLedgerApi/V2/ParamName.hs
@@ -363,5 +363,10 @@ data ParamName
| Policies'cpu'arguments'slope
| Policies'memory'arguments'intercept
| Policies'memory'arguments'slope
+ | KeepPolicies'cpu'arguments'intercept
+ | KeepPolicies'cpu'arguments'slope1
+ | KeepPolicies'cpu'arguments'slope2
+ | KeepPolicies'memory'arguments'intercept
+ | KeepPolicies'memory'arguments'slope
deriving stock (Eq, Ord, Enum, Ix, Bounded, Generic)
deriving (IsParamName) via (GenericParamName ParamName)
diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs b/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs
index 399d9b570a4..bf1e30a91d3 100644
--- a/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs
+++ b/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs
@@ -379,5 +379,10 @@ data ParamName
| Policies'cpu'arguments'slope
| Policies'memory'arguments'intercept
| Policies'memory'arguments'slope
+ | KeepPolicies'cpu'arguments'intercept
+ | KeepPolicies'cpu'arguments'slope1
+ | KeepPolicies'cpu'arguments'slope2
+ | KeepPolicies'memory'arguments'intercept
+ | KeepPolicies'memory'arguments'slope
deriving stock (Eq, Ord, Enum, Ix, Bounded, Generic)
deriving (IsParamName) via (GenericParamName ParamName)
diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V4/ParamName.hs b/plutus-ledger-api/src/PlutusLedgerApi/V4/ParamName.hs
index 5d7a5498118..7e3b2b7de89 100644
--- a/plutus-ledger-api/src/PlutusLedgerApi/V4/ParamName.hs
+++ b/plutus-ledger-api/src/PlutusLedgerApi/V4/ParamName.hs
@@ -374,5 +374,10 @@ data ParamName
| Policies'cpu'arguments'slope
| Policies'memory'arguments'intercept
| Policies'memory'arguments'slope
+ | KeepPolicies'cpu'arguments'intercept
+ | KeepPolicies'cpu'arguments'slope1
+ | KeepPolicies'cpu'arguments'slope2
+ | KeepPolicies'memory'arguments'intercept
+ | KeepPolicies'memory'arguments'slope
deriving stock (Eq, Ord, Enum, Ix, Bounded, Generic)
deriving (IsParamName) via (GenericParamName ParamName)
diff --git a/plutus-ledger-api/test/Spec/CostModelParams.hs b/plutus-ledger-api/test/Spec/CostModelParams.hs
index 3993cf191b0..d56bb728108 100644
--- a/plutus-ledger-api/test/Spec/CostModelParams.hs
+++ b/plutus-ledger-api/test/Spec/CostModelParams.hs
@@ -41,10 +41,10 @@ tests =
"CostModelParams"
"costModelParams"
[ embed $ testCase "length" do
- 343 @=? length v1_ParamNames
- 343 @=? length v2_ParamNames
- 361 @=? length v3_ParamNames
- 361 @=? length v4_ParamNames
+ 348 @=? length v1_ParamNames
+ 348 @=? length v2_ParamNames
+ 366 @=? length v3_ParamNames
+ 366 @=? length v4_ParamNames
, embed $ testCase "tripping paramname" do
for_ v1_ParamNames \p ->
assertBool "tripping v1 cm params failed" $