-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ATL-1923] feat(iris): Implement in-memory ledger
- Loading branch information
Showing
29 changed files
with
363 additions
and
35 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
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
3 changes: 3 additions & 0 deletions
3
iris/service/core/src/main/scala/io/iohk/atala/iris/core/model/ledger/Funds.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,3 @@ | ||
package io.iohk.atala.iris.core.model.ledger | ||
|
||
case class Funds(lovelaces: Int) |
15 changes: 15 additions & 0 deletions
15
iris/service/core/src/main/scala/io/iohk/atala/iris/core/model/ledger/Ledger.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,15 @@ | ||
package io.iohk.atala.iris.core.model.ledger | ||
|
||
import enumeratum.{Enum, EnumEntry} | ||
|
||
import scala.collection.immutable.ArraySeq | ||
|
||
sealed trait Ledger extends EnumEntry | ||
|
||
object Ledger extends Enum[Ledger] { | ||
val values = ArraySeq(InMemory, CardanoMainnet, CardanoTestnet) | ||
|
||
case object InMemory extends Ledger | ||
case object CardanoMainnet extends Ledger | ||
case object CardanoTestnet extends Ledger | ||
} |
3 changes: 3 additions & 0 deletions
3
...service/core/src/main/scala/io/iohk/atala/iris/core/model/ledger/TransactionDetails.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,3 @@ | ||
package io.iohk.atala.iris.core.model.ledger | ||
|
||
case class TransactionDetails(id: TransactionId, status: TransactionStatus) |
18 changes: 18 additions & 0 deletions
18
iris/service/core/src/main/scala/io/iohk/atala/iris/core/model/ledger/TransactionId.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,18 @@ | ||
package io.iohk.atala.iris.core.model.ledger | ||
|
||
import com.typesafe.config.ConfigMemorySize | ||
import io.iohk.atala.shared.{HashValueConfig, HashValueFrom} | ||
|
||
import scala.collection.immutable.ArraySeq | ||
|
||
case class TransactionId(hex: ArraySeq[Byte]) | ||
|
||
object TransactionId extends HashValueFrom[TransactionId] { | ||
|
||
override val config: HashValueConfig = HashValueConfig( | ||
ConfigMemorySize.ofBytes(32) | ||
) | ||
|
||
override protected def constructor(value: ArraySeq[Byte]): TransactionId = | ||
new TransactionId(value) | ||
} |
16 changes: 16 additions & 0 deletions
16
.../service/core/src/main/scala/io/iohk/atala/iris/core/model/ledger/TransactionStatus.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,16 @@ | ||
package io.iohk.atala.iris.core.model.ledger | ||
|
||
import enumeratum.{Enum, EnumEntry} | ||
import enumeratum.EnumEntry.Snakecase | ||
import scala.collection.immutable.ArraySeq | ||
|
||
sealed trait TransactionStatus extends EnumEntry with Snakecase | ||
|
||
object TransactionStatus extends Enum[TransactionStatus] { | ||
val values = ArraySeq(InWalletMempool, Submitted, Expired, InLedger) | ||
|
||
case object InWalletMempool extends TransactionStatus | ||
case object Submitted extends TransactionStatus | ||
case object Expired extends TransactionStatus | ||
case object InLedger extends TransactionStatus | ||
} |
6 changes: 3 additions & 3 deletions
6
...service/core/src/main/scala/io/iohk/atala/iris/core/repository/OperationsRepository.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 |
---|---|---|
@@ -1,10 +1,10 @@ | ||
package io.iohk.atala.iris.core.repository | ||
|
||
import io.iohk.atala.iris.core.model.{IrisOperation, IrisOperationId, SignedIrisOperation} | ||
import io.iohk.atala.iris.core.model as model | ||
import zio.* | ||
|
||
// TODO: replace with actual implementation | ||
trait OperationsRepository[F[_]] { | ||
def getOperation(id: IrisOperationId): F[IrisOperation] | ||
def saveOperations(ops: Seq[SignedIrisOperation]): F[Unit] | ||
def getOperation(id: model.IrisOperationId): F[model.IrisOperation] | ||
def saveOperations(ops: Seq[model.IrisOperation]): F[Unit] | ||
} |
105 changes: 105 additions & 0 deletions
105
...core/src/main/scala/io/iohk/atala/iris/core/service/InmemoryUnderlyingLedgerService.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,105 @@ | ||
package io.iohk.atala.iris.core.service | ||
|
||
import io.iohk.atala.iris.core.model.ledger.TransactionStatus.{InWalletMempool, InLedger} | ||
import io.iohk.atala.iris.core.model.ledger.{Funds, TransactionDetails, TransactionId} | ||
import io.iohk.atala.iris.core.service.InmemoryUnderlyingLedgerService.{CardanoBlock, CardanoTransaction, Config} | ||
import io.iohk.atala.iris.proto.service.IrisOperation | ||
import zio.{Duration as ZDuration, *} | ||
import zio.stm.* | ||
import io.iohk.atala.iris.proto.dlt_operations as proto_dlt | ||
import io.iohk.atala.iris.proto.service as proto_service | ||
import io.iohk.atala.prism.crypto.Sha256 | ||
|
||
import scala.concurrent.duration.Duration | ||
|
||
object InmemoryUnderlyingLedgerService { | ||
case class Config(blockEvery: Duration, initialFunds: Funds, txFee: Funds) | ||
|
||
case class CardanoTransaction(operations: Seq[proto_service.IrisOperation]) { | ||
lazy val transactionId: TransactionId = { | ||
val objectBytes = proto_dlt.AtalaObject(operations).toByteArray | ||
val hash = Sha256.compute(objectBytes) | ||
TransactionId | ||
.from(hash.getValue) | ||
.getOrElse(throw new RuntimeException("Unexpected invalid hash")) | ||
} | ||
} | ||
|
||
case class CardanoBlock(txs: List[CardanoTransaction]) | ||
|
||
def layer(config: Config): ULayer[UnderlyingLedgerService] = ZLayer.fromZIO { | ||
for { | ||
mempoolRef <- TRef.make(List[CardanoTransaction]()).commit | ||
blocksRef <- TRef.make(List[CardanoBlock]()).commit | ||
initialBalance <- TRef.make(config.initialFunds).commit | ||
srv = InmemoryUnderlyingLedgerService(config, mempoolRef, blocksRef, initialBalance) | ||
_ <- srv.startBackgroundProcess() | ||
} yield srv | ||
} | ||
} | ||
|
||
class InmemoryUnderlyingLedgerService( | ||
config: Config, | ||
mempoolRef: TRef[List[CardanoTransaction]], | ||
blocksRef: TRef[List[CardanoBlock]], | ||
balanceRef: TRef[Funds] | ||
) extends UnderlyingLedgerService { | ||
|
||
def startBackgroundProcess(): UIO[Unit] = STM.atomically { | ||
for { | ||
// Craft a new block from mempool transactions | ||
txs <- mempoolRef.modify(old => (old, List.empty)) | ||
_ <- blocksRef.update(CardanoBlock(txs) :: _) | ||
} yield () | ||
} | ||
.repeat(Schedule.spaced(ZDuration.fromScala(config.blockEvery))) | ||
.fork.map(_ => ()) | ||
|
||
override def publish(operations: Seq[proto_service.IrisOperation]): IO[LedgerError, Unit] = | ||
STM.atomically { | ||
for { | ||
curFunds <- balanceRef.get | ||
newFunds <- STM.cond( | ||
curFunds.lovelaces >= config.txFee.lovelaces, | ||
Funds(curFunds.lovelaces - config.txFee.lovelaces), | ||
LedgerError("Insufficient wallet balance") | ||
) | ||
_ <- balanceRef.set(newFunds) | ||
_ <- mempoolRef.update(CardanoTransaction(operations) :: _) | ||
} yield () | ||
} | ||
|
||
override def getTransactionDetails(transactionId: TransactionId): IO[LedgerError, TransactionDetails] = | ||
STM.atomically { | ||
for { | ||
mempool <- mempoolRef.get | ||
blockchain <- blocksRef.get | ||
tdetails <- STM.fromOption { | ||
mempool.find(_.transactionId == transactionId) | ||
.map(_ => TransactionDetails(transactionId, InWalletMempool)) | ||
}.orElse { | ||
STM.fromOption { | ||
blockchain.find(block => block.txs.exists(t => t.transactionId == transactionId)) | ||
.map(_ => TransactionDetails(transactionId, InLedger)) | ||
} | ||
} | ||
.orElseFail(LedgerError(s"Couldn't find tx $transactionId")) | ||
} yield tdetails | ||
} | ||
|
||
override def deleteTransaction(transactionId: TransactionId): IO[LedgerError, Unit] = STM.atomically { | ||
for { | ||
mempool <- mempoolRef.get | ||
_ <- STM.cond(mempool.exists(_.transactionId == transactionId), | ||
(), | ||
LedgerError(s"Transaction $transactionId not found in the mempool") | ||
) | ||
_ <- mempoolRef.update(m => m.filter { | ||
_.transactionId != transactionId | ||
}) | ||
_ <- balanceRef.update(b => Funds(b.lovelaces + config.txFee.lovelaces)) | ||
} yield () | ||
} | ||
|
||
override def getWalletBalance: IO[LedgerError, Funds] = balanceRef.get.commit | ||
} |
6 changes: 3 additions & 3 deletions
6
iris/service/core/src/main/scala/io/iohk/atala/iris/core/service/PublishingService.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 |
---|---|---|
@@ -1,17 +1,17 @@ | ||
package io.iohk.atala.iris.core.service | ||
|
||
import io.iohk.atala.iris.core.model.SignedIrisOperation | ||
import io.iohk.atala.iris.proto.service as proto | ||
import zio.* | ||
|
||
// TODO: replace with actual implementation | ||
trait PublishingService { | ||
def publishOperations(op: SignedIrisOperation): UIO[Unit] | ||
def publishOperation(op: proto.IrisOperation): UIO[Unit] = ??? | ||
} | ||
|
||
object MockPublishingService { | ||
val layer: ULayer[PublishingService] = ZLayer.succeed { | ||
new PublishingService { | ||
override def publishOperations(op: SignedIrisOperation): UIO[Unit] = ZIO.unit | ||
override def publishOperation(op: proto.IrisOperation): UIO[Unit] = ZIO.unit | ||
} | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
...service/core/src/main/scala/io/iohk/atala/iris/core/service/UnderlyingLedgerService.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,20 @@ | ||
package io.iohk.atala.iris.core.service | ||
|
||
import io.iohk.atala.iris.proto.{service => proto} | ||
import io.iohk.atala.iris.core.model.IrisOperation | ||
import io.iohk.atala.iris.core.model.ledger.{Funds, TransactionDetails, TransactionId} | ||
import zio.{IO, UIO} | ||
|
||
case class LedgerError(msg: String) extends RuntimeException(msg) | ||
|
||
trait UnderlyingLedgerService { | ||
// def getType: Ledger | ||
|
||
def publish(operations: Seq[proto.IrisOperation]): IO[LedgerError, Unit] | ||
|
||
def getTransactionDetails(transactionId: TransactionId): IO[LedgerError, TransactionDetails] | ||
|
||
def deleteTransaction(transactionId: TransactionId): IO[LedgerError, Unit] | ||
|
||
def getWalletBalance: IO[LedgerError, Funds] | ||
} |
7 changes: 3 additions & 4 deletions
7
iris/service/core/src/main/scala/io/iohk/atala/iris/core/worker/PublishingScheduler.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 |
---|---|---|
@@ -1,17 +1,16 @@ | ||
package io.iohk.atala.iris.core.worker | ||
|
||
import io.iohk.atala.iris.core.model.SignedIrisOperation | ||
import io.iohk.atala.iris.core.service.PublishingService | ||
import io.iohk.atala.iris.proto.service as proto | ||
import zio.{UIO, ULayer, ZIO, ZLayer} | ||
|
||
trait PublishingScheduler { | ||
def scheduleOperations(op: SignedIrisOperation): UIO[Unit] | ||
def scheduleOperations(op: proto.IrisOperation): UIO[Unit] | ||
} | ||
|
||
object MockPublishingScheduler { | ||
val layer: ULayer[PublishingScheduler] = ZLayer.succeed { | ||
new PublishingScheduler { | ||
def scheduleOperations(op: SignedIrisOperation): UIO[Unit] = ZIO.unit | ||
def scheduleOperations(op: proto.IrisOperation): UIO[Unit] = ZIO.unit | ||
} | ||
} | ||
} |
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 |
---|---|---|
@@ -1,3 +1 @@ | ||
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") | ||
|
||
libraryDependencies ++= Seq("org.openapitools" % "openapi-generator" % "6.0.0") |
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 @@ | ||
addSbtPlugin("com.codecommit" % "sbt-github-packages" % "0.5.3") |
2 changes: 1 addition & 1 deletion
2
...a/io/iohk/atala/iris/apiserver/Main.scala → ...cala/io/iohk/atala/iris/server/Main.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 |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package io.iohk.atala.iris.apiserver | ||
package io.iohk.atala.iris.server | ||
|
||
import zio.* | ||
|
||
|
6 changes: 3 additions & 3 deletions
6
...o/iohk/atala/iris/apiserver/Modules.scala → ...a/io/iohk/atala/iris/server/Modules.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
2 changes: 1 addition & 1 deletion
2
...tala/iris/apiserver/grpc/GrpcServer.scala → ...k/atala/iris/server/grpc/GrpcServer.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
2 changes: 1 addition & 1 deletion
2
...la/iris/apiserver/grpc/GrpcServices.scala → ...atala/iris/server/grpc/GrpcServices.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
2 changes: 1 addition & 1 deletion
2
...er/grpc/service/IrisServiceGrpcImpl.scala → ...er/grpc/service/IrisServiceGrpcImpl.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
Oops, something went wrong.