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

org.alephium.protocol.vm.GasSchedule.scala Maven / Gradle / Ivy

There is a newer version: 3.8.8
Show 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.protocol.vm

import org.alephium.macros.Gas
import org.alephium.protocol.PublicKey

//scalastyle:off magic.number number.of.types

trait GasSchedule

trait GasSimple extends GasSchedule {
  def gas(): GasBox
}

trait GasFormula extends GasSchedule {
  def gas(size: Int): GasBox
}
object GasFormula {
  def wordLength(byteLength: Int): Int = (byteLength + 7) / 8
}

trait UpgradedGasFormula extends GasFormula {
  def gasDeprecated(size: Int): GasBox
}

@Gas
trait GasZero extends GasSimple
object GasZero {
  val gas: GasBox = GasBox.unsafe(0)
}

@Gas
trait GasBase extends GasSimple
object GasBase {
  val gas: GasBox = GasBox.unsafe(2)
}

@Gas
trait GasVeryLow extends GasSimple
object GasVeryLow {
  val gas: GasBox = GasBox.unsafe(3)
}

@Gas
trait GasLow extends GasSimple
object GasLow {
  val gas: GasBox = GasBox.unsafe(5)
}

@Gas
trait GasMid extends GasSimple
object GasMid {
  val gas: GasBox = GasBox.unsafe(8)
}

@Gas
trait GasHigh extends GasSimple
object GasHigh {
  val gas: GasBox = GasBox.unsafe(10)
}

trait GasToByte extends GasFormula {
  def gas(byteLength: Int): GasBox = GasToByte.gas(byteLength)
}
object GasToByte {
  val gasPerByte: Int = 1

  def gas(byteLength: Int): GasBox =
    GasBox.unsafe(gasPerByte * GasFormula.wordLength(byteLength))
}

trait GasExp extends GasFormula {
  def gas(byteLength: Int): GasBox = GasExp.gas(byteLength)
}
object GasExp {
  val baseGas: Int    = 10
  val gasPerByte: Int = 50

  def gas(byteLength: Int): GasBox = GasBox.unsafe(baseGas + gasPerByte * byteLength)
}

@Gas
trait GasMulModN extends GasSimple
object GasMulModN {
  val gas: GasBox = GasBox.unsafe(13) // GasMid + GasLow
}

@Gas
trait GasAddModN extends GasSimple
object GasAddModN {
  val gas: GasBox = GasBox.unsafe(8) // GasVeryLow + GasLow
}

trait GasHash extends GasFormula {
  def gas(byteLength: Int): GasBox = GasHash.gas(byteLength)
}
object GasHash {
  val baseGas: Int         = 30
  val extraGasPerWord: Int = 6

  def gas(byteLength: Int): GasBox =
    GasBox.unsafe(GasHash.baseGas + GasHash.extraGasPerWord * GasFormula.wordLength(byteLength))
}

trait GasBytesEq extends UpgradedGasFormula {
  def gas(byteLength: Int): GasBox = GasBytesEq.gas(byteLength)

  def gasDeprecated(byteLength: Int): GasBox = GasBytesEq.gasDeprecated(byteLength)
}
object GasBytesEq {
  val gasPerWord: Int = 1
  def gas(byteLength: Int): GasBox =
    GasBox.unsafe(GasVeryLow.gas.value + gasPerWord * GasFormula.wordLength(byteLength))

  def gasDeprecated(byteLength: Int): GasBox =
    GasBox.unsafe(gasPerWord * GasFormula.wordLength(byteLength))
}

trait GasBytesConcat extends UpgradedGasFormula {
  def gas(byteLength: Int): GasBox = GasBytesConcat.gas(byteLength)

  def gasDeprecated(byteLength: Int): GasBox = GasBytesConcat.gasDeprecated(byteLength)
}
object GasBytesConcat {
  val gasPerByte: Int              = 1
  def gas(byteLength: Int): GasBox = GasBox.unsafe(GasVeryLow.gas.value + byteLength * gasPerByte)

  def gasDeprecated(byteLength: Int): GasBox = GasBox.unsafe(byteLength * gasPerByte)
}

