Skip to content

Commit

Permalink
add MineAndAddNextBlock in BlockPool
Browse files Browse the repository at this point in the history
  • Loading branch information
fluency03 committed May 5, 2018
1 parent 772fddd commit 194a85c
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package com.github.fluency03.blockchain.api.actors

import akka.actor.{ActorSelection, Props}
import akka.actor.{ActorRef, ActorSelection, Props}
import akka.pattern.ask
import com.github.fluency03.blockchain.api.actors.BlockPoolActor._
import com.github.fluency03.blockchain.api._
import com.github.fluency03.blockchain.api.actors.BlockchainActor
import com.github.fluency03.blockchain.core.Block

import scala.collection.mutable
import scala.concurrent.Future
import scala.util.{Failure, Success}

object BlockPoolActor {
final case object GetBlocks
Expand All @@ -14,6 +18,7 @@ object BlockPoolActor {
final case class GetBlock(hash: String)
final case class DeleteBlock(hash: String)
final case class GetTxOfBlock(id: String, hash: String)
final case class MineAndAddNextBlock(data: String, ids: Seq[String])

def props: Props = Props[BlockPoolActor]
}
Expand All @@ -36,13 +41,13 @@ class BlockPoolActor extends ActorSupport {
case GetBlock(hash) => onGetBlock(hash)
case DeleteBlock(hash) => onDeleteBlock(hash)
case GetTxOfBlock(id, hash) => onGetTxOfBlock(id, hash)
case MineAndAddNextBlock(data, ids) => onMineAndAddNextBlock(data, ids)
case _ => unhandled _
}

/**
* TODO (Chang): new APIS:
* - CreateBlock
* - ContainsBlock
*
*/

Expand Down Expand Up @@ -77,4 +82,20 @@ class BlockPoolActor extends ActorSupport {
case None => sender() ! None
}

private def onMineAndAddNextBlock(data: String, ids: Seq[String]): Unit = {
val maybeBlock: Future[Option[Block]] =
(blockchainActor ? BlockchainActor.MineNextBlock(data, ids)).mapTo[Option[Block]]
val theSender: ActorRef = sender()
maybeBlock onComplete {
case Success(blockOpt) => blockOpt match {
case Some(block) =>
blocksPool += (block.hash -> block)
Some(block)
case None => theSender ! None
}
case Failure(_) => theSender ! None
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class BlockchainActor extends ActorSupport {
}

/**
* Handlers for each of the Messages.
* Handlers for each of the BlockchainMsg.
*/

private def onGetBlockchain(): Unit = sender() ! blockchainOpt
Expand All @@ -94,6 +94,20 @@ class BlockchainActor extends ActorSupport {
sender() ! SuccessMsg("Blockchain deleted.")
} else sender() ! FailureMsg("Blockchain does not exist.")

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("Blockchain does not exist.")
}

/**
* Handlers for each of the BlockMsg.
*/

private def onGetBlockFromChain(hash: String): Unit = sender() ! getBlockFromChain(hash)

private def onGetLastBlock(): Unit = blockchainOpt match {
Expand Down Expand Up @@ -171,16 +185,6 @@ class BlockchainActor extends ActorSupport {
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("Blockchain does not exist.")
}

private def onGetBlockFromPool(hash: String): Unit = blockPoolActor forward BlockPoolActor.GetBlock(hash)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package com.github.fluency03.blockchain.api.routes

import akka.actor.ActorRef
import akka.event.Logging
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Directives.{path, _}
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.directives.MethodDirectives.{delete, get, post}
import akka.http.scaladsl.server.directives.PathDirectives.path
import akka.http.scaladsl.server.directives.RouteDirectives.complete
import akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallers.CsvSeq
import akka.pattern.ask
import com.github.fluency03.blockchain.api.{Blocks, Message}
import com.github.fluency03.blockchain.api.{Blocks, Input, Message}
import com.github.fluency03.blockchain.api.actors.BlockPoolActor._
import com.github.fluency03.blockchain.api.actors.BlockchainActor.MineNextBlock
import com.github.fluency03.blockchain.core.{Block, Transaction}

import scala.concurrent.Future
Expand All @@ -23,45 +24,56 @@ trait BlockPoolRoutes extends RoutesSupport {
/**
* TODO (Chang): new APIS:
* - CreateBlock
* - GetTransactionOfABlock
* - ContainsBlock
*
*/

lazy val blockPoolRoutes: Route =
path(BLOCKS) {
parameters( 'hashes.as(CsvSeq[String]).? ) { hashesOpt: Option[Seq[String]] =>
val blocks: Future[Blocks] = hashesOpt match {
case Some(hashes) => (blockPoolActor ? GetBlocks(hashes.toSet)).mapTo[Blocks]
case None => (blockPoolActor ? GetBlocks).mapTo[Blocks]
path(BLOCK_POOL) {
path(BLOCKS) {
parameters('hashes.as(CsvSeq[String]).?) { hashesOpt: Option[Seq[String]] =>
val blocks: Future[Blocks] = hashesOpt match {
case Some(hashes) => (blockPoolActor ? GetBlocks(hashes.toSet)).mapTo[Blocks]
case None => (blockPoolActor ? GetBlocks).mapTo[Blocks]
}
complete(blocks)
}
complete(blocks)
}
} ~
pathPrefix(BLOCK) {
pathEnd {
} ~
path(NEXT_BLOCK) {
post {
entity(as[Block]) { block =>
val blockCreated: Future[Message] = (blockPoolActor ? AddBlock(block)).mapTo[Message]
onSuccess(blockCreated) { respondOnCreation }
parameters('id.as(CsvSeq[String]).?) { idsOpt: Option[Seq[String]] =>
entity(as[Input]) { in =>
val maybeNextBlock: Future[Option[Block]] =
(blockPoolActor ? MineAndAddNextBlock(in.content, idsOpt.getOrElse(Seq.empty[String]))).mapTo[Option[Block]]
rejectEmptyResponse { complete(maybeNextBlock) }
}
}
}
} ~
pathPrefix(Segment) { hash =>
pathPrefix(BLOCK) {
pathEnd {
get {
val maybeBlock: Future[Option[Block]] = (blockPoolActor ? GetBlock(hash)).mapTo[Option[Block]]
rejectEmptyResponse { complete(maybeBlock) }
} ~
delete {
val blockDeleted: Future[Message] = (blockPoolActor ? DeleteBlock(hash)).mapTo[Message]
onSuccess(blockDeleted) { respondOnDeletion }
post {
entity(as[Block]) { block =>
val blockCreated: Future[Message] = (blockPoolActor ? AddBlock(block)).mapTo[Message]
onSuccess(blockCreated) { respondOnCreation }
}
}
} ~
path(TRANSACTION / Segment) { id =>
get {
val maybeTx: Future[Option[Transaction]] = (blockPoolActor ? GetTxOfBlock(id, hash)).mapTo[Option[Transaction]]
rejectEmptyResponse { complete(maybeTx) }
pathPrefix(Segment) { hash =>
pathEnd {
get {
val maybeBlock: Future[Option[Block]] = (blockPoolActor ? GetBlock(hash)).mapTo[Option[Block]]
rejectEmptyResponse { complete(maybeBlock) }
} ~
delete {
val blockDeleted: Future[Message] = (blockPoolActor ? DeleteBlock(hash)).mapTo[Message]
onSuccess(blockDeleted) { respondOnDeletion }
}
} ~
path(TRANSACTION / Segment) { id =>
get {
val maybeTx: Future[Option[Transaction]] = (blockPoolActor ? GetTxOfBlock(id, hash)).mapTo[Option[Transaction]]
rejectEmptyResponse { complete(maybeTx) }
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.github.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}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,40 +28,42 @@ trait TxPoolRoutes extends RoutesSupport {
*/

lazy val txPoolRoutes: Route =
path(TRANSACTIONS) {
parameters( 'ids.as(CsvSeq[String]).? ) { idsOpt =>
val transactions: Future[Transactions] = idsOpt match {
case Some(ids) => (txPoolActor ? GetTransactions(ids)).mapTo[Transactions]
case None => (txPoolActor ? GetTransactions).mapTo[Transactions]
}
complete(transactions)
}
} ~
pathPrefix(TRANSACTION) {
pathEnd {
post {
entity(as[Transaction]) { tx =>
val msgOnCreate: Future[Message] = (txPoolActor ? AddTransaction(tx)).mapTo[Message]
onSuccess(msgOnCreate) { respondOnCreation }
path(TX_POOL) {
path(TRANSACTIONS) {
parameters('ids.as(CsvSeq[String]).?) { idsOpt =>
val transactions: Future[Transactions] = idsOpt match {
case Some(ids) => (txPoolActor ? GetTransactions(ids)).mapTo[Transactions]
case None => (txPoolActor ? GetTransactions).mapTo[Transactions]
}
complete(transactions)
}
} ~
path(Segment) { id =>
get {
val maybeTx: Future[Option[Transaction]] = (txPoolActor ? GetTransaction(id)).mapTo[Option[Transaction]]
rejectEmptyResponse { complete(maybeTx) }
} ~
delete {
val txDeleted: Future[Message] = (txPoolActor ? DeleteTransaction(id)).mapTo[Message]
onSuccess(txDeleted) { respondOnDeletion }
pathPrefix(TRANSACTION) {
pathEnd {
post {
entity(as[Transaction]) { tx =>
val msgOnCreate: Future[Message] = (txPoolActor ? AddTransaction(tx)).mapTo[Message]
onSuccess(msgOnCreate) { respondOnCreation }
}
}
} ~
put {
entity(as[Transaction]) { tx =>
if (tx.id != id)
complete((StatusCodes.InternalServerError, FailureMsg("Transaction ID in the data does not match ID on the path.")))
else {
val msgOnUpdate: Future[Message] = (txPoolActor ? UpdateTransaction(tx)).mapTo[Message]
onSuccess(msgOnUpdate) { respondOnUpdate }
path(Segment) { id =>
get {
val maybeTx: Future[Option[Transaction]] = (txPoolActor ? GetTransaction(id)).mapTo[Option[Transaction]]
rejectEmptyResponse { complete(maybeTx) }
} ~
delete {
val txDeleted: Future[Message] = (txPoolActor ? DeleteTransaction(id)).mapTo[Message]
onSuccess(txDeleted) { respondOnDeletion }
} ~
put {
entity(as[Transaction]) { tx =>
if (tx.id != id)
complete((StatusCodes.InternalServerError, FailureMsg("Transaction ID in the data does not match ID on the path.")))
else {
val msgOnUpdate: Future[Message] = (txPoolActor ? UpdateTransaction(tx)).mapTo[Message]
onSuccess(msgOnUpdate) { respondOnUpdate }
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ package object routes {
val NEW_BLOCK = "new-block"
val NEXT_BLOCK = "next-block"

// block
// block-pool
val BLOCK_POOL = "block-pool"
val BLOCKS = "blocks"
val BLOCK = "block"

Expand All @@ -29,7 +30,8 @@ package object routes {
val PEERS = "peers"
val PEER = "peer"

// transaction
// tx-pool
val TX_POOL = "tx-pool"
val TRANSACTIONS = "transactions"
val TRANSACTION = "transaction"

Expand Down

0 comments on commit 194a85c

Please sign in to comment.