diff --git a/doc/cost-models/policies/index.html b/doc/cost-models/policies/index.html new file mode 100644 index 00000000000..b0824f6d133 --- /dev/null +++ b/doc/cost-models/policies/index.html @@ -0,0 +1,118 @@ + + + + + + Policies - Plutus Cost Model Visualization + + + + + + +
+

Policies Cost Model Visualization

+

+ Interactive visualization of benchmark data and fitted cost model for the Policies builtin function. + This function returns the currency symbols of a Value in ascending order. +

+ +
+

Data Source Configuration

+
+
+ +
+ + +
+
+
+ + +
+
+ + +
+
+ +
+
+
+ +
+

Plot Controls

+
+
+ + +
+
+ + +
+
+
+ +
+
+
Loading data and generating plot...
+
+ +
+

Plot Information

+ +
+
+
X-axis:
+
Value Size
+ +
Y-axis:
+
Time (nanoseconds)
+ +
Description:
+
Each point represents one benchmark run
+
+
+ +
+
Cost Model Type:
+
Loading...
+ +
Model Formula (net):
+
Loading...
+ +
Overhead:
+
Loading...
+
+ +
+
+
Data points:
+
-
+ +
Value Size range:
+
-
+ +
Time range:
+
-
+
+
+ +
+
+
+
+
+
+ + + + + + + diff --git a/doc/cost-models/policies/plot.js b/doc/cost-models/policies/plot.js new file mode 100644 index 00000000000..6419da09279 --- /dev/null +++ b/doc/cost-models/policies/plot.js @@ -0,0 +1,171 @@ +// Policies plot configuration and rendering + +// Configuration +const FUNCTION_NAME = 'Policies'; // CSV uses PascalCase +const COST_MODEL_NAME = 'policies'; // JSON uses camelCase +const ARITY = 1; + +// Global state +let benchmarkData = []; +let modelPredictions = []; +let costModel = null; +let overhead = 0; +let showModel = true; +let yAxisMode = 'zero'; + +setupCostModelPage({ + slug: 'policies', + functionName: FUNCTION_NAME, + costModelName: COST_MODEL_NAME, + arity: ARITY, + render(data) { + ({ benchmarkData, costModel, overhead, modelPredictions } = data); + updateInfoPanel(); + renderPlot(); + }, + setupControls +}); + +function updateInfoPanel() { + // Calculate stats + const stats = calculateStats(benchmarkData, 0); + + // Update data points + document.getElementById('info-data-points').textContent = stats.dataPoints; + + // Update ranges + if (stats.minArg !== undefined) { + document.getElementById('info-x-range').textContent = `${stats.minArg} - ${stats.maxArg}`; + } + + document.getElementById('info-time-range').textContent = stats.timeRange; + + // Update model info + if (costModel) { + document.getElementById('info-model-type').textContent = costModel.modelType; + document.getElementById('info-model-formula').textContent = formatModelFormula( + costModel.modelType, + costModel.coefficients + ); + } else { + document.getElementById('info-model-type').textContent = 'Not available'; + document.getElementById('info-model-formula').textContent = 'Cost model not found'; + } + + // Update overhead + if (overhead > 0) { + document.getElementById('info-overhead').textContent = + `${overhead.toFixed(2)} ns (arity ${ARITY}) added to predictions`; + } else { + document.getElementById('info-overhead').textContent = 'Not calculated'; + } +} + +function renderPlot() { + // Prepare benchmark trace + const benchmarkX = benchmarkData.map(d => d.args[0]); + const benchmarkY = benchmarkData.map(d => d.time); + + const benchmarkTrace = { + x: benchmarkX, + y: benchmarkY, + mode: 'markers', + type: 'scatter', + name: 'Benchmark Data', + marker: { + size: 6, + color: '#0033AD', + opacity: 0.7 + } + }; + + const traces = [benchmarkTrace]; + + // Prepare model trace if available + if (showModel && modelPredictions.length > 0) { + const modelX = modelPredictions.map(d => d.args[0]); + const modelY = modelPredictions.map(d => d.predictedTime); + + const modelTrace = { + x: modelX, + y: modelY, + mode: 'markers', + type: 'scatter', + name: 'Model Predictions', + marker: { + size: 6, + color: '#E53E3E', + opacity: 0.4, + symbol: 'x' + } + }; + + traces.push(modelTrace); + } + + // Layout configuration + const layout = { + title: { + text: `${FUNCTION_NAME} - Benchmark vs Model`, + font: { size: 20 } + }, + xaxis: { + title: 'Value Size', + gridcolor: '#E0E0E0' + }, + yaxis: { + title: 'Time (nanoseconds)', + gridcolor: '#E0E0E0' + }, + hovermode: 'closest', + showlegend: true, + legend: { + x: 0.02, + y: 0.98, + bgcolor: 'rgba(255, 255, 255, 0.8)', + bordercolor: '#BDC3C7', + borderwidth: 1 + }, + plot_bgcolor: '#FAFAFA', + paper_bgcolor: 'rgba(0,0,0,0)' + }; + + // Set Y-axis range based on mode + if (yAxisMode === 'zero') { + layout.yaxis.range = [0, Math.max(...benchmarkY) * 1.1]; + } else { + const minY = Math.min(...benchmarkY); + const maxY = Math.max(...benchmarkY); + const padding = (maxY - minY) * 0.1; + layout.yaxis.range = [minY - padding, maxY + padding]; + } + + // Config + const config = { + responsive: true, + displayModeBar: true, + displaylogo: false + }; + + // Render + // Clear loading message + const container = document.getElementById('plot-container'); + container.innerHTML = ''; + Plotly.newPlot('plot-container', traces, layout, config); +} + +function setupControls() { + // Show/hide model checkbox + const showModelCheckbox = document.getElementById('show-model'); + showModelCheckbox.addEventListener('change', (e) => { + showModel = e.target.checked; + renderPlot(); + }); + + // Y-axis mode selector + const yAxisModeSelect = document.getElementById('y-axis-mode'); + yAxisModeSelect.addEventListener('change', (e) => { + yAxisMode = e.target.value; + renderPlot(); + }); +} diff --git a/doc/cost-models/shared/utils.js b/doc/cost-models/shared/utils.js index 71906fa8b78..7a9c974fe57 100644 --- a/doc/cost-models/shared/utils.js +++ b/doc/cost-models/shared/utils.js @@ -505,6 +505,7 @@ const PAGES = [ ['insertcoin', 'InsertCoin'], ['unionvalue', 'UnionValue'], ['scalevalue', 'ScaleValue'], + ['policies', 'Policies'], ['listtoarray', 'ListToArray'], ['lengthofarray', 'LengthOfArray'], ['indexarray', 'IndexArray'], diff --git a/plutus-core/changelog.d/20260819_154936_yuriy.lazaryev_policies_costing.md b/plutus-core/changelog.d/20260819_154936_yuriy.lazaryev_policies_costing.md new file mode 100644 index 00000000000..e72921336b2 --- /dev/null +++ b/plutus-core/changelog.d/20260819_154936_yuriy.lazaryev_policies_costing.md @@ -0,0 +1,3 @@ +### Added + +- Cost model for the `policies` builtin ([CIP-0168](https://cips.cardano.org/cip/CIP-0168)), with four new cost model parameters. Linear in the 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 1c29fa77aae..e916b8a5abd 100644 --- a/plutus-core/cost-model/budgeting-bench/Benchmarks/Values.hs +++ b/plutus-core/cost-model/budgeting-bench/Benchmarks/Values.hs @@ -21,7 +21,16 @@ import Data.Map.Strict qualified as Map import Data.Word (Word8) import GHC.Stack (HasCallStack) import PlutusCore - ( DefaultFun (InsertCoin, LookupCoin, ScaleValue, UnValueData, UnionValue, ValueContains, ValueData) + ( DefaultFun + ( InsertCoin + , LookupCoin + , Policies + , ScaleValue + , UnValueData + , UnionValue + , ValueContains + , ValueData + ) ) import PlutusCore.Builtin (BuiltinResult (BuiltinFailure, BuiltinSuccess, BuiltinSuccessWithLogs)) @@ -57,6 +66,7 @@ makeBenchmarks gen = , insertCoinBenchmark gen , unionValueBenchmark gen , scaleValueBenchmark gen + , policiesBenchmark gen ] ---------------------------------------------------------------------------------------------------- @@ -368,6 +378,49 @@ scaleValueArgs gen = replicateM 200 $ do value = buildValue policyIds [tokenName] amt pure (scalar, value) +---------------------------------------------------------------------------------------------------- +-- Policies ---------------------------------------------------------------------------------------- + +{- Note [Benchmarking policies on the one-token-per-policy diagonal] +`policies` is \(O(m)\) in the size of the outer map, but the argument is costed by +`ValueTotalSize` (the `ExMemoryUsage Value` instance the denotation uses), which measures +the total number of `(policy, token)` pairs. Those two agree only when every policy holds +exactly one token, so the generator fixes that shape: the resulting fit is keyed on a size +measure that equals the number of policies. + +This is deliberately the worst case per unit of the size measure. For any other shape the +total size exceeds the number of policies, so the real cost is lower than the fitted model +predicts and the model over-charges. Benchmarking off the diagonal instead would fit a +shallower slope and under-charge the one-token-per-policy case, which is the failure +direction that matters. + +`nf` rather than `whnf`, for the same reason as `valueData`: the result is a lazy list and +`whnf` would stop at the first cons cell. +-} +policiesBenchmark :: StdGen -> Benchmark +policiesBenchmark gen = + createOneTermBuiltinBenchWithWrapper_NF + ValueTotalSize + Policies + [] + (runBenchGen gen policiesArgs) + +{-| Maximum number of policies for `policies` benchmarking, matching the bound used for +`valueData` so the generated `Value`s stay in the same size regime as the other +single-argument `Value` benchmarks. -} +maxPoliciesEntries :: Int +maxPoliciesEntries = Value.valueDataMaxSize + +{-| Generate `Value`s holding one token per policy, so that total size equals the number of +policies. See Note [Benchmarking policies on the one-token-per-policy diagonal]. -} +policiesArgs :: StatefulGen g m => g -> m [Value] +policiesArgs gen = + (Value.empty :) <$> replicateM 100 do + numPolicyIds <- uniformRM (1, maxPoliciesEntries) gen + policyIds <- replicateM numPolicyIds (generateKey gen) + tokenName <- generateKey gen + pure $ buildValue policyIds [tokenName] (mkQuantity 1) + ---------------------------------------------------------------------------------------------------- -- Value Generators -------------------------------------------------------------------------------- diff --git a/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs b/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs index cd06085cecb..cf39d26cd7d 100644 --- a/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs +++ b/plutus-core/cost-model/create-cost-model/BuiltinMemoryModels.hs @@ -382,6 +382,12 @@ builtinMemoryModels = -- the array; only the spine is new, at three words per cons cell. The nonzero -- intercept keeps the cost nonzero for the empty index list. paramMultiIndexArray = Id $ ModelTwoArgumentsLinearInY $ OneVariableLinearFunction 4 3 + , -- `policies` returns the outer map's keys. The bytestrings are shared with the + -- `Value`, so only the list spine is new, at three words per cons cell (as for + -- `multiIndexArray`). The size measure is the total number of (policy, token) pairs, + -- which is at least the number of policies, so this over-charges values holding more + -- than one token per policy rather than under-charging any of them. + paramPolicies = Id $ ModelOneArgumentLinearInX $ OneVariableLinearFunction 4 3 } 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 3cdb4c13cd9..d3cd9465f5b 100644 --- a/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs +++ b/plutus-core/cost-model/create-cost-model/CreateBuiltinCostModel.hs @@ -154,6 +154,7 @@ builtinCostModelNames = , paramUnionValue = "unionValueModel" , paramScaleValue = "scaleValueModel" , paramMultiIndexArray = "multiIndexArrayModel" + , paramPolicies = "policiesModel" } {-| Loads the models from R. @@ -310,6 +311,7 @@ createBuiltinCostModel bmfile rfile = do paramUnionValue <- getParams readCF2 paramUnionValue paramScaleValue <- getParams readCF2 paramScaleValue paramMultiIndexArray <- getParams readCF2 paramMultiIndexArray + paramPolicies <- getParams readCF1 paramPolicies pure $ BuiltinCostModelBase {..} diff --git a/plutus-core/cost-model/data/benching-conway.csv b/plutus-core/cost-model/data/benching-conway.csv index b3c15f50d1d..4da098ee036 100644 --- a/plutus-core/cost-model/data/benching-conway.csv +++ b/plutus-core/cost-model/data/benching-conway.csv @@ -14781,3 +14781,104 @@ MultiIndexArray/128/656,9.742384457259018e-6,9.738226628587493e-6,9.758796384809 MultiIndexArray/2048/250,4.545746465191931e-6,4.542337915786206e-6,4.549915914643576e-6,1.2382943128493691e-8,7.933523427199416e-9,1.884083220446766e-8 MultiIndexArray/2048/500,8.030964088467131e-6,8.027945849897267e-6,8.038003334134253e-6,1.4344883735867401e-8,7.222525582368531e-9,2.708292118501812e-8 MultiIndexArray/2048/1024,1.5908025068953797e-5,1.5891687337303956e-5,1.595130243978917e-5,8.451021253065874e-8,3.66756042104449e-8,1.6477584846151207e-7 +Policies/0,9.131855522970573e-7,9.126126628886761e-7,9.138414853838659e-7,2.143248345388286e-9,1.7846318035511555e-9,2.9502029971041177e-9 +Policies/21933,3.135502232821667e-4,3.132424920742215e-4,3.139915491546955e-4,1.2370355588879281e-6,9.137504820862114e-7,1.6931361466004032e-6 +Policies/33125,4.648660927509344e-4,4.6310565494019984e-4,4.666304873531442e-4,5.766783535923867e-6,5.02858860969426e-6,7.17575868653308e-6 +Policies/15568,2.231483897239813e-4,2.228426017730975e-4,2.237459926509625e-4,1.4878215252044066e-6,9.42921107844315e-7,2.7526241455614773e-6 +Policies/16202,2.337068306186552e-4,2.331115402266963e-4,2.3449660158742866e-4,2.2969714224806536e-6,1.6190427025662178e-6,3.590256854030701e-6 +Policies/31535,4.6182415531563807e-4,4.6110575853186905e-4,4.6282161912180214e-4,2.9853640209979655e-6,2.1157817532639455e-6,4.443586490374839e-6 +Policies/10623,1.6649508256592188e-4,1.6568233382409405e-4,1.6726561920083876e-4,2.713760983771339e-6,2.2320513309573755e-6,3.3237329922601326e-6 +Policies/32298,4.6839593009820324e-4,4.674015525245757e-4,4.697699277804703e-4,4.0002425702528185e-6,2.9421678815873625e-6,6.0845075439867145e-6 +Policies/4941,7.334819655801512e-5,7.3199776435787e-5,7.347381126141131e-5,4.675142259727988e-7,3.565004190835575e-7,6.020809038752586e-7 +Policies/25737,3.690081510276924e-4,3.675575979571992e-4,3.7078792385278564e-4,5.592286943945871e-6,4.64879572743689e-6,6.631172737995925e-6 +Policies/32672,4.5509179012548053e-4,4.540592011804767e-4,4.5609542930729653e-4,3.4705496788152714e-6,2.81319364576823e-6,4.072668139800535e-6 +Policies/29569,4.1753562551116735e-4,4.1672991874438576e-4,4.1877552978006116e-4,3.362766416543673e-6,2.3810896179615394e-6,5.232424124819834e-6 +Policies/20634,2.9343774232427206e-4,2.927893693479051e-4,2.940901797453179e-4,2.1336909326303566e-6,1.8268182162337883e-6,2.583350574306775e-6 +Policies/30075,4.291187209772412e-4,4.2848028909823305e-4,4.2983234496415566e-4,2.221874305686318e-6,1.8234445861745025e-6,2.936066455547135e-6 +Policies/15351,2.2911934439554752e-4,2.269198362717838e-4,2.3079893667088712e-4,6.483169131060017e-6,5.6170728341518e-6,7.365009127193493e-6 +Policies/36822,5.097045984839868e-4,5.081561016173017e-4,5.116860160318286e-4,6.033723048960552e-6,4.550781650502326e-6,7.92080924860203e-6 +Policies/15993,2.397581800722469e-4,2.3838818687263092e-4,2.409128847290993e-4,4.156100908622073e-6,3.4230057105340304e-6,5.10710176417085e-6 +Policies/3025,4.671488888575841e-5,4.667444358935709e-5,4.677419645257871e-5,1.5971076504489207e-7,1.1997372050976833e-7,2.1481247338974752e-7 +Policies/15516,2.2788304536501184e-4,2.2717879921174312e-4,2.2899987120827094e-4,2.995324705221257e-6,2.2070359161596315e-6,4.061491801419709e-6 +Policies/7555,1.1608559886262634e-4,1.1595739557017717e-4,1.1622910836868635e-4,4.5669727024386307e-7,3.775298108576534e-7,6.073278016333574e-7 +Policies/3320,5.266221230131826e-5,5.248081865074514e-5,5.286548684182852e-5,6.271661163875053e-7,5.384395377439601e-7,7.519510477549883e-7 +Policies/5127,7.778040245113222e-5,7.751972746318042e-5,7.804959360707097e-5,8.806480084460984e-7,8.01520563672763e-7,9.852040841086238e-7 +Policies/14379,2.1683163498701594e-4,2.16312794232003e-4,2.1752349874193394e-4,2.0579635257256364e-6,1.6958694997150296e-6,2.6068229511041085e-6 +Policies/14547,2.1619865655128886e-4,2.1522914288801546e-4,2.1698365649666136e-4,2.970077361821075e-6,2.3163341459227084e-6,3.7474335963599617e-6 +Policies/1335,2.109125690761253e-5,2.10255422332116e-5,2.113316280523657e-5,1.700770927868924e-7,1.1226792592034611e-7,2.3628530168019454e-7 +Policies/702,1.1289532249771797e-5,1.1264679219467246e-5,1.1324772478680986e-5,1.0201778483005881e-7,7.7299726397786e-8,1.3571425740621686e-7 +Policies/34558,4.775595610648504e-4,4.766450655794333e-4,4.787104914690451e-4,3.391760679181432e-6,2.600304134035987e-6,4.489302283742534e-6 +Policies/25916,3.738532466196209e-4,3.7303382149813497e-4,3.7483570756090685e-4,3.2368677267836197e-6,2.677245680013501e-6,4.185326270455116e-6 +Policies/11675,1.6971559917725043e-4,1.6922409524808494e-4,1.7035735674777343e-4,1.8835851831282912e-6,1.5559717984904454e-6,2.238452215865655e-6 +Policies/878,1.3707996458756375e-5,1.3680453505761118e-5,1.3745464687797095e-5,1.0159859582177393e-7,7.04547141439249e-8,1.6196627853153915e-7 +Policies/1318,2.0839914317311964e-5,2.0724535695422415e-5,2.0989002962709608e-5,4.443306501593533e-7,3.280538929689753e-7,5.560672069733588e-7 +Policies/29829,4.3158104586301743e-4,4.301277749422949e-4,4.333025520355236e-4,5.369780359629833e-6,4.686852098736846e-6,6.534780608416621e-6 +Policies/20218,2.902798558186343e-4,2.8891412549881396e-4,2.9178538103643556e-4,4.824102106702638e-6,4.39143846596575e-6,5.386895708722551e-6 +Policies/5008,7.711984270555451e-5,7.694492936662265e-5,7.740215997155673e-5,7.202482633665469e-7,4.478238325807528e-7,1.2259780095202702e-6 +Policies/10969,1.6430285356997242e-4,1.6369232634626322e-4,1.6485451359746586e-4,1.9837600874540682e-6,1.6311909595613036e-6,2.4195172858556432e-6 +Policies/24232,3.443201484385501e-4,3.433574586509297e-4,3.4532160970461264e-4,3.3419397921811173e-6,2.862564324300231e-6,3.7623833832574452e-6 +Policies/32036,4.5056096286792734e-4,4.4969329405952145e-4,4.5205882868121764e-4,3.6394249763357023e-6,2.461090225826036e-6,5.922144404402781e-6 +Policies/37381,5.338012228205993e-4,5.301696314258291e-4,5.373259054128509e-4,1.1797006500592447e-5,1.0491355471746678e-5,1.3486550190810237e-5 +Policies/20218,2.9396171806328155e-4,2.929056947060712e-4,2.949688372326039e-4,3.6346358477279566e-6,2.944870991073485e-6,4.609669441358329e-6 +Policies/24994,3.5343579456726727e-4,3.5304663563781835e-4,3.5397194449137586e-4,1.578906018797827e-6,1.2047734420777474e-6,2.154710871639216e-6 +Policies/13588,1.9590487077050995e-4,1.9557990679820047e-4,1.9669607120294594e-4,1.5665500074899476e-6,8.018370137006353e-7,2.921813792039714e-6 +Policies/22017,3.2210560151177175e-4,3.208112606714244e-4,3.2315631044910675e-4,4.00246035142115e-6,3.142336032793093e-6,4.850881665540998e-6 +Policies/33492,4.682726421673919e-4,4.663412412433551e-4,4.706071534401548e-4,6.952503801354028e-6,5.556087705844966e-6,8.019538303671656e-6 +Policies/9827,1.4253547315841864e-4,1.422403305109509e-4,1.4287100185921128e-4,1.093327411639789e-6,9.016627674943157e-7,1.3550200174281405e-6 +Policies/18309,2.713024125866962e-4,2.7008684367017745e-4,2.724286778259254e-4,3.983568539493249e-6,3.503297277689087e-6,4.471810986092001e-6 +Policies/6731,1.0316757437637888e-4,1.0306523115972629e-4,1.0328771941647367e-4,3.6794850978149864e-7,2.948153549507961e-7,4.5460260150091985e-7 +Policies/33376,4.6918970569470705e-4,4.678418675458963e-4,4.707577065350775e-4,4.6709666432735765e-6,3.361142501829036e-6,5.8939124070903295e-6 +Policies/27253,3.9125062963124064e-4,3.8969339494434745e-4,3.929077465874276e-4,5.570970077881762e-6,5.273493974042264e-6,6.082097522027978e-6 +Policies/22996,3.262111011831281e-4,3.2598696128937927e-4,3.2662121348562705e-4,9.69095037324153e-7,6.102278872466315e-7,1.6349359677306114e-6 +Policies/1729,2.7283868262548596e-5,2.7230522211249746e-5,2.7343123036442473e-5,1.9335821537972962e-7,1.5459727412021315e-7,2.4170946368746213e-7 +Policies/16223,2.389706460747714e-4,2.3850182327798069e-4,2.395175395730136e-4,1.6638626488648953e-6,1.473228953467051e-6,1.874033462837362e-6 +Policies/24460,3.5279196348291897e-4,3.5145497634936335e-4,3.542283814487531e-4,4.724689945168977e-6,4.285101386149618e-6,5.164843177360141e-6 +Policies/38514,5.401474197890282e-4,5.385104986372556e-4,5.420124845051076e-4,5.979320463477195e-6,4.562497028055993e-6,8.234710575644372e-6 +Policies/19441,2.7966187185046547e-4,2.7943880543538935e-4,2.799082886541207e-4,8.334196964670294e-7,6.712982972255678e-7,1.069301267458982e-6 +Policies/17023,2.4805892803241676e-4,2.474635568875345e-4,2.4893598215214107e-4,2.4244175174308784e-6,1.8757290712874809e-6,2.923719836112785e-6 +Policies/16481,2.3647902597667795e-4,2.3615152270186905e-4,2.3685536224391274e-4,1.17423706949995e-6,1.0008003991442826e-6,1.482379436723364e-6 +Policies/33380,4.6560385846154966e-4,4.6423234439630295e-4,4.6767268683153525e-4,5.575254253730879e-6,4.140646170748946e-6,7.015453275562679e-6 +Policies/39112,5.381439568977499e-4,5.37586680331792e-4,5.386870989577525e-4,1.857619703752122e-6,1.5270171350549078e-6,2.298330438411037e-6 +Policies/31622,4.441320433927214e-4,4.4249670446683547e-4,4.4646971892668924e-4,6.634219612845224e-6,4.610233789654513e-6,9.28992609829243e-6 +Policies/25929,3.687281620166917e-4,3.6842198300595416e-4,3.690807868502561e-4,1.101215491697312e-6,8.568479077831633e-7,1.4999352129785798e-6 +Policies/11182,1.6808268194644144e-4,1.6786732574492285e-4,1.6848159531485202e-4,9.714836288422983e-7,6.603470965620472e-7,1.4215936171431127e-6 +Policies/11198,1.6309514314355014e-4,1.6286079636802474e-4,1.6347481307701366e-4,9.847708463546417e-7,6.40432162906837e-7,1.54820243612342e-6 +Policies/19572,2.84145117463687e-4,2.830046049134821e-4,2.8520084467853295e-4,3.6002752431616183e-6,3.3203374189804887e-6,3.895318641474864e-6 +Policies/35378,4.924341648328958e-4,4.917044894900241e-4,4.931085901916918e-4,2.3859265949530446e-6,1.8953788980476032e-6,3.015131004220731e-6 +Policies/10222,1.5322887302074884e-4,1.5259610396421044e-4,1.5379968974816492e-4,2.0363786317326087e-6,1.784427162523545e-6,2.4820631124537576e-6 +Policies/36275,5.023295337076376e-4,5.011579772787786e-4,5.040909076924859e-4,4.4523747742247146e-6,3.1578306857895134e-6,6.061199608741227e-6 +Policies/10102,1.4725477229318056e-4,1.4715980995155787e-4,1.4736908675225474e-4,3.463141355409694e-7,2.7444237913108165e-7,4.737603344487607e-7 +Policies/5474,8.387917680223125e-5,8.3457345995777e-5,8.41588614264513e-5,1.1377491921606543e-6,8.764137869047576e-7,1.478847416546899e-6 +Policies/10811,1.592640301710783e-4,1.5868556238450498e-4,1.6000082622316463e-4,2.2141084519801446e-6,1.6875894297221697e-6,2.8236126956069825e-6 +Policies/32026,4.609249207350331e-4,4.585947554000628e-4,4.6291636326972985e-4,6.867654845316367e-6,5.023912921646395e-6,9.246185588000589e-6 +Policies/9879,1.458847645769842e-4,1.4552599431091878e-4,1.4640698558696701e-4,1.4810537315325102e-6,1.171308879668304e-6,1.8528581895926608e-6 +Policies/1473,2.309398712147864e-5,2.300775740154692e-5,2.3158382593568606e-5,2.5045677188178255e-7,1.8435269193534121e-7,3.416513722113496e-7 +Policies/24866,3.658579172188184e-4,3.6437642963168957e-4,3.673271783630834e-4,4.845607613676181e-6,4.380569379290976e-6,5.349113634491042e-6 +Policies/27436,3.966386518770602e-4,3.94698116163164e-4,3.98100705500339e-4,5.417284147645655e-6,4.325829186331842e-6,6.425605520118951e-6 +Policies/29495,4.1540463313075694e-4,4.141195145356056e-4,4.1725083465553764e-4,5.18747986342795e-6,3.4473335227173533e-6,6.983689768763312e-6 +Policies/38963,5.423628338481931e-4,5.41539979125111e-4,5.431843139085198e-4,2.7273532674644514e-6,2.355215488706201e-6,3.2608813812964146e-6 +Policies/32515,4.525193704126624e-4,4.520773637696091e-4,4.530324879633117e-4,1.5642462127313792e-6,1.246402194622578e-6,2.01983022746109e-6 +Policies/21485,3.1168632208249754e-4,3.1064961257176797e-4,3.129399237096866e-4,3.8084549595105654e-6,3.0688532933708927e-6,4.760273370341906e-6 +Policies/11613,1.714710798539333e-4,1.7122257426972854e-4,1.717447782289905e-4,8.666125706413362e-7,6.879576183137085e-7,1.1414126620646275e-6 +Policies/33182,4.6358622668655737e-4,4.624058954549852e-4,4.647914558948804e-4,3.89538953935967e-6,2.9369771107792883e-6,4.829018466956586e-6 +Policies/12212,1.7781310836526172e-4,1.7750296190049712e-4,1.7860136986091405e-4,1.5614780032618678e-6,7.800092436507426e-7,3.1244786178198256e-6 +Policies/33252,4.741923149670491e-4,4.7215602740525834e-4,4.763209324608886e-4,7.046210193626091e-6,6.279219958513394e-6,8.25681867565309e-6 +Policies/2758,4.168727918727299e-5,4.1505072286795314e-5,4.1867794150922456e-5,6.232367711851267e-7,5.652580896248828e-7,6.972134691876067e-7 +Policies/20270,2.8837368158019715e-4,2.88065614642687e-4,2.887342360128978e-4,1.1486136469627735e-6,8.949299422091514e-7,1.4110920679913481e-6 +Policies/10380,1.530147466729351e-4,1.5257754483672984e-4,1.5367134320176112e-4,1.877250541237866e-6,1.484122674604654e-6,2.507368143686984e-6 +Policies/15739,2.2715642907494143e-4,2.2697617149917328e-4,2.2739333570501177e-4,6.871674298707241e-7,5.424447776466937e-7,9.56863510086251e-7 +Policies/20395,2.903127904254808e-4,2.895613236223963e-4,2.9142473439883274e-4,3.052098601612166e-6,2.1613227223964195e-6,5.0947748295977986e-6 +Policies/37394,5.376367593362557e-4,5.344645313923734e-4,5.410848715947426e-4,1.0998162385910478e-5,9.522904896615853e-6,1.3060017367195437e-5 +Policies/3635,5.4931673726459577e-5,5.486044960925916e-5,5.5064057244251785e-5,3.0947523022374656e-7,2.0584905564328382e-7,5.155460542285187e-7 +Policies/8624,1.2773017814992404e-4,1.2755853600758313e-4,1.2797207230455778e-4,7.004718125595645e-7,5.416498087440988e-7,9.892919082031474e-7 +Policies/26510,3.8328337908816694e-4,3.8169873486825016e-4,3.844880094866223e-4,4.951123285276782e-6,4.252663850175773e-6,5.610976635001246e-6 +Policies/17071,2.442558210646473e-4,2.4378907841472662e-4,2.448635675252482e-4,1.683458679590913e-6,1.4622145809222045e-6,1.989420002118517e-6 +Policies/2079,3.392256004192105e-5,3.379927094374491e-5,3.405469767511481e-5,4.22022777462817e-7,3.348510785263597e-7,6.012884718166228e-7 +Policies/28081,3.970882345314863e-4,3.961050244234686e-4,3.982853337033692e-4,3.815790483047592e-6,2.5627680750797958e-6,4.764497220569244e-6 +Policies/26124,3.7030788266819364e-4,3.6997399981105166e-4,3.706386856325749e-4,1.1045575398222011e-6,9.340124373674002e-7,1.4117607948976898e-6 +Policies/27323,3.8772381417946926e-4,3.8664053454736286e-4,3.891742428242611e-4,4.185254745819592e-6,3.1941820732598108e-6,5.279061444449415e-6 +Policies/5182,8.041594511238326e-5,8.006884609621973e-5,8.083379840172508e-5,1.2700727304505276e-6,1.1125351978357052e-6,1.4764850467254883e-6 +Policies/28004,3.9577525703963926e-4,3.9418389118987243e-4,3.9695719989387557e-4,4.6982559281621185e-6,3.4074932308425477e-6,5.776508355748856e-6 +Policies/4601,6.881327724268903e-5,6.868229153629646e-5,6.897565481439094e-5,4.986768868262524e-7,4.075444633324556e-7,6.38626422576307e-7 +Policies/856,1.3498107757160584e-5,1.3457202769923031e-5,1.35512033888457e-5,1.5300421872384877e-7,1.2455972492365177e-7,1.8998585648966752e-7 +Policies/13219,1.9409490678077822e-4,1.9365921780047885e-4,1.946116814089425e-4,1.5302399576737378e-6,1.3019335450762688e-6,1.8059268716597244e-6 diff --git a/plutus-core/cost-model/data/builtinCostModelA.json b/plutus-core/cost-model/data/builtinCostModelA.json index 3cf708c8960..bce78715f0b 100644 --- a/plutus-core/cost-model/data/builtinCostModelA.json +++ b/plutus-core/cost-model/data/builtinCostModelA.json @@ -1338,5 +1338,21 @@ }, "type": "linear_in_y" } + }, + "policies": { + "cpu": { + "arguments": { + "intercept": 7158161, + "slope": 13922 + }, + "type": "linear_in_x" + }, + "memory": { + "arguments": { + "intercept": 4, + "slope": 3 + }, + "type": "linear_in_x" + } } } diff --git a/plutus-core/cost-model/data/builtinCostModelB.json b/plutus-core/cost-model/data/builtinCostModelB.json index 6cbe5636d7e..49c489ae7a0 100644 --- a/plutus-core/cost-model/data/builtinCostModelB.json +++ b/plutus-core/cost-model/data/builtinCostModelB.json @@ -1338,5 +1338,21 @@ }, "type": "linear_in_y" } + }, + "policies": { + "cpu": { + "arguments": { + "intercept": 7158161, + "slope": 13922 + }, + "type": "linear_in_x" + }, + "memory": { + "arguments": { + "intercept": 4, + "slope": 3 + }, + "type": "linear_in_x" + } } } diff --git a/plutus-core/cost-model/data/builtinCostModelC.json b/plutus-core/cost-model/data/builtinCostModelC.json index 24071b72982..afe2ee0972b 100644 --- a/plutus-core/cost-model/data/builtinCostModelC.json +++ b/plutus-core/cost-model/data/builtinCostModelC.json @@ -1356,5 +1356,21 @@ }, "type": "linear_in_y" } + }, + "policies": { + "cpu": { + "arguments": { + "intercept": 7158161, + "slope": 13922 + }, + "type": "linear_in_x" + }, + "memory": { + "arguments": { + "intercept": 4, + "slope": 3 + }, + "type": "linear_in_x" + } } } diff --git a/plutus-core/cost-model/data/builtinCostModelD.json b/plutus-core/cost-model/data/builtinCostModelD.json index d3b6f2e45d1..cddca799836 100644 --- a/plutus-core/cost-model/data/builtinCostModelD.json +++ b/plutus-core/cost-model/data/builtinCostModelD.json @@ -1338,5 +1338,21 @@ }, "type": "linear_in_y" } + }, + "policies": { + "cpu": { + "arguments": { + "intercept": 7158161, + "slope": 13922 + }, + "type": "linear_in_x" + }, + "memory": { + "arguments": { + "intercept": 4, + "slope": 3 + }, + "type": "linear_in_x" + } } } diff --git a/plutus-core/cost-model/data/builtinCostModelE.json b/plutus-core/cost-model/data/builtinCostModelE.json index e225e1f580e..a8724829242 100644 --- a/plutus-core/cost-model/data/builtinCostModelE.json +++ b/plutus-core/cost-model/data/builtinCostModelE.json @@ -1356,5 +1356,21 @@ }, "type": "linear_in_y" } + }, + "policies": { + "cpu": { + "arguments": { + "intercept": 7158161, + "slope": 13922 + }, + "type": "linear_in_x" + }, + "memory": { + "arguments": { + "intercept": 4, + "slope": 3 + }, + "type": "linear_in_x" + } } } diff --git a/plutus-core/cost-model/data/models.R b/plutus-core/cost-model/data/models.R index 49269619b2e..1d52cbed53b 100644 --- a/plutus-core/cost-model/data/models.R +++ b/plutus-core/cost-model/data/models.R @@ -160,6 +160,7 @@ arity <- function(name) { "UnValueData" = 1, "ScaleValue" = 2, "MultiIndexArray" = 2, + "Policies" = 1, -1 ## Default for missing values ) } @@ -850,6 +851,14 @@ modelFun <- function(path) { mk.result (m, "quadratic_in_y") } + ## `policies` copies the outer map's keys into a list, so the cost is linear in the + ## number of policies. The size measure is the total number of (policy, token) pairs, + ## which equals the number of policies only when each policy holds a single token; the + ## benchmark generates that shape, so the slope below is the per-policy cost. Values + ## carrying more tokens per policy have a larger size for the same work, so they are + ## over-charged rather than under-charged. + policiesModel <- linearInX ("Policies") + ## Values # Z wrapped with `Logarithmic . ValueOuterOrMaxInner` @@ -1006,7 +1015,8 @@ modelFun <- function(path) { insertCoinModel = insertCoinModel, unionValueModel = unionValueModel, scaleValueModel = scaleValueModel, - multiIndexArrayModel = multiIndexArrayModel + multiIndexArrayModel = multiIndexArrayModel, + policiesModel = policiesModel ) ## 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 917c0e2d0fc..9f1710441ec 100644 --- a/plutus-core/cost-model/test/TestCostModels.hs +++ b/plutus-core/cost-model/test/TestCostModels.hs @@ -558,4 +558,6 @@ main = $(genTest 2 "scaleValue") Everywhere , -- Arrays (batch 7) $(genTest 2 "multiIndexArray") Everywhere + , -- Values (batch 7) + $(genTest 1 "policies") ] diff --git a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs index 83b764a9044..735d3ee4968 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs @@ -2499,7 +2499,7 @@ instance uni ~ DefaultUni => ToBuiltinMeaning uni DefaultFun where {-# INLINE policiesDenotation #-} in makeBuiltinMeaning policiesDenotation - (runCostingFunOneArgument . unimplementedCostingFun) + (runCostingFunOneArgument . paramPolicies) toBuiltinMeaning _semvar AssetCount = let assetCountDenotation :: Value -> Integer assetCountDenotation = toInteger . Value.totalSize 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 fc57352fd58..0c62c41ef6c 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/BuiltinCostModel.hs @@ -199,6 +199,7 @@ data BuiltinCostModelBase f , paramScaleValue :: f ModelTwoArguments , -- Batch 7 paramMultiIndexArray :: f ModelTwoArguments + , paramPolicies :: f ModelOneArgument } 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 dc08e6c3c8e..8ca2dec58a0 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExBudgetingDefaults.hs @@ -429,6 +429,7 @@ unitCostBuiltinCostModel = , paramScaleValue = unitCostTwoArguments , -- Batch 7 paramMultiIndexArray = unitCostTwoArguments + , paramPolicies = unitCostOneArgument } unitCekParameters diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V1/ParamName.hs b/plutus-ledger-api/src/PlutusLedgerApi/V1/ParamName.hs index f47c26fb943..bf822368cf2 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V1/ParamName.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V1/ParamName.hs @@ -355,5 +355,9 @@ data ParamName | MultiIndexArray'cpu'arguments'c2 | MultiIndexArray'memory'arguments'intercept | MultiIndexArray'memory'arguments'slope + | Policies'cpu'arguments'intercept + | Policies'cpu'arguments'slope + | Policies'memory'arguments'intercept + | Policies'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 0340acbb802..234d1bf3408 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V2/ParamName.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V2/ParamName.hs @@ -357,5 +357,9 @@ data ParamName | MultiIndexArray'cpu'arguments'c2 | MultiIndexArray'memory'arguments'intercept | MultiIndexArray'memory'arguments'slope + | Policies'cpu'arguments'intercept + | Policies'cpu'arguments'slope + | Policies'memory'arguments'intercept + | Policies'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 5c16e227b78..bac4ef57c7c 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V3/ParamName.hs @@ -373,5 +373,9 @@ data ParamName | MultiIndexArray'cpu'arguments'c2 | MultiIndexArray'memory'arguments'intercept | MultiIndexArray'memory'arguments'slope + | Policies'cpu'arguments'intercept + | Policies'cpu'arguments'slope + | Policies'memory'arguments'intercept + | Policies'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 f7c3565f9c2..1389d1c2013 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V4/ParamName.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V4/ParamName.hs @@ -368,5 +368,9 @@ data ParamName | MultiIndexArray'cpu'arguments'c2 | MultiIndexArray'memory'arguments'intercept | MultiIndexArray'memory'arguments'slope + | Policies'cpu'arguments'intercept + | Policies'cpu'arguments'slope + | Policies'memory'arguments'intercept + | Policies'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 0383ea64207..ec707cfacaf 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 - 337 @=? length v1_ParamNames - 337 @=? length v2_ParamNames - 355 @=? length v3_ParamNames - 355 @=? length v4_ParamNames + 341 @=? length v1_ParamNames + 341 @=? length v2_ParamNames + 359 @=? length v3_ParamNames + 359 @=? length v4_ParamNames , embed $ testCase "tripping paramname" do for_ v1_ParamNames \p -> assertBool "tripping v1 cm params failed" $ diff --git a/plutus-ledger-api/test/Spec/Data/CostModelParams.hs b/plutus-ledger-api/test/Spec/Data/CostModelParams.hs index abadbbbbb05..c913203f08c 100644 --- a/plutus-ledger-api/test/Spec/Data/CostModelParams.hs +++ b/plutus-ledger-api/test/Spec/Data/CostModelParams.hs @@ -41,10 +41,10 @@ tests = "CostModelParams" "costModelParams" [ embed $ testCase "length" do - 337 @=? length v1_ParamNames - 337 @=? length v2_ParamNames - 355 @=? length v3_ParamNames - 355 @=? length v4_ParamNames + 341 @=? length v1_ParamNames + 341 @=? length v2_ParamNames + 359 @=? length v3_ParamNames + 359 @=? length v4_ParamNames , embed $ testCase "tripping paramname" do for_ v1_ParamNames \p -> assertBool "tripping v1 cm params failed" $