diff --git a/src/main/scala/com/fluency03/blockchain/Util.scala b/src/main/scala/com/fluency03/blockchain/Util.scala deleted file mode 100644 index 8eb9b2a..0000000 --- a/src/main/scala/com/fluency03/blockchain/Util.scala +++ /dev/null @@ -1,84 +0,0 @@ -package com.fluency03.blockchain - -import java.security.MessageDigest -import java.time.Instant - -import akka.http.scaladsl.model.{StatusCode, StatusCodes} -import com.fluency03.blockchain.api.{FailureMsg, Message, SuccessMsg} -import org.bouncycastle.util.encoders.Base64 - -object Util { - - /** - * 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")) - - /** - * Return the current timestamp in Unix Epoch Time. - */ - def getCurrentTimestamp: Long = Instant.now.getEpochSecond - - /** - * Parse a time format string to its Epoch time in seconds. - */ - def epochTimeOf(t: String): Long = Instant.parse(t).getEpochSecond - - /** - * Calculate the hash of concatenation a Seq of Strings. - */ - def sha256Of(strings: String*): String = sha256HashOf(strings mkString "") - - /** - * Get binary representation of a hash. - */ - def binaryOfHex(hash: String): String = BigInt(hash, 16).toString(2) - - /** - * Check whether the given hash is with valid difficulty. - */ - def isWithValidDifficulty(hash: String, difficulty: Int): Boolean = hash startsWith ("0" * difficulty) - - /** - * Encode a String to Base64. - */ - def base64Of(text: String): String = Base64.toBase64String(text.getBytes("UTF-8")) - - /** - * Encode an Array of Bytes String to Base64. - */ - def base64Of(data: Bytes): String = Base64.toBase64String(data) - - /** - * Decode a Base64 to String. - */ - def fromBase64(base64: String): String = new String(Base64.decode(base64), "UTF-8") - - /** - * Return either SuccessMsg (if fun successfully returned a String) or FailureMsg (if fun failed). - */ - def failsafeMsg(fun: => String): Message = - try { SuccessMsg(fun) } - catch { - case e: Exception => FailureMsg(e.getMessage) - } - - /** - * Return either SuccessMsg (if fun successfully returned a String) or FailureMsg (if fun failed). - */ - def failsafeResp(fun: => String): (StatusCode, Message) = - try { (StatusCodes.OK, SuccessMsg(fun)) } - catch { - case e: Exception => (StatusCodes.InternalServerError, FailureMsg(e.getMessage)) - } - -} diff --git a/src/main/scala/com/fluency03/blockchain/api/package.scala b/src/main/scala/com/fluency03/blockchain/api/package.scala index 6fdf96d..61857c2 100644 --- a/src/main/scala/com/fluency03/blockchain/api/package.scala +++ b/src/main/scala/com/fluency03/blockchain/api/package.scala @@ -1,5 +1,6 @@ package com.fluency03.blockchain +import akka.http.scaladsl.model.{StatusCode, StatusCodes} import com.fluency03.blockchain.core.{Block, Peer, Transaction} package object api { @@ -17,6 +18,4 @@ package object api { val PARENT_UP = "../" - - } diff --git a/src/main/scala/com/fluency03/blockchain/api/routes/BlockRoutes.scala b/src/main/scala/com/fluency03/blockchain/api/routes/BlockRoutes.scala index f504c22..214ffef 100644 --- a/src/main/scala/com/fluency03/blockchain/api/routes/BlockRoutes.scala +++ b/src/main/scala/com/fluency03/blockchain/api/routes/BlockRoutes.scala @@ -21,13 +21,13 @@ trait BlockRoutes extends RoutesSupport { def blocksActor: ActorRef lazy val blockRoutes: Route = - path("blocks") { + path(BLOCKS) { get { val blocks: Future[Blocks] = (blocksActor ? GetBlocks).mapTo[Blocks] complete(blocks) } } ~ - pathPrefix("block") { + pathPrefix(BLOCK) { pathEnd { post { entity(as[Block]) { block => diff --git a/src/main/scala/com/fluency03/blockchain/api/routes/BlockchainRoutes.scala b/src/main/scala/com/fluency03/blockchain/api/routes/BlockchainRoutes.scala index 753f7a6..1e03b8f 100644 --- a/src/main/scala/com/fluency03/blockchain/api/routes/BlockchainRoutes.scala +++ b/src/main/scala/com/fluency03/blockchain/api/routes/BlockchainRoutes.scala @@ -21,7 +21,7 @@ trait BlockchainRoutes extends RoutesSupport { def blockchainActor: ActorRef lazy val blockchainRoutes: Route = - pathPrefix("blockchain") { + pathPrefix(BLOCKCHAIN) { pathEnd { get { val blockchain: Future[Option[Blockchain]] = (blockchainActor ? GetBlockchain).mapTo[Option[Blockchain]] diff --git a/src/main/scala/com/fluency03/blockchain/api/routes/GenericRoutes.scala b/src/main/scala/com/fluency03/blockchain/api/routes/GenericRoutes.scala index 5001766..46cc9b3 100644 --- a/src/main/scala/com/fluency03/blockchain/api/routes/GenericRoutes.scala +++ b/src/main/scala/com/fluency03/blockchain/api/routes/GenericRoutes.scala @@ -4,13 +4,11 @@ package api.routes import java.time.Instant import akka.event.Logging -import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import akka.http.scaladsl.server.directives.MethodDirectives.post import akka.http.scaladsl.server.directives.RouteDirectives.complete -import com.fluency03.blockchain.Util._ -import com.fluency03.blockchain.api.{FailureMsg, Input, SuccessMsg} +import com.fluency03.blockchain.api.{Input, SuccessMsg} trait GenericRoutes extends RoutesSupport { lazy val log = Logging(system, classOf[GenericRoutes]) diff --git a/src/main/scala/com/fluency03/blockchain/api/routes/NetworkRoutes.scala b/src/main/scala/com/fluency03/blockchain/api/routes/NetworkRoutes.scala index e885914..70c4267 100644 --- a/src/main/scala/com/fluency03/blockchain/api/routes/NetworkRoutes.scala +++ b/src/main/scala/com/fluency03/blockchain/api/routes/NetworkRoutes.scala @@ -21,13 +21,13 @@ trait NetworkRoutes extends RoutesSupport { def networkActor: ActorRef lazy val networkRoutes: Route = - path("peers") { + path(PEERS) { get { val peers: Future[Set[String]] = (networkActor ? GetPeers).mapTo[Set[String]] complete(peers) } } ~ - pathPrefix("peer") { + pathPrefix(PEER) { pathEnd { post { entity(as[PeerSimple]) { peer => diff --git a/src/main/scala/com/fluency03/blockchain/api/routes/TransactionRoutes.scala b/src/main/scala/com/fluency03/blockchain/api/routes/TransactionRoutes.scala index 64e8553..17055b6 100644 --- a/src/main/scala/com/fluency03/blockchain/api/routes/TransactionRoutes.scala +++ b/src/main/scala/com/fluency03/blockchain/api/routes/TransactionRoutes.scala @@ -21,13 +21,13 @@ trait TransactionRoutes extends RoutesSupport { def transActor: ActorRef lazy val transRoutes: Route = - path("transactions") { + path(TRANSACTIONS) { get { val transactions: Future[Transactions] = (transActor ? GetTransactions).mapTo[Transactions] complete(transactions) } } ~ - pathPrefix("transaction") { + pathPrefix(TRANSACTION) { pathEnd { post { entity(as[Transaction]) { tx => diff --git a/src/main/scala/com/fluency03/blockchain/api/routes/package.scala b/src/main/scala/com/fluency03/blockchain/api/routes/package.scala index 18ac220..4bdc032 100644 --- a/src/main/scala/com/fluency03/blockchain/api/routes/package.scala +++ b/src/main/scala/com/fluency03/blockchain/api/routes/package.scala @@ -1,5 +1,7 @@ package com.fluency03.blockchain.api +import akka.http.scaladsl.model.{StatusCode, StatusCodes} + package object routes { // generics @@ -11,6 +13,47 @@ package object routes { val TO_EPOCH_TIME = "to-epoch-time" val TIME_FROM_EPOCH = "time-from-epoch" + // blockchain + val BLOCKCHAIN = "blockchain" + + // block + val BLOCKS = "blocks" + val BLOCK = "block" + + // network + val PEERS = "peers" + val PEER = "peer" + + // transaction + val TRANSACTIONS = "transactions" + val TRANSACTION = "transaction" + + /** + * Concatenate a seq of String segments into full API path + */ def pathOf(seg: String*): String = SLASH + seg.mkString(SLASH) + /** + * Return either SuccessMsg (if fun successfully returned a String) or FailureMsg (if fun failed). + */ + def failsafeMsg(fun: => String): Message = + try { SuccessMsg(fun) } + catch { + case e: Exception => FailureMsg(e.getMessage) + } + + /** + * Return either SuccessMsg (if fun successfully returned a String) or FailureMsg (if fun failed). + */ + def failsafeResp(fun: => String): (StatusCode, Message) = + try { (StatusCodes.OK, SuccessMsg(fun)) } + catch { + case e: Exception => (StatusCodes.InternalServerError, FailureMsg(e.getMessage)) + } + + + + + + } diff --git a/src/main/scala/com/fluency03/blockchain/core/Block.scala b/src/main/scala/com/fluency03/blockchain/core/Block.scala index 4907884..de84707 100644 --- a/src/main/scala/com/fluency03/blockchain/core/Block.scala +++ b/src/main/scala/com/fluency03/blockchain/core/Block.scala @@ -1,7 +1,6 @@ package com.fluency03.blockchain package core -import com.fluency03.blockchain.Util.isWithValidDifficulty import com.fluency03.blockchain.core.BlockHeader.hashOfHeaderFields import com.fluency03.blockchain.core.Transaction.createCoinbaseTx import org.json4s.JsonAST.JObject diff --git a/src/main/scala/com/fluency03/blockchain/core/BlockHeader.scala b/src/main/scala/com/fluency03/blockchain/core/BlockHeader.scala index fb412b4..24135fa 100644 --- a/src/main/scala/com/fluency03/blockchain/core/BlockHeader.scala +++ b/src/main/scala/com/fluency03/blockchain/core/BlockHeader.scala @@ -2,7 +2,6 @@ package com.fluency03.blockchain package core import com.fluency03.blockchain.core.BlockHeader.hashOfBlockHeader -import com.fluency03.blockchain.Util.sha256Of import org.json4s.native.JsonMethods.{compact, render} import org.json4s.{Extraction, JValue} diff --git a/src/main/scala/com/fluency03/blockchain/core/Blockchain.scala b/src/main/scala/com/fluency03/blockchain/core/Blockchain.scala index 8330244..4ee74f5 100644 --- a/src/main/scala/com/fluency03/blockchain/core/Blockchain.scala +++ b/src/main/scala/com/fluency03/blockchain/core/Blockchain.scala @@ -1,12 +1,9 @@ package com.fluency03.blockchain package core -import com.fluency03.blockchain.Util.getCurrentTimestamp import com.fluency03.blockchain.core.Blockchain._ import com.fluency03.blockchain.core.Block.canBeChained -import scala.collection.mutable - /** * Blockchain with difficulty and the chain of Blocks. * @param difficulty Difficulty of a Blockchain diff --git a/src/main/scala/com/fluency03/blockchain/core/Merkle.scala b/src/main/scala/com/fluency03/blockchain/core/Merkle.scala index 3fa4d6a..be39da6 100644 --- a/src/main/scala/com/fluency03/blockchain/core/Merkle.scala +++ b/src/main/scala/com/fluency03/blockchain/core/Merkle.scala @@ -1,8 +1,6 @@ package com.fluency03.blockchain package core -import com.fluency03.blockchain.Util.sha256Of - object Merkle { def computeRoot(trans: Seq[Transaction]): String = computeRootOfHashes(trans.map(_.id)) diff --git a/src/main/scala/com/fluency03/blockchain/core/Transaction.scala b/src/main/scala/com/fluency03/blockchain/core/Transaction.scala index ac4fe2c..59e6e82 100644 --- a/src/main/scala/com/fluency03/blockchain/core/Transaction.scala +++ b/src/main/scala/com/fluency03/blockchain/core/Transaction.scala @@ -4,7 +4,6 @@ package core import java.security.KeyPair import com.fluency03.blockchain.Crypto -import com.fluency03.blockchain.Util.sha256Of import com.fluency03.blockchain.core.Transaction.hashOfTransaction import org.bouncycastle.util.encoders.Hex import org.json4s.JsonAST.JObject diff --git a/src/main/scala/com/fluency03/blockchain/package.scala b/src/main/scala/com/fluency03/blockchain/package.scala index 9cb55ce..5b77def 100644 --- a/src/main/scala/com/fluency03/blockchain/package.scala +++ b/src/main/scala/com/fluency03/blockchain/package.scala @@ -1,9 +1,9 @@ package com.fluency03 import java.nio.charset.Charset +import java.security.MessageDigest import java.time.Instant -import com.fluency03.blockchain.Util.{sha256HashOf, base64Of, binaryOfHex} import org.bouncycastle.util.encoders.{Base64, Hex} import org.json4s.{Formats, NoTypeHints} import org.json4s.native.Serialization @@ -41,4 +41,61 @@ package object blockchain { def toBase64: String = base64Of(bytes) } + + /** + * 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. + */ + def getCurrentTimestamp: Long = Instant.now.getEpochSecond + + /** + * Parse a time format string to its Epoch time in seconds. + */ + def epochTimeOf(t: String): Long = Instant.parse(t).getEpochSecond + + /** + * Get binary representation of a hash. + */ + def binaryOfHex(hash: String): String = BigInt(hash, 16).toString(2) + + /** + * Check whether the given hash is with valid difficulty. + */ + def isWithValidDifficulty(hash: String, difficulty: Int): Boolean = hash startsWith ("0" * difficulty) + + /** + * Encode a String to Base64. + */ + def base64Of(text: String): String = Base64.toBase64String(text.getBytes("UTF-8")) + + /** + * Encode an Array of Bytes String to Base64. + */ + def base64Of(data: Bytes): String = Base64.toBase64String(data) + + /** + * Decode a Base64 to String. + */ + def fromBase64(base64: String): String = new String(Base64.decode(base64), "UTF-8") + + + } diff --git a/src/test/scala/com/fluency03/blockchain/UtilTest.scala b/src/test/scala/com/fluency03/blockchain/UtilTest.scala index 4468ea5..3224542 100644 --- a/src/test/scala/com/fluency03/blockchain/UtilTest.scala +++ b/src/test/scala/com/fluency03/blockchain/UtilTest.scala @@ -2,7 +2,6 @@ package com.fluency03.blockchain import java.time.format.DateTimeParseException -import com.fluency03.blockchain.Util._ import org.scalamock.scalatest.MockFactory import org.scalatest.{FlatSpec, Matchers} diff --git a/src/test/scala/com/fluency03/blockchain/core/MerkleTest.scala b/src/test/scala/com/fluency03/blockchain/core/MerkleTest.scala index 0cf2a8c..7a5c20a 100644 --- a/src/test/scala/com/fluency03/blockchain/core/MerkleTest.scala +++ b/src/test/scala/com/fluency03/blockchain/core/MerkleTest.scala @@ -1,7 +1,6 @@ package com.fluency03.blockchain package core -import com.fluency03.blockchain.Util.sha256Of import com.fluency03.blockchain.core.Merkle._ import com.fluency03.blockchain.core.Transaction.createCoinbaseTx import org.scalatest.{FlatSpec, Matchers}