All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sss.openstar.test.ClaimUsersActor.scala Maven / Gradle / Ivy

package sss.openstar.test

import akka.actor.Status.{Failure => FutureFailure}
import akka.actor.{Actor, ActorLogging}
import akka.pattern.pipe
import scorex.crypto.signatures.PublicKey
import sss.ancillary.FutureOps.AwaitResult
import sss.openstar.account.{NodeIdTag, NodeIdentity, NodeIdentityManager}
import sss.openstar.block.{NotSynchronized, Synchronized}
import sss.openstar.chains.TxWriterActor.{InternalAck, InternalCommit, InternalNack, InternalTempNack}
import sss.openstar.common.users.UserDirectory
import sss.openstar.contract.FindPublicKeyAccOpt
import sss.openstar.controller.Utils
import sss.openstar.identityledger.{Claim, Claim0}
import sss.openstar.ledger.{LedgerItem, SeqLedgerItem}
import sss.openstar.network.MessageEventBus
import sss.openstar.test.MultiIdentityTestTransactionSenderInternalClaim.{Claimed, Register}
import sss.openstar.tools.SendTxSupport.SendTx

import scala.concurrent.Future
import scala.concurrent.duration._

class ClaimUsersActor(testUsersConfig: Int,
                      users: UserDirectory,
                      defaultPassword: String,
                      nodeIdentityManager: NodeIdentityManager,
                      accountOpt: FindPublicKeyAccOpt,
                      toIdentityLedgerOwner: NodeIdentity => Option[NodeIdentity],
                      hostingNodeIdentity: NodeIdentity)(implicit sendTx: SendTx,
                                               messageEventBus: MessageEventBus)
  extends Actor with ActorLogging {

  private var tempClaimNacks: Int = 0

  import context.dispatcher

  override def preStart(): Unit = {
    super.preStart()
    messageEventBus.subscribe(classOf[Synchronized])
    messageEventBus.subscribe(classOf[NotSynchronized])

  }

  private def chars = ('a' to 'z').to(LazyList)

  def streamOfUserNames: LazyList[String] = for {
    a <- chars
    b <- chars
    c <- chars
    d <- chars
    e <- chars
    f <- chars
  } yield (Seq(a, b, c, d, e, f).mkString)


  val testUsers = streamOfUserNames.take(testUsersConfig)

  def missingUsers: Seq[String] = {
    val existingUsers = users.listUsers()
    testUsers.filterNot(existingUsers.contains)
  }


  override def receive: Receive = registerMissingUsers(missingUsers)

  private var isSynced = false
  private var registering: (Seq[String], Seq[String]) = missingUsers.splitAt(10)


  log.debug("ClaimUsersActor cons")

  private def registerMissingUsers(missingUsers: Seq[String]): Receive = {

    case Register if registering._1.isEmpty =>
      log.info(s"All users done")
      context.stop(self)

    case FutureFailure(e) =>
      log.warning("Failed, retry, " + e.toString)
      //self ! Register(missingUsers.headOption)


    case com: InternalCommit =>
      log.info(s"Got User claim commit: $com, going again")
      registering._1.foreach { u =>
        nodeIdentityManager(u, NodeIdTag.defaultTag, defaultPassword)
          .map(Claimed) pipeTo context.parent
      }
      registering = registering._2.splitAt(10)
      self ! Register


    case ack: InternalAck =>
    //log.info(s"Got ack: $ack")

    case r: InternalTempNack =>
      tempClaimNacks += 1
      if (tempClaimNacks % 20 == 0) {
        log.info(r.toString + s"Claim TempNack number $tempClaimNacks ")
      }
      self ! Register


    case r: InternalNack =>
      log.info(r.toString + s"Claim Nack ${r.txMsg.msg}")
      hideUserKeyFile(missingUsers.head)
      self ! Register


    case _ : Synchronized =>
      isSynced = true
      // make scheduled delay to avoid race condition with ClaimLedgerOwnership
      context.system.scheduler.scheduleOnce(5.seconds, self, Register)

    case _ : NotSynchronized =>
      isSynced = false

    case Register if isSynced =>

      registering._1.foreach { user =>
        val nodeIdentity = nodeIdentityManager(user, defaultPassword, NodeIdTag.defaultTag ).await()

        if (accountOpt(user, NodeIdTag.defaultTag).isEmpty) {
          createClaim(nodeIdentity.id, nodeIdentity.publicKey) flatMap { claim =>
            sendTx(SeqLedgerItem(claim)).whenAvailableLocally.map(_.commitTxResult.internalCommit)
          } pipeTo self

        } else {
          context.parent ! Claimed(nodeIdentity)
          registering = registering._2.splitAt(10)
          self ! Register
        }
      }

  }


  private def createClaim(newIdentity: String, publicKey: PublicKey): Future[LedgerItem] = {
    val identityLedgerOwner = toIdentityLedgerOwner(hostingNodeIdentity)
      .getOrElse(throw new RuntimeException(s"This node is ${hostingNodeIdentity.id} and can not claim $newIdentity"))
    Utils.simplySignedIdentityLedgerItem(hostingNodeIdentity, Claim0(identityLedgerOwner.id, newIdentity, publicKey))
  }

  private def hideUserKeyFile(user: String) =
    users.deleteUser(user).await()

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy