diff --git a/core-lib/shared/src/main/scala/special/collection/package.scala b/core-lib/shared/src/main/scala/special/collection/package.scala index 826c1bd3b5..b8be71be23 100644 --- a/core-lib/shared/src/main/scala/special/collection/package.scala +++ b/core-lib/shared/src/main/scala/special/collection/package.scala @@ -20,5 +20,14 @@ package object collection { /** Implicit resolution of `Coll[A]` type descriptor, given a descriptor of `A`. */ implicit def collRType[A](implicit tA: RType[A]): RType[Coll[A]] = CollType[A](tA) + /** Conversion to underlying descriptor class. + * Allows syntax like + * + * ```val tColl: RType[Coll[A]] = ...; tColl.tItem``` + * + * where `tItem` is a method of `CollType`, but is not defined on `RType`. + */ + implicit def downcastCollType[A](ct: RType[Coll[A]]): CollType[A] = ct.asInstanceOf[CollType[A]] + implicit val collBuilderRType: RType[CollBuilder] = RType.fromClassTag(classTag[CollBuilder]) } diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBox.scala b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBox.scala index 37a6e96193..9d373fb36a 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBox.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBox.scala @@ -1,11 +1,11 @@ package org.ergoplatform -import scorex.utils.{Ints, Shorts} -import org.ergoplatform.ErgoBox.{NonMandatoryRegisterId, Token} +import org.ergoplatform.ErgoBox.{AdditionalRegisters, Token} import org.ergoplatform.settings.ErgoAlgos import scorex.crypto.authds.ADKey -import scorex.crypto.hash.{Blake2b256, Digest32} +import scorex.crypto.hash.Blake2b256 import scorex.util._ +import scorex.utils.{Ints, Shorts} import sigmastate.SCollection.SByteArray import sigmastate.SType.AnyOps import sigmastate.Values._ @@ -13,12 +13,10 @@ import sigmastate._ import sigmastate.eval.Extensions._ import sigmastate.eval._ import sigmastate.serialization.SigmaSerializer -import sigmastate.utils.{SigmaByteReader, SigmaByteWriter, Helpers} +import sigmastate.utils.{Helpers, SigmaByteReader, SigmaByteWriter} import sigmastate.utxo.ExtractCreationInfo import special.collection._ -import scala.runtime.ScalaRunTime - /** * Box (aka coin, or an unspent output) is a basic concept of a UTXO-based cryptocurrency. In Bitcoin, such an object * is associated with some monetary value (arbitrary, but with predefined precision, so we use integer arithmetic to @@ -52,7 +50,7 @@ class ErgoBox( override val value: Long, override val ergoTree: ErgoTree, override val additionalTokens: Coll[Token] = Colls.emptyColl[Token], - override val additionalRegisters: Map[NonMandatoryRegisterId, _ <: EvaluatedValue[_ <: SType]] = Map.empty, + override val additionalRegisters: AdditionalRegisters = Map.empty, val transactionId: ModifierId, val index: Short, override val creationHeight: Int @@ -136,7 +134,7 @@ object ErgoBox { /** Represents id of optional registers of a box. */ sealed abstract class NonMandatoryRegisterId(override val number: Byte) extends RegisterId - type AdditionalRegisters = Map[NonMandatoryRegisterId, _ <: EvaluatedValue[_ <: SType]] + type AdditionalRegisters = scala.collection.Map[NonMandatoryRegisterId, EvaluatedValue[_ <: SType]] object R0 extends MandatoryRegisterId(0, "Monetary value, in Ergo tokens") object R1 extends MandatoryRegisterId(1, "Guarding script") diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBoxCandidate.scala b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBoxCandidate.scala index 8d5765caf5..da1fdc94fd 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBoxCandidate.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoBoxCandidate.scala @@ -38,7 +38,7 @@ class ErgoBoxCandidate(val value: Long, val ergoTree: ErgoTree, val creationHeight: Int, val additionalTokens: Coll[Token] = Colls.emptyColl, - val additionalRegisters: Map[NonMandatoryRegisterId, _ <: EvaluatedValue[_ <: SType]] = Map()) + val additionalRegisters: AdditionalRegisters = Map()) extends ErgoBoxAssets { /** Transforms this tree to a proposition, substituting the constants if the constant diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeTransaction.scala b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeTransaction.scala index 5ad3e08207..f5b8a2c15f 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeTransaction.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeTransaction.scala @@ -50,7 +50,6 @@ trait ErgoLikeTransactionTemplate[IT <: UnsignedInput] { lazy val inputIds: IndexedSeq[ADKey] = inputs.map(_.boxId) - override def toString = s"ErgoLikeTransactionTemplate(dataInputs=$dataInputs, inputs=$inputs, outputCandidates=$outputCandidates)" } @@ -76,6 +75,8 @@ class UnsignedErgoLikeTransaction(override val inputs: IndexedSeq[UnsignedInput] } override def hashCode(): Int = id.hashCode() + + override def toString = s"UnsignedErgoLikeTransaction(dataInputs=$dataInputs, inputs=$inputs, outputCandidates=$outputCandidates)" } object UnsignedErgoLikeTransaction { @@ -105,6 +106,7 @@ class ErgoLikeTransaction(override val inputs: IndexedSeq[Input], } override def hashCode(): Int = id.hashCode() + override def toString = s"ErgoLikeTransaction(dataInputs=$dataInputs, inputs=$inputs, outputCandidates=$outputCandidates)" } object ErgoLikeTransactionSerializer extends SigmaSerializer[ErgoLikeTransaction, ErgoLikeTransaction] { diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettings.scala b/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettings.scala index d295b17ce7..fac738ce5a 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettings.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettings.scala @@ -73,7 +73,8 @@ sealed class MapSigmaValidationSettings(private val map: Map[Short, (ValidationR override def equals(obj: Any): Boolean = (this eq obj.asInstanceOf[AnyRef]) || (obj match { case that: MapSigmaValidationSettings => - map.iterator.forall { case (id, v) => that.map.get(id).exists(_ == v) } + map.size == that.map.size && + map.iterator.forall { case (id, v) => that.map.get(id).exists(_ == v) } case _ => false }) diff --git a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/ObjectGenerators.scala b/interpreter/shared/src/test/scala/sigmastate/serialization/generators/ObjectGenerators.scala index 92538aca22..d566e416ba 100644 --- a/interpreter/shared/src/test/scala/sigmastate/serialization/generators/ObjectGenerators.scala +++ b/interpreter/shared/src/test/scala/sigmastate/serialization/generators/ObjectGenerators.scala @@ -210,7 +210,7 @@ trait ObjectGenerators extends TypeGenerators lazy val evaluatedValueGen: Gen[EvaluatedValue[SType]] = Gen.oneOf(booleanConstGen.asInstanceOf[Gen[EvaluatedValue[SType]]], byteArrayConstGen, longConstGen) - def additionalRegistersGen(cnt: Byte): Seq[Gen[(NonMandatoryRegisterId, EvaluatedValue[SType])]] = { + def additionalRegistersGen(cnt: Byte): Seq[Gen[(NonMandatoryRegisterId, EvaluatedValue[_ <: SType])]] = { scala.util.Random.shuffle((0 until cnt).toList) .map(_ + ErgoBox.startingNonMandatoryIndex) .map(rI => ErgoBox.registerByIndex(rI).asInstanceOf[NonMandatoryRegisterId]) @@ -348,7 +348,8 @@ trait ObjectGenerators extends TypeGenerators lazy val additionalRegistersGen: Gen[AdditionalRegisters] = for { regNum <- Gen.chooseNum[Byte](0, ErgoBox.nonMandatoryRegistersCount) regs <- Gen.sequence(additionalRegistersGen(regNum))(Buildable.buildableSeq) - } yield regs.toMap + } yield + Map(regs.toIndexedSeq:_*) def ergoBoxTokens(availableTokens: Seq[TokenId]): Gen[Coll[Token]] = for { tokens <- diff --git a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala index aae3410df4..52e1565ca3 100644 --- a/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala +++ b/sdk/shared/src/main/scala/org/ergoplatform/sdk/JsonCodecs.scala @@ -18,6 +18,7 @@ import sigmastate.interpreter.{ContextExtension, ProverResult} import sigmastate.{AvlTreeData, AvlTreeFlags, SType} import special.collection.Coll import special.sigma.{AnyValue, Header, PreHeader} + import scala.util.Try import sigmastate.utils.Helpers._ // required for Scala 2.11 import org.ergoplatform.ErgoBox @@ -238,9 +239,9 @@ trait JsonCodecs { }) implicit val contextExtensionEncoder: Encoder[ContextExtension] = Encoder.instance({ extension => - extension.values.map { case (key, value) => - key -> evaluatedValueEncoder(value) - }.asJson + Json.obj(extension.values.toSeq.map { case (key, value) => + key.toString -> evaluatedValueEncoder(value) + }: _*) }) implicit val contextExtensionDecoder: Decoder[ContextExtension] = Decoder.instance({ cursor => @@ -259,8 +260,8 @@ trait JsonCodecs { implicit val proverResultDecoder: Decoder[ProverResult] = Decoder.instance({ cursor => for { proofBytes <- cursor.downField("proofBytes").as[Array[Byte]] - extMap <- cursor.downField("extension").as[Map[Byte, EvaluatedValue[SType]]] - } yield ProverResult(proofBytes, ContextExtension(extMap)) + ext <- cursor.downField("extension").as[ContextExtension] + } yield ProverResult(proofBytes, ext) }) @@ -296,13 +297,17 @@ trait JsonCodecs { decodeErgoTree(_.asInstanceOf[ErgoTree]) } - implicit def registersEncoder[T <: EvaluatedValue[_ <: SType]]: Encoder[Map[NonMandatoryRegisterId, T]] = Encoder.instance({ m => + implicit def registersEncoder[T <: EvaluatedValue[_ <: SType]]: Encoder[scala.collection.Map[NonMandatoryRegisterId, T]] = Encoder.instance({ m => Json.obj( m.toSeq .sortBy(_._1.number) .map { case (k, v) => registerIdEncoder(k) -> evaluatedValueEncoder(v) }: _*) }) + implicit def registersDecoder[T <: EvaluatedValue[_ <: SType]]: Decoder[scala.collection.Map[NonMandatoryRegisterId, T]] = Decoder.instance({ implicit m => + m.as[mutable.LinkedHashMap[NonMandatoryRegisterId, EvaluatedValue[SType]]].asInstanceOf[Decoder.Result[scala.collection.Map[NonMandatoryRegisterId, T]]] + }) + implicit val ergoBoxEncoder: Encoder[ErgoBox] = Encoder.instance({ box => Json.obj( "boxId" -> box.id.asJson, @@ -322,7 +327,7 @@ trait JsonCodecs { ergoTreeBytes <- cursor.downField("ergoTree").as[Array[Byte]] additionalTokens <- cursor.downField("assets").as(Decoder.decodeSeq(assetDecoder)) creationHeight <- cursor.downField("creationHeight").as[Int] - additionalRegisters <- cursor.downField("additionalRegisters").as[Map[NonMandatoryRegisterId, EvaluatedValue[SType]]] + additionalRegisters <- cursor.downField("additionalRegisters").as(registersDecoder) transactionId <- cursor.downField("transactionId").as[ModifierId] index <- cursor.downField("index").as[Short] } yield new ErgoBox( @@ -336,62 +341,86 @@ trait JsonCodecs { ) }) + implicit val ergoBoxCandidateEncoder: Encoder[ErgoBoxCandidate] = Encoder.instance({ box => + Json.obj( + "value" -> box.value.asJson, + "ergoTree" -> ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(box.ergoTree).asJson, + "assets" -> box.additionalTokens.toArray.toSeq.asJson, + "creationHeight" -> box.creationHeight.asJson, + "additionalRegisters" -> box.additionalRegisters.asJson + ) + }) + + implicit val ergoBoxCandidateDecoder: Decoder[ErgoBoxCandidate] = Decoder.instance({ cursor => + for { + value <- cursor.downField("value").as[Long] + ergoTreeBytes <- cursor.downField("ergoTree").as[Array[Byte]] + additionalTokens <- cursor.downField("assets").as(Decoder.decodeSeq(assetDecoder)) + creationHeight <- cursor.downField("creationHeight").as[Int] + additionalRegisters <- cursor.downField("additionalRegisters").as(registersDecoder) + } yield new ErgoBoxCandidate( + value = value, + ergoTree = ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(ergoTreeBytes), + creationHeight = creationHeight, + additionalTokens = additionalTokens.toColl, + additionalRegisters = additionalRegisters + ) + }) + implicit val ergoLikeTransactionEncoder: Encoder[ErgoLikeTransaction] = Encoder.instance({ tx => Json.obj( + "type" -> "ELT".asJson, // ErgoLikeTransaction "id" -> tx.id.asJson, "inputs" -> tx.inputs.asJson, "dataInputs" -> tx.dataInputs.asJson, - "outputs" -> tx.outputs.asJson + "outputs" -> tx.outputCandidates.asJson ) }) + implicit val ergoLikeTransactionDecoder: Decoder[ErgoLikeTransaction] = Decoder.instance({ implicit cursor => + for { + t <- cursor.downField("type").as[String] + inputs <- {require(t == "ELT"); cursor.downField("inputs").as[IndexedSeq[Input]] } + dataInputs <- cursor.downField("dataInputs").as[IndexedSeq[DataInput]] + outputs <- cursor.downField("outputs").as[IndexedSeq[ErgoBoxCandidate]] + } yield new ErgoLikeTransaction(inputs, dataInputs, outputs) + }) + implicit val unsignedErgoLikeTransactionEncoder: Encoder[UnsignedErgoLikeTransaction] = Encoder.instance({ tx => Json.obj( + "type" -> "UELT".asJson, // UnsignedErgoLikeTransaction "id" -> tx.id.asJson, "inputs" -> tx.inputs.asJson, "dataInputs" -> tx.dataInputs.asJson, - "outputs" -> tx.outputs.asJson + "outputs" -> tx.outputCandidates.asJson ) }) + implicit val unsignedErgoLikeTransactionDecoder: Decoder[UnsignedErgoLikeTransaction] = Decoder.instance({ implicit cursor => + for { + t <- cursor.downField("type").as[String] + inputs <- {require(t == "UELT"); cursor.downField("inputs").as[IndexedSeq[UnsignedInput]] } + dataInputs <- cursor.downField("dataInputs").as[IndexedSeq[DataInput]] + outputs <- cursor.downField("outputs").as[IndexedSeq[ErgoBoxCandidate]] + } yield new UnsignedErgoLikeTransaction(inputs, dataInputs, outputs) + }) + implicit def ergoLikeTransactionTemplateEncoder[T <: UnsignedInput]: Encoder[ErgoLikeTransactionTemplate[T]] = Encoder.instance({ case transaction: ErgoLikeTransaction => ergoLikeTransactionEncoder(transaction) case transaction: UnsignedErgoLikeTransaction => unsignedErgoLikeTransactionEncoder(transaction) case t => throw new SigmaException(s"Don't know how to encode transaction $t") }) - implicit val transactionOutputsDecoder: Decoder[(ErgoBoxCandidate, Option[BoxId])] = Decoder.instance({ cursor => + implicit val ergoLikeTransactionTemplateDecoder: Decoder[ErgoLikeTransactionTemplate[_ <: UnsignedInput]] = Decoder.instance({ implicit cursor => for { - maybeId <- cursor.downField("boxId").as[Option[BoxId]] - value <- cursor.downField("value").as[Long] - creationHeight <- cursor.downField("creationHeight").as[Int] - ergoTree <- cursor.downField("ergoTree").as[ErgoTree] - assets <- cursor.downField("assets").as[Seq[(ErgoBox.TokenId, Long)]] // TODO optimize: encode directly into Coll avoiding allocation of Tuple2 for each element - registers <- cursor.downField("additionalRegisters").as[Map[NonMandatoryRegisterId, EvaluatedValue[SType]]] - } yield (new ErgoBoxCandidate(value, ergoTree, creationHeight, assets.toColl, registers), maybeId) + t <- cursor.downField("type").as[String] + tx <- t match { + case "ELT" => ergoLikeTransactionDecoder(cursor) + case "UELT" => unsignedErgoLikeTransactionDecoder(cursor) + } + } yield tx }) - implicit val ergoLikeTransactionDecoder: Decoder[ErgoLikeTransaction] = Decoder.instance({ implicit cursor => - for { - inputs <- cursor.downField("inputs").as[IndexedSeq[Input]] - dataInputs <- cursor.downField("dataInputs").as[IndexedSeq[DataInput]] - outputsWithIndex <- cursor.downField("outputs").as[IndexedSeq[(ErgoBoxCandidate, Option[BoxId])]] - } yield new ErgoLikeTransaction(inputs, dataInputs, outputsWithIndex.map(_._1)) - }) - - implicit val unsignedErgoLikeTransactionDecoder: Decoder[UnsignedErgoLikeTransaction] = Decoder.instance({ implicit cursor => - for { - inputs <- cursor.downField("inputs").as[IndexedSeq[UnsignedInput]] - dataInputs <- cursor.downField("dataInputs").as[IndexedSeq[DataInput]] - outputsWithIndex <- cursor.downField("outputs").as[IndexedSeq[(ErgoBoxCandidate, Option[BoxId])]] - } yield new UnsignedErgoLikeTransaction(inputs, dataInputs, outputsWithIndex.map(_._1)) - }) - - implicit val ergoLikeTransactionTemplateDecoder: Decoder[ErgoLikeTransactionTemplate[_ <: UnsignedInput]] = { - ergoLikeTransactionDecoder.asInstanceOf[Decoder[ErgoLikeTransactionTemplate[_ <: UnsignedInput]]] or - unsignedErgoLikeTransactionDecoder.asInstanceOf[Decoder[ErgoLikeTransactionTemplate[_ <: UnsignedInput]]] - } - implicit val sigmaValidationSettingsEncoder: Encoder[SigmaValidationSettings] = Encoder.instance({ v => SigmaValidationSettingsSerializer.toBytes(v).asJson }) diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala index 44d7030df2..e85757985e 100644 --- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala +++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala @@ -19,14 +19,9 @@ import sigmastate.serialization.SerializationSpecification import sigmastate.utils.Helpers.DecoderResultOps // required for Scala 2.11 (extension method toTry) import special.collection.Coll import special.sigma.{Header, PreHeader} -import org.ergoplatform.ErgoLikeContext -import org.ergoplatform.DataInput -import org.ergoplatform.Input -import org.ergoplatform.UnsignedInput -import org.ergoplatform.ErgoBox -import org.ergoplatform.ErgoLikeTransaction -import org.ergoplatform.UnsignedErgoLikeTransaction -import org.ergoplatform.ErgoLikeTransactionTemplate +import org.ergoplatform.{DataInput, ErgoBox, ErgoBoxCandidate, ErgoLikeContext, ErgoLikeTransaction, ErgoLikeTransactionTemplate, Input, UnsignedErgoLikeTransaction, UnsignedInput} + +import scala.collection.mutable class JsonSerializationSpec extends SerializationSpecification with JsonCodecs { @@ -84,43 +79,49 @@ class JsonSerializationSpec extends SerializationSpecification with JsonCodecs { } property("Input should be encoded into JSON and decoded back correctly") { - forAll(inputGen) { v: Input => jsonRoundTrip(v) } + forAll(inputGen, MinSuccessful(50)) { v: Input => jsonRoundTrip(v) } } property("UnsignedInput should be encoded into JSON and decoded back correctly") { - forAll(unsignedInputGen) { v: UnsignedInput => jsonRoundTrip(v) } + forAll(unsignedInputGen, MinSuccessful(50)) { v: UnsignedInput => jsonRoundTrip(v) } } property("ContextExtension should be encoded into JSON and decoded back correctly") { - forAll(contextExtensionGen) { v: ContextExtension => jsonRoundTrip(v) } + forAll(contextExtensionGen, MinSuccessful(500)) { v: ContextExtension => jsonRoundTrip(v) } + } + + property("AdditionalRegisters should be encoded into JSON and decoded back correctly") { + forAll(additionalRegistersGen, MinSuccessful(500)) { regs => + jsonRoundTrip(regs)(registersEncoder, registersDecoder) + } } property("ProverResult should be encoded into JSON and decoded back correctly") { - forAll(serializedProverResultGen) { v: ProverResult => jsonRoundTrip(v) } + forAll(serializedProverResultGen, MinSuccessful(500)) { v: ProverResult => jsonRoundTrip(v) } } property("AvlTreeData should be encoded into JSON and decoded back correctly") { - forAll(avlTreeDataGen) { v: AvlTreeData => jsonRoundTrip(v) } + forAll(avlTreeDataGen, MinSuccessful(500)) { v: AvlTreeData => jsonRoundTrip(v) } } property("ErgoTree should be encoded into JSON and decoded back correctly") { - forAll(ergoTreeGen) { v: ErgoTree => jsonRoundTrip(v) } + forAll(ergoTreeGen, MinSuccessful(500)) { v: ErgoTree => jsonRoundTrip(v) } } property("ErgoBox should be encoded into JSON and decoded back correctly") { - forAll(ergoBoxGen) { v: ErgoBox => jsonRoundTrip(v) } + forAll(ergoBoxGen, MinSuccessful(500)) { v: ErgoBox => jsonRoundTrip(v) } } property("ErgoLikeTransaction should be encoded into JSON and decoded back correctly") { - forAll(ergoLikeTransactionGen) { v: ErgoLikeTransaction => jsonRoundTrip(v) } + forAll(ergoLikeTransactionGen, MinSuccessful(50)) { v: ErgoLikeTransaction => jsonRoundTrip(v) } } property("UnsignedErgoLikeTransaction should be encoded into JSON and decoded back correctly") { - forAll(unsignedErgoLikeTransactionGen) { v: UnsignedErgoLikeTransaction => jsonRoundTrip(v) } + forAll(unsignedErgoLikeTransactionGen, MinSuccessful(50)) { v: UnsignedErgoLikeTransaction => jsonRoundTrip(v) } } property("ErgoLikeTransactionTemplate should be encoded into JSON and decoded back correctly") { - forAll(ergoLikeTransactionTemplateGen) { v: ErgoLikeTransactionTemplate[_ <: UnsignedInput] => + forAll(ergoLikeTransactionTemplateGen, MinSuccessful(50)) { v: ErgoLikeTransactionTemplate[_ <: UnsignedInput] => v.asJson.as(ergoLikeTransactionTemplateDecoder).toTry.get shouldEqual v } } @@ -136,7 +137,7 @@ class JsonSerializationSpec extends SerializationSpecification with JsonCodecs { CryptoConstants.dlogGroup.ctx.decodePoint(point).asInstanceOf[CryptoConstants.EcPointType] ) }.get - val regs = Map( + val regs = scala.collection.Map( R7 -> LongArrayConstant(Array(1L, 2L, 1234123L)), R4 -> ByteConstant(1), R6 -> IntConstant(10),