Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
# Conflicts:
#	Readme.md
  • Loading branch information
kushti committed Mar 27, 2016
2 parents ce88477 + 615fd18 commit 93f87e9
Show file tree
Hide file tree
Showing 10 changed files with 279 additions and 30 deletions.
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# PermaScorex
# Lagonaki

This is permacoin implementation on top of Scorex framework.

Expand Down
5 changes: 4 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ scalaVersion := "2.11.8"
resolvers += "SonaType" at "https://oss.sonatype.org/content/groups/public"

libraryDependencies ++= Seq(
"org.consensusresearch" %% "scorex" % "1.2.1"
"org.consensusresearch" %% "scorex-basics" % "1.2.+",
"org.consensusresearch" %% "scorex-consensus" % "1.2.+",
"org.consensusresearch" %% "scorex-perma" % "1.2.+",
"org.consensusresearch" %% "scorex-transaction" % "1.2.+"
)

mainClass in assembly := Some("scorex.perma.Application")
11 changes: 5 additions & 6 deletions lock.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ dependencyOverrides in ThisBuild ++= Set(
"javax.ws.rs" % "jsr311-api" % "1.1.1",
"joda-time" % "joda-time" % "2.8.1",
"org.bitlet" % "weupnp" % "0.1.4",
"org.consensusresearch" % "scorex-basics_2.11" % "1.2.1",
"org.consensusresearch" % "scorex-consensus_2.11" % "1.2.1",
"org.consensusresearch" % "scorex-perma_2.11" % "1.2.1",
"org.consensusresearch" % "scorex-transaction_2.11" % "1.2.1",
"org.consensusresearch" % "scorex_2.11" % "1.2.1",
"org.consensusresearch" % "scorex-basics_2.11" % "1.2.2",
"org.consensusresearch" % "scorex-consensus_2.11" % "1.2.2",
"org.consensusresearch" % "scorex-perma_2.11" % "1.2.2",
"org.consensusresearch" % "scorex-transaction_2.11" % "1.2.2",
"org.consensusresearch" % "scrypto_2.11" % "1.0.4",
"org.joda" % "joda-convert" % "1.7",
"org.json4s" % "json4s-ast_2.11" % "3.2.11",
Expand All @@ -62,4 +61,4 @@ dependencyOverrides in ThisBuild ++= Set(
"org.slf4j" % "slf4j-api" % "1.7.18",
"org.whispersystems" % "curve25519-java" % "0.2.4"
)
// LIBRARY_DEPENDENCIES_HASH 011cd9994bdbf98994a54c73e5e7423f83a91480
// LIBRARY_DEPENDENCIES_HASH 111038646dc7c922ca4f2f8b646d0e96e0d35c99
2 changes: 1 addition & 1 deletion pack.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ enablePlugins(JavaAppPackaging)
enablePlugins(DebianPlugin)
linuxPackageMappings in Debian := linuxPackageMappings.value
name in Debian := name.value
version in Debian := "0.1.0"
version in Debian := "1.2.1"
genChanges in Debian := new File("changelog.md")

name in Universal := name.value
Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/application.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
app {
product = "Scorex"
release = "Lagonaki"
version = "1.2.2"
consensusAlgo = "perma"
}
Original file line number Diff line number Diff line change
@@ -1,40 +1,28 @@
package scorex.perma
package scorex.lagonaki

import java.io.File

import akka.actor.Props
import com.typesafe.config.ConfigFactory
import scorex.account.Account
import scorex.api.http._
import scorex.app.ApplicationVersion
import scorex.crypto.ads.merkle.AuthDataBlock
import scorex.lagonaki.api.http.{DebugApiRoute, PaymentApiRoute, PeersHttpService, ScorexApiRoute}
import scorex.lagonaki.server.LagonakiSettings
import scorex.lagonaki.http.{ScorexApiRoute, DebugApiRoute}
import scorex.lagonaki.settings.LagonakiSettings
import scorex.network.{TransactionalMessagesRepo, UnconfirmedPoolSynchronizer}
import scorex.perma.api.http.PermaConsensusApiRoute
import scorex.perma.consensus.PermaConsensusModule
import scorex.perma.network.{PermacoinMessagesRepo, SegmentsSynchronizer}
import scorex.perma.settings.PermaConstants._
import scorex.perma.storage.AuthDataStorage
import scorex.storage.Storage
import scorex.transaction.SimpleTransactionModule
import scorex.transaction.{BalanceSheet, GenesisTransaction, SimpleTransactionModule, Transaction}
import scorex.utils.ScorexLogging

import scala.concurrent.duration._
import scala.reflect.runtime.universe._


object Application extends App with ScorexLogging {

log.debug("Start server with args: {} ", args)
val filename = args.headOption.getOrElse("settings.json")

val application = new Application(filename)

log.debug("PermaScorex has been started")
application.run()

if (application.wallet.privateKeyAccounts().isEmpty) application.wallet.generateNewAccounts(1)

}
import scala.util.Random

class Application(val settingsFilename: String) extends scorex.app.Application {

Expand All @@ -52,7 +40,7 @@ class Application(val settingsFilename: String) extends scorex.app.Application {

override implicit lazy val consensusModule = {
new File(settings.treeDir).mkdirs()
val authDataStorage: Storage[Long, AuthDataBlock[DataSegment]] = new AuthDataStorage(settings.authDataStorage)
val authDataStorage: Storage[Long, AuthDataBlock[DataSegment]] = new AuthDataStorage(Some(settings.authDataStorage))
val rootHash = settings.rootHash
actorSystem.actorOf(Props(classOf[SegmentsSynchronizer], this, rootHash, authDataStorage))
new PermaConsensusModule(rootHash, Some(networkController))(authDataStorage)
Expand Down Expand Up @@ -98,4 +86,65 @@ class Application(val settingsFilename: String) extends scorex.app.Application {

actorSystem.actorOf(Props(classOf[UnconfirmedPoolSynchronizer], this))

}
}

object Application extends App with ScorexLogging {

log.debug("Start server with args: {} ", args)
val filename = args.headOption.getOrElse("settings.json")

val application = new Application(filename)

log.debug("PermaScorex has been started")
application.run()

if (application.wallet.privateKeyAccounts().isEmpty) application.wallet.generateNewAccounts(1)

def testingScript(application: Application): Unit = {
log.info("Going to execute testing scenario")
log.info("Current state is:" + application.blockStorage.state)
val wallet = application.wallet

if (wallet.privateKeyAccounts().isEmpty) {
wallet.generateNewAccounts(3)
log.info("Generated Accounts:\n" + wallet.privateKeyAccounts().toList.map(_.address).mkString("\n"))
}

log.info("Executing testing scenario with accounts" +
s"(${wallet.privateKeyAccounts().size}) : "
+ wallet.privateKeyAccounts().mkString(" "))

require(wallet.privateKeyAccounts().nonEmpty)

Thread.sleep(3.seconds.toMillis)

val genesisBlock = application.blockStorage.history.genesis
val genesisAccs = genesisBlock.transactions.flatMap(_ match {
case gtx: GenesisTransaction =>
Some(gtx.recipient)
case _ =>
log.error("Non-genesis tx in the genesis block!")
None
})

def genPayment(recipient: Option[Account] = None, amtOpt: Option[Long] = None): Option[Transaction] = {
val pkAccs = wallet.privateKeyAccounts().ensuring(_.nonEmpty)
val senderAcc = pkAccs(Random.nextInt(pkAccs.size))
val senderBalance = application.blockStorage.state.asInstanceOf[BalanceSheet].generationBalance(senderAcc)
val recipientAcc = recipient.getOrElse(genesisAccs(Random.nextInt(genesisAccs.size)))
val fee = Random.nextInt(5).toLong + 1
if (senderBalance - fee > 0) {
val amt = amtOpt.getOrElse(Math.abs(Random.nextLong() % (senderBalance - fee)))
Some(application.transactionModule.createPayment(senderAcc, recipientAcc, amt, fee))
} else None
}

log.info("Generate 200 transactions")
(1 to 200) foreach (_ => genPayment())

(1 to Int.MaxValue).foreach { _ =>
Thread.sleep(Random.nextInt(5.seconds.toMillis.toInt))
log.info(s"Payment created: ${genPayment()}")
}
}
}
103 changes: 103 additions & 0 deletions src/main/scala/scorex/lagonaki/http/DebugApiRoute.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package scorex.lagonaki.http

import javax.ws.rs.Path

import akka.actor.ActorRefFactory
import com.wordnik.swagger.annotations._
import play.api.libs.json.Json
import scorex.api.http._
import scorex.app.Application
import scorex.crypto.encode.Base58
import scorex.crypto.hash.FastCryptographicHash
import scorex.transaction.state.database.blockchain.StoredState
import spray.routing.Route

@Api(value = "/debug", description = "Debug methods", position = 1)
case class DebugApiRoute(override val application: Application)(implicit val context: ActorRefFactory)
extends ApiRoute with CommonTransactionApiFunctions {

implicit lazy val transactionModule = application.transactionModule
lazy val wallet = application.wallet

override lazy val route = pathPrefix("debug") {
blocks ~ state ~ stateAt ~ info ~ settings
}

@Path("/blocks/{howMany}")
@ApiOperation(value = "Blocks", notes = "Get sizes and full hashes for last blocks", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(
name = "howMany",
value = "How many last blocks to take",
required = true,
dataType = "String",
paramType = "path")
))
def blocks: Route = {
path("blocks" / IntNumber) { case howMany =>
jsonRoute {
Json.arr(application.blockStorage.history.lastBlocks(howMany).map { block =>
val bytes = block.bytes
Json.obj(bytes.length.toString -> Base58.encode(FastCryptographicHash(bytes)))
}).toString()
}
}
}

@Path("/state")
@ApiOperation(value = "State", notes = "Get current state", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "Json state")
))
def state: Route = {
path("state") {
jsonRoute {
application.blockStorage.state.toString
}
}
}

@Path("/state/{height}")
@ApiOperation(value = "State at block", notes = "Get state at specified height", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "height", value = "height", required = true, dataType = "Int", paramType = "path")
))
def stateAt: Route = {
path("state" / IntNumber) { case height =>
jsonRoute {
application.blockStorage.state.asInstanceOf[StoredState].toJson(Some(height)).toString
}
}
}

@Path("/info")
@ApiOperation(value = "State", notes = "All info you need to debug", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "Json state")
))
def info: Route = {
path("info") {
jsonRoute {
val state = application.blockStorage.state.asInstanceOf[StoredState]
Json.obj(
"stateHeight" -> state.stateHeight,
"stateHash" -> state.hash
).toString
}
}
}

@Path("/settings")
@ApiOperation(value = "State", notes = "Settings file", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "Json state")
))
def settings: Route = {
path("settings") {
jsonRoute {
application.settings.settingsJSON.toString()
}
}
}

}
65 changes: 65 additions & 0 deletions src/main/scala/scorex/lagonaki/http/ScorexApiRoute.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package scorex.lagonaki.http

import javax.ws.rs.Path

import akka.actor.ActorRefFactory
import akka.pattern.ask
import com.wordnik.swagger.annotations._
import play.api.libs.json.Json
import scorex.api.http.{ApiRoute, CommonApiFunctions}
import scorex.app.Application
import scorex.consensus.mining.BlockGeneratorController._
import scorex.lagonaki.settings.Constants
import scorex.network.HistorySynchronizer
import spray.routing.Route

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

@Api(value = "scorex", description = "General commands & information", position = 0)
case class ScorexApiRoute(override val application: Application)(implicit val context: ActorRefFactory)
extends ApiRoute with CommonApiFunctions {

override lazy val route =
pathPrefix("scorex") {
scorex ~ status ~ version
}

@Path("/version")
@ApiOperation(value = "Version", notes = "get Scorex version", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "Json Scorex version")
))
def version: Route = {
path("version") {
jsonRoute {
Json.obj("version" -> Constants.AgentName).toString()
}
}
}