trait GasBytesSlice extends GasFormula {
  def gas(byteLength: Int): GasBox = GasBytesSlice.gas(byteLength)
}
object GasBytesSlice {
  val gasPerByte: Int = 1
  def gas(byteLength: Int): GasBox =
    GasVeryLow.gas.addUnsafe(GasBox.unsafe(byteLength * gasPerByte))
}

trait GasEncode extends GasBytesSlice

trait GasZeros extends GasBytesEq

@Gas
trait GasSignature extends GasSimple
object GasSignature {
  val gas: GasBox = GasBox.unsafe(2000)
}

@Gas
trait GasEcRecover extends GasSimple
object GasEcRecover {
  val gas: GasBox = GasBox.unsafe(2500)
}

@Gas
trait GasCreate extends GasSimple
object GasCreate {
  val gas: GasBox = GasBox.unsafe(32000)
}

@Gas
trait GasCopyCreate extends GasSimple
object GasCopyCreate {
  val gas: GasBox = GasBox.unsafe(24000)
}

@Gas
trait GasContractExists extends GasSimple
object GasContractExists {
  val gas: GasBox = GasBox.unsafe(800)
}

@Gas
trait GasDestroy extends GasSimple
object GasDestroy {
  val gas: GasBox = GasSchedule.txInputBaseGas
}

@Gas
trait GasMigrate extends GasSimple
object GasMigrate {
  val gas: GasBox = GasCreate.gas
}

trait GasLoadContractFields extends GasFormula {
  def gas(size: Int): GasBox = GasBox.unsafe((size + 1) * GasBase.gas.value)
}

@Gas
trait GasBalance extends GasSimple
object GasBalance {
  val gas: GasBox = GasBox.unsafe(30)
}

trait GasCall extends GasFormula {
  def gas(size: Int): GasBox = ??? // should call the companion object instead
}
object GasCall {
  def scriptBaseGas(byteLength: Int): GasBox =
    GasBox.unsafe(byteLength + GasSchedule.callGas.value)

  def fieldsBaseGas(byteLength: Int): GasBox =
    GasBox.unsafe(byteLength)
}

trait GasLog extends GasFormula {
  def gas(n: Int): GasBox = GasLog.gas(n)
}
object GasLog {
  val gasBase: Int    = 100
  val gasPerData: Int = 20

  def gas(n: Int): GasBox = GasBox.unsafe(gasBase + gasPerData * n)
}

trait GasUniqueAddress extends GasFormula {
  def gas(n: Int): GasBox = GasUniqueAddress.gas(n)
}
object GasUniqueAddress {
  val gasBase: Int       = GasVeryLow.gas.value
  val gasPerAddress: Int = 1

  def gas(n: Int): GasBox = GasBox.unsafe(gasBase + gasPerAddress * n)
}

object GasSchedule {
  val callGas: GasBox = GasBox.unsafe(200)
  def selectorCallSearchGas(numSearches: Int): GasBox =
    GasBox.unsafe(numSearches * GasMid.gas.value)

  def contractLoadGas(estimatedContractSize: Int): GasBox = {
    GasBox.unsafe(800 + GasFormula.wordLength(estimatedContractSize))
  }

  val contractStateUpdateBaseGas: GasBox = GasBox.unsafe(5000)

  /*
   * The gas cost of a transaction consists of 4 parts
   * 1. a fixed base gas for each transaction
   * 2. gas for each input including the auto generated contract inputs:
   *    2.1. gas for removing the input from the blockchain state trie
   *    2.2. execution gas for the unlock script of the input
   * 3. gas for each output including the auto generated vm outputs:
   *    3.1. gas for adding the output into the blockchain state trie
   * 4. execution gas for the optional tx script
   */
  val txBaseGas: GasBox       = GasBox.unsafe(1000)
  val txInputBaseGas: GasBox  = GasBox.unsafe(2000)
  val txOutputBaseGas: GasBox = GasBox.unsafe(4500)

  val p2pkUnlockGas: GasBox = {
    GasBox.unsafe(GasHash.gas(PublicKey.length).value + GasSignature.gas.value)
  }

  def p2mpkUnlockGas(m: Int): GasBox = p2pkUnlockGas.mulUnsafe(m)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy