Skip to content

Commit

Permalink
Merge pull request #2089 from wavesplatform/sc-140-add-directives-to-…
Browse files Browse the repository at this point in the history
…decompiled-script

SC-140 Add directives to decompiled script
  • Loading branch information
ismagin authored Mar 26, 2019
2 parents 220b475 + a7a867f commit d6b9716
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 9 deletions.
17 changes: 13 additions & 4 deletions src/main/scala/com/wavesplatform/api/http/UtilsApiRoute.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,24 @@ case class UtilsApiRoute(timeService: Time, settings: RestAPISettings) extends A
new ApiResponse(code = 200, message = "string or error")
))
def decompile: Route = path("script" / "decompile") {
import play.api.libs.json.Json.toJsFieldJsValueWrapper

(post & entity(as[String])) { code =>
Script.fromBase64String(code, checkComplexity = false) match {
case Left(err) => complete(err)
case Right(script) =>
val ret = Script.decompile(script)
val (scriptText, meta) = Script.decompile(script)
val directives: List[(String, JsValue)] = meta.map {
case (k, v) =>
(k, v match {
case n: Number => JsNumber(BigDecimal(n.toString))
case s => JsString(s.toString)
})
}
val result = directives ::: "script" -> JsString(scriptText) :: Nil
val wrapped = result.map { case (k, v) => (k, toJsFieldJsValueWrapper(v)) }
complete(
Json.obj(
"script" -> ret.toString,
)
Json.obj(wrapped: _*)
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.wavesplatform.transaction.smart.script

import com.wavesplatform.lang.ContentType.{ContentType, DApp, Expression}
import com.wavesplatform.lang.ScriptType.{Account, Asset, ScriptType}
import com.wavesplatform.lang.StdLibVersion.{StdLibVersion, V1, V2, V3}
import shapeless.Poly1

object PolyDecompile extends Poly1 {
implicit def decompile[A](implicit d: Decompile[A]) = at[A](d.decompile)
}

trait Decompile[A] {
def decompile(value: A): (String, Any) = (key, decompileValue(value))
def key: String
def decompileValue(value: A): Any
}

object DecompileInstances {
implicit val versionDecompiler = new Decompile[StdLibVersion] {
override def key = "STDLIB_VERSION"
override def decompileValue(value: StdLibVersion): Int = value match {
case V1 => 1
case V2 => 2
case V3 => 3
}
}

implicit val expressionDecompiler = new Decompile[ContentType] {
override def key = "CONTENT_TYPE"
override def decompileValue(value: ContentType): String = value match {
case Expression => "EXPRESSION"
case DApp => "DAPP"
}
}

implicit val scriptDecompiler = new Decompile[ScriptType] {
override def key = "SCRIPT_TYPE"
override def decompileValue(value: ScriptType): String = value match {
case Account => "ACCOUNT"
case Asset => "ASSET"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ package com.wavesplatform.transaction.smart.script

import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils.Base64
import com.wavesplatform.lang.ContentType.{DApp, Expression}
import com.wavesplatform.lang.ScriptType.Account
import com.wavesplatform.lang.StdLibVersion._
import com.wavesplatform.lang.v1.compiler.Decompiler
import com.wavesplatform.transaction.ValidationError.ScriptParseError
import com.wavesplatform.utils.defaultDecompilerContext
import com.wavesplatform.transaction.smart.script.ContractScript.ContractScriptImpl
import monix.eval.Coeval
import com.wavesplatform.transaction.smart.script.v1.ExprScript
import DecompileInstances._
import shapeless.HList

trait Script {
type Expr
Expand Down Expand Up @@ -38,9 +44,23 @@ object Script {
script <- ScriptReader.fromBytes(bytes, checkComplexity = checkComplexity)
} yield script

def decompile(s: Script): String = s match {
case e: ExprScript => Decompiler(e.expr, com.wavesplatform.utils.defaultDecompilerContext)
case com.wavesplatform.transaction.smart.script.ContractScript.ContractScriptImpl(_, contract, _) =>
Decompiler(contract, com.wavesplatform.utils.defaultDecompilerContext)
type DirectiveMeta = List[(String, Any)]

def decompile(s: Script): (String, DirectiveMeta) = {
val (scriptText, directives: DirectiveMeta) = s match {
case e: ExprScript =>
val directives = HList(s.stdLibVersion, Expression).map(PolyDecompile).toList
val decompiler = Decompiler(e.expr, defaultDecompilerContext)
(decompiler, directives)
case ContractScriptImpl(_, contract, _) =>
val directives = HList(s.stdLibVersion, Account, DApp).map(PolyDecompile).toList
val decompiler = Decompiler(contract, defaultDecompilerContext)
(decompiler, directives)
}
val directivesText = directives
.map { case (key, value) => s"{-#$key $value#-}" }
.mkString(start = "", sep = "\n", end = "\n")

(directivesText + scriptText, directives)
}
}
30 changes: 29 additions & 1 deletion src/test/scala/com/wavesplatform/http/UtilsRouteSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,35 @@ class UtilsRouteSpec extends RouteSpec("/utils") with RestAPISettingsHelper with
val base64 = ExprScript(script).explicitGet().bytes().base64
Post(routePath("/script/decompile"), base64) ~> route ~> check {
val json = responseAs[JsValue]
(json \ "script").as[String] shouldBe "(1 == 2)"
(json \ "STDLIB_VERSION").as[Int] shouldBe 1
(json \ "CONTENT_TYPE").as[String] shouldBe "EXPRESSION"
(json \ "script").as[String] shouldBe "" +
"{-#STDLIB_VERSION 1#-}\n" +
"{-#CONTENT_TYPE EXPRESSION#-}\n" +
"(1 == 2)"
}

Post(routePath("/script/decompile"), "AgZ7TN8j") ~> route ~> check {
val json = responseAs[JsValue]
(json \ "STDLIB_VERSION").as[Int] shouldBe 2
(json \ "CONTENT_TYPE").as[String] shouldBe "EXPRESSION"
(json \ "script").as[String] shouldBe "" +
"{-#STDLIB_VERSION 2#-}\n" +
"{-#CONTENT_TYPE EXPRESSION#-}\n" +
"true"
}

Post(routePath("/script/decompile"), "AAIDAAAAAAAAAAAAAAAAAAAAAQAAAAJ0eAEAAAAGdmVyaWZ5AAAAAAbAmSEV") ~> route ~> check {
val json = responseAs[JsValue]
(json \ "STDLIB_VERSION").as[Int] shouldBe 3
(json \ "CONTENT_TYPE").as[String] shouldBe "DAPP"
(json \ "SCRIPT_TYPE").as[String] shouldBe "ACCOUNT"
(json \ "script").as[String] shouldBe "" +
"{-#STDLIB_VERSION 3#-}\n" +
"{-#SCRIPT_TYPE ACCOUNT#-}\n" +
"{-#CONTENT_TYPE DAPP#-}\n\n\n\n" +
"@Verifier(tx)\n" +
"func verify () = true\n"
}
}

Expand Down

0 comments on commit d6b9716

Please sign in to comment.