From 45106114d056ff552af0b1b53f71de6f6579d62f Mon Sep 17 00:00:00 2001 From: fluency03 Date: Sun, 6 May 2018 14:54:07 +0200 Subject: [PATCH] add Base58 and refactor SHA256 --- build.sbt | 2 +- .../github/fluency03/blockchain/Base58.scala | 50 +++++++++++++++++ .../github/fluency03/blockchain/Crypto.scala | 15 +++++- .../fluency03/blockchain/RIPEMD160.scala | 5 ++ .../github/fluency03/blockchain/SHA256.scala | 31 +++++++++++ .../blockchain/core/BlockHeader.scala | 2 +- .../fluency03/blockchain/core/Merkle.scala | 2 +- .../blockchain/core/Transaction.scala | 4 +- .../github/fluency03/blockchain/package.scala | 54 +++++++++++-------- .../fluency03/blockchain/Base58Test.scala | 44 +++++++++++++++ .../fluency03/blockchain/RIPEMD160Test.scala | 12 +++++ .../fluency03/blockchain/SHA256Test.scala | 39 ++++++++++++++ .../fluency03/blockchain/UtilTest.scala | 7 --- .../blockchain/core/MerkleTest.scala | 12 ++--- 14 files changed, 236 insertions(+), 43 deletions(-) create mode 100644 src/main/scala/com/github/fluency03/blockchain/Base58.scala create mode 100644 src/main/scala/com/github/fluency03/blockchain/RIPEMD160.scala create mode 100644 src/main/scala/com/github/fluency03/blockchain/SHA256.scala create mode 100644 src/test/scala/com/github/fluency03/blockchain/Base58Test.scala create mode 100644 src/test/scala/com/github/fluency03/blockchain/RIPEMD160Test.scala create mode 100644 src/test/scala/com/github/fluency03/blockchain/SHA256Test.scala diff --git a/build.sbt b/build.sbt index ab88d07..c825b06 100644 --- a/build.sbt +++ b/build.sbt @@ -40,7 +40,7 @@ libraryDependencies ++= { "org.scalaz" %% "scalaz-core" % scalazVersion, "org.json4s" %% "json4s-native" % json4sVersion, "org.json4s" %% "json4s-jackson" % json4sVersion, - "org.bouncycastle" % "bcprov-jdk15on" % "1.59" + "org.bouncycastle" % "bcprov-jdk15on" % "1.59" ) } ++ httpDependencies ++ testDependencies diff --git a/src/main/scala/com/github/fluency03/blockchain/Base58.scala b/src/main/scala/com/github/fluency03/blockchain/Base58.scala new file mode 100644 index 0000000..bff83a8 --- /dev/null +++ b/src/main/scala/com/github/fluency03/blockchain/Base58.scala @@ -0,0 +1,50 @@ +package com.github.fluency03.blockchain + +import org.bouncycastle.util.encoders.Hex + +import scala.annotation.tailrec + +object Base58 { + + lazy val ALPHABET: Array[Char] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray + private val ENCODED_ZERO = ALPHABET(0) + + def encodeString(str: String): String = encode(str.getBytes) + + def encodeHex(hex: String): String = encode(hex.hex2Bytes) + + def encode(bytes: Bytes): String = { + @tailrec + def buildBase58(res: String, bi: BigInt): String = + if (bi <= 0) res + else buildBase58(ALPHABET((bi % 58).toInt) + res, bi / 58) + + @tailrec + def confirmZeroByte(res: String, bytes: Array[Byte], idx: Int): String = + if (bytes(idx) != 0 || idx >= bytes.length) res + else confirmZeroByte(ENCODED_ZERO + res, bytes, idx + 1) + + confirmZeroByte(buildBase58("", bytes.toBigInt), bytes, 0) + } + + def decode(str: String): Bytes = { + @tailrec + def restoreBigInt(chars: Array[Char], bi: BigInt, idx: Int): BigInt = + if (idx >= chars.length) bi + else { + val i: Int = ALPHABET.zipWithIndex.find(t => t._1 == chars(idx)).map(_._2).get + restoreBigInt(chars, bi * 58 + i, idx + 1) + } + + val bi = restoreBigInt(str.toCharArray, 0, 0) + Hex.decode(bi.toString(16)) + } + + def decodeToHex(str: String): String = new String(decode(str)) + + def checkEncodeHex(str: String): String = encodeString(str + str.hex2Bytes.toSha256Digest.toSha256.substring(0, 8)) + + def checkEncode(bytes: Bytes): String = encode(bytes ++ bytes.toSha256Digest.toSha256Digest.slice(0, 4)) + + +} \ No newline at end of file diff --git a/src/main/scala/com/github/fluency03/blockchain/Crypto.scala b/src/main/scala/com/github/fluency03/blockchain/Crypto.scala index 48976ed..f5aff58 100644 --- a/src/main/scala/com/github/fluency03/blockchain/Crypto.scala +++ b/src/main/scala/com/github/fluency03/blockchain/Crypto.scala @@ -59,10 +59,21 @@ object Crypto { KeyFactory.getInstance(KEY_ALGORITHM) .generatePrivate(new ECPrivateKeySpec(new BigInteger(hex, 16), ecSpec)) - def publicKeyToHex(publicKey: PublicKey): String = - publicKey.asInstanceOf[ECPublicKey].getQ.getEncoded(false).toHex + def publicKeyToHex(publicKey: PublicKey): String = publicKeyToBytes(publicKey).toHex def privateKeyToHex(privateKey: PrivateKey): String = privateKey.asInstanceOf[ECPrivateKey].getD.toString(16) + def publicKeyToBytes(publicKey: PublicKey): Bytes = + publicKey.asInstanceOf[ECPublicKey].getQ.getEncoded(false) + + def privateKeyToBytes(privateKey: PrivateKey): Bytes = + privateKey.asInstanceOf[ECPrivateKey].getD.toByteArray + + def publicKeyToAddress(publicKey: String, networkBytes: String = "00"): String = + Base58.checkEncode(networkBytes.hex2Bytes ++ publicKey.hex2Bytes.toHash160Bytes) + + + + } diff --git a/src/main/scala/com/github/fluency03/blockchain/RIPEMD160.scala b/src/main/scala/com/github/fluency03/blockchain/RIPEMD160.scala new file mode 100644 index 0000000..7d7388f --- /dev/null +++ b/src/main/scala/com/github/fluency03/blockchain/RIPEMD160.scala @@ -0,0 +1,5 @@ +package com.github.fluency03.blockchain + +object RIPEMD160 { + +} diff --git a/src/main/scala/com/github/fluency03/blockchain/SHA256.scala b/src/main/scala/com/github/fluency03/blockchain/SHA256.scala new file mode 100644 index 0000000..a76ddc5 --- /dev/null +++ b/src/main/scala/com/github/fluency03/blockchain/SHA256.scala @@ -0,0 +1,31 @@ +package com.github.fluency03.blockchain + +import java.security.MessageDigest + +object SHA256 { + + /** + * Generate SHA256 Hash from a input String. + * https://gist.github.com/navicore/6234040bbfce3aa58f866db314c07c15 + */ + def hash(text: String) : String = hash(text.getBytes) + + /** + * Generate SHA256 Hash from a input Array of Byte. + */ + def hash(bytes: Bytes) : String = String.format("%064x", + new java.math.BigInteger(1, hashToDigest(bytes))) + + /** + * Generate digest from a input Array of Byte. + */ + def hashToDigest(bytes: Bytes): Bytes = + MessageDigest.getInstance("SHA-256").digest(bytes) + + /** + * Calculate the hash of concatenation a Seq of Strings. + */ + def hashAll(strings: String*): String = hash(strings mkString "") + + +} diff --git a/src/main/scala/com/github/fluency03/blockchain/core/BlockHeader.scala b/src/main/scala/com/github/fluency03/blockchain/core/BlockHeader.scala index 7ab24d4..ea8588f 100644 --- a/src/main/scala/com/github/fluency03/blockchain/core/BlockHeader.scala +++ b/src/main/scala/com/github/fluency03/blockchain/core/BlockHeader.scala @@ -55,6 +55,6 @@ object BlockHeader { timestamp: Long, difficulty: Int, nonce: Int): String = - sha256Of(index.toString, previousHash, data, merkleHash, timestamp.toString, difficulty.toString, nonce.toString) + SHA256.hashAll(index.toString, previousHash, data, merkleHash, timestamp.toString, difficulty.toString, nonce.toString) } diff --git a/src/main/scala/com/github/fluency03/blockchain/core/Merkle.scala b/src/main/scala/com/github/fluency03/blockchain/core/Merkle.scala index b8ad456..9f62110 100644 --- a/src/main/scala/com/github/fluency03/blockchain/core/Merkle.scala +++ b/src/main/scala/com/github/fluency03/blockchain/core/Merkle.scala @@ -11,7 +11,7 @@ object Merkle { case 0 => ZERO64 case 1 => hashes.head case n if n % 2 != 0 => computeRootOfHashes(hashes :+ hashes.last) // append last element again - case _ => computeRootOfHashes(hashes.grouped(2).map { a => sha256Of(a(0), a(1)) } .toList) + case _ => computeRootOfHashes(hashes.grouped(2).map { a => SHA256.hashAll(a(0), a(1)) } .toList) } } diff --git a/src/main/scala/com/github/fluency03/blockchain/core/Transaction.scala b/src/main/scala/com/github/fluency03/blockchain/core/Transaction.scala index b9cbd75..dafff94 100644 --- a/src/main/scala/com/github/fluency03/blockchain/core/Transaction.scala +++ b/src/main/scala/com/github/fluency03/blockchain/core/Transaction.scala @@ -61,12 +61,12 @@ object Transaction { hashOfTransaction(cbTx) == cbTx.id // hash of transaction - def hashOfTransaction(tx: Transaction): String = sha256Of( + def hashOfTransaction(tx: Transaction): String = SHA256.hashAll( tx.txIns.map(tx => tx.previousOut.id + tx.previousOut.index).mkString, tx.txOuts.map(tx => tx.address + tx.amount).mkString, tx.timestamp.toString) - def hashOfTransaction(txIns: Seq[TxIn], txOuts: Seq[TxOut], timestamp: Long): String = sha256Of( + def hashOfTransaction(txIns: Seq[TxIn], txOuts: Seq[TxOut], timestamp: Long): String = SHA256.hashAll( txIns.map(tx => tx.previousOut.id + tx.previousOut.index).mkString, txOuts.map(tx => tx.address + tx.amount).mkString, timestamp.toString) diff --git a/src/main/scala/com/github/fluency03/blockchain/package.scala b/src/main/scala/com/github/fluency03/blockchain/package.scala index c4b8d63..721c22c 100644 --- a/src/main/scala/com/github/fluency03/blockchain/package.scala +++ b/src/main/scala/com/github/fluency03/blockchain/package.scala @@ -1,11 +1,12 @@ package com.github.fluency03 import java.nio.charset.Charset -import java.security.{MessageDigest, PrivateKey, PublicKey} +import java.security.{PrivateKey, PublicKey} import java.time.Instant import com.github.fluency03.blockchain.Crypto.{privateKeyToHex, publicKeyToHex} import com.github.fluency03.blockchain.core.{Peer, PeerSimple, TxIn, TxOut} +import org.bouncycastle.crypto.digests.RIPEMD160Digest import org.bouncycastle.util.encoders.{Base64, Hex} import org.json4s.native.Serialization import org.json4s.{Formats, NoTypeHints} @@ -33,15 +34,24 @@ package object blockchain { implicit class StringImplicit(val str: String) { def hex2Long: Long = java.lang.Long.parseLong(str, 16) + def hex2BigInt: BigInt = BigInt(str, 16) def hex2Bytes: Array[Byte] = Hex.decode(str) def hex2Binary: String = binaryOfHex(str) - def toBase64: String = base64Of(str.getBytes("UTF-8")) - def toSha256: String = sha256HashOf(str) + def toBase64: String = base64Of(str.getBytes) + def toSha256: String = SHA256.hash(str) + def toRipemd160Of: String = ripemd160Of(str) } implicit class BytesImplicit(val bytes: Bytes) { def toHex: String = Hex.toHexString(bytes) + def toBigInt: BigInt = BigInt(bytes) def toBase64: String = base64Of(bytes) + def toSha256: String = SHA256.hash(bytes) + def toSha256Digest: Bytes = SHA256.hashToDigest(bytes) + def toRipemd160Of: String = ripemd160Of(bytes) + def toRipemd160ODigest: Bytes = ripemd160ODigestOf(bytes) + def toHash160: String = hash160Of(bytes) + def toHash160Bytes: Bytes = hash160BytesOf(bytes) } implicit class PublicKeyImplicit(val publicKey: PublicKey) { @@ -57,25 +67,6 @@ package object blockchain { } - /** - * Generate SHA256 Hash from a input String. - * https://gist.github.com/navicore/6234040bbfce3aa58f866db314c07c15 - */ - def sha256HashOf(text: String) : String = String.format("%064x", - new java.math.BigInteger(1, digestOf(text))) - - /** - * Generate digest from a input String. - * https://gist.github.com/navicore/6234040bbfce3aa58f866db314c07c15 - */ - def digestOf(text: String): Bytes = - MessageDigest.getInstance("SHA-256").digest(text.getBytes("UTF-8")) - - /** - * Calculate the hash of concatenation a Seq of Strings. - */ - def sha256Of(strings: String*): String = sha256HashOf(strings mkString "") - /** * Return the current timestamp in Unix Epoch Time. */ @@ -99,7 +90,7 @@ package object blockchain { /** * Encode a String to Base64. */ - def base64Of(text: String): String = Base64.toBase64String(text.getBytes("UTF-8")) + def base64Of(text: String): String = Base64.toBase64String(text.getBytes) /** * Encode an Array of Bytes String to Base64. @@ -112,5 +103,22 @@ package object blockchain { def fromBase64(base64: String): String = new String(Base64.decode(base64), "UTF-8") + def ripemd160Of(str: String): String = ripemd160Of(str.getBytes) + + def ripemd160Of(bytes: Bytes): String = ripemd160ODigestOf(bytes).map("%02x".format(_)).mkString + + def ripemd160ODigestOf(bytes: Bytes): Bytes = { + val (raw, messageDigest) = (bytes, new RIPEMD160Digest()) + messageDigest.update(raw, 0, raw.length) + val out = Array.fill[Byte](messageDigest.getDigestSize)(0) + messageDigest.doFinal(out, 0) + out + } + + def hash160Of(bytes: Bytes): String = ripemd160Of(SHA256.hashToDigest(bytes)) + + def hash160BytesOf(bytes: Bytes): Bytes = ripemd160ODigestOf(SHA256.hashToDigest(bytes)) + + } diff --git a/src/test/scala/com/github/fluency03/blockchain/Base58Test.scala b/src/test/scala/com/github/fluency03/blockchain/Base58Test.scala new file mode 100644 index 0000000..71a8a60 --- /dev/null +++ b/src/test/scala/com/github/fluency03/blockchain/Base58Test.scala @@ -0,0 +1,44 @@ +package com.github.fluency03.blockchain + +import org.scalatest.{FlatSpec, Matchers} + +class Base58Test extends FlatSpec with Matchers { + + "Base58" should "encode String to Base58 and decode it back to original." in { + Base58.encodeString("abc") shouldEqual "ZiCa" + Base58.encodeString("bitcoin") shouldEqual "4jJc4sAwPs" + Base58.encodeString("blockchain") shouldEqual "6XidGdGeMggztM" + Base58.encodeString("00F5F2D624CFB5C3F66D06123D0829D1C9CEBF770E2C13A798") shouldEqual + "bSMTi3tDLFwyLC26U3SB8ctp7Y4iCcGpXxztHUWQSeo4tXV6p7WABrsxVa4tB7n8e8iT" + + Base58.decodeToHex("ZiCa") shouldEqual "abc" + Base58.decodeToHex("4jJc4sAwPs") shouldEqual "bitcoin" + Base58.decodeToHex("6XidGdGeMggztM") shouldEqual "blockchain" + + Base58.encodeString("04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a254112" + + "9368d7d9bb05cd8afbdf7705a6540d98028236965553f91bf1c5b4f70073f55b55d") shouldEqual + "2f6iufmY2PoZhwnZkWwvNYmN6A3G4dH8TSDH1Y5FKpC7yCxoJfqStHLBmkUYrwkekaYUttiAwYWCtioTWJn1s" + + "mMSGtMwsyLqmSLpQbLrTpSrMNjKcNzL1viBDBkFuJEM3KMtPAx2g2hVLeBFDP79iaqHvwuVyu2zaViPVeLjWtRpWzu4sM" + + Base58.decodeToHex("2f6iufmY2PoZhwnZkWwvNYmN6A3G4dH8TSDH1Y5FKpC7yCxoJfqStHLBmkUYrwkekaYUttiAwYWCtioTWJn1s" + + "mMSGtMwsyLqmSLpQbLrTpSrMNjKcNzL1viBDBkFuJEM3KMtPAx2g2hVLeBFDP79iaqHvwuVyu2zaViPVeLjWtRpWzu4sM") shouldEqual + "04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a254112" + + "9368d7d9bb05cd8afbdf7705a6540d98028236965553f91bf1c5b4f70073f55b55d" + + ripemd160Of("61956bf4e271df1cd88a9a7828a59c88eb7ea13c176c4d03355ac27129760673") shouldEqual + "352b0b6bd7284755d5c685fb7793c9f4d672c5ff" + ripemd160Of("abcd") shouldEqual "2e7e536fd487deaa943fda5522d917bdb9011b7a" + ripemd160Of("205575f4f33a39ff47f569613a694c6321d6cdd7") shouldEqual "bd4e962413308b4a6689aa0e7cff5e419391c3db" + ripemd160Of("bitcoin") shouldEqual "5891bf40b0b0e8e19f524bdc2e842d012264624b" + ripemd160Of("blockchain") shouldEqual "5c403af45cae136a79eea3c7e9f79c3dd049776b" + + Crypto.publicKeyToAddress("04B4D653FCBB4B96000C99343F23B08A44FA306031E0587F9E657AB" + + "4A2541129368D7D9BB05CD8AFBDF7705A6540D98028236965553F91BF1C5B4F70073F55B55D") shouldEqual + "1DU8Hi1sbHTpEP9vViBEkEw6noeUrgKkJH" + + Base58.encodeHex("0088C2D2FA846282C870A76CADECBE45C4ACD72BB655DA1216") shouldEqual + "1DU8Hi1sbHTpEP9vViBEkEw6noeUrgKkJH" + + } + +} diff --git a/src/test/scala/com/github/fluency03/blockchain/RIPEMD160Test.scala b/src/test/scala/com/github/fluency03/blockchain/RIPEMD160Test.scala new file mode 100644 index 0000000..316358b --- /dev/null +++ b/src/test/scala/com/github/fluency03/blockchain/RIPEMD160Test.scala @@ -0,0 +1,12 @@ +package com.github.fluency03.blockchain + +import org.scalatest.{FlatSpec, Matchers} + +class RIPEMD160Test extends FlatSpec with Matchers { + + "RIPEMD160" should "encode String to RIPEMD160 and decode it back to original." in { + + + } + +} diff --git a/src/test/scala/com/github/fluency03/blockchain/SHA256Test.scala b/src/test/scala/com/github/fluency03/blockchain/SHA256Test.scala new file mode 100644 index 0000000..97347ac --- /dev/null +++ b/src/test/scala/com/github/fluency03/blockchain/SHA256Test.scala @@ -0,0 +1,39 @@ +package com.github.fluency03.blockchain + +import org.scalatest.{FlatSpec, Matchers} + +class SHA256Test extends FlatSpec with Matchers { + + "SHA256" should "encode String to SHA256 and decode it back to original." in { + SHA256.hash("open sesame") shouldEqual "41ef4bb0b23661e66301aac36066912dac037827b4ae63a7b1165a5aa93ed4eb" + SHA256.hashAll("open", " ", "sesame") shouldEqual "41ef4bb0b23661e66301aac36066912dac037827b4ae63a7b1165a5aa93ed4eb" + SHA256.hash("") shouldEqual "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + SHA256.hash("0000000000000000000000000000000000000000000000000000000000000") shouldEqual "a738b0b5c122d30af5b9da1c63c5d590a31aeafa7de1723ee9b5e3a11c9def35" + + SHA256.hash(("04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a25411" + + "29368d7d9bb05cd8afbdf7705a6540d98028236965553f91bf1c5b4f70073f55b55d").hex2Bytes) shouldEqual + "173BDED8F2A2069C193E63EA30DC8FD20E815EC3642B9C24AD7002C03D1BFB9B".toLowerCase + + SHA256.hashToDigest(("04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a25411" + + "29368d7d9bb05cd8afbdf7705a6540d98028236965553f91bf1c5b4f70073f55b55d").hex2Bytes) shouldEqual + "173BDED8F2A2069C193E63EA30DC8FD20E815EC3642B9C24AD7002C03D1BFB9B".hex2Bytes + + SHA256.hash("0088C2D2FA846282C870A76CADECBE45C4ACD72BB6".hex2Bytes) shouldEqual + "1F87490FC565C795595563D56412A0100CD1F29FFB60A3779789FE0C018C6164".toLowerCase + + + SHA256.hash("1F87490FC565C795595563D56412A0100CD1F29FFB60A3779789FE0C018C6164".hex2Bytes) shouldEqual + "55DA1216A5EF5BAE605B543A5A9CE2AC8A8FA1781AA037F35DE3F2222BAD8127".toLowerCase + + ripemd160Of("173BDED8F2A2069C193E63EA30DC8FD20E815EC3642B9C24AD7002C03D1BFB9B".hex2Bytes) shouldEqual + "88C2D2FA846282C870A76CADECBE45C4ACD72BB6".toLowerCase + + hash160BytesOf(("04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a25411" + + "29368d7d9bb05cd8afbdf7705a6540d98028236965553f91bf1c5b4f70073f55b55d").hex2Bytes) shouldEqual + "88C2D2FA846282C870A76CADECBE45C4ACD72BB6".hex2Bytes + + SHA256.hashToDigest("00".hex2Bytes ++ "88C2D2FA846282C870A76CADECBE45C4ACD72BB6".hex2Bytes) shouldEqual + "1F87490FC565C795595563D56412A0100CD1F29FFB60A3779789FE0C018C6164".hex2Bytes + } + +} diff --git a/src/test/scala/com/github/fluency03/blockchain/UtilTest.scala b/src/test/scala/com/github/fluency03/blockchain/UtilTest.scala index f7f3f00..fcca1cb 100644 --- a/src/test/scala/com/github/fluency03/blockchain/UtilTest.scala +++ b/src/test/scala/com/github/fluency03/blockchain/UtilTest.scala @@ -7,13 +7,6 @@ import org.scalatest.{FlatSpec, Matchers} class UtilTest extends FlatSpec with Matchers with MockFactory { - "hashOf" should "convert a String to SHA256 hash." in { - sha256Of("open sesame") shouldEqual "41ef4bb0b23661e66301aac36066912dac037827b4ae63a7b1165a5aa93ed4eb" - sha256Of("open", " ", "sesame") shouldEqual "41ef4bb0b23661e66301aac36066912dac037827b4ae63a7b1165a5aa93ed4eb" - sha256Of("") shouldEqual "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - sha256Of("0000000000000000000000000000000000000000000000000000000000000") shouldEqual "a738b0b5c122d30af5b9da1c63c5d590a31aeafa7de1723ee9b5e3a11c9def35" - } - "getCurrentTimestamp" should "be able to get current Unix epoch time." in { val t1 = getCurrentTimestamp val t2 = getCurrentTimestamp diff --git a/src/test/scala/com/github/fluency03/blockchain/core/MerkleTest.scala b/src/test/scala/com/github/fluency03/blockchain/core/MerkleTest.scala index 257cdc6..f6749f3 100644 --- a/src/test/scala/com/github/fluency03/blockchain/core/MerkleTest.scala +++ b/src/test/scala/com/github/fluency03/blockchain/core/MerkleTest.scala @@ -23,21 +23,21 @@ class MerkleTest extends FlatSpec with Matchers { "A Merkle Tree" should "have a valid root hash." in { val h1 = "41ef4bb0b23661e66301aac36066912dac037827b4ae63a7b1165a5aa93ed4eb" val h2 = "000031bee3fa033f2d69ae7d0d9f565bf3a235452ccf8a5edffb78cfbcdd7137" - val h12 = sha256Of(h1, h2) + val h12 = SHA256.hashAll(h1, h2) computeRootOfHashes(List(h1, h2)) shouldEqual h12 val h3 = "000031beekdjnvj2310i0i0c4i3jomo1m2km10ijodsjco1edffb78cfbcdd7137" - val h33 = sha256Of(h3, h3) - computeRootOfHashes(List(h1, h2, h3)) shouldEqual sha256Of(h12, h33) + val h33 = SHA256.hashAll(h3, h3) + computeRootOfHashes(List(h1, h2, h3)) shouldEqual SHA256.hashAll(h12, h33) val t1 = createCoinbaseTx(1, genesisMiner, genesisTimestamp) val t2 = createCoinbaseTx(2, genesisMiner, genesisTimestamp) - val th12 = sha256Of(t1.id, t2.id) + val th12 = SHA256.hashAll(t1.id, t2.id) computeRoot(List(t1, t2)) shouldEqual th12 val t3 = createCoinbaseTx(3, genesisMiner, genesisTimestamp) - val th33 = sha256Of(t3.id, t3.id) - computeRoot(List(t1, t2, t3)) shouldEqual sha256Of(th12, th33) + val th33 = SHA256.hashAll(t3.id, t3.id) + computeRoot(List(t1, t2, t3)) shouldEqual SHA256.hashAll(th12, th33) } }