Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spectrum behaviour sim #29

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions sim/src/main/scala/agent.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package sim

import cats.Monad
import cats.effect.kernel.{Async, Clock}
import cats.effect.std.{AtomicCell, Queue}
Expand Down
7 changes: 3 additions & 4 deletions sim/src/main/scala/blockchain.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package sim

import cats.Monad
import cats.effect.std.Random
import cats.effect.{Clock, Sync, Temporal}
Expand All @@ -9,10 +11,7 @@ import fs2.Stream

import scala.concurrent.duration.*

case class Account(value: String)

case class Transaction(id: Long, account: Account, change: Long)
case class Block(txs: Vector[Transaction], seqNum: Int)
import sim.env.*

/** L1 robust ledger system.
*/
Expand Down
38 changes: 27 additions & 11 deletions sim/src/main/scala/env/ledger.scala
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
package env
package sim.env
import cats.effect.{ExitCode, IO, IOApp}

case class Rejection()
case class Address(v: String)

case class VrfPublicKey(value: String) // HexString
case class KesPublicKey(value: String) // HexString
case class DsigPublicKey(value: String) // HexString

case class Account(
address: Address,
stake: Long,
vrfPk: VrfPublicKey,
kesPk: KesPublicKey,
dsigPk: DsigPublicKey
)

case class Transaction(id: Long, account: Account, change: Long)

case class BlockId(value: Long)

/** @type
* B - Block
* @type
* S - State
*/
trait Ledger[B, S, F[_]]:
case class Block(id: BlockId, seqNum: Int)

case class State(verAccounts: Vector[Account]) // set of verification keys to store in the Ledger

trait Ledger[F[_]]:
/** Add a new block to the ledger.
*/
def add(block: B): F[Either[Rejection, S]]
def add(block: Block): F[Unit]

/** Get all blocks at the given height.
*/
def getAll(height: Int): F[List[B]]
def getAll(height: Int): F[List[Block]]

/** Get specific block.
*/
def get(id: BlockId): F[Option[B]]
def get(id: BlockId): F[Option[Block]]

def addParticipant(acc: Account): F[Unit]
2 changes: 2 additions & 0 deletions sim/src/main/scala/main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import cats.syntax.show.*

import scala.concurrent.duration.*

import sim.*

object Main extends IOApp {
override def run(args: List[String]): IO[ExitCode] =
for
Expand Down
57 changes: 57 additions & 0 deletions sim/src/main/scala/protocol/spectrum.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package sim.spectrum

import cats.Monad
import cats.effect.IO
import cats.effect.kernel.{Async, Clock}
import cats.effect.std.{AtomicCell, Queue}
import cats.syntax.applicative.*
import cats.syntax.flatMap.*
import cats.syntax.foldable.*
import cats.syntax.functor.*
import cats.syntax.traverse.*
import sim.*
import sim.env.*

import scala.concurrent.duration.*
import scala.language.postfixOps


sealed trait SpectrumMsg
case class NewBlock(block: Block) extends SpectrumMsg
case class GetBlock(blockId: BlockId) extends SpectrumMsg
case class Register(newAcc: Account) extends SpectrumMsg


final class Spectrum[F[_]: Monad](
selfAddr: Addr,
// abstract interface to Ledger, so you dont have to care about impl.
ledger: Ledger[F],
// queue of pending output commands waiting to be returned from poll().
pendingOutputs: Queue[F, (Addr, AgentOut[SpectrumMsg])]
) extends Agent[SpectrumMsg, F]:
def getAddr: F[Addr] = selfAddr.pure

def injectMessage(srcAddr: Addr, m: SpectrumMsg): F[Unit] =
m match
case NewBlock(block) => ledger.add(block)
case Register(account) => ledger.addParticipant(account)
case GetBlock(blockId) =>
for
maybeBlock <- ledger.get(blockId)
_ <- maybeBlock match
case None =>
// do nothing
().pure
case Some(block) =>
// if the requested block is found locally we send it to the peer which requested it
pendingOutputs.offer(srcAddr -> SendMessage(NewBlock(block)))
yield ()

def injectConnReq(peerAddr: Addr, handshake: SpectrumMsg): F[Either[Reject, SpectrumMsg]] = ???

def injectConnLost(peerAddr: Addr): F[Unit] = ???

def injectConnEstablished(peerAddr: Addr, handshake: SpectrumMsg): F[Unit] = ???

def poll: F[Option[(Addr, AgentOut[SpectrumMsg])]] =
pendingOutputs.tryTake
2 changes: 2 additions & 0 deletions sim/src/main/scala/swarm.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package sim

import cats.effect.kernel.Async
import cats.effect.std.{AtomicCell, Random}
import cats.effect.syntax.spawn.*
Expand Down