diff --git a/src/main/scala/com/fluency03/blockchain/api/actors/BlockchainActor.scala b/src/main/scala/com/fluency03/blockchain/api/actors/BlockchainActor.scala index 08c77f9..4a6c11f 100644 --- a/src/main/scala/com/fluency03/blockchain/api/actors/BlockchainActor.scala +++ b/src/main/scala/com/fluency03/blockchain/api/actors/BlockchainActor.scala @@ -48,14 +48,14 @@ class BlockchainActor extends ActorSupport { /** * TODO (Chang): new APIS: - * - MineNextBlock - * + * - AddBlock with Block obtained from pool based on hash + * - MineNextBlock with Transactions */ private def onGetBlockchain(): Unit = sender() ! blockchainOpt private def onCreateBlockchain(): Unit = - if (blockchainOpt.isDefined) sender() ! FailureMsg(s"Blockchain already exists.") + if (blockchainOpt.isDefined) sender() ! FailureMsg("Blockchain already exists.") else { blockchainOpt = Some(Blockchain()) if (hashIndexMapping.nonEmpty) { @@ -70,8 +70,8 @@ class BlockchainActor extends ActorSupport { if (blockchainOpt.isDefined) { blockchainOpt = None hashIndexMapping.clear() - sender() ! SuccessMsg(s"Blockchain deleted.") - } else sender() ! FailureMsg(s"Blockchain does not exist.") + sender() ! SuccessMsg("Blockchain deleted.") + } else sender() ! FailureMsg("Blockchain does not exist.") private def onGetBlock(hash: String): Unit = sender() ! getBlock(hash) @@ -86,11 +86,11 @@ class BlockchainActor extends ActorSupport { case Some(blockchain) => blockchainOpt = Some(blockchain.addBlock(block)) hashIndexMapping += (block.hash -> blockchain.length) - sender() ! SuccessMsg(s"New Block added on the chain.") + sender() ! SuccessMsg(s"New Block ${block.hash} added on the chain.") case None => log.error("Blockchain does not exist! Clear the hash-to-index mapping!") hashIndexMapping.clear() - sender() ! FailureMsg(s"Blockchain does not exist.") + sender() ! FailureMsg("Blockchain does not exist.") } private def onRemoveBlock(): Unit = blockchainOpt match { @@ -98,11 +98,11 @@ class BlockchainActor extends ActorSupport { val toBeRemoved = blockchain.chain.head blockchainOpt = Some(blockchain.removeBlock()) hashIndexMapping -= toBeRemoved.hash - sender() ! SuccessMsg(s"Last Block removed from the chain.") + sender() ! SuccessMsg(s"Last Block ${toBeRemoved.hash} removed from the chain.") case None => log.error("Blockchain does not exist! Clear the hash-to-index mapping!") hashIndexMapping.clear() - sender() ! FailureMsg(s"Blockchain does not exist.") + sender() ! FailureMsg("Blockchain does not exist.") } private def onMineNextBlock(data: String, trans: Seq[Transaction]): Unit = blockchainOpt match { @@ -120,7 +120,7 @@ class BlockchainActor extends ActorSupport { case None => log.error("Blockchain does not exist! Clear the hash-to-index mapping!") hashIndexMapping.clear() - sender() ! FailureMsg(s"Blockchain does not exist.") + sender() ! FailureMsg("Blockchain does not exist.") } 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 aff40cc..02d2ab1 100644 --- a/src/main/scala/com/fluency03/blockchain/api/routes/BlockchainRoutes.scala +++ b/src/main/scala/com/fluency03/blockchain/api/routes/BlockchainRoutes.scala @@ -21,8 +21,8 @@ trait BlockchainRoutes extends RoutesSupport { /** * TODO (Chang): new APIS: - * - MineNextBlock - * + * - AddBlock with Block obtained from pool based on hash + * - MineNextBlock with Transactions */ lazy val blockchainRoutes: Route = diff --git a/src/main/scala/com/fluency03/blockchain/core/Blockchain.scala b/src/main/scala/com/fluency03/blockchain/core/Blockchain.scala index 2b4e0ee..6c88ee6 100644 --- a/src/main/scala/com/fluency03/blockchain/core/Blockchain.scala +++ b/src/main/scala/com/fluency03/blockchain/core/Blockchain.scala @@ -50,6 +50,7 @@ object Blockchain { def apply(difficulty: Int): Blockchain = new Blockchain(difficulty, Seq(Block.genesis(difficulty))) + // TODO (Chang): return both the validity and highest valid Block index @tailrec def isValidChain(chain: Seq[Block]): Boolean = chain match { case Nil => true diff --git a/src/test/scala/com/fluency03/blockchain/api/actors/BlockchainActorTest.scala b/src/test/scala/com/fluency03/blockchain/api/actors/BlockchainActorTest.scala index 7c2c2ce..a29bb38 100644 --- a/src/test/scala/com/fluency03/blockchain/api/actors/BlockchainActorTest.scala +++ b/src/test/scala/com/fluency03/blockchain/api/actors/BlockchainActorTest.scala @@ -4,7 +4,7 @@ import akka.actor.{ActorRef, ActorSystem, Props} import akka.testkit.{DefaultTimeout, ImplicitSender, TestKit} import com.fluency03.blockchain.api.actors.BlockchainActor._ import com.fluency03.blockchain.api.{FailureMsg, SuccessMsg} -import com.fluency03.blockchain.core.{Block, Blockchain} +import com.fluency03.blockchain.core.{Block, Blockchain, Transaction} import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike} import scala.concurrent.duration._ @@ -52,11 +52,47 @@ class BlockchainActorTest extends TestKit(ActorSystem("BlockchainActorTest")) wi blockchainActor ! GetTxOfBlock(genesis.transactions.head.id, "bb") expectMsg(None) + blockchainActor ! CheckBlockchainValidity + expectMsg(SuccessMsg("true")) + + blockchainActor ! AddBlock(genesis) + expectMsg(SuccessMsg(s"New Block ${genesis.hash} added on the chain.")) + + blockchainActor ! CheckBlockchainValidity + expectMsg(SuccessMsg("false")) + + blockchainActor ! RemoveBlock + expectMsg(SuccessMsg(s"Last Block ${genesis.hash} removed from the chain.")) + + blockchainActor ! CheckBlockchainValidity + expectMsg(SuccessMsg("true")) + + blockchainActor ! MineNextBlock("next", Seq.empty[Transaction]) + val actualBlock = expectMsgType[Some[Block]].get + actualBlock.data shouldEqual "next" + actualBlock.transactions shouldEqual Seq.empty[Transaction] + actualBlock.difficulty shouldEqual blockchain.difficulty + actualBlock.index shouldEqual 1 + actualBlock.hasValidHash shouldEqual true + actualBlock.previousHash shouldEqual genesis.hash + blockchainActor ! DeleteBlockchain - expectMsg(SuccessMsg(s"Blockchain deleted.")) + expectMsg(SuccessMsg("Blockchain deleted.")) blockchainActor ! DeleteBlockchain - expectMsg(FailureMsg(s"Blockchain does not exist.")) + expectMsg(FailureMsg("Blockchain does not exist.")) + + blockchainActor ! AddBlock(genesis) + expectMsg(FailureMsg("Blockchain does not exist.")) + + blockchainActor ! RemoveBlock + expectMsg(FailureMsg("Blockchain does not exist.")) + + blockchainActor ! CheckBlockchainValidity + expectMsg(FailureMsg("Blockchain does not exist.")) + + blockchainActor ! MineNextBlock("next", Seq.empty[Transaction]) + expectMsg(None) blockchainActor ! "other" expectNoMessage