From d6f8b253d35951b72da76f2a6f18e68b24c444ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Paradzi=C5=84ski?= Date: Wed, 9 Sep 2020 19:00:36 +0200 Subject: [PATCH] change example app in SparseMarkleTree into tests fix #38 --- .../merkle/sparse/SparseMerkleTree.scala | 50 +---------------- .../merkle/MerkleTreeSpecification.scala | 1 - .../SparseMerkleTreeSpecification.scala | 54 +++++++++++++++++++ 3 files changed, 55 insertions(+), 50 deletions(-) create mode 100644 src/test/scala/scorex/crypto/authds/merkle/sparse/SparseMerkleTreeSpecification.scala diff --git a/src/main/scala/scorex/crypto/authds/merkle/sparse/SparseMerkleTree.scala b/src/main/scala/scorex/crypto/authds/merkle/sparse/SparseMerkleTree.scala index eab086b8..9562b707 100644 --- a/src/main/scala/scorex/crypto/authds/merkle/sparse/SparseMerkleTree.scala +++ b/src/main/scala/scorex/crypto/authds/merkle/sparse/SparseMerkleTree.scala @@ -5,7 +5,7 @@ import scorex.crypto.authds.LeafData import scorex.crypto.hash._ import scala.collection.mutable -import scala.util.{Random, Try} +import scala.util.Try /** * @@ -174,54 +174,6 @@ case class SparseMerkleProof[D <: Digest](idx: Node.ID, def valid(tree: SparseMerkleTree[D])(implicit hf: CryptographicHash[D]): Boolean = valid(tree.rootDigest, tree.height) } - -object TreeTester extends App { - - implicit val hf: CryptographicHash[Digest32] = new Blake2b256Unsafe - - (1 to 2000000).foreach(i => hf.hash(i.toString)) - - val height: Byte = 30 - - val tree0 = SparseMerkleTree.emptyTree(height) - - assert(tree0.lastProof.valid(tree0.rootDigest, height)(hf)) - - val zp = SparseMerkleTree.zeroProof[Digest32](height) - - val zp1 = zp.copy(idx = 1) - - val (tree1, updProofs) = tree0.update(zp, Some(LeafData @@ Longs.toByteArray(5)), Seq(zp)).get - - - assert(zp.valid(tree0.rootDigest, height)(hf)) - assert(zp1.valid(tree0.rootDigest, height)(hf)) - assert(updProofs.head.valid(tree1.rootDigest, height)(hf)) - - assert(tree1.lastProof.valid(tree1.rootDigest, height)(hf)) - - val tree2 = tree1.update(tree1.lastProof, Some(LeafData @@ Longs.toByteArray(10))).get._1 - - assert(tree2.lastProof.valid(tree2.rootDigest, height)(hf)) - - - val t0 = System.currentTimeMillis() - (1 to 10000).foldLeft(SparseMerkleTree.emptyTree(height) -> Seq[SparseMerkleProof[Digest32]]()) { case ((tree, proofs), _) => - - val (newProofs, proof, newValue) = if (Random.nextInt(3) == 0 && proofs.nonEmpty) { - val nps = Random.shuffle(proofs) - (nps.tail, nps.head, None) - } else { - val nps = if (Random.nextInt(2) == 0 && proofs.size < 5) proofs :+ tree.lastProof else proofs - (nps, tree.lastProof, Some(LeafData @@ Longs.toByteArray(Random.nextInt()))) - } - - tree.update(proof, newValue, newProofs).get - } - val t = System.currentTimeMillis() - println((t - t0) + " ms.") -} - object OpsBenchmark extends App { implicit val hf: CryptographicHash[Digest32] = new Blake2b256Unsafe diff --git a/src/test/scala/scorex/crypto/authds/merkle/MerkleTreeSpecification.scala b/src/test/scala/scorex/crypto/authds/merkle/MerkleTreeSpecification.scala index 9bb6b4a6..e0803af7 100644 --- a/src/test/scala/scorex/crypto/authds/merkle/MerkleTreeSpecification.scala +++ b/src/test/scala/scorex/crypto/authds/merkle/MerkleTreeSpecification.scala @@ -1,6 +1,5 @@ package scorex.crypto.authds.merkle - import org.scalatest.propspec.AnyPropSpec import org.scalatest.matchers.should.Matchers import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks diff --git a/src/test/scala/scorex/crypto/authds/merkle/sparse/SparseMerkleTreeSpecification.scala b/src/test/scala/scorex/crypto/authds/merkle/sparse/SparseMerkleTreeSpecification.scala new file mode 100644 index 00000000..7a3857f4 --- /dev/null +++ b/src/test/scala/scorex/crypto/authds/merkle/sparse/SparseMerkleTreeSpecification.scala @@ -0,0 +1,54 @@ +package scorex.crypto.authds.merkle.sparse + +import com.google.common.primitives.Longs +import org.scalatest.matchers.should.Matchers +import org.scalatest.propspec.AnyPropSpec +import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks +import scorex.crypto.TestingCommons +import scorex.crypto.authds.LeafData +import scorex.crypto.hash.{Blake2b256Unsafe, CryptographicHash, Digest32} + +class SparseMerkleTreeSpecification extends AnyPropSpec with ScalaCheckDrivenPropertyChecks with Matchers with TestingCommons { + + implicit val hf: CryptographicHash[Digest32] = new Blake2b256Unsafe + + property("Tree has valid last proof") { + forAll { height: Byte => + whenever(height > 0) { + val tree0 = SparseMerkleTree.emptyTree(height) + tree0.lastProof.valid(tree0.rootDigest, height) shouldBe true + } + } + } + + property("ZeroProof tree has valid proof") { + forAll { height: Byte => + whenever(height > 0) { + val zp = SparseMerkleTree.zeroProof[Digest32](height) + val zp1 = zp.copy(idx = 1) + val tree0 = SparseMerkleTree.emptyTree(height) + + zp.valid(tree0.rootDigest, height) shouldBe true + zp1.valid(tree0.rootDigest, height) shouldBe true + } + } + } + + property("Updated tree has valid proof") { + forAll { height: Byte => + whenever(height > 1) { + val zp = SparseMerkleTree.zeroProof[Digest32](height) + val tree0 = SparseMerkleTree.emptyTree(height) + val newLeafData = Some(LeafData @@ Longs.toByteArray(5)) + val (tree1, updProofs) = tree0.update(zp, newLeafData, Seq(zp)).get + + updProofs.head.valid(tree1.rootDigest, height) shouldBe true + tree1.lastProof.valid(tree1.rootDigest, height) shouldBe true + + val newLeafData10 = Some(LeafData @@ Longs.toByteArray(10)) + val tree2 = tree1.update(tree1.lastProof, newLeafData10).get._1 + tree2.lastProof.valid(tree2.rootDigest, height) shouldBe true + } + } + } +}