From 6369c64b6f40c9aa65dce8a17c5a4005e0e6416e Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Wed, 14 Aug 2019 06:35:10 -0500 Subject: [PATCH] Make all instances of HashDigest extend AnyVal so we do not allocate runtime objects to avoid GCs (#690) --- .../org/bitcoins/core/crypto/HashDigest.scala | 133 ++++++++++-------- .../core/protocol/NetworkElement.scala | 4 +- 2 files changed, 80 insertions(+), 57 deletions(-) diff --git a/core/src/main/scala/org/bitcoins/core/crypto/HashDigest.scala b/core/src/main/scala/org/bitcoins/core/crypto/HashDigest.scala index 7902c09c68..3c1cbcf30a 100644 --- a/core/src/main/scala/org/bitcoins/core/crypto/HashDigest.scala +++ b/core/src/main/scala/org/bitcoins/core/crypto/HashDigest.scala @@ -7,10 +7,10 @@ import scodec.bits.ByteVector /** * Created by chris on 5/24/16. */ -sealed abstract class HashDigest extends NetworkElement { +sealed trait HashDigest extends Any with NetworkElement { /** The message digest represented in bytes */ - def bytes: ByteVector + override def bytes: ByteVector /** * Flips the endianness of the byte sequence. @@ -24,12 +24,14 @@ sealed abstract class HashDigest extends NetworkElement { /** * Represents the result of SHA1() */ -sealed abstract class Sha1Digest extends HashDigest { +sealed trait Sha1Digest extends Any with HashDigest { override def flip: Sha1DigestBE = Sha1DigestBE(bytes.reverse) } object Sha1Digest extends Factory[Sha1Digest] { - private case class Sha1DigestImpl(bytes: ByteVector) extends Sha1Digest { + private case class Sha1DigestImpl(bytes: ByteVector) + extends AnyVal + with Sha1Digest { // $COVERAGE-OFF$ override def toString = s"Sha1DigestImpl($hex)" // $COVERAGE-ON$ @@ -37,37 +39,44 @@ object Sha1Digest extends Factory[Sha1Digest] { override def fromBytes(bytes: ByteVector): Sha1Digest = Sha1DigestImpl(bytes) } -sealed abstract class Sha1DigestBE extends HashDigest { +sealed trait Sha1DigestBE extends Any with HashDigest { override def flip: Sha1Digest = Sha1Digest(bytes.reverse) } object Sha1DigestBE extends Factory[Sha1DigestBE] { - private case class Sha1DigestBEImpl(bytes: ByteVector) extends Sha1DigestBE { + private case class Sha1DigestBEImpl(bytes: ByteVector) + extends AnyVal + with Sha1DigestBE { // $COVERAGE-OFF$ override def toString = s"Sha1DigestBEImpl($hex)" // $COVERAGE-ON$ } - override def fromBytes(bytes: ByteVector): Sha1DigestBE = + + override def fromBytes(bytes: ByteVector): Sha1DigestBE = { Sha1DigestBEImpl(bytes) + } } /** * Represents the result of SHA256() */ -sealed abstract class Sha256Digest extends HashDigest { +sealed trait Sha256Digest extends Any with HashDigest { override def flip: Sha256DigestBE = Sha256DigestBE(bytes.reverse) } object Sha256Digest extends Factory[Sha256Digest] { - private case class Sha256DigestImpl(bytes: ByteVector) extends Sha256Digest { - require(bytes.length == 32, - // $COVERAGE-OFF$ - "Sha256Digest must be 32 bytes in size, got: " + bytes.length) + private case class Sha256DigestImpl(bytes: ByteVector) + extends AnyVal + with Sha256Digest { override def toString = s"Sha256DigestImpl($hex)" // $COVERAGE-ON$ } - override def fromBytes(bytes: ByteVector): Sha256Digest = + override def fromBytes(bytes: ByteVector): Sha256Digest = { + require(bytes.length == 32, + // $COVERAGE-OFF$ + "Sha256Digest must be 32 bytes in size, got: " + bytes.length) Sha256DigestImpl(bytes) + } private val e = ByteVector(Array.fill(32)(0.toByte)) @@ -78,41 +87,45 @@ object Sha256Digest extends Factory[Sha256Digest] { /** * Represents the result of SHA256() */ -sealed abstract class Sha256DigestBE extends HashDigest { +sealed trait Sha256DigestBE extends Any with HashDigest { override def flip: Sha256Digest = Sha256Digest(bytes.reverse) } object Sha256DigestBE extends Factory[Sha256DigestBE] { private case class Sha256DigestBEImpl(bytes: ByteVector) - extends Sha256DigestBE { - require(bytes.length == 32, - // $COVERAGE-OFF$ - "Sha256Digest must be 32 bytes in size, got: " + bytes.length) + extends AnyVal + with Sha256DigestBE { override def toString = s"Sha256DigestBEImpl($hex)" // $COVERAGE-ON$ } - override def fromBytes(bytes: ByteVector): Sha256DigestBE = + override def fromBytes(bytes: ByteVector): Sha256DigestBE = { + require(bytes.length == 32, + // $COVERAGE-OFF$ + "Sha256Digest must be 32 bytes in size, got: " + bytes.length) Sha256DigestBEImpl(bytes) + } } /** * Represents the result of SHA256(SHA256()) */ -sealed abstract class DoubleSha256Digest extends HashDigest { +sealed trait DoubleSha256Digest extends Any with HashDigest { def flip: DoubleSha256DigestBE = DoubleSha256DigestBE(bytes.reverse) } object DoubleSha256Digest extends Factory[DoubleSha256Digest] { private case class DoubleSha256DigestImpl(bytes: ByteVector) - extends DoubleSha256Digest { - require(bytes.length == 32, - // $COVERAGE-OFF$ - "DoubleSha256Digest must always be 32 bytes, got: " + bytes.length) + extends AnyVal + with DoubleSha256Digest { override def toString = s"DoubleSha256DigestImpl($hex)" // $COVERAGE-ON$ } - override def fromBytes(bytes: ByteVector): DoubleSha256Digest = + override def fromBytes(bytes: ByteVector): DoubleSha256Digest = { + require(bytes.length == 32, + // $COVERAGE-OFF$ + "DoubleSha256Digest must always be 32 bytes, got: " + bytes.length) DoubleSha256DigestImpl(bytes) + } private val e = ByteVector(Array.fill(32)(0.toByte)) val empty: DoubleSha256Digest = DoubleSha256Digest.fromBytes(e) @@ -120,21 +133,23 @@ object DoubleSha256Digest extends Factory[DoubleSha256Digest] { } /** The big endian version of [[org.bitcoins.core.crypto.DoubleSha256Digest DoubleSha256Digest]] */ -sealed abstract class DoubleSha256DigestBE extends HashDigest { +sealed trait DoubleSha256DigestBE extends Any with HashDigest { def flip: DoubleSha256Digest = DoubleSha256Digest.fromBytes(bytes.reverse) } object DoubleSha256DigestBE extends Factory[DoubleSha256DigestBE] { private case class DoubleSha256DigestBEImpl(bytes: ByteVector) - extends DoubleSha256DigestBE { - require(bytes.length == 32, - // $COVERAGE-OFF$ - "DoubleSha256Digest must always be 32 bytes, got: " + bytes.length) + extends AnyVal + with DoubleSha256DigestBE { override def toString = s"DoubleSha256BDigestBEImpl($hex)" // $COVERAGE-ON$ } - override def fromBytes(bytes: ByteVector): DoubleSha256DigestBE = + override def fromBytes(bytes: ByteVector): DoubleSha256DigestBE = { + require(bytes.length == 32, + // $COVERAGE-OFF$ + "DoubleSha256Digest must always be 32 bytes, got: " + bytes.length) DoubleSha256DigestBEImpl(bytes) + } val empty: DoubleSha256DigestBE = DoubleSha256Digest.empty.flip } @@ -142,80 +157,88 @@ object DoubleSha256DigestBE extends Factory[DoubleSha256DigestBE] { /** * Represents the result of RIPEMD160() */ -sealed abstract class RipeMd160Digest extends HashDigest { +sealed trait RipeMd160Digest extends Any with HashDigest { override def flip: RipeMd160DigestBE = RipeMd160DigestBE(bytes.reverse) } object RipeMd160Digest extends Factory[RipeMd160Digest] { private case class RipeMd160DigestImpl(bytes: ByteVector) - extends RipeMd160Digest { - require(bytes.length == 20, - // $COVERAGE-OFF$ - "RIPEMD160Digest must always be 20 bytes, got: " + bytes.length) + extends AnyVal + with RipeMd160Digest { override def toString = s"RipeMd160DigestImpl($hex)" // $COVERAGE-ON$ } - override def fromBytes(bytes: ByteVector): RipeMd160Digest = + override def fromBytes(bytes: ByteVector): RipeMd160Digest = { + require(bytes.length == 20, + // $COVERAGE-OFF$ + "RIPEMD160Digest must always be 20 bytes, got: " + bytes.length) RipeMd160DigestImpl(bytes) + } } /** * Represents the result of RIPEMD160() big endian */ -sealed abstract class RipeMd160DigestBE extends HashDigest { +sealed trait RipeMd160DigestBE extends Any with HashDigest { override def flip: RipeMd160Digest = RipeMd160Digest(bytes.reverse) } object RipeMd160DigestBE extends Factory[RipeMd160DigestBE] { private case class RipeMd160DigestBEImpl(bytes: ByteVector) - extends RipeMd160DigestBE { - require(bytes.length == 20, - // $COVERAGE-OFF$ - "RIPEMD160Digest must always be 20 bytes, got: " + bytes.length) + extends AnyVal + with RipeMd160DigestBE { override def toString = s"RipeMd160DigestBEImpl($hex)" // $COVERAGE-ON$ } - override def fromBytes(bytes: ByteVector): RipeMd160DigestBE = + override def fromBytes(bytes: ByteVector): RipeMd160DigestBE = { + require(bytes.length == 20, + // $COVERAGE-OFF$ + "RIPEMD160Digest must always be 20 bytes, got: " + bytes.length) RipeMd160DigestBEImpl(bytes) + } } /** * Represents the result of RIPEMD160(SHA256()) */ -sealed abstract class Sha256Hash160Digest extends HashDigest { +sealed trait Sha256Hash160Digest extends Any with HashDigest { override def flip: Sha256Hash160DigestBE = Sha256Hash160DigestBE(bytes.reverse) } object Sha256Hash160Digest extends Factory[Sha256Hash160Digest] { private case class Sha256Hash160DigestImpl(bytes: ByteVector) - extends Sha256Hash160Digest { - require(bytes.length == 20, - // $COVERAGE-OFF$ - "Sha256Hash160Digest must always be 20 bytes, got: " + bytes.length) + extends AnyVal + with Sha256Hash160Digest { override def toString = s"Sha256Hash160DigestImpl($hex)" // $COVERAGE-ON$ } - override def fromBytes(bytes: ByteVector): Sha256Hash160Digest = + override def fromBytes(bytes: ByteVector): Sha256Hash160Digest = { + require(bytes.length == 20, + // $COVERAGE-OFF$ + "Sha256Hash160Digest must always be 20 bytes, got: " + bytes.length) Sha256Hash160DigestImpl(bytes) + } } /** * Represents the result of RIPEMD160(SHA256()) big endian */ -sealed abstract class Sha256Hash160DigestBE extends HashDigest { +sealed trait Sha256Hash160DigestBE extends Any with HashDigest { override def flip: Sha256Hash160Digest = Sha256Hash160Digest(bytes.reverse) } object Sha256Hash160DigestBE extends Factory[Sha256Hash160DigestBE] { private case class Sha256Hash160DigestBEImpl(bytes: ByteVector) - extends Sha256Hash160DigestBE { - require(bytes.length == 20, - // $COVERAGE-OFF$ - "Sha256Hash160Digest must always be 20 bytes, got: " + bytes.length) + extends AnyVal + with Sha256Hash160DigestBE { override def toString = s"Sha256Hash160DigestBEImpl($hex)" // $COVERAGE-ON$ } - override def fromBytes(bytes: ByteVector): Sha256Hash160DigestBE = + override def fromBytes(bytes: ByteVector): Sha256Hash160DigestBE = { + require(bytes.length == 20, + // $COVERAGE-OFF$ + "Sha256Hash160Digest must always be 20 bytes, got: " + bytes.length) Sha256Hash160DigestBEImpl(bytes) + } } diff --git a/core/src/main/scala/org/bitcoins/core/protocol/NetworkElement.scala b/core/src/main/scala/org/bitcoins/core/protocol/NetworkElement.scala index 91b7dc5c53..c49faa773d 100644 --- a/core/src/main/scala/org/bitcoins/core/protocol/NetworkElement.scala +++ b/core/src/main/scala/org/bitcoins/core/protocol/NetworkElement.scala @@ -8,7 +8,7 @@ import scodec.bits.ByteVector * This represents a element that can be serialized to * be sent over the network */ -abstract class NetworkElement { +trait NetworkElement extends Any { /** The size of the NetworkElement in bytes. */ def size: Long = bytes.size @@ -19,5 +19,5 @@ abstract class NetworkElement { /** The byte representation of the NetworkElement */ def bytes: ByteVector - lazy val logger = BitcoinSLogger.logger + def logger = BitcoinSLogger.logger }