diff --git a/src/main/scala/org/ergoplatform/kiosk/ergo/package.scala b/src/main/scala/org/ergoplatform/kiosk/ergo/package.scala index 3d80d39..c332a34 100644 --- a/src/main/scala/org/ergoplatform/kiosk/ergo/package.scala +++ b/src/main/scala/org/ergoplatform/kiosk/ergo/package.scala @@ -2,10 +2,21 @@ package org.ergoplatform.kiosk import org.ergoplatform.kiosk.encoding.ScalaErgoConverters import org.bouncycastle.util.encoders.Hex -import org.ergoplatform.appkit.{BlockchainContext, ErgoType, ErgoValue, InputBox, OutBox} +import org.ergoplatform.appkit.{ + BlockchainContext, + ErgoType, + ErgoValue, + InputBox, + OutBox +} import org.ergoplatform.sdk.ErgoToken import sigmastate.SGroupElement -import sigmastate.Values.{ByteArrayConstant, CollectionConstant, ErgoTree} +import sigmastate.Values.{ + ByteArrayConstant, + CollectionConstant, + ErgoTree, + LongConstant +} import sigmastate.crypto.SecP256K1Group import sigmastate.eval.SigmaDsl import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer @@ -13,6 +24,7 @@ import sigmastate.serialization.ValueSerializer import sigma.Coll import sigma.Colls import sigma.GroupElement +import sigmastate.lang.StdSigmaBuilder.mkTuple import scala.io.BufferedSource import scala.util.Try @@ -22,13 +34,15 @@ package object ergo { def decodeHex = Hex.decode(string) } - implicit def ByteArrayToBetterByteArray(bytes: Array[Byte]): BetterByteArray = new BetterByteArray(bytes) + implicit def ByteArrayToBetterByteArray(bytes: Array[Byte]): BetterByteArray = + new BetterByteArray(bytes) class BetterByteArray(bytes: Seq[Byte]) { def encodeHex: String = Hex.toHexString(bytes.toArray).toLowerCase } - implicit def StringToBetterString(string: String): BetterString = new BetterString(string) + implicit def StringToBetterString(string: String): BetterString = + new BetterString(string) sealed trait KioskType[T] { val serialize: Array[Byte] @@ -40,71 +54,107 @@ package object ergo { override def toString = value.toString } - case class KioskCollByte(arrayBytes: Array[Byte]) extends KioskType[Coll[Byte]] { + case class KioskCollByte(arrayBytes: Array[Byte]) + extends KioskType[Coll[Byte]] { override val value: Coll[Byte] = Colls.fromArray(arrayBytes) - override val serialize: Array[Byte] = ValueSerializer.serialize(ByteArrayConstant(value)) + override val serialize: Array[Byte] = + ValueSerializer.serialize(ByteArrayConstant(value)) override def toString: String = arrayBytes.encodeHex override val typeName: String = "Coll[Byte]" - override def getErgoValue = ErgoValue.of(arrayBytes) + override def getErgoValue = ErgoValue.of(arrayBytes) } - case class KioskCollGroupElement(groupElements: Array[GroupElement]) extends KioskType[Coll[GroupElement]] { + case class KioskCollGroupElement(groupElements: Array[GroupElement]) + extends KioskType[Coll[GroupElement]] { override val value: Coll[GroupElement] = Colls.fromArray(groupElements) - override val serialize: Array[Byte] = ValueSerializer.serialize(CollectionConstant[SGroupElement.type](value, SGroupElement)) - override def toString: String = "[" + groupElements.map(_.getEncoded.toArray.encodeHex).reduceLeft(_ + "," + _) + "]" + override val serialize: Array[Byte] = ValueSerializer.serialize( + CollectionConstant[SGroupElement.type](value, SGroupElement) + ) + override def toString: String = "[" + groupElements + .map(_.getEncoded.toArray.encodeHex) + .reduceLeft(_ + "," + _) + "]" override val typeName: String = "Coll[GroupElement]" - override def getErgoValue = ErgoValue.of(groupElements, ErgoType.groupElementType) + override def getErgoValue = + ErgoValue.of(groupElements, ErgoType.groupElementType) } case class KioskInt(value: Int) extends KioskType[Int] { override val serialize: Array[Byte] = ValueSerializer.serialize(value) - override val typeName: String = "Int" - override def getErgoValue = ErgoValue.of(value) + override val typeName: String = "Int" + override def getErgoValue = ErgoValue.of(value) } case class KioskLong(value: Long) extends KioskType[Long] { override val serialize: Array[Byte] = ValueSerializer.serialize(value) - override val typeName: String = "Long" - override def getErgoValue = ErgoValue.of(value) + override val typeName: String = "Long" + override def getErgoValue = ErgoValue.of(value) } case class KioskBigInt(bigInt: BigInt) extends KioskType[sigma.BigInt] { - override val value: sigma.BigInt = SigmaDsl.BigInt(bigInt.bigInteger) + override val value: sigma.BigInt = SigmaDsl.BigInt(bigInt.bigInteger) override val serialize: Array[Byte] = ValueSerializer.serialize(value) - override val typeName: String = "BigInt" - override def toString: String = bigInt.toString(10) - override def getErgoValue = ErgoValue.of(bigInt.bigInteger) + override val typeName: String = "BigInt" + override def toString: String = bigInt.toString(10) + override def getErgoValue = ErgoValue.of(bigInt.bigInteger) } - case class KioskGroupElement(value: GroupElement) extends KioskType[GroupElement] { + case class KioskGroupElement(value: GroupElement) + extends KioskType[GroupElement] { override val serialize: Array[Byte] = ValueSerializer.serialize(value) + override def toString: String = value.getEncoded.toArray.encodeHex override val typeName: String = "GroupElement" - override def getErgoValue = ErgoValue.of(value) - def +(that: KioskGroupElement) = KioskGroupElement(value.multiply(that.value)) + override def getErgoValue = ErgoValue.of(value) + def +(that: KioskGroupElement) = KioskGroupElement( + value.multiply(that.value) + ) + } + + case class KioskTupleLong(value: (Long, Long)) + extends KioskType[Tuple2[Long, Long]] { + override val serialize: Array[Byte] = ValueSerializer.serialize( + mkTuple(Seq(LongConstant(value._1), LongConstant(value._2))) + ) + override def toString: String = value.toString() + override val typeName: String = "Tuple[Long, Long]" + override def getErgoValue = + ErgoValue.pairOf(ErgoValue.of(value._1), ErgoValue.of(value._2)) } - lazy val PointAtInfinity = KioskGroupElement(SigmaDsl.GroupElement(SecP256K1Group.identity)) + lazy val PointAtInfinity = KioskGroupElement( + SigmaDsl.GroupElement(SecP256K1Group.identity) + ) case class KioskErgoTree(value: ErgoTree) extends KioskType[ErgoTree] { - override val serialize: Array[Byte] = DefaultSerializer.serializeErgoTree(value) + override val serialize: Array[Byte] = + DefaultSerializer.serializeErgoTree(value) override val typeName: String = "ErgoTree" override def getErgoValue = ??? // should never be needed override def toString: ID = "" } - implicit def groupElementToKioskGroupElement(g: GroupElement): KioskGroupElement = KioskGroupElement(g) + implicit def groupElementToKioskGroupElement( + g: GroupElement + ): KioskGroupElement = KioskGroupElement(g) - case class DhtData(g: GroupElement, h: GroupElement, u: GroupElement, v: GroupElement, x: BigInt) + case class DhtData( + g: GroupElement, + h: GroupElement, + u: GroupElement, + v: GroupElement, + x: BigInt + ) - type ID = String + type ID = String type Amount = Long - type Token = (ID, Amount) + type Token = (ID, Amount) type Tokens = Array[Token] - def decodeBigInt(encoded: String): BigInt = Try(BigInt(encoded, 10)).recover { case ex => BigInt(encoded, 16) }.get + def decodeBigInt(encoded: String): BigInt = Try(BigInt(encoded, 10)).recover { + case ex => BigInt(encoded, 16) + }.get case class KioskBox( address: String, @@ -120,11 +170,17 @@ package object ergo { .outBoxBuilder .value(value) .tokens(tokens.map(token => new ErgoToken(token._1, token._2)): _*) - .contract(ctx.newContract(ScalaErgoConverters.getAddressFromString(address).script)) + .contract( + ctx.newContract( + ScalaErgoConverters.getAddressFromString(address).script + ) + ) .registers(registers.map(register => register.getErgoValue): _*) .build() } - def toInBox(txId: String, txIndex: Short)(implicit ctx: BlockchainContext): InputBox = { + def toInBox(txId: String, txIndex: Short)(implicit + ctx: BlockchainContext + ): InputBox = { val outBox = toOutBox outBox.convertToInputWith(txId, txIndex) } @@ -138,7 +194,11 @@ package object ergo { def fromString(str: String): Value = values .find(value => value.toString.equalsIgnoreCase(str)) - .getOrElse(throw new Exception(s"Invalid op $str. Permitted options are ${values.map(_.toString).reduceLeft(_ + ", " + _)}")) + .getOrElse( + throw new Exception( + s"Invalid op $str. Permitted options are ${values.map(_.toString).reduceLeft(_ + ", " + _)}" + ) + ) def toString(op: Value): String = op.toString } }