Make all instances of HashDigest extend AnyVal so we do not allocate runtime objects to avoid GCs (#690)

This commit is contained in:
Chris Stewart 2019-08-14 06:35:10 -05:00 committed by GitHub
parent 7caf0c355b
commit 6369c64b6f
2 changed files with 80 additions and 57 deletions

View file

@ -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)
}
}

View file

@ -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
}