Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[6.0.0] activation details and revised checkSoftForkCondition #1029

Open
wants to merge 5 commits into
base: v6.0.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import sigma.VersionContext
import sigma.ast.SCollectionType.{CollectionTypeCode, NestedCollectionTypeCode}
import sigma.ast._
import sigma.util.safeNewArray
import sigma.validation.ValidationRules.{CheckPrimitiveTypeCode, CheckTypeCode}
import sigma.validation.ValidationRules.{CheckPrimitiveTypeCode, CheckPrimitiveTypeCodeV6, CheckTypeCode, CheckTypeCodeV6}

import java.nio.charset.StandardCharsets

Expand All @@ -14,7 +14,12 @@ class TypeSerializer {
import TypeSerializer._

def getEmbeddableType(code: Int): SType = {
CheckPrimitiveTypeCode(code.toByte)
// todo : add unsigned bit int to embeddable id to type
if (VersionContext.current.isV6SoftForkActivated) {
CheckPrimitiveTypeCodeV6(code.toByte)
} else {
CheckPrimitiveTypeCode(code.toByte)
}
embeddableIdToType(code)
}

Expand Down Expand Up @@ -215,9 +220,13 @@ class TypeSerializer {
}
SFunc(tDom, tRange, tpeParams)
case _ =>
// todo: 6.0: replace 1008 check with identical behavior but other opcode, to activate
// ReplacedRule(1008 -> new opcode) during 6.0 activation
CheckTypeCode(c.toByte)
// the #1008 check replaced with one with identical behavior but different opcode (1018), to activate
// ReplacedRule(1008 -> 1018) during 6.0 activation
if (VersionContext.current.isV6SoftForkActivated) {
CheckTypeCodeV6(c.toByte)
} else {
CheckTypeCode(c.toByte)
}
NoType
}
}
Expand Down
43 changes: 34 additions & 9 deletions core/shared/src/main/scala/sigma/validation/ValidationRules.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package sigma.validation

import sigma.SigmaException
import sigma.{SigmaException, VersionContext}
import sigma.ast.{SGlobal, SOption, TypeCodes}
import sigma.serialization.{ReaderPositionLimitExceeded, SerializerException}
import sigma.util.Extensions.toUByte
Expand Down Expand Up @@ -77,7 +77,7 @@ object ValidationRules {
/** The id of the first validation rule. Can be used as the beginning of the rules id range. */
val FirstRuleId = 1000.toShort

object CheckPrimitiveTypeCode extends ValidationRule(1007,
class CheckPrimitiveTypeCodeTemplate(ruleId: Short) extends ValidationRule(ruleId,
"Check the primitive type code is supported or is added via soft-fork")
with SoftForkWhenCodeAdded {
override protected lazy val settings: SigmaValidationSettings = coreSettings
Expand All @@ -93,10 +93,14 @@ object ValidationRules {
}
}

object CheckTypeCode extends ValidationRule(1008,
object CheckPrimitiveTypeCode extends CheckPrimitiveTypeCodeTemplate(1007)

object CheckPrimitiveTypeCodeV6 extends CheckPrimitiveTypeCodeTemplate(1017)

class CheckTypeCodeTemplate(ruleId: Short) extends ValidationRule(ruleId,
"Check the non-primitive type code is supported or is added via soft-fork")
with SoftForkWhenCodeAdded {
override protected lazy val settings: SigmaValidationSettings = coreSettings
override protected def settings: SigmaValidationSettings = coreSettings

final def apply[T](typeCode: Byte): Unit = {
checkRule()
Expand All @@ -109,10 +113,14 @@ object ValidationRules {
}
}

object CheckTypeCode extends CheckTypeCodeTemplate(1008)

object CheckTypeCodeV6 extends CheckTypeCodeTemplate(1018)

object CheckSerializableTypeCode extends ValidationRule(1009,
"Check the data values of the type (given by type code) can be serialized")
with SoftForkWhenReplaced {
override protected lazy val settings: SigmaValidationSettings = coreSettings
override protected def settings: SigmaValidationSettings = coreSettings

/** Creates an exception which is used as a cause when throwing a ValidationException. */
def throwValidationException(typeCode: Byte): Nothing = {
Expand Down Expand Up @@ -141,7 +149,7 @@ object ValidationRules {
object CheckTypeWithMethods extends ValidationRule(1010,
"Check the type (given by type code) supports methods")
with SoftForkWhenCodeAdded {
override protected lazy val settings: SigmaValidationSettings = coreSettings
override protected def settings: SigmaValidationSettings = coreSettings

final def apply[T](typeCode: Byte, cond: Boolean): Unit = {
checkRule()
Expand All @@ -160,7 +168,7 @@ object ValidationRules {
*/
object CheckPositionLimit extends ValidationRule(1014,
"Check that the Reader has not exceeded the position limit.") with SoftForkWhenReplaced {
override protected lazy val settings: SigmaValidationSettings = coreSettings
override protected def settings: SigmaValidationSettings = coreSettings

/** Wraps the given cause into [[ValidationException]] and throws it. */
def throwValidationException(cause: ReaderPositionLimitExceeded): Nothing = {
Expand All @@ -183,21 +191,38 @@ object ValidationRules {
}
}

private val ruleSpecs: Seq[ValidationRule] = Seq(
private val ruleSpecsV5: Seq[ValidationRule] = Seq(
CheckPrimitiveTypeCode,
CheckTypeCode,
CheckSerializableTypeCode,
CheckTypeWithMethods,
CheckPositionLimit
)

private val ruleSpecsV6: Seq[ValidationRule] = Seq(
CheckPrimitiveTypeCodeV6,
CheckTypeCodeV6,
CheckSerializableTypeCode,
CheckTypeWithMethods,
CheckPositionLimit
)

private def ruleSpecs: Seq[ValidationRule] = {
if(VersionContext.current.isV6SoftForkActivated) {
ruleSpecsV6
} else {
ruleSpecsV5
}
}

/** Validation settings that correspond to the current version of the ErgoScript implementation.
* Different version of the code will have a different set of rules here.
* This variable is globally available and can be use wherever checking of the rules is necessary.
* This is immutable data structure, it can be augmented with RuleStates from block extension
* sections of the blockchain, but that augmentation is only available in stateful context.
*/
val coreSettings: SigmaValidationSettings = new MapSigmaValidationSettings({
// todo: versioned cache here for efficiency
def coreSettings: SigmaValidationSettings = new MapSigmaValidationSettings({
val map = ruleSpecs.map(r => r.id -> (r, EnabledRule)).toMap
assert(map.size == ruleSpecs.size, s"Duplicate ruleIds ${ruleSpecs.groupBy(_.id).filter(g => g._2.length > 1)}")
map
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.ergoplatform.validation

import sigma.SigmaException
import sigma.{SigmaException, VersionContext}
import sigma.ast.{DeserializeContext, ErgoTree, MethodsContainer, SMethod}
import sigma.ast.TypeCodes.LastConstantCode
import sigma.serialization.{InvalidOpCode, SerializerException}
Expand All @@ -23,7 +23,7 @@ object ValidationRules {

object CheckDeserializedScriptType extends ValidationRule(FirstRuleId,
"Deserialized script should have expected type") {
override protected lazy val settings: SigmaValidationSettings = currentSettings
override protected def settings: SigmaValidationSettings = currentSettings

final def apply[T](d: DeserializeContext[_], script: SValue): Unit = {
checkRule()
Expand All @@ -38,7 +38,7 @@ object ValidationRules {

object CheckDeserializedScriptIsSigmaProp extends ValidationRule(1001,
"Deserialized script should have SigmaProp type") {
override protected lazy val settings: SigmaValidationSettings = currentSettings
override protected def settings: SigmaValidationSettings = currentSettings

/** @param root candidate node before it is added as a root of ErgoTree */
final def apply[T](root: SValue): Unit = {
Expand All @@ -54,7 +54,7 @@ object ValidationRules {
object CheckValidOpCode extends ValidationRule(1002,
"Check the opcode is supported by registered serializer or is added via soft-fork")
with SoftForkWhenCodeAdded {
override protected lazy val settings: SigmaValidationSettings = currentSettings
override protected def settings: SigmaValidationSettings = currentSettings

final def apply[T](ser: ValueSerializer[_], opCode: OpCode): Unit = {
checkRule()
Expand All @@ -69,26 +69,26 @@ object ValidationRules {
/** Not used since v5.0.1. */
object CheckIsSupportedIndexExpression extends ValidationRule(1003,
"Check the index expression for accessing collection element is supported.") {
override protected lazy val settings: SigmaValidationSettings = currentSettings
override protected def settings: SigmaValidationSettings = currentSettings
}

/** Not used since v5.0.3 */
object CheckCostFunc extends ValidationRule(1004,
"Cost function should contain only operations from specified list.") {
override protected lazy val settings: SigmaValidationSettings = currentSettings
override protected def settings: SigmaValidationSettings = currentSettings
}

object CheckCalcFunc extends ValidationRule(1005,
"If SigmaProp.isProven method calls exists in the given function,\n then it is the last operation") {
override protected lazy val settings: SigmaValidationSettings = currentSettings
override protected def settings: SigmaValidationSettings = currentSettings
}

/** This rule is not use in v5.x, keep the commented code below as a precise
* documentation of its semantics.
*/
object CheckTupleType extends ValidationRule(1006,
"Supported tuple type.") with SoftForkWhenReplaced {
override protected lazy val settings: SigmaValidationSettings = currentSettings
override protected def settings: SigmaValidationSettings = currentSettings

// final def apply[Ctx <: IRContext, T](ctx: Ctx)(e: ctx.Elem[_]): Unit = {
// checkRule()
Expand All @@ -102,9 +102,9 @@ object ValidationRules {
// }
}

object CheckAndGetMethod extends ValidationRule(1011,
class CheckAndGetMethodTemplate(ruleId: Short) extends ValidationRule(ruleId,
"Check the type has the declared method.") {
override protected lazy val settings: SigmaValidationSettings = currentSettings
override protected def settings: SigmaValidationSettings = currentSettings

final def apply[T](objType: MethodsContainer, methodId: Byte): SMethod = {
checkRule()
Expand All @@ -128,9 +128,12 @@ object ValidationRules {
}
}

object CheckAndGetMethod extends CheckAndGetMethodTemplate(1011)
object CheckAndGetMethodV6 extends CheckAndGetMethodTemplate(1016)

object CheckHeaderSizeBit extends ValidationRule(1012,
"For version greater then 0, size bit should be set.") with SoftForkWhenReplaced {
override protected lazy val settings: SigmaValidationSettings = currentSettings
override protected def settings: SigmaValidationSettings = currentSettings

final def apply(header: HeaderType): Unit = {
checkRule()
Expand All @@ -146,16 +149,16 @@ object ValidationRules {
/** Not used since v5.0.3 */
object CheckCostFuncOperation extends ValidationRule(1013,
"Check the opcode is allowed in cost function") {
override protected lazy val settings: SigmaValidationSettings = currentSettings
override protected def settings: SigmaValidationSettings = currentSettings
}

/** Not used since v5.0.1 */
object CheckLoopLevelInCostFunction extends ValidationRule(1015,
"Check that loop level is not exceeded.") {
override protected lazy val settings: SigmaValidationSettings = currentSettings
override protected def settings: SigmaValidationSettings = currentSettings
}

val ruleSpecs: Seq[ValidationRule] = Seq(
private val ruleSpecsV5: Seq[ValidationRule] = Seq(
CheckDeserializedScriptType,
CheckDeserializedScriptIsSigmaProp,
CheckValidOpCode,
Expand All @@ -174,13 +177,26 @@ object ValidationRules {
CheckLoopLevelInCostFunction
)

// v6 validation rules below
private val ruleSpecsV6: Seq[ValidationRule] = {
ruleSpecsV5.filter(_.id != CheckAndGetMethod.id) ++ Seq(CheckAndGetMethodV6)
}

def ruleSpecs: Seq[ValidationRule] = {
if (VersionContext.current.isV6SoftForkActivated) {
ruleSpecsV6
} else {
ruleSpecsV5
}
}

/** Validation settings that correspond to the current version of the ErgoScript implementation.
* Different version of the code will have a different set of rules here.
* This variable is globally available and can be use wherever checking of the rules is necessary.
* This is immutable data structure, it can be augmented with RuleStates from block extension
* sections of the blockchain, but that augmentation is only available in stateful context.
*/
val currentSettings: SigmaValidationSettings = new MapSigmaValidationSettings({
def currentSettings: SigmaValidationSettings = new MapSigmaValidationSettings({
val map = ruleSpecs.map(r => r.id -> (r, EnabledRule)).toMap
assert(map.size == ruleSpecs.size, s"Duplicate ruleIds ${ruleSpecs.groupBy(_.id).filter(g => g._2.length > 1)}")
map
Expand Down
8 changes: 6 additions & 2 deletions data/shared/src/main/scala/sigma/ast/methods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,17 @@ sealed trait MethodsContainer {

/** Lookup method in this type by method's id or throw ValidationException.
* This method can be used in trySoftForkable section to either obtain valid method
* or catch ValidatioinException which can be checked for soft-fork condition.
* or catch ValidationException which can be checked for soft-fork condition.
* It delegate to getMethodById to lookup method.
*
* @see getMethodById
*/
def methodById(methodId: Byte): SMethod = {
ValidationRules.CheckAndGetMethod(this, methodId)
if (VersionContext.current.isV6SoftForkActivated) {
ValidationRules.CheckAndGetMethodV6(this, methodId)
} else {
ValidationRules.CheckAndGetMethod(this, methodId)
}
}

/** Finds a method descriptor [[SMethod]] for the given name. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import java.math.BigInteger
* @see [[SigmaDslBuilder]] for detailed descriptions
*/
class CSigmaDslBuilder extends SigmaDslBuilder { dsl =>
implicit val validationSettings: SigmaValidationSettings = ValidationRules.currentSettings
def validationSettings: SigmaValidationSettings = ValidationRules.currentSettings

override val Colls: CollBuilder = sigma.Colls

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package org.ergoplatform.validation
import sigma.validation.SigmaValidationSettings

trait ValidationSpecification {
implicit val vs: SigmaValidationSettings = ValidationRules.currentSettings
def vs: SigmaValidationSettings = ValidationRules.currentSettings
}
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ class SoftForkabilitySpecification extends SigmaTestingData
trySoftForkable(false) {
action
true
}
}(vs)
}, {
case ve: ValidationException if ve.rule == rule => true
case _ => false
Expand Down
Loading