@Path("/stop")
@ApiOperation(value = "Stop", notes = "Stop the app", httpMethod = "POST")
def scorex: Route = path("stop") {
jsonRoute({
Future(application.stopAll())
Json.obj("stopped" -> true).toString()
}, post)
}

@Path("/status")
@ApiOperation(value = "Status", notes = "Get status of the running core(Offline/Syncing/Generating)", httpMethod = "GET")
def status: Route = path("status") {
jsonRoute {
def bgf = (application.blockGenerator ? GetStatus).map(_.toString)
def hsf = (application.historySynchronizer ? HistorySynchronizer.GetStatus).map(_.toString)

Future.sequence(Seq(bgf, hsf)).map { case statusesSeq =>
Json.obj(
"block_generator_status" -> statusesSeq.head,
"history_synchronization_status" -> statusesSeq.tail.head
).toString()
}
}
}
}
17 changes: 17 additions & 0 deletions src/main/scala/scorex/lagonaki/settings/Constants.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package scorex.lagonaki.settings

import com.typesafe.config.ConfigFactory
import scorex.utils.ScorexLogging

/**
* System constants here.
*/

object Constants extends ScorexLogging {
private val appConf = ConfigFactory.load().getConfig("app")

val Product = appConf.getString("product")
val Release = appConf.getString("release")
val VersionString = appConf.getString("version")
val AgentName = s"$Product - $Release v. $VersionString"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package scorex.lagonaki.settings

import scorex.perma.settings.PermaSettings
import scorex.settings.Settings
import scorex.transaction.TransactionSettings

class LagonakiSettings(override val filename: String) extends Settings with TransactionSettings with PermaSettings

0 comments on commit 93f87e9

Please sign in to comment.