mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-13 19:37:30 +01:00
Merge pull request #149 from Christewart/add_hashdigest_endianness_flip
Adding helper function to flip hash's endianness, adding helper funct…
This commit is contained in:
commit
cbf23d0935
3 changed files with 70 additions and 13 deletions
|
@ -5,22 +5,32 @@ import org.bitcoins.core.util.{ Factory, BitcoinSUtil }
|
|||
/**
|
||||
* Created by chris on 5/24/16.
|
||||
*/
|
||||
sealed trait HashDigest {
|
||||
sealed abstract class HashDigest {
|
||||
/** The message digest represented in bytes */
|
||||
def bytes: Seq[Byte]
|
||||
|
||||
/** The message digest represented in hexadecimal */
|
||||
def hex: String = BitcoinSUtil.encodeHex(bytes)
|
||||
|
||||
/**
|
||||
* Flips the endianness of the byte sequence.
|
||||
* Since bitcoin unfortunately has inconsistent endianness between the protocol
|
||||
* level and the presentation level. This is useful for switching between the two.
|
||||
* @return
|
||||
*/
|
||||
def flip: HashDigest
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the result of SHA1()
|
||||
*/
|
||||
sealed trait Sha1Digest extends HashDigest
|
||||
sealed abstract class Sha1Digest extends HashDigest {
|
||||
override def flip: Sha1Digest = Sha1Digest(bytes.reverse)
|
||||
}
|
||||
|
||||
object Sha1Digest extends Factory[Sha1Digest] {
|
||||
private case class Sha1DigestImpl(bytes: Seq[Byte]) extends Sha1Digest {
|
||||
override def toString = "Sha1DigestImpl(" + hex + ")"
|
||||
override def toString = s"Sha1DigestImpl($hex)"
|
||||
}
|
||||
override def fromBytes(bytes: Seq[Byte]): Sha1Digest = Sha1DigestImpl(bytes)
|
||||
}
|
||||
|
@ -28,12 +38,14 @@ object Sha1Digest extends Factory[Sha1Digest] {
|
|||
/**
|
||||
* Represents the result of SHA256()
|
||||
*/
|
||||
sealed trait Sha256Digest extends HashDigest
|
||||
sealed abstract class Sha256Digest extends HashDigest {
|
||||
override def flip: Sha256Digest = Sha256Digest(bytes.reverse)
|
||||
}
|
||||
|
||||
object Sha256Digest extends Factory[Sha256Digest] {
|
||||
private case class Sha256DigestImpl(bytes: Seq[Byte]) extends Sha256Digest {
|
||||
require(bytes.length == 32, "Sha256Digest must be 32 bytes in size, got: " + bytes.length)
|
||||
override def toString = "Sha256DigestImpl(" + hex + ")"
|
||||
override def toString = s"Sha256DigestImpl($hex)"
|
||||
}
|
||||
override def fromBytes(bytes: Seq[Byte]): Sha256Digest = Sha256DigestImpl(bytes)
|
||||
}
|
||||
|
@ -41,12 +53,14 @@ object Sha256Digest extends Factory[Sha256Digest] {
|
|||
/**
|
||||
* Represents the result of SHA256(SHA256())
|
||||
*/
|
||||
sealed trait DoubleSha256Digest extends HashDigest
|
||||
sealed abstract class DoubleSha256Digest extends HashDigest {
|
||||
def flip: DoubleSha256Digest = DoubleSha256Digest(bytes.reverse)
|
||||
}
|
||||
|
||||
object DoubleSha256Digest extends Factory[DoubleSha256Digest] {
|
||||
private case class DoubleSha256DigestImpl(bytes: Seq[Byte]) extends DoubleSha256Digest {
|
||||
require(bytes.length == 32, "DoubleSha256Digest must always be 32 bytes, got: " + bytes.length)
|
||||
override def toString = "DoubleSha256DigestImpl(" + hex + ")"
|
||||
override def toString = s"DoubleSha256DigestImpl($hex)"
|
||||
}
|
||||
override def fromBytes(bytes: Seq[Byte]): DoubleSha256Digest = DoubleSha256DigestImpl(bytes)
|
||||
|
||||
|
@ -55,12 +69,14 @@ object DoubleSha256Digest extends Factory[DoubleSha256Digest] {
|
|||
/**
|
||||
* Represents the result of RIPEMD160()
|
||||
*/
|
||||
sealed trait RipeMd160Digest extends HashDigest
|
||||
sealed abstract class RipeMd160Digest extends HashDigest {
|
||||
override def flip: RipeMd160Digest = RipeMd160Digest(bytes.reverse)
|
||||
}
|
||||
|
||||
object RipeMd160Digest extends Factory[RipeMd160Digest] {
|
||||
private case class RipeMd160DigestImpl(bytes: Seq[Byte]) extends RipeMd160Digest {
|
||||
require(bytes.length == 20, "RIPEMD160Digest must always be 20 bytes, got: " + bytes.length)
|
||||
override def toString = "RipeMd160DigestImpl(" + hex + ")"
|
||||
override def toString = s"RipeMd160DigestImpl($hex)"
|
||||
}
|
||||
override def fromBytes(bytes: Seq[Byte]): RipeMd160Digest = RipeMd160DigestImpl(bytes)
|
||||
}
|
||||
|
@ -68,12 +84,14 @@ object RipeMd160Digest extends Factory[RipeMd160Digest] {
|
|||
/**
|
||||
* Represents the result of RIPEMD160(SHA256())
|
||||
*/
|
||||
sealed trait Sha256Hash160Digest extends HashDigest
|
||||
sealed abstract class Sha256Hash160Digest extends HashDigest {
|
||||
override def flip: Sha256Hash160Digest = Sha256Hash160Digest(bytes.reverse)
|
||||
}
|
||||
|
||||
object Sha256Hash160Digest extends Factory[Sha256Hash160Digest] {
|
||||
private case class Sha256Hash160DigestImpl(bytes: Seq[Byte]) extends Sha256Hash160Digest {
|
||||
require(bytes.length == 20, "Sha256Hash160Digest must always be 20 bytes, got: " + bytes.length)
|
||||
override def toString = "Sha256Hash160DigestImpl(" + hex + ")"
|
||||
override def toString = s"Sha256Hash160DigestImpl($hex)"
|
||||
}
|
||||
override def fromBytes(bytes: Seq[Byte]): Sha256Hash160Digest = Sha256Hash160DigestImpl(bytes)
|
||||
}
|
|
@ -40,6 +40,15 @@ sealed trait BlockHeader extends NetworkElement {
|
|||
|
||||
def previousBlockHash: DoubleSha256Digest
|
||||
|
||||
/**
|
||||
* Returns the big endian encoding of the previous block hash
|
||||
* This is useful for using rpc and block exporers, but is NOT used in the protocol itself
|
||||
* See this link for more info
|
||||
* [[https://bitcoin.stackexchange.com/questions/2063/why-does-the-bitcoin-protocol-use-the-little-endian-notation]]
|
||||
* @return
|
||||
*/
|
||||
def previousBlockHashBE: DoubleSha256Digest = previousBlockHash.flip
|
||||
|
||||
/**
|
||||
* A SHA256(SHA256()) hash in internal byte order.
|
||||
* The merkle root is derived from the hashes of all transactions included in this block,
|
||||
|
@ -51,6 +60,14 @@ sealed trait BlockHeader extends NetworkElement {
|
|||
|
||||
def merkleRootHash: DoubleSha256Digest
|
||||
|
||||
/** Returns the merkle root hash in BIG ENDIAN format. This is not compatible with the bitcoin
|
||||
* protocol but it is useful for rpc clients and block explorers
|
||||
* See this link for more info
|
||||
* [[https://bitcoin.stackexchange.com/questions/2063/why-does-the-bitcoin-protocol-use-the-little-endian-notation]]
|
||||
* @return
|
||||
*/
|
||||
def merkleRootHashBE: DoubleSha256Digest = merkleRootHash.flip
|
||||
|
||||
/**
|
||||
* The block time is a Unix epoch time when the miner started hashing the header (according to the miner).
|
||||
* Must be greater than or equal to the median time of the previous 11 blocks.
|
||||
|
@ -78,9 +95,18 @@ sealed trait BlockHeader extends NetworkElement {
|
|||
*/
|
||||
def nonce: UInt32
|
||||
|
||||
/** Returns the block's hash */
|
||||
/** Returns the block's hash in the protocol level little endian encoding */
|
||||
def hash: DoubleSha256Digest = CryptoUtil.doubleSHA256(bytes)
|
||||
|
||||
/**
|
||||
* Returns the block hash in big endian format, this is useful for rpc
|
||||
* and block explorer debugging. This is *not* used in the core protocol itself.
|
||||
* See this link for more info
|
||||
* [[https://bitcoin.stackexchange.com/questions/2063/why-does-the-bitcoin-protocol-use-the-little-endian-notation]]
|
||||
* @return
|
||||
*/
|
||||
def hashBE: DoubleSha256Digest = hash.flip
|
||||
|
||||
override def bytes: Seq[Byte] = RawBlockHeaderSerializer.write(this)
|
||||
|
||||
}
|
||||
|
|
|
@ -14,10 +14,21 @@ import scala.util.{ Failure, Success, Try }
|
|||
sealed abstract class Transaction extends NetworkElement {
|
||||
/**
|
||||
* The sha256(sha256(tx)) of this transaction
|
||||
* Note that this is the big endian encoding of the hash NOT the little endian encoding displayed on block explorers
|
||||
* Note that this is the little endian encoding of the hash, NOT the big endian encoding shown in block
|
||||
* explorers. See this link for more info
|
||||
* [[https://bitcoin.stackexchange.com/questions/2063/why-does-the-bitcoin-protocol-use-the-little-endian-notation]]
|
||||
*/
|
||||
def txId: DoubleSha256Digest = CryptoUtil.doubleSHA256(bytes)
|
||||
|
||||
/**
|
||||
* This is the BIG ENDIAN encoding for the txid. This is commonly used for
|
||||
* RPC interfaces and block explorers, this encoding is NOT used at the protocol level
|
||||
* For more info see:
|
||||
* [[https://bitcoin.stackexchange.com/questions/2063/why-does-the-bitcoin-protocol-use-the-little-endian-notation]]
|
||||
* @return
|
||||
*/
|
||||
def txIdBE: DoubleSha256Digest = txId.flip
|
||||
|
||||
/** The version number for this transaction */
|
||||
def version: UInt32
|
||||
|
||||
|
@ -100,6 +111,8 @@ sealed abstract class WitnessTransaction extends Transaction {
|
|||
*/
|
||||
def wTxId: DoubleSha256Digest = CryptoUtil.doubleSHA256(bytes)
|
||||
|
||||
/** Returns the big endian encoding of the wtxid */
|
||||
def wTxIdBE: DoubleSha256Digest = wTxId.flip
|
||||
/**
|
||||
* Weight calculation in bitcoin for witness txs
|
||||
* [[https://github.com/bitcoin/bitcoin/blob/5961b23898ee7c0af2626c46d5d70e80136578d3/src/consensus/validation.h#L96]]
|
||||
|
|
Loading…
Add table
Reference in a new issue