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

sparkz.mid.state.BoxMinimalState.scala Maven / Gradle / Ivy

The newest version!
package sparkz.mid.state

import sparkz.core.transaction.BoxTransaction
import sparkz.core.transaction.box.Box
import sparkz.core.transaction.box.proposition.Proposition
import sparkz.core.transaction.state.{BoxStateChanges, MinimalState, ModifierValidation, TransactionValidation}
import sparkz.core.{PersistentNodeViewModifier, VersionTag, idToVersion}

import scala.util.{Failure, Success, Try}


trait BoxMinimalState[P <: Proposition,
  BX <: Box[P],
  BTX <: BoxTransaction[P, BX],
  M <: PersistentNodeViewModifier,
  BMS <: BoxMinimalState[P, BX, BTX, M, BMS]]
  extends MinimalState[M, BMS] with TransactionValidation[BTX] with ModifierValidation[M] {
  self: BMS =>

  def closedBox(boxId: Array[Byte]): Option[BX]

  def boxesOf(proposition: P): Seq[BX]

  def changes(mod: M): Try[BoxStateChanges[P, BX]]

  def applyChanges(changes: BoxStateChanges[P, BX], newVersion: VersionTag): Try[BMS]

  override def applyModifier(mod: M): Try[BMS] = {
    validate(mod) flatMap {_ =>
      changes(mod).flatMap(cs => applyChanges(cs, idToVersion(mod.id)))
    }
  }

 override def validate(mod: M): Try[Unit]

  /**
    * A transaction is valid against a state if:
    * - boxes a transaction is opening are stored in the state as closed
    * - sum of values of closed boxes = sum of values of open boxes - fee
    * - all the signatures for open boxes are valid(against all the txs bytes except of sigs)
    *
    * - fee >= 0
    *
    * specific semantic rules are applied
    *
    * @param tx - transaction to check against the state
    * @return
    */
  override def validate(tx: BTX): Try[Unit] = {
    val statefulValid = {
      val boxesSumTry = tx.unlockers.foldLeft[Try[Long]](Success(0L)) { case (partialRes, unlocker) =>
        partialRes.flatMap { partialSum =>
          closedBox(unlocker.closedBoxId) match {
            case Some(box) =>
              if (unlocker.boxKey.isValid(box.proposition, tx.messageToSign)) {
                Success(partialSum + box.value)
              } else {
                Failure(new Exception("Incorrect unlocker"))
              }
            case None => Failure(new Exception(s"Box for unlocker $unlocker is not in the state"))
          }
        }
      }

      boxesSumTry flatMap { openSum =>
        if (tx.newBoxes.map(_.value).sum == openSum - tx.fee) {
          Success(())
        } else {
          Failure(new Exception("Negative fee"))
        }
      }
    }
    statefulValid.flatMap(_ => semanticValidity(tx))
  }

  def semanticValidity(tx: BTX): Try[Unit]
}






© 2015 - 2024 Weber Informatics LLC | Privacy Policy