Skip to content

Commit

Permalink
add apis: AddBlock, RemoveBlock, MineNextBlock, CheckBlockchainValidity
Browse files Browse the repository at this point in the history
  • Loading branch information
fluency03 committed May 1, 2018
1 parent f4cdf68 commit 99d374f
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 21 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ com.fluency03.blockchain.api.Server
#### Todos

- Complete APIs' Todos
- API tests
- Make states in actor persistent (using Akka Persistent)
- Concurrent collections?
- Make data distributed within cluster of peer (using Akka Cluster)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.fluency03.blockchain.api.actors
import akka.actor.{ActorSelection, Props}
import com.fluency03.blockchain.api.actors.BlockchainActor._
import com.fluency03.blockchain.api._
import com.fluency03.blockchain.core.{Block, Blockchain}
import com.fluency03.blockchain.core.{Block, Blockchain, Transaction}

import scala.collection.mutable

Expand All @@ -13,6 +13,10 @@ object BlockchainActor {
final case object DeleteBlockchain
final case class GetBlock(hash: String)
final case class GetTxOfBlock(id: String, hash: String)
final case class AddBlock(block: Block)
final case object RemoveBlock
final case class MineNextBlock(data: String, trans: Seq[Transaction])
final case object CheckBlockchainValidity

def props: Props = Props[BlockchainActor]
}
Expand All @@ -35,13 +39,15 @@ class BlockchainActor extends ActorSupport {
case DeleteBlockchain => onDeleteBlockchain()
case GetBlock(hash) => onGetBlock(hash)
case GetTxOfBlock(id, hash) => onGetTxOfBlock(id, hash)
case AddBlock(block) => onAddBlock(block)
case RemoveBlock => onRemoveBlock()
case MineNextBlock(data, trans) => onMineNextBlock(data, trans)
case CheckBlockchainValidity => onCheckBlockchainValidity()
case _ => unhandled _
}

/**
* TODO (Chang): new APIS:
* - AddBlockOnBlockchain
* - CheckBlockchainIsValid
* - MineNextBlock
*
*/
Expand Down Expand Up @@ -76,20 +82,57 @@ class BlockchainActor extends ActorSupport {
}
}

private def getBlock(hash: String): Option[Block] = {
hashIndexMapping.get(hash) match {
case Some(index) => blockchainOpt match {
case Some(blockchain) => Some(blockchain.chain(index))
case None =>
log.error("Blockchain does not exist! Clear the hash-to-index mapping!")
hashIndexMapping.clear()
None
}
case None => None
}
private def onAddBlock(block: Block): Unit = blockchainOpt match {
case Some(blockchain) =>
blockchainOpt = Some(blockchain.addBlock(block))
hashIndexMapping += (block.hash -> blockchain.length)
sender() ! SuccessMsg(s"New Block 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.")
}

private def onRemoveBlock(): Unit = blockchainOpt match {
case Some(blockchain) =>
val toBeRemoved = blockchain.chain.head
blockchainOpt = Some(blockchain.removeBlock())
hashIndexMapping -= toBeRemoved.hash
sender() ! SuccessMsg(s"Last Block 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.")
}

private def onMineNextBlock(data: String, trans: Seq[Transaction]): Unit = blockchainOpt match {
case Some(blockchain) => sender() ! Some(blockchain.mineNextBlock(data, trans))
case None =>
log.error("Blockchain does not exist! Clear the hash-to-index mapping!")
hashIndexMapping.clear()
sender() ! None
}

private def onCheckBlockchainValidity(): Unit = blockchainOpt match {
case Some(blockchain) =>
if (blockchain.isValid) sender() ! SuccessMsg("true")
else sender() ! SuccessMsg("false")
case None =>
log.error("Blockchain does not exist! Clear the hash-to-index mapping!")
hashIndexMapping.clear()
sender() ! FailureMsg(s"Blockchain does not exist.")
}


private def getBlock(hash: String): Option[Block] = hashIndexMapping.get(hash) match {
case Some(index) => blockchainOpt match {
case Some(blockchain) => Some(blockchain.chain(index))
case None =>
log.error("Blockchain does not exist! Clear the hash-to-index mapping!")
hashIndexMapping.clear()
None
}
case None => None
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class BlocksActor extends ActorSupport {
* - CreateBlock
* - GetBlock (onChain or offChain)
* - GetTransactionOfABlock
* - ContainsBlock
* - AddBlockOnChain
*
*/
Expand Down Expand Up @@ -69,5 +70,4 @@ class BlocksActor extends ActorSupport {
} else sender() ! FailureMsg(s"Block $hash does not exist.")
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ trait BlockRoutes extends RoutesSupport {
* - CreateBlock
* - GetBlock (onChain or offChain)
* - GetTransactionOfABlock
* - ContainsBlock
* - AddBlockOnChain
*
*/
Expand Down Expand Up @@ -58,4 +59,5 @@ trait BlockRoutes extends RoutesSupport {
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package com.fluency03.blockchain.api.routes

import akka.actor.ActorRef
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.{delete, get, post}
import akka.http.scaladsl.server.directives.RouteDirectives.complete
import akka.pattern.ask
import com.fluency03.blockchain.api.Message
import com.fluency03.blockchain.api.{FailureMsg, Input, Message}
import com.fluency03.blockchain.api.actors.BlockchainActor._
import com.fluency03.blockchain.core.{Block, Blockchain, Transaction}

Expand All @@ -20,14 +21,18 @@ trait BlockchainRoutes extends RoutesSupport {

/**
* TODO (Chang): new APIS:
* - AddBlockOnBlockchain
* - CheckBlockchainIsValid
* - MineNextBlock
*
*/

lazy val blockchainRoutes: Route =
pathPrefix(BLOCKCHAIN) {
path(VALIDITY) {
get {
val validity: Future[Message] = (blockchainActor ? CheckBlockchainValidity).mapTo[Message]
onSuccess(validity) { respondOnUpdate }
}
} ~
pathEnd {
get {
val blockchain: Future[Option[Blockchain]] = (blockchainActor ? GetBlockchain).mapTo[Option[Blockchain]]
Expand All @@ -37,6 +42,25 @@ trait BlockchainRoutes extends RoutesSupport {
val blockchainCreated: Future[Message] = (blockchainActor ? CreateBlockchain).mapTo[Message]
onSuccess(blockchainCreated) { respondOnCreation }
} ~
put {
parameters('action) {
case ADD_BLOCK_ACTION =>
entity(as[Block]) { block =>
val blockchainUpdated: Future[Message] = (blockchainActor ? AddBlock(block)).mapTo[Message]
onSuccess(blockchainUpdated) { respondOnUpdate }
}
case REMOVE_BLOCK_ACTION =>
val blockchainUpdated: Future[Message] = (blockchainActor ? RemoveBlock).mapTo[Message]
onSuccess(blockchainUpdated) { respondOnUpdate }
case MINE_NEXT_BLOCK_ACTION =>
entity(as[Input]) { in =>
val maybeNextBlock: Future[Option[Block]] =
(blockchainActor ? MineNextBlock(in.content, Seq.empty[Transaction])).mapTo[Option[Block]]
rejectEmptyResponse { complete(maybeNextBlock) }
}
case act => complete((StatusCodes.BadRequest, FailureMsg(s"Action Not Supported: $act")))
}
} ~
delete {
val blockchainDeleted: Future[Message] = (blockchainActor ? DeleteBlockchain).mapTo[Message]
onSuccess(blockchainDeleted) { respondOnDeletion }
Expand All @@ -46,9 +70,7 @@ trait BlockchainRoutes extends RoutesSupport {
pathEnd {
get {
val maybeBlock: Future[Option[Block]] = (blockchainActor ? GetBlock(hash)).mapTo[Option[Block]]
rejectEmptyResponse {
complete(maybeBlock)
}
rejectEmptyResponse { complete(maybeBlock) }
}
} ~
path(TRANSACTION / Segment) { id =>
Expand All @@ -60,4 +82,5 @@ trait BlockchainRoutes extends RoutesSupport {
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ package object routes {

// blockchain
val BLOCKCHAIN = "blockchain"
val VALIDITY = "validity"
val ADD_BLOCK_ACTION = "addBlock"
val REMOVE_BLOCK_ACTION = "removeBlock"
val MINE_NEXT_BLOCK_ACTION = "mineNextBlock"

// block
val BLOCKS = "blocks"
Expand Down

0 comments on commit 99d374f

Please sign in to comment.