@@ -6,30 +6,33 @@ package engine
66package script
77package v2
88
9- import org .apache .pekko .stream .Materializer
109import com .daml .grpc .adapter .ExecutionSequencerFactory
10+ import com .digitalasset .canton .logging .NamedLoggerFactory
1111import com .digitalasset .canton .tracing .TraceContext
12- import com .digitalasset .daml .lf .data .ImmArray
12+ import com .digitalasset .daml .lf .data .{ImmArray , Ref }
13+ import com .digitalasset .daml .lf .engine .ScriptEngine .{
14+ ExtendedValue ,
15+ ExtendedValueClosureBlob ,
16+ ExtendedValueComputationMode ,
17+ runExtendedValueComputation ,
18+ }
1319import com .digitalasset .daml .lf .engine .free .Free
1420import com .digitalasset .daml .lf .engine .script .Runner .IdeLedgerContext
1521import com .digitalasset .daml .lf .engine .script .ledgerinteraction .{
1622 ScriptLedgerClient => UnversionedScriptLedgerClient
1723}
1824import com .digitalasset .daml .lf .engine .script .v2 .ledgerinteraction .ScriptLedgerClient
25+ import com .digitalasset .daml .lf .language .Ast
26+ import com .digitalasset .daml .lf .interpretation .{Error => IE }
1927import com .digitalasset .daml .lf .script .IdeLedger
20- import com .digitalasset .daml .lf .engine .ScriptEngine .{
21- ExtendedValue ,
22- ExtendedValueClosureBlob ,
23- ExtendedValueComputationMode ,
24- runExtendedValueComputation ,
25- }
26- import com .digitalasset .daml .lf .speedy .MachineLogger
27- import com .digitalasset .daml .lf .transaction .{NextGenContractStateMachine => ContractStateMachine }
28- import com .digitalasset .daml .lf .value .Value ._
2928import com .digitalasset .daml .lf .script .converter .ConverterException
30- import com .digitalasset .canton .logging .NamedLoggerFactory
29+ import com .digitalasset .daml .lf .speedy .{MachineLogger , SError }
30+ import com .digitalasset .daml .lf .transaction .{NextGenContractStateMachine => ContractStateMachine }
31+ import com .digitalasset .daml .lf .value .Value
32+ import org .apache .pekko .stream .Materializer
3133
3234import scala .concurrent .{ExecutionContext , Future }
35+ import scala .util .{Failure , Success }
3336
3437private [lf] class Runner (
3538 unversionedRunner : script.Runner ,
@@ -99,14 +102,14 @@ private[lf] class Runner(
99102 }
100103
101104 // Takes a Script X and runs it
102- def runResolved (scriptValue : ExtendedValue , convertLegacyExceptions : Boolean = true )(implicit
105+ def runResolved (scriptValue : ExtendedValue , convertLegacyExceptions : Boolean )(implicit
103106 ec : ExecutionContext ,
104107 esf : ExecutionSequencerFactory ,
105108 mat : Materializer ,
106- ): Future [ExtendedValue ] =
109+ ): Future [ExtendedValue ] = handleLegacyExceptions(convertLegacyExceptions)(
107110 for {
108111 freeClosure <- scriptValue match {
109- case ValueRecord (_, ImmArray ((_, freeClosure : ExtendedValueClosureBlob ), _)) =>
112+ case Value . ValueRecord (_, ImmArray ((_, freeClosure : ExtendedValueClosureBlob ), _)) =>
110113 Future .successful(freeClosure)
111114 case a => Future .failed(new RuntimeException (s " Expected Script a but got $a" ))
112115 }
@@ -115,7 +118,6 @@ private[lf] class Runner(
115118 freeClosure,
116119 unversionedRunner.extendedCompiledPackages,
117120 machineLogger,
118- convertLegacyExceptions,
119121 canceled,
120122 )
121123 result <-
@@ -125,21 +127,21 @@ private[lf] class Runner(
125127 .recover { case err : RuntimeException => Result .failed(err) }
126128 )
127129 } yield result
130+ )
128131
129132 // Takes something that resolves/computes to a Script X, then runs the script
130- def run (comp : ExtendedValueComputationMode , convertLegacyExceptions : Boolean = true )(implicit
133+ def run (comp : ExtendedValueComputationMode , convertLegacyExceptions : Boolean )(implicit
131134 ec : ExecutionContext ,
132135 esf : ExecutionSequencerFactory ,
133136 mat : Materializer ,
134137 ): Future [ExtendedValue ] =
135138 for {
136- scriptValue <- runComputation(comp, convertLegacyExceptions )
139+ scriptValue <- handleLegacyExceptions(convertLegacyExceptions)( runComputation(comp) )
137140 result <- runResolved(scriptValue, convertLegacyExceptions)
138141 } yield result
139142
140143 def runComputation (
141- comp : ExtendedValueComputationMode ,
142- convertLegacyExceptions : Boolean = true ,
144+ comp : ExtendedValueComputationMode
143145 )(implicit ec : ExecutionContext ): Future [ExtendedValue ] =
144146 Future {
145147 runExtendedValueComputation(
@@ -148,7 +150,7 @@ private[lf] class Runner(
148150 unversionedRunner.extendedCompiledPackages,
149151 machineLogger,
150152 iterationsBetweenInterruptions = 100000 ,
151- convertLegacyExceptions,
153+ convertLegacyExceptions = false ,
152154 ).fold(
153155 err => throw err.fold(identity, free.InterpretationError (_)),
154156 identity,
@@ -173,14 +175,67 @@ private[lf] class Runner(
173175 (
174176 unversionedRunner.script match {
175177 case ScriptAction .NoParam (id, _) =>
176- run(ExtendedValueComputationMode .ByIdentifier (id))
178+ run(ExtendedValueComputationMode .ByIdentifier (id), convertLegacyExceptions = true )
177179 case ScriptAction .Param (id, paramType, Some (param), _) =>
178- run(ExtendedValueComputationMode .ByIdentifier (id, Some (List (param))))
180+ run(
181+ ExtendedValueComputationMode .ByIdentifier (id, Some (List (param))),
182+ convertLegacyExceptions = true ,
183+ )
179184 case _ =>
180185 Future .failed(
181186 new RuntimeException (" impossible" )
182187 ) // This case is caught by script.Runner, when a Param ScriptAction is called without a param
183188 },
184189 ideLedgerContext,
185190 )
191+
192+ def makeFailureStatus (excpType : Ref .TypeConId , msg : String ) =
193+ free.InterpretationError (
194+ SError .SErrorDamlException (
195+ IE .FailureStatus (
196+ " UNHANDLED_EXCEPTION/" + excpType.qualifiedName.toString,
197+ Ast .FCInvalidGivenCurrentSystemStateOther .cantonCategoryId,
198+ msg,
199+ Map (),
200+ )
201+ )
202+ )
203+
204+ def handleLegacyExceptions [X ](
205+ convertLegacyExceptions : Boolean
206+ )(x : Future [X ])(implicit ec : ExecutionContext ) =
207+ x.recoverWith {
208+ case free.InterpretationError (
209+ SError .SErrorDamlException (IE .UnhandledException (Ast .TTyCon (excpType), value))
210+ ) if convertLegacyExceptions =>
211+ convertLegacyException(excpType, value)
212+ }
213+
214+ def convertLegacyException (excpType : Ref .TypeConId , value : ExtendedValue )(implicit
215+ ec : ExecutionContext
216+ ): Future [Nothing ] = {
217+ runComputation(
218+ ExtendedValueComputationMode .ByExceptionMessage (excpType, value)
219+ ).transform { result =>
220+ val error = result match {
221+ case Success (Value .ValueText (msg)) =>
222+ makeFailureStatus(excpType, msg)
223+ case Success (_) =>
224+ new RuntimeException (s " Message computation for exception $excpType did not give Text " )
225+ case Failure (
226+ free.InterpretationError (
227+ SError .SErrorDamlException (
228+ IE .UnhandledException (Ast .TTyCon (messageExceptionName), _)
229+ )
230+ )
231+ ) =>
232+ makeFailureStatus(
233+ excpType,
234+ s " <Failed to calculate message as ${messageExceptionName.qualifiedName.toString} was thrown during conversion> " ,
235+ )
236+ case Failure (error) => error
237+ }
238+ Failure (error)
239+ }
240+ }
186241}
0 commit comments