Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:ScorexFoundation/sigmastate-inte…
Browse files Browse the repository at this point in the history
…rpreter into distributed-sigs
  • Loading branch information
kushti committed Aug 11, 2020
2 parents e4cae3c + 0905651 commit 8d6865a
Show file tree
Hide file tree
Showing 15 changed files with 3,207 additions and 1,373 deletions.
40 changes: 36 additions & 4 deletions library-api/src/main/scala/special/collection/Colls.scala
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,12 @@ trait Coll[@specialized A] {
*/
def reverse: Coll[A]

/** Checks if this collection is a replication of the given value a given number of times.
*
* @param len how many times the `value` is replicated
* @param value the replicated value
* @return true if this collection is element-wise equal to a collection of replicated values.
*/
@Internal
private[collection] def isReplArray(len: Int, value: A): Boolean

Expand Down Expand Up @@ -427,9 +433,26 @@ trait ReplColl[@specialized A] extends Coll[A] {
@scalan.Liftable
@WithMethodCallRecognizers
trait CollBuilder {
/** Monoid builder associated with this collections builder.
* It should be used to create monoids which are required by some of the Coll methods.
*/
def Monoids: MonoidBuilder

/** Constructs a new collection of pairs out of the pair of collections by zipping them.
* The resulting collection is semantically equivalent to `as.zip(bs)`.
* @param as collection of first items
* @param bs collection of second items
* @return an instance of [[PairColl]] interface with represents the resulting collection of pairs.
*/
def pairColl[@specialized A, @specialized B](as: Coll[A], bs: Coll[B]): PairColl[A,B]

/** Constructs a new collection of pairs out of the pair of arrays by wrapping them in collections
* and delegating to [[pairColl]] method.
* The resulting collection is semantically equivalent to as.zip(bs).
* @param as collection of first items
* @param bs collection of second items
* @return an instance of [[PairColl]] interface with represents the resulting collection of pairs.
*/
@Internal
def pairCollFromArrays[A: RType, B: RType](as: Array[A], bs: Array[B]): PairColl[A,B] =
pairColl(fromArray(as), fromArray(bs))
Expand Down Expand Up @@ -471,6 +494,16 @@ trait CollBuilder {
@Internal
def makeView[@specialized A, @specialized B: RType](source: Coll[A], f: A => B): Coll[B]

/** Create a new view using pre-calculated results of `f`.
*
* @param source the collection the view is based on.
* @param f view function, which transforms each pre-image element to the
* corresponding `image` element of the resulting collection
* @param calculated array of flags marking which element where pre-calculated
* @param calculatedItems pre-calculated images to be used in the resulting collection
* so that `calculated.length == calculatedItems.length`
* @return collection of images of `f`
*/
@Internal
def makePartialView[@specialized A, @specialized B: RType](source: Coll[A], f: A => B, calculated: Array[Boolean], calculatedItems: Array[B]): Coll[B]

Expand All @@ -492,11 +525,10 @@ trait CollBuilder {
(left: Coll[(K, L)], right: Coll[(K, R)])
(l: ((K,L)) => O, r: ((K,R)) => O, inner: ((K,(L,R))) => O): Coll[(K,O)]

/** Flattens a two-dimensional array by concatenating all its rows
* into a single array.
/** Flattens a two-dimensional collection by concatenating all its rows
* into a single collection.
*
* @tparam U Type of row elements.
* @param asTrav A function that converts elements of this array to rows - arrays of type `U`.
* @tparam A Type of row elements.
* @return An array obtained by concatenating rows of this array.
*/
def flattenColl[A:RType](coll: Coll[Coll[A]]): Coll[A]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ class CollOverArray[@specialized A](val toArray: Array[A])(implicit tA: RType[A]
}

@Internal
def isReplArray(len: Int, value: A): Boolean = {
override def isReplArray(len: Int, value: A): Boolean = {
length == len && {
if (tItem.classTag.runtimeClass.isPrimitive) {
isAllPrimValue(value)
Expand All @@ -210,7 +210,14 @@ class CollOverArray[@specialized A](val toArray: Array[A])(implicit tA: RType[A]
class CollOverArrayBuilder extends CollBuilder {
override def Monoids: MonoidBuilder = new MonoidBuilderInst

@inline def pairColl[@specialized A, @specialized B](as: Coll[A], bs: Coll[B]): PairColl[A, B] = new PairOfCols(as, bs)
@inline override def pairColl[@specialized A, @specialized B](as: Coll[A], bs: Coll[B]): PairColl[A, B] = {
// TODO HF: use minimal length and slice longer collection
// The current implementation doesn't check the case when `as` and `bs` have different lengths.
// in which case the implementation of `PairOfCols` has inconsistent semantics of `map`, `exists` etc methods.
// To fix the problem, the longer collection have to be truncated (which is consistent
// with how zip is implemented for Arrays)
new PairOfCols(as, bs)
}

@Internal
override def fromMap[K: RType, V: RType](m: Map[K, V]): Coll[(K, V)] = {
Expand All @@ -233,7 +240,7 @@ class CollOverArrayBuilder extends CollBuilder {

@NeverInline
@Reified("T")
def fromItems[T](items: T*)(implicit cT: RType[T]): Coll[T] = cT match {
override def fromItems[T](items: T*)(implicit cT: RType[T]): Coll[T] = cT match {
case pt: PairType[a,b] =>
val tA = pt.tFst
val tB = pt.tSnd
Expand All @@ -243,7 +250,7 @@ class CollOverArrayBuilder extends CollBuilder {
}

@NeverInline
def fromArray[@specialized T: RType](arr: Array[T]): Coll[T] = RType[T] match {
override def fromArray[@specialized T: RType](arr: Array[T]): Coll[T] = RType[T] match {
case pt: PairType[a,b] =>
val tA = pt.tFst
val tB = pt.tSnd
Expand All @@ -253,7 +260,7 @@ class CollOverArrayBuilder extends CollBuilder {
}

@NeverInline
def replicate[@specialized T: RType](n: Int, v: T): Coll[T] = RType[T] match {
override def replicate[@specialized T: RType](n: Int, v: T): Coll[T] = RType[T] match {
case pt: PairType[a,b] =>
val tA = pt.tFst
val tB = pt.tSnd
Expand All @@ -264,15 +271,15 @@ class CollOverArrayBuilder extends CollBuilder {
}

@NeverInline
def makeView[@specialized A, @specialized B: RType](source: Coll[A], f: A => B): Coll[B] = new CViewColl(source, f)
override def makeView[@specialized A, @specialized B: RType](source: Coll[A], f: A => B): Coll[B] = new CViewColl(source, f)

@NeverInline
def makePartialView[@specialized A, @specialized B: RType](source: Coll[A], f: A => B, calculated: Array[Boolean], calculatedItems: Array[B]): Coll[B] = {
override def makePartialView[@specialized A, @specialized B: RType](source: Coll[A], f: A => B, calculated: Array[Boolean], calculatedItems: Array[B]): Coll[B] = {
new CViewColl(source, f).fromPartialCalculation(calculated, calculatedItems)
}

@NeverInline
def unzip[@specialized A, @specialized B](xs: Coll[(A,B)]): (Coll[A], Coll[B]) = xs match {
override def unzip[@specialized A, @specialized B](xs: Coll[(A,B)]): (Coll[A], Coll[B]) = xs match {
case pa: PairColl[_,_] => (pa.ls, pa.rs)
case _ =>
val limit = xs.length
Expand All @@ -289,7 +296,7 @@ class CollOverArrayBuilder extends CollBuilder {
}

@NeverInline
def xor(left: Coll[Byte], right: Coll[Byte]): Coll[Byte] = left.zip(right).map { case (l, r) => (l ^ r).toByte }
override def xor(left: Coll[Byte], right: Coll[Byte]): Coll[Byte] = left.zip(right).map { case (l, r) => (l ^ r).toByte }

@NeverInline
override def emptyColl[T](implicit cT: RType[T]): Coll[T] = cT match {
Expand Down
14 changes: 13 additions & 1 deletion sigma-api/src/main/scala/special/sigma/SigmaDsl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,13 @@ trait SigmaProp {
@OverloadId("or_bool") def ||(other: Boolean): SigmaProp
}

/** Represents any value paired with type descriptor. */
@scalan.Liftable
@WithMethodCallRecognizers
trait AnyValue {
/** The data value wrapped by this instance. */
def value: Any
/** The type descriptor of the `value` instance. */
def tVal: RType[Any]
}

Expand Down Expand Up @@ -697,7 +700,16 @@ trait SigmaContract {
(implicit cT: RType[T]): Coll[Byte] = this.builder.substConstants(scriptBytes, positions, newValues)
}

/** Runtime representation of Global ErgoTree type. */
/** Runtime representation of SGlobal ErgoTree type.
* The only instance of SGlobal type can be referenced as `Global` variable in ErgoScript.
* It is represented as [[org.ergoplatform.Global]] node of ErgoTree, which evaluates to
* the default singleton instance of this interface.
*
* CostingSigmaDslBuilder object serves as the default singleton instance of Global
* object, which implements global ErgoTree functions.
*
* @see SGlobal.WrappedType, CostingSigmaDslBuilder
*/
@scalan.Liftable
@WithMethodCallRecognizers
trait SigmaDslBuilder {
Expand Down
10 changes: 9 additions & 1 deletion sigma-impl/src/main/scala/special/sigma/TestContext.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
package special.sigma

import scalan.OverloadHack.Overloaded1
import scalan.RType

// TODO refactor: move to sigmastate package and rename to CAnyValue

/** Default implementation of AnyValue interface. */
case class TestValue[A](value: A, tVal: RType[Any]) extends AnyValue {
def tA: RType[A] = tVal.asInstanceOf[RType[A]]
override def toString = s"Value($value)"
override def toString = s"TestValue($value)"
}

object TestValue {
def apply[A](value: A, t: RType[A])(implicit o: Overloaded1): TestValue[A] =
new TestValue(value, t.asInstanceOf[RType[Any]])
}
11 changes: 5 additions & 6 deletions sigmastate/src/main/scala/sigmastate/eval/BigIntegerOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,23 @@ import java.math.BigInteger

import scalan.{ExactNumeric, ExactIntegral, ExactOrderingImpl}

import scala.math.{LowPriorityOrderingImplicits, Integral, Ordering}
import scala.math.{Integral, Ordering}
import special.sigma._
import scalan.util.Extensions._
import sigmastate.eval.Extensions._
import sigmastate.eval.NumericOps.BigIntIsExactNumeric.n
import special.collection.Coll

object OrderingOps extends LowPriorityOrderingImplicits {
object OrderingOps {
def apply[T](implicit ord: Ordering[T]) = ord

trait BigIntegerOrdering extends Ordering[BigInteger] {
def compare(x: BigInteger, y: BigInteger) = x.compareTo(y)
}
implicit object BigInteger extends BigIntegerOrdering
implicit object BigIntegerOrdering extends BigIntegerOrdering

trait BigIntOrdering extends Ordering[BigInt] {
def compare(x: BigInt, y: BigInt) = x.compareTo(y)
}
implicit object BigInt extends BigIntOrdering
implicit object BigIntOrdering extends BigIntOrdering
}

object NumericOps {
Expand Down
10 changes: 10 additions & 0 deletions sigmastate/src/main/scala/sigmastate/eval/CostingDataContext.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import java.math.BigInteger
import java.util

import org.bouncycastle.math.ec.ECPoint
import org.ergoplatform.settings.ErgoAlgos
import org.ergoplatform.{ErgoBox, SigmaConstants}
import org.ergoplatform.validation.ValidationRules
import scorex.crypto.authds.avltree.batch._
Expand Down Expand Up @@ -621,6 +622,13 @@ class CostingSigmaDslBuilder extends TestSigmaDslBuilder { dsl =>
this.GroupElement(CryptoConstants.dlogGroup.generator)
}

/**
* @return the identity of the Dlog group used in ErgoTree
*/
def groupIdentity: GroupElement = {
this.GroupElement(CryptoConstants.dlogGroup.identity)
}

override def substConstants[T](scriptBytes: Coll[Byte],
positions: Coll[Int],
newValues: Coll[T])
Expand All @@ -635,8 +643,10 @@ class CostingSigmaDslBuilder extends TestSigmaDslBuilder { dsl =>
val p = GroupElementSerializer.parse(r)
this.GroupElement(p)
}

}

/** Default singleton instance of Global object, which implements global ErgoTree functions. */
object CostingSigmaDslBuilder extends CostingSigmaDslBuilder

/** A default implementation of [[Context]] interface.
Expand Down
26 changes: 26 additions & 0 deletions sigmastate/src/main/scala/sigmastate/utils/Helpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ package sigmastate.utils
import java.util

import io.circe.Decoder
import org.ergoplatform.settings.ErgoAlgos
import sigmastate.eval.{Colls, SigmaDsl}
import sigmastate.interpreter.CryptoConstants.EcPointType
import special.collection.Coll
import special.sigma.GroupElement

import scala.reflect.ClassTag
import scala.util.{Failure, Try, Either, Success, Right}
Expand Down Expand Up @@ -127,6 +132,27 @@ object Helpers {
}
}

/** Decodes the given hex string into byte array and then uses
* [[SigmaDsl.decodePoint()]] to construct [[GroupElement]] instance.
*/
def decodeGroupElement(hexString: String): GroupElement = {
val bytes = ErgoAlgos.decodeUnsafe(hexString)
SigmaDsl.decodePoint(Colls.fromArray(bytes))
}

/** Decodes the given hex string into [[GroupElement]] and then extracts the underlying
* [[EcPointType]] instance
*/
def decodeECPoint(hexString: String): EcPointType = {
val ge = decodeGroupElement(hexString)
SigmaDsl.toECPoint(ge).asInstanceOf[EcPointType]
}

/** Decodes the given hex string into a collection of bytes. */
def decodeBytes(base16String: String): Coll[Byte] = {
val bytes = ErgoAlgos.decodeUnsafe(base16String)
Colls.fromArray(bytes)
}
}

object Overloading {
Expand Down
Loading

0 comments on commit 8d6865a

Please sign in to comment.