Skip to content

Commit a093aff

Browse files
carlpulley-daremyhaemmerle-da
authored andcommitted
Implement Daml/Engine cost model infrastructure for pure builtins (#21668)
* Implement Daml/Engine cost model infrastructure for pure builtins * Add in checks for pure builtins being within cost budgets * Build fixes * grpc parser fixes * More ci fixes * script service protobuf fixes * compiler fixes * doc sync * Move Cost.Error into Dev scope * build fix * doc sync
1 parent 66c2cc6 commit a093aff

File tree

6 files changed

+435
-89
lines changed

6 files changed

+435
-89
lines changed

sdk/compiler/script-service/server/src/main/scala/com/digitalasset/daml/lf/script/Conversions.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ final class Conversions(
278278
.setExpected(convertIdentifier(expected))
279279
.addAllAccepted(accepted.map(convertIdentifier(_)).asJava)
280280
)
281+
case Dev.Cost(Dev.Cost.BudgetExceeded(cause)) =>
282+
builder.setCrash(cause)
281283
}
282284
case _: Upgrade =>
283285
builder.setUpgradeError(

sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/CostModel.scala

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
package com.digitalasset.daml.lf
55
package speedy
66

7+
import com.digitalasset.daml.lf.speedy.SError.SErrorCrash
78
import com.digitalasset.daml.lf.speedy.SValue._
89
import data.{FrontStack, Ref}
910

10-
abstract class CostModel {
11+
abstract class CostModel(maximumCost: CostModel.Cost) {
1112

1213
import CostModel._
1314

@@ -89,13 +90,22 @@ abstract class CostModel {
8990
val BTypeRepTyConName = NotDefined
9091
val BFailWithStatus = NotDefined
9192

92-
def update(cost: Cost): Unit
93+
private[this] var totalCost: Cost = 0
9394

94-
def undefined(cost: NotDefined.type): Unit
95+
private[speedy] final def update(cost: Cost): Unit = {
96+
if (totalCost + cost <= maximumCost) {
97+
totalCost += cost
98+
} else {
99+
throw SErrorCrash(
100+
getClass.getCanonicalName,
101+
s"Current interpretation has used $totalCost, so an operation with cost $cost will exceed maximum budgeted cost of $maximumCost",
102+
)
103+
}
104+
}
95105

96-
def costAware(cost: CostAware.type): Unit
106+
private[speedy] final def undefined(cost: NotDefined.type): Unit = {}
97107

98-
def getCost: Cost
108+
private[speedy] final def costAware(cost: CostAware.type): Unit = {}
99109
}
100110

101111
object CostModel {
@@ -142,7 +152,7 @@ object CostModel {
142152
override def cost(x: Y, y: Y, z: Z): Cost = c
143153
}
144154

145-
object EmptyModel extends CostModel {
155+
object EmptyModel extends CostModel(0) {
146156
override val AddNumeric: CostFunction2[Numeric, Numeric] = ConstantCost2(0)
147157
override val SubNumeric: CostFunction2[Numeric, Numeric] = ConstantCost2(0)
148158
override val MulNumeric: CostFunction3[Numeric, Numeric, Numeric] = ConstantCost3(0)
@@ -195,15 +205,5 @@ object CostModel {
195205
override val BGreater: CostFunction2[Value, Value] = ConstantCost2(0)
196206
override val BGreaterEq: CostFunction2[Value, Value] = ConstantCost2(0)
197207
override val BCoerceContractId: CostFunction1[ContractId] = ConstantCost1(0)
198-
199-
override def update(cost: Cost): Unit = {}
200-
201-
override def undefined(cost: NotDefined.type): Unit = {}
202-
203-
override def costAware(cost: CostAware.type): Unit = {}
204-
205-
override def getCost: Cost = {
206-
0
207-
}
208208
}
209209
}

sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ private[lf] object Pretty {
254254
) & prettyTypeConId(
255255
actual
256256
)
257+
case Dev.Cost(Dev.Cost.BudgetExceeded(cause)) =>
258+
text("Cost budget has been exceeded:") /
259+
text(cause)
257260
}
258261
}
259262
}

0 commit comments

Comments
 (0)