Skip to content

Commit

Permalink
NODE-2501 Extended log info for nested dApp invocations (#3759)
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-mashonskiy authored Oct 21, 2022
1 parent dc78dea commit 55b619d
Show file tree
Hide file tree
Showing 65 changed files with 4,794 additions and 1,054 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@ package com.wavesplatform.lang
sealed trait ExecutionError {
def message: String
}
case class CommonError(message: String) extends ExecutionError
case class CommonError(details: String, cause: Option[ValidationError] = None) extends ExecutionError {
override def toString: String = s"CommonError($message)"
override def message: String = cause.map(_.toString).getOrElse(details)
}
case class FailOrRejectError(message: String, skipInvokeComplexity: Boolean = true) extends ExecutionError with ValidationError
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import com.wavesplatform.lang.v1.FunctionHeader.Native
import com.wavesplatform.lang.v1.compiler.Terms.EVALUATED
import com.wavesplatform.lang.v1.compiler.Types.CASETYPEREF
import com.wavesplatform.lang.v1.compiler.{CompilerContext, DecompilerContext}
import com.wavesplatform.lang.v1.evaluator.FunctionIds
import com.wavesplatform.lang.v1.evaluator.{FunctionIds, Log}
import com.wavesplatform.lang.v1.evaluator.ctx.EvaluationContext
import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.WavesContext
import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, PureContext}
Expand Down Expand Up @@ -60,7 +60,7 @@ package object utils {
payments: Seq[(Option[Array[Byte]], Long)],
availableComplexity: Int,
reentrant: Boolean
): Coeval[(Either[ValidationError, EVALUATED], Int)] = ???
): Coeval[(Either[ValidationError, (EVALUATED, Log[Id])], Int)] = ???
}

val lazyContexts: Map[(DirectiveSet, Boolean), Coeval[CTX[Environment]]] =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
package com.wavesplatform.lang.v1.compiler

import com.wavesplatform.lang.v1.compiler.Terms.{ARR, CaseObj, EVALUATED}
import com.wavesplatform.common.utils.{Base58, Base64}
import com.wavesplatform.lang.v1.compiler.Terms.{ARR, CONST_BYTESTR, CONST_STRING, CaseObj, EVALUATED}

case class TermPrinter(fixArrIndentation: Boolean = false) {
def prettyString(e: EVALUATED, depth: Int): String = {
e match {
case obj: CaseObj => indentObjString(obj, depth)
case arr: ARR => indentArrString(arr, depth)
case CONST_BYTESTR(bs) =>
if (bs.size > 1024) {
"base64'" ++ Base64.encode(bs.arr) ++ "'"
} else {
"base58'" ++ Base58.encode(bs.arr) ++ "'"
}
case CONST_STRING(s) =>
"\"" ++ escape(s) ++ "\""
case other => other.toString
}
}

object TermPrinter {
def string(e: EVALUATED): String = {
val sb = new StringBuilder()
print(s => sb.append(s), e)
Expand All @@ -15,13 +32,41 @@ object TermPrinter {
sb.mkString
}

def indentArrString(e: ARR, depth: Int): String = {
val sb = new StringBuilder()
if (fixArrIndentation) printArr(s => sb.append(s), e, depth) else printArr(s => sb.append(s), e)
sb.mkString
}

def print(toDest: String => Unit, e: EVALUATED, depth: Int = 0): Unit =
e match {
case obj: CaseObj => printObj(toDest, obj, depth)
case arr: ARR => printArr(toDest, arr)
case a => toDest(a.prettyString(depth))
case arr: ARR => if (fixArrIndentation) printArr(toDest, arr, depth) else printArr(toDest, arr)
case a => toDest(prettyString(a, depth))
}

private def printArr(toDest: String => Unit, arr: ARR, depth: Int): Unit = {
toDest("[")
val length = arr.xs.length
if (length > 0) {
var i = 0
toDest("\n")
while (i < length - 1) {
indent(toDest, depth + 1)
print(toDest, arr.xs(i), depth + 1)
toDest(",\n")
i = i + 1
}
indent(toDest, depth + 1)
print(toDest, arr.xs(length - 1), depth + 1)
toDest("\n")
indent(toDest, depth)
toDest("]")
} else {
toDest("]")
}
}

private def printArr(toDest: String => Unit, arr: ARR): Unit = {
toDest("[")
val length = arr.xs.length
Expand Down Expand Up @@ -61,4 +106,22 @@ object TermPrinter {
i = i - 1
}
}

private def escape(s: String): String = {
// Simple and very naive implementation based on
// https://github.com/linkedin/dustjs/blob/3fc12efd153433a21fd79ac81e8c5f5d6f273a1c/dist/dust-core.js#L1099

// Note this might not be the most efficient since Scala.js compiles this to a bunch of .split and .join calls
s.replace("\\", "\\\\")
.replace("/", "\\/")
.replace("'", "\\'")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t")
.replace("\b", "\\b")
.replace("\f", "\\f")
.replace("\u2028", "\\u2028")
.replace("\u2029", "\\u2029")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@ package com.wavesplatform.lang.v1.compiler
import java.nio.charset.StandardCharsets

import cats.Eval
import cats.instances.list._
import cats.syntax.traverse._
import cats.instances.list.*
import cats.syntax.traverse.*
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils._
import com.wavesplatform.lang.{ExecutionError, CommonError}
import com.wavesplatform.lang.v1.ContractLimits._
import com.wavesplatform.lang.v1.ContractLimits.*
import com.wavesplatform.lang.v1.FunctionHeader
import com.wavesplatform.lang.v1.compiler.Types._
import com.wavesplatform.lang.v1.compiler.Types.*
import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext.MaxListLengthV4
import monix.eval.Coeval

object Terms {
val DataTxMaxBytes: Int = 150 * 1024 // should be the same as DataTransaction.MaxBytes
val DataTxMaxProtoBytes: Int = 165947 // depends from DataTransaction.MaxProtoBytes
val DataEntryValueMax: Int = Short.MaxValue // should be the same as DataEntry.MaxValueSize
val DataTxMaxBytes: Int = 150 * 1024 // should be the same as DataTransaction.MaxBytes
val DataTxMaxProtoBytes: Int = 165947 // depends from DataTransaction.MaxProtoBytes
val DataEntryValueMax: Int = Short.MaxValue // should be the same as DataEntry.MaxValueSize

sealed abstract class DECLARATION {
def name: String
Expand Down Expand Up @@ -147,8 +146,7 @@ object Terms {
}

sealed trait EVALUATED extends EXPR {
def prettyString(level: Int): String = toString
def toStr: Coeval[String] = Coeval.now(toString)
def toStr: Coeval[String] = Coeval.now(toString)
def weight: Long
val getType: REAL // used for _isInstanceOf and therefore for match

Expand All @@ -159,23 +157,17 @@ object Terms {
case class CONST_LONG(t: Long) extends EVALUATED {
override def toString: String = t.toString
override val weight: Long = 8L
override val getType: REAL = LONG
override val getType: REAL = LONG
}
case class CONST_BIGINT(t: BigInt) extends EVALUATED {
override def toString: String = t.toString
override val weight: Long = 64L
override val getType: REAL = BIGINT
override val getType: REAL = BIGINT
}

class CONST_BYTESTR private (val bs: ByteStr) extends EVALUATED {
override def toString: String = bs.toString
override def prettyString(level: Int): String = {
if (bs.size > 1024) {
"base64'" ++ Base64.encode(bs.arr) ++ "'"
} else {
"base58'" ++ Base58.encode(bs.arr) ++ "'"
}
}

override val weight: Long = bs.size

override val getType: REAL = BYTESTR
Expand All @@ -191,9 +183,9 @@ object Terms {

object CONST_BYTESTR {
sealed abstract class Limit(val value: Int)
case object DataEntrySize extends Limit(DataEntryValueMax)
case object DataTxSize extends Limit(DataTxMaxBytes)
case object NoLimit extends Limit(Int.MaxValue)
case object DataEntrySize extends Limit(DataEntryValueMax)
case object DataTxSize extends Limit(DataTxMaxBytes)
case object NoLimit extends Limit(Int.MaxValue)

def apply(bs: ByteStr, limit: Limit = DataEntrySize): Either[CommonError, EVALUATED] =
Either.cond(
Expand All @@ -207,9 +199,8 @@ object Terms {
}

class CONST_STRING private (val s: String, bytesLength: Int) extends EVALUATED {
override def toString: String = s
override def prettyString(level: Int): String = "\"" ++ escape(s) ++ "\""
override lazy val weight: Long = bytesLength
override def toString: String = s
override lazy val weight: Long = bytesLength

override val getType: REAL = STRING

Expand Down Expand Up @@ -241,24 +232,6 @@ object Terms {
Some(arg.s)
}

private def escape(s: String): String = {
// Simple and very naive implementation based on
// https://github.com/linkedin/dustjs/blob/3fc12efd153433a21fd79ac81e8c5f5d6f273a1c/dist/dust-core.js#L1099

// Note this might not be the most efficient since Scala.js compiles this to a bunch of .split and .join calls
s.replace("\\", "\\\\")
.replace("/", "\\/")
.replace("'", "\\'")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t")
.replace("\b", "\\b")
.replace("\f", "\\f")
.replace("\u2028", "\\u2028")
.replace("\u2029", "\\u2029")
}

case class CONST_BOOLEAN(b: Boolean) extends EVALUATED {
override def toString: String = b.toString
override val weight: Long = 1L
Expand All @@ -270,9 +243,8 @@ object Terms {
lazy val FALSE: CONST_BOOLEAN = CONST_BOOLEAN(false)

case class CaseObj private (caseType: CASETYPEREF, fields: Map[String, EVALUATED]) extends EVALUATED {
override def toString: String = TermPrinter.string(this)

override def prettyString(depth: Int): String = TermPrinter.indentObjString(this, depth)
// must be with fixArrIndentation = false, because of makeString behavior before RideV6 (NODE-2370)
override def toString: String = TermPrinter().string(this)

override val weight: Long = OBJ_WEIGHT + FIELD_WEIGHT * fields.size + fields.map(_._2.weight).sum

Expand All @@ -295,7 +267,8 @@ object Terms {
}

abstract case class ARR private (xs: IndexedSeq[EVALUATED]) extends EVALUATED {
override def toString: String = TermPrinter.string(this)
// must be with fixArrIndentation = false, because of makeString behavior before RideV6 (NODE-2370)
override def toString: String = TermPrinter().string(this)

lazy val elementsWeightSum: Long =
weight - EMPTYARR_WEIGHT - ELEM_WEIGHT * xs.size
Expand Down Expand Up @@ -323,8 +296,8 @@ object Terms {

case class FAIL(reason: String) extends EVALUATED {
override def toString: String = "Evaluation failed: " ++ reason
def weight: Long = 0
override val getType: REAL = NOTHING
def weight: Long = 0
override val getType: REAL = NOTHING
}

val runtimeTupleType: CASETYPEREF = CASETYPEREF("Tuple", Nil)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ object ContextfulNativeFunction {
env: C[F],
evaluatedArgs: List[EVALUATED],
availableComplexity: Int
)(implicit m: Monad[CoevalF[F, *]]): Coeval[F[(Either[ExecutionError, EVALUATED], Int)]]
)(implicit m: Monad[CoevalF[F, *]]): Coeval[F[(Either[ExecutionError, (EVALUATED, Log[F])], Int)]]
}
}

Expand Down
Loading

0 comments on commit 55b619d

Please sign in to comment.