From 579318cad06eaec4526c9dcb3320803ac2d92f56 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Mon, 6 Nov 2023 17:03:09 -0600 Subject: [PATCH] Make `Gen[ECPrivateKey]` in scalacheck to use randomness from scalacheck to preserve reproducibility of test cases (#5285) * Make Gen[ECPrivateKey] in scalacheck to use randomness from scalacheck to preserve reproducibility of test cases * Revert build.sbt --- .../bitcoins/crypto/CryptoGenerators.scala | 28 ++++++++++++++++--- .../testkitcore/gen/ScriptGenerators.scala | 4 +-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/crypto-test/src/test/scala/org/bitcoins/crypto/CryptoGenerators.scala b/crypto-test/src/test/scala/org/bitcoins/crypto/CryptoGenerators.scala index 500e5c51ac..c054d7ebfe 100644 --- a/crypto-test/src/test/scala/org/bitcoins/crypto/CryptoGenerators.scala +++ b/crypto-test/src/test/scala/org/bitcoins/crypto/CryptoGenerators.scala @@ -8,7 +8,16 @@ import scodec.bits.ByteVector */ sealed abstract class CryptoGenerators { - def privateKey: Gen[ECPrivateKey] = Gen.delay(ECPrivateKey()) + def privateKey: Gen[ECPrivateKey] = { + //purposefully don't reach for cryptographically strong + //number generation, we want determinism to reproduce failed + //test cases. If we don't generate the private key with scalacheck + //we won't be able to reproduce the test case with a seed + //see: https://github.com/bitcoin-s/bitcoin-s/issues/1339 + NumberGenerator.bytevector(32).map { vec => + ECPrivateKey.fromBytes(vec) + } + } def fieldElement: Gen[FieldElement] = privateKey.map(_.fieldElement) @@ -169,9 +178,20 @@ sealed abstract class CryptoGenerators { hash = CryptoUtil.sha256Hash160(pubKey.bytes) } yield hash - def aesKey128Bit: Gen[AesKey] = Gen.delay(AesKey.get128Bit()) - def aesKey192Bit: Gen[AesKey] = Gen.delay(AesKey.get192Bit()) - def aesKey256Bit: Gen[AesKey] = Gen.delay(AesKey.get256Bit()) + def aesKey128Bit: Gen[AesKey] = { + val bytesGen = NumberGenerator.bytevector(16) + bytesGen.map(AesKey.fromValidBytes(_)) + } + + def aesKey192Bit: Gen[AesKey] = { + val bytesGen = NumberGenerator.bytevector(24) + bytesGen.map(AesKey.fromValidBytes(_)) + } + + def aesKey256Bit: Gen[AesKey] = { + val bytesGen = NumberGenerator.bytevector(32) + bytesGen.map(AesKey.fromValidBytes(_)) + } def aesKey: Gen[AesKey] = Gen.oneOf(aesKey128Bit, aesKey192Bit, aesKey256Bit) diff --git a/testkit-core/src/main/scala/org/bitcoins/testkitcore/gen/ScriptGenerators.scala b/testkit-core/src/main/scala/org/bitcoins/testkitcore/gen/ScriptGenerators.scala index 52bd4aa01f..9d071d0778 100644 --- a/testkit-core/src/main/scala/org/bitcoins/testkitcore/gen/ScriptGenerators.scala +++ b/testkit-core/src/main/scala/org/bitcoins/testkitcore/gen/ScriptGenerators.scala @@ -79,9 +79,9 @@ sealed abstract class ScriptGenerators { numKeys <- Gen.choose(1, Consensus.maxPublicKeysPerMultiSig) hash <- CryptoGenerators.doubleSha256Digest hashType <- CryptoGenerators.hashType + privKeys <- CryptoGenerators.privateKeySeq(numKeys) } yield for { - _ <- 0 until numKeys - privKey = ECPrivateKey() + privKey <- privKeys } yield ECDigitalSignature.fromBytes( privKey.sign(hash).bytes ++ ByteVector.fromByte(hashType.byte)) signatures.map(sigs => MultiSignatureScriptSignature(sigs))