All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.plasmalabs.quivr.runtime.DynamicContext.scala Maven / Gradle / Ivy

The newest version!
package org.plasmalabs.quivr.runtime

import cats.Monad
import cats.data.EitherT
import org.plasmalabs.common.ParsableDataInterface
import org.plasmalabs.quivr.runtime.QuivrRuntimeErrors.{ContextError, ValidationError}
import org.plasmalabs.quivr.models._
import org.plasmalabs.quivr.algebras.{DigestVerifier, SignatureVerifier}

/**
 * The context that will be provided during evaluation of Quivr protocols. This context provides generic interfaces for digest and signature verificiation
 * . Additionally, a data persing interface may do constructed for retrieving and parsing values not currently supported by Quivr
 * @tparam F execution context of the runtime
 * @tparam K the key type that will be used to lookup values in the generic interface maps
 */
trait DynamicContext[F[_], K, Datum] {
  val datums: K => Option[Datum]

  val interfaces: Map[K, ParsableDataInterface]
  val signingRoutines: Map[K, SignatureVerifier[F]]
  val hashingRoutines: Map[K, DigestVerifier[F]]

  def signableBytes: F[SignableBytes]

  def currentTick: F[Long]

  def heightOf(label: K): F[Option[Long]]

  def digestVerify(routine: K)(verification: DigestVerification)(implicit
    monad: Monad[F]
  ): EitherT[F, QuivrRuntimeError, DigestVerification] = for {
    verifier <- EitherT.fromOption[F](hashingRoutines.get(routine), ContextError.FailedToFindDigestVerifier)
    res      <- EitherT(verifier.validate(verification))
  } yield res

  def signatureVerify(routine: K)(verification: SignatureVerification)(implicit
    monad: Monad[F]
  ): EitherT[F, QuivrRuntimeError, SignatureVerification] = for {
    verifier <- EitherT.fromOption[F](signingRoutines.get(routine), ContextError.FailedToFindSignatureVerifier)
    res      <- EitherT(verifier.validate(verification))
  } yield res

  def useInterface[E, T](label: K)(f: Data => Either[QuivrRuntimeError, T])(ff: T => Boolean)(implicit
    monad: Monad[F]
  ): EitherT[F, QuivrRuntimeError, T] =
    EitherT.fromEither[F](
      interfaces.get(label) match {
        case Some(interface) =>
          interface.parse[QuivrRuntimeError, T](f).flatMap { t =>
            Either.cond(ff(t), t, ValidationError.UserProvidedInterfaceFailure)
          }
        case None => Left(ContextError.FailedToFindInterface)
      }
    )

  def exactMatch(label: K, compareTo: Array[Byte])(implicit
    monad: Monad[F]
  ): EitherT[F, QuivrRuntimeError, Array[Byte]] =
    useInterface(label)(d => Right(d.value))(b => b.toByteArray sameElements compareTo)(monad)
      .map(_.toByteArray)

  def lessThan(label: K, compareTo: BigInt)(implicit
    monad: Monad[F]
  ): EitherT[F, QuivrRuntimeError, BigInt] =
    useInterface(label)(d => Right(BigInt(d.value.toByteArray)))(n => n < compareTo)

  def greaterThan(label: K, compareTo: BigInt)(implicit
    monad: Monad[F]
  ): EitherT[F, QuivrRuntimeError, BigInt] =
    useInterface(label)(d => Right(BigInt(d.value.toByteArray)))(n => n > compareTo)

  def equalTo(label: K, compareTo: BigInt)(implicit
    monad: Monad[F]
  ): EitherT[F, QuivrRuntimeError, BigInt] =
    useInterface(label)(d => Right(BigInt(d.value.toByteArray)))(n => n == compareTo)

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy