From 748962dc1cd365c0dda9ff697548b50ac4244c3c Mon Sep 17 00:00:00 2001 From: Alexander Slesarenko Date: Fri, 18 Aug 2023 22:47:37 +0200 Subject: [PATCH] tx-signing-js: fix equality of ValidationSettings --- .../org/ergoplatform/ErgoLikeContext.scala | 6 +++--- .../validation/SigmaValidationSettings.scala | 7 ++++--- .../SigmaValidationSettingsSerializer.scala | 19 +++++++++++-------- .../validation/ValidationRules.scala | 4 ++-- ...igmaValidationSettingsSerializerSpec.scala | 12 ++++++++++-- .../sdk/JsonSerializationSpec.scala | 4 ++-- 6 files changed, 32 insertions(+), 20 deletions(-) diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala index 3bf455ae6f..3b356fd4ec 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/ErgoLikeContext.scala @@ -200,11 +200,11 @@ class ErgoLikeContext(val lastBlockUtxoRoot: AvlTreeData, lastBlockUtxoRoot, headers, preHeader, dataBoxes, boxesToSpend, spendingTransaction, selfIndex, extension, validationSettings, costLimit, initCost, activatedScriptVersion) - var hashCode = 0 + var h = 0 cfor(0)(_ < state.length, _ + 1) { i => - hashCode = 31 * hashCode + state(i).hashCode + h = 31 * h + state(i).hashCode } - hashCode + h } override def toString = s"ErgoLikeContext(lastBlockUtxoRoot=$lastBlockUtxoRoot, headers=$headers, preHeader=$preHeader, dataBoxes=$dataBoxes, boxesToSpend=$boxesToSpend, spendingTransaction=$spendingTransaction, selfIndex=$selfIndex, extension=$extension, validationSettings=$validationSettings, costLimit=$costLimit, initCost=$initCost, activatedScriptVersion=$activatedScriptVersion)" diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettings.scala b/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettings.scala index 6314ea0b20..d295b17ce7 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettings.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettings.scala @@ -48,7 +48,7 @@ abstract class SigmaValidationSettings extends Iterable[(Short, (ValidationRule, def isSoftFork(ruleId: Short, ve: ValidationException): Boolean = { val infoOpt = get(ruleId) infoOpt match { - case Some((_, ReplacedRule(newRuleId))) => true + case Some((_, ReplacedRule(_))) => true case Some((rule, status)) => rule.isSoftFork(this, rule.id, status, ve.args) case None => false } @@ -72,10 +72,11 @@ sealed class MapSigmaValidationSettings(private val map: Map[Short, (ValidationR } override def equals(obj: Any): Boolean = (this eq obj.asInstanceOf[AnyRef]) || (obj match { - case that: MapSigmaValidationSettings => map == that.map + case that: MapSigmaValidationSettings => + map.iterator.forall { case (id, v) => that.map.get(id).exists(_ == v) } case _ => false }) - override def hashCode(): Int = map.hashCode() + override def hashCode(): Int = map.toIndexedSeq.sortBy(_._1).hashCode() } diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializer.scala b/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializer.scala index 1e2b8b352a..1b53b7dbf1 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializer.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializer.scala @@ -2,7 +2,8 @@ package org.ergoplatform.validation import sigmastate.serialization.SigmaSerializer import sigmastate.utils.{SigmaByteReader, SigmaByteWriter} -import scalan.util.Extensions.{IntOps,LongOps} +import scalan.util.Extensions.{IntOps, LongOps} +import sigmastate.exceptions.SerializerException // TODO v5.x: remove unused class and related json encoders /** The rules are serialized ordered by ruleId. @@ -13,9 +14,9 @@ object SigmaValidationSettingsSerializer extends SigmaSerializer[SigmaValidation override def serialize(settings: SigmaValidationSettings, w: SigmaByteWriter): Unit = { val rules = settings.toArray.sortBy(_._1) w.putUInt(rules.length) - rules.foreach { r => - w.putUShort(r._1) - RuleStatusSerializer.serialize(r._2._2, w) + rules.foreach { case (id, (_, status)) => + w.putUShort(id) + RuleStatusSerializer.serialize(status, w) } } @@ -27,10 +28,12 @@ object SigmaValidationSettingsSerializer extends SigmaSerializer[SigmaValidation val status = RuleStatusSerializer.parse(r) ruleId -> status } - val initVs = ValidationRules.currentSettings - val res = parsed - .filter(pair => initVs.get(pair._1).isDefined) - .foldLeft(initVs) { (vs, rule) => vs.updated(rule._1, rule._2) } + val map = parsed.map { case (id, status) => + val (rule, _) = ValidationRules.currentSettings.get(id) + .getOrElse(throw SerializerException(s"Rule with id $id is not registered")) + id -> (rule, status) + }.toMap + val res = new MapSigmaValidationSettings(map) res } } diff --git a/interpreter/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala b/interpreter/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala index 1110916e03..2573d3f592 100644 --- a/interpreter/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala +++ b/interpreter/shared/src/main/scala/org/ergoplatform/validation/ValidationRules.scala @@ -1,9 +1,9 @@ package org.ergoplatform.validation import scalan.util.Extensions.toUByte -import sigmastate.Values.{SValue, ErgoTree} +import sigmastate.Values.{ErgoTree, SValue} import sigmastate._ -import sigmastate.exceptions.{InvalidOpCode, SerializerException, ReaderPositionLimitExceeded, SigmaException, InterpreterException} +import sigmastate.exceptions.{InterpreterException, InvalidOpCode, ReaderPositionLimitExceeded, SerializerException, SigmaException} import sigmastate.serialization.OpCodes.OpCode import sigmastate.serialization.TypeSerializer.embeddableIdToType import sigmastate.serialization.{OpCodes, ValueSerializer} diff --git a/sc/shared/src/test/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializerSpec.scala b/sc/shared/src/test/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializerSpec.scala index b74d4014f2..ee4ec75c3c 100644 --- a/sc/shared/src/test/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializerSpec.scala +++ b/sc/shared/src/test/scala/org/ergoplatform/validation/SigmaValidationSettingsSerializerSpec.scala @@ -1,5 +1,6 @@ package org.ergoplatform.validation +import org.ergoplatform.validation.ValidationRules.{FirstRuleId, currentSettings} import org.scalatest.Assertion import sigmastate.helpers.CompilerTestingCommons import sigmastate.serialization.SerializationSpecification @@ -13,14 +14,21 @@ class SigmaValidationSettingsSerializerSpec extends SerializationSpecification w } property("ValidationRules.currentSettings round trip") { - roundtrip(ValidationRules.currentSettings) + roundtrip(currentSettings) } property("SigmaValidationSettings round trip") { forAll(ruleIdGen, statusGen, MinSuccessful(100)) { (ruleId, status) => - val vs = ValidationRules.currentSettings.updated(ruleId, status) + val vs = currentSettings.updated(ruleId, status) roundtrip(vs) } } + property("SigmaValidationSettings equality") { + val vs = currentSettings + val vs_copy = currentSettings.updated(FirstRuleId, currentSettings.getStatus(FirstRuleId).get) + val vs2 = currentSettings.updated(FirstRuleId, DisabledRule) + vs.equals(vs2) shouldBe false + vs.equals(vs_copy) shouldBe true + } } \ No newline at end of file diff --git a/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala b/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala index e651a542b8..44d7030df2 100644 --- a/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala +++ b/sdk/shared/src/test/scala/org/ergoplatform/sdk/JsonSerializationSpec.scala @@ -16,7 +16,7 @@ import sigmastate.basics.DLogProtocol.ProveDlog import sigmastate.eval.Digest32Coll import sigmastate.interpreter.{ContextExtension, ProverResult} import sigmastate.serialization.SerializationSpecification -import sigmastate.utils.Helpers._ +import sigmastate.utils.Helpers.DecoderResultOps // required for Scala 2.11 (extension method toTry) import special.collection.Coll import special.sigma.{Header, PreHeader} import org.ergoplatform.ErgoLikeContext @@ -36,7 +36,7 @@ class JsonSerializationSpec extends SerializationSpecification with JsonCodecs { } property("ErgoLikeContext should be encoded into JSON and decoded back correctly") { - forAll(ergoLikeContextGen) { v: ErgoLikeContext => jsonRoundTrip(v) } + forAll(ergoLikeContextGen, MinSuccessful(50)) { v: ErgoLikeContext => jsonRoundTrip(v) } } property("sigma.BigInt should be encoded into JSON and decoded back correctly") {