From 12f47c5b6ab97717d6f38f7becd001c0b19fb0c0 Mon Sep 17 00:00:00 2001 From: fluency03 Date: Sun, 29 Apr 2018 15:49:37 +0200 Subject: [PATCH] add GetTransactions based on ids --- .../api/actors/BlockchainActor.scala | 5 ++++- .../api/actors/TransactionsActor.scala | 17 ++++++++++------- .../blockchain/api/routes/BlockRoutes.scala | 3 +-- .../blockchain/api/routes/NetworkRoutes.scala | 18 ++++++------------ .../api/routes/TransactionRoutes.scala | 10 ++++++---- .../api/actors/TransactionsActorTest.scala | 9 +++++++++ .../api/routes/BlockRoutesTest.scala | 3 ++- .../api/routes/BlockchainRoutesTest.scala | 3 ++- .../api/routes/NetworkRoutesTest.scala | 3 ++- .../api/routes/TransactionRoutesTest.scala | 3 ++- 10 files changed, 44 insertions(+), 30 deletions(-) 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 e0620df..99de84c 100644 --- a/src/main/scala/com/fluency03/blockchain/api/actors/BlockchainActor.scala +++ b/src/main/scala/com/fluency03/blockchain/api/actors/BlockchainActor.scala @@ -3,7 +3,9 @@ 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.Blockchain +import com.fluency03.blockchain.core.{Block, Blockchain} + +import scala.collection.mutable object BlockchainActor { final case object GetBlockchain @@ -23,6 +25,7 @@ class BlockchainActor extends ActorSupport { // TODO (Chang): need persistence var blockchainOpt: Option[Blockchain] = None + var hashIndexMapping = mutable.Map.empty[String, Int] def receive: Receive = { case GetBlockchain => onGetBlockchain() diff --git a/src/main/scala/com/fluency03/blockchain/api/actors/TransactionsActor.scala b/src/main/scala/com/fluency03/blockchain/api/actors/TransactionsActor.scala index d6e273d..b644aa8 100644 --- a/src/main/scala/com/fluency03/blockchain/api/actors/TransactionsActor.scala +++ b/src/main/scala/com/fluency03/blockchain/api/actors/TransactionsActor.scala @@ -9,9 +9,10 @@ import scala.collection.mutable object TransactionsActor { final case object GetTransactions + final case class GetTransactions(ids: Set[String]) final case class CreateTransaction(tx: Transaction) - final case class GetTransaction(hash: String) - final case class DeleteTransaction(hash: String) + final case class GetTransaction(id: String) + final case class DeleteTransaction(id: String) def props: Props = Props[TransactionsActor] } @@ -30,14 +31,19 @@ class TransactionsActor extends ActorSupport { def receive: Receive = { case GetTransactions => onGetTransactions() + case GetTransactions(ids) => onGetTransactions(ids) case CreateTransaction(tx) => onCreateTransaction(tx) - case GetTransaction(hash) => onGetTransaction(hash) - case DeleteTransaction(hash) => onDeleteTransaction(hash) + case GetTransaction(id) => onGetTransaction(id) + case DeleteTransaction(id) => onDeleteTransaction(id) case _ => unhandled _ } private def onGetTransactions(): Unit = sender() ! currentTransactions.values.toSeq + private def onGetTransactions(ids: Set[String]): Unit = sender() ! currentTransactions.filterKeys( + k => ids.contains(k) + ).values.toSeq + private def onCreateTransaction(tx: Transaction): Unit = { if (currentTransactions.contains(tx.id)) sender() ! FailureMsg(s"Transaction ${tx.id} already exists.") else { @@ -54,7 +60,4 @@ class TransactionsActor extends ActorSupport { sender() ! SuccessMsg(s"Transaction $id deleted.") } else sender() ! FailureMsg(s"Transaction $id does not exist.") - // TODO (Chang): APIs for selecting transactions based on Seq of ids - - } 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 53e1c24..6e36ac1 100644 --- a/src/main/scala/com/fluency03/blockchain/api/routes/BlockRoutes.scala +++ b/src/main/scala/com/fluency03/blockchain/api/routes/BlockRoutes.scala @@ -2,14 +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.PathDirectives.path import akka.http.scaladsl.server.directives.RouteDirectives.complete import akka.pattern.ask -import com.fluency03.blockchain.api.{Blocks, FailureMsg, Message, SuccessMsg} +import com.fluency03.blockchain.api.{Blocks, Message} import com.fluency03.blockchain.api.actors.BlocksActor._ import com.fluency03.blockchain.core.Block 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 4abf69c..12f4a3e 100644 --- a/src/main/scala/com/fluency03/blockchain/api/routes/NetworkRoutes.scala +++ b/src/main/scala/com/fluency03/blockchain/api/routes/NetworkRoutes.scala @@ -2,16 +2,15 @@ package com.fluency03.blockchain.api.routes import akka.actor.ActorRef import akka.event.Logging -import akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallers.CsvSeq -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.PathDirectives.path import akka.http.scaladsl.server.directives.RouteDirectives.complete +import akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallers.CsvSeq import akka.pattern.ask +import com.fluency03.blockchain.api.Message import com.fluency03.blockchain.api.actors.NetworkActor._ -import com.fluency03.blockchain.api.{FailureMsg, Message, SuccessMsg} import com.fluency03.blockchain.core.{Peer, PeerSimple} import scala.concurrent.Future @@ -31,15 +30,10 @@ trait NetworkRoutes extends RoutesSupport { path(PEERS) { get { parameters( 'names.as(CsvSeq[String]) ? ) { names => - if (names.isDefined) { - val peers: Future[Map[String, Set[String]]] = - (networkActor ? GetPeers(names.get.toSet)).mapTo[Map[String, Set[String]]] - complete(peers) - } else { - val peers: Future[Map[String, Set[String]]] = - (networkActor ? GetPeers).mapTo[Map[String, Set[String]]] - complete(peers) - } + val peers: Future[Map[String, Set[String]]] = + if (names.isDefined) (networkActor ? GetPeers(names.get.toSet)).mapTo[Map[String, Set[String]]] + else (networkActor ? GetPeers).mapTo[Map[String, Set[String]]] + complete(peers) } } } ~ 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 3f241b2..ae24724 100644 --- a/src/main/scala/com/fluency03/blockchain/api/routes/TransactionRoutes.scala +++ b/src/main/scala/com/fluency03/blockchain/api/routes/TransactionRoutes.scala @@ -2,15 +2,15 @@ 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.PathDirectives.path import akka.http.scaladsl.server.directives.RouteDirectives.complete +import akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallers.CsvSeq import akka.pattern.ask -import com.fluency03.blockchain.api.{FailureMsg, Message, SuccessMsg, Transactions} import com.fluency03.blockchain.api.actors.TransactionsActor._ +import com.fluency03.blockchain.api.{Message, Transactions} import com.fluency03.blockchain.core.Transaction import scala.concurrent.Future @@ -22,8 +22,10 @@ trait TransactionRoutes extends RoutesSupport { lazy val transRoutes: Route = path(TRANSACTIONS) { - get { - val transactions: Future[Transactions] = (transActor ? GetTransactions).mapTo[Transactions] + parameters( 'ids.as(CsvSeq[String]) ? ) { ids => + val transactions: Future[Transactions] = + if (ids.isDefined) (transActor ? GetTransactions(ids.get.toSet)).mapTo[Transactions] + else (transActor ? GetTransactions).mapTo[Transactions] complete(transactions) } } ~ diff --git a/src/test/scala/com/fluency03/blockchain/api/actors/TransactionsActorTest.scala b/src/test/scala/com/fluency03/blockchain/api/actors/TransactionsActorTest.scala index 5bc716d..d0162e6 100644 --- a/src/test/scala/com/fluency03/blockchain/api/actors/TransactionsActorTest.scala +++ b/src/test/scala/com/fluency03/blockchain/api/actors/TransactionsActorTest.scala @@ -25,6 +25,9 @@ class TransactionsActorTest extends TestKit(ActorSystem("TransactionsActorTest") transActor ! GetTransactions expectMsg(Seq.empty[Transaction]) + transActor ! GetTransactions(Set("someid")) + expectMsg(Seq.empty[Transaction]) + val genesisTx: Transaction = createCoinbaseTx(0, genesisMiner, genesisTimestamp) transActor ! CreateTransaction(genesisTx) expectMsg(SuccessMsg(s"Transaction ${genesisTx.id} created.")) @@ -35,6 +38,12 @@ class TransactionsActorTest extends TestKit(ActorSystem("TransactionsActorTest") transActor ! GetTransactions expectMsg(Seq(genesisTx)) + transActor ! GetTransactions(Set("someid")) + expectMsg(Seq.empty[Transaction]) + + transActor ! GetTransactions(Set(genesisTx.id)) + expectMsg(Seq(genesisTx)) + transActor ! GetTransaction(genesisTx.id) expectMsg(Some(genesisTx)) diff --git a/src/test/scala/com/fluency03/blockchain/api/routes/BlockRoutesTest.scala b/src/test/scala/com/fluency03/blockchain/api/routes/BlockRoutesTest.scala index 486af66..aff84b5 100644 --- a/src/test/scala/com/fluency03/blockchain/api/routes/BlockRoutesTest.scala +++ b/src/test/scala/com/fluency03/blockchain/api/routes/BlockRoutesTest.scala @@ -1,8 +1,9 @@ package com.fluency03.blockchain.api.routes import akka.http.scaladsl.testkit.ScalatestRouteTest +import com.fluency03.blockchain.api.JsonSupport import org.scalatest.{Matchers, WordSpec} -class BlockRoutesTest extends WordSpec with Matchers with ScalatestRouteTest { +class BlockRoutesTest extends WordSpec with Matchers with ScalatestRouteTest with JsonSupport { } diff --git a/src/test/scala/com/fluency03/blockchain/api/routes/BlockchainRoutesTest.scala b/src/test/scala/com/fluency03/blockchain/api/routes/BlockchainRoutesTest.scala index 2b8a8a1..ed3a460 100644 --- a/src/test/scala/com/fluency03/blockchain/api/routes/BlockchainRoutesTest.scala +++ b/src/test/scala/com/fluency03/blockchain/api/routes/BlockchainRoutesTest.scala @@ -1,9 +1,10 @@ package com.fluency03.blockchain.api.routes import akka.http.scaladsl.testkit.ScalatestRouteTest +import com.fluency03.blockchain.api.JsonSupport import org.scalatest.{Matchers, WordSpec} -class BlockchainRoutesTest extends WordSpec with Matchers with ScalatestRouteTest { +class BlockchainRoutesTest extends WordSpec with Matchers with ScalatestRouteTest with JsonSupport { diff --git a/src/test/scala/com/fluency03/blockchain/api/routes/NetworkRoutesTest.scala b/src/test/scala/com/fluency03/blockchain/api/routes/NetworkRoutesTest.scala index f5f013d..28e9567 100644 --- a/src/test/scala/com/fluency03/blockchain/api/routes/NetworkRoutesTest.scala +++ b/src/test/scala/com/fluency03/blockchain/api/routes/NetworkRoutesTest.scala @@ -1,8 +1,9 @@ package com.fluency03.blockchain.api.routes import akka.http.scaladsl.testkit.ScalatestRouteTest +import com.fluency03.blockchain.api.JsonSupport import org.scalatest.{Matchers, WordSpec} -class NetworkRoutesTest extends WordSpec with Matchers with ScalatestRouteTest { +class NetworkRoutesTest extends WordSpec with Matchers with ScalatestRouteTest with JsonSupport { } diff --git a/src/test/scala/com/fluency03/blockchain/api/routes/TransactionRoutesTest.scala b/src/test/scala/com/fluency03/blockchain/api/routes/TransactionRoutesTest.scala index 7788748..6dbe8cc 100644 --- a/src/test/scala/com/fluency03/blockchain/api/routes/TransactionRoutesTest.scala +++ b/src/test/scala/com/fluency03/blockchain/api/routes/TransactionRoutesTest.scala @@ -1,8 +1,9 @@ package com.fluency03.blockchain.api.routes import akka.http.scaladsl.testkit.ScalatestRouteTest +import com.fluency03.blockchain.api.JsonSupport import org.scalatest.{Matchers, WordSpec} -class TransactionRoutesTest extends WordSpec with Matchers with ScalatestRouteTest { +class TransactionRoutesTest extends WordSpec with Matchers with ScalatestRouteTest with JsonSupport { }