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] Improve collections equality #1011

Merged
merged 7 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
19 changes: 16 additions & 3 deletions core/shared/src/main/scala/sigma/data/CollsOverArrays.scala
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,13 @@ class CollOverArray[@specialized A](val toArray: Array[A], val builder: CollBuil

override def equals(obj: scala.Any): Boolean = (this eq obj.asInstanceOf[AnyRef]) || (obj match {
case obj: CollOverArray[_] if obj.tItem == this.tItem =>
java.util.Objects.deepEquals(obj.toArray, toArray)
java.util.Objects.deepEquals(obj.toArray, this.toArray)
case obj: PairColl[_, _] if obj.tItem == this.tItem =>
if(VersionContext.current.isV6SoftForkActivated) {
java.util.Objects.deepEquals(obj.toArray, this.toArray)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the obj.toArray will lead to many allocations (one for the array, and one for each pair). It is better to avoid it allocations in equals. Here it can be done by accessing obj.ls, obj.rs and comparing with this.toArray in a cfor loop.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, please check

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

} else {
false
}
case _ => false
})

Expand Down Expand Up @@ -241,8 +247,15 @@ private[sigma] class CollOverArrayBuilder extends CollBuilder { builder =>

class PairOfCols[@specialized L, @specialized R](val ls: Coll[L], val rs: Coll[R]) extends PairColl[L,R] {

override def equals(that: scala.Any) = (this eq that.asInstanceOf[AnyRef]) || (that match {
case that: PairColl[_,_] if that.tItem == this.tItem => ls == that.ls && rs == that.rs
override def equals(that: scala.Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match {
case that: PairColl[_,_] if that.tItem == this.tItem =>
ls == that.ls && rs == that.rs
case that: CollOverArray[_] if that.tItem == this.tItem =>
if (VersionContext.current.isV6SoftForkActivated) {
java.util.Objects.deepEquals(that.toArray, this.toArray)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comparison loop above (once implemented) can be reused here to avoid allocations.

} else {
false
}
case _ => false
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import org.ergoplatform.settings.ErgoAlgos
import scorex.util.encode.Base16
import scorex.util.{ModifierId, Random}
import sigma.Extensions._
import sigma.SigmaDslTesting
import sigma.ast.SCollection.SByteArray
import sigma.{SigmaDslTesting, VersionContext}
import sigma.ast.SType._
import sigma.ast.syntax.{ErgoBoxCandidateRType, TrueSigmaProp}
import sigma.ast._
Expand All @@ -20,9 +19,11 @@ import sigmastate.helpers.TestingHelpers.copyTransaction
import sigmastate.utils.Helpers
import sigma.SigmaDslTesting
import sigma.Extensions._
import sigma.ast.SCollection.SByteArray
import sigmastate.CrossVersionProps
import sigmastate.utils.Helpers.EitherOps // required for Scala 2.11

class ErgoLikeTransactionSpec extends SigmaDslTesting with JsonCodecs {
class ErgoLikeTransactionSpec extends SigmaDslTesting with CrossVersionProps with JsonCodecs {

property("ErgoBox test vectors") {
val token1 = "6e789ab7b2fffff12280a6cd01557f6fb22b7f80ff7aff8e1f7f15973d7f0001"
Expand Down Expand Up @@ -99,14 +100,24 @@ class ErgoLikeTransactionSpec extends SigmaDslTesting with JsonCodecs {

{ // test case for R2
val res = b1.get(ErgoBox.R2).get
val exp = Coll(
(Digest32Coll @@ ErgoAlgos.decodeUnsafe(token1).toColl) -> 10000000L,
(Digest32Coll @@ ErgoAlgos.decodeUnsafe(token2).toColl) -> 500L
).map(identity).toConstant
// TODO v6.0 (16h): fix collections equality and remove map(identity)
// (PairOfColl should be equal CollOverArray but now it is not)

// We have versioned check here due to fixed collections equality in 6.0.0
// (PairOfColl equal CollOverArray now)
// see (https://github.com/ScorexFoundation/sigmastate-interpreter/issues/909)
res shouldBe exp
if(VersionContext.current.isV6SoftForkActivated) {
val exp = Coll(
(Digest32Coll @@ ErgoAlgos.decodeUnsafe(token1).toColl) -> 10000000L,
(Digest32Coll @@ ErgoAlgos.decodeUnsafe(token2).toColl) -> 500L
).toConstant
res shouldBe exp
exp shouldBe res
} else {
val exp = Coll(
(Digest32Coll @@ ErgoAlgos.decodeUnsafe(token1).toColl) -> 10000000L,
(Digest32Coll @@ ErgoAlgos.decodeUnsafe(token2).toColl) -> 500L
).map(identity).toConstant
res shouldBe exp
}
}

{ // test case for R3
Expand Down Expand Up @@ -470,7 +481,6 @@ class ErgoLikeTransactionSpec extends SigmaDslTesting with JsonCodecs {
// test equivalence of "from Json" and "from bytes" deserialization
tx2.id shouldBe tx.id
tx2.id shouldBe "d5c0a7908bbb8eefe72ad70a9f668dd47b748239fd34378d3588d5625dd75c82"
println(tx2.id)
}

property("Tuple in register test vector") {
Expand Down
Loading