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

com.wavesplatform.transaction.validation.impl.InvokeScriptTxValidator.scala Maven / Gradle / Ivy

The newest version!
package com.wavesplatform.transaction.validation.impl

import cats.data.NonEmptyList
import cats.data.Validated.{Invalid, Valid}
import cats.syntax.either.*
import com.wavesplatform.lang.v1.compiler.Terms.FUNCTION_CALL
import com.wavesplatform.lang.v1.{ContractLimits, FunctionHeader}
import com.wavesplatform.protobuf.transaction.PBTransactions
import com.wavesplatform.transaction.PBSince
import com.wavesplatform.transaction.TxValidationError.{GenericError, NonPositiveAmount}
import com.wavesplatform.transaction.smart.InvokeScriptTransaction
import com.wavesplatform.transaction.smart.InvokeScriptTransaction.Payment
import com.wavesplatform.transaction.validation.{TxValidator, ValidatedNV, ValidatedV}
import com.wavesplatform.utils.*

import scala.util.Try

object InvokeScriptTxValidator extends TxValidator[InvokeScriptTransaction] {
  def checkAmounts(payments: Seq[Payment]): ValidatedNV = {
    val invalid = payments.filter(_.amount <= 0)
    if (invalid.nonEmpty)
      Invalid(NonEmptyList.fromListUnsafe(invalid.toList).map(p => NonPositiveAmount(p.amount, p.assetId.fold("Waves")(_.toString))))
    else Valid(())
  }

  override def validate(tx: InvokeScriptTransaction): ValidatedV[InvokeScriptTransaction] = {
    import tx._

    def checkLength: Either[GenericError, Unit] = {
      val length =
        if (PBSince.affects(tx))
          PBTransactions.toPBInvokeScriptData(tx.dApp, tx.funcCallOpt, tx.payments).toByteArray.length
        else
          tx.bytes().length
      Either.cond(
        length <= ContractLimits.MaxInvokeScriptSizeInBytes,
        (),
        GenericError(s"InvokeScriptTransaction bytes length = $length exceeds limit = ${ContractLimits.MaxInvokeScriptSizeInBytes}")
      )
    }

    val callableNameSize =
      funcCallOpt match {
        case Some(FUNCTION_CALL(FunctionHeader.User(internalName, _), _)) => internalName.utf8Bytes.length
        case _                                                            => 0
      }

    V.seq(tx)(
      V.addressChainId(dApp, chainId),
      V.cond(
        funcCallOpt.isEmpty || funcCallOpt.get.args.size <= ContractLimits.MaxInvokeScriptArgs,
        GenericError(s"InvokeScript can't have more than ${ContractLimits.MaxInvokeScriptArgs} arguments")
      ),
      V.cond(
        callableNameSize <= ContractLimits.MaxDeclarationNameInBytes,
        GenericError(s"Callable function name size = $callableNameSize bytes must be less than ${ContractLimits.MaxDeclarationNameInBytes}")
      ),
      checkAmounts(payments),
      Try(checkLength).toEither.leftMap(e => GenericError(e.toString)).flatten.toValidatedNel
    )
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy