diff --git a/interpreter/shared/src/main/scala/sigmastate/Values.scala b/interpreter/shared/src/main/scala/sigmastate/Values.scala index c2b6de9823..1e9114a782 100644 --- a/interpreter/shared/src/main/scala/sigmastate/Values.scala +++ b/interpreter/shared/src/main/scala/sigmastate/Values.scala @@ -15,7 +15,7 @@ import sigmastate.serialization.OpCodes._ import sigmastate.TrivialProp.{FalseProp, TrueProp} import sigmastate.Values.ErgoTree.substConstants import sigmastate.basics.DLogProtocol.ProveDlog -import sigmastate.basics.{ProveDHTuple, CryptoConstants} +import sigmastate.basics.{CryptoConstants, ProveDHTuple} import sigmastate.lang.Terms._ import sigmastate.utxo._ import sigmastate.eval._ @@ -23,7 +23,9 @@ import sigmastate.eval.Extensions._ import scalan.util.Extensions.ByteOps import sigmastate.interpreter.ErgoTreeEvaluator._ import debox.cfor +import scorex.util.encode.Base16 import sigmastate.exceptions.InterpreterException + import scala.language.implicitConversions import scala.reflect.ClassTag import sigmastate.lang.CheckingSigmaBuilder._ @@ -1314,13 +1316,16 @@ object Values { } /** Serialized proposition expression of SigmaProp type with - * ConstantPlaceholder nodes instead of Constant nodes + * ConstantPlaceholder nodes not replaced by Constant nodes. */ lazy val template: Array[Byte] = { val r = SigmaSerializer.startReader(bytes) DefaultSerializer.deserializeHeaderWithTreeBytes(r)._4 } + /** Base16 encoding of `template` bytes. */ + def templateHex: String = Base16.encode(template) + /** Get proposition expression from this contract. * When root.isRight then * if replaceConstants == false this is the same as `root.right.get`. @@ -1496,6 +1501,24 @@ object Values { */ def withSegregation(prop: SigmaPropValue): ErgoTree = withSegregation(DefaultHeader, prop) + + /** Deserializes an ErgoTree instance from a hexadecimal string. + * + * @param hex a hexadecimal string representing the serialized ErgoTree + */ + def fromHex(hex: String): ErgoTree = { + val bytes = Base16.decode(hex).get + fromBytes(bytes) + } + + /** Deserializes an ErgoTree instance from an array of bytes. + * + * @param bytes an array of bytes representing the serialized ErgoTree + */ + def fromBytes(bytes: Array[Byte]): ErgoTree = { + ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes) + } + } } diff --git a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala index d76f54e6e8..20aabb1b00 100644 --- a/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala +++ b/sc/shared/src/test/scala/sigmastate/ErgoTreeSpecification.scala @@ -75,12 +75,19 @@ class ErgoTreeSpecification extends SigmaDslTesting with ContractsTestkit { } property("ErgoTree.template") { - val t = new ErgoTree( - 16.toByte, - Array(IntConstant(1)), - Right(BoolToSigmaProp(EQ(ConstantPlaceholder(0, SInt), IntConstant(1)))) - ) - t.template shouldBe ErgoAlgos.decodeUnsafe("d19373000402") + { + val t = new ErgoTree( + 16.toByte, + Array(IntConstant(1)), + Right(BoolToSigmaProp(EQ(ConstantPlaceholder(0, SInt), IntConstant(1)))) + ) + t.template shouldBe ErgoAlgos.decodeUnsafe("d19373000402") + } + + { + val t = ErgoTree.fromHex("100604000e000400040005000500d803d601e30004d602e4c6a70408d603e4c6a7050595e67201d804d604b2a5e4720100d605b2db63087204730000d606db6308a7d60799c1a7c17204d1968302019683050193c27204c2a7938c720501730193e4c672040408720293e4c672040505720393e4c67204060ec5a796830201929c998c7205029591b1720673028cb272067303000273047203720792720773057202") + t.templateHex shouldBe "d803d601e30004d602e4c6a70408d603e4c6a7050595e67201d804d604b2a5e4720100d605b2db63087204730000d606db6308a7d60799c1a7c17204d1968302019683050193c27204c2a7938c720501730193e4c672040408720293e4c672040505720393e4c67204060ec5a796830201929c998c7205029591b1720673028cb272067303000273047203720792720773057202" + } } property("ErgoTree.bytes") { diff --git a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ErgoTree.scala b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ErgoTree.scala index 672f79e687..810cc1ea81 100644 --- a/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ErgoTree.scala +++ b/sdk/js/src/main/scala/org/ergoplatform/sdk/js/ErgoTree.scala @@ -26,6 +26,14 @@ class ErgoTree(tree: Values.ErgoTree) extends js.Object { /** Serializes the ErgoTree instance to a hexadecimal string. */ def toHex(): String = tree.bytesHex + /** Serialized proposition expression of SigmaProp type with + * ConstantPlaceholder nodes not replaced by Constant nodes. + */ + def template(): Array[Byte] = tree.template + + /** Base16 encoding of `template` bytes. */ + def templateHex(): String = tree.templateHex + /** Returns segregated constants of this tree as [[js.Array]]. */ def constants(): js.Array[Value] = { val constants = tree.constants @@ -42,17 +50,14 @@ object ErgoTree extends js.Object { * * @param hex a hexadecimal string representing the serialized ErgoTree */ - def fromHex(hex: String): ErgoTree = { - val bytes = Base16.decode(hex).get - fromBytes(bytes) - } + def fromHex(hex: String): ErgoTree = + new ErgoTree(Values.ErgoTree.fromHex(hex)) /** Deserializes an ErgoTree instance from an array of bytes. * * @param bytes an array of bytes representing the serialized ErgoTree */ def fromBytes(bytes: Array[Byte]): ErgoTree = { - val tree = ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bytes) - new ErgoTree(tree) + new ErgoTree(Values.ErgoTree.fromBytes(bytes)) } } diff --git a/sigma-js/tests/js/ErgoTree.spec.js b/sigma-js/tests/js/ErgoTree.spec.js index f951b2ea99..688ea9bfa3 100644 --- a/sigma-js/tests/js/ErgoTree.spec.js +++ b/sigma-js/tests/js/ErgoTree.spec.js @@ -29,5 +29,11 @@ describe("Smoke tests for ErgoTree", () => { let constants = tree.constants().map(c => c.toHex()) expect(constants).toEqual(["0400", "0e00", "0400", "0400", "0500", "0500"]) }); + + it("Has template", () => { + let tree = ErgoTreeObj.fromHex(hex); + let templateHex = tree.templateHex(); + expect(templateHex).toEqual("d803d601e30004d602e4c6a70408d603e4c6a7050595e67201d804d604b2a5e4720100d605b2db63087204730000d606db6308a7d60799c1a7c17204d1968302019683050193c27204c2a7938c720501730193e4c672040408720293e4c672040505720393e4c67204060ec5a796830201929c998c7205029591b1720673028cb272067303000273047203720792720773057202") + }); });