diff --git a/src/main/scala/encry/api/http/DataHolderForApi.scala b/src/main/scala/encry/api/http/DataHolderForApi.scala index 72adcec939..fd7b82de1c 100644 --- a/src/main/scala/encry/api/http/DataHolderForApi.scala +++ b/src/main/scala/encry/api/http/DataHolderForApi.scala @@ -17,6 +17,7 @@ import encry.local.miner.Miner.{DisableMining, EnableMining, MinerStatus, StartM import encry.network.BlackList.BanReason.InvalidNetworkMessage import encry.network.BlackList.{BanReason, BanTime, BanType} import encry.network.ConnectedPeersCollection +import encry.network.DeliveryManager.FullBlockChainIsSynced import encry.network.NodeViewSynchronizer.ReceivableMessages._ import encry.network.PeerConnectionHandler.ConnectedPeer import encry.network.PeersKeeper.BanPeerFromAPI @@ -69,7 +70,8 @@ class DataHolderForApi(settings: EncryAppSettings, ntp: NetworkTimeProvider) minerStatus: MinerStatus = MinerStatus(isMining = false, None), blockInfo: BlockAndHeaderInfo = BlockAndHeaderInfo(None, None), allPeers: Seq[InetSocketAddress] = Seq.empty, - connectedPeersCollection: ConnectedPeersCollection = ConnectedPeersCollection()): Receive = { + connectedPeersCollection: ConnectedPeersCollection = ConnectedPeersCollection(), + isSynced: Boolean = false): Receive = { case UpdatingTransactionsNumberForApi(qty) => context.become( @@ -281,10 +283,26 @@ class DataHolderForApi(settings: EncryAppSettings, ntp: NetworkTimeProvider) settings.constants )).pipeTo(sender()) - case GetDataFromHistory => history.foreach(sender() ! _) - case GetMinerStatus => sender() ! minerStatus - case GetAllPeers => sender() ! allPeers - case GetConnections => sender() ! connectedPeersCollection + case GetDataFromHistory => history.foreach(sender() ! _) + case FullBlockChainIsSynced => + context.become( + workingCycle( + nvhRef, + blackList, + connectedPeers, + history, + state, + transactionsOnMinerActor, + minerStatus, + blockInfo, + allPeers, + connectedPeersCollection, + isSynced = true + )) + case GetBlockChainSync => sender() ! isSynced + case GetMinerStatus => sender() ! minerStatus + case GetAllPeers => sender() ! allPeers + case GetConnections => sender() ! connectedPeersCollection case PeerBanHelper(peer, msg) => context.system.eventStream.publish(BanPeerFromAPI(peer, InvalidNetworkMessage(msg))) case StartMinerApiMessage => @@ -372,6 +390,8 @@ object DataHolderForApi { //scalastyle:ignore case object GetAllInfo + case object GetBlockChainSync + case object GetConnections def props(settings: EncryAppSettings, ntp: NetworkTimeProvider): Props = Props(new DataHolderForApi(settings, ntp)) diff --git a/src/main/scala/encry/api/http/routes/BanPeersRoute.scala b/src/main/scala/encry/api/http/routes/BanPeersRoute.scala index 258f88ea7b..ebe3dfe87f 100644 --- a/src/main/scala/encry/api/http/routes/BanPeersRoute.scala +++ b/src/main/scala/encry/api/http/routes/BanPeersRoute.scala @@ -6,7 +6,7 @@ import akka.http.scaladsl.model.{ContentTypes, HttpEntity} import akka.http.scaladsl.server.Route import akka.pattern._ import com.typesafe.scalalogging.StrictLogging -import encry.api.http.DataHolderForApi.GetBannedPeersHelper +import encry.api.http.DataHolderForApi.{GetBannedPeersHelper, GetBlockChainSync} import encry.api.http.ScriptHelper import encry.network.BlackList.{BanReason, BanTime, BanType} import encry.settings.RESTApiSettings @@ -24,7 +24,14 @@ case class BanPeersRoute(settings: RESTApiSettings, dataHolder: ActorRef)( def peersAllF: Future[Seq[(InetAddress, (BanReason, BanTime, BanType))]] = (dataHolder ? GetBannedPeersHelper).mapTo[Seq[(InetAddress, (BanReason, BanTime, BanType))]] - def peerScript(peers: Seq[(InetAddress, (BanReason, BanTime, BanType))] ): Text.TypedTag[String] = { + def syncIsDoneF: Future[Boolean] = (dataHolder ? GetBlockChainSync).mapTo[Boolean] + + def info: Future[(Seq[(InetAddress, (BanReason, BanTime, BanType))], Boolean)] = for { + peers <- peersAllF + sync <- syncIsDoneF + } yield (peers, sync) + + def peerScript(peers: Seq[(InetAddress, (BanReason, BanTime, BanType))], sync: Boolean): Text.TypedTag[String] = { html( scalatags.Text.all.head( @@ -112,11 +119,20 @@ case class BanPeersRoute(settings: RESTApiSettings, dataHolder: ActorRef)( i(cls := "ni ni-tv-2 text-primary"), "Info" ) ), - li(cls := "nav-item", - a(cls := "nav-link", href := "./webWallet", - i(cls := "ni ni-planet text-blue"), "Wallet" + if (sync) { + li(cls := "nav-item", + a(tpe := "button", cls := "nav-link", disabled := "disabled", + i(cls := "ni ni-planet text-blue"), "Wallet (n.a during sync)" + ) ) - ), + } + else { + li(cls := "nav-item", + a(cls := "nav-link", href := "./webWallet", + i(cls := "ni ni-planet text-blue"), "Wallet" + ) + ) + }, div(cls := "dropdown", a(cls := "nav-link", href := "#", role := "button", data("toggle") := "dropdown", aria.haspopup := "true", aria.expanded := "false", i(cls := "ni ni-bullet-list-67 text-orange"), "Peers" @@ -294,9 +310,9 @@ case class BanPeersRoute(settings: RESTApiSettings, dataHolder: ActorRef)( override def route: Route = (path("bannedPeers") & get) { WebRoute.authRoute( - onComplete(peersAllF) { - case Success(info) => - complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, peerScript(info).render)) + onComplete(info) { + case Success((peers, isSynced)) => + complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, peerScript(peers, isSynced).render)) case Failure(_) => complete(s"Couldn't load page with banned peers cause inner system is overloaded. Try it later!") }, diff --git a/src/main/scala/encry/api/http/routes/PeersApiRoute.scala b/src/main/scala/encry/api/http/routes/PeersApiRoute.scala index 4130e69ac5..2f5caa1fb8 100755 --- a/src/main/scala/encry/api/http/routes/PeersApiRoute.scala +++ b/src/main/scala/encry/api/http/routes/PeersApiRoute.scala @@ -88,4 +88,4 @@ object PeersApiRoute { } implicit val encodePeerInfoResponse: Encoder[PeerInfoResponse] = deriveEncoder -} +} \ No newline at end of file diff --git a/src/main/scala/encry/api/http/routes/PeersConnectedRoute.scala b/src/main/scala/encry/api/http/routes/PeersConnectedRoute.scala index ee3f674e30..9106933cba 100644 --- a/src/main/scala/encry/api/http/routes/PeersConnectedRoute.scala +++ b/src/main/scala/encry/api/http/routes/PeersConnectedRoute.scala @@ -5,7 +5,7 @@ import akka.http.scaladsl.model.{ContentTypes, HttpEntity} import akka.http.scaladsl.server.Route import akka.pattern._ import com.typesafe.scalalogging.StrictLogging -import encry.api.http.DataHolderForApi.GetConnections +import encry.api.http.DataHolderForApi.{GetBlockChainSync, GetConnections} import encry.api.http.ScriptHelper import encry.network.ConnectedPeersCollection import encry.settings.RESTApiSettings @@ -16,14 +16,20 @@ import scala.concurrent.Future import scala.language.implicitConversions import scala.util.{Failure, Success} - case class PeersConnectedRoute(settings: RESTApiSettings, dataHolder: ActorRef)( implicit val context: ActorRefFactory ) extends EncryBaseApiRoute with StrictLogging { def connectedPeers: Future[ConnectedPeersCollection] = (dataHolder ? GetConnections).mapTo[ConnectedPeersCollection] - def peerScript(peersR: ConnectedPeersCollection): Text.TypedTag[String] = { + def syncIsDoneF: Future[Boolean] = (dataHolder ? GetBlockChainSync).mapTo[Boolean] + + def info: Future[(ConnectedPeersCollection, Boolean)] = for { + peers <- connectedPeers + sync <- syncIsDoneF + } yield (peers, sync) + + def peerScript(peersR: ConnectedPeersCollection, sync: Boolean): Text.TypedTag[String] = { html( scalatags.Text.all.head( @@ -109,11 +115,20 @@ case class PeersConnectedRoute(settings: RESTApiSettings, dataHolder: ActorRef)( i(cls := "ni ni-tv-2 text-primary"), "Info" ) ), - li(cls := "nav-item", - a(cls := "nav-link", href := "./webWallet", - i(cls := "ni ni-planet text-blue"), "Wallet" + if (sync) { + li(cls := "nav-item", + a(tpe := "button", cls := "nav-link", disabled := "disabled", + i(cls := "ni ni-planet text-blue"), "Wallet (n.a during sync)" + ) ) - ), + } + else { + li(cls := "nav-item", + a(cls := "nav-link", href := "./webWallet", + i(cls := "ni ni-planet text-blue"), "Wallet" + ) + ) + }, div(cls := "dropdown", a(cls := "nav-link", href := "#", role := "button", data("toggle") := "dropdown", aria.haspopup := "true", aria.expanded := "false", i(cls := "ni ni-bullet-list-67 text-orange"), "Peers" @@ -296,9 +311,9 @@ case class PeersConnectedRoute(settings: RESTApiSettings, dataHolder: ActorRef)( } override def route: Route = (path("connectedPeers") & get) { - onComplete(connectedPeers) { - case Success(info) => complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, peerScript(info).render)) - case Failure(_) => complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, peerScript(ConnectedPeersCollection()).render)) + onComplete(info) { + case Success((peers, isSynced)) => complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, peerScript(peers, isSynced).render)) + case Failure(_) => complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, peerScript(ConnectedPeersCollection(), false).render)) } } diff --git a/src/main/scala/encry/api/http/routes/PeersRoute.scala b/src/main/scala/encry/api/http/routes/PeersRoute.scala index fd164ebbe4..92ea432feb 100644 --- a/src/main/scala/encry/api/http/routes/PeersRoute.scala +++ b/src/main/scala/encry/api/http/routes/PeersRoute.scala @@ -6,7 +6,7 @@ import akka.http.scaladsl.model.{ContentTypes, HttpEntity} import akka.http.scaladsl.server.Route import akka.pattern._ import com.typesafe.scalalogging.StrictLogging -import encry.api.http.DataHolderForApi.GetAllPeers +import encry.api.http.DataHolderForApi.{GetAllPeers, GetBlockChainSync} import encry.settings.{NodeSettings, RESTApiSettings} import io.circe.generic.auto._ import scalatags.Text @@ -21,7 +21,14 @@ case class PeersRoute(settings: RESTApiSettings, nodeSettings: NodeSettings, dat def peersAllF: Future[Seq[InetSocketAddress]] = (dataHolder ? GetAllPeers).mapTo[Seq[InetSocketAddress]] - def peerScript(peers: Seq[InetSocketAddress] ): Text.TypedTag[String] = { + def syncIsDoneF: Future[Boolean] = (dataHolder ? GetBlockChainSync).mapTo[Boolean] + + def info: Future[(Seq[InetSocketAddress], Boolean)] = for { + peers <- peersAllF + sync <- syncIsDoneF + } yield (peers, sync) + + def peerScript(peers: Seq[InetSocketAddress], sync: Boolean): Text.TypedTag[String] = { html( scalatags.Text.all.head( @@ -82,11 +89,20 @@ case class PeersRoute(settings: RESTApiSettings, nodeSettings: NodeSettings, dat i(cls := "ni ni-tv-2 text-primary"), "Info" ) ), - li(cls := "nav-item", - a(cls := "nav-link", href := "./webWallet", - i(cls := "ni ni-planet text-blue"), "Wallet" + if (sync) { + li(cls := "nav-item", + a(tpe := "button", cls := "nav-link", disabled := "disabled", + i(cls := "ni ni-planet text-blue"), "Wallet (n.a during sync)" + ) ) - ), + } + else { + li(cls := "nav-item", + a(cls := "nav-link", href := "./webWallet", + i(cls := "ni ni-planet text-blue"), "Wallet" + ) + ) + }, div(cls := "dropdown", a(cls := "nav-link", href := "#", role := "button", data("toggle") := "dropdown", aria.haspopup := "true", aria.expanded := "false", i(cls := "ni ni-bullet-list-67 text-orange"), "Peers" @@ -203,9 +219,9 @@ case class PeersRoute(settings: RESTApiSettings, nodeSettings: NodeSettings, dat override def route: Route = (path("allPeers") & get) { WebRoute.authRoute( - onComplete(peersAllF) { - case Success(info) => - complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, peerScript(info).render)) + onComplete(info) { + case Success((peers, isSynced)) => + complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, peerScript(peers, isSynced).render)) case Failure(_) => complete("Couldn't load page with peers cause of inner system is overloaded. Try it later!") }, settings diff --git a/src/main/scala/encry/api/http/routes/WalletRoute.scala b/src/main/scala/encry/api/http/routes/WalletRoute.scala index 1dde32a658..6bb93d2e0c 100644 --- a/src/main/scala/encry/api/http/routes/WalletRoute.scala +++ b/src/main/scala/encry/api/http/routes/WalletRoute.scala @@ -826,8 +826,8 @@ case class WalletRoute(settings: RESTApiSettings, override def route: Route = path("webWallet") { WebRoute.authRoute( onComplete(info) { - case Success(info) => - complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, walletScript(info._1).render)) + case Success((balance, _)) => + complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, walletScript(balance).render)) }, settings ) } diff --git a/src/main/scala/encry/api/http/routes/WebRoute.scala b/src/main/scala/encry/api/http/routes/WebRoute.scala index ab9ff2e418..8ffb86c7a0 100644 --- a/src/main/scala/encry/api/http/routes/WebRoute.scala +++ b/src/main/scala/encry/api/http/routes/WebRoute.scala @@ -9,7 +9,7 @@ import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCodes} import akka.http.scaladsl.server.{Route, ValidationRejection} import akka.pattern._ import com.typesafe.scalalogging.StrictLogging -import encry.api.http.DataHolderForApi.{GetAllInfoHelper, GetMinerStatus, GetNodePassHashAndSalt} +import encry.api.http.DataHolderForApi.{GetAllInfoHelper, GetBlockChainSync, GetMinerStatus, GetNodePassHashAndSalt} import encry.local.miner.Miner.MinerStatus import encry.settings.{NodeSettings, RESTApiSettings} import io.circe.generic.auto._ @@ -48,6 +48,8 @@ case class WebRoute(override val settings: RESTApiSettings, nodeSettings: NodeSe def getPass: Future[String => Boolean] = (dataHolder ? GetNodePassHashAndSalt).mapTo[String => Boolean] + def syncIsDoneF: Future[Boolean] = (dataHolder ? GetBlockChainSync).mapTo[Boolean] + def signUp: Text.TypedTag[String] = html( scalatags.Text.all.head( meta(charset := "utf-8"), @@ -178,8 +180,8 @@ case class WebRoute(override val settings: RESTApiSettings, nodeSettings: NodeSe path("web") { WebRoute.authRoute( onComplete(currentInfoF) { - case Success(info) => - complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, webResponse(info._1, info._2).render)) + case Success((nodeInfo, minerStatus, isSynced)) => + complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, webResponse(nodeInfo, minerStatus, isSynced).render)) case Failure(exception) => complete(exception) }, settings) } @@ -189,12 +191,13 @@ case class WebRoute(override val settings: RESTApiSettings, nodeSettings: NodeSe def infoHelper: Future[Json] = (dataHolder ? GetAllInfoHelper).mapTo[Json] - def currentInfoF: Future[(Json, MinerStatus)] = for { + def currentInfoF: Future[(Json, MinerStatus, Boolean)] = for { info <- infoHelper status <- statusF - } yield (info, status) + sync <- syncIsDoneF + } yield (info, status, sync) - def webResponse(json: Json, minerStatus: MinerStatus): Text.TypedTag[String] = { + def webResponse(json: Json, minerStatus: MinerStatus, sync: Boolean): Text.TypedTag[String] = { val nodeInfo = parser.decode[InfoApi](json.toString()) html( @@ -282,11 +285,20 @@ case class WebRoute(override val settings: RESTApiSettings, nodeSettings: NodeSe i(cls := "ni ni-tv-2 text-primary"), "Info" ) ), - li(cls := "nav-item", - a(cls := "nav-link", href := "./webWallet", - i(cls := "ni ni-planet text-blue"), "Wallet" + if (sync) { + li(cls := "nav-item", + a(tpe := "button", cls := "nav-link", disabled := "disabled", + i(cls := "ni ni-planet text-blue"), "Wallet (n.a during sync)" + ) ) - ), + } + else { + li(cls := "nav-item", + a(cls := "nav-link", href := "./webWallet", + i(cls := "ni ni-planet text-blue"), "Wallet" + ) + ) + }, div(cls := "dropdown", a(cls := "nav-link", href := "#", role := "button", data("toggle") := "dropdown", aria.haspopup := "true", aria.expanded := "false", i(cls := "ni ni-bullet-list-67 text-orange"), "Peers" diff --git a/src/main/scala/encry/local/miner/Miner.scala b/src/main/scala/encry/local/miner/Miner.scala index 68ca34bbe3..d6c6023792 100644 --- a/src/main/scala/encry/local/miner/Miner.scala +++ b/src/main/scala/encry/local/miner/Miner.scala @@ -97,12 +97,10 @@ class Miner(dataHolder: ActorRef, case TransactionsForMiner(txs) => transactionsPool = transactionsPool ++ txs case StartMining => logger.info("Can't start mining because of chain is not synced!") case DisableMining if context.children.nonEmpty => - println(s"Miner -> Disable mining context.children.nonEmpty") killAllWorkers() candidateOpt = None context.become(miningDisabled) case DisableMining => - println(s"Miner -> Disable mining") killAllWorkers() candidateOpt = None context.become(miningDisabled) diff --git a/src/main/scala/encry/network/NodeViewSynchronizer.scala b/src/main/scala/encry/network/NodeViewSynchronizer.scala index 1d02fcbc96..b27e1c909c 100644 --- a/src/main/scala/encry/network/NodeViewSynchronizer.scala +++ b/src/main/scala/encry/network/NodeViewSynchronizer.scala @@ -221,6 +221,7 @@ class NodeViewSynchronizer(influxRef: Option[ActorRef], case FullBlockChainIsSynced => chainSynced = true deliveryManager ! FullBlockChainIsSynced + dataHolder ! FullBlockChainIsSynced peersKeeper ! FullBlockChainIsSynced if (!settings.snapshotSettings.enableFastSynchronization) snapshotHolder ! FullBlockChainIsSynced case StopTransactionsValidation =>