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

org.alephium.api.model.TestContract.scala Maven / Gradle / Ivy

The newest version!
// Copyright 2018 The Alephium Authors
// This file is part of the alephium project.
//
// The library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the library. If not, see .

package org.alephium.api.model

import org.alephium.api.{badRequest, Try}
import org.alephium.api.model.TestContract._
import org.alephium.protocol.{ALPH, Hash}
import org.alephium.protocol.config.GroupConfig
import org.alephium.protocol.model.{Address, BlockHash, ContractId, GroupIndex, TransactionId}
import org.alephium.protocol.vm.{ContractState => _, Val => _, _}
import org.alephium.util.{AVector, TimeStamp}

@SuppressWarnings(Array("org.wartremover.warts.DefaultArguments"))
final case class TestContract(
    group: Option[Int] = None,
    blockHash: Option[BlockHash] = None,
    blockTimeStamp: Option[TimeStamp] = None,
    txId: Option[TransactionId] = None,
    address: Option[Address.Contract] = None,
    callerAddress: Option[Address.Contract] = None,
    bytecode: StatefulContract,
    initialImmFields: Option[AVector[Val]] = None,
    initialMutFields: Option[AVector[Val]] = None,
    initialAsset: Option[AssetState] = None,
    methodIndex: Option[Int] = None,
    args: Option[AVector[Val]] = None,
    existingContracts: Option[AVector[ContractState]] = None,
    inputAssets: Option[AVector[TestInputAsset]] = None
) {
  def toComplete(): Try[TestContract.Complete] = {
    val testMethodIndex = methodIndex.getOrElse(testMethodIndexDefault)
    bytecode.methods.get(testMethodIndex) match {
      case Some(method) =>
        val testCode =
          if (method.isPublic) {
            bytecode
          } else {
            bytecode.copy(methods =
              bytecode.methods.replace(testMethodIndex, method.copy(isPublic = true))
            )
          }
        Right(
          Complete(
            group.getOrElse(groupDefault),
            blockHash.getOrElse(BlockHash.random),
            blockTimeStamp.getOrElse(TimeStamp.now()),
            txId.getOrElse(TransactionId.random),
            address.getOrElse(addressDefault).contractId,
            callerAddress.map(_.contractId),
            code = testCode,
            originalCodeHash = bytecode.hash,
            initialImmFields.getOrElse(AVector.empty),
            initialMutFields.getOrElse(AVector.empty),
            initialAsset.getOrElse(initialAssetDefault),
            testMethodIndex,
            args.getOrElse(AVector.empty),
            existingContracts.getOrElse(existingContractsDefault),
            inputAssets.getOrElse(inputAssetsDefault)
          )
        )
      case None => Left(badRequest(s"Invalid method index ${testMethodIndex}"))
    }
  }
}

object TestContract {
  val groupDefault: Int                                = 0
  val addressDefault: Address.Contract                 = Address.contract(ContractId.zero)
  val initialFieldsDefault: AVector[Val]               = AVector.empty
  val testMethodIndexDefault: Int                      = 0
  val testArgsDefault: AVector[Val]                    = AVector.empty
  val existingContractsDefault: AVector[ContractState] = AVector.empty
  val inputAssetsDefault: AVector[TestInputAsset]      = AVector.empty
  val initialAssetDefault: AssetState                  = AssetState(ALPH.alph(1))

  @SuppressWarnings(Array("org.wartremover.warts.DefaultArguments"))
  final case class Complete(
      group: Int = groupDefault,
      blockHash: BlockHash = BlockHash.random,
      blockTimeStamp: TimeStamp = TimeStamp.now(),
      txId: TransactionId = TransactionId.random,
      contractId: ContractId = addressDefault.contractId,
      callerContractIdOpt: Option[ContractId] = None,
      code: StatefulContract,
      originalCodeHash: Hash,
      initialImmFields: AVector[Val] = initialFieldsDefault,
      initialMutFields: AVector[Val] = initialFieldsDefault,
      initialAsset: AssetState = initialAssetDefault,
      testMethodIndex: Int = testMethodIndexDefault,
      testArgs: AVector[Val] = testArgsDefault,
      existingContracts: AVector[ContractState] = existingContractsDefault,
      inputAssets: AVector[TestInputAsset] = inputAssetsDefault
  ) {
    // We return original code hash when testing private methods
    // We return the new code hash when the test code is migrated
    def codeHash(hash: Hash): Hash = {
      val codeMigrated = hash != code.hash
      if (!codeMigrated) originalCodeHash else hash
    }

    def groupIndex(implicit groupConfig: GroupConfig): Try[GroupIndex] = {
      GroupIndex.from(group).toRight(badRequest("Invalid group index"))
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy