-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
300 additions
and
185 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
# blockchain-scala | ||
|
||
Simple Blockchain Implementation in Scala. | ||
|
||
Inspired by [Daniel van Flymen](http://www.dvf.nyc/)'s blog [Learn Blockchains by Building One](https://hackernoon.com/learn-blockchains-by-building-one-117428612f46), I started to implement this Scala version of a simple Blockchain. | ||
|
||
REST API service is built on the open source projects [akka](https://github.com/akka/akka) and [akka-http](https://github.com/akka/akka-http). | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
http { | ||
host = "0.0.0.0" | ||
port = 9090 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
src/main/scala/com/fluency03/blockchain/api/actors/BlockActor.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.fluency03.blockchain.api.actors | ||
|
||
import akka.actor.{Actor, ActorLogging, ActorSelection, Props} | ||
import com.fluency03.blockchain.api.actors.BlockActor._ | ||
import com.fluency03.blockchain.api.utils.GenericMessage._ | ||
import com.fluency03.blockchain.api.{BLOCKCHAIN_ACTOR_NAME, PARENT_UP, TX_ACTOR_NAME} | ||
import com.fluency03.blockchain.core.Block | ||
import scala.collection.mutable | ||
|
||
object BlockActor { | ||
final case object GetBlocks | ||
final case class CreateBlock(block: Block) | ||
final case class GetBlock(hash: String) | ||
final case class DeleteBlock(hash: String) | ||
|
||
def props: Props = Props[BlockActor] | ||
} | ||
|
||
class BlockActor extends Actor with ActorLogging { | ||
override def preStart(): Unit = log.info("{} started!", this.getClass.getSimpleName) | ||
override def postStop(): Unit = log.info("{} stopped!", this.getClass.getSimpleName) | ||
|
||
val blockchainActor: ActorSelection = context.actorSelection(PARENT_UP + BLOCKCHAIN_ACTOR_NAME) | ||
val txActor: ActorSelection = context.actorSelection(PARENT_UP + TX_ACTOR_NAME) | ||
|
||
var blocks = mutable.Map.empty[String, Block] | ||
|
||
def receive: Receive = { | ||
case GetBlocks => onGetBlocks() | ||
case CreateBlock(block) => onCreateBlock(block) | ||
case GetBlock(hash) => onGetBlock(hash) | ||
case DeleteBlock(hash) => onDeleteBlock(hash) | ||
} | ||
|
||
private[this] def onGetBlocks(): Unit = sender() ! blocks.values.toList | ||
|
||
private[this] def onCreateBlock(block: Block): Unit = { | ||
blocks += (block.hash -> block) | ||
sender() ! Response(s"Block ${block.hash} created.") | ||
} | ||
|
||
private[this] def onGetBlock(hash: String): Unit = sender() ! blocks.get(hash) | ||
|
||
private[this] def onDeleteBlock(hash: String): Unit = { | ||
blocks -= hash | ||
sender() ! Response(s"Block $hash deleted.") | ||
} | ||
|
||
} |
33 changes: 0 additions & 33 deletions
33
src/main/scala/com/fluency03/blockchain/api/actors/BlockRegistryActor.scala
This file was deleted.
Oops, something went wrong.
78 changes: 78 additions & 0 deletions
78
src/main/scala/com/fluency03/blockchain/api/actors/BlockchainActor.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package com.fluency03.blockchain.api.actors | ||
|
||
import akka.actor.{Actor, ActorLogging, ActorSelection, Props} | ||
import com.fluency03.blockchain.api.actors.BlockchainActor._ | ||
import com.fluency03.blockchain.api.actors.TransactionActor._ | ||
import com.fluency03.blockchain.api.utils.GenericMessage._ | ||
import com.fluency03.blockchain.api.{BLOCK_ACTOR_NAME, PARENT_UP, TX_ACTOR_NAME} | ||
import com.fluency03.blockchain.core.{Blockchain, Transaction} | ||
|
||
object BlockchainActor { | ||
final case object GetBlockchain | ||
final case object CreateBlockchain | ||
final case object DeleteBlockchain | ||
|
||
def props: Props = Props[BlockchainActor] | ||
} | ||
|
||
class BlockchainActor extends Actor with ActorLogging { | ||
override def preStart(): Unit = log.info("{} started!", this.getClass.getSimpleName) | ||
override def postStop(): Unit = log.info("{} stopped!", this.getClass.getSimpleName) | ||
|
||
val txActor: ActorSelection = context.actorSelection(PARENT_UP + TX_ACTOR_NAME) | ||
val blockActor: ActorSelection = context.actorSelection(PARENT_UP + BLOCK_ACTOR_NAME) | ||
|
||
var blockchainOpt: Option[Blockchain] = None | ||
|
||
def receive: Receive = { | ||
/* ---------- Blockchain actions ---------- */ | ||
case GetBlockchain => onGetBlockchain() | ||
case CreateBlockchain => onCreateBlockchain() | ||
case DeleteBlockchain => onDeleteBlockchain() | ||
/* ---------- Transaction actions ---------- */ | ||
case GetTransactions => onGetTransactions() | ||
case CreateTransaction(tx) => onCreateTransaction(tx) | ||
case GetTransaction(hash) => onGetTransaction(hash) | ||
case DeleteTransaction(hash) => onDeleteTransaction(hash) | ||
} | ||
|
||
/* ---------- Blockchain actions ---------- */ | ||
private[this] def onGetBlockchain(): Unit = sender() ! blockchainOpt | ||
|
||
private[this] def onCreateBlockchain(): Unit = | ||
if (blockchainOpt.isDefined) sender() ! Response(s"Blockchain already exists.") | ||
else { | ||
blockchainOpt = Some(Blockchain()) | ||
sender() ! Response(s"Blockchain created, with difficulty ${blockchainOpt.get.difficulty}.") | ||
} | ||
|
||
private[this] def onDeleteBlockchain(): Unit = | ||
if (blockchainOpt.isDefined) { | ||
blockchainOpt = None | ||
sender() ! Response(s"Blockchain deleted.") | ||
} else sender() ! Response(s"Blockchain does not exist.") | ||
|
||
/* ---------- Transaction actions ---------- */ | ||
private[this] def onGetTransactions(): Unit = sender() ! { | ||
if (blockchainOpt.isDefined) blockchainOpt.get.currentTransactions.toList | ||
else List() | ||
} | ||
|
||
private[this] def onCreateTransaction(tx: Transaction): Unit = | ||
if (blockchainOpt.isDefined) { | ||
blockchainOpt.get.currentTransactions += (tx.hash -> tx) | ||
sender() ! Response(s"Transaction ${tx.hash} created.") | ||
} else sender() ! Response(s"Blockchain does not exist.") | ||
|
||
private[this] def onGetTransaction(hash: String): Unit = sender() ! { | ||
if (blockchainOpt.isDefined) blockchainOpt.get.currentTransactions(hash) | ||
else None | ||
} | ||
|
||
private[this] def onDeleteTransaction(hash: String): Unit = | ||
if (blockchainOpt.isDefined) { | ||
blockchainOpt.get.currentTransactions -= hash | ||
sender() ! Response(s"Transaction $hash deleted.") | ||
} else sender() ! Response(s"Blockchain does not exist.") | ||
|
||
} |
31 changes: 0 additions & 31 deletions
31
src/main/scala/com/fluency03/blockchain/api/actors/BlockchainRegistryActor.scala
This file was deleted.
Oops, something went wrong.
38 changes: 38 additions & 0 deletions
38
src/main/scala/com/fluency03/blockchain/api/actors/TransactionActor.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.fluency03.blockchain.api.actors | ||
|
||
import akka.actor.{Actor, ActorLogging, ActorSelection, Props} | ||
import com.fluency03.blockchain.api.actors.TransactionActor._ | ||
import com.fluency03.blockchain.api.utils.GenericMessage._ | ||
import com.fluency03.blockchain.api.{BLOCKCHAIN_ACTOR_NAME, BLOCK_ACTOR_NAME, PARENT_UP} | ||
import com.fluency03.blockchain.core.Transaction | ||
|
||
object TransactionActor { | ||
final case object GetTransactions | ||
final case class CreateTransaction(tx: Transaction) | ||
final case class GetTransaction(hash: String) | ||
final case class DeleteTransaction(hash: String) | ||
|
||
def props: Props = Props[TransactionActor] | ||
} | ||
|
||
class TransactionActor extends Actor with ActorLogging { | ||
override def preStart(): Unit = log.info("{} started!", this.getClass.getSimpleName) | ||
override def postStop(): Unit = log.info("{} stopped!", this.getClass.getSimpleName) | ||
|
||
val blockchainActor: ActorSelection = context.actorSelection(PARENT_UP + BLOCKCHAIN_ACTOR_NAME) | ||
val blockActor: ActorSelection = context.actorSelection(PARENT_UP + BLOCK_ACTOR_NAME) | ||
|
||
def receive: Receive = { | ||
case _ => blockchainActor forward _ | ||
} | ||
|
||
// | ||
// { | ||
// case msg @ GetTransactions => blockchainActor forward msg | ||
// case msg: CreateTransaction => blockchainActor forward msg | ||
// case msg: GetTransaction => blockchainActor forward msg | ||
// case msg: DeleteTransaction => blockchainActor forward msg | ||
// } | ||
|
||
|
||
} |
31 changes: 0 additions & 31 deletions
31
src/main/scala/com/fluency03/blockchain/api/actors/TransactionRegistryActor.scala
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,16 @@ | ||
package com.fluency03.blockchain | ||
|
||
import com.fluency03.blockchain.core.Block | ||
import com.fluency03.blockchain.core.{Block, Transaction} | ||
|
||
package object api { | ||
|
||
type Blocks = List[Block] | ||
type Transactions = List[Transaction] | ||
|
||
lazy val BLOCK_ACTOR_NAME = "blockActor" | ||
lazy val BLOCKCHAIN_ACTOR_NAME = "blockchainActor" | ||
lazy val TX_ACTOR_NAME = "txActor" | ||
|
||
lazy val PARENT_UP = "../" | ||
|
||
} |
Oops, something went wrong